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