1 /* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2009, 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 /*! This file contains the debugger and debug output facilities */ 12 13 14 #include "blue_screen.h" 15 16 #include <algorithm> 17 18 #include <cpu.h> 19 #include <debug.h> 20 #include <debug_heap.h> 21 #include <debug_paranoia.h> 22 #include <driver_settings.h> 23 #include <frame_buffer_console.h> 24 #include <int.h> 25 #include <kernel.h> 26 #include <ksystem_info.h> 27 #include <safemode.h> 28 #include <smp.h> 29 #include <thread.h> 30 #include <tracing.h> 31 #include <vm.h> 32 #include <vm_translation_map.h> 33 34 #include <arch/debug_console.h> 35 #include <arch/debug.h> 36 #include <util/AutoLock.h> 37 #include <util/ring_buffer.h> 38 39 #include <syslog_daemon.h> 40 41 #include <ctype.h> 42 #include <stdarg.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <syslog.h> 47 48 #include "debug_builtin_commands.h" 49 #include "debug_commands.h" 50 #include "debug_output_filter.h" 51 #include "debug_variables.h" 52 53 54 struct debug_memcpy_parameters { 55 void* to; 56 const void* from; 57 size_t size; 58 }; 59 60 struct debug_strlcpy_parameters { 61 char* to; 62 const char* from; 63 size_t size; 64 size_t result; 65 }; 66 67 68 static const char* const kKDLPrompt = "kdebug> "; 69 70 extern "C" int kgets(char* buffer, int length); 71 72 void call_modules_hook(bool enter); 73 74 75 int dbg_register_file[B_MAX_CPU_COUNT][14]; 76 /* XXXmpetit -- must be made generic */ 77 78 static debug_page_fault_info sPageFaultInfo; 79 80 static bool sSerialDebugEnabled = true; 81 static bool sSyslogOutputEnabled = true; 82 static bool sBlueScreenEnabled = false; 83 // must always be false on startup 84 static bool sDebugScreenEnabled = false; 85 static bool sBlueScreenOutput = true; 86 static bool sEmergencyKeysEnabled = true; 87 static spinlock sSpinlock = B_SPINLOCK_INITIALIZER; 88 static int32 sDebuggerOnCPU = -1; 89 90 static sem_id sSyslogNotify = -1; 91 static struct syslog_message* sSyslogMessage; 92 static struct ring_buffer* sSyslogBuffer; 93 static bool sSyslogDropped = false; 94 95 static const char* sCurrentKernelDebuggerMessage; 96 97 #define DEFAULT_SYSLOG_BUFFER_SIZE 65536 98 #define OUTPUT_BUFFER_SIZE 1024 99 static char sOutputBuffer[OUTPUT_BUFFER_SIZE]; 100 static char sInterruptOutputBuffer[OUTPUT_BUFFER_SIZE]; 101 static char sLastOutputBuffer[OUTPUT_BUFFER_SIZE]; 102 static DebugOutputFilter* sDebugOutputFilter = NULL; 103 DefaultDebugOutputFilter gDefaultDebugOutputFilter; 104 static mutex sOutputLock = MUTEX_INITIALIZER("debug output"); 105 106 static void flush_pending_repeats(bool syslogOutput); 107 static void check_pending_repeats(void* data, int iter); 108 109 static int64 sMessageRepeatFirstTime = 0; 110 static int64 sMessageRepeatLastTime = 0; 111 static int32 sMessageRepeatCount = 0; 112 113 static debugger_module_info* sDebuggerModules[8]; 114 static const uint32 kMaxDebuggerModules = sizeof(sDebuggerModules) 115 / sizeof(sDebuggerModules[0]); 116 117 #define LINE_BUFFER_SIZE 1024 118 #define HISTORY_SIZE 16 119 120 static char sLineBuffer[HISTORY_SIZE][LINE_BUFFER_SIZE] = { "", }; 121 static int32 sCurrentLine = 0; 122 123 static debugger_demangle_module_info* sDemangleModule; 124 125 static struct thread* sDebuggedThread; 126 static vint32 sInDebugger = 0; 127 static bool sPreviousDprintfState; 128 static volatile bool sHandOverKDL = false; 129 static vint32 sHandOverKDLToCPU = -1; 130 static bool sCPUTrapped[B_MAX_CPU_COUNT]; 131 132 133 #define distance(a, b) ((a) < (b) ? (b) - (a) : (a) - (b)) 134 135 136 // #pragma mark - DebugOutputFilter 137 138 139 DebugOutputFilter::DebugOutputFilter() 140 { 141 } 142 143 144 DebugOutputFilter::~DebugOutputFilter() 145 { 146 } 147 148 149 void 150 DebugOutputFilter::PrintString(const char* string) 151 { 152 } 153 154 155 void 156 DebugOutputFilter::Print(const char* format, va_list args) 157 { 158 } 159 160 161 void 162 DefaultDebugOutputFilter::PrintString(const char* string) 163 { 164 if (sSerialDebugEnabled) 165 arch_debug_serial_puts(string); 166 if (sBlueScreenEnabled || sDebugScreenEnabled) 167 blue_screen_puts(string); 168 169 for (uint32 i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) { 170 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) 171 sDebuggerModules[i]->debugger_puts(string, strlen(string)); 172 } 173 } 174 175 176 void 177 DefaultDebugOutputFilter::Print(const char* format, va_list args) 178 { 179 vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE, format, args); 180 flush_pending_repeats(sInDebugger == 0); 181 PrintString(sInterruptOutputBuffer); 182 } 183 184 185 // #pragma mark - 186 187 188 DebugOutputFilter* 189 set_debug_output_filter(DebugOutputFilter* filter) 190 { 191 DebugOutputFilter* oldFilter = sDebugOutputFilter; 192 sDebugOutputFilter = filter; 193 return oldFilter; 194 } 195 196 197 static void 198 kputchar(char c) 199 { 200 if (sSerialDebugEnabled) 201 arch_debug_serial_putchar(c); 202 if (sBlueScreenEnabled || sDebugScreenEnabled) 203 blue_screen_putchar(c); 204 for (uint32 i = 0; sSerialDebugEnabled && i < kMaxDebuggerModules; i++) 205 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) 206 sDebuggerModules[i]->debugger_puts(&c, sizeof(c)); 207 } 208 209 210 void 211 kputs(const char* s) 212 { 213 if (sDebugOutputFilter != NULL) 214 sDebugOutputFilter->PrintString(s); 215 } 216 217 218 void 219 kputs_unfiltered(const char* s) 220 { 221 gDefaultDebugOutputFilter.PrintString(s); 222 } 223 224 225 static void 226 insert_chars_into_line(char* buffer, int32& position, int32& length, 227 const char* chars, int32 charCount) 228 { 229 // move the following chars to make room for the ones to insert 230 if (position < length) { 231 memmove(buffer + position + charCount, buffer + position, 232 length - position); 233 } 234 235 // insert chars 236 memcpy(buffer + position, chars, charCount); 237 int32 oldPosition = position; 238 position += charCount; 239 length += charCount; 240 241 // print the new chars (and the following ones) 242 kprintf("%.*s", (int)(length - oldPosition), 243 buffer + oldPosition); 244 245 // reposition cursor, if necessary 246 if (position < length) 247 kprintf("\x1b[%ldD", length - position); 248 } 249 250 251 static void 252 insert_char_into_line(char* buffer, int32& position, int32& length, char c) 253 { 254 insert_chars_into_line(buffer, position, length, &c, 1); 255 } 256 257 258 static void 259 remove_char_from_line(char* buffer, int32& position, int32& length) 260 { 261 if (position == length) 262 return; 263 264 length--; 265 266 if (position < length) { 267 // move the subsequent chars 268 memmove(buffer + position, buffer + position + 1, length - position); 269 270 // print the rest of the line again, if necessary 271 for (int32 i = position; i < length; i++) 272 kputchar(buffer[i]); 273 } 274 275 // visually clear the last char 276 kputchar(' '); 277 278 // reposition the cursor 279 kprintf("\x1b[%ldD", length - position + 1); 280 } 281 282 283 class LineEditingHelper { 284 public: 285 virtual ~LineEditingHelper() {} 286 287 virtual void TabCompletion(char* buffer, int32 capacity, int32& position, 288 int32& length) = 0; 289 }; 290 291 292 class CommandLineEditingHelper : public LineEditingHelper { 293 public: 294 CommandLineEditingHelper() 295 { 296 } 297 298 virtual ~CommandLineEditingHelper() {} 299 300 virtual void TabCompletion(char* buffer, int32 capacity, int32& position, 301 int32& length) 302 { 303 // find the first space 304 char tmpChar = buffer[position]; 305 buffer[position] = '\0'; 306 char* firstSpace = strchr(buffer, ' '); 307 buffer[position] = tmpChar; 308 309 bool reprintLine = false; 310 311 if (firstSpace != NULL) { 312 // a complete command -- print its help 313 314 // get the command 315 tmpChar = *firstSpace; 316 *firstSpace = '\0'; 317 bool ambiguous; 318 debugger_command* command = find_debugger_command(buffer, true, ambiguous); 319 *firstSpace = tmpChar; 320 321 if (command != NULL) { 322 kputchar('\n'); 323 print_debugger_command_usage(command->name); 324 } else { 325 if (ambiguous) 326 kprintf("\nambiguous command\n"); 327 else 328 kprintf("\nno such command\n"); 329 } 330 331 reprintLine = true; 332 } else { 333 // a partial command -- look for completions 334 335 // check for possible completions 336 int32 count = 0; 337 int32 longestName = 0; 338 debugger_command* command = NULL; 339 int32 longestCommonPrefix = 0; 340 const char* previousCommandName = NULL; 341 while ((command = next_debugger_command(command, buffer, position)) 342 != NULL) { 343 count++; 344 int32 nameLength = strlen(command->name); 345 longestName = max_c(longestName, nameLength); 346 347 // updated the length of the longest common prefix of the 348 // commands 349 if (count == 1) { 350 longestCommonPrefix = longestName; 351 } else { 352 longestCommonPrefix = min_c(longestCommonPrefix, 353 nameLength); 354 355 for (int32 i = position; i < longestCommonPrefix; i++) { 356 if (previousCommandName[i] != command->name[i]) { 357 longestCommonPrefix = i; 358 break; 359 } 360 } 361 } 362 363 previousCommandName = command->name; 364 } 365 366 if (count == 0) { 367 // no possible completions 368 kprintf("\nno completions\n"); 369 reprintLine = true; 370 } else if (count == 1) { 371 // exactly one completion 372 command = next_debugger_command(NULL, buffer, position); 373 374 // check for sufficient space in the buffer 375 int32 neededSpace = longestName - position + 1; 376 // remainder of the name plus one space 377 // also consider the terminating null char 378 if (length + neededSpace + 1 >= capacity) 379 return; 380 381 insert_chars_into_line(buffer, position, length, 382 command->name + position, longestName - position); 383 insert_char_into_line(buffer, position, length, ' '); 384 } else if (longestCommonPrefix > position) { 385 // multiple possible completions with longer common prefix 386 // -- insert the remainder of the common prefix 387 388 // check for sufficient space in the buffer 389 int32 neededSpace = longestCommonPrefix - position; 390 // also consider the terminating null char 391 if (length + neededSpace + 1 >= capacity) 392 return; 393 394 insert_chars_into_line(buffer, position, length, 395 previousCommandName + position, neededSpace); 396 } else { 397 // multiple possible completions without longer common prefix 398 // -- print them all 399 kprintf("\n"); 400 reprintLine = true; 401 402 int columns = 80 / (longestName + 2); 403 debugger_command* command = NULL; 404 int column = 0; 405 while ((command = next_debugger_command(command, buffer, position)) 406 != NULL) { 407 // spacing 408 if (column > 0 && column % columns == 0) 409 kputchar('\n'); 410 column++; 411 412 kprintf(" %-*s", (int)longestName, command->name); 413 } 414 kputchar('\n'); 415 } 416 } 417 418 // reprint the editing line, if necessary 419 if (reprintLine) { 420 kprintf("%s%.*s", kKDLPrompt, (int)length, buffer); 421 if (position < length) 422 kprintf("\x1b[%ldD", length - position); 423 } 424 } 425 }; 426 427 428 static int 429 read_line(char* buffer, int32 maxLength, 430 LineEditingHelper* editingHelper = NULL) 431 { 432 int32 currentHistoryLine = sCurrentLine; 433 int32 position = 0; 434 int32 length = 0; 435 bool done = false; 436 char c = 0; 437 438 while (!done) { 439 c = kgetc(); 440 441 switch (c) { 442 case '\n': 443 case '\r': 444 buffer[length++] = '\0'; 445 kputchar('\n'); 446 done = true; 447 break; 448 case '\t': 449 { 450 if (editingHelper != NULL) { 451 editingHelper->TabCompletion(buffer, maxLength, 452 position, length); 453 } 454 break; 455 } 456 case 8: // backspace 457 if (position > 0) { 458 kputs("\x1b[1D"); // move to the left one 459 position--; 460 remove_char_from_line(buffer, position, length); 461 } 462 break; 463 case 0x1f & 'K': // CTRL-K -- clear line after current position 464 if (position < length) { 465 // clear chars 466 for (int32 i = position; i < length; i++) 467 kputchar(' '); 468 469 // reposition cursor 470 kprintf("\x1b[%ldD", length - position); 471 472 length = position; 473 } 474 break; 475 case 0x1f & 'L': // CTRL-L -- clear screen 476 if (sBlueScreenOutput) { 477 // All the following needs to be transparent for the 478 // serial debug output. I.e. after clearing the screen 479 // we have to get the on-screen line into the visual state 480 // it should have. 481 482 // clear screen 483 blue_screen_clear_screen(); 484 485 // reprint line 486 buffer[length] = '\0'; 487 blue_screen_puts(kKDLPrompt); 488 blue_screen_puts(buffer); 489 490 // reposition cursor 491 if (position < length) { 492 for (int i = length; i > position; i--) 493 blue_screen_puts("\x1b[1D"); 494 } 495 } 496 break; 497 case 27: // escape sequence 498 c = kgetc(); 499 if (c != '[') { 500 // ignore broken escape sequence 501 break; 502 } 503 c = kgetc(); 504 switch (c) { 505 case 'C': // right arrow 506 if (position < length) { 507 kputs("\x1b[1C"); // move to the right one 508 position++; 509 } 510 break; 511 case 'D': // left arrow 512 if (position > 0) { 513 kputs("\x1b[1D"); // move to the left one 514 position--; 515 } 516 break; 517 case 'A': // up arrow 518 case 'B': // down arrow 519 { 520 int32 historyLine = 0; 521 522 if (c == 'A') { 523 // up arrow 524 historyLine = currentHistoryLine - 1; 525 if (historyLine < 0) 526 historyLine = HISTORY_SIZE - 1; 527 } else { 528 // down arrow 529 if (currentHistoryLine == sCurrentLine) 530 break; 531 532 historyLine = currentHistoryLine + 1; 533 if (historyLine >= HISTORY_SIZE) 534 historyLine = 0; 535 } 536 537 // clear the history again if we're in the current line again 538 // (the buffer we get just is the current line buffer) 539 if (historyLine == sCurrentLine) { 540 sLineBuffer[historyLine][0] = '\0'; 541 } else if (sLineBuffer[historyLine][0] == '\0') { 542 // empty history lines are unused -- so bail out 543 break; 544 } 545 546 // swap the current line with something from the history 547 if (position > 0) 548 kprintf("\x1b[%ldD", position); // move to beginning of line 549 550 strcpy(buffer, sLineBuffer[historyLine]); 551 length = position = strlen(buffer); 552 kprintf("%s\x1b[K", buffer); // print the line and clear the rest 553 currentHistoryLine = historyLine; 554 break; 555 } 556 case '5': // if "5~", it's PAGE UP 557 case '6': // if "6~", it's PAGE DOWN 558 { 559 if (kgetc() != '~') 560 break; 561 562 // PAGE UP: search backward, PAGE DOWN: forward 563 int32 searchDirection = (c == '5' ? -1 : 1); 564 565 bool found = false; 566 int32 historyLine = currentHistoryLine; 567 do { 568 historyLine = (historyLine + searchDirection 569 + HISTORY_SIZE) % HISTORY_SIZE; 570 if (historyLine == sCurrentLine) 571 break; 572 573 if (strncmp(sLineBuffer[historyLine], buffer, 574 position) == 0) { 575 found = true; 576 } 577 } while (!found); 578 579 // bail out, if we've found nothing or hit an empty 580 // (i.e. unused) history line 581 if (!found || strlen(sLineBuffer[historyLine]) == 0) 582 break; 583 584 // found a suitable line -- replace the current buffer 585 // content with it 586 strcpy(buffer, sLineBuffer[historyLine]); 587 length = strlen(buffer); 588 kprintf("%s\x1b[K", buffer + position); 589 // print the line and clear the rest 590 kprintf("\x1b[%ldD", length - position); 591 // reposition cursor 592 currentHistoryLine = historyLine; 593 594 break; 595 } 596 case 'H': // home 597 { 598 if (position > 0) { 599 kprintf("\x1b[%ldD", position); 600 position = 0; 601 } 602 break; 603 } 604 case 'F': // end 605 { 606 if (position < length) { 607 kprintf("\x1b[%ldC", length - position); 608 position = length; 609 } 610 break; 611 } 612 case '3': // if "3~", it's DEL 613 { 614 if (kgetc() != '~') 615 break; 616 617 if (position < length) 618 remove_char_from_line(buffer, position, length); 619 620 break; 621 } 622 default: 623 break; 624 } 625 break; 626 case '$': 627 case '+': 628 if (!sBlueScreenOutput) { 629 /* HACK ALERT!!! 630 * 631 * If we get a $ at the beginning of the line 632 * we assume we are talking with GDB 633 */ 634 if (position == 0) { 635 strcpy(buffer, "gdb"); 636 position = 4; 637 done = true; 638 break; 639 } 640 } 641 /* supposed to fall through */ 642 default: 643 if (isprint(c)) 644 insert_char_into_line(buffer, position, length, c); 645 break; 646 } 647 648 if (length >= maxLength - 2) { 649 buffer[length++] = '\0'; 650 kputchar('\n'); 651 done = true; 652 break; 653 } 654 } 655 656 return length; 657 } 658 659 660 char 661 kgetc(void) 662 { 663 // give the kernel debugger modules a chance first 664 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 665 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_getchar) { 666 int getChar = sDebuggerModules[i]->debugger_getchar(); 667 if (getChar >= 0) 668 return (char)getChar; 669 } 670 } 671 672 if (sBlueScreenOutput) 673 return blue_screen_getchar(); 674 675 return arch_debug_serial_getchar(); 676 } 677 678 679 int 680 kgets(char* buffer, int length) 681 { 682 return read_line(buffer, length); 683 } 684 685 686 static void 687 kernel_debugger_loop(const char* message, int32 cpu) 688 { 689 int32 previousCPU = sDebuggerOnCPU; 690 sDebuggerOnCPU = cpu; 691 692 DebugAllocPool* allocPool = create_debug_alloc_pool(); 693 694 sCurrentKernelDebuggerMessage = message; 695 696 if (message) 697 kprintf("PANIC: %s\n", message); 698 699 kprintf("Welcome to Kernel Debugging Land...\n"); 700 701 // Set a few temporary debug variables and print on which CPU and in which 702 // thread we are running. 703 set_debug_variable("_cpu", sDebuggerOnCPU); 704 705 struct thread* thread = thread_get_current_thread(); 706 if (thread == NULL) { 707 kprintf("Running on CPU %ld\n", sDebuggerOnCPU); 708 } else if (!debug_is_kernel_memory_accessible((addr_t)thread, 709 sizeof(struct thread), B_KERNEL_READ_AREA)) { 710 kprintf("Running on CPU %ld\n", sDebuggerOnCPU); 711 kprintf("Current thread pointer is %p, which is an address we " 712 "can't read from.\n", thread); 713 arch_debug_unset_current_thread(); 714 } else { 715 set_debug_variable("_thread", (uint64)(addr_t)thread); 716 set_debug_variable("_threadID", thread->id); 717 718 kprintf("Thread %ld \"%.64s\" running on CPU %ld\n", thread->id, 719 thread->name, sDebuggerOnCPU); 720 721 if (thread->cpu != gCPU + cpu) { 722 kprintf("The thread's CPU pointer is %p, but should be %p.\n", 723 thread->cpu, gCPU + cpu); 724 arch_debug_unset_current_thread(); 725 } else if (thread->team != NULL) { 726 if (debug_is_kernel_memory_accessible((addr_t)thread->team, 727 sizeof(struct team), B_KERNEL_READ_AREA)) { 728 set_debug_variable("_team", (uint64)(addr_t)thread->team); 729 set_debug_variable("_teamID", thread->team->id); 730 } else { 731 kprintf("The thread's team pointer is %p, which is an " 732 "address we can't read from.\n", thread->team); 733 arch_debug_unset_current_thread(); 734 } 735 } 736 } 737 738 if (!has_debugger_command("help")) 739 arch_debug_stack_trace(); 740 741 int32 continuableLine = -1; 742 // Index of the previous command line, if the command returned 743 // B_KDEBUG_CONT, i.e. asked to be repeatable, -1 otherwise. 744 745 for (;;) { 746 CommandLineEditingHelper editingHelper; 747 kprintf(kKDLPrompt); 748 char* line = sLineBuffer[sCurrentLine]; 749 read_line(line, LINE_BUFFER_SIZE, &editingHelper); 750 751 // check, if the line is empty or whitespace only 752 bool whiteSpaceOnly = true; 753 for (int i = 0 ; line[i] != '\0'; i++) { 754 if (!isspace(line[i])) { 755 whiteSpaceOnly = false; 756 break; 757 } 758 } 759 760 if (whiteSpaceOnly) { 761 if (continuableLine < 0) 762 continue; 763 764 // the previous command can be repeated 765 sCurrentLine = continuableLine; 766 line = sLineBuffer[sCurrentLine]; 767 } 768 769 int rc = evaluate_debug_command(line); 770 771 if (rc == B_KDEBUG_QUIT) { 772 // okay, exit now. 773 break; 774 } 775 776 // If the command is continuable, remember the current line index. 777 continuableLine = (rc == B_KDEBUG_CONT ? sCurrentLine : -1); 778 779 int previousLine = sCurrentLine - 1; 780 if (previousLine < 0) 781 previousLine = HISTORY_SIZE - 1; 782 783 // Only use the next slot in the history, if the entries differ 784 if (strcmp(sLineBuffer[sCurrentLine], sLineBuffer[previousLine])) { 785 if (++sCurrentLine >= HISTORY_SIZE) 786 sCurrentLine = 0; 787 } 788 } 789 790 delete_debug_alloc_pool(allocPool); 791 792 sDebuggerOnCPU = previousCPU; 793 } 794 795 796 static void 797 enter_kernel_debugger(int32 cpu) 798 { 799 while (atomic_add(&sInDebugger, 1) > 0) { 800 // The debugger is already running, find out where... 801 if (sDebuggerOnCPU == cpu) { 802 // We are re-entering the debugger on the same CPU. 803 break; 804 } 805 806 // Some other CPU must have entered the debugger and tried to halt 807 // us. Process ICIs to ensure we get the halt request. Then we are 808 // blocking there until everyone leaves the debugger and we can 809 // try to enter it again. 810 atomic_add(&sInDebugger, -1); 811 smp_intercpu_int_handler(cpu); 812 } 813 814 arch_debug_save_registers(&dbg_register_file[cpu][0]); 815 sPreviousDprintfState = set_dprintf_enabled(true); 816 817 if (!gKernelStartup && sDebuggerOnCPU != cpu && smp_get_num_cpus() > 1) { 818 // First entry on a MP system, send a halt request to all of the other 819 // CPUs. Should they try to enter the debugger they will be cought in 820 // the loop above. 821 smp_send_broadcast_ici_interrupts_disabled(cpu, SMP_MSG_CPU_HALT, 0, 0, 822 0, NULL, SMP_MSG_FLAG_SYNC); 823 } 824 825 if (sBlueScreenOutput) { 826 if (blue_screen_enter(false) == B_OK) 827 sBlueScreenEnabled = true; 828 } 829 830 sDebugOutputFilter = &gDefaultDebugOutputFilter; 831 832 sDebuggedThread = NULL; 833 834 // sort the commands 835 sort_debugger_commands(); 836 837 call_modules_hook(true); 838 } 839 840 841 static void 842 exit_kernel_debugger() 843 { 844 call_modules_hook(false); 845 set_dprintf_enabled(sPreviousDprintfState); 846 847 sDebugOutputFilter = NULL; 848 849 sBlueScreenEnabled = false; 850 if (sDebugScreenEnabled) 851 blue_screen_enter(true); 852 853 atomic_add(&sInDebugger, -1); 854 } 855 856 857 static void 858 hand_over_kernel_debugger() 859 { 860 // Wait until the hand-over is complete. 861 // The other CPU gets our sInDebugger reference and will release it when 862 // done. Note, that there's a small race condition: the other CPU could 863 // hand over to another CPU without us noticing. Since this is only 864 // initiated by the user, it is harmless, though. 865 sHandOverKDL = true; 866 while (sHandOverKDLToCPU >= 0) 867 PAUSE(); 868 } 869 870 871 static void 872 kernel_debugger_internal(const char* message, int32 cpu) 873 { 874 while (true) { 875 if (sHandOverKDLToCPU == cpu) { 876 sHandOverKDLToCPU = -1; 877 sHandOverKDL = false; 878 } else 879 enter_kernel_debugger(cpu); 880 881 kernel_debugger_loop(message, cpu); 882 883 if (sHandOverKDLToCPU < 0) { 884 exit_kernel_debugger(); 885 break; 886 } 887 888 hand_over_kernel_debugger(); 889 890 debug_trap_cpu_in_kdl(cpu, true); 891 892 if (sHandOverKDLToCPU != cpu) 893 break; 894 } 895 } 896 897 898 static int 899 cmd_dump_kdl_message(int argc, char** argv) 900 { 901 if (sCurrentKernelDebuggerMessage) { 902 kputs(sCurrentKernelDebuggerMessage); 903 kputs("\n"); 904 } 905 906 return 0; 907 } 908 909 910 static int 911 cmd_dump_syslog(int argc, char** argv) 912 { 913 if (!sSyslogOutputEnabled) { 914 kprintf("Syslog is not enabled.\n"); 915 return 0; 916 } 917 918 bool currentOnly = false; 919 if (argc > 1) { 920 if (!strcmp(argv[1], "-n")) 921 currentOnly = true; 922 else { 923 print_debugger_command_usage(argv[0]); 924 return 0; 925 } 926 } 927 928 uint32 start = sSyslogBuffer->first; 929 size_t end = start + sSyslogBuffer->in; 930 if (!currentOnly) { 931 // Start the buffer after the current end (we don't really know if 932 // this part has been written to already). 933 start = (start + sSyslogBuffer->in) % sSyslogBuffer->size; 934 end = start + sSyslogBuffer->size; 935 } else if (!ring_buffer_readable(sSyslogBuffer)) { 936 kprintf("Syslog is empty.\n"); 937 return 0; 938 } 939 940 // break it down to lines to make it grep'able 941 942 bool newLine = false; 943 char line[256]; 944 size_t linePos = 0; 945 for (uint32 i = start; i < end; i++) { 946 char c = sSyslogBuffer->buffer[i % sSyslogBuffer->size]; 947 if (c == '\0' || (uint8)c == 0xcc) 948 continue; 949 950 line[linePos++] = c; 951 newLine = false; 952 953 if (c == '\n' || linePos == sizeof(line) - 1) { 954 newLine = c == '\n'; 955 line[linePos] = '\0'; 956 linePos = 0; 957 kprintf(line); 958 } 959 } 960 if (!newLine) 961 kprintf("\n"); 962 963 return 0; 964 } 965 966 967 static int 968 cmd_switch_cpu(int argc, char** argv) 969 { 970 if (argc > 2) { 971 print_debugger_command_usage(argv[0]); 972 return 0; 973 } 974 975 if (argc == 1) { 976 kprintf("running on CPU %ld\n", smp_get_current_cpu()); 977 return 0; 978 } 979 980 int32 newCPU = parse_expression(argv[1]); 981 if (newCPU < 0 || newCPU >= smp_get_num_cpus()) { 982 kprintf("invalid CPU index\n"); 983 return 0; 984 } 985 986 if (newCPU == smp_get_current_cpu()) { 987 kprintf("already running on CPU %ld\n", newCPU); 988 return 0; 989 } 990 991 sHandOverKDLToCPU = newCPU; 992 993 return B_KDEBUG_QUIT; 994 } 995 996 997 static status_t 998 syslog_sender(void* data) 999 { 1000 status_t error = B_BAD_PORT_ID; 1001 port_id port = -1; 1002 bool bufferPending = false; 1003 int32 length = 0; 1004 1005 while (true) { 1006 // wait for syslog data to become available 1007 acquire_sem(sSyslogNotify); 1008 1009 sSyslogMessage->when = real_time_clock(); 1010 1011 if (error == B_BAD_PORT_ID) { 1012 // last message couldn't be sent, try to locate the syslog_daemon 1013 port = find_port(SYSLOG_PORT_NAME); 1014 } 1015 1016 if (port >= B_OK) { 1017 if (!bufferPending) { 1018 // we need to have exclusive access to our syslog buffer 1019 cpu_status state = disable_interrupts(); 1020 acquire_spinlock(&sSpinlock); 1021 1022 length = ring_buffer_readable(sSyslogBuffer); 1023 if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH) 1024 length = SYSLOG_MAX_MESSAGE_LENGTH; 1025 1026 length = ring_buffer_read(sSyslogBuffer, 1027 (uint8*)sSyslogMessage->message, length); 1028 if (sSyslogDropped) { 1029 // Add drop marker - since parts had to be dropped, it's 1030 // guaranteed that we have enough space in the buffer now. 1031 ring_buffer_write(sSyslogBuffer, (uint8*)"<DROP>", 6); 1032 sSyslogDropped = false; 1033 } 1034 1035 release_spinlock(&sSpinlock); 1036 restore_interrupts(state); 1037 } 1038 1039 if (length == 0) { 1040 // the buffer we came here for might have been sent already 1041 bufferPending = false; 1042 continue; 1043 } 1044 1045 error = write_port_etc(port, SYSLOG_MESSAGE, sSyslogMessage, 1046 sizeof(struct syslog_message) + length, B_RELATIVE_TIMEOUT, 0); 1047 1048 if (error < B_OK) { 1049 // sending has failed - just wait, maybe it'll work later. 1050 bufferPending = true; 1051 continue; 1052 } 1053 1054 if (bufferPending) { 1055 // we could write the last pending buffer, try to read more 1056 // from the syslog ring buffer 1057 release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE); 1058 bufferPending = false; 1059 } 1060 } 1061 } 1062 1063 return 0; 1064 } 1065 1066 1067 static void 1068 syslog_write(const char* text, int32 length) 1069 { 1070 bool trunc = false; 1071 1072 if (sSyslogBuffer == NULL) 1073 return; 1074 1075 if ((int32)ring_buffer_writable(sSyslogBuffer) < length) { 1076 // truncate data 1077 length = ring_buffer_writable(sSyslogBuffer); 1078 1079 if (length > 8) { 1080 trunc = true; 1081 length -= 8; 1082 } else 1083 sSyslogDropped = true; 1084 } 1085 1086 ring_buffer_write(sSyslogBuffer, (uint8*)text, length); 1087 if (trunc) 1088 ring_buffer_write(sSyslogBuffer, (uint8*)"<TRUNC>", 7); 1089 1090 release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE); 1091 } 1092 1093 1094 static status_t 1095 syslog_init_post_threads(void) 1096 { 1097 if (!sSyslogOutputEnabled) 1098 return B_OK; 1099 1100 sSyslogNotify = create_sem(0, "syslog data"); 1101 if (sSyslogNotify >= B_OK) { 1102 thread_id thread = spawn_kernel_thread(syslog_sender, "syslog sender", 1103 B_LOW_PRIORITY, NULL); 1104 if (thread >= B_OK && resume_thread(thread) == B_OK) 1105 return B_OK; 1106 } 1107 1108 // initializing kernel syslog service failed -- disable it 1109 1110 sSyslogOutputEnabled = false; 1111 free(sSyslogMessage); 1112 free(sSyslogBuffer); 1113 delete_sem(sSyslogNotify); 1114 1115 return B_ERROR; 1116 } 1117 1118 1119 static status_t 1120 syslog_init(struct kernel_args* args) 1121 { 1122 status_t status; 1123 int32 length = 0; 1124 1125 if (!sSyslogOutputEnabled) 1126 return B_OK; 1127 1128 sSyslogMessage = (syslog_message*)malloc(SYSLOG_MESSAGE_BUFFER_SIZE); 1129 if (sSyslogMessage == NULL) { 1130 status = B_NO_MEMORY; 1131 goto err1; 1132 } 1133 1134 { 1135 size_t bufferSize = DEFAULT_SYSLOG_BUFFER_SIZE; 1136 void* handle = load_driver_settings("kernel"); 1137 if (handle != NULL) { 1138 const char* sizeString = get_driver_parameter(handle, 1139 "syslog_buffer_size", NULL, NULL); 1140 if (sizeString != NULL) { 1141 bufferSize = strtoul(sizeString, NULL, 0); 1142 if (bufferSize > 262144) 1143 bufferSize = 262144; 1144 else if (bufferSize < SYSLOG_MESSAGE_BUFFER_SIZE) 1145 bufferSize = SYSLOG_MESSAGE_BUFFER_SIZE; 1146 } 1147 1148 unload_driver_settings(handle); 1149 } 1150 1151 sSyslogBuffer = create_ring_buffer(bufferSize); 1152 } 1153 if (sSyslogBuffer == NULL) { 1154 status = B_NO_MEMORY; 1155 goto err2; 1156 } 1157 1158 // initialize syslog message 1159 sSyslogMessage->from = 0; 1160 sSyslogMessage->options = LOG_KERN; 1161 sSyslogMessage->priority = LOG_DEBUG; 1162 sSyslogMessage->ident[0] = '\0'; 1163 //strcpy(sSyslogMessage->ident, "KERNEL"); 1164 1165 if (args->debug_output != NULL) 1166 syslog_write((const char*)args->debug_output, args->debug_size); 1167 1168 char revisionBuffer[64]; 1169 length = snprintf(revisionBuffer, sizeof(revisionBuffer), 1170 "Welcome to syslog debug output!\nHaiku revision: %lu\n", 1171 get_haiku_revision()); 1172 syslog_write(revisionBuffer, length); 1173 1174 add_debugger_command_etc("syslog", &cmd_dump_syslog, 1175 "Dumps the syslog buffer.", 1176 "[-n]\nDumps the whole syslog buffer, or, if -n is specified, only " 1177 "the part that hasn't been sent yet.\n", 0); 1178 1179 return B_OK; 1180 1181 err2: 1182 free(sSyslogMessage); 1183 err1: 1184 sSyslogOutputEnabled = false; 1185 return status; 1186 } 1187 1188 1189 static void 1190 debug_memcpy_trampoline(void* _parameters) 1191 { 1192 debug_memcpy_parameters* parameters = (debug_memcpy_parameters*)_parameters; 1193 memcpy(parameters->to, parameters->from, parameters->size); 1194 } 1195 1196 1197 static void 1198 debug_strlcpy_trampoline(void* _parameters) 1199 { 1200 debug_strlcpy_parameters* parameters 1201 = (debug_strlcpy_parameters*)_parameters; 1202 parameters->result = strlcpy(parameters->to, parameters->from, 1203 parameters->size); 1204 } 1205 1206 1207 void 1208 call_modules_hook(bool enter) 1209 { 1210 uint32 index = 0; 1211 while (index < kMaxDebuggerModules && sDebuggerModules[index] != NULL) { 1212 debugger_module_info* module = sDebuggerModules[index]; 1213 1214 if (enter && module->enter_debugger != NULL) 1215 module->enter_debugger(); 1216 else if (!enter && module->exit_debugger != NULL) 1217 module->exit_debugger(); 1218 1219 index++; 1220 } 1221 } 1222 1223 1224 //! Must be called with the sSpinlock held. 1225 static void 1226 debug_output(const char* string, int32 length, bool syslogOutput) 1227 { 1228 if (length >= OUTPUT_BUFFER_SIZE) 1229 length = OUTPUT_BUFFER_SIZE - 1; 1230 1231 if (length > 1 && string[length - 1] == '\n' 1232 && strncmp(string, sLastOutputBuffer, length) == 0) { 1233 sMessageRepeatCount++; 1234 sMessageRepeatLastTime = system_time(); 1235 if (sMessageRepeatFirstTime == 0) 1236 sMessageRepeatFirstTime = sMessageRepeatLastTime; 1237 } else { 1238 flush_pending_repeats(syslogOutput); 1239 1240 if (sSerialDebugEnabled) 1241 arch_debug_serial_puts(string); 1242 if (sSyslogOutputEnabled && syslogOutput) 1243 syslog_write(string, length); 1244 if (sBlueScreenEnabled || sDebugScreenEnabled) 1245 blue_screen_puts(string); 1246 if (sSerialDebugEnabled) { 1247 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1248 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) 1249 sDebuggerModules[i]->debugger_puts(string, length); 1250 } 1251 } 1252 1253 memcpy(sLastOutputBuffer, string, length); 1254 sLastOutputBuffer[length] = 0; 1255 } 1256 } 1257 1258 1259 //! Must be called with the sSpinlock held. 1260 static void 1261 flush_pending_repeats(bool syslogOutput) 1262 { 1263 if (sMessageRepeatCount <= 0) 1264 return; 1265 1266 if (sMessageRepeatCount > 1) { 1267 static char temp[40]; 1268 size_t length = snprintf(temp, sizeof(temp), 1269 "Last message repeated %ld times.\n", sMessageRepeatCount); 1270 1271 if (sSerialDebugEnabled) 1272 arch_debug_serial_puts(temp); 1273 if (sSyslogOutputEnabled && syslogOutput) 1274 syslog_write(temp, length); 1275 if (sBlueScreenEnabled || sDebugScreenEnabled) 1276 blue_screen_puts(temp); 1277 if (sSerialDebugEnabled) { 1278 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1279 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) 1280 sDebuggerModules[i]->debugger_puts(temp, length); 1281 } 1282 } 1283 } else { 1284 // if we only have one repeat just reprint the last buffer 1285 size_t length = strlen(sLastOutputBuffer); 1286 1287 if (sSerialDebugEnabled) 1288 arch_debug_serial_puts(sLastOutputBuffer); 1289 if (sSyslogOutputEnabled && syslogOutput) 1290 syslog_write(sLastOutputBuffer, length); 1291 if (sBlueScreenEnabled || sDebugScreenEnabled) 1292 blue_screen_puts(sLastOutputBuffer); 1293 if (sSerialDebugEnabled) { 1294 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1295 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) { 1296 sDebuggerModules[i]->debugger_puts(sLastOutputBuffer, 1297 length); 1298 } 1299 } 1300 } 1301 } 1302 1303 sMessageRepeatFirstTime = 0; 1304 sMessageRepeatCount = 0; 1305 } 1306 1307 1308 static void 1309 check_pending_repeats(void* /*data*/, int /*iteration*/) 1310 { 1311 if (sMessageRepeatCount > 0 1312 && (system_time() - sMessageRepeatLastTime > 1000000 1313 || system_time() - sMessageRepeatFirstTime > 3000000)) { 1314 cpu_status state = disable_interrupts(); 1315 acquire_spinlock(&sSpinlock); 1316 1317 flush_pending_repeats(true); 1318 1319 release_spinlock(&sSpinlock); 1320 restore_interrupts(state); 1321 } 1322 } 1323 1324 1325 static void 1326 dprintf_args(const char* format, va_list args, bool syslogOutput) 1327 { 1328 if (are_interrupts_enabled()) { 1329 MutexLocker locker(sOutputLock); 1330 1331 int32 length = vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, 1332 format, args); 1333 1334 InterruptsSpinLocker _(sSpinlock); 1335 debug_output(sOutputBuffer, length, syslogOutput); 1336 } else { 1337 InterruptsSpinLocker _(sSpinlock); 1338 1339 int32 length = vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE, 1340 format, args); 1341 1342 debug_output(sInterruptOutputBuffer, length, syslogOutput); 1343 } 1344 } 1345 1346 1347 // #pragma mark - private kernel API 1348 1349 1350 bool 1351 debug_screen_output_enabled(void) 1352 { 1353 return sDebugScreenEnabled; 1354 } 1355 1356 1357 void 1358 debug_stop_screen_debug_output(void) 1359 { 1360 sDebugScreenEnabled = false; 1361 } 1362 1363 1364 bool 1365 debug_debugger_running(void) 1366 { 1367 return sDebuggerOnCPU != -1; 1368 } 1369 1370 1371 void 1372 debug_puts(const char* string, int32 length) 1373 { 1374 InterruptsSpinLocker _(sSpinlock); 1375 debug_output(string, length, sSyslogOutputEnabled); 1376 } 1377 1378 1379 void 1380 debug_early_boot_message(const char* string) 1381 { 1382 arch_debug_serial_early_boot_message(string); 1383 } 1384 1385 1386 status_t 1387 debug_init(kernel_args* args) 1388 { 1389 new(&gDefaultDebugOutputFilter) DefaultDebugOutputFilter; 1390 1391 debug_paranoia_init(); 1392 return arch_debug_console_init(args); 1393 } 1394 1395 1396 status_t 1397 debug_init_post_vm(kernel_args* args) 1398 { 1399 add_debugger_command_etc("cpu", &cmd_switch_cpu, 1400 "Switches to another CPU.", 1401 "<cpu>\n" 1402 "Switches to CPU with the index <cpu>.\n", 0); 1403 add_debugger_command_etc("message", &cmd_dump_kdl_message, 1404 "Reprint the message printed when entering KDL", 1405 "\n" 1406 "Reprints the message printed when entering KDL.\n", 0); 1407 1408 debug_builtin_commands_init(); 1409 1410 debug_heap_init(); 1411 debug_variables_init(); 1412 frame_buffer_console_init(args); 1413 arch_debug_console_init_settings(args); 1414 tracing_init(); 1415 1416 // get debug settings 1417 1418 sSerialDebugEnabled = get_safemode_boolean("serial_debug_output", 1419 sSerialDebugEnabled); 1420 sSyslogOutputEnabled = get_safemode_boolean("syslog_debug_output", 1421 sSyslogOutputEnabled); 1422 sBlueScreenOutput = get_safemode_boolean("bluescreen", true); 1423 sEmergencyKeysEnabled = get_safemode_boolean("emergency_keys", 1424 sEmergencyKeysEnabled); 1425 sDebugScreenEnabled = get_safemode_boolean("debug_screen", false); 1426 1427 if ((sBlueScreenOutput || sDebugScreenEnabled) 1428 && blue_screen_init() != B_OK) 1429 sBlueScreenOutput = sDebugScreenEnabled = false; 1430 1431 if (sDebugScreenEnabled) 1432 blue_screen_enter(true); 1433 1434 syslog_init(args); 1435 1436 return arch_debug_init(args); 1437 } 1438 1439 1440 status_t 1441 debug_init_post_modules(struct kernel_args* args) 1442 { 1443 void* cookie; 1444 1445 // check for dupped lines every 10/10 second 1446 register_kernel_daemon(check_pending_repeats, NULL, 10); 1447 1448 syslog_init_post_threads(); 1449 1450 // load kernel debugger addons 1451 1452 static const char* kDemanglePrefix = "debugger/demangle/"; 1453 1454 cookie = open_module_list("debugger"); 1455 uint32 count = 0; 1456 while (count < kMaxDebuggerModules) { 1457 char name[B_FILE_NAME_LENGTH]; 1458 size_t nameLength = sizeof(name); 1459 1460 if (read_next_module_name(cookie, name, &nameLength) != B_OK) 1461 break; 1462 1463 // get demangle module, if any 1464 if (!strncmp(name, kDemanglePrefix, strlen(kDemanglePrefix))) { 1465 if (sDemangleModule == NULL) 1466 get_module(name, (module_info**)&sDemangleModule); 1467 continue; 1468 } 1469 1470 if (get_module(name, (module_info**)&sDebuggerModules[count]) == B_OK) { 1471 dprintf("kernel debugger extension \"%s\": loaded\n", name); 1472 count++; 1473 } else 1474 dprintf("kernel debugger extension \"%s\": failed to load\n", name); 1475 } 1476 close_module_list(cookie); 1477 1478 return frame_buffer_console_init_post_modules(args); 1479 } 1480 1481 1482 void 1483 debug_set_page_fault_info(addr_t faultAddress, addr_t pc, uint32 flags) 1484 { 1485 sPageFaultInfo.fault_address = faultAddress; 1486 sPageFaultInfo.pc = pc; 1487 sPageFaultInfo.flags = flags; 1488 } 1489 1490 1491 debug_page_fault_info* 1492 debug_get_page_fault_info() 1493 { 1494 return &sPageFaultInfo; 1495 } 1496 1497 1498 void 1499 debug_trap_cpu_in_kdl(int32 cpu, bool returnIfHandedOver) 1500 { 1501 InterruptsLocker locker; 1502 1503 // return, if we've been called recursively (we call 1504 // smp_intercpu_int_handler() below) 1505 if (sCPUTrapped[cpu]) 1506 return; 1507 1508 sCPUTrapped[cpu] = true; 1509 1510 while (sInDebugger != 0) { 1511 if (sHandOverKDL && sHandOverKDLToCPU == cpu) { 1512 if (returnIfHandedOver) 1513 break; 1514 1515 kernel_debugger_internal(NULL, cpu); 1516 } else 1517 smp_intercpu_int_handler(cpu); 1518 } 1519 1520 sCPUTrapped[cpu] = false; 1521 } 1522 1523 1524 void 1525 debug_double_fault(int32 cpu) 1526 { 1527 kernel_debugger_internal("Double Fault!\n", cpu); 1528 } 1529 1530 1531 bool 1532 debug_emergency_key_pressed(char key) 1533 { 1534 if (!sEmergencyKeysEnabled) 1535 return false; 1536 1537 if (key == 'd') { 1538 kernel_debugger("Keyboard Requested Halt."); 1539 return true; 1540 } 1541 1542 // Broadcast to the kernel debugger modules 1543 1544 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1545 if (sDebuggerModules[i] && sDebuggerModules[i]->emergency_key_pressed) { 1546 if (sDebuggerModules[i]->emergency_key_pressed(key)) 1547 return true; 1548 } 1549 } 1550 1551 return false; 1552 } 1553 1554 1555 /*! Verifies that the complete given memory range is accessible in the current 1556 context. 1557 1558 Invoked in the kernel debugger only. 1559 1560 \param address The start address of the memory range to be checked. 1561 \param size The size of the memory range to be checked. 1562 \param protection The area protection for which to check. Valid is a bitwise 1563 or of one or more of \c B_KERNEL_READ_AREA or \c B_KERNEL_WRITE_AREA. 1564 \return \c true, if the complete memory range can be accessed in all ways 1565 specified by \a protection, \c false otherwise. 1566 */ 1567 bool 1568 debug_is_kernel_memory_accessible(addr_t address, size_t size, 1569 uint32 protection) 1570 { 1571 addr_t endAddress = ROUNDUP(address + size, B_PAGE_SIZE); 1572 address = ROUNDDOWN(address, B_PAGE_SIZE); 1573 1574 if (!IS_KERNEL_ADDRESS(address) || endAddress < address) 1575 return false; 1576 1577 for (; address < endAddress; address += B_PAGE_SIZE) { 1578 if (!arch_vm_translation_map_is_kernel_page_accessible(address, 1579 protection)) { 1580 return false; 1581 } 1582 } 1583 1584 return true; 1585 } 1586 1587 1588 /*! Calls a function in a setjmp() + fault handler context. 1589 May only be used in the kernel debugger. 1590 1591 \param jumpBuffer Buffer to be used for setjmp()/longjmp(). 1592 \param function The function to be called. 1593 \param parameter The parameter to be passed to the function to be called. 1594 \return 1595 - \c 0, when the function executed without causing a page fault or 1596 calling longjmp(). 1597 - \c 1, when the function caused a page fault. 1598 - Any other value the function passes to longjmp(). 1599 */ 1600 int 1601 debug_call_with_fault_handler(jmp_buf jumpBuffer, void (*function)(void*), 1602 void* parameter) 1603 { 1604 // save current fault handler 1605 cpu_ent* cpu = gCPU + sDebuggerOnCPU; 1606 addr_t oldFaultHandler = cpu->fault_handler; 1607 addr_t oldFaultHandlerStackPointer = cpu->fault_handler_stack_pointer; 1608 1609 int result = setjmp(jumpBuffer); 1610 if (result == 0) { 1611 arch_debug_call_with_fault_handler(cpu, jumpBuffer, function, 1612 parameter); 1613 } 1614 1615 // restore old fault handler 1616 cpu->fault_handler = oldFaultHandler; 1617 cpu->fault_handler_stack_pointer = oldFaultHandlerStackPointer; 1618 1619 return result; 1620 } 1621 1622 1623 /*! Similar to user_memcpy(), but can only be invoked from within the kernel 1624 debugger (and must not be used outside). 1625 */ 1626 status_t 1627 debug_memcpy(void* to, const void* from, size_t size) 1628 { 1629 // don't allow address overflows 1630 if ((addr_t)from + size < (addr_t)from || (addr_t)to + size < (addr_t)to) 1631 return B_BAD_ADDRESS; 1632 1633 debug_memcpy_parameters parameters = {to, from, size}; 1634 1635 if (debug_call_with_fault_handler(gCPU[sDebuggerOnCPU].fault_jump_buffer, 1636 &debug_memcpy_trampoline, ¶meters) != 0) { 1637 return B_BAD_ADDRESS; 1638 } 1639 return B_OK; 1640 } 1641 1642 1643 /*! Similar to user_strlcpy(), but can only be invoked from within the kernel 1644 debugger (and must not be used outside). 1645 */ 1646 ssize_t 1647 debug_strlcpy(char* to, const char* from, size_t size) 1648 { 1649 if (size == 0) 1650 return 0; 1651 if (from == NULL || to == NULL) 1652 return B_BAD_ADDRESS; 1653 1654 // limit size to avoid address overflows 1655 size_t maxSize = std::min(size, 1656 ~(addr_t)0 - std::max((addr_t)from, (addr_t)to) + 1); 1657 // NOTE: Since strlcpy() determines the length of \a from, the source 1658 // address might still overflow. 1659 1660 debug_strlcpy_parameters parameters = {to, from, maxSize}; 1661 1662 if (debug_call_with_fault_handler(gCPU[sDebuggerOnCPU].fault_jump_buffer, 1663 &debug_strlcpy_trampoline, ¶meters) != 0) { 1664 return B_BAD_ADDRESS; 1665 } 1666 1667 // If we hit the address overflow boundary, fail. 1668 if (parameters.result >= maxSize && maxSize < size) 1669 return B_BAD_ADDRESS; 1670 1671 return parameters.result; 1672 } 1673 1674 1675 // #pragma mark - public API 1676 1677 1678 uint64 1679 parse_expression(const char* expression) 1680 { 1681 uint64 result; 1682 return evaluate_debug_expression(expression, &result, true) ? result : 0; 1683 } 1684 1685 1686 void 1687 panic(const char* format, ...) 1688 { 1689 va_list args; 1690 char temp[128]; 1691 1692 va_start(args, format); 1693 vsnprintf(temp, sizeof(temp), format, args); 1694 va_end(args); 1695 1696 kernel_debugger(temp); 1697 } 1698 1699 1700 void 1701 kernel_debugger(const char* message) 1702 { 1703 cpu_status state = disable_interrupts(); 1704 1705 kernel_debugger_internal(message, smp_get_current_cpu()); 1706 1707 restore_interrupts(state); 1708 } 1709 1710 1711 bool 1712 set_dprintf_enabled(bool newState) 1713 { 1714 bool oldState = sSerialDebugEnabled; 1715 sSerialDebugEnabled = newState; 1716 1717 return oldState; 1718 } 1719 1720 1721 void 1722 dprintf(const char* format, ...) 1723 { 1724 va_list args; 1725 1726 if (!sSerialDebugEnabled && !sSyslogOutputEnabled && !sBlueScreenEnabled) 1727 return; 1728 1729 va_start(args, format); 1730 dprintf_args(format, args, sSyslogOutputEnabled); 1731 va_end(args); 1732 } 1733 1734 1735 void 1736 dprintf_no_syslog(const char* format, ...) 1737 { 1738 va_list args; 1739 1740 if (!sSerialDebugEnabled && !sBlueScreenEnabled) 1741 return; 1742 1743 va_start(args, format); 1744 dprintf_args(format, args, false); 1745 va_end(args); 1746 } 1747 1748 1749 /*! Similar to dprintf() but thought to be used in the kernel 1750 debugger only (it doesn't lock). 1751 */ 1752 void 1753 kprintf(const char* format, ...) 1754 { 1755 if (sDebugOutputFilter != NULL) { 1756 va_list args; 1757 va_start(args, format); 1758 sDebugOutputFilter->Print(format, args); 1759 va_end(args); 1760 } 1761 } 1762 1763 1764 void 1765 kprintf_unfiltered(const char* format, ...) 1766 { 1767 va_list args; 1768 va_start(args, format); 1769 gDefaultDebugOutputFilter.Print(format, args); 1770 va_end(args); 1771 } 1772 1773 1774 const char* 1775 debug_demangle_symbol(const char* symbol, char* buffer, size_t bufferSize, 1776 bool* _isObjectMethod) 1777 { 1778 if (sDemangleModule != NULL && sDemangleModule->demangle_symbol != NULL) { 1779 return sDemangleModule->demangle_symbol(symbol, buffer, bufferSize, 1780 _isObjectMethod); 1781 } 1782 1783 if (_isObjectMethod != NULL) 1784 *_isObjectMethod = false; 1785 1786 return symbol; 1787 } 1788 1789 1790 status_t 1791 debug_get_next_demangled_argument(uint32* _cookie, const char* symbol, 1792 char* name, size_t nameSize, int32* _type, size_t* _argumentLength) 1793 { 1794 if (sDemangleModule != NULL && sDemangleModule->get_next_argument != NULL) { 1795 return sDemangleModule->get_next_argument(_cookie, symbol, name, 1796 nameSize, _type, _argumentLength); 1797 } 1798 1799 return B_NOT_SUPPORTED; 1800 } 1801 1802 1803 struct thread* 1804 debug_set_debugged_thread(struct thread* thread) 1805 { 1806 struct thread* previous = sDebuggedThread; 1807 sDebuggedThread = thread; 1808 return previous; 1809 } 1810 1811 1812 struct thread* 1813 debug_get_debugged_thread() 1814 { 1815 return sDebuggedThread != NULL 1816 ? sDebuggedThread : thread_get_current_thread(); 1817 } 1818 1819 1820 // #pragma mark - 1821 // userland syscalls 1822 1823 1824 status_t 1825 _user_kernel_debugger(const char *userMessage) 1826 { 1827 if (geteuid() != 0) 1828 return B_NOT_ALLOWED; 1829 1830 char message[512]; 1831 strcpy(message, "USER: "); 1832 size_t len = strlen(message); 1833 1834 if (userMessage == NULL || !IS_USER_ADDRESS(userMessage) 1835 || user_strlcpy(message + len, userMessage, sizeof(message) - len) 1836 < 0) { 1837 return B_BAD_ADDRESS; 1838 } 1839 1840 kernel_debugger(message); 1841 return B_OK; 1842 } 1843 1844 1845 void 1846 _user_debug_output(const char* userString) 1847 { 1848 char string[512]; 1849 int32 length; 1850 1851 if (!sSerialDebugEnabled && !sSyslogOutputEnabled) 1852 return; 1853 1854 if (!IS_USER_ADDRESS(userString)) 1855 return; 1856 1857 do { 1858 length = user_strlcpy(string, userString, sizeof(string)); 1859 debug_puts(string, length); 1860 userString += sizeof(string) - 1; 1861 } while (length >= (ssize_t)sizeof(string)); 1862 } 1863 1864 1865 void 1866 dump_block(const char* buffer, int size, const char* prefix) 1867 { 1868 const int DUMPED_BLOCK_SIZE = 16; 1869 int i; 1870 1871 for (i = 0; i < size;) { 1872 int start = i; 1873 1874 dprintf("%s%04x ", prefix, i); 1875 for (; i < start + DUMPED_BLOCK_SIZE; i++) { 1876 if (!(i % 4)) 1877 dprintf(" "); 1878 1879 if (i >= size) 1880 dprintf(" "); 1881 else 1882 dprintf("%02x", *(unsigned char*)(buffer + i)); 1883 } 1884 dprintf(" "); 1885 1886 for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) { 1887 if (i < size) { 1888 char c = buffer[i]; 1889 1890 if (c < 30) 1891 dprintf("."); 1892 else 1893 dprintf("%c", c); 1894 } else 1895 break; 1896 } 1897 dprintf("\n"); 1898 } 1899 } 1900