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