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