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