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