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