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