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