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