xref: /haiku/src/system/kernel/arch/x86/arch_debug.cpp (revision 90b9af1ddd498e701d354c3a2b448ef46953f7a6)
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
already_visited(addr_t * visited,int32 * _last,int32 * _num,addr_t bp)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
get_next_frame_no_debugger(addr_t bp,addr_t * _next,addr_t * _ip,bool onKernelStack,Thread * thread)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
get_next_frame_debugger(addr_t bp,addr_t * _next,addr_t * _ip)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
lookup_symbol(Thread * thread,addr_t address,addr_t * _baseAddress,const char ** _symbolName,const char ** _imageName,bool * _exactMatch)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
set_debug_argument_variable(int32 index,uint64 value)135 set_debug_argument_variable(int32 index, uint64 value)
136 {
137 	char name[8];
138 	snprintf(name, sizeof(name), "_arg%d", index);
139 	set_debug_variable(name, value);
140 }
141 
142 
143 template<typename Type>
144 static Type
read_function_argument_value(void * argument,bool & _valueKnown)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
print_demangled_call(const char * image,const char * symbol,addr_t args,bool noObjectMethod,bool addDebugVariables)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%d\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%#x\33[0m", (uint32)value);
244 					if (value < 0x100000)
245 						kprintf(" (\33[34m%u\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%#x\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
print_demangled_call(const char * image,const char * symbol,addr_t args,bool noObjectMethod,bool addDebugVariables)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
print_stack_frame(Thread * thread,addr_t ip,addr_t calleeBp,addr_t bp,int32 callIndex,bool demangle)373 print_stack_frame(Thread* thread, addr_t ip, addr_t calleeBp, addr_t bp,
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 = bp - calleeBp;
384 
385 	// kernel space/user space switch
386 	if (calleeBp > bp)
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 				bp + 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
print_iframe(iframe * frame)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 %#-10x    ebx %#-10x     ecx %#-10x  edx %#x\n",
451 		frame->ax, frame->bx, frame->cx, frame->dx);
452 	kprintf(" esi %#-10x    edi %#-10x     ebp %#-10x  esp %#x\n",
453 		frame->si, frame->di, frame->bp, frame->sp);
454 	kprintf(" eip %#-10x eflags %#-10x", frame->ip, frame->flags);
455 	if (isUser) {
456 		// from user space
457 		kprintf("user esp %#x", frame->user_sp);
458 	}
459 	kprintf("\n");
460 #endif
461 
462 	kprintf(" vector: %#lx, error code: %#lx\n",
463 		(long unsigned int)frame->vector,
464 		(long unsigned int)frame->error_code);
465 }
466 
467 
468 static bool
setup_for_thread(char * arg,Thread ** _thread,addr_t * _bp,phys_addr_t * _oldPageDirectory)469 setup_for_thread(char* arg, Thread** _thread, addr_t* _bp,
470 	phys_addr_t* _oldPageDirectory)
471 {
472 	Thread* thread = NULL;
473 
474 	if (arg != NULL) {
475 		thread_id id = strtoul(arg, NULL, 0);
476 		thread = Thread::GetDebug(id);
477 		if (thread == NULL) {
478 			kprintf("could not find thread %" B_PRId32 "\n", id);
479 			return false;
480 		}
481 
482 		if (id != thread_get_current_thread_id()) {
483 			// switch to the page directory of the new thread to be
484 			// able to follow the stack trace into userland
485 			phys_addr_t newPageDirectory = x86_next_page_directory(
486 				thread_get_current_thread(), thread);
487 
488 			if (newPageDirectory != 0) {
489 				*_oldPageDirectory = x86_read_cr3();
490 				x86_write_cr3(newPageDirectory);
491 			}
492 
493 			if (thread->state == B_THREAD_RUNNING) {
494 				// The thread is currently running on another CPU.
495 				if (thread->cpu == NULL)
496 					return false;
497 				arch_debug_registers* registers = debug_get_debug_registers(
498 					thread->cpu->cpu_num);
499 				if (registers == NULL)
500 					return false;
501 				*_bp = registers->bp;
502 			} else {
503 				// Read frame pointer from the thread's stack.
504 				*_bp = thread->arch_info.GetFramePointer();
505 			}
506 		} else
507 			thread = NULL;
508 	}
509 
510 	if (thread == NULL) {
511 		// if we don't have a thread yet, we want the current one
512 		// (ebp has been set by the caller for this case already)
513 		thread = thread_get_current_thread();
514 	}
515 
516 	*_thread = thread;
517 	return true;
518 }
519 
520 
521 static bool
is_double_fault_stack_address(int32 cpu,addr_t address)522 is_double_fault_stack_address(int32 cpu, addr_t address)
523 {
524 	size_t size;
525 	addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size);
526 	return address >= bottom && address < bottom + size;
527 }
528 
529 
530 static bool
is_kernel_stack_address(Thread * thread,addr_t address)531 is_kernel_stack_address(Thread* thread, addr_t address)
532 {
533 	// We don't have a thread pointer in the early boot process, but then we are
534 	// on the kernel stack for sure.
535 	if (thread == NULL)
536 		return IS_KERNEL_ADDRESS(address);
537 
538 	// Also in the early boot process we might have a thread structure, but it
539 	// might not have its kernel stack attributes set yet.
540 	if (thread->kernel_stack_top == 0)
541 		return IS_KERNEL_ADDRESS(address);
542 
543 	return (address >= thread->kernel_stack_base
544 			&& address < thread->kernel_stack_top)
545 		|| (thread->cpu != NULL
546 			&& is_double_fault_stack_address(thread->cpu->cpu_num, address));
547 }
548 
549 
550 static bool
is_iframe(Thread * thread,addr_t frame)551 is_iframe(Thread* thread, addr_t frame)
552 {
553 	if (!is_kernel_stack_address(thread, frame))
554 		return false;
555 
556 	addr_t previousFrame = *(addr_t*)frame;
557 	return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0
558 		&& previousFrame != 0);
559 }
560 
561 
562 static iframe*
find_previous_iframe(Thread * thread,addr_t frame)563 find_previous_iframe(Thread* thread, addr_t frame)
564 {
565 	// iterate backwards through the stack frames, until we hit an iframe
566 	while (is_kernel_stack_address(thread, frame)) {
567 		if (is_iframe(thread, frame))
568 			return (iframe*)frame;
569 
570 		frame = *(addr_t*)frame;
571 	}
572 
573 	return NULL;
574 }
575 
576 
577 static iframe*
get_previous_iframe(Thread * thread,iframe * frame)578 get_previous_iframe(Thread* thread, iframe* frame)
579 {
580 	if (frame == NULL)
581 		return NULL;
582 
583 	return find_previous_iframe(thread, frame->bp);
584 }
585 
586 
587 static iframe*
get_current_iframe(Thread * thread)588 get_current_iframe(Thread* thread)
589 {
590 	if (thread == thread_get_current_thread())
591 		return x86_get_current_iframe();
592 
593 	// NOTE: This doesn't work, if the thread is running (on another CPU).
594 	return find_previous_iframe(thread, thread->arch_info.GetFramePointer());
595 }
596 
597 
598 #define CHECK_DEBUG_VARIABLE(_name, _member, _settable) \
599 	if (strcmp(variableName, _name) == 0) { \
600 		settable = _settable; \
601 		return (addr_t*)&_member; \
602 	}
603 
604 
605 static addr_t*
find_debug_variable(const char * variableName,bool & settable)606 find_debug_variable(const char* variableName, bool& settable)
607 {
608 	iframe* frame = get_current_iframe(debug_get_debugged_thread());
609 	if (frame == NULL)
610 		return NULL;
611 
612 #ifdef __x86_64__
613 	CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
614 	CHECK_DEBUG_VARIABLE("ss", frame->ss, false);
615 	CHECK_DEBUG_VARIABLE("r15", frame->r15, true);
616 	CHECK_DEBUG_VARIABLE("r14", frame->r14, true);
617 	CHECK_DEBUG_VARIABLE("r13", frame->r13, true);
618 	CHECK_DEBUG_VARIABLE("r12", frame->r12, true);
619 	CHECK_DEBUG_VARIABLE("r11", frame->r11, true);
620 	CHECK_DEBUG_VARIABLE("r10", frame->r10, true);
621 	CHECK_DEBUG_VARIABLE("r9", frame->r9, true);
622 	CHECK_DEBUG_VARIABLE("r8", frame->r8, true);
623 	CHECK_DEBUG_VARIABLE("rbp", frame->bp, true);
624 	CHECK_DEBUG_VARIABLE("rsi", frame->si, true);
625 	CHECK_DEBUG_VARIABLE("rdi", frame->di, true);
626 	CHECK_DEBUG_VARIABLE("rdx", frame->dx, true);
627 	CHECK_DEBUG_VARIABLE("rcx", frame->cx, true);
628 	CHECK_DEBUG_VARIABLE("rbx", frame->bx, true);
629 	CHECK_DEBUG_VARIABLE("rax", frame->ax, true);
630 	CHECK_DEBUG_VARIABLE("rip", frame->ip, true);
631 	CHECK_DEBUG_VARIABLE("rflags", frame->flags, true);
632 	CHECK_DEBUG_VARIABLE("rsp", frame->sp, true);
633 #else
634 	CHECK_DEBUG_VARIABLE("gs", frame->gs, false);
635 	CHECK_DEBUG_VARIABLE("fs", frame->fs, false);
636 	CHECK_DEBUG_VARIABLE("es", frame->es, false);
637 	CHECK_DEBUG_VARIABLE("ds", frame->ds, false);
638 	CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
639 	CHECK_DEBUG_VARIABLE("edi", frame->di, true);
640 	CHECK_DEBUG_VARIABLE("esi", frame->si, true);
641 	CHECK_DEBUG_VARIABLE("ebp", frame->bp, true);
642 	CHECK_DEBUG_VARIABLE("esp", frame->sp, true);
643 	CHECK_DEBUG_VARIABLE("ebx", frame->bx, true);
644 	CHECK_DEBUG_VARIABLE("edx", frame->dx, true);
645 	CHECK_DEBUG_VARIABLE("ecx", frame->cx, true);
646 	CHECK_DEBUG_VARIABLE("eax", frame->ax, true);
647 	CHECK_DEBUG_VARIABLE("orig_eax", frame->orig_eax, true);
648 	CHECK_DEBUG_VARIABLE("orig_edx", frame->orig_edx, true);
649 	CHECK_DEBUG_VARIABLE("eip", frame->ip, true);
650 	CHECK_DEBUG_VARIABLE("eflags", frame->flags, true);
651 
652 	if (IFRAME_IS_USER(frame)) {
653 		CHECK_DEBUG_VARIABLE("user_esp", frame->user_sp, true);
654 		CHECK_DEBUG_VARIABLE("user_ss", frame->user_ss, false);
655 	}
656 #endif
657 
658 	return NULL;
659 }
660 
661 
662 static int
stack_trace(int argc,char ** argv)663 stack_trace(int argc, char** argv)
664 {
665 	static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
666 		"Prints a stack trace for the current, respectively the specified\n"
667 		"thread.\n"
668 		"  -d           -  Disables the demangling of the symbols.\n"
669 		"  <thread id>  -  The ID of the thread for which to print the stack\n"
670 		"                  trace.\n";
671 	bool demangle = true;
672 	int32 threadIndex = 1;
673 	if (argc > 1 && !strcmp(argv[1], "-d")) {
674 		demangle = false;
675 		threadIndex++;
676 	}
677 
678 	if (argc > threadIndex + 1
679 		|| (argc == 2 && strcmp(argv[1], "--help") == 0)) {
680 		kprintf(usage, argv[0]);
681 		return 0;
682 	}
683 
684 	addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
685 	Thread* thread = NULL;
686 	phys_addr_t oldPageDirectory = 0;
687 	addr_t bp = x86_get_stack_frame();
688 	int32 num = 0, last = 0;
689 
690 	if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
691 			&thread, &bp, &oldPageDirectory))
692 		return 0;
693 
694 	DebuggedThreadSetter threadSetter(thread);
695 
696 	if (thread != NULL) {
697 		kprintf("stack trace for thread %" B_PRId32 " \"%s\"\n", thread->id,
698 			thread->name);
699 
700 		kprintf("    kernel stack: %p to %p\n",
701 			(void*)thread->kernel_stack_base,
702 			(void*)(thread->kernel_stack_top));
703 		if (thread->user_stack_base != 0) {
704 			kprintf("      user stack: %p to %p\n",
705 				(void*)thread->user_stack_base,
706 				(void*)(thread->user_stack_base + thread->user_stack_size));
707 		}
708 	}
709 
710 	kprintf("%-*s            %-*s   <image>:function + offset\n",
711 		B_PRINTF_POINTER_WIDTH, "frame", B_PRINTF_POINTER_WIDTH, "caller");
712 
713 	bool onKernelStack = true;
714 
715 	for (int32 callIndex = 0; ; callIndex++) {
716 		onKernelStack = onKernelStack
717 			&& is_kernel_stack_address(thread, bp);
718 
719 		if (onKernelStack && is_iframe(thread, bp)) {
720 			iframe* frame = (iframe*)bp;
721 
722 			print_iframe(frame);
723 			print_stack_frame(thread, frame->ip, bp, frame->bp, callIndex,
724 				demangle);
725 
726  			bp = frame->bp;
727 		} else {
728 			addr_t ip, nextBp;
729 
730 			if (get_next_frame_debugger(bp, &nextBp, &ip) != B_OK) {
731 				kprintf("%0*lx -- read fault\n", B_PRINTF_POINTER_WIDTH, bp);
732 				break;
733 			}
734 
735 			if (ip == 0 || bp == 0)
736 				break;
737 
738 			print_stack_frame(thread, ip, bp, nextBp, callIndex, demangle);
739 			bp = nextBp;
740 		}
741 
742 		if (already_visited(previousLocations, &last, &num, bp)) {
743 			kprintf("circular stack frame: %p!\n", (void*)bp);
744 			break;
745 		}
746 		if (bp == 0)
747 			break;
748 	}
749 
750 	if (oldPageDirectory != 0) {
751 		// switch back to the previous page directory to no cause any troubles
752 		x86_write_cr3(oldPageDirectory);
753 	}
754 
755 	return 0;
756 }
757 
758 
759 #ifndef __x86_64__
760 static void
print_call(Thread * thread,addr_t eip,addr_t ebp,addr_t nextEbp,int32 argCount)761 print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
762 	int32 argCount)
763 {
764 	const char *symbol, *image;
765 	addr_t baseAddress;
766 	bool exactMatch;
767 	status_t status;
768 	bool demangled = false;
769 	int32 *arg = (int32 *)(nextEbp + 8);
770 
771 	status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
772 		&exactMatch);
773 
774 	kprintf("%08lx %08lx   ", ebp, eip);
775 
776 	if (status == B_OK) {
777 		if (symbol != NULL) {
778 			if (exactMatch && (argCount == 0 || argCount == -1)) {
779 				status = print_demangled_call(image, symbol, (addr_t)arg,
780 					argCount == -1, true);
781 				if (status == B_OK)
782 					demangled = true;
783 			}
784 			if (!demangled) {
785 				kprintf("<%s>:%s%s", image, symbol,
786 					exactMatch ? "" : " (nearest)");
787 			}
788 		} else {
789 			kprintf("<%s@%p>:unknown + 0x%04lx", image,
790 				(void *)baseAddress, eip - baseAddress);
791 		}
792 	} else {
793 		VMArea *area = NULL;
794 		if (thread->team->address_space != NULL)
795 			area = thread->team->address_space->LookupArea(eip);
796 		if (area != NULL) {
797 			kprintf("%d:%s@%p + %#lx", area->id, area->name,
798 				(void *)area->Base(), eip - area->Base());
799 		}
800 	}
801 
802 	if (!demangled) {
803 		kprintf("(");
804 
805 		for (int32 i = 0; i < argCount; i++) {
806 			if (i > 0)
807 				kprintf(", ");
808 			kprintf("%#x", *arg);
809 			if (*arg > -0x10000 && *arg < 0x10000)
810 				kprintf(" (%d)", *arg);
811 
812 			set_debug_argument_variable(i + 1, *(uint32 *)arg);
813 			arg++;
814 		}
815 
816 		kprintf(")\n");
817 	} else
818 		kprintf("\n");
819 
820 	set_debug_variable("_frame", nextEbp);
821 }
822 
823 
824 static int
show_call(int argc,char ** argv)825 show_call(int argc, char **argv)
826 {
827 	static const char* usage
828 		= "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n"
829 		"Prints a function call with parameters of the current, respectively\n"
830 		"the specified thread.\n"
831 		"  <thread id>   -  The ID of the thread for which to print the call.\n"
832 		"  <call index>  -  The index of the call in the stack trace.\n"
833 		"  <arg count>   -  The number of call arguments to print (use 'c' to\n"
834 		"                   force the C++ demangler to use class methods,\n"
835 		"                   use 'd' to disable demangling).\n";
836 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
837 		kprintf(usage, argv[0]);
838 		return 0;
839 	}
840 
841 	Thread *thread = NULL;
842 	phys_addr_t oldPageDirectory = 0;
843 	addr_t ebp = x86_get_stack_frame();
844 	int32 argCount = 0;
845 
846 	if (argc >= 2 && argv[argc - 1][0] == '-') {
847 		if (argv[argc - 1][1] == 'c')
848 			argCount = -1;
849 		else if (argv[argc - 1][1] == 'd')
850 			argCount = -2;
851 		else
852 			argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
853 
854 		if (argCount < -2 || argCount > 16) {
855 			kprintf("Invalid argument count \"%d\".\n", argCount);
856 			return 0;
857 		}
858 		argc--;
859 	}
860 
861 	if (argc < 2 || argc > 3) {
862 		kprintf(usage, argv[0]);
863 		return 0;
864 	}
865 
866 	if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp,
867 			&oldPageDirectory))
868 		return 0;
869 
870 	DebuggedThreadSetter threadSetter(thread);
871 
872 	int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0);
873 
874 	if (thread != NULL)
875 		kprintf("thread %d, %s\n", thread->id, thread->name);
876 
877 	bool onKernelStack = true;
878 
879 	for (int32 index = 0; index <= callIndex; index++) {
880 		onKernelStack = onKernelStack
881 			&& is_kernel_stack_address(thread, ebp);
882 
883 		if (onKernelStack && is_iframe(thread, ebp)) {
884 			struct iframe *frame = (struct iframe *)ebp;
885 
886 			if (index == callIndex)
887 				print_call(thread, frame->ip, ebp, frame->bp, argCount);
888 
889  			ebp = frame->bp;
890 		} else {
891 			addr_t eip, nextEbp;
892 
893 			if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
894 				kprintf("%08lx -- read fault\n", ebp);
895 				break;
896 			}
897 
898 			if (eip == 0 || ebp == 0)
899 				break;
900 
901 			if (index == callIndex)
902 				print_call(thread, eip, ebp, nextEbp, argCount);
903 
904 			ebp = nextEbp;
905 		}
906 
907 		if (ebp == 0)
908 			break;
909 	}
910 
911 	if (oldPageDirectory != 0) {
912 		// switch back to the previous page directory to not cause any troubles
913 		x86_write_cr3(oldPageDirectory);
914 	}
915 
916 	return 0;
917 }
918 #endif
919 
920 
921 static int
dump_iframes(int argc,char ** argv)922 dump_iframes(int argc, char** argv)
923 {
924 	static const char* usage = "usage: %s [ <thread id> ]\n"
925 		"Prints the iframe stack for the current, respectively the specified\n"
926 		"thread.\n"
927 		"  <thread id>  -  The ID of the thread for which to print the iframe\n"
928 		"                  stack.\n";
929 	if (argc == 2 && strcmp(argv[1], "--help") == 0) {
930 		kprintf(usage, argv[0]);
931 		return 0;
932 	}
933 
934 	Thread* thread = NULL;
935 
936 	if (argc < 2) {
937 		thread = thread_get_current_thread();
938 	} else if (argc == 2) {
939 		thread_id id = strtoul(argv[1], NULL, 0);
940 		thread = Thread::GetDebug(id);
941 		if (thread == NULL) {
942 			kprintf("could not find thread %" B_PRId32 "\n", id);
943 			return 0;
944 		}
945 	} else if (argc > 2) {
946 		kprintf(usage, argv[0]);
947 		return 0;
948 	}
949 
950 	if (thread != NULL) {
951 		kprintf("iframes for thread %" B_PRId32 " \"%s\"\n", thread->id,
952 			thread->name);
953 	}
954 
955 	DebuggedThreadSetter threadSetter(thread);
956 
957 	iframe* frame = find_previous_iframe(thread, x86_get_stack_frame());
958 	while (frame != NULL) {
959 		print_iframe(frame);
960 		frame = get_previous_iframe(thread, frame);
961 	}
962 
963 	return 0;
964 }
965 
966 
967 static bool
is_calling(Thread * thread,addr_t ip,const char * pattern,addr_t start,addr_t end)968 is_calling(Thread* thread, addr_t ip, const char* pattern, addr_t start,
969 	addr_t end)
970 {
971 	if (pattern == NULL)
972 		return ip >= start && ip < end;
973 
974 	if (!IS_KERNEL_ADDRESS(ip))
975 		return false;
976 
977 	const char* symbol;
978 	if (lookup_symbol(thread, ip, NULL, &symbol, NULL, NULL) != B_OK)
979 		return false;
980 
981 	return strstr(symbol, pattern);
982 }
983 
984 
985 static int
cmd_in_context(int argc,char ** argv)986 cmd_in_context(int argc, char** argv)
987 {
988 	if (argc != 2) {
989 		print_debugger_command_usage(argv[0]);
990 		return 0;
991 	}
992 
993 	// get the thread ID
994 	const char* commandLine = argv[1];
995 	char threadIDString[16];
996 	if (parse_next_debug_command_argument(&commandLine, threadIDString,
997 			sizeof(threadIDString)) != B_OK) {
998 		kprintf("Failed to parse thread ID.\n");
999 		return 0;
1000 	}
1001 
1002 	if (commandLine == NULL) {
1003 		print_debugger_command_usage(argv[0]);
1004 		return 0;
1005 	}
1006 
1007 	uint64 threadID;
1008 	if (!evaluate_debug_expression(threadIDString, &threadID, false))
1009 		return 0;
1010 
1011 	// get the thread
1012 	Thread* thread = Thread::GetDebug(threadID);
1013 	if (thread == NULL) {
1014 		kprintf("Could not find thread with ID \"%s\".\n", threadIDString);
1015 		return 0;
1016 	}
1017 
1018 	// switch the page directory, if necessary
1019 	phys_addr_t oldPageDirectory = 0;
1020 	if (thread != thread_get_current_thread()) {
1021 		phys_addr_t newPageDirectory = x86_next_page_directory(
1022 			thread_get_current_thread(), thread);
1023 
1024 		if (newPageDirectory != 0) {
1025 			oldPageDirectory = x86_read_cr3();
1026 			x86_write_cr3(newPageDirectory);
1027 		}
1028 	}
1029 
1030 	// execute the command
1031 	{
1032 		DebuggedThreadSetter threadSetter(thread);
1033 		evaluate_debug_command(commandLine);
1034 	}
1035 
1036 	// reset the page directory
1037 	if (oldPageDirectory)
1038 		x86_write_cr3(oldPageDirectory);
1039 
1040 	return 0;
1041 }
1042 
1043 
1044 //	#pragma mark -
1045 
1046 
1047 void
arch_debug_save_registers(arch_debug_registers * registers)1048 arch_debug_save_registers(arch_debug_registers* registers)
1049 {
1050 	// get the caller's frame pointer
1051 	stack_frame* frame = (stack_frame*)x86_get_stack_frame();
1052 	registers->bp = (addr_t)frame->previous;
1053 }
1054 
1055 
1056 void
arch_debug_stack_trace(void)1057 arch_debug_stack_trace(void)
1058 {
1059 	stack_trace(0, NULL);
1060 }
1061 
1062 
1063 bool
arch_debug_contains_call(Thread * thread,const char * symbol,addr_t start,addr_t end)1064 arch_debug_contains_call(Thread* thread, const char* symbol, addr_t start,
1065 	addr_t end)
1066 {
1067 	DebuggedThreadSetter threadSetter(thread);
1068 
1069 	addr_t bp;
1070 	if (thread == thread_get_current_thread())
1071 		bp = x86_get_stack_frame();
1072 	else {
1073 		if (thread->state == B_THREAD_RUNNING) {
1074 			// The thread is currently running on another CPU.
1075 			if (thread->cpu == NULL)
1076 				return false;
1077 			arch_debug_registers* registers = debug_get_debug_registers(
1078 				thread->cpu->cpu_num);
1079 			if (registers == NULL)
1080 				return false;
1081 			bp = registers->bp;
1082 		} else {
1083 			// thread not running
1084 			bp = thread->arch_info.GetFramePointer();
1085 		}
1086 	}
1087 
1088 	for (;;) {
1089 		if (!is_kernel_stack_address(thread, bp))
1090 			break;
1091 
1092 		if (is_iframe(thread, bp)) {
1093 			iframe* frame = (iframe*)bp;
1094 
1095 			if (is_calling(thread, frame->ip, symbol, start, end))
1096 				return true;
1097 
1098  			bp = frame->bp;
1099 		} else {
1100 			addr_t ip, nextBp;
1101 
1102 			if (get_next_frame_no_debugger(bp, &nextBp, &ip, true,
1103 					thread) != B_OK
1104 				|| ip == 0 || bp == 0)
1105 				break;
1106 
1107 			if (is_calling(thread, ip, symbol, start, end))
1108 				return true;
1109 
1110 			bp = nextBp;
1111 		}
1112 
1113 		if (bp == 0)
1114 			break;
1115 	}
1116 
1117 	return false;
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
arch_debug_get_stack_trace(addr_t * returnAddresses,int32 maxCount,int32 skipIframes,int32 skipFrames,uint32 flags)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 	if ((flags & (STACK_TRACE_KERNEL | STACK_TRACE_USER)) == STACK_TRACE_USER) {
1147 		iframe* frame = x86_get_user_iframe();
1148 		if (frame == NULL)
1149 			return 0;
1150 
1151 		bp = (addr_t)frame;
1152 	}
1153 
1154 	while (bp != 0 && count < maxCount) {
1155 		onKernelStack = onKernelStack
1156 			&& is_kernel_stack_address(thread, bp);
1157 		if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
1158 			break;
1159 
1160 		addr_t ip;
1161 		addr_t nextBp;
1162 
1163 		if (onKernelStack && is_iframe(thread, bp)) {
1164 			iframe* frame = (iframe*)bp;
1165 			ip = frame->ip;
1166 			nextBp = frame->bp;
1167 
1168 			if (skipIframes > 0) {
1169 				if (--skipIframes == 0)
1170 					skipFrames = 0;
1171 			}
1172 		} else {
1173 			if (get_next_frame_no_debugger(bp, &nextBp, &ip,
1174 					onKernelStack, thread) != B_OK) {
1175 				break;
1176 			}
1177 		}
1178 
1179 		if (ip == 0)
1180 			break;
1181 
1182 		if (skipFrames > 0)
1183 			skipFrames--;
1184 		else
1185 			returnAddresses[count++] = ip;
1186 
1187 		bp = nextBp;
1188 	}
1189 
1190 	return count;
1191 }
1192 
1193 
1194 /*!	Returns the program counter of the currently debugged (respectively this)
1195 	thread where the innermost interrupts happened. \a _isSyscall, if specified,
1196 	is set to whether this interrupt frame was created by a syscall. Returns
1197 	\c NULL, if there's no such frame or a problem occurred retrieving it;
1198 	\a _isSyscall won't be set in this case.
1199 */
1200 void*
arch_debug_get_interrupt_pc(bool * _isSyscall)1201 arch_debug_get_interrupt_pc(bool* _isSyscall)
1202 {
1203 	iframe* frame = get_current_iframe(debug_get_debugged_thread());
1204 	if (frame == NULL)
1205 		return NULL;
1206 
1207 	if (_isSyscall != NULL)
1208 		*_isSyscall = frame->type == IFRAME_TYPE_SYSCALL;
1209 
1210 	return (void*)(addr_t)frame->ip;
1211 }
1212 
1213 
1214 /*!	Sets the current thread to \c NULL.
1215 	Invoked in the kernel debugger only.
1216 */
1217 void
arch_debug_unset_current_thread(void)1218 arch_debug_unset_current_thread(void)
1219 {
1220 	// Can't just write 0 to the GS base, that will cause the read from %gs:0
1221 	// to fault. Instead point it at a NULL pointer, %gs:0 will get this value.
1222 	static Thread* unsetThread = NULL;
1223 #ifdef __x86_64__
1224 	x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&unsetThread);
1225 #else
1226 	asm volatile("mov %0, %%gs:0" : : "r" (unsetThread) : "memory");
1227 #endif
1228 }
1229 
1230 
1231 bool
arch_is_debug_variable_defined(const char * variableName)1232 arch_is_debug_variable_defined(const char* variableName)
1233 {
1234 	bool settable;
1235 	return find_debug_variable(variableName, settable);
1236 }
1237 
1238 
1239 status_t
arch_set_debug_variable(const char * variableName,uint64 value)1240 arch_set_debug_variable(const char* variableName, uint64 value)
1241 {
1242 	bool settable;
1243 	size_t* variable = find_debug_variable(variableName, settable);
1244 	if (variable == NULL)
1245 		return B_ENTRY_NOT_FOUND;
1246 
1247 	if (!settable)
1248 		return B_NOT_ALLOWED;
1249 
1250 	*variable = (size_t)value;
1251 	return B_OK;
1252 }
1253 
1254 
1255 status_t
arch_get_debug_variable(const char * variableName,uint64 * value)1256 arch_get_debug_variable(const char* variableName, uint64* value)
1257 {
1258 	bool settable;
1259 	size_t* variable = find_debug_variable(variableName, settable);
1260 	if (variable == NULL)
1261 		return B_ENTRY_NOT_FOUND;
1262 
1263 	*value = *variable;
1264 	return B_OK;
1265 }
1266 
1267 
1268 struct gdb_register {
1269 	int32 type;
1270 	uint64 value;
1271 };
1272 
1273 
1274 /*!	Writes the contents of the CPU registers at some fixed outer stack frame or
1275 	iframe into the given buffer in the format expected by gdb.
1276 
1277 	This function is called in response to gdb's 'g' command.
1278 
1279 	\param buffer The buffer to write the registers to.
1280 	\param bufferSize The size of \a buffer in bytes.
1281 	\return When successful, the number of bytes written to \a buffer, or a
1282 		negative error code on error.
1283 */
1284 ssize_t
arch_debug_gdb_get_registers(char * buffer,size_t bufferSize)1285 arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
1286 {
1287 	iframe* frame = get_current_iframe(debug_get_debugged_thread());
1288 	if (frame == NULL)
1289 		return B_NOT_SUPPORTED;
1290 
1291 #ifdef __x86_64__
1292 	// For x86_64 the register order is:
1293 	//
1294 	//    rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
1295 	//    r8, r9, r10, r11, r12, r13, r14, r15,
1296 	//    rip, rflags, cs, ss, ds, es, fs, gs
1297 	//
1298 	// Annoyingly, GDB wants all the registers as 64-bit values, but then
1299 	// RFLAGS and the segment registers as 32-bit values, hence the need for
1300 	// the type information.
1301 	static const int32 kRegisterCount = 24;
1302 	gdb_register registers[kRegisterCount] = {
1303 		{ B_UINT64_TYPE, frame->ax },  { B_UINT64_TYPE, frame->bx },
1304 		{ B_UINT64_TYPE, frame->cx },  { B_UINT64_TYPE, frame->dx },
1305 		{ B_UINT64_TYPE, frame->si },  { B_UINT64_TYPE, frame->di },
1306 		{ B_UINT64_TYPE, frame->bp },  { B_UINT64_TYPE, frame->sp },
1307 		{ B_UINT64_TYPE, frame->r8 },  { B_UINT64_TYPE, frame->r9 },
1308 		{ B_UINT64_TYPE, frame->r10 }, { B_UINT64_TYPE, frame->r11 },
1309 		{ B_UINT64_TYPE, frame->r12 }, { B_UINT64_TYPE, frame->r13 },
1310 		{ B_UINT64_TYPE, frame->r14 }, { B_UINT64_TYPE, frame->r15 },
1311 		{ B_UINT64_TYPE, frame->ip },  { B_UINT32_TYPE, frame->flags },
1312 		{ B_UINT32_TYPE, frame->cs },  { B_UINT32_TYPE, frame->ss },
1313 		{ B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1314 		{ B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1315 	};
1316 #else
1317 	// For x86 the register order is:
1318 	//
1319 	//    eax, ecx, edx, ebx,
1320 	//    esp, ebp, esi, edi,
1321 	//    eip, eflags,
1322 	//    cs, ss, ds, es, fs, gs
1323 	//
1324 	// Note that even though the segment descriptors are actually 16 bits wide,
1325 	// gdb requires them as 32 bit integers.
1326 	static const int32 kRegisterCount = 16;
1327 	gdb_register registers[kRegisterCount] = {
1328 		{ B_UINT32_TYPE, frame->ax }, { B_UINT32_TYPE, frame->cx },
1329 		{ B_UINT32_TYPE, frame->dx }, { B_UINT32_TYPE, frame->bx },
1330 		{ B_UINT32_TYPE, frame->sp }, { B_UINT32_TYPE, frame->bp },
1331 		{ B_UINT32_TYPE, frame->si }, { B_UINT32_TYPE, frame->di },
1332 		{ B_UINT32_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
1333 		{ B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ds },
1334 			// assume ss == ds
1335 		{ B_UINT32_TYPE, frame->ds }, { B_UINT32_TYPE, frame->es },
1336 		{ B_UINT32_TYPE, frame->fs }, { B_UINT32_TYPE, frame->gs },
1337 	};
1338 #endif
1339 
1340 	const char* const bufferStart = buffer;
1341 
1342 	for (int32 i = 0; i < kRegisterCount; i++) {
1343 		// For some reason gdb wants the register dump in *big endian* format.
1344 		int result = 0;
1345 		switch (registers[i].type) {
1346 			case B_UINT64_TYPE:
1347 				result = snprintf(buffer, bufferSize, "%016" B_PRIx64,
1348 					(uint64)B_HOST_TO_BENDIAN_INT64(registers[i].value));
1349 				break;
1350 			case B_UINT32_TYPE:
1351 				result = snprintf(buffer, bufferSize, "%08" B_PRIx32,
1352 					(uint32)B_HOST_TO_BENDIAN_INT32((uint32)registers[i].value));
1353 				break;
1354 		}
1355 		if (result >= (int)bufferSize)
1356 			return B_BUFFER_OVERFLOW;
1357 
1358 		buffer += result;
1359 		bufferSize -= result;
1360 	}
1361 
1362 	return buffer - bufferStart;
1363 }
1364 
1365 
1366 status_t
arch_debug_init(kernel_args * args)1367 arch_debug_init(kernel_args* args)
1368 {
1369 	// at this stage, the debugger command system is alive
1370 
1371 	add_debugger_command("where", &stack_trace, "Same as \"sc\"");
1372 	add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
1373 	add_debugger_command("sc", &stack_trace,
1374 		"Stack crawl for current thread (or any other)");
1375 	add_debugger_command("iframe", &dump_iframes,
1376 		"Dump iframes for the specified thread");
1377 #ifndef __x86_64__
1378 	add_debugger_command("call", &show_call, "Show call with arguments");
1379 #endif
1380 	add_debugger_command_etc("in_context", &cmd_in_context,
1381 		"Executes a command in the context of a given thread",
1382 		"<thread ID> <command> ...\n"
1383 		"Executes a command in the context of a given thread.\n",
1384 		B_KDEBUG_DONT_PARSE_ARGUMENTS);
1385 
1386 	return B_NO_ERROR;
1387 }
1388 
1389