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