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