xref: /haiku/src/system/kernel/arch/x86/arch_debug.cpp (revision faf79e7f783976326856422ff006b4c6ae9c3031)
1 /*
2  * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
4  * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
5  * Distributed under the terms of the MIT License.
6  *
7  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8  * Distributed under the terms of the NewOS License.
9  */
10 
11 
12 #include <arch/debug.h>
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 
17 #include <ByteOrder.h>
18 #include <TypeConstants.h>
19 
20 #include <cpu.h>
21 #include <debug.h>
22 #include <debug_heap.h>
23 #include <elf.h>
24 #include <kernel.h>
25 #include <kimage.h>
26 #include <thread.h>
27 #include <vm/vm.h>
28 #include <vm/vm_types.h>
29 #include <vm/VMAddressSpace.h>
30 #include <vm/VMArea.h>
31 
32 
33 struct stack_frame {
34 	stack_frame*	previous;
35 	addr_t			return_address;
36 };
37 
38 #define NUM_PREVIOUS_LOCATIONS 32
39 
40 
41 static bool is_kernel_stack_address(Thread* thread, addr_t address);
42 
43 
44 static bool
45 already_visited(addr_t* visited, int32* _last, int32* _num, addr_t bp)
46 {
47 	int32 last = *_last;
48 	int32 num = *_num;
49 	int32 i;
50 
51 	for (i = 0; i < num; i++) {
52 		if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == bp)
53 			return true;
54 	}
55 
56 	*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
57 	visited[last] = bp;
58 
59 	if (num < NUM_PREVIOUS_LOCATIONS)
60 		*_num = num + 1;
61 
62 	return false;
63 }
64 
65 
66 /*!	Safe to be called only from outside the debugger.
67 */
68 static status_t
69 get_next_frame_no_debugger(addr_t bp, addr_t* _next, addr_t* _ip,
70 	bool onKernelStack, Thread* thread)
71 {
72 	// TODO: Do this more efficiently in assembly.
73 	stack_frame frame;
74 	if (onKernelStack
75 		&& is_kernel_stack_address(thread, bp + sizeof(frame) - 1))
76 		memcpy(&frame, (void*)bp, sizeof(frame));
77 	else if (user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK)
78 		return B_BAD_ADDRESS;
79 
80 	*_ip = frame.return_address;
81 	*_next = (addr_t)frame.previous;
82 
83 	return B_OK;
84 }
85 
86 
87 /*!	Safe to be called only from inside the debugger.
88 */
89 static status_t
90 get_next_frame_debugger(addr_t bp, addr_t* _next, addr_t* _ip)
91 {
92 	stack_frame frame;
93 	if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)bp, sizeof(frame)) != B_OK)
94 		return B_BAD_ADDRESS;
95 
96 	*_ip = frame.return_address;
97 	*_next = (addr_t)frame.previous;
98 
99 	return B_OK;
100 }
101 
102 
103 static status_t
104 lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
105 	const char** _symbolName, const char** _imageName, bool* _exactMatch)
106 {
107 	status_t status = B_ENTRY_NOT_FOUND;
108 
109 	if (IS_KERNEL_ADDRESS(address)) {
110 		// a kernel symbol
111 		status = elf_debug_lookup_symbol_address(address, _baseAddress,
112 			_symbolName, _imageName, _exactMatch);
113 	} else if (thread != NULL && thread->team != NULL) {
114 		// try a lookup using the userland runtime loader structures
115 		status = elf_debug_lookup_user_symbol_address(thread->team, address,
116 			_baseAddress, _symbolName, _imageName, _exactMatch);
117 
118 		if (status != B_OK) {
119 			// try to locate the image in the images loaded into user space
120 			status = image_debug_lookup_user_symbol_address(thread->team,
121 				address, _baseAddress, _symbolName, _imageName, _exactMatch);
122 		}
123 	}
124 
125 	return status;
126 }
127 
128 
129 #ifndef __x86_64__
130 
131 
132 static void
133 set_debug_argument_variable(int32 index, uint64 value)
134 {
135 	char name[8];
136 	snprintf(name, sizeof(name), "_arg%ld", index);
137 	set_debug_variable(name, value);
138 }
139 
140 
141 template<typename Type>
142 static Type
143 read_function_argument_value(void* argument, bool& _valueKnown)
144 {
145 	Type value;
146 	if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) {
147 		_valueKnown = true;
148 		return value;
149 	}
150 
151 	_valueKnown = false;
152 	return 0;
153 }
154 
155 
156 static status_t
157 print_demangled_call(const char* image, const char* symbol, addr_t args,
158 	bool noObjectMethod, bool addDebugVariables)
159 {
160 	static const size_t kBufferSize = 256;
161 	char* buffer = (char*)debug_malloc(kBufferSize);
162 	if (buffer == NULL)
163 		return B_NO_MEMORY;
164 
165 	bool isObjectMethod;
166 	const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
167 		&isObjectMethod);
168 	if (name == NULL) {
169 		debug_free(buffer);
170 		return B_ERROR;
171 	}
172 
173 	uint32* arg = (uint32*)args;
174 
175 	if (noObjectMethod)
176 		isObjectMethod = false;
177 	if (isObjectMethod) {
178 		const char* lastName = strrchr(name, ':') - 1;
179 		int namespaceLength = lastName - name;
180 
181 		uint32 argValue = 0;
182 		if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) {
183 			kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image,
184 				namespaceLength, name, argValue, lastName);
185 		} else
186 			kprintf("<%s> %.*s<???>%s", image, namespaceLength, name, lastName);
187 
188 		if (addDebugVariables)
189 			set_debug_variable("_this", argValue);
190 		arg++;
191 	} else
192 		kprintf("<%s> %s", image, name);
193 
194 	kprintf("(");
195 
196 	size_t length;
197 	int32 type, i = 0;
198 	uint32 cookie = 0;
199 	while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
200 			kBufferSize, &type, &length) == B_OK) {
201 		if (i++ > 0)
202 			kprintf(", ");
203 
204 		// retrieve value and type identifier
205 
206 		uint64 value;
207 		bool valueKnown = false;
208 
209 		switch (type) {
210 			case B_INT64_TYPE:
211 				value = read_function_argument_value<int64>(arg, valueKnown);
212 				if (valueKnown)
213 					kprintf("int64: \33[34m%Ld\33[0m", value);
214 				break;
215 			case B_INT32_TYPE:
216 				value = read_function_argument_value<int32>(arg, valueKnown);
217 				if (valueKnown)
218 					kprintf("int32: \33[34m%ld\33[0m", (int32)value);
219 				break;
220 			case B_INT16_TYPE:
221 				value = read_function_argument_value<int16>(arg, valueKnown);
222 				if (valueKnown)
223 					kprintf("int16: \33[34m%d\33[0m", (int16)value);
224 				break;
225 			case B_INT8_TYPE:
226 				value = read_function_argument_value<int8>(arg, valueKnown);
227 				if (valueKnown)
228 					kprintf("int8: \33[34m%d\33[0m", (int8)value);
229 				break;
230 			case B_UINT64_TYPE:
231 				value = read_function_argument_value<uint64>(arg, valueKnown);
232 				if (valueKnown) {
233 					kprintf("uint64: \33[34m%#Lx\33[0m", value);
234 					if (value < 0x100000)
235 						kprintf(" (\33[34m%Lu\33[0m)", value);
236 				}
237 				break;
238 			case B_UINT32_TYPE:
239 				value = read_function_argument_value<uint32>(arg, valueKnown);
240 				if (valueKnown) {
241 					kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value);
242 					if (value < 0x100000)
243 						kprintf(" (\33[34m%lu\33[0m)", (uint32)value);
244 				}
245 				break;
246 			case B_UINT16_TYPE:
247 				value = read_function_argument_value<uint16>(arg, valueKnown);
248 				if (valueKnown) {
249 					kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
250 						(uint16)value, (uint16)value);
251 				}
252 				break;
253 			case B_UINT8_TYPE:
254 				value = read_function_argument_value<uint8>(arg, valueKnown);
255 				if (valueKnown) {
256 					kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
257 						(uint8)value, (uint8)value);
258 				}
259 				break;
260 			case B_BOOL_TYPE:
261 				value = read_function_argument_value<uint8>(arg, valueKnown);
262 				if (valueKnown)
263 					kprintf("\33[34m%s\33[0m", value ? "true" : "false");
264 				break;
265 			default:
266 				if (buffer[0])
267 					kprintf("%s: ", buffer);
268 
269 				if (length == 4) {
270 					value = read_function_argument_value<uint32>(arg,
271 						valueKnown);
272 					if (valueKnown) {
273 						if (value == 0
274 							&& (type == B_POINTER_TYPE || type == B_REF_TYPE))
275 							kprintf("NULL");
276 						else
277 							kprintf("\33[34m%#lx\33[0m", (uint32)value);
278 					}
279 					break;
280 				}
281 
282 
283 				if (length == 8) {
284 					value = read_function_argument_value<uint64>(arg,
285 						valueKnown);
286 				} else
287 					value = (uint64)arg;
288 
289 				if (valueKnown)
290 					kprintf("\33[34m%#Lx\33[0m", value);
291 				break;
292 		}
293 
294 		if (!valueKnown)
295 			kprintf("???");
296 
297 		if (valueKnown && type == B_STRING_TYPE) {
298 			if (value == 0)
299 				kprintf(" \33[31m\"<NULL>\"\33[0m");
300 			else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)(addr_t)value,
301 					kBufferSize) < B_OK) {
302 				kprintf(" \33[31m\"<???>\"\33[0m");
303 			} else
304 				kprintf(" \33[36m\"%s\"\33[0m", buffer);
305 		}
306 
307 		if (addDebugVariables)
308 			set_debug_argument_variable(i, value);
309 		arg = (uint32*)((uint8*)arg + length);
310 	}
311 
312 	debug_free(buffer);
313 
314 	kprintf(")");
315 	return B_OK;
316 }
317 
318 
319 #else	// __x86_64__
320 
321 
322 static status_t
323 print_demangled_call(const char* image, const char* symbol, addr_t args,
324 	bool noObjectMethod, bool addDebugVariables)
325 {
326 	// Since x86_64 uses registers rather than the stack for the first 6
327 	// arguments we cannot use the same method as x86 to read the function
328 	// arguments. Maybe we need DWARF support in the kernel debugger. For now
329 	// just print out the function signature without the argument values.
330 
331 	static const size_t kBufferSize = 256;
332 	char* buffer = (char*)debug_malloc(kBufferSize);
333 	if (buffer == NULL)
334 		return B_NO_MEMORY;
335 
336 	bool isObjectMethod;
337 	const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
338 		&isObjectMethod);
339 	if (name == NULL) {
340 		debug_free(buffer);
341 		return B_ERROR;
342 	}
343 
344 	kprintf("<%s> %s(", image, name);
345 
346 	size_t length;
347 	int32 type, i = 0;
348 	uint32 cookie = 0;
349 	while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
350 			kBufferSize, &type, &length) == B_OK) {
351 		if (i++ > 0)
352 			kprintf(", ");
353 
354 		if (buffer[0])
355 			kprintf("%s", buffer);
356 		else
357 			kprintf("???");
358 	}
359 
360 	debug_free(buffer);
361 
362 	kprintf(")");
363 	return B_OK;
364 }
365 
366 
367 #endif	// __x86_64__
368 
369 
370 static void
371 print_stack_frame(Thread* thread, addr_t ip, addr_t bp, addr_t nextBp,
372 	int32 callIndex, bool demangle)
373 {
374 	const char* symbol;
375 	const char* image;
376 	addr_t baseAddress;
377 	bool exactMatch;
378 	status_t status;
379 	addr_t diff;
380 
381 	diff = nextBp - bp;
382 
383 	// MSB set = kernel space/user space switch
384 	if (diff & ~((addr_t)-1 >> 1))
385 		diff = 0;
386 
387 	status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image,
388 		&exactMatch);
389 
390 	kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx   ", callIndex,
391 		B_PRINTF_POINTER_WIDTH, bp, diff, B_PRINTF_POINTER_WIDTH, ip);
392 
393 	if (status == B_OK) {
394 		if (exactMatch && demangle) {
395 			status = print_demangled_call(image, symbol,
396 				nextBp + sizeof(stack_frame), false, false);
397 		}
398 
399 		if (!exactMatch || !demangle || status != B_OK) {
400 			if (symbol != NULL) {
401 				kprintf("<%s> %s%s", image, symbol,
402 					exactMatch ? "" : " (nearest)");
403 			} else
404 				kprintf("<%s@%p> <unknown>", image, (void*)baseAddress);
405 		}
406 
407 		kprintf(" + %#04lx\n", ip - baseAddress);
408 	} else {
409 		VMArea *area = NULL;
410 		if (thread != NULL && thread->team != NULL
411 			&& thread->team->address_space != NULL) {
412 			area = thread->team->address_space->LookupArea(ip);
413 		}
414 		if (area != NULL) {
415 			kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name,
416 				(void*)area->Base(), ip - area->Base());
417 		} else
418 			kprintf("\n");
419 	}
420 }
421 
422 
423 static void
424 print_iframe(iframe* frame)
425 {
426 	bool isUser = IFRAME_IS_USER(frame);
427 
428 #ifdef __x86_64__
429 	kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
430 		frame + 1);
431 
432 	kprintf(" rax %#-18lx    rbx %#-18lx    rcx %#lx\n", frame->ax,
433 		frame->bx, frame->cx);
434 	kprintf(" rdx %#-18lx    rsi %#-18lx    rdi %#lx\n", frame->dx,
435 		frame->si, frame->di);
436 	kprintf(" rbp %#-18lx     r8 %#-18lx     r9 %#lx\n", frame->bp,
437 		frame->r8, frame->r9);
438 	kprintf(" r10 %#-18lx    r11 %#-18lx    r12 %#lx\n", frame->r10,
439 		frame->r11, frame->r12);
440 	kprintf(" r13 %#-18lx    r14 %#-18lx    r15 %#lx\n", frame->r13,
441 		frame->r14, frame->r15);
442 	kprintf(" rip %#-18lx    rsp %#-18lx rflags %#lx\n", frame->ip,
443 		frame->sp, frame->flags);
444 #else
445 	kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
446 		isUser ? (void*)(frame + 1) : (void*)&frame->user_sp);
447 
448 	kprintf(" eax %#-10lx    ebx %#-10lx     ecx %#-10lx  edx %#lx\n",
449 		frame->ax, frame->bx, frame->cx, frame->dx);
450 	kprintf(" esi %#-10lx    edi %#-10lx     ebp %#-10lx  esp %#lx\n",
451 		frame->si, frame->di, frame->bp, frame->sp);
452 	kprintf(" eip %#-10lx eflags %#-10lx", frame->ip, frame->flags);
453 	if (isUser) {
454 		// from user space
455 		kprintf("user esp %#lx", frame->user_sp);
456 	}
457 	kprintf("\n");
458 #endif
459 
460 	kprintf(" vector: %#lx, error code: %#lx\n", frame->vector,
461 		frame->error_code);
462 }
463 
464 
465 static bool
466 setup_for_thread(char* arg, Thread** _thread, addr_t* _bp,
467 	phys_addr_t* _oldPageDirectory)
468 {
469 	Thread* thread = NULL;
470 
471 	if (arg != NULL) {
472 		thread_id id = strtoul(arg, NULL, 0);
473 		thread = Thread::GetDebug(id);
474 		if (thread == NULL) {
475 			kprintf("could not find thread %" B_PRId32 "\n", id);
476 			return false;
477 		}
478 
479 		if (id != thread_get_current_thread_id()) {
480 			// switch to the page directory of the new thread to be
481 			// able to follow the stack trace into userland
482 			phys_addr_t newPageDirectory = x86_next_page_directory(
483 				thread_get_current_thread(), thread);
484 
485 			if (newPageDirectory != 0) {
486 				*_oldPageDirectory = x86_read_cr3();
487 				x86_write_cr3(newPageDirectory);
488 			}
489 
490 			if (thread->state == B_THREAD_RUNNING) {
491 				// The thread is currently running on another CPU.
492 				if (thread->cpu == NULL)
493 					return false;
494 				arch_debug_registers* registers = debug_get_debug_registers(
495 					thread->cpu->cpu_num);
496 				if (registers == NULL)
497 					return false;
498 				*_bp = registers->bp;
499 			} else {
500 				// Read frame pointer from the thread's stack.
501 				*_bp = thread->arch_info.GetFramePointer();
502 			}
503 		} else
504 			thread = NULL;
505 	}
506 
507 	if (thread == NULL) {
508 		// if we don't have a thread yet, we want the current one
509 		// (ebp has been set by the caller for this case already)
510 		thread = thread_get_current_thread();
511 	}
512 
513 	*_thread = thread;
514 	return true;
515 }
516 
517 
518 static bool
519 is_double_fault_stack_address(int32 cpu, addr_t address)
520 {
521 	size_t size;
522 	addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size);
523 	return address >= bottom && address < bottom + size;
524 }
525 
526 
527 static bool
528 is_kernel_stack_address(Thread* thread, addr_t address)
529 {
530 	// We don't have a thread pointer in the early boot process, but then we are
531 	// on the kernel stack for sure.
532 	if (thread == NULL)
533 		return IS_KERNEL_ADDRESS(address);
534 
535 	// Also in the early boot process we might have a thread structure, but it
536 	// might not have its kernel stack attributes set yet.
537 	if (thread->kernel_stack_top == 0)
538 		return IS_KERNEL_ADDRESS(address);
539 
540 	return (address >= thread->kernel_stack_base
541 			&& address < thread->kernel_stack_top)
542 		|| (thread->cpu != NULL
543 			&& is_double_fault_stack_address(thread->cpu->cpu_num, address));
544 }
545 
546 
547 static bool
548 is_iframe(Thread* thread, addr_t frame)
549 {
550 	if (!is_kernel_stack_address(thread, frame))
551 		return false;
552 
553 	addr_t previousFrame = *(addr_t*)frame;
554 	return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0
555 		&& previousFrame != 0);
556 }
557 
558 
559 static iframe*
560 find_previous_iframe(Thread* thread, addr_t frame)
561 {
562 	// iterate backwards through the stack frames, until we hit an iframe
563 	while (is_kernel_stack_address(thread, frame)) {
564 		if (is_iframe(thread, frame))
565 			return (iframe*)frame;
566 
567 		frame = *(addr_t*)frame;
568 	}
569 
570 	return NULL;
571 }
572 
573 
574 static iframe*
575 get_previous_iframe(Thread* thread, iframe* frame)
576 {
577 	if (frame == NULL)
578 		return NULL;
579 
580 	return find_previous_iframe(thread, frame->bp);
581 }
582 
583 
584 static iframe*
585 get_current_iframe(Thread* thread)
586 {
587 	if (thread == thread_get_current_thread())
588 		return x86_get_current_iframe();
589 
590 	// NOTE: This doesn't work, if the thread is running (on another CPU).
591 	return find_previous_iframe(thread, thread->arch_info.GetFramePointer());
592 }
593 
594 
595 #define CHECK_DEBUG_VARIABLE(_name, _member, _settable) \
596 	if (strcmp(variableName, _name) == 0) { \
597 		settable = _settable; \
598 		return &_member; \
599 	}
600 
601 
602 static size_t*
603 find_debug_variable(const char* variableName, bool& settable)
604 {
605 	iframe* frame = get_current_iframe(debug_get_debugged_thread());
606 	if (frame == NULL)
607 		return NULL;
608 
609 #ifdef __x86_64__
610 	CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
611 	CHECK_DEBUG_VARIABLE("ss", frame->ss, false);
612 	CHECK_DEBUG_VARIABLE("r15", frame->r15, true);
613 	CHECK_DEBUG_VARIABLE("r14", frame->r14, true);
614 	CHECK_DEBUG_VARIABLE("r13", frame->r13, true);
615 	CHECK_DEBUG_VARIABLE("r12", frame->r12, true);
616 	CHECK_DEBUG_VARIABLE("r11", frame->r11, true);
617 	CHECK_DEBUG_VARIABLE("r10", frame->r10, true);
618 	CHECK_DEBUG_VARIABLE("r9", frame->r9, true);
619 	CHECK_DEBUG_VARIABLE("r8", frame->r8, true);
620 	CHECK_DEBUG_VARIABLE("rbp", frame->bp, true);
621 	CHECK_DEBUG_VARIABLE("rsi", frame->si, true);
622 	CHECK_DEBUG_VARIABLE("rdi", frame->di, true);
623 	CHECK_DEBUG_VARIABLE("rdx", frame->dx, true);
624 	CHECK_DEBUG_VARIABLE("rcx", frame->cx, true);
625 	CHECK_DEBUG_VARIABLE("rbx", frame->bx, true);
626 	CHECK_DEBUG_VARIABLE("rax", frame->ax, true);
627 	CHECK_DEBUG_VARIABLE("rip", frame->ip, true);
628 	CHECK_DEBUG_VARIABLE("rflags", frame->flags, true);
629 	CHECK_DEBUG_VARIABLE("rsp", frame->sp, true);
630 #else
631 	CHECK_DEBUG_VARIABLE("gs", frame->gs, false);
632 	CHECK_DEBUG_VARIABLE("fs", frame->fs, false);
633 	CHECK_DEBUG_VARIABLE("es", frame->es, false);
634 	CHECK_DEBUG_VARIABLE("ds", frame->ds, false);
635 	CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
636 	CHECK_DEBUG_VARIABLE("edi", frame->di, true);
637 	CHECK_DEBUG_VARIABLE("esi", frame->si, true);
638 	CHECK_DEBUG_VARIABLE("ebp", frame->bp, true);
639 	CHECK_DEBUG_VARIABLE("esp", frame->sp, true);
640 	CHECK_DEBUG_VARIABLE("ebx", frame->bx, true);
641 	CHECK_DEBUG_VARIABLE("edx", frame->dx, true);
642 	CHECK_DEBUG_VARIABLE("ecx", frame->cx, true);
643 	CHECK_DEBUG_VARIABLE("eax", frame->ax, true);
644 	CHECK_DEBUG_VARIABLE("orig_eax", frame->orig_eax, true);
645 	CHECK_DEBUG_VARIABLE("orig_edx", frame->orig_edx, true);
646 	CHECK_DEBUG_VARIABLE("eip", frame->ip, true);
647 	CHECK_DEBUG_VARIABLE("eflags", frame->flags, true);
648 
649 	if (IFRAME_IS_USER(frame)) {
650 		CHECK_DEBUG_VARIABLE("user_esp", frame->user_sp, true);
651 		CHECK_DEBUG_VARIABLE("user_ss", frame->user_ss, false);
652 	}
653 #endif
654 
655 	return NULL;
656 }
657 
658 
659 static int
660 stack_trace(int argc, char** argv)
661 {
662 	static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
663 		"Prints a stack trace for the current, respectively the specified\n"
664 		"thread.\n"
665 		"  -d           -  Disables the demangling of the symbols.\n"
666 		"  <thread id>  -  The ID of the thread for which to print the stack\n"
667 		"                  trace.\n";
668 	bool demangle = true;
669 	int32 threadIndex = 1;
670 	if (argc > 1 && !strcmp(argv[1], "-d")) {
671 		demangle = false;
672 		threadIndex++;
673 	}
674 
675 	if (argc > threadIndex + 1
676 		|| (argc == 2 && strcmp(argv[1], "--help") == 0)) {
677 		kprintf(usage, argv[0]);
678 		return 0;
679 	}
680 
681 	addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
682 	Thread* thread = NULL;
683 	phys_addr_t oldPageDirectory = 0;
684 	addr_t bp = x86_get_stack_frame();
685 	int32 num = 0, last = 0;
686 
687 	if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
688 			&thread, &bp, &oldPageDirectory))
689 		return 0;
690 
691 	DebuggedThreadSetter threadSetter(thread);
692 
693 	if (thread != NULL) {
694 		kprintf("stack trace for thread %" B_PRId32 " \"%s\"\n", thread->id,
695 			thread->name);
696 
697 		kprintf("    kernel stack: %p to %p\n",
698 			(void*)thread->kernel_stack_base,
699 			(void*)(thread->kernel_stack_top));
700 		if (thread->user_stack_base != 0) {
701 			kprintf("      user stack: %p to %p\n",
702 				(void*)thread->user_stack_base,
703 				(void*)(thread->user_stack_base + thread->user_stack_size));
704 		}
705 	}
706 
707 	kprintf("%-*s            %-*s   <image>:function + offset\n",
708 		B_PRINTF_POINTER_WIDTH, "frame", B_PRINTF_POINTER_WIDTH, "caller");
709 
710 	bool onKernelStack = true;
711 
712 	for (int32 callIndex = 0;; callIndex++) {
713 		onKernelStack = onKernelStack
714 			&& is_kernel_stack_address(thread, bp);
715 
716 		if (onKernelStack && is_iframe(thread, bp)) {
717 			iframe* frame = (iframe*)bp;
718 
719 			print_iframe(frame);
720 			print_stack_frame(thread, frame->ip, bp, frame->bp, callIndex,
721 				demangle);
722 
723  			bp = frame->bp;
724 		} else {
725 			addr_t ip, nextBp;
726 
727 			if (get_next_frame_debugger(bp, &nextBp, &ip) != B_OK) {
728 				kprintf("%0*lx -- read fault\n", B_PRINTF_POINTER_WIDTH, bp);
729 				break;
730 			}
731 
732 			if (ip == 0 || bp == 0)
733 				break;
734 
735 			print_stack_frame(thread, ip, bp, nextBp, callIndex, demangle);
736 			bp = nextBp;
737 		}
738 
739 		if (already_visited(previousLocations, &last, &num, bp)) {
740 			kprintf("circular stack frame: %p!\n", (void*)bp);
741 			break;
742 		}
743 		if (bp == 0)
744 			break;
745 	}
746 
747 	if (oldPageDirectory != 0) {
748 		// switch back to the previous page directory to no cause any troubles
749 		x86_write_cr3(oldPageDirectory);
750 	}
751 
752 	return 0;
753 }
754 
755 
756 #ifndef __x86_64__
757 static void
758 print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
759 	int32 argCount)
760 {
761 	const char *symbol, *image;
762 	addr_t baseAddress;
763 	bool exactMatch;
764 	status_t status;
765 	bool demangled = false;
766 	int32 *arg = (int32 *)(nextEbp + 8);
767 
768 	status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
769 		&exactMatch);
770 
771 	kprintf("%08lx %08lx   ", ebp, eip);
772 
773 	if (status == B_OK) {
774 		if (symbol != NULL) {
775 			if (exactMatch && (argCount == 0 || argCount == -1)) {
776 				status = print_demangled_call(image, symbol, (addr_t)arg,
777 					argCount == -1, true);
778 				if (status == B_OK)
779 					demangled = true;
780 			}
781 			if (!demangled) {
782 				kprintf("<%s>:%s%s", image, symbol,
783 					exactMatch ? "" : " (nearest)");
784 			}
785 		} else {
786 			kprintf("<%s@%p>:unknown + 0x%04lx", image,
787 				(void *)baseAddress, eip - baseAddress);
788 		}
789 	} else {
790 		VMArea *area = NULL;
791 		if (thread->team->address_space != NULL)
792 			area = thread->team->address_space->LookupArea(eip);
793 		if (area != NULL) {
794 			kprintf("%ld:%s@%p + %#lx", area->id, area->name,
795 				(void *)area->Base(), eip - area->Base());
796 		}
797 	}
798 
799 	if (!demangled) {
800 		kprintf("(");
801 
802 		for (int32 i = 0; i < argCount; i++) {
803 			if (i > 0)
804 				kprintf(", ");
805 			kprintf("%#lx", *arg);
806 			if (*arg > -0x10000 && *arg < 0x10000)
807 				kprintf(" (%ld)", *arg);
808 
809 			set_debug_argument_variable(i + 1, *(uint32 *)arg);
810 			arg++;
811 		}
812 
813 		kprintf(")\n");
814 	} else
815 		kprintf("\n");
816 
817 	set_debug_variable("_frame", nextEbp);
818 }
819 
820 
821 static int
822 show_call(int argc, char **argv)
823 {
824 	static const char* usage
825 		= "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n"
826 		"Prints a function call with parameters of the current, respectively\n"
827 		"the specified thread.\n"
828 		"  <thread id>   -  The ID of the thread for which to print the call.\n"
829 		"  <call index>  -  The index of the call in the stack trace.\n"
830 		"  <arg count>   -  The number of call arguments to print (use 'c' to\n"
831 		"                   force the C++ demangler to use class methods,\n"
832 		"                   use 'd' to disable demangling).\n";
833 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
834 		kprintf(usage, argv[0]);
835 		return 0;
836 	}
837 
838 	Thread *thread = NULL;
839 	phys_addr_t oldPageDirectory = 0;
840 	addr_t ebp = x86_get_stack_frame();
841 	int32 argCount = 0;
842 
843 	if (argc >= 2 && argv[argc - 1][0] == '-') {
844 		if (argv[argc - 1][1] == 'c')
845 			argCount = -1;
846 		else if (argv[argc - 1][1] == 'd')
847 			argCount = -2;
848 		else
849 			argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
850 
851 		if (argCount < -2 || argCount > 16) {
852 			kprintf("Invalid argument count \"%ld\".\n", argCount);
853 			return 0;
854 		}
855 		argc--;
856 	}
857 
858 	if (argc < 2 || argc > 3) {
859 		kprintf(usage, argv[0]);
860 		return 0;
861 	}
862 
863 	if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp,
864 			&oldPageDirectory))
865 		return 0;
866 
867 	DebuggedThreadSetter threadSetter(thread);
868 
869 	int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0);
870 
871 	if (thread != NULL)
872 		kprintf("thread %ld, %s\n", thread->id, thread->name);
873 
874 	bool onKernelStack = true;
875 
876 	for (int32 index = 0; index <= callIndex; index++) {
877 		onKernelStack = onKernelStack
878 			&& is_kernel_stack_address(thread, ebp);
879 
880 		if (onKernelStack && is_iframe(thread, ebp)) {
881 			struct iframe *frame = (struct iframe *)ebp;
882 
883 			if (index == callIndex)
884 				print_call(thread, frame->ip, ebp, frame->bp, argCount);
885 
886  			ebp = frame->bp;
887 		} else {
888 			addr_t eip, nextEbp;
889 
890 			if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
891 				kprintf("%08lx -- read fault\n", ebp);
892 				break;
893 			}
894 
895 			if (eip == 0 || ebp == 0)
896 				break;
897 
898 			if (index == callIndex)
899 				print_call(thread, eip, ebp, nextEbp, argCount);
900 
901 			ebp = nextEbp;
902 		}
903 
904 		if (ebp == 0)
905 			break;
906 	}
907 
908 	if (oldPageDirectory != 0) {
909 		// switch back to the previous page directory to not cause any troubles
910 		x86_write_cr3(oldPageDirectory);
911 	}
912 
913 	return 0;
914 }
915 #endif
916 
917 
918 static int
919 dump_iframes(int argc, char** argv)
920 {
921 	static const char* usage = "usage: %s [ <thread id> ]\n"
922 		"Prints the iframe stack for the current, respectively the specified\n"
923 		"thread.\n"
924 		"  <thread id>  -  The ID of the thread for which to print the iframe\n"
925 		"                  stack.\n";
926 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
927 		kprintf(usage, argv[0]);
928 		return 0;
929 	}
930 
931 	Thread* thread = NULL;
932 
933 	if (argc < 2) {
934 		thread = thread_get_current_thread();
935 	} else if (argc == 2) {
936 		thread_id id = strtoul(argv[1], NULL, 0);
937 		thread = Thread::GetDebug(id);
938 		if (thread == NULL) {
939 			kprintf("could not find thread %" B_PRId32 "\n", id);
940 			return 0;
941 		}
942 	} else if (argc > 2) {
943 		kprintf(usage, argv[0]);
944 		return 0;
945 	}
946 
947 	if (thread != NULL) {
948 		kprintf("iframes for thread %" B_PRId32 " \"%s\"\n", thread->id,
949 			thread->name);
950 	}
951 
952 	DebuggedThreadSetter threadSetter(thread);
953 
954 	iframe* frame = find_previous_iframe(thread, x86_get_stack_frame());
955 	while (frame != NULL) {
956 		print_iframe(frame);
957 		frame = get_previous_iframe(thread, frame);
958 	}
959 
960 	return 0;
961 }
962 
963 
964 static bool
965 is_calling(Thread* thread, addr_t ip, const char* pattern, addr_t start,
966 	addr_t end)
967 {
968 	if (pattern == NULL)
969 		return ip >= start && ip < end;
970 
971 	if (!IS_KERNEL_ADDRESS(ip))
972 		return false;
973 
974 	const char* symbol;
975 	if (lookup_symbol(thread, ip, NULL, &symbol, NULL, NULL) != B_OK)
976 		return false;
977 
978 	return strstr(symbol, pattern);
979 }
980 
981 
982 static int
983 cmd_in_context(int argc, char** argv)
984 {
985 	if (argc != 2) {
986 		print_debugger_command_usage(argv[0]);
987 		return 0;
988 	}
989 
990 	// get the thread ID
991 	const char* commandLine = argv[1];
992 	char threadIDString[16];
993 	if (parse_next_debug_command_argument(&commandLine, threadIDString,
994 			sizeof(threadIDString)) != B_OK) {
995 		kprintf("Failed to parse thread ID.\n");
996 		return 0;
997 	}
998 
999 	if (commandLine == NULL) {
1000 		print_debugger_command_usage(argv[0]);
1001 		return 0;
1002 	}
1003 
1004 	uint64 threadID;
1005 	if (!evaluate_debug_expression(threadIDString, &threadID, false))
1006 		return 0;
1007 
1008 	// get the thread
1009 	Thread* thread = Thread::GetDebug(threadID);
1010 	if (thread == NULL) {
1011 		kprintf("Could not find thread with ID \"%s\".\n", threadIDString);
1012 		return 0;
1013 	}
1014 
1015 	// switch the page directory, if necessary
1016 	phys_addr_t oldPageDirectory = 0;
1017 	if (thread != thread_get_current_thread()) {
1018 		phys_addr_t newPageDirectory = x86_next_page_directory(
1019 			thread_get_current_thread(), thread);
1020 
1021 		if (newPageDirectory != 0) {
1022 			oldPageDirectory = x86_read_cr3();
1023 			x86_write_cr3(newPageDirectory);
1024 		}
1025 	}
1026 
1027 	// execute the command
1028 	{
1029 		DebuggedThreadSetter threadSetter(thread);
1030 		evaluate_debug_command(commandLine);
1031 	}
1032 
1033 	// reset the page directory
1034 	if (oldPageDirectory)
1035 		x86_write_cr3(oldPageDirectory);
1036 
1037 	return 0;
1038 }
1039 
1040 
1041 //	#pragma mark -
1042 
1043 
1044 void
1045 arch_debug_save_registers(arch_debug_registers* registers)
1046 {
1047 	// get the caller's frame pointer
1048 	stack_frame* frame = (stack_frame*)x86_get_stack_frame();
1049 	registers->bp = (addr_t)frame->previous;
1050 }
1051 
1052 
1053 void
1054 arch_debug_stack_trace(void)
1055 {
1056 	stack_trace(0, NULL);
1057 }
1058 
1059 
1060 bool
1061 arch_debug_contains_call(Thread* thread, const char* symbol, addr_t start,
1062 	addr_t end)
1063 {
1064 	DebuggedThreadSetter threadSetter(thread);
1065 
1066 	addr_t bp;
1067 	if (thread == thread_get_current_thread())
1068 		bp = x86_get_stack_frame();
1069 	else {
1070 		if (thread->state == B_THREAD_RUNNING) {
1071 			// The thread is currently running on another CPU.
1072 			if (thread->cpu == NULL)
1073 				return false;
1074 			arch_debug_registers* registers = debug_get_debug_registers(
1075 				thread->cpu->cpu_num);
1076 			if (registers == NULL)
1077 				return false;
1078 			bp = registers->bp;
1079 		} else {
1080 			// thread not running
1081 			bp = thread->arch_info.GetFramePointer();
1082 		}
1083 	}
1084 
1085 	for (;;) {
1086 		if (!is_kernel_stack_address(thread, bp))
1087 			break;
1088 
1089 		if (is_iframe(thread, bp)) {
1090 			iframe* frame = (iframe*)bp;
1091 
1092 			if (is_calling(thread, frame->ip, symbol, start, end))
1093 				return true;
1094 
1095  			bp = frame->bp;
1096 		} else {
1097 			addr_t ip, nextBp;
1098 
1099 			if (get_next_frame_no_debugger(bp, &nextBp, &ip, true,
1100 					thread) != B_OK
1101 				|| ip == 0 || bp == 0)
1102 				break;
1103 
1104 			if (is_calling(thread, ip, symbol, start, end))
1105 				return true;
1106 
1107 			bp = nextBp;
1108 		}
1109 
1110 		if (bp == 0)
1111 			break;
1112 	}
1113 
1114 	return false;
1115 }
1116 
1117 
1118 void*
1119 arch_debug_get_caller(void)
1120 {
1121 	stack_frame* frame = (stack_frame*)x86_get_stack_frame();
1122 	return (void*)frame->previous->return_address;
1123 }
1124 
1125 
1126 /*!	Captures a stack trace (the return addresses) of the current thread.
1127 	\param returnAddresses The array the return address shall be written to.
1128 	\param maxCount The maximum number of return addresses to be captured.
1129 	\param skipIframes The number of interrupt frames that shall be skipped. If
1130 		greater than 0, \a skipFrames is ignored.
1131 	\param skipFrames The number of stack frames that shall be skipped.
1132 	\param flags A combination of one or two of the following:
1133 		- \c STACK_TRACE_KERNEL: Capture kernel return addresses.
1134 		- \c STACK_TRACE_USER: Capture user return addresses.
1135 	\return The number of return addresses written to the given array.
1136 */
1137 int32
1138 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
1139 	int32 skipIframes, int32 skipFrames, uint32 flags)
1140 {
1141 	// Keep skipping normal stack frames until we've skipped the iframes we're
1142 	// supposed to skip.
1143 	if (skipIframes > 0)
1144 		skipFrames = INT_MAX;
1145 
1146 	Thread* thread = thread_get_current_thread();
1147 	int32 count = 0;
1148 	addr_t bp = x86_get_stack_frame();
1149 	bool onKernelStack = true;
1150 
1151 	while (bp != 0 && count < maxCount) {
1152 		onKernelStack = onKernelStack
1153 			&& is_kernel_stack_address(thread, bp);
1154 		if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
1155 			break;
1156 
1157 		addr_t ip;
1158 		addr_t nextBp;
1159 
1160 		if (onKernelStack && is_iframe(thread, bp)) {
1161 			iframe* frame = (iframe*)bp;
1162 			ip = frame->ip;
1163 			nextBp = frame->bp;
1164 
1165 			if (skipIframes > 0) {
1166 				if (--skipIframes == 0)
1167 					skipFrames = 0;
1168 			}
1169 		} else {
1170 			if (get_next_frame_no_debugger(bp, &nextBp, &ip,
1171 					onKernelStack, thread) != B_OK) {
1172 				break;
1173 			}
1174 		}
1175 
1176 		if (ip == 0)
1177 			break;
1178 
1179 		if (skipFrames <= 0
1180 			&& ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) {
1181 			returnAddresses[count++] = ip;
1182 		} else
1183 			skipFrames--;
1184 
1185 		bp = nextBp;
1186 	}
1187 
1188 	return count;
1189 }
1190 
1191 
1192 /*!	Returns the program counter of the currently debugged (respectively this)
1193 	thread where the innermost interrupts happened. \a _isSyscall, if specified,
1194 	is set to whether this interrupt frame was created by a syscall. Returns
1195 	\c NULL, if there's no such frame or a problem occurred retrieving it;
1196 	\a _isSyscall won't be set in this case.
1197 */
1198 void*
1199 arch_debug_get_interrupt_pc(bool* _isSyscall)
1200 {
1201 	iframe* frame = get_current_iframe(debug_get_debugged_thread());
1202 	if (frame == NULL)
1203 		return NULL;
1204 
1205 	if (_isSyscall != NULL)
1206 		*_isSyscall = frame->type == IFRAME_TYPE_SYSCALL;
1207 
1208 	return (void*)(addr_t)frame->ip;
1209 }
1210 
1211 
1212 /*!	Sets the current thread to \c NULL.
1213 	Invoked in the kernel debugger only.
1214 */
1215 void
1216 arch_debug_unset_current_thread(void)
1217 {
1218 	// Can't just write 0 to the GS base, that will cause the read from %gs:0
1219 	// to fault. Instead point it at a NULL pointer, %gs:0 will get this value.
1220 	static Thread* unsetThread = NULL;
1221 #ifdef __x86_64__
1222 	x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&unsetThread);
1223 #else
1224 	asm volatile("mov %0, %%gs:0" : : "r" (unsetThread) : "memory");
1225 #endif
1226 }
1227 
1228 
1229 bool
1230 arch_is_debug_variable_defined(const char* variableName)
1231 {
1232 	bool settable;
1233 	return find_debug_variable(variableName, settable);
1234 }
1235 
1236 
1237 status_t
1238 arch_set_debug_variable(const char* variableName, uint64 value)
1239 {
1240 	bool settable;
1241 	size_t* variable = find_debug_variable(variableName, settable);
1242 	if (variable == NULL)
1243 		return B_ENTRY_NOT_FOUND;
1244 
1245 	if (!settable)
1246 		return B_NOT_ALLOWED;
1247 
1248 	*variable = (size_t)value;
1249 	return B_OK;
1250 }
1251 
1252 
1253 status_t
1254 arch_get_debug_variable(const char* variableName, uint64* value)
1255 {
1256 	bool settable;
1257 	size_t* variable = find_debug_variable(variableName, settable);
1258 	if (variable == NULL)
1259 		return B_ENTRY_NOT_FOUND;
1260 
1261 	*value = *variable;
1262 	return B_OK;
1263 }
1264 
1265 
1266 struct gdb_register {
1267 	int32 type;
1268 	uint64 value;
1269 };
1270 
1271 
1272 /*!	Writes the contents of the CPU registers at some fixed outer stack frame or
1273 	iframe into the given buffer in the format expected by gdb.
1274 
1275 	This function is called in response to gdb's 'g' command.
1276 
1277 	\param buffer The buffer to write the registers to.
1278 	\param bufferSize The size of \a buffer in bytes.
1279 	\return When successful, the number of bytes written to \a buffer, or a
1280 		negative error code on error.
1281 */
1282 ssize_t
1283 arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
1284 {
1285 	iframe* frame = get_current_iframe(debug_get_debugged_thread());
1286 	if (frame == NULL)
1287 		return B_NOT_SUPPORTED;
1288 
1289 #ifdef __x86_64__
1290 	// For x86_64 the register order is:
1291 	//
1292 	//    rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
1293 	//    r8, r9, r10, r11, r12, r13, r14, r15,
1294 	//    rip, rflags, cs, ss, ds, es, fs, gs
1295 	//
1296 	// Annoyingly, GDB wants all the registers as 64-bit values, but then
1297 	// RFLAGS and the segment registers as 32-bit values, hence the need for
1298 	// the type information.
1299 	static const int32 kRegisterCount = 24;
1300 	gdb_register registers[kRegisterCount] = {
1301 		{ B_UINT64_TYPE, frame->ax },  { B_UINT64_TYPE, frame->bx },
1302 		{ B_UINT64_TYPE, frame->cx },  { B_UINT64_TYPE, frame->dx },
1303 		{ B_UINT64_TYPE, frame->si },  { B_UINT64_TYPE, frame->di },
1304 		{ B_UINT64_TYPE, frame->bp },  { B_UINT64_TYPE, frame->sp },
1305 		{ B_UINT64_TYPE, frame->r8 },  { B_UINT64_TYPE, frame->r9 },
1306 		{ B_UINT64_TYPE, frame->r10 }, { B_UINT64_TYPE, frame->r11 },
1307 		{ B_UINT64_TYPE, frame->r12 }, { B_UINT64_TYPE, frame->r13 },
1308 		{ B_UINT64_TYPE, frame->r14 }, { B_UINT64_TYPE, frame->r15 },
1309 		{ B_UINT64_TYPE, frame->ip },  { B_UINT32_TYPE, frame->flags },
1310 		{ B_UINT32_TYPE, frame->cs },  { B_UINT32_TYPE, frame->ss },
1311 		{ B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1312 		{ B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1313 	};
1314 #else
1315 	// For x86 the register order is:
1316 	//
1317 	//    eax, ecx, edx, ebx,
1318 	//    esp, ebp, esi, edi,
1319 	//    eip, eflags,
1320 	//    cs, ss, ds, es, fs, gs
1321 	//
1322 	// Note that even though the segment descriptors are actually 16 bits wide,
1323 	// gdb requires them as 32 bit integers.
1324 	static const int32 kRegisterCount = 16;
1325 	gdb_register registers[kRegisterCount] = {
1326 		{ B_UINT32_TYPE, frame->ax }, { B_UINT32_TYPE, frame->cx },
1327 		{ B_UINT32_TYPE, frame->dx }, { B_UINT32_TYPE, frame->bx },
1328 		{ B_UINT32_TYPE, frame->sp }, { B_UINT32_TYPE, frame->bp },
1329 		{ B_UINT32_TYPE, frame->si }, { B_UINT32_TYPE, frame->di },
1330 		{ B_UINT32_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
1331 		{ B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ds },
1332 			// assume ss == ds
1333 		{ B_UINT32_TYPE, frame->ds }, { B_UINT32_TYPE, frame->es },
1334 		{ B_UINT32_TYPE, frame->fs }, { B_UINT32_TYPE, frame->gs },
1335 	};
1336 #endif
1337 
1338 	const char* const bufferStart = buffer;
1339 
1340 	for (int32 i = 0; i < kRegisterCount; i++) {
1341 		// For some reason gdb wants the register dump in *big endian* format.
1342 		int result = 0;
1343 		switch (registers[i].type) {
1344 			case B_UINT64_TYPE:
1345 				result = snprintf(buffer, bufferSize, "%016" B_PRIx64,
1346 					(uint64)B_HOST_TO_BENDIAN_INT64(registers[i].value));
1347 				break;
1348 			case B_UINT32_TYPE:
1349 				result = snprintf(buffer, bufferSize, "%08" B_PRIx32,
1350 					(uint32)B_HOST_TO_BENDIAN_INT32((uint32)registers[i].value));
1351 				break;
1352 		}
1353 		if (result >= (int)bufferSize)
1354 			return B_BUFFER_OVERFLOW;
1355 
1356 		buffer += result;
1357 		bufferSize -= result;
1358 	}
1359 
1360 	return buffer - bufferStart;
1361 }
1362 
1363 
1364 status_t
1365 arch_debug_init(kernel_args* args)
1366 {
1367 	// at this stage, the debugger command system is alive
1368 
1369 	add_debugger_command("where", &stack_trace, "Same as \"sc\"");
1370 	add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
1371 	add_debugger_command("sc", &stack_trace,
1372 		"Stack crawl for current thread (or any other)");
1373 	add_debugger_command("iframe", &dump_iframes,
1374 		"Dump iframes for the specified thread");
1375 #ifndef __x86_64__
1376 	add_debugger_command("call", &show_call, "Show call with arguments");
1377 #endif
1378 	add_debugger_command_etc("in_context", &cmd_in_context,
1379 		"Executes a command in the context of a given thread",
1380 		"<thread ID> <command> ...\n"
1381 		"Executes a command in the context of a given thread.\n",
1382 		B_KDEBUG_DONT_PARSE_ARGUMENTS);
1383 
1384 	return B_NO_ERROR;
1385 }
1386 
1387