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