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 // read %ebp from the thread's stack stored by a pushad 361 *_ebp = thread->arch_info.current_stack.esp[2]; 362 } else 363 thread = NULL; 364 } 365 366 if (thread == NULL) { 367 // if we don't have a thread yet, we want the current one 368 // (ebp has been set by the caller for this case already) 369 thread = thread_get_current_thread(); 370 } 371 372 *_thread = thread; 373 return true; 374 } 375 376 377 static bool 378 is_double_fault_stack_address(int32 cpu, addr_t address) 379 { 380 size_t size; 381 addr_t bottom = (addr_t)x86_get_double_fault_stack(cpu, &size); 382 return address >= bottom && address < bottom + size; 383 } 384 385 386 static bool 387 is_kernel_stack_address(struct thread* thread, addr_t address) 388 { 389 // We don't have a thread pointer in the early boot process, but then we are 390 // on the kernel stack for sure. 391 if (thread == NULL) 392 return IS_KERNEL_ADDRESS(address); 393 394 // Also in the early boot process we might have a thread structure, but it 395 // might not have its kernel stack attributes set yet. 396 if (thread->kernel_stack_top == 0) 397 return IS_KERNEL_ADDRESS(address); 398 399 return (address >= thread->kernel_stack_base 400 && address < thread->kernel_stack_top) 401 || (thread->cpu != NULL 402 && is_double_fault_stack_address(thread->cpu->cpu_num, address)); 403 } 404 405 406 static bool 407 is_iframe(struct thread* thread, addr_t frame) 408 { 409 if (!is_kernel_stack_address(thread, frame)) 410 return false; 411 412 addr_t previousFrame = *(addr_t*)frame; 413 return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0); 414 } 415 416 417 static struct iframe * 418 find_previous_iframe(struct thread *thread, addr_t frame) 419 { 420 // iterate backwards through the stack frames, until we hit an iframe 421 while (is_kernel_stack_address(thread, frame)) { 422 if (is_iframe(thread, frame)) 423 return (struct iframe*)frame; 424 425 frame = *(addr_t*)frame; 426 } 427 428 return NULL; 429 } 430 431 432 static struct iframe* 433 get_previous_iframe(struct thread* thread, struct iframe* frame) 434 { 435 if (frame == NULL) 436 return NULL; 437 438 return find_previous_iframe(thread, frame->ebp); 439 } 440 441 442 static struct iframe* 443 get_current_iframe(struct thread* thread) 444 { 445 if (thread == thread_get_current_thread()) 446 return i386_get_current_iframe(); 447 448 addr_t ebp = thread->arch_info.current_stack.esp[2]; 449 // NOTE: This doesn't work, if the thread is running (on another CPU). 450 return find_previous_iframe(thread, ebp); 451 } 452 453 454 uint32* 455 find_debug_variable(const char* variableName, bool& settable) 456 { 457 struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); 458 if (frame == NULL) 459 return NULL; 460 461 settable = false; 462 463 if (strcmp(variableName, "gs") == 0) { 464 return &frame->gs; 465 } else if (strcmp(variableName, "fs") == 0) { 466 return &frame->fs; 467 } else if (strcmp(variableName, "es") == 0) { 468 return &frame->es; 469 } else if (strcmp(variableName, "ds") == 0) { 470 return &frame->ds; 471 } else if (strcmp(variableName, "cs") == 0) { 472 return &frame->cs; 473 } else if (strcmp(variableName, "edi") == 0) { 474 settable = true; 475 return &frame->edi; 476 } else if (strcmp(variableName, "esi") == 0) { 477 settable = true; 478 return &frame->esi; 479 } else if (strcmp(variableName, "ebp") == 0) { 480 settable = true; 481 return &frame->ebp; 482 } else if (strcmp(variableName, "esp") == 0) { 483 settable = true; 484 return &frame->esp; 485 } else if (strcmp(variableName, "ebx") == 0) { 486 settable = true; 487 return &frame->ebx; 488 } else if (strcmp(variableName, "edx") == 0) { 489 settable = true; 490 return &frame->edx; 491 } else if (strcmp(variableName, "ecx") == 0) { 492 settable = true; 493 return &frame->ecx; 494 } else if (strcmp(variableName, "eax") == 0) { 495 settable = true; 496 return &frame->eax; 497 } else if (strcmp(variableName, "orig_eax") == 0) { 498 settable = true; 499 return &frame->orig_eax; 500 } else if (strcmp(variableName, "orig_edx") == 0) { 501 settable = true; 502 return &frame->orig_edx; 503 } else if (strcmp(variableName, "eip") == 0) { 504 settable = true; 505 return &frame->eip; 506 } else if (strcmp(variableName, "eflags") == 0) { 507 settable = true; 508 return &frame->flags; 509 } 510 511 if (IFRAME_IS_USER(frame)) { 512 if (strcmp(variableName, "user_esp") == 0) { 513 settable = true; 514 return &frame->user_esp; 515 } else if (strcmp(variableName, "user_ss") == 0) { 516 return &frame->user_ss; 517 } 518 } 519 520 return NULL; 521 } 522 523 524 static int 525 stack_trace(int argc, char **argv) 526 { 527 static const char* usage = "usage: %s [-d] [ <thread id> ]\n" 528 "Prints a stack trace for the current, respectively the specified\n" 529 "thread.\n" 530 " -d - Disables the demangling of the symbols.\n" 531 " <thread id> - The ID of the thread for which to print the stack\n" 532 " trace.\n"; 533 bool demangle = true; 534 int32 threadIndex = 1; 535 if (argc > 1 && !strcmp(argv[1], "-d")) { 536 demangle = false; 537 threadIndex++; 538 } 539 540 if (argc > threadIndex + 1 541 || (argc == 2 && strcmp(argv[1], "--help") == 0)) { 542 kprintf(usage, argv[0]); 543 return 0; 544 } 545 546 uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; 547 struct thread *thread = NULL; 548 addr_t oldPageDirectory = 0; 549 uint32 ebp = x86_read_ebp(); 550 int32 num = 0, last = 0; 551 552 if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL, 553 &thread, &ebp, &oldPageDirectory)) 554 return 0; 555 556 if (thread != NULL) { 557 kprintf("stack trace for thread %ld \"%s\"\n", thread->id, 558 thread->name); 559 560 kprintf(" kernel stack: %p to %p\n", 561 (void *)thread->kernel_stack_base, 562 (void *)(thread->kernel_stack_top)); 563 if (thread->user_stack_base != 0) { 564 kprintf(" user stack: %p to %p\n", 565 (void *)thread->user_stack_base, 566 (void *)(thread->user_stack_base + thread->user_stack_size)); 567 } 568 } 569 570 kprintf("frame caller <image>:function + offset\n"); 571 572 bool onKernelStack = true; 573 574 for (int32 callIndex = 0;; callIndex++) { 575 onKernelStack = onKernelStack 576 && is_kernel_stack_address(thread, ebp); 577 578 if (onKernelStack && is_iframe(thread, ebp)) { 579 struct iframe *frame = (struct iframe *)ebp; 580 581 print_iframe(frame); 582 print_stack_frame(thread, frame->eip, ebp, frame->ebp, callIndex, 583 demangle); 584 585 ebp = frame->ebp; 586 } else { 587 addr_t eip, nextEbp; 588 589 if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) { 590 kprintf("%08lx -- read fault\n", ebp); 591 break; 592 } 593 594 if (eip == 0 || ebp == 0) 595 break; 596 597 print_stack_frame(thread, eip, ebp, nextEbp, callIndex, demangle); 598 ebp = nextEbp; 599 } 600 601 if (already_visited(previousLocations, &last, &num, ebp)) { 602 kprintf("circular stack frame: %p!\n", (void *)ebp); 603 break; 604 } 605 if (ebp == 0) 606 break; 607 } 608 609 if (oldPageDirectory != 0) { 610 // switch back to the previous page directory to no cause any troubles 611 write_cr3(oldPageDirectory); 612 } 613 614 return 0; 615 } 616 617 618 static void 619 print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, 620 int32 argCount) 621 { 622 const char *symbol, *image; 623 addr_t baseAddress; 624 bool exactMatch; 625 status_t status; 626 bool demangled = false; 627 int32 *arg = (int32 *)(nextEbp + 8); 628 629 status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, 630 &exactMatch); 631 632 kprintf("%08lx %08lx ", ebp, eip); 633 634 if (status == B_OK) { 635 if (symbol != NULL) { 636 if (exactMatch && (argCount == 0 || argCount == -1)) { 637 status = print_demangled_call(image, symbol, (addr_t)arg, 638 argCount == -1, true); 639 if (status == B_OK) 640 demangled = true; 641 } 642 if (!demangled) { 643 kprintf("<%s>:%s%s", image, symbol, 644 exactMatch ? "" : " (nearest)"); 645 } 646 } else { 647 kprintf("<%s@%p>:unknown + 0x%04lx", image, 648 (void *)baseAddress, eip - baseAddress); 649 } 650 } else { 651 VMArea *area = NULL; 652 if (thread->team->address_space != NULL) 653 area = thread->team->address_space->LookupArea(eip); 654 if (area != NULL) { 655 kprintf("%ld:%s@%p + %#lx", area->id, area->name, 656 (void *)area->Base(), eip - area->Base()); 657 } 658 } 659 660 if (!demangled) { 661 kprintf("("); 662 663 for (int32 i = 0; i < argCount; i++) { 664 if (i > 0) 665 kprintf(", "); 666 kprintf("%#lx", *arg); 667 if (*arg > -0x10000 && *arg < 0x10000) 668 kprintf(" (%ld)", *arg); 669 670 set_debug_argument_variable(i + 1, *(uint32 *)arg); 671 arg++; 672 } 673 674 kprintf(")\n"); 675 } else 676 kprintf("\n"); 677 678 set_debug_variable("_frame", nextEbp); 679 } 680 681 682 static int 683 show_call(int argc, char **argv) 684 { 685 static const char* usage 686 = "usage: %s [ <thread id> ] <call index> [ -<arg count> ]\n" 687 "Prints a function call with parameters of the current, respectively\n" 688 "the specified thread.\n" 689 " <thread id> - The ID of the thread for which to print the call.\n" 690 " <call index> - The index of the call in the stack trace.\n" 691 " <arg count> - The number of call arguments to print (use 'c' to\n" 692 " force the C++ demangler to use class methods,\n" 693 " use 'd' to disable demangling).\n"; 694 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 695 kprintf(usage, argv[0]); 696 return 0; 697 } 698 699 struct thread *thread = NULL; 700 addr_t oldPageDirectory = 0; 701 addr_t ebp = x86_read_ebp(); 702 int32 argCount = 0; 703 704 if (argc >= 2 && argv[argc - 1][0] == '-') { 705 if (argv[argc - 1][1] == 'c') 706 argCount = -1; 707 else if (argv[argc - 1][1] == 'd') 708 argCount = -2; 709 else 710 argCount = strtoul(argv[argc - 1] + 1, NULL, 0); 711 712 if (argCount < -2 || argCount > 16) { 713 kprintf("Invalid argument count \"%ld\".\n", argCount); 714 return 0; 715 } 716 argc--; 717 } 718 719 if (argc < 2 || argc > 3) { 720 kprintf(usage, argv[0]); 721 return 0; 722 } 723 724 if (!setup_for_thread(argc == 3 ? argv[1] : NULL, &thread, &ebp, 725 &oldPageDirectory)) 726 return 0; 727 728 int32 callIndex = strtoul(argv[argc == 3 ? 2 : 1], NULL, 0); 729 730 if (thread != NULL) 731 kprintf("thread %ld, %s\n", thread->id, thread->name); 732 733 bool onKernelStack = true; 734 735 for (int32 index = 0; index <= callIndex; index++) { 736 onKernelStack = onKernelStack 737 && is_kernel_stack_address(thread, ebp); 738 739 if (onKernelStack && is_iframe(thread, ebp)) { 740 struct iframe *frame = (struct iframe *)ebp; 741 742 if (index == callIndex) 743 print_call(thread, frame->eip, ebp, frame->ebp, argCount); 744 745 ebp = frame->ebp; 746 } else { 747 addr_t eip, nextEbp; 748 749 if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) { 750 kprintf("%08lx -- read fault\n", ebp); 751 break; 752 } 753 754 if (eip == 0 || ebp == 0) 755 break; 756 757 if (index == callIndex) 758 print_call(thread, eip, ebp, nextEbp, argCount); 759 760 ebp = nextEbp; 761 } 762 763 if (ebp == 0) 764 break; 765 } 766 767 if (oldPageDirectory != 0) { 768 // switch back to the previous page directory to not cause any troubles 769 write_cr3(oldPageDirectory); 770 } 771 772 return 0; 773 } 774 775 776 static int 777 dump_iframes(int argc, char **argv) 778 { 779 static const char* usage = "usage: %s [ <thread id> ]\n" 780 "Prints the iframe stack for the current, respectively the specified\n" 781 "thread.\n" 782 " <thread id> - The ID of the thread for which to print the iframe\n" 783 " stack.\n"; 784 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 785 kprintf(usage, argv[0]); 786 return 0; 787 } 788 789 struct thread *thread = NULL; 790 791 if (argc < 2) { 792 thread = thread_get_current_thread(); 793 } else if (argc == 2) { 794 thread_id id = strtoul(argv[1], NULL, 0); 795 thread = thread_get_thread_struct_locked(id); 796 if (thread == NULL) { 797 kprintf("could not find thread %ld\n", id); 798 return 0; 799 } 800 } else if (argc > 2) { 801 kprintf(usage, argv[0]); 802 return 0; 803 } 804 805 if (thread != NULL) 806 kprintf("iframes for thread %ld \"%s\"\n", thread->id, thread->name); 807 808 struct iframe* frame = find_previous_iframe(thread, x86_read_ebp()); 809 while (frame != NULL) { 810 print_iframe(frame); 811 frame = get_previous_iframe(thread, frame); 812 } 813 814 return 0; 815 } 816 817 818 static bool 819 is_calling(struct thread *thread, addr_t eip, const char *pattern, 820 addr_t start, addr_t end) 821 { 822 if (pattern == NULL) 823 return eip >= start && eip < end; 824 825 const char *symbol; 826 if (lookup_symbol(thread, eip, NULL, &symbol, NULL, NULL) != B_OK) 827 return false; 828 829 return strstr(symbol, pattern); 830 } 831 832 833 static int 834 cmd_in_context(int argc, char** argv) 835 { 836 if (argc != 2) { 837 print_debugger_command_usage(argv[0]); 838 return 0; 839 } 840 841 // get the thread ID 842 const char* commandLine = argv[1]; 843 char threadIDString[16]; 844 if (parse_next_debug_command_argument(&commandLine, threadIDString, 845 sizeof(threadIDString)) != B_OK) { 846 kprintf("Failed to parse thread ID.\n"); 847 return 0; 848 } 849 850 if (commandLine == NULL) { 851 print_debugger_command_usage(argv[0]); 852 return 0; 853 } 854 855 uint64 threadID; 856 if (!evaluate_debug_expression(threadIDString, &threadID, false)) 857 return 0; 858 859 // get the thread 860 struct thread* thread = thread_get_thread_struct_locked(threadID); 861 if (thread == NULL) { 862 kprintf("Could not find thread with ID \"%s\".\n", threadIDString); 863 return 0; 864 } 865 866 // switch the page directory, if necessary 867 addr_t oldPageDirectory = 0; 868 if (thread != thread_get_current_thread()) { 869 addr_t newPageDirectory = (addr_t)x86_next_page_directory( 870 thread_get_current_thread(), thread); 871 872 if (newPageDirectory != 0) { 873 read_cr3(oldPageDirectory); 874 write_cr3(newPageDirectory); 875 } 876 } 877 878 struct thread* previousThread = debug_set_debugged_thread(thread); 879 880 // execute the command 881 evaluate_debug_command(commandLine); 882 883 debug_set_debugged_thread(previousThread); 884 885 // reset the page directory 886 if (oldPageDirectory) 887 write_cr3(oldPageDirectory); 888 889 return 0; 890 } 891 892 893 // #pragma mark - 894 895 896 void 897 arch_debug_stack_trace(void) 898 { 899 stack_trace(0, NULL); 900 } 901 902 903 bool 904 arch_debug_contains_call(struct thread *thread, const char *symbol, 905 addr_t start, addr_t end) 906 { 907 addr_t ebp; 908 if (thread == thread_get_current_thread()) 909 ebp = x86_read_ebp(); 910 else 911 ebp = thread->arch_info.current_stack.esp[2]; 912 913 for (;;) { 914 if (!is_kernel_stack_address(thread, ebp)) 915 break; 916 917 if (is_iframe(thread, ebp)) { 918 struct iframe *frame = (struct iframe *)ebp; 919 920 if (is_calling(thread, frame->eip, symbol, start, end)) 921 return true; 922 923 ebp = frame->ebp; 924 } else { 925 addr_t eip, nextEbp; 926 927 if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK 928 || eip == 0 || ebp == 0) 929 break; 930 931 if (is_calling(thread, eip, symbol, start, end)) 932 return true; 933 934 ebp = nextEbp; 935 } 936 937 if (ebp == 0) 938 break; 939 } 940 941 return false; 942 } 943 944 945 void * 946 arch_debug_get_caller(void) 947 { 948 struct stack_frame *frame = (struct stack_frame *)x86_read_ebp(); 949 return (void *)frame->previous->return_address; 950 } 951 952 953 /*! Captures a stack trace (the return addresses) of the current thread. 954 \param returnAddresses The array the return address shall be written to. 955 \param maxCount The maximum number of return addresses to be captured. 956 \param skipIframes The number of interrupt frames that shall be skipped. If 957 greater than 0, \a skipFrames is ignored. 958 \param skipFrames The number of stack frames that shall be skipped. 959 \param flags A combination of one or two of the following: 960 - \c STACK_TRACE_KERNEL: Capture kernel return addresses. 961 - \c STACK_TRACE_USER: Capture user return addresses. 962 \return The number of return addresses written to the given array. 963 */ 964 int32 965 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, 966 int32 skipIframes, int32 skipFrames, uint32 flags) 967 { 968 // Keep skipping normal stack frames until we've skipped the iframes we're 969 // supposed to skip. 970 if (skipIframes > 0) 971 skipFrames = INT_MAX; 972 973 struct thread* thread = thread_get_current_thread(); 974 int32 count = 0; 975 addr_t ebp = x86_read_ebp(); 976 bool onKernelStack = true; 977 978 while (ebp != 0 && count < maxCount) { 979 onKernelStack = onKernelStack 980 && is_kernel_stack_address(thread, ebp); 981 if (!onKernelStack && (flags & STACK_TRACE_USER) == 0) 982 break; 983 984 addr_t eip; 985 addr_t nextEbp; 986 987 if (onKernelStack && is_iframe(thread, ebp)) { 988 struct iframe *frame = (struct iframe*)ebp; 989 eip = frame->eip; 990 nextEbp = frame->ebp; 991 992 if (skipIframes > 0) { 993 if (--skipIframes == 0) 994 skipFrames = 0; 995 } 996 } else { 997 if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK) 998 break; 999 } 1000 1001 if (skipFrames <= 0 1002 && ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) { 1003 returnAddresses[count++] = eip; 1004 } else 1005 skipFrames--; 1006 1007 ebp = nextEbp; 1008 } 1009 1010 return count; 1011 } 1012 1013 1014 /*! Returns the program counter of the currently debugged (respectively this) 1015 thread where the innermost interrupts happened. \a _isSyscall, if specified, 1016 is set to whether this interrupt frame was created by a syscall. Returns 1017 \c NULL, if there's no such frame or a problem occurred retrieving it; 1018 \a _isSyscall won't be set in this case. 1019 */ 1020 void* 1021 arch_debug_get_interrupt_pc(bool* _isSyscall) 1022 { 1023 struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); 1024 if (frame == NULL) 1025 return NULL; 1026 1027 if (_isSyscall != NULL) 1028 *_isSyscall = frame->vector == 99; 1029 1030 return (void*)(addr_t)frame->eip; 1031 } 1032 1033 1034 /*! Sets the current thread to \c NULL. 1035 Invoked in the kernel debugger only. 1036 */ 1037 void 1038 arch_debug_unset_current_thread(void) 1039 { 1040 write_dr3(NULL); 1041 } 1042 1043 1044 bool 1045 arch_is_debug_variable_defined(const char* variableName) 1046 { 1047 bool settable; 1048 return find_debug_variable(variableName, settable); 1049 } 1050 1051 1052 status_t 1053 arch_set_debug_variable(const char* variableName, uint64 value) 1054 { 1055 bool settable; 1056 uint32* variable = find_debug_variable(variableName, settable); 1057 if (variable == NULL) 1058 return B_ENTRY_NOT_FOUND; 1059 1060 if (!settable) 1061 return B_NOT_ALLOWED; 1062 1063 *variable = (uint32)value; 1064 return B_OK; 1065 } 1066 1067 1068 status_t 1069 arch_get_debug_variable(const char* variableName, uint64* value) 1070 { 1071 bool settable; 1072 uint32* variable = find_debug_variable(variableName, settable); 1073 if (variable == NULL) 1074 return B_ENTRY_NOT_FOUND; 1075 1076 *value = *variable; 1077 return B_OK; 1078 } 1079 1080 1081 status_t 1082 arch_debug_init(kernel_args *args) 1083 { 1084 // at this stage, the debugger command system is alive 1085 1086 add_debugger_command("where", &stack_trace, "Same as \"sc\""); 1087 add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)"); 1088 add_debugger_command("sc", &stack_trace, 1089 "Stack crawl for current thread (or any other)"); 1090 add_debugger_command("iframe", &dump_iframes, 1091 "Dump iframes for the specified thread"); 1092 add_debugger_command("call", &show_call, "Show call with arguments"); 1093 add_debugger_command_etc("in_context", &cmd_in_context, 1094 "Executes a command in the context of a given thread", 1095 "<thread ID> <command> ...\n" 1096 "Executes a command in the context of a given thread.\n", 1097 B_KDEBUG_DONT_PARSE_ARGUMENTS); 1098 1099 return B_NO_ERROR; 1100 } 1101 1102