1 /* 2 * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 #include <arch/debug.h> 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 16 #include <cpu.h> 17 #include <debug.h> 18 #include <debug_heap.h> 19 #include <elf.h> 20 #include <kernel.h> 21 #include <kimage.h> 22 #include <thread.h> 23 #include <vm/vm.h> 24 #include <vm/vm_types.h> 25 #include <vm/VMAddressSpace.h> 26 #include <vm/VMArea.h> 27 28 #include <arch_cpu.h> 29 30 31 struct stack_frame { 32 struct stack_frame *previous; 33 addr_t return_address; 34 }; 35 36 #define NUM_PREVIOUS_LOCATIONS 32 37 38 39 static bool 40 already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp) 41 { 42 int32 last = *_last; 43 int32 num = *_num; 44 int32 i; 45 46 for (i = 0; i < num; i++) { 47 if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == ebp) 48 return true; 49 } 50 51 *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS; 52 visited[last] = ebp; 53 54 if (num < NUM_PREVIOUS_LOCATIONS) 55 *_num = num + 1; 56 57 return false; 58 } 59 60 61 /*! Safe to be called only from outside the debugger. 62 */ 63 static status_t 64 get_next_frame_no_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) 65 { 66 // TODO: Do this more efficiently in assembly. 67 stack_frame frame; 68 if (user_memcpy(&frame, (void*)ebp, sizeof(frame)) != B_OK) 69 return B_BAD_ADDRESS; 70 71 *_eip = frame.return_address; 72 *_next = (addr_t)frame.previous; 73 74 return B_OK; 75 } 76 77 78 /*! Safe to be called only from inside the debugger. 79 */ 80 static status_t 81 get_next_frame_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) 82 { 83 stack_frame frame; 84 if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)ebp, sizeof(frame)) != B_OK) 85 return B_BAD_ADDRESS; 86 87 *_eip = frame.return_address; 88 *_next = (addr_t)frame.previous; 89 90 return B_OK; 91 } 92 93 94 static status_t 95 lookup_symbol(struct thread* thread, addr_t address, addr_t *_baseAddress, 96 const char **_symbolName, const char **_imageName, bool *_exactMatch) 97 { 98 status_t status = B_ENTRY_NOT_FOUND; 99 100 if (IS_KERNEL_ADDRESS(address)) { 101 // a kernel symbol 102 status = elf_debug_lookup_symbol_address(address, _baseAddress, 103 _symbolName, _imageName, _exactMatch); 104 } else if (thread != NULL && thread->team != NULL) { 105 // try a lookup using the userland runtime loader structures 106 status = elf_debug_lookup_user_symbol_address(thread->team, address, 107 _baseAddress, _symbolName, _imageName, _exactMatch); 108 109 if (status != B_OK) { 110 // try to locate the image in the images loaded into user space 111 status = image_debug_lookup_user_symbol_address(thread->team, 112 address, _baseAddress, _symbolName, _imageName, _exactMatch); 113 } 114 } 115 116 return status; 117 } 118 119 120 static void 121 set_debug_argument_variable(int32 index, uint64 value) 122 { 123 char name[8]; 124 snprintf(name, sizeof(name), "_arg%ld", index); 125 set_debug_variable(name, value); 126 } 127 128 129 template<typename Type> 130 static Type 131 read_function_argument_value(void* argument, bool& _valueKnown) 132 { 133 Type value; 134 if (debug_memcpy(B_CURRENT_TEAM, &value, argument, sizeof(Type)) == B_OK) { 135 _valueKnown = true; 136 return value; 137 } 138 139 _valueKnown = false; 140 return 0; 141 } 142 143 144 static status_t 145 print_demangled_call(const char* image, const char* symbol, addr_t args, 146 bool noObjectMethod, bool addDebugVariables) 147 { 148 static const size_t kBufferSize = 256; 149 char* buffer = (char*)debug_malloc(kBufferSize); 150 if (buffer == NULL) 151 return B_NO_MEMORY; 152 153 bool isObjectMethod; 154 const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize, 155 &isObjectMethod); 156 if (name == NULL) { 157 debug_free(buffer); 158 return B_ERROR; 159 } 160 161 uint32* arg = (uint32*)args; 162 163 if (noObjectMethod) 164 isObjectMethod = false; 165 if (isObjectMethod) { 166 const char* lastName = strrchr(name, ':') - 1; 167 int namespaceLength = lastName - name; 168 169 uint32 argValue = 0; 170 if (debug_memcpy(B_CURRENT_TEAM, &argValue, arg, 4) == B_OK) { 171 kprintf("<%s> %.*s<\33[32m%#" B_PRIx32 "\33[0m>%s", image, 172 namespaceLength, name, argValue, lastName); 173 } else 174 kprintf("<%s> %.*s<???>%s", image, namespaceLength, name, lastName); 175 176 if (addDebugVariables) 177 set_debug_variable("_this", argValue); 178 arg++; 179 } else 180 kprintf("<%s> %s", image, name); 181 182 kprintf("("); 183 184 size_t length; 185 int32 type, i = 0; 186 uint32 cookie = 0; 187 while (debug_get_next_demangled_argument(&cookie, symbol, buffer, 188 kBufferSize, &type, &length) == B_OK) { 189 if (i++ > 0) 190 kprintf(", "); 191 192 // retrieve value and type identifier 193 194 uint64 value; 195 bool valueKnown = false; 196 197 switch (type) { 198 case B_INT64_TYPE: 199 value = read_function_argument_value<int64>(arg, valueKnown); 200 if (valueKnown) 201 kprintf("int64: \33[34m%Ld\33[0m", value); 202 break; 203 case B_INT32_TYPE: 204 value = read_function_argument_value<int32>(arg, valueKnown); 205 if (valueKnown) 206 kprintf("int32: \33[34m%ld\33[0m", (int32)value); 207 break; 208 case B_INT16_TYPE: 209 value = read_function_argument_value<int16>(arg, valueKnown); 210 if (valueKnown) 211 kprintf("int16: \33[34m%d\33[0m", (int16)value); 212 break; 213 case B_INT8_TYPE: 214 value = read_function_argument_value<int8>(arg, valueKnown); 215 if (valueKnown) 216 kprintf("int8: \33[34m%d\33[0m", (int8)value); 217 break; 218 case B_UINT64_TYPE: 219 value = read_function_argument_value<uint64>(arg, valueKnown); 220 if (valueKnown) { 221 kprintf("uint64: \33[34m%#Lx\33[0m", value); 222 if (value < 0x100000) 223 kprintf(" (\33[34m%Lu\33[0m)", value); 224 } 225 break; 226 case B_UINT32_TYPE: 227 value = read_function_argument_value<uint32>(arg, valueKnown); 228 if (valueKnown) { 229 kprintf("uint32: \33[34m%#lx\33[0m", (uint32)value); 230 if (value < 0x100000) 231 kprintf(" (\33[34m%lu\33[0m)", (uint32)value); 232 } 233 break; 234 case B_UINT16_TYPE: 235 value = read_function_argument_value<uint16>(arg, valueKnown); 236 if (valueKnown) { 237 kprintf("uint16: \33[34m%#x\33[0m (\33[34m%u\33[0m)", 238 (uint16)value, (uint16)value); 239 } 240 break; 241 case B_UINT8_TYPE: 242 value = read_function_argument_value<uint8>(arg, valueKnown); 243 if (valueKnown) { 244 kprintf("uint8: \33[34m%#x\33[0m (\33[34m%u\33[0m)", 245 (uint8)value, (uint8)value); 246 } 247 break; 248 case B_BOOL_TYPE: 249 value = read_function_argument_value<uint8>(arg, valueKnown); 250 if (valueKnown) 251 kprintf("\33[34m%s\33[0m", value ? "true" : "false"); 252 break; 253 default: 254 if (buffer[0]) 255 kprintf("%s: ", buffer); 256 257 if (length == 4) { 258 value = read_function_argument_value<uint32>(arg, 259 valueKnown); 260 if (valueKnown) { 261 if (value == 0 262 && (type == B_POINTER_TYPE || type == B_REF_TYPE)) 263 kprintf("NULL"); 264 else 265 kprintf("\33[34m%#lx\33[0m", (uint32)value); 266 } 267 break; 268 } 269 270 271 if (length == 8) { 272 value = read_function_argument_value<uint64>(arg, 273 valueKnown); 274 } else 275 value = (uint64)arg; 276 277 if (valueKnown) 278 kprintf("\33[34m%#Lx\33[0m", value); 279 break; 280 } 281 282 if (!valueKnown) 283 kprintf("???"); 284 285 if (valueKnown && type == B_STRING_TYPE) { 286 if (value == 0) 287 kprintf(" \33[31m\"<NULL>\"\33[0m"); 288 else if (debug_strlcpy(B_CURRENT_TEAM, buffer, (char*)value, 289 kBufferSize) < B_OK) { 290 kprintf(" \33[31m\"<???>\"\33[0m"); 291 } else 292 kprintf(" \33[36m\"%s\"\33[0m", buffer); 293 } 294 295 if (addDebugVariables) 296 set_debug_argument_variable(i, value); 297 arg = (uint32*)((uint8*)arg + length); 298 } 299 300 debug_free(buffer); 301 302 kprintf(")"); 303 return B_OK; 304 } 305 306 307 static void 308 print_stack_frame(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, 309 int32 callIndex, bool demangle) 310 { 311 const char *symbol, *image; 312 addr_t baseAddress; 313 bool exactMatch; 314 status_t status; 315 addr_t diff; 316 317 diff = nextEbp - ebp; 318 319 // kernel space/user space switch 320 if (diff & 0x80000000) 321 diff = 0; 322 323 status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, 324 &exactMatch); 325 326 kprintf("%2ld %08lx (+%4ld) %08lx ", callIndex, ebp, diff, eip); 327 328 if (status == B_OK) { 329 if (exactMatch && demangle) { 330 status = print_demangled_call(image, symbol, nextEbp + 8, false, 331 false); 332 } 333 334 if (!exactMatch || !demangle || status != B_OK) { 335 if (symbol != NULL) { 336 kprintf("<%s>:%s%s", image, symbol, 337 exactMatch ? "" : " (nearest)"); 338 } else 339 kprintf("<%s@%p>:unknown", image, (void *)baseAddress); 340 } 341 342 kprintf(" + 0x%04lx\n", eip - baseAddress); 343 } else { 344 VMArea *area = NULL; 345 if (thread != NULL && thread->team != NULL 346 && thread->team->address_space != NULL) { 347 area = thread->team->address_space->LookupArea(eip); 348 } 349 if (area != NULL) { 350 kprintf("%ld:%s@%p + %#lx\n", area->id, area->name, 351 (void*)area->Base(), eip - area->Base()); 352 } else 353 kprintf("\n"); 354 } 355 } 356 357 358 static void 359 print_iframe(struct iframe *frame) 360 { 361 bool isUser = IFRAME_IS_USER(frame); 362 kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, 363 isUser ? (uint32*)(frame + 1) : &frame->user_esp); 364 365 kprintf(" eax 0x%-9lx ebx 0x%-9lx ecx 0x%-9lx edx 0x%lx\n", 366 frame->eax, frame->ebx, frame->ecx, frame->edx); 367 kprintf(" esi 0x%-9lx edi 0x%-9lx ebp 0x%-9lx esp 0x%lx\n", 368 frame->esi, frame->edi, frame->ebp, frame->esp); 369 kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->eip, frame->flags); 370 if (isUser) { 371 // from user space 372 kprintf("user esp 0x%lx", frame->user_esp); 373 } 374 kprintf("\n"); 375 kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, 376 frame->error_code); 377 } 378 379 380 static bool 381 setup_for_thread(char *arg, struct thread **_thread, uint32 *_ebp, 382 uint32 *_oldPageDirectory) 383 { 384 struct thread *thread = NULL; 385 386 if (arg != NULL) { 387 thread_id id = strtoul(arg, NULL, 0); 388 thread = thread_get_thread_struct_locked(id); 389 if (thread == NULL) { 390 kprintf("could not find thread %ld\n", id); 391 return false; 392 } 393 394 if (id != thread_get_current_thread_id()) { 395 // switch to the page directory of the new thread to be 396 // able to follow the stack trace into userland 397 uint32 newPageDirectory = x86_next_page_directory( 398 thread_get_current_thread(), thread); 399 400 if (newPageDirectory != 0) { 401 read_cr3(*_oldPageDirectory); 402 write_cr3(newPageDirectory); 403 } 404 405 if (thread->state == B_THREAD_RUNNING) { 406 // The thread is currently running on another CPU. 407 if (thread->cpu == NULL) 408 return false; 409 arch_debug_registers* registers = debug_get_debug_registers( 410 thread->cpu->cpu_num); 411 if (registers == NULL) 412 return false; 413 *_ebp = registers->ebp; 414 } else { 415 // read %ebp from the thread's stack stored by a pushad 416 *_ebp = thread->arch_info.current_stack.esp[2]; 417 } 418 } else 419 thread = NULL; 420 } 421 422 if (thread == NULL) { 423 // if we don't have a thread yet, we want the current one 424 // (ebp has been set by the caller for this case already) 425 thread = thread_get_current_thread(); 426 } 427 428 *_thread = thread; 429 return true; 430 } 431 432 433 static bool 434 is_double_fault_stack_address(int32 cpu, addr_t address) 435 { 436 size_t size; 437 addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size); 438 return address >= bottom && address < bottom + size; 439 } 440 441 442 static bool 443 is_kernel_stack_address(struct thread* thread, addr_t address) 444 { 445 // We don't have a thread pointer in the early boot process, but then we are 446 // on the kernel stack for sure. 447 if (thread == NULL) 448 return IS_KERNEL_ADDRESS(address); 449 450 // Also in the early boot process we might have a thread structure, but it 451 // might not have its kernel stack attributes set yet. 452 if (thread->kernel_stack_top == 0) 453 return IS_KERNEL_ADDRESS(address); 454 455 return (address >= thread->kernel_stack_base 456 && address < thread->kernel_stack_top) 457 || (thread->cpu != NULL 458 && is_double_fault_stack_address(thread->cpu->cpu_num, address)); 459 } 460 461 462 static bool 463 is_iframe(struct thread* thread, addr_t frame) 464 { 465 if (!is_kernel_stack_address(thread, frame)) 466 return false; 467 468 addr_t previousFrame = *(addr_t*)frame; 469 return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0); 470 } 471 472 473 static struct iframe * 474 find_previous_iframe(struct thread *thread, addr_t frame) 475 { 476 // iterate backwards through the stack frames, until we hit an iframe 477 while (is_kernel_stack_address(thread, frame)) { 478 if (is_iframe(thread, frame)) 479 return (struct iframe*)frame; 480 481 frame = *(addr_t*)frame; 482 } 483 484 return NULL; 485 } 486 487 488 static struct iframe* 489 get_previous_iframe(struct thread* thread, struct iframe* frame) 490 { 491 if (frame == NULL) 492 return NULL; 493 494 return find_previous_iframe(thread, frame->ebp); 495 } 496 497 498 static struct iframe* 499 get_current_iframe(struct thread* thread) 500 { 501 if (thread == thread_get_current_thread()) 502 return i386_get_current_iframe(); 503 504 addr_t ebp = thread->arch_info.current_stack.esp[2]; 505 // NOTE: This doesn't work, if the thread is running (on another CPU). 506 return find_previous_iframe(thread, ebp); 507 } 508 509 510 uint32* 511 find_debug_variable(const char* variableName, bool& settable) 512 { 513 struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); 514 if (frame == NULL) 515 return NULL; 516 517 settable = false; 518 519 if (strcmp(variableName, "gs") == 0) { 520 return &frame->gs; 521 } else if (strcmp(variableName, "fs") == 0) { 522 return &frame->fs; 523 } else if (strcmp(variableName, "es") == 0) { 524 return &frame->es; 525 } else if (strcmp(variableName, "ds") == 0) { 526 return &frame->ds; 527 } else if (strcmp(variableName, "cs") == 0) { 528 return &frame->cs; 529 } else if (strcmp(variableName, "edi") == 0) { 530 settable = true; 531 return &frame->edi; 532 } else if (strcmp(variableName, "esi") == 0) { 533 settable = true; 534 return &frame->esi; 535 } else if (strcmp(variableName, "ebp") == 0) { 536 settable = true; 537 return &frame->ebp; 538 } else if (strcmp(variableName, "esp") == 0) { 539 settable = true; 540 return &frame->esp; 541 } else if (strcmp(variableName, "ebx") == 0) { 542 settable = true; 543 return &frame->ebx; 544 } else if (strcmp(variableName, "edx") == 0) { 545 settable = true; 546 return &frame->edx; 547 } else if (strcmp(variableName, "ecx") == 0) { 548 settable = true; 549 return &frame->ecx; 550 } else if (strcmp(variableName, "eax") == 0) { 551 settable = true; 552 return &frame->eax; 553 } else if (strcmp(variableName, "orig_eax") == 0) { 554 settable = true; 555 return &frame->orig_eax; 556 } else if (strcmp(variableName, "orig_edx") == 0) { 557 settable = true; 558 return &frame->orig_edx; 559 } else if (strcmp(variableName, "eip") == 0) { 560 settable = true; 561 return &frame->eip; 562 } else if (strcmp(variableName, "eflags") == 0) { 563 settable = true; 564 return &frame->flags; 565 } 566 567 if (IFRAME_IS_USER(frame)) { 568 if (strcmp(variableName, "user_esp") == 0) { 569 settable = true; 570 return &frame->user_esp; 571 } else if (strcmp(variableName, "user_ss") == 0) { 572 return &frame->user_ss; 573 } 574 } 575 576 return NULL; 577 } 578 579 580 static int 581 stack_trace(int argc, char **argv) 582 { 583 static const char* usage = "usage: %s [-d] [ <thread id> ]\n" 584 "Prints a stack trace for the current, respectively the specified\n" 585 "thread.\n" 586 " -d - Disables the demangling of the symbols.\n" 587 " <thread id> - The ID of the thread for which to print the stack\n" 588 " trace.\n"; 589 bool demangle = true; 590 int32 threadIndex = 1; 591 if (argc > 1 && !strcmp(argv[1], "-d")) { 592 demangle = false; 593 threadIndex++; 594 } 595 596 if (argc > threadIndex + 1 597 || (argc == 2 && strcmp(argv[1], "--help") == 0)) { 598 kprintf(usage, argv[0]); 599 return 0; 600 } 601 602 uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; 603 struct thread *thread = NULL; 604 uint32 oldPageDirectory = 0; 605 uint32 ebp = x86_read_ebp(); 606 int32 num = 0, last = 0; 607 608 if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL, 609 &thread, &ebp, &oldPageDirectory)) 610 return 0; 611 612 DebuggedThreadSetter threadSetter(thread); 613 614 if (thread != NULL) { 615 kprintf("stack trace for thread %ld \"%s\"\n", thread->id, 616 thread->name); 617 618 kprintf(" kernel stack: %p to %p\n", 619 (void *)thread->kernel_stack_base, 620 (void *)(thread->kernel_stack_top)); 621 if (thread->user_stack_base != 0) { 622 kprintf(" user stack: %p to %p\n", 623 (void *)thread->user_stack_base, 624 (void *)(thread->user_stack_base + thread->user_stack_size)); 625 } 626 } 627 628 kprintf("frame caller <image>:function + offset\n"); 629 630 bool onKernelStack = true; 631 632 for (int32 callIndex = 0;; callIndex++) { 633 onKernelStack = onKernelStack 634 && is_kernel_stack_address(thread, ebp); 635 636 if (onKernelStack && is_iframe(thread, ebp)) { 637 struct iframe *frame = (struct iframe *)ebp; 638 639 print_iframe(frame); 640 print_stack_frame(thread, frame->eip, ebp, frame->ebp, callIndex, 641 demangle); 642 643 ebp = frame->ebp; 644 } else { 645 addr_t eip, nextEbp; 646 647 if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) { 648 kprintf("%08lx -- read fault\n", ebp); 649 break; 650 } 651 652 if (eip == 0 || ebp == 0) 653 break; 654 655 print_stack_frame(thread, eip, ebp, nextEbp, callIndex, demangle); 656 ebp = nextEbp; 657 } 658 659 if (already_visited(previousLocations, &last, &num, ebp)) { 660 kprintf("circular stack frame: %p!\n", (void *)ebp); 661 break; 662 } 663 if (ebp == 0) 664 break; 665 } 666 667 if (oldPageDirectory != 0) { 668 // switch back to the previous page directory to no cause any troubles 669 write_cr3(oldPageDirectory); 670 } 671 672 return 0; 673 } 674 675 676 static void 677 print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, 678 int32 argCount) 679 { 680 const char *symbol, *image; 681 addr_t baseAddress; 682 bool exactMatch; 683 status_t status; 684 bool demangled = false; 685 int32 *arg = (int32 *)(nextEbp + 8); 686 687 status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, 688 &exactMatch); 689 690 kprintf("%08lx %08lx ", ebp, eip); 691 692 if (status == B_OK) { 693 if (symbol != NULL) { 694 if (exactMatch && (argCount == 0 || argCount == -1)) { 695 status = print_demangled_call(image, symbol, (addr_t)arg, 696 argCount == -1, true); 697 if (status == B_OK) 698 demangled = true; 699 } 700 if (!demangled) { 701 kprintf("<%s>:%s%s", image, symbol, 702 exactMatch ? "" : " (nearest)"); 703 } 704 } else { 705 kprintf("<%s@%p>:unknown + 0x%04lx", image, 706 (void *)baseAddress, eip - baseAddress); 707 } 708 } else { 709 VMArea *area = NULL; 710 if (thread->team->address_space != NULL) 711 area = thread->team->address_space->LookupArea(eip); 712 if (area != NULL) { 713 kprintf("%ld:%s@%p + %#lx", area->id, area->name, 714 (void *)area->Base(), eip - area->Base()); 715 } 716 } 717 718 if (!demangled) { 719 kprintf("("); 720 721 for (int32 i = 0; i < argCount; i++) { 722 if (i > 0) 723 kprintf(", "); 724 kprintf("%#lx", *arg); 725 if (*arg > -0x10000 && *arg < 0x10000) 726 kprintf(" (%ld)", *arg); 727 728 set_debug_argument_variable(i + 1, *(uint32 *)arg); 729 arg++; 730 } 731 732 kprintf(")\n"); 733 } else 734 kprintf("\n"); 735 736 set_debug_variable("_frame", nextEbp); 737 } 738 739 740 static int 741 show_call(int argc, char **argv) 742 { 743 static const char* usage 744 = "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n" 745 "Prints a function call with parameters of the current, respectively\n" 746 "the specified thread.\n" 747 " <thread id> - The ID of the thread for which to print the call.\n" 748 " <call index> - The index of the call in the stack trace.\n" 749 " <arg count> - The number of call arguments to print (use 'c' to\n" 750 " force the C++ demangler to use class methods,\n" 751 " use 'd' to disable demangling).\n"; 752 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 753 kprintf(usage, argv[0]); 754 return 0; 755 } 756 757 struct thread *thread = NULL; 758 uint32 oldPageDirectory = 0; 759 addr_t ebp = x86_read_ebp(); 760 int32 argCount = 0; 761 762 if (argc >= 2 && argv[argc - 1][0] == '-') { 763 if (argv[argc - 1][1] == 'c') 764 argCount = -1; 765 else if (argv[argc - 1][1] == 'd') 766 argCount = -2; 767 else 768 argCount = strtoul(argv[argc - 1] + 1, NULL, 0); 769 770 if (argCount < -2 || argCount > 16) { 771 kprintf("Invalid argument count \"%ld\".\n", argCount); 772 return 0; 773 } 774 argc--; 775 } 776 777 if (argc < 2 || argc > 3) { 778 kprintf(usage, argv[0]); 779 return 0; 780 } 781 782 if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp, 783 &oldPageDirectory)) 784 return 0; 785 786 DebuggedThreadSetter threadSetter(thread); 787 788 int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0); 789 790 if (thread != NULL) 791 kprintf("thread %ld, %s\n", thread->id, thread->name); 792 793 bool onKernelStack = true; 794 795 for (int32 index = 0; index <= callIndex; index++) { 796 onKernelStack = onKernelStack 797 && is_kernel_stack_address(thread, ebp); 798 799 if (onKernelStack && is_iframe(thread, ebp)) { 800 struct iframe *frame = (struct iframe *)ebp; 801 802 if (index == callIndex) 803 print_call(thread, frame->eip, ebp, frame->ebp, argCount); 804 805 ebp = frame->ebp; 806 } else { 807 addr_t eip, nextEbp; 808 809 if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) { 810 kprintf("%08lx -- read fault\n", ebp); 811 break; 812 } 813 814 if (eip == 0 || ebp == 0) 815 break; 816 817 if (index == callIndex) 818 print_call(thread, eip, ebp, nextEbp, argCount); 819 820 ebp = nextEbp; 821 } 822 823 if (ebp == 0) 824 break; 825 } 826 827 if (oldPageDirectory != 0) { 828 // switch back to the previous page directory to not cause any troubles 829 write_cr3(oldPageDirectory); 830 } 831 832 return 0; 833 } 834 835 836 static int 837 dump_iframes(int argc, char **argv) 838 { 839 static const char* usage = "usage: %s [ <thread id> ]\n" 840 "Prints the iframe stack for the current, respectively the specified\n" 841 "thread.\n" 842 " <thread id> - The ID of the thread for which to print the iframe\n" 843 " stack.\n"; 844 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 845 kprintf(usage, argv[0]); 846 return 0; 847 } 848 849 struct thread *thread = NULL; 850 851 if (argc < 2) { 852 thread = thread_get_current_thread(); 853 } else if (argc == 2) { 854 thread_id id = strtoul(argv[1], NULL, 0); 855 thread = thread_get_thread_struct_locked(id); 856 if (thread == NULL) { 857 kprintf("could not find thread %ld\n", id); 858 return 0; 859 } 860 } else if (argc > 2) { 861 kprintf(usage, argv[0]); 862 return 0; 863 } 864 865 if (thread != NULL) 866 kprintf("iframes for thread %ld \"%s\"\n", thread->id, thread->name); 867 868 DebuggedThreadSetter threadSetter(thread); 869 870 struct iframe* frame = find_previous_iframe(thread, x86_read_ebp()); 871 while (frame != NULL) { 872 print_iframe(frame); 873 frame = get_previous_iframe(thread, frame); 874 } 875 876 return 0; 877 } 878 879 880 static bool 881 is_calling(struct thread *thread, addr_t eip, const char *pattern, 882 addr_t start, addr_t end) 883 { 884 if (pattern == NULL) 885 return eip >= start && eip < end; 886 887 if (!IS_KERNEL_ADDRESS(eip)) 888 return false; 889 890 const char *symbol; 891 if (lookup_symbol(thread, eip, NULL, &symbol, NULL, NULL) != B_OK) 892 return false; 893 894 return strstr(symbol, pattern); 895 } 896 897 898 static int 899 cmd_in_context(int argc, char** argv) 900 { 901 if (argc != 2) { 902 print_debugger_command_usage(argv[0]); 903 return 0; 904 } 905 906 // get the thread ID 907 const char* commandLine = argv[1]; 908 char threadIDString[16]; 909 if (parse_next_debug_command_argument(&commandLine, threadIDString, 910 sizeof(threadIDString)) != B_OK) { 911 kprintf("Failed to parse thread ID.\n"); 912 return 0; 913 } 914 915 if (commandLine == NULL) { 916 print_debugger_command_usage(argv[0]); 917 return 0; 918 } 919 920 uint64 threadID; 921 if (!evaluate_debug_expression(threadIDString, &threadID, false)) 922 return 0; 923 924 // get the thread 925 struct thread* thread = thread_get_thread_struct_locked(threadID); 926 if (thread == NULL) { 927 kprintf("Could not find thread with ID \"%s\".\n", threadIDString); 928 return 0; 929 } 930 931 // switch the page directory, if necessary 932 uint32 oldPageDirectory = 0; 933 if (thread != thread_get_current_thread()) { 934 uint32 newPageDirectory = x86_next_page_directory( 935 thread_get_current_thread(), thread); 936 937 if (newPageDirectory != 0) { 938 read_cr3(oldPageDirectory); 939 write_cr3(newPageDirectory); 940 } 941 } 942 943 // execute the command 944 { 945 DebuggedThreadSetter threadSetter(thread); 946 evaluate_debug_command(commandLine); 947 } 948 949 // reset the page directory 950 if (oldPageDirectory) 951 write_cr3(oldPageDirectory); 952 953 return 0; 954 } 955 956 957 // #pragma mark - 958 959 960 void 961 arch_debug_save_registers(struct arch_debug_registers* registers) 962 { 963 // get the caller's frame pointer 964 stack_frame* frame = (stack_frame*)x86_read_ebp(); 965 registers->ebp = (addr_t)frame->previous; 966 } 967 968 969 void 970 arch_debug_stack_trace(void) 971 { 972 stack_trace(0, NULL); 973 } 974 975 976 bool 977 arch_debug_contains_call(struct thread *thread, const char *symbol, 978 addr_t start, addr_t end) 979 { 980 DebuggedThreadSetter threadSetter(thread); 981 982 addr_t ebp; 983 if (thread == thread_get_current_thread()) 984 ebp = x86_read_ebp(); 985 else { 986 if (thread->state == B_THREAD_RUNNING) { 987 // The thread is currently running on another CPU. 988 if (thread->cpu == NULL) 989 return false; 990 arch_debug_registers* registers = debug_get_debug_registers( 991 thread->cpu->cpu_num); 992 if (registers == NULL) 993 return false; 994 ebp = registers->ebp; 995 } else { 996 // thread not running 997 ebp = thread->arch_info.current_stack.esp[2]; 998 } 999 } 1000 1001 for (;;) { 1002 if (!is_kernel_stack_address(thread, ebp)) 1003 break; 1004 1005 if (is_iframe(thread, ebp)) { 1006 struct iframe *frame = (struct iframe *)ebp; 1007 1008 if (is_calling(thread, frame->eip, symbol, start, end)) 1009 return true; 1010 1011 ebp = frame->ebp; 1012 } else { 1013 addr_t eip, nextEbp; 1014 1015 if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK 1016 || eip == 0 || ebp == 0) 1017 break; 1018 1019 if (is_calling(thread, eip, symbol, start, end)) 1020 return true; 1021 1022 ebp = nextEbp; 1023 } 1024 1025 if (ebp == 0) 1026 break; 1027 } 1028 1029 return false; 1030 } 1031 1032 1033 void * 1034 arch_debug_get_caller(void) 1035 { 1036 struct stack_frame *frame = (struct stack_frame *)x86_read_ebp(); 1037 return (void *)frame->previous->return_address; 1038 } 1039 1040 1041 /*! Captures a stack trace (the return addresses) of the current thread. 1042 \param returnAddresses The array the return address shall be written to. 1043 \param maxCount The maximum number of return addresses to be captured. 1044 \param skipIframes The number of interrupt frames that shall be skipped. If 1045 greater than 0, \a skipFrames is ignored. 1046 \param skipFrames The number of stack frames that shall be skipped. 1047 \param flags A combination of one or two of the following: 1048 - \c STACK_TRACE_KERNEL: Capture kernel return addresses. 1049 - \c STACK_TRACE_USER: Capture user return addresses. 1050 \return The number of return addresses written to the given array. 1051 */ 1052 int32 1053 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, 1054 int32 skipIframes, int32 skipFrames, uint32 flags) 1055 { 1056 // Keep skipping normal stack frames until we've skipped the iframes we're 1057 // supposed to skip. 1058 if (skipIframes > 0) 1059 skipFrames = INT_MAX; 1060 1061 struct thread* thread = thread_get_current_thread(); 1062 int32 count = 0; 1063 addr_t ebp = x86_read_ebp(); 1064 bool onKernelStack = true; 1065 1066 while (ebp != 0 && count < maxCount) { 1067 onKernelStack = onKernelStack 1068 && is_kernel_stack_address(thread, ebp); 1069 if (!onKernelStack && (flags & STACK_TRACE_USER) == 0) 1070 break; 1071 1072 addr_t eip; 1073 addr_t nextEbp; 1074 1075 if (onKernelStack && is_iframe(thread, ebp)) { 1076 struct iframe *frame = (struct iframe*)ebp; 1077 eip = frame->eip; 1078 nextEbp = frame->ebp; 1079 1080 if (skipIframes > 0) { 1081 if (--skipIframes == 0) 1082 skipFrames = 0; 1083 } 1084 } else { 1085 if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK) 1086 break; 1087 } 1088 1089 if (skipFrames <= 0 1090 && ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) { 1091 returnAddresses[count++] = eip; 1092 } else 1093 skipFrames--; 1094 1095 ebp = nextEbp; 1096 } 1097 1098 return count; 1099 } 1100 1101 1102 /*! Returns the program counter of the currently debugged (respectively this) 1103 thread where the innermost interrupts happened. \a _isSyscall, if specified, 1104 is set to whether this interrupt frame was created by a syscall. Returns 1105 \c NULL, if there's no such frame or a problem occurred retrieving it; 1106 \a _isSyscall won't be set in this case. 1107 */ 1108 void* 1109 arch_debug_get_interrupt_pc(bool* _isSyscall) 1110 { 1111 struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); 1112 if (frame == NULL) 1113 return NULL; 1114 1115 if (_isSyscall != NULL) 1116 *_isSyscall = frame->vector == 99; 1117 1118 return (void*)(addr_t)frame->eip; 1119 } 1120 1121 1122 /*! Sets the current thread to \c NULL. 1123 Invoked in the kernel debugger only. 1124 */ 1125 void 1126 arch_debug_unset_current_thread(void) 1127 { 1128 write_dr3(NULL); 1129 } 1130 1131 1132 bool 1133 arch_is_debug_variable_defined(const char* variableName) 1134 { 1135 bool settable; 1136 return find_debug_variable(variableName, settable); 1137 } 1138 1139 1140 status_t 1141 arch_set_debug_variable(const char* variableName, uint64 value) 1142 { 1143 bool settable; 1144 uint32* variable = find_debug_variable(variableName, settable); 1145 if (variable == NULL) 1146 return B_ENTRY_NOT_FOUND; 1147 1148 if (!settable) 1149 return B_NOT_ALLOWED; 1150 1151 *variable = (uint32)value; 1152 return B_OK; 1153 } 1154 1155 1156 status_t 1157 arch_get_debug_variable(const char* variableName, uint64* value) 1158 { 1159 bool settable; 1160 uint32* variable = find_debug_variable(variableName, settable); 1161 if (variable == NULL) 1162 return B_ENTRY_NOT_FOUND; 1163 1164 *value = *variable; 1165 return B_OK; 1166 } 1167 1168 1169 status_t 1170 arch_debug_init(kernel_args *args) 1171 { 1172 // at this stage, the debugger command system is alive 1173 1174 add_debugger_command("where", &stack_trace, "Same as \"sc\""); 1175 add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)"); 1176 add_debugger_command("sc", &stack_trace, 1177 "Stack crawl for current thread (or any other)"); 1178 add_debugger_command("iframe", &dump_iframes, 1179 "Dump iframes for the specified thread"); 1180 add_debugger_command("call", &show_call, "Show call with arguments"); 1181 add_debugger_command_etc("in_context", &cmd_in_context, 1182 "Executes a command in the context of a given thread", 1183 "<thread ID> <command> ...\n" 1184 "Executes a command in the context of a given thread.\n", 1185 B_KDEBUG_DONT_PARSE_ARGUMENTS); 1186 1187 return B_NO_ERROR; 1188 } 1189 1190