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