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[%" B_PRId32 "D", 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[%" B_PRId32 "D", 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[%" B_PRId32 "D", 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[%" B_PRId32 "D", 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[%" B_PRId32 "D", 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[%" B_PRId32 "D", length - position); 612 // reposition cursor 613 currentHistoryLine = historyLine; 614 615 break; 616 } 617 case 'H': // home 618 { 619 if (position > 0) { 620 kprintf("\x1b[%" B_PRId32 "D", position); 621 position = 0; 622 } 623 break; 624 } 625 case 'F': // end 626 { 627 if (position < length) { 628 kprintf("\x1b[%" B_PRId32 "C", 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 %" B_PRId32 "\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 %" B_PRId32 "\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 %" B_PRId32 " \"%.64s\" running on CPU %" B_PRId32 "\n", 840 thread->id, 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 %" B_PRId32 "\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 %" B_PRId32 "\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)(void *)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.Pointer(), 1406 args->debug_size, false); 1407 } 1408 1409 char revisionBuffer[64]; 1410 length = snprintf(revisionBuffer, sizeof(revisionBuffer), 1411 "Welcome to syslog debug output!\nHaiku revision: %s\n", 1412 get_haiku_revision()); 1413 syslog_write(revisionBuffer, 1414 std::min(length, (int32)sizeof(revisionBuffer) - 1), false); 1415 1416 add_debugger_command_etc("syslog", &cmd_dump_syslog, 1417 "Dumps the syslog buffer.", 1418 "[ \"-n\" ] [ \"-k\" ]\n" 1419 "Dumps the whole syslog buffer, or, if -k is specified, only " 1420 "the part that hasn't been sent yet.\n", 0); 1421 1422 return B_OK; 1423 1424 err2: 1425 free(sSyslogMessage); 1426 err1: 1427 sSyslogOutputEnabled = false; 1428 sSyslogBuffer = NULL; 1429 return status; 1430 } 1431 1432 1433 static status_t 1434 syslog_init(struct kernel_args* args) 1435 { 1436 if (!args->keep_debug_output_buffer || args->debug_output == NULL) 1437 return B_OK; 1438 1439 sSyslogBuffer = create_ring_buffer_etc(args->debug_output, args->debug_size, 1440 RING_BUFFER_INIT_FROM_BUFFER); 1441 sDebugSyslog = true; 1442 1443 return B_OK; 1444 } 1445 1446 1447 static void 1448 debug_memcpy_trampoline(void* _parameters) 1449 { 1450 debug_memcpy_parameters* parameters = (debug_memcpy_parameters*)_parameters; 1451 memcpy(parameters->to, parameters->from, parameters->size); 1452 } 1453 1454 1455 static void 1456 debug_strlcpy_trampoline(void* _parameters) 1457 { 1458 debug_strlcpy_parameters* parameters 1459 = (debug_strlcpy_parameters*)_parameters; 1460 parameters->result = strlcpy(parameters->to, parameters->from, 1461 parameters->size); 1462 } 1463 1464 1465 void 1466 call_modules_hook(bool enter) 1467 { 1468 uint32 index = 0; 1469 while (index < kMaxDebuggerModules && sDebuggerModules[index] != NULL) { 1470 debugger_module_info* module = sDebuggerModules[index]; 1471 1472 if (enter && module->enter_debugger != NULL) 1473 module->enter_debugger(); 1474 else if (!enter && module->exit_debugger != NULL) 1475 module->exit_debugger(); 1476 1477 index++; 1478 } 1479 } 1480 1481 1482 //! Must be called with the sSpinlock held. 1483 static void 1484 debug_output(const char* string, int32 length, bool notifySyslog) 1485 { 1486 if (length >= OUTPUT_BUFFER_SIZE) 1487 length = OUTPUT_BUFFER_SIZE - 1; 1488 1489 if (length > 1 && string[length - 1] == '\n' 1490 && strncmp(string, sLastOutputBuffer, length) == 0) { 1491 sMessageRepeatCount++; 1492 sMessageRepeatLastTime = system_time(); 1493 if (sMessageRepeatFirstTime == 0) 1494 sMessageRepeatFirstTime = sMessageRepeatLastTime; 1495 } else { 1496 flush_pending_repeats(notifySyslog); 1497 1498 if (sSerialDebugEnabled) 1499 arch_debug_serial_puts(string); 1500 if (sSyslogOutputEnabled) 1501 syslog_write(string, length, notifySyslog); 1502 if (sBlueScreenEnabled || sDebugScreenEnabled) 1503 blue_screen_puts(string); 1504 if (sSerialDebugEnabled) { 1505 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1506 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) 1507 sDebuggerModules[i]->debugger_puts(string, length); 1508 } 1509 } 1510 1511 memcpy(sLastOutputBuffer, string, length); 1512 sLastOutputBuffer[length] = 0; 1513 } 1514 } 1515 1516 1517 //! Must be called with the sSpinlock held. 1518 static void 1519 flush_pending_repeats(bool notifySyslog) 1520 { 1521 if (sMessageRepeatCount <= 0) 1522 return; 1523 1524 if (sMessageRepeatCount > 1) { 1525 static char temp[40]; 1526 size_t length = snprintf(temp, sizeof(temp), 1527 "Last message repeated %" B_PRId32 " times.\n", sMessageRepeatCount); 1528 length = std::min(length, sizeof(temp) - 1); 1529 1530 if (sSerialDebugEnabled) 1531 arch_debug_serial_puts(temp); 1532 if (sSyslogOutputEnabled) 1533 syslog_write(temp, length, notifySyslog); 1534 if (sBlueScreenEnabled || sDebugScreenEnabled) 1535 blue_screen_puts(temp); 1536 if (sSerialDebugEnabled) { 1537 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1538 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) 1539 sDebuggerModules[i]->debugger_puts(temp, length); 1540 } 1541 } 1542 } else { 1543 // if we only have one repeat just reprint the last buffer 1544 size_t length = strlen(sLastOutputBuffer); 1545 1546 if (sSerialDebugEnabled) 1547 arch_debug_serial_puts(sLastOutputBuffer); 1548 if (sSyslogOutputEnabled) 1549 syslog_write(sLastOutputBuffer, length, notifySyslog); 1550 if (sBlueScreenEnabled || sDebugScreenEnabled) 1551 blue_screen_puts(sLastOutputBuffer); 1552 if (sSerialDebugEnabled) { 1553 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1554 if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_puts) { 1555 sDebuggerModules[i]->debugger_puts(sLastOutputBuffer, 1556 length); 1557 } 1558 } 1559 } 1560 } 1561 1562 sMessageRepeatFirstTime = 0; 1563 sMessageRepeatCount = 0; 1564 } 1565 1566 1567 static void 1568 check_pending_repeats(void* /*data*/, int /*iteration*/) 1569 { 1570 if (sMessageRepeatCount > 0 1571 && (system_time() - sMessageRepeatLastTime > 1000000 1572 || system_time() - sMessageRepeatFirstTime > 3000000)) { 1573 cpu_status state = disable_interrupts(); 1574 acquire_spinlock(&sSpinlock); 1575 1576 flush_pending_repeats(true); 1577 1578 release_spinlock(&sSpinlock); 1579 restore_interrupts(state); 1580 } 1581 } 1582 1583 1584 static void 1585 dprintf_args(const char* format, va_list args, bool notifySyslog) 1586 { 1587 if (are_interrupts_enabled()) { 1588 MutexLocker locker(sOutputLock); 1589 1590 int32 length = vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, format, 1591 args); 1592 length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1); 1593 1594 InterruptsSpinLocker _(sSpinlock); 1595 debug_output(sOutputBuffer, length, notifySyslog); 1596 } else { 1597 InterruptsSpinLocker _(sSpinlock); 1598 1599 int32 length = vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE, 1600 format, args); 1601 length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1); 1602 1603 debug_output(sInterruptOutputBuffer, length, notifySyslog); 1604 } 1605 } 1606 1607 1608 // #pragma mark - private kernel API 1609 1610 1611 bool 1612 debug_screen_output_enabled(void) 1613 { 1614 return sDebugScreenEnabled; 1615 } 1616 1617 1618 void 1619 debug_stop_screen_debug_output(void) 1620 { 1621 sDebugScreenEnabled = false; 1622 } 1623 1624 1625 bool 1626 debug_debugger_running(void) 1627 { 1628 return sDebuggerOnCPU != -1; 1629 } 1630 1631 1632 void 1633 debug_puts(const char* string, int32 length) 1634 { 1635 InterruptsSpinLocker _(sSpinlock); 1636 debug_output(string, length, true); 1637 } 1638 1639 1640 void 1641 debug_early_boot_message(const char* string) 1642 { 1643 arch_debug_serial_early_boot_message(string); 1644 } 1645 1646 1647 void 1648 debug_init(kernel_args* args) 1649 { 1650 new(&gDefaultDebugOutputFilter) DefaultDebugOutputFilter; 1651 1652 syslog_init(args); 1653 1654 debug_paranoia_init(); 1655 arch_debug_console_init(args); 1656 } 1657 1658 1659 void 1660 debug_init_post_vm(kernel_args* args) 1661 { 1662 add_debugger_command_etc("cpu", &cmd_switch_cpu, 1663 "Switches to another CPU.", 1664 "<cpu>\n" 1665 "Switches to CPU with the index <cpu>.\n", 0); 1666 add_debugger_command_etc("message", &cmd_dump_kdl_message, 1667 "Reprint the message printed when entering KDL", 1668 "\n" 1669 "Reprints the message printed when entering KDL.\n", 0); 1670 add_debugger_command_etc("panic_commands", &cmd_execute_panic_commands, 1671 "Execute commands associated with the panic() that caused " 1672 "entering KDL", 1673 "\n" 1674 "Executes the commands associated with the panic() that caused " 1675 "entering KDL.\n", 0); 1676 1677 debug_builtin_commands_init(); 1678 arch_debug_init(args); 1679 1680 debug_heap_init(); 1681 debug_variables_init(); 1682 frame_buffer_console_init(args); 1683 arch_debug_console_init_settings(args); 1684 tracing_init(); 1685 } 1686 1687 1688 void 1689 debug_init_post_settings(struct kernel_args* args) 1690 { 1691 // get debug settings 1692 1693 sSerialDebugEnabled = get_safemode_boolean("serial_debug_output", 1694 sSerialDebugEnabled); 1695 sSyslogOutputEnabled = get_safemode_boolean("syslog_debug_output", 1696 sSyslogOutputEnabled); 1697 sBlueScreenOutput = get_safemode_boolean("bluescreen", true); 1698 sEmergencyKeysEnabled = get_safemode_boolean("emergency_keys", 1699 sEmergencyKeysEnabled); 1700 sDebugScreenEnabled = get_safemode_boolean("debug_screen", false); 1701 1702 if ((sBlueScreenOutput || sDebugScreenEnabled) 1703 && blue_screen_init() != B_OK) 1704 sBlueScreenOutput = sDebugScreenEnabled = false; 1705 1706 if (sDebugScreenEnabled) 1707 blue_screen_enter(true); 1708 1709 syslog_init_post_vm(args); 1710 } 1711 1712 1713 void 1714 debug_init_post_modules(struct kernel_args* args) 1715 { 1716 void* cookie; 1717 1718 // check for dupped lines every 10/10 second 1719 register_kernel_daemon(check_pending_repeats, NULL, 10); 1720 1721 syslog_init_post_threads(); 1722 1723 // load kernel debugger addons 1724 1725 static const char* kDemanglePrefix = "debugger/demangle/"; 1726 1727 cookie = open_module_list("debugger"); 1728 uint32 count = 0; 1729 while (count < kMaxDebuggerModules) { 1730 char name[B_FILE_NAME_LENGTH]; 1731 size_t nameLength = sizeof(name); 1732 1733 if (read_next_module_name(cookie, name, &nameLength) != B_OK) 1734 break; 1735 1736 // get demangle module, if any 1737 if (!strncmp(name, kDemanglePrefix, strlen(kDemanglePrefix))) { 1738 if (sDemangleModule == NULL) 1739 get_module(name, (module_info**)&sDemangleModule); 1740 continue; 1741 } 1742 1743 if (get_module(name, (module_info**)&sDebuggerModules[count]) == B_OK) { 1744 dprintf("kernel debugger extension \"%s\": loaded\n", name); 1745 count++; 1746 } else 1747 dprintf("kernel debugger extension \"%s\": failed to load\n", name); 1748 } 1749 close_module_list(cookie); 1750 1751 frame_buffer_console_init_post_modules(args); 1752 } 1753 1754 1755 void 1756 debug_set_page_fault_info(addr_t faultAddress, addr_t pc, uint32 flags) 1757 { 1758 sPageFaultInfo.fault_address = faultAddress; 1759 sPageFaultInfo.pc = pc; 1760 sPageFaultInfo.flags = flags; 1761 } 1762 1763 1764 debug_page_fault_info* 1765 debug_get_page_fault_info() 1766 { 1767 return &sPageFaultInfo; 1768 } 1769 1770 1771 void 1772 debug_trap_cpu_in_kdl(int32 cpu, bool returnIfHandedOver) 1773 { 1774 InterruptsLocker locker; 1775 1776 // return, if we've been called recursively (we call 1777 // smp_intercpu_int_handler() below) 1778 if (sCPUTrapped[cpu]) 1779 return; 1780 1781 arch_debug_save_registers(&sDebugRegisters[cpu]); 1782 1783 sCPUTrapped[cpu] = true; 1784 1785 while (sInDebugger != 0) { 1786 if (sHandOverKDL && sHandOverKDLToCPU == cpu) { 1787 if (returnIfHandedOver) 1788 break; 1789 1790 kernel_debugger_internal(NULL, NULL, 1791 sCurrentKernelDebuggerMessageArgs, cpu); 1792 } else 1793 smp_intercpu_int_handler(cpu); 1794 } 1795 1796 sCPUTrapped[cpu] = false; 1797 } 1798 1799 1800 void 1801 debug_double_fault(int32 cpu) 1802 { 1803 kernel_debugger_internal("Double Fault!", NULL, 1804 sCurrentKernelDebuggerMessageArgs, cpu); 1805 } 1806 1807 1808 bool 1809 debug_emergency_key_pressed(char key) 1810 { 1811 if (!sEmergencyKeysEnabled) 1812 return false; 1813 1814 if (key == 'd') { 1815 kernel_debugger("Keyboard Requested Halt."); 1816 return true; 1817 } 1818 1819 // Broadcast to the kernel debugger modules 1820 1821 for (uint32 i = 0; i < kMaxDebuggerModules; i++) { 1822 if (sDebuggerModules[i] && sDebuggerModules[i]->emergency_key_pressed) { 1823 if (sDebuggerModules[i]->emergency_key_pressed(key)) 1824 return true; 1825 } 1826 } 1827 1828 return false; 1829 } 1830 1831 1832 /*! Verifies that the complete given memory range is accessible in the current 1833 context. 1834 1835 Invoked in the kernel debugger only. 1836 1837 \param address The start address of the memory range to be checked. 1838 \param size The size of the memory range to be checked. 1839 \param protection The area protection for which to check. Valid is a bitwise 1840 or of one or more of \c B_KERNEL_READ_AREA or \c B_KERNEL_WRITE_AREA. 1841 \return \c true, if the complete memory range can be accessed in all ways 1842 specified by \a protection, \c false otherwise. 1843 */ 1844 bool 1845 debug_is_kernel_memory_accessible(addr_t address, size_t size, 1846 uint32 protection) 1847 { 1848 addr_t endAddress = ROUNDUP(address + size, B_PAGE_SIZE); 1849 address = ROUNDDOWN(address, B_PAGE_SIZE); 1850 1851 if (!IS_KERNEL_ADDRESS(address) || endAddress < address) 1852 return false; 1853 1854 for (; address < endAddress; address += B_PAGE_SIZE) { 1855 if (!arch_vm_translation_map_is_kernel_page_accessible(address, 1856 protection)) { 1857 return false; 1858 } 1859 } 1860 1861 return true; 1862 } 1863 1864 1865 /*! Calls a function in a setjmp() + fault handler context. 1866 May only be used in the kernel debugger. 1867 1868 \param jumpBuffer Buffer to be used for setjmp()/longjmp(). 1869 \param function The function to be called. 1870 \param parameter The parameter to be passed to the function to be called. 1871 \return 1872 - \c 0, when the function executed without causing a page fault or 1873 calling longjmp(). 1874 - \c 1, when the function caused a page fault. 1875 - Any other value the function passes to longjmp(). 1876 */ 1877 int 1878 debug_call_with_fault_handler(jmp_buf jumpBuffer, void (*function)(void*), 1879 void* parameter) 1880 { 1881 // save current fault handler 1882 cpu_ent* cpu = gCPU + sDebuggerOnCPU; 1883 addr_t oldFaultHandler = cpu->fault_handler; 1884 addr_t oldFaultHandlerStackPointer = cpu->fault_handler_stack_pointer; 1885 1886 int result = setjmp(jumpBuffer); 1887 if (result == 0) { 1888 arch_debug_call_with_fault_handler(cpu, jumpBuffer, function, 1889 parameter); 1890 } 1891 1892 // restore old fault handler 1893 cpu->fault_handler = oldFaultHandler; 1894 cpu->fault_handler_stack_pointer = oldFaultHandlerStackPointer; 1895 1896 return result; 1897 } 1898 1899 1900 /*! Similar to user_memcpy(), but can only be invoked from within the kernel 1901 debugger (and must not be used outside). 1902 The supplied \a teamID specifies the address space in which to interpret 1903 the addresses. It can be \c B_CURRENT_TEAM for debug_get_debugged_thread(), 1904 or any valid team ID. If the addresses are both kernel addresses, the 1905 argument is ignored and the current address space is used. 1906 */ 1907 status_t 1908 debug_memcpy(team_id teamID, void* to, const void* from, size_t size) 1909 { 1910 // don't allow address overflows 1911 if ((addr_t)from + size < (addr_t)from || (addr_t)to + size < (addr_t)to) 1912 return B_BAD_ADDRESS; 1913 1914 // Try standard memcpy() with fault handler, if the addresses can be 1915 // interpreted in the current address space. 1916 if ((IS_KERNEL_ADDRESS(from) && IS_KERNEL_ADDRESS(to)) 1917 || debug_is_debugged_team(teamID)) { 1918 debug_memcpy_parameters parameters = {to, from, size}; 1919 1920 if (debug_call_with_fault_handler(gCPU[sDebuggerOnCPU].fault_jump_buffer, 1921 &debug_memcpy_trampoline, ¶meters) == 0) { 1922 return B_OK; 1923 } 1924 } 1925 1926 // Try harder. The pages of the respective memory could be unmapped but 1927 // still exist in a cache (the page daemon does that with inactive pages). 1928 while (size > 0) { 1929 uint8 buffer[32]; 1930 size_t toCopy = std::min(size, sizeof(buffer)); 1931 1932 // restrict the size so we don't cross page boundaries 1933 if (((addr_t)from + toCopy) % B_PAGE_SIZE < toCopy) 1934 toCopy -= ((addr_t)from + toCopy) % B_PAGE_SIZE; 1935 if (((addr_t)to + toCopy) % B_PAGE_SIZE < toCopy) 1936 toCopy -= ((addr_t)to + toCopy) % B_PAGE_SIZE; 1937 1938 if (vm_debug_copy_page_memory(teamID, (void*)from, buffer, toCopy, 1939 false) != B_OK 1940 || vm_debug_copy_page_memory(teamID, to, buffer, toCopy, true) 1941 != B_OK) { 1942 return B_BAD_ADDRESS; 1943 } 1944 1945 from = (const uint8*)from + toCopy; 1946 to = (uint8*)to + toCopy; 1947 size -= toCopy; 1948 } 1949 1950 return B_OK; 1951 } 1952 1953 1954 /*! Similar to user_strlcpy(), but can only be invoked from within the kernel 1955 debugger (and must not be used outside). 1956 The supplied \a teamID specifies the address space in which to interpret 1957 the addresses. It can be \c B_CURRENT_TEAM for debug_get_debugged_thread(), 1958 or any valid team ID. If the addresses are both kernel addresses, the 1959 argument is ignored and the current address space is used. 1960 */ 1961 ssize_t 1962 debug_strlcpy(team_id teamID, char* to, const char* from, size_t size) 1963 { 1964 if (from == NULL || (to == NULL && size > 0)) 1965 return B_BAD_ADDRESS; 1966 1967 // limit size to avoid address overflows 1968 size_t maxSize = std::min(size, 1969 ~(addr_t)0 - std::max((addr_t)from, (addr_t)to) + 1); 1970 // NOTE: Since strlcpy() determines the length of \a from, the source 1971 // address might still overflow. 1972 1973 // Try standard strlcpy() with fault handler, if the addresses can be 1974 // interpreted in the current address space. 1975 if ((IS_KERNEL_ADDRESS(from) && IS_KERNEL_ADDRESS(to)) 1976 || debug_is_debugged_team(teamID)) { 1977 debug_strlcpy_parameters parameters = {to, from, maxSize}; 1978 1979 if (debug_call_with_fault_handler( 1980 gCPU[sDebuggerOnCPU].fault_jump_buffer, 1981 &debug_strlcpy_trampoline, ¶meters) == 0) { 1982 // If we hit the address overflow boundary, fail. 1983 if (parameters.result >= maxSize && maxSize < size) 1984 return B_BAD_ADDRESS; 1985 1986 return parameters.result; 1987 } 1988 } 1989 1990 // Try harder. The pages of the respective memory could be unmapped but 1991 // still exist in a cache (the page daemon does that with inactive pages). 1992 size_t totalLength = 0; 1993 while (maxSize > 0) { 1994 char buffer[32]; 1995 size_t toCopy = std::min(maxSize, sizeof(buffer)); 1996 1997 // restrict the size so we don't cross page boundaries 1998 if (((addr_t)from + toCopy) % B_PAGE_SIZE < toCopy) 1999 toCopy -= ((addr_t)from + toCopy) % B_PAGE_SIZE; 2000 if (((addr_t)to + toCopy) % B_PAGE_SIZE < toCopy) 2001 toCopy -= ((addr_t)to + toCopy) % B_PAGE_SIZE; 2002 2003 // copy the next part of the string from the source 2004 if (vm_debug_copy_page_memory(teamID, (void*)from, buffer, toCopy, 2005 false) != B_OK) { 2006 return B_BAD_ADDRESS; 2007 } 2008 2009 // determine the length of the part and whether we've reached the end 2010 // of the string 2011 size_t length = strnlen(buffer, toCopy); 2012 bool endOfString = length < toCopy; 2013 2014 from = (const char*)from + toCopy; 2015 totalLength += length; 2016 maxSize -= length; 2017 2018 if (endOfString) { 2019 // only copy the actual string, including the terminating null 2020 toCopy = length + 1; 2021 } 2022 2023 if (size > 0) { 2024 // We still have space left in the target buffer. 2025 if (size <= length) { 2026 // Not enough space for the complete part. Null-terminate it and 2027 // copy what we can. 2028 buffer[size - 1] = '\0'; 2029 totalLength += length - size; 2030 toCopy = size; 2031 } 2032 2033 if (vm_debug_copy_page_memory(teamID, to, buffer, toCopy, true) 2034 != B_OK) { 2035 return B_BAD_ADDRESS; 2036 } 2037 2038 to = (char*)to + toCopy; 2039 size -= toCopy; 2040 } 2041 2042 if (endOfString) 2043 return totalLength; 2044 } 2045 2046 return totalLength; 2047 } 2048 2049 2050 // #pragma mark - public API 2051 2052 2053 uint64 2054 parse_expression(const char* expression) 2055 { 2056 uint64 result; 2057 return evaluate_debug_expression(expression, &result, true) ? result : 0; 2058 } 2059 2060 2061 void 2062 panic(const char* format, ...) 2063 { 2064 va_list args; 2065 va_start(args, format); 2066 2067 cpu_status state = disable_interrupts(); 2068 2069 kernel_debugger_internal("PANIC: ", format, args, 2070 thread_get_current_thread() ? smp_get_current_cpu() : 0); 2071 2072 restore_interrupts(state); 2073 2074 va_end(args); 2075 } 2076 2077 2078 void 2079 kernel_debugger(const char* message) 2080 { 2081 cpu_status state = disable_interrupts(); 2082 2083 kernel_debugger_internal(message, NULL, sCurrentKernelDebuggerMessageArgs, 2084 smp_get_current_cpu()); 2085 2086 restore_interrupts(state); 2087 } 2088 2089 2090 bool 2091 set_dprintf_enabled(bool newState) 2092 { 2093 bool oldState = sSerialDebugEnabled; 2094 sSerialDebugEnabled = newState; 2095 2096 return oldState; 2097 } 2098 2099 2100 void 2101 dprintf(const char* format, ...) 2102 { 2103 va_list args; 2104 2105 if (!sSerialDebugEnabled && !sSyslogOutputEnabled && !sBlueScreenEnabled) 2106 return; 2107 2108 va_start(args, format); 2109 dprintf_args(format, args, true); 2110 va_end(args); 2111 } 2112 2113 2114 void 2115 dprintf_no_syslog(const char* format, ...) 2116 { 2117 va_list args; 2118 2119 if (!sSerialDebugEnabled && !sBlueScreenEnabled) 2120 return; 2121 2122 va_start(args, format); 2123 dprintf_args(format, args, false); 2124 va_end(args); 2125 } 2126 2127 2128 /*! Similar to dprintf() but thought to be used in the kernel 2129 debugger only (it doesn't lock). 2130 */ 2131 void 2132 kprintf(const char* format, ...) 2133 { 2134 if (sDebugOutputFilter != NULL) { 2135 va_list args; 2136 va_start(args, format); 2137 sDebugOutputFilter->Print(format, args); 2138 va_end(args); 2139 } 2140 } 2141 2142 2143 void 2144 kprintf_unfiltered(const char* format, ...) 2145 { 2146 va_list args; 2147 va_start(args, format); 2148 gDefaultDebugOutputFilter.Print(format, args); 2149 va_end(args); 2150 } 2151 2152 2153 const char* 2154 debug_demangle_symbol(const char* symbol, char* buffer, size_t bufferSize, 2155 bool* _isObjectMethod) 2156 { 2157 if (sDemangleModule != NULL && sDemangleModule->demangle_symbol != NULL) { 2158 return sDemangleModule->demangle_symbol(symbol, buffer, bufferSize, 2159 _isObjectMethod); 2160 } 2161 2162 if (_isObjectMethod != NULL) 2163 *_isObjectMethod = false; 2164 2165 return symbol; 2166 } 2167 2168 2169 status_t 2170 debug_get_next_demangled_argument(uint32* _cookie, const char* symbol, 2171 char* name, size_t nameSize, int32* _type, size_t* _argumentLength) 2172 { 2173 if (sDemangleModule != NULL && sDemangleModule->get_next_argument != NULL) { 2174 return sDemangleModule->get_next_argument(_cookie, symbol, name, 2175 nameSize, _type, _argumentLength); 2176 } 2177 2178 return B_NOT_SUPPORTED; 2179 } 2180 2181 2182 struct arch_debug_registers* 2183 debug_get_debug_registers(int32 cpu) 2184 { 2185 if (cpu < 0 || cpu > smp_get_num_cpus()) 2186 return NULL; 2187 2188 return &sDebugRegisters[cpu]; 2189 } 2190 2191 2192 Thread* 2193 debug_set_debugged_thread(Thread* thread) 2194 { 2195 Thread* previous = sDebuggedThread; 2196 sDebuggedThread = thread; 2197 return previous; 2198 } 2199 2200 2201 Thread* 2202 debug_get_debugged_thread() 2203 { 2204 return sDebuggedThread != NULL 2205 ? sDebuggedThread : thread_get_current_thread(); 2206 } 2207 2208 2209 /*! Returns whether the supplied team ID refers to the same team the currently 2210 debugged thread (debug_get_debugged_thread()) belongs to. 2211 Always returns \c true, if \c B_CURRENT_TEAM is given. 2212 */ 2213 bool 2214 debug_is_debugged_team(team_id teamID) 2215 { 2216 if (teamID == B_CURRENT_TEAM) 2217 return true; 2218 2219 Thread* thread = debug_get_debugged_thread(); 2220 return thread != NULL && thread->team != NULL 2221 && thread->team->id == teamID; 2222 } 2223 2224 2225 // #pragma mark - 2226 // userland syscalls 2227 2228 2229 status_t 2230 _user_kernel_debugger(const char *userMessage) 2231 { 2232 if (geteuid() != 0) 2233 return B_NOT_ALLOWED; 2234 2235 char message[512]; 2236 strcpy(message, "USER: "); 2237 size_t len = strlen(message); 2238 2239 if (userMessage == NULL || !IS_USER_ADDRESS(userMessage) 2240 || user_strlcpy(message + len, userMessage, sizeof(message) - len) 2241 < 0) { 2242 return B_BAD_ADDRESS; 2243 } 2244 2245 kernel_debugger(message); 2246 return B_OK; 2247 } 2248 2249 2250 void 2251 _user_debug_output(const char* userString) 2252 { 2253 if (!sSerialDebugEnabled && !sSyslogOutputEnabled) 2254 return; 2255 2256 if (!IS_USER_ADDRESS(userString)) 2257 return; 2258 2259 char string[512]; 2260 int32 length; 2261 do { 2262 length = user_strlcpy(string, userString, sizeof(string)); 2263 if (length <= 0) 2264 break; 2265 debug_puts(string, length); 2266 userString += sizeof(string) - 1; 2267 } while (length >= (ssize_t)sizeof(string)); 2268 } 2269 2270 2271 void 2272 dump_block(const char* buffer, int size, const char* prefix) 2273 { 2274 const int DUMPED_BLOCK_SIZE = 16; 2275 int i; 2276 2277 for (i = 0; i < size;) { 2278 int start = i; 2279 2280 dprintf("%s%04x ", prefix, i); 2281 for (; i < start + DUMPED_BLOCK_SIZE; i++) { 2282 if (!(i % 4)) 2283 dprintf(" "); 2284 2285 if (i >= size) 2286 dprintf(" "); 2287 else 2288 dprintf("%02x", *(unsigned char*)(buffer + i)); 2289 } 2290 dprintf(" "); 2291 2292 for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) { 2293 if (i < size) { 2294 char c = buffer[i]; 2295 2296 if (c < 30) 2297 dprintf("."); 2298 else 2299 dprintf("%c", c); 2300 } else 2301 break; 2302 } 2303 dprintf("\n"); 2304 } 2305 } 2306