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