btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / arch / x86 / arch_debug.cpp
blob6bb1a4ed53dc9f14bd37094d62c727ffbdc4fb32
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.
7 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
12 #include <arch/debug.h>
14 #include <stdio.h>
15 #include <stdlib.h>
17 #include <ByteOrder.h>
18 #include <TypeConstants.h>
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>
33 struct stack_frame {
34 stack_frame* previous;
35 addr_t return_address;
38 #define NUM_PREVIOUS_LOCATIONS 32
41 static bool is_kernel_stack_address(Thread* thread, addr_t address);
44 static bool
45 already_visited(addr_t* visited, int32* _last, int32* _num, addr_t bp)
47 int32 last = *_last;
48 int32 num = *_num;
49 int32 i;
51 for (i = 0; i < num; i++) {
52 if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == bp)
53 return true;
56 *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
57 visited[last] = bp;
59 if (num < NUM_PREVIOUS_LOCATIONS)
60 *_num = num + 1;
62 return false;
66 /*! Safe to be called only from outside the debugger.
68 static status_t
69 get_next_frame_no_debugger(addr_t bp, addr_t* _next, addr_t* _ip,
70 bool onKernelStack, Thread* thread)
72 // TODO: Do this more efficiently in assembly.
73 stack_frame frame;
74 if (onKernelStack
75 && is_kernel_stack_address(thread, bp + sizeof(frame) - 1))
76 memcpy(&frame, (void*)bp, sizeof(frame));
77 else if (user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK)
78 return B_BAD_ADDRESS;
80 *_ip = frame.return_address;
81 *_next = (addr_t)frame.previous;
83 return B_OK;
87 /*! Safe to be called only from inside the debugger.
89 static status_t
90 get_next_frame_debugger(addr_t bp, addr_t* _next, addr_t* _ip)
92 stack_frame frame;
93 if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)bp, sizeof(frame)) != B_OK)
94 return B_BAD_ADDRESS;
96 *_ip = frame.return_address;
97 *_next = (addr_t)frame.previous;
99 return B_OK;
103 static status_t
104 lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
105 const char** _symbolName, const char** _imageName, bool* _exactMatch)
107 status_t status = B_ENTRY_NOT_FOUND;
109 if (IS_KERNEL_ADDRESS(address)) {
110 // a kernel symbol
111 status = elf_debug_lookup_symbol_address(address, _baseAddress,
112 _symbolName, _imageName, _exactMatch);
113 } else if (thread != NULL && thread->team != NULL) {
114 // try a lookup using the userland runtime loader structures
115 status = elf_debug_lookup_user_symbol_address(thread->team, address,
116 _baseAddress, _symbolName, _imageName, _exactMatch);
118 if (status != B_OK) {
119 // try to locate the image in the images loaded into user space
120 status = image_debug_lookup_user_symbol_address(thread->team,
121 address, _baseAddress, _symbolName, _imageName, _exactMatch);
125 return status;
129 #ifndef __x86_64__
132 static void
133 set_debug_argument_variable(int32 index, uint64 value)
135 char name[8];
136 snprintf(name, sizeof(name), "_arg%ld", index);
137 set_debug_variable(name, value);
141 template<typename Type>
142 static Type
143 read_function_argument_value(void* argument, bool& _valueKnown)
145 Type value;
146 if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) {
147 _valueKnown = true;
148 return value;
151 _valueKnown = false;
152 return 0;
156 static status_t
157 print_demangled_call(const char* image, const char* symbol, addr_t args,
158 bool noObjectMethod, bool addDebugVariables)
160 static const size_t kBufferSize = 256;
161 char* buffer = (char*)debug_malloc(kBufferSize);
162 if (buffer == NULL)
163 return B_NO_MEMORY;
165 bool isObjectMethod;
166 const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
167 &isObjectMethod);
168 if (name == NULL) {
169 debug_free(buffer);
170 return B_ERROR;
173 uint32* arg = (uint32*)args;
175 if (noObjectMethod)
176 isObjectMethod = false;
177 if (isObjectMethod) {
178 const char* lastName = strrchr(name, ':') - 1;
179 int namespaceLength = lastName - name;
181 uint32 argValue = 0;
182 if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) {
183 kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image,
184 namespaceLength, name, argValue, lastName);
185 } else
186 kprintf("<%s> %.*s<???>%s", image, namespaceLength, name, lastName);
188 if (addDebugVariables)
189 set_debug_variable("_this", argValue);
190 arg++;
191 } else
192 kprintf("<%s> %s", image, name);
194 kprintf("(");
196 size_t length;
197 int32 type, i = 0;
198 uint32 cookie = 0;
199 while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
200 kBufferSize, &type, &length) == B_OK) {
201 if (i++ > 0)
202 kprintf(", ");
204 // retrieve value and type identifier
206 uint64 value;
207 bool valueKnown = false;
209 switch (type) {
210 case B_INT64_TYPE:
211 value = read_function_argument_value<int64>(arg, valueKnown);
212 if (valueKnown)
213 kprintf("int64: \33[34m%Ld\33[0m", value);
214 break;
215 case B_INT32_TYPE:
216 value = read_function_argument_value<int32>(arg, valueKnown);
217 if (valueKnown)
218 kprintf("int32: \33[34m%ld\33[0m", (int32)value);
219 break;
220 case B_INT16_TYPE:
221 value = read_function_argument_value<int16>(arg, valueKnown);
222 if (valueKnown)
223 kprintf("int16: \33[34m%d\33[0m", (int16)value);
224 break;
225 case B_INT8_TYPE:
226 value = read_function_argument_value<int8>(arg, valueKnown);
227 if (valueKnown)
228 kprintf("int8: \33[34m%d\33[0m", (int8)value);
229 break;
230 case B_UINT64_TYPE:
231 value = read_function_argument_value<uint64>(arg, valueKnown);
232 if (valueKnown) {
233 kprintf("uint64: \33[34m%#Lx\33[0m", value);
234 if (value < 0x100000)
235 kprintf(" (\33[34m%Lu\33[0m)", value);
237 break;
238 case B_UINT32_TYPE:
239 value = read_function_argument_value<uint32>(arg, valueKnown);
240 if (valueKnown) {
241 kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value);
242 if (value < 0x100000)
243 kprintf(" (\33[34m%lu\33[0m)", (uint32)value);
245 break;
246 case B_UINT16_TYPE:
247 value = read_function_argument_value<uint16>(arg, valueKnown);
248 if (valueKnown) {
249 kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
250 (uint16)value, (uint16)value);
252 break;
253 case B_UINT8_TYPE:
254 value = read_function_argument_value<uint8>(arg, valueKnown);
255 if (valueKnown) {
256 kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)",
257 (uint8)value, (uint8)value);
259 break;
260 case B_BOOL_TYPE:
261 value = read_function_argument_value<uint8>(arg, valueKnown);
262 if (valueKnown)
263 kprintf("\33[34m%s\33[0m", value ? "true" : "false");
264 break;
265 default:
266 if (buffer[0])
267 kprintf("%s: ", buffer);
269 if (length == 4) {
270 value = read_function_argument_value<uint32>(arg,
271 valueKnown);
272 if (valueKnown) {
273 if (value == 0
274 && (type == B_POINTER_TYPE || type == B_REF_TYPE))
275 kprintf("NULL");
276 else
277 kprintf("\33[34m%#lx\33[0m", (uint32)value);
279 break;
283 if (length == 8) {
284 value = read_function_argument_value<uint64>(arg,
285 valueKnown);
286 } else
287 value = (uint64)arg;
289 if (valueKnown)
290 kprintf("\33[34m%#Lx\33[0m", value);
291 break;
294 if (!valueKnown)
295 kprintf("???");
297 if (valueKnown && type == B_STRING_TYPE) {
298 if (value == 0)
299 kprintf(" \33[31m\"<NULL>\"\33[0m");
300 else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)(addr_t)value,
301 kBufferSize) < B_OK) {
302 kprintf(" \33[31m\"<???>\"\33[0m");
303 } else
304 kprintf(" \33[36m\"%s\"\33[0m", buffer);
307 if (addDebugVariables)
308 set_debug_argument_variable(i, value);
309 arg = (uint32*)((uint8*)arg + length);
312 debug_free(buffer);
314 kprintf(")");
315 return B_OK;
319 #else // __x86_64__
322 static status_t
323 print_demangled_call(const char* image, const char* symbol, addr_t args,
324 bool noObjectMethod, bool addDebugVariables)
326 // Since x86_64 uses registers rather than the stack for the first 6
327 // arguments we cannot use the same method as x86 to read the function
328 // arguments. Maybe we need DWARF support in the kernel debugger. For now
329 // just print out the function signature without the argument values.
331 static const size_t kBufferSize = 256;
332 char* buffer = (char*)debug_malloc(kBufferSize);
333 if (buffer == NULL)
334 return B_NO_MEMORY;
336 bool isObjectMethod;
337 const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize,
338 &isObjectMethod);
339 if (name == NULL) {
340 debug_free(buffer);
341 return B_ERROR;
344 kprintf("<%s> %s(", image, name);
346 size_t length;
347 int32 type, i = 0;
348 uint32 cookie = 0;
349 while (debug_get_next_demangled_argument(&cookie, symbol, buffer,
350 kBufferSize, &type, &length) == B_OK) {
351 if (i++ > 0)
352 kprintf(", ");
354 if (buffer[0])
355 kprintf("%s", buffer);
356 else
357 kprintf("???");
360 debug_free(buffer);
362 kprintf(")");
363 return B_OK;
367 #endif // __x86_64__
370 static void
371 print_stack_frame(Thread* thread, addr_t ip, addr_t bp, addr_t nextBp,
372 int32 callIndex, bool demangle)
374 const char* symbol;
375 const char* image;
376 addr_t baseAddress;
377 bool exactMatch;
378 status_t status;
379 addr_t diff;
381 diff = nextBp - bp;
383 // MSB set = kernel space/user space switch
384 if (diff & ~((addr_t)-1 >> 1))
385 diff = 0;
387 status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image,
388 &exactMatch);
390 kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex,
391 B_PRINTF_POINTER_WIDTH, bp, diff, B_PRINTF_POINTER_WIDTH, ip);
393 if (status == B_OK) {
394 if (exactMatch && demangle) {
395 status = print_demangled_call(image, symbol,
396 nextBp + sizeof(stack_frame), false, false);
399 if (!exactMatch || !demangle || status != B_OK) {
400 if (symbol != NULL) {
401 kprintf("<%s> %s%s", image, symbol,
402 exactMatch ? "" : " (nearest)");
403 } else
404 kprintf("<%s@%p> <unknown>", image, (void*)baseAddress);
407 kprintf(" + %#04lx\n", ip - baseAddress);
408 } else {
409 VMArea *area = NULL;
410 if (thread != NULL && thread->team != NULL
411 && thread->team->address_space != NULL) {
412 area = thread->team->address_space->LookupArea(ip);
414 if (area != NULL) {
415 kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name,
416 (void*)area->Base(), ip - area->Base());
417 } else
418 kprintf("\n");
423 static void
424 print_iframe(iframe* frame)
426 bool isUser = IFRAME_IS_USER(frame);
428 #ifdef __x86_64__
429 kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
430 frame + 1);
432 kprintf(" rax %#-18lx rbx %#-18lx rcx %#lx\n", frame->ax,
433 frame->bx, frame->cx);
434 kprintf(" rdx %#-18lx rsi %#-18lx rdi %#lx\n", frame->dx,
435 frame->si, frame->di);
436 kprintf(" rbp %#-18lx r8 %#-18lx r9 %#lx\n", frame->bp,
437 frame->r8, frame->r9);
438 kprintf(" r10 %#-18lx r11 %#-18lx r12 %#lx\n", frame->r10,
439 frame->r11, frame->r12);
440 kprintf(" r13 %#-18lx r14 %#-18lx r15 %#lx\n", frame->r13,
441 frame->r14, frame->r15);
442 kprintf(" rip %#-18lx rsp %#-18lx rflags %#lx\n", frame->ip,
443 frame->sp, frame->flags);
444 #else
445 kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
446 isUser ? (void*)(frame + 1) : (void*)&frame->user_sp);
448 kprintf(" eax %#-10lx ebx %#-10lx ecx %#-10lx edx %#lx\n",
449 frame->ax, frame->bx, frame->cx, frame->dx);
450 kprintf(" esi %#-10lx edi %#-10lx ebp %#-10lx esp %#lx\n",
451 frame->si, frame->di, frame->bp, frame->sp);
452 kprintf(" eip %#-10lx eflags %#-10lx", frame->ip, frame->flags);
453 if (isUser) {
454 // from user space
455 kprintf("user esp %#lx", frame->user_sp);
457 kprintf("\n");
458 #endif
460 kprintf(" vector: %#lx, error code: %#lx\n", frame->vector,
461 frame->error_code);
465 static bool
466 setup_for_thread(char* arg, Thread** _thread, addr_t* _bp,
467 phys_addr_t* _oldPageDirectory)
469 Thread* thread = NULL;
471 if (arg != NULL) {
472 thread_id id = strtoul(arg, NULL, 0);
473 thread = Thread::GetDebug(id);
474 if (thread == NULL) {
475 kprintf("could not find thread %" B_PRId32 "\n", id);
476 return false;
479 if (id != thread_get_current_thread_id()) {
480 // switch to the page directory of the new thread to be
481 // able to follow the stack trace into userland
482 phys_addr_t newPageDirectory = x86_next_page_directory(
483 thread_get_current_thread(), thread);
485 if (newPageDirectory != 0) {
486 *_oldPageDirectory = x86_read_cr3();
487 x86_write_cr3(newPageDirectory);
490 if (thread->state == B_THREAD_RUNNING) {
491 // The thread is currently running on another CPU.
492 if (thread->cpu == NULL)
493 return false;
494 arch_debug_registers* registers = debug_get_debug_registers(
495 thread->cpu->cpu_num);
496 if (registers == NULL)
497 return false;
498 *_bp = registers->bp;
499 } else {
500 // Read frame pointer from the thread's stack.
501 *_bp = thread->arch_info.GetFramePointer();
503 } else
504 thread = NULL;
507 if (thread == NULL) {
508 // if we don't have a thread yet, we want the current one
509 // (ebp has been set by the caller for this case already)
510 thread = thread_get_current_thread();
513 *_thread = thread;
514 return true;
518 static bool
519 is_double_fault_stack_address(int32 cpu, addr_t address)
521 size_t size;
522 addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size);
523 return address >= bottom && address < bottom + size;
527 static bool
528 is_kernel_stack_address(Thread* thread, addr_t address)
530 // We don't have a thread pointer in the early boot process, but then we are
531 // on the kernel stack for sure.
532 if (thread == NULL)
533 return IS_KERNEL_ADDRESS(address);
535 // Also in the early boot process we might have a thread structure, but it
536 // might not have its kernel stack attributes set yet.
537 if (thread->kernel_stack_top == 0)
538 return IS_KERNEL_ADDRESS(address);
540 return (address >= thread->kernel_stack_base
541 && address < thread->kernel_stack_top)
542 || (thread->cpu != NULL
543 && is_double_fault_stack_address(thread->cpu->cpu_num, address));
547 static bool
548 is_iframe(Thread* thread, addr_t frame)
550 if (!is_kernel_stack_address(thread, frame))
551 return false;
553 addr_t previousFrame = *(addr_t*)frame;
554 return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0
555 && previousFrame != 0);
559 static iframe*
560 find_previous_iframe(Thread* thread, addr_t frame)
562 // iterate backwards through the stack frames, until we hit an iframe
563 while (is_kernel_stack_address(thread, frame)) {
564 if (is_iframe(thread, frame))
565 return (iframe*)frame;
567 frame = *(addr_t*)frame;
570 return NULL;
574 static iframe*
575 get_previous_iframe(Thread* thread, iframe* frame)
577 if (frame == NULL)
578 return NULL;
580 return find_previous_iframe(thread, frame->bp);
584 static iframe*
585 get_current_iframe(Thread* thread)
587 if (thread == thread_get_current_thread())
588 return x86_get_current_iframe();
590 // NOTE: This doesn't work, if the thread is running (on another CPU).
591 return find_previous_iframe(thread, thread->arch_info.GetFramePointer());
595 #define CHECK_DEBUG_VARIABLE(_name, _member, _settable) \
596 if (strcmp(variableName, _name) == 0) { \
597 settable = _settable; \
598 return &_member; \
602 static size_t*
603 find_debug_variable(const char* variableName, bool& settable)
605 iframe* frame = get_current_iframe(debug_get_debugged_thread());
606 if (frame == NULL)
607 return NULL;
609 #ifdef __x86_64__
610 CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
611 CHECK_DEBUG_VARIABLE("ss", frame->ss, false);
612 CHECK_DEBUG_VARIABLE("r15", frame->r15, true);
613 CHECK_DEBUG_VARIABLE("r14", frame->r14, true);
614 CHECK_DEBUG_VARIABLE("r13", frame->r13, true);
615 CHECK_DEBUG_VARIABLE("r12", frame->r12, true);
616 CHECK_DEBUG_VARIABLE("r11", frame->r11, true);
617 CHECK_DEBUG_VARIABLE("r10", frame->r10, true);
618 CHECK_DEBUG_VARIABLE("r9", frame->r9, true);
619 CHECK_DEBUG_VARIABLE("r8", frame->r8, true);
620 CHECK_DEBUG_VARIABLE("rbp", frame->bp, true);
621 CHECK_DEBUG_VARIABLE("rsi", frame->si, true);
622 CHECK_DEBUG_VARIABLE("rdi", frame->di, true);
623 CHECK_DEBUG_VARIABLE("rdx", frame->dx, true);
624 CHECK_DEBUG_VARIABLE("rcx", frame->cx, true);
625 CHECK_DEBUG_VARIABLE("rbx", frame->bx, true);
626 CHECK_DEBUG_VARIABLE("rax", frame->ax, true);
627 CHECK_DEBUG_VARIABLE("rip", frame->ip, true);
628 CHECK_DEBUG_VARIABLE("rflags", frame->flags, true);
629 CHECK_DEBUG_VARIABLE("rsp", frame->sp, true);
630 #else
631 CHECK_DEBUG_VARIABLE("gs", frame->gs, false);
632 CHECK_DEBUG_VARIABLE("fs", frame->fs, false);
633 CHECK_DEBUG_VARIABLE("es", frame->es, false);
634 CHECK_DEBUG_VARIABLE("ds", frame->ds, false);
635 CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
636 CHECK_DEBUG_VARIABLE("edi", frame->di, true);
637 CHECK_DEBUG_VARIABLE("esi", frame->si, true);
638 CHECK_DEBUG_VARIABLE("ebp", frame->bp, true);
639 CHECK_DEBUG_VARIABLE("esp", frame->sp, true);
640 CHECK_DEBUG_VARIABLE("ebx", frame->bx, true);
641 CHECK_DEBUG_VARIABLE("edx", frame->dx, true);
642 CHECK_DEBUG_VARIABLE("ecx", frame->cx, true);
643 CHECK_DEBUG_VARIABLE("eax", frame->ax, true);
644 CHECK_DEBUG_VARIABLE("orig_eax", frame->orig_eax, true);
645 CHECK_DEBUG_VARIABLE("orig_edx", frame->orig_edx, true);
646 CHECK_DEBUG_VARIABLE("eip", frame->ip, true);
647 CHECK_DEBUG_VARIABLE("eflags", frame->flags, true);
649 if (IFRAME_IS_USER(frame)) {
650 CHECK_DEBUG_VARIABLE("user_esp", frame->user_sp, true);
651 CHECK_DEBUG_VARIABLE("user_ss", frame->user_ss, false);
653 #endif
655 return NULL;
659 static int
660 stack_trace(int argc, char** argv)
662 static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
663 "Prints a stack trace for the current, respectively the specified\n"
664 "thread.\n"
665 " -d - Disables the demangling of the symbols.\n"
666 " <thread id> - The ID of the thread for which to print the stack\n"
667 " trace.\n";
668 bool demangle = true;
669 int32 threadIndex = 1;
670 if (argc > 1 && !strcmp(argv[1], "-d")) {
671 demangle = false;
672 threadIndex++;
675 if (argc > threadIndex + 1
676 || (argc == 2 && strcmp(argv[1], "--help") == 0)) {
677 kprintf(usage, argv[0]);
678 return 0;
681 addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
682 Thread* thread = NULL;
683 phys_addr_t oldPageDirectory = 0;
684 addr_t bp = x86_get_stack_frame();
685 int32 num = 0, last = 0;
687 if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
688 &thread, &bp, &oldPageDirectory))
689 return 0;
691 DebuggedThreadSetter threadSetter(thread);
693 if (thread != NULL) {
694 kprintf("stack trace for thread %" B_PRId32 " \"%s\"\n", thread->id,
695 thread->name);
697 kprintf(" kernel stack: %p to %p\n",
698 (void*)thread->kernel_stack_base,
699 (void*)(thread->kernel_stack_top));
700 if (thread->user_stack_base != 0) {
701 kprintf(" user stack: %p to %p\n",
702 (void*)thread->user_stack_base,
703 (void*)(thread->user_stack_base + thread->user_stack_size));
707 kprintf("%-*s %-*s <image>:function + offset\n",
708 B_PRINTF_POINTER_WIDTH, "frame", B_PRINTF_POINTER_WIDTH, "caller");
710 bool onKernelStack = true;
712 for (int32 callIndex = 0;; callIndex++) {
713 onKernelStack = onKernelStack
714 && is_kernel_stack_address(thread, bp);
716 if (onKernelStack && is_iframe(thread, bp)) {
717 iframe* frame = (iframe*)bp;
719 print_iframe(frame);
720 print_stack_frame(thread, frame->ip, bp, frame->bp, callIndex,
721 demangle);
723 bp = frame->bp;
724 } else {
725 addr_t ip, nextBp;
727 if (get_next_frame_debugger(bp, &nextBp, &ip) != B_OK) {
728 kprintf("%0*lx -- read fault\n", B_PRINTF_POINTER_WIDTH, bp);
729 break;
732 if (ip == 0 || bp == 0)
733 break;
735 print_stack_frame(thread, ip, bp, nextBp, callIndex, demangle);
736 bp = nextBp;
739 if (already_visited(previousLocations, &last, &num, bp)) {
740 kprintf("circular stack frame: %p!\n", (void*)bp);
741 break;
743 if (bp == 0)
744 break;
747 if (oldPageDirectory != 0) {
748 // switch back to the previous page directory to no cause any troubles
749 x86_write_cr3(oldPageDirectory);
752 return 0;
756 #ifndef __x86_64__
757 static void
758 print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
759 int32 argCount)
761 const char *symbol, *image;
762 addr_t baseAddress;
763 bool exactMatch;
764 status_t status;
765 bool demangled = false;
766 int32 *arg = (int32 *)(nextEbp + 8);
768 status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image,
769 &exactMatch);
771 kprintf("%08lx %08lx ", ebp, eip);
773 if (status == B_OK) {
774 if (symbol != NULL) {
775 if (exactMatch && (argCount == 0 || argCount == -1)) {
776 status = print_demangled_call(image, symbol, (addr_t)arg,
777 argCount == -1, true);
778 if (status == B_OK)
779 demangled = true;
781 if (!demangled) {
782 kprintf("<%s>:%s%s", image, symbol,
783 exactMatch ? "" : " (nearest)");
785 } else {
786 kprintf("<%s@%p>:unknown + 0x%04lx", image,
787 (void *)baseAddress, eip - baseAddress);
789 } else {
790 VMArea *area = NULL;
791 if (thread->team->address_space != NULL)
792 area = thread->team->address_space->LookupArea(eip);
793 if (area != NULL) {
794 kprintf("%ld:%s@%p + %#lx", area->id, area->name,
795 (void *)area->Base(), eip - area->Base());
799 if (!demangled) {
800 kprintf("(");
802 for (int32 i = 0; i < argCount; i++) {
803 if (i > 0)
804 kprintf(", ");
805 kprintf("%#lx", *arg);
806 if (*arg > -0x10000 && *arg < 0x10000)
807 kprintf(" (%ld)", *arg);
809 set_debug_argument_variable(i + 1, *(uint32 *)arg);
810 arg++;
813 kprintf(")\n");
814 } else
815 kprintf("\n");
817 set_debug_variable("_frame", nextEbp);
821 static int
822 show_call(int argc, char **argv)
824 static const char* usage
825 = "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n"
826 "Prints a function call with parameters of the current, respectively\n"
827 "the specified thread.\n"
828 " <thread id> - The ID of the thread for which to print the call.\n"
829 " <call index> - The index of the call in the stack trace.\n"
830 " <arg count> - The number of call arguments to print (use 'c' to\n"
831 " force the C++ demangler to use class methods,\n"
832 " use 'd' to disable demangling).\n";
833 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
834 kprintf(usage, argv[0]);
835 return 0;
838 Thread *thread = NULL;
839 phys_addr_t oldPageDirectory = 0;
840 addr_t ebp = x86_get_stack_frame();
841 int32 argCount = 0;
843 if (argc >= 2 && argv[argc - 1][0] == '-') {
844 if (argv[argc - 1][1] == 'c')
845 argCount = -1;
846 else if (argv[argc - 1][1] == 'd')
847 argCount = -2;
848 else
849 argCount = strtoul(argv[argc - 1] + 1, NULL, 0);
851 if (argCount < -2 || argCount > 16) {
852 kprintf("Invalid argument count \"%ld\".\n", argCount);
853 return 0;
855 argc--;
858 if (argc < 2 || argc > 3) {
859 kprintf(usage, argv[0]);
860 return 0;
863 if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp,
864 &oldPageDirectory))
865 return 0;
867 DebuggedThreadSetter threadSetter(thread);
869 int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0);
871 if (thread != NULL)
872 kprintf("thread %ld, %s\n", thread->id, thread->name);
874 bool onKernelStack = true;
876 for (int32 index = 0; index <= callIndex; index++) {
877 onKernelStack = onKernelStack
878 && is_kernel_stack_address(thread, ebp);
880 if (onKernelStack && is_iframe(thread, ebp)) {
881 struct iframe *frame = (struct iframe *)ebp;
883 if (index == callIndex)
884 print_call(thread, frame->ip, ebp, frame->bp, argCount);
886 ebp = frame->bp;
887 } else {
888 addr_t eip, nextEbp;
890 if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) {
891 kprintf("%08lx -- read fault\n", ebp);
892 break;
895 if (eip == 0 || ebp == 0)
896 break;
898 if (index == callIndex)
899 print_call(thread, eip, ebp, nextEbp, argCount);
901 ebp = nextEbp;
904 if (ebp == 0)
905 break;
908 if (oldPageDirectory != 0) {
909 // switch back to the previous page directory to not cause any troubles
910 x86_write_cr3(oldPageDirectory);
913 return 0;
915 #endif
918 static int
919 dump_iframes(int argc, char** argv)
921 static const char* usage = "usage: %s [ <thread id> ]\n"
922 "Prints the iframe stack for the current, respectively the specified\n"
923 "thread.\n"
924 " <thread id> - The ID of the thread for which to print the iframe\n"
925 " stack.\n";
926 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
927 kprintf(usage, argv[0]);
928 return 0;
931 Thread* thread = NULL;
933 if (argc < 2) {
934 thread = thread_get_current_thread();
935 } else if (argc == 2) {
936 thread_id id = strtoul(argv[1], NULL, 0);
937 thread = Thread::GetDebug(id);
938 if (thread == NULL) {
939 kprintf("could not find thread %" B_PRId32 "\n", id);
940 return 0;
942 } else if (argc > 2) {
943 kprintf(usage, argv[0]);
944 return 0;
947 if (thread != NULL) {
948 kprintf("iframes for thread %" B_PRId32 " \"%s\"\n", thread->id,
949 thread->name);
952 DebuggedThreadSetter threadSetter(thread);
954 iframe* frame = find_previous_iframe(thread, x86_get_stack_frame());
955 while (frame != NULL) {
956 print_iframe(frame);
957 frame = get_previous_iframe(thread, frame);
960 return 0;
964 static bool
965 is_calling(Thread* thread, addr_t ip, const char* pattern, addr_t start,
966 addr_t end)
968 if (pattern == NULL)
969 return ip >= start && ip < end;
971 if (!IS_KERNEL_ADDRESS(ip))
972 return false;
974 const char* symbol;
975 if (lookup_symbol(thread, ip, NULL, &symbol, NULL, NULL) != B_OK)
976 return false;
978 return strstr(symbol, pattern);
982 static int
983 cmd_in_context(int argc, char** argv)
985 if (argc != 2) {
986 print_debugger_command_usage(argv[0]);
987 return 0;
990 // get the thread ID
991 const char* commandLine = argv[1];
992 char threadIDString[16];
993 if (parse_next_debug_command_argument(&commandLine, threadIDString,
994 sizeof(threadIDString)) != B_OK) {
995 kprintf("Failed to parse thread ID.\n");
996 return 0;
999 if (commandLine == NULL) {
1000 print_debugger_command_usage(argv[0]);
1001 return 0;
1004 uint64 threadID;
1005 if (!evaluate_debug_expression(threadIDString, &threadID, false))
1006 return 0;
1008 // get the thread
1009 Thread* thread = Thread::GetDebug(threadID);
1010 if (thread == NULL) {
1011 kprintf("Could not find thread with ID \"%s\".\n", threadIDString);
1012 return 0;
1015 // switch the page directory, if necessary
1016 phys_addr_t oldPageDirectory = 0;
1017 if (thread != thread_get_current_thread()) {
1018 phys_addr_t newPageDirectory = x86_next_page_directory(
1019 thread_get_current_thread(), thread);
1021 if (newPageDirectory != 0) {
1022 oldPageDirectory = x86_read_cr3();
1023 x86_write_cr3(newPageDirectory);
1027 // execute the command
1029 DebuggedThreadSetter threadSetter(thread);
1030 evaluate_debug_command(commandLine);
1033 // reset the page directory
1034 if (oldPageDirectory)
1035 x86_write_cr3(oldPageDirectory);
1037 return 0;
1041 // #pragma mark -
1044 void
1045 arch_debug_save_registers(arch_debug_registers* registers)
1047 // get the caller's frame pointer
1048 stack_frame* frame = (stack_frame*)x86_get_stack_frame();
1049 registers->bp = (addr_t)frame->previous;
1053 void
1054 arch_debug_stack_trace(void)
1056 stack_trace(0, NULL);
1060 bool
1061 arch_debug_contains_call(Thread* thread, const char* symbol, addr_t start,
1062 addr_t end)
1064 DebuggedThreadSetter threadSetter(thread);
1066 addr_t bp;
1067 if (thread == thread_get_current_thread())
1068 bp = x86_get_stack_frame();
1069 else {
1070 if (thread->state == B_THREAD_RUNNING) {
1071 // The thread is currently running on another CPU.
1072 if (thread->cpu == NULL)
1073 return false;
1074 arch_debug_registers* registers = debug_get_debug_registers(
1075 thread->cpu->cpu_num);
1076 if (registers == NULL)
1077 return false;
1078 bp = registers->bp;
1079 } else {
1080 // thread not running
1081 bp = thread->arch_info.GetFramePointer();
1085 for (;;) {
1086 if (!is_kernel_stack_address(thread, bp))
1087 break;
1089 if (is_iframe(thread, bp)) {
1090 iframe* frame = (iframe*)bp;
1092 if (is_calling(thread, frame->ip, symbol, start, end))
1093 return true;
1095 bp = frame->bp;
1096 } else {
1097 addr_t ip, nextBp;
1099 if (get_next_frame_no_debugger(bp, &nextBp, &ip, true,
1100 thread) != B_OK
1101 || ip == 0 || bp == 0)
1102 break;
1104 if (is_calling(thread, ip, symbol, start, end))
1105 return true;
1107 bp = nextBp;
1110 if (bp == 0)
1111 break;
1114 return false;
1118 void*
1119 arch_debug_get_caller(void)
1121 stack_frame* frame = (stack_frame*)x86_get_stack_frame();
1122 return (void*)frame->previous->return_address;
1126 /*! Captures a stack trace (the return addresses) of the current thread.
1127 \param returnAddresses The array the return address shall be written to.
1128 \param maxCount The maximum number of return addresses to be captured.
1129 \param skipIframes The number of interrupt frames that shall be skipped. If
1130 greater than 0, \a skipFrames is ignored.
1131 \param skipFrames The number of stack frames that shall be skipped.
1132 \param flags A combination of one or two of the following:
1133 - \c STACK_TRACE_KERNEL: Capture kernel return addresses.
1134 - \c STACK_TRACE_USER: Capture user return addresses.
1135 \return The number of return addresses written to the given array.
1137 int32
1138 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
1139 int32 skipIframes, int32 skipFrames, uint32 flags)
1141 // Keep skipping normal stack frames until we've skipped the iframes we're
1142 // supposed to skip.
1143 if (skipIframes > 0)
1144 skipFrames = INT_MAX;
1146 Thread* thread = thread_get_current_thread();
1147 int32 count = 0;
1148 addr_t bp = x86_get_stack_frame();
1149 bool onKernelStack = true;
1151 while (bp != 0 && count < maxCount) {
1152 onKernelStack = onKernelStack
1153 && is_kernel_stack_address(thread, bp);
1154 if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
1155 break;
1157 addr_t ip;
1158 addr_t nextBp;
1160 if (onKernelStack && is_iframe(thread, bp)) {
1161 iframe* frame = (iframe*)bp;
1162 ip = frame->ip;
1163 nextBp = frame->bp;
1165 if (skipIframes > 0) {
1166 if (--skipIframes == 0)
1167 skipFrames = 0;
1169 } else {
1170 if (get_next_frame_no_debugger(bp, &nextBp, &ip,
1171 onKernelStack, thread) != B_OK) {
1172 break;
1176 if (ip == 0)
1177 break;
1179 if (skipFrames <= 0
1180 && ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) {
1181 returnAddresses[count++] = ip;
1182 } else
1183 skipFrames--;
1185 bp = nextBp;
1188 return count;
1192 /*! Returns the program counter of the currently debugged (respectively this)
1193 thread where the innermost interrupts happened. \a _isSyscall, if specified,
1194 is set to whether this interrupt frame was created by a syscall. Returns
1195 \c NULL, if there's no such frame or a problem occurred retrieving it;
1196 \a _isSyscall won't be set in this case.
1198 void*
1199 arch_debug_get_interrupt_pc(bool* _isSyscall)
1201 iframe* frame = get_current_iframe(debug_get_debugged_thread());
1202 if (frame == NULL)
1203 return NULL;
1205 if (_isSyscall != NULL)
1206 *_isSyscall = frame->type == IFRAME_TYPE_SYSCALL;
1208 return (void*)(addr_t)frame->ip;
1212 /*! Sets the current thread to \c NULL.
1213 Invoked in the kernel debugger only.
1215 void
1216 arch_debug_unset_current_thread(void)
1218 // Can't just write 0 to the GS base, that will cause the read from %gs:0
1219 // to fault. Instead point it at a NULL pointer, %gs:0 will get this value.
1220 static Thread* unsetThread = NULL;
1221 #ifdef __x86_64__
1222 x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&unsetThread);
1223 #else
1224 asm volatile("mov %0, %%gs:0" : : "r" (unsetThread) : "memory");
1225 #endif
1229 bool
1230 arch_is_debug_variable_defined(const char* variableName)
1232 bool settable;
1233 return find_debug_variable(variableName, settable);
1237 status_t
1238 arch_set_debug_variable(const char* variableName, uint64 value)
1240 bool settable;
1241 size_t* variable = find_debug_variable(variableName, settable);
1242 if (variable == NULL)
1243 return B_ENTRY_NOT_FOUND;
1245 if (!settable)
1246 return B_NOT_ALLOWED;
1248 *variable = (size_t)value;
1249 return B_OK;
1253 status_t
1254 arch_get_debug_variable(const char* variableName, uint64* value)
1256 bool settable;
1257 size_t* variable = find_debug_variable(variableName, settable);
1258 if (variable == NULL)
1259 return B_ENTRY_NOT_FOUND;
1261 *value = *variable;
1262 return B_OK;
1266 struct gdb_register {
1267 int32 type;
1268 uint64 value;
1272 /*! Writes the contents of the CPU registers at some fixed outer stack frame or
1273 iframe into the given buffer in the format expected by gdb.
1275 This function is called in response to gdb's 'g' command.
1277 \param buffer The buffer to write the registers to.
1278 \param bufferSize The size of \a buffer in bytes.
1279 \return When successful, the number of bytes written to \a buffer, or a
1280 negative error code on error.
1282 ssize_t
1283 arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
1285 iframe* frame = get_current_iframe(debug_get_debugged_thread());
1286 if (frame == NULL)
1287 return B_NOT_SUPPORTED;
1289 #ifdef __x86_64__
1290 // For x86_64 the register order is:
1292 // rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
1293 // r8, r9, r10, r11, r12, r13, r14, r15,
1294 // rip, rflags, cs, ss, ds, es, fs, gs
1296 // Annoyingly, GDB wants all the registers as 64-bit values, but then
1297 // RFLAGS and the segment registers as 32-bit values, hence the need for
1298 // the type information.
1299 static const int32 kRegisterCount = 24;
1300 gdb_register registers[kRegisterCount] = {
1301 { B_UINT64_TYPE, frame->ax }, { B_UINT64_TYPE, frame->bx },
1302 { B_UINT64_TYPE, frame->cx }, { B_UINT64_TYPE, frame->dx },
1303 { B_UINT64_TYPE, frame->si }, { B_UINT64_TYPE, frame->di },
1304 { B_UINT64_TYPE, frame->bp }, { B_UINT64_TYPE, frame->sp },
1305 { B_UINT64_TYPE, frame->r8 }, { B_UINT64_TYPE, frame->r9 },
1306 { B_UINT64_TYPE, frame->r10 }, { B_UINT64_TYPE, frame->r11 },
1307 { B_UINT64_TYPE, frame->r12 }, { B_UINT64_TYPE, frame->r13 },
1308 { B_UINT64_TYPE, frame->r14 }, { B_UINT64_TYPE, frame->r15 },
1309 { B_UINT64_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
1310 { B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ss },
1311 { B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1312 { B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
1314 #else
1315 // For x86 the register order is:
1317 // eax, ecx, edx, ebx,
1318 // esp, ebp, esi, edi,
1319 // eip, eflags,
1320 // cs, ss, ds, es, fs, gs
1322 // Note that even though the segment descriptors are actually 16 bits wide,
1323 // gdb requires them as 32 bit integers.
1324 static const int32 kRegisterCount = 16;
1325 gdb_register registers[kRegisterCount] = {
1326 { B_UINT32_TYPE, frame->ax }, { B_UINT32_TYPE, frame->cx },
1327 { B_UINT32_TYPE, frame->dx }, { B_UINT32_TYPE, frame->bx },
1328 { B_UINT32_TYPE, frame->sp }, { B_UINT32_TYPE, frame->bp },
1329 { B_UINT32_TYPE, frame->si }, { B_UINT32_TYPE, frame->di },
1330 { B_UINT32_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
1331 { B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ds },
1332 // assume ss == ds
1333 { B_UINT32_TYPE, frame->ds }, { B_UINT32_TYPE, frame->es },
1334 { B_UINT32_TYPE, frame->fs }, { B_UINT32_TYPE, frame->gs },
1336 #endif
1338 const char* const bufferStart = buffer;
1340 for (int32 i = 0; i < kRegisterCount; i++) {
1341 // For some reason gdb wants the register dump in *big endian* format.
1342 int result = 0;
1343 switch (registers[i].type) {
1344 case B_UINT64_TYPE:
1345 result = snprintf(buffer, bufferSize, "%016" B_PRIx64,
1346 (uint64)B_HOST_TO_BENDIAN_INT64(registers[i].value));
1347 break;
1348 case B_UINT32_TYPE:
1349 result = snprintf(buffer, bufferSize, "%08" B_PRIx32,
1350 (uint32)B_HOST_TO_BENDIAN_INT32((uint32)registers[i].value));
1351 break;
1353 if (result >= (int)bufferSize)
1354 return B_BUFFER_OVERFLOW;
1356 buffer += result;
1357 bufferSize -= result;
1360 return buffer - bufferStart;
1364 status_t
1365 arch_debug_init(kernel_args* args)
1367 // at this stage, the debugger command system is alive
1369 add_debugger_command("where", &stack_trace, "Same as \"sc\"");
1370 add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
1371 add_debugger_command("sc", &stack_trace,
1372 "Stack crawl for current thread (or any other)");
1373 add_debugger_command("iframe", &dump_iframes,
1374 "Dump iframes for the specified thread");
1375 #ifndef __x86_64__
1376 add_debugger_command("call", &show_call, "Show call with arguments");
1377 #endif
1378 add_debugger_command_etc("in_context", &cmd_in_context,
1379 "Executes a command in the context of a given thread",
1380 "<thread ID> <command> ...\n"
1381 "Executes a command in the context of a given thread.\n",
1382 B_KDEBUG_DONT_PARSE_ARGUMENTS);
1384 return B_NO_ERROR;