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