xref: /haiku/src/system/libroot/os/debug.c (revision 44b5d72b5aeb8bba2c348c27022e7cfe1c96f456)
15af32e75SAxel Dörfler /*
22da9a412SAxel Dörfler  * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
35af32e75SAxel Dörfler  * Distributed under the terms of the MIT License.
45af32e75SAxel Dörfler  */
55af32e75SAxel Dörfler 
65af32e75SAxel Dörfler 
75af32e75SAxel Dörfler #include <debugger.h>
85af32e75SAxel Dörfler #include <OS.h>
95af32e75SAxel Dörfler #include <Debug.h>
105af32e75SAxel Dörfler #include "syscalls.h"
115af32e75SAxel Dörfler 
125af32e75SAxel Dörfler #include <stdio.h>
135af32e75SAxel Dörfler #include <stdlib.h>
145af32e75SAxel Dörfler #include <string.h>
155af32e75SAxel Dörfler 
165af32e75SAxel Dörfler 
175af32e75SAxel Dörfler typedef struct debug_string_entry {
185af32e75SAxel Dörfler 	const char	*string;
195af32e75SAxel Dörfler 	uint32		code;
205af32e75SAxel Dörfler } debug_string_entry;
215af32e75SAxel Dörfler 
225af32e75SAxel Dörfler static const debug_string_entry sDebugMessageStrings[] = {
235af32e75SAxel Dörfler 	{ "Thread not running",	B_DEBUGGER_MESSAGE_THREAD_DEBUGGED },
245af32e75SAxel Dörfler 	{ "Debugger call",		B_DEBUGGER_MESSAGE_DEBUGGER_CALL },
255af32e75SAxel Dörfler 	{ "Breakpoint hit",		B_DEBUGGER_MESSAGE_BREAKPOINT_HIT },
265af32e75SAxel Dörfler 	{ "Watchpoint hit",		B_DEBUGGER_MESSAGE_WATCHPOINT_HIT },
275af32e75SAxel Dörfler 	{ "Single step",		B_DEBUGGER_MESSAGE_SINGLE_STEP },
285af32e75SAxel Dörfler 	{ "Before syscall",		B_DEBUGGER_MESSAGE_PRE_SYSCALL },
295af32e75SAxel Dörfler 	{ "After syscall",		B_DEBUGGER_MESSAGE_POST_SYSCALL },
305af32e75SAxel Dörfler 	{ "Signal received",	B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED },
315af32e75SAxel Dörfler 	{ "Exception occurred",	B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED },
325af32e75SAxel Dörfler 	{ "Team created",		B_DEBUGGER_MESSAGE_TEAM_CREATED },
335af32e75SAxel Dörfler 	{ "Team deleted",		B_DEBUGGER_MESSAGE_TEAM_DELETED },
345af32e75SAxel Dörfler 	{ "Thread created",		B_DEBUGGER_MESSAGE_THREAD_CREATED },
355af32e75SAxel Dörfler 	{ "Thread created",		B_DEBUGGER_MESSAGE_THREAD_DELETED },
365af32e75SAxel Dörfler 	{ "Image created",		B_DEBUGGER_MESSAGE_IMAGE_CREATED },
375af32e75SAxel Dörfler 	{ "Image deleted",		B_DEBUGGER_MESSAGE_IMAGE_DELETED },
385af32e75SAxel Dörfler 	{ NULL, 0 }
395af32e75SAxel Dörfler };
405af32e75SAxel Dörfler 
415af32e75SAxel Dörfler static const debug_string_entry sDebugExceptionTypeStrings[] = {
425af32e75SAxel Dörfler 	{ "Non-maskable interrupt",		B_NON_MASKABLE_INTERRUPT },
435af32e75SAxel Dörfler 	{ "Machine check exception",	B_MACHINE_CHECK_EXCEPTION },
445af32e75SAxel Dörfler 	{ "Segment violation",			B_SEGMENT_VIOLATION },
455af32e75SAxel Dörfler 	{ "Alignment exception",		B_ALIGNMENT_EXCEPTION },
465af32e75SAxel Dörfler 	{ "Divide error",				B_DIVIDE_ERROR },
475af32e75SAxel Dörfler 	{ "Overflow exception",			B_OVERFLOW_EXCEPTION },
485af32e75SAxel Dörfler 	{ "Bounds check exception",		B_BOUNDS_CHECK_EXCEPTION },
495af32e75SAxel Dörfler 	{ "Invalid opcode exception",	B_INVALID_OPCODE_EXCEPTION },
505af32e75SAxel Dörfler 	{ "Segment not present",		B_SEGMENT_NOT_PRESENT },
515af32e75SAxel Dörfler 	{ "Stack fault",				B_STACK_FAULT },
525af32e75SAxel Dörfler 	{ "General protection fault",	B_GENERAL_PROTECTION_FAULT },
535af32e75SAxel Dörfler 	{ "Floating point exception",	B_FLOATING_POINT_EXCEPTION },
545af32e75SAxel Dörfler 	{ NULL, 0 }
555af32e75SAxel Dörfler };
565af32e75SAxel Dörfler 
575af32e75SAxel Dörfler 
585af32e75SAxel Dörfler void
595af32e75SAxel Dörfler debugger(const char *message)
605af32e75SAxel Dörfler {
612da9a412SAxel Dörfler 	debug_printf("%ld: DEBUGGER: %s\n", find_thread(NULL), message);
625af32e75SAxel Dörfler 	_kern_debugger(message);
635af32e75SAxel Dörfler }
645af32e75SAxel Dörfler 
655af32e75SAxel Dörfler 
66758b1d0eSIngo Weinhold int
675af32e75SAxel Dörfler disable_debugger(int state)
685af32e75SAxel Dörfler {
695af32e75SAxel Dörfler 	return _kern_disable_debugger(state);
705af32e75SAxel Dörfler }
715af32e75SAxel Dörfler 
725af32e75SAxel Dörfler 
735af32e75SAxel Dörfler status_t
745af32e75SAxel Dörfler install_default_debugger(port_id debuggerPort)
755af32e75SAxel Dörfler {
765af32e75SAxel Dörfler 	return _kern_install_default_debugger(debuggerPort);
775af32e75SAxel Dörfler }
785af32e75SAxel Dörfler 
795af32e75SAxel Dörfler 
805af32e75SAxel Dörfler port_id
815af32e75SAxel Dörfler install_team_debugger(team_id team, port_id debuggerPort)
825af32e75SAxel Dörfler {
835af32e75SAxel Dörfler 	return _kern_install_team_debugger(team, debuggerPort);
845af32e75SAxel Dörfler }
855af32e75SAxel Dörfler 
865af32e75SAxel Dörfler 
875af32e75SAxel Dörfler status_t
885af32e75SAxel Dörfler remove_team_debugger(team_id team)
895af32e75SAxel Dörfler {
905af32e75SAxel Dörfler 	return _kern_remove_team_debugger(team);
915af32e75SAxel Dörfler }
925af32e75SAxel Dörfler 
935af32e75SAxel Dörfler 
945af32e75SAxel Dörfler status_t
955af32e75SAxel Dörfler debug_thread(thread_id thread)
965af32e75SAxel Dörfler {
975af32e75SAxel Dörfler 	return _kern_debug_thread(thread);
985af32e75SAxel Dörfler }
995af32e75SAxel Dörfler 
1005af32e75SAxel Dörfler 
1015af32e75SAxel Dörfler /**	\brief Suspends the thread until a debugger has been installed for this
1025af32e75SAxel Dörfler  *		   team.
1035af32e75SAxel Dörfler  *
1045af32e75SAxel Dörfler  *	As soon as this happens (immediately, if a debugger is already installed)
1055af32e75SAxel Dörfler  *	the thread stops for debugging. This is desirable for debuggers that spawn
1065af32e75SAxel Dörfler  *	their debugged teams via fork() and want the child to wait till they have
1075af32e75SAxel Dörfler  *	installed themselves as team debugger before continuing with exec*().
1085af32e75SAxel Dörfler  */
1095af32e75SAxel Dörfler 
1105af32e75SAxel Dörfler void
1115af32e75SAxel Dörfler wait_for_debugger(void)
1125af32e75SAxel Dörfler {
1135af32e75SAxel Dörfler 	_kern_wait_for_debugger();
1145af32e75SAxel Dörfler }
1155af32e75SAxel Dörfler 
1165af32e75SAxel Dörfler 
117*44b5d72bSIngo Weinhold status_t
118*44b5d72bSIngo Weinhold set_debugger_breakpoint(void *address)
119*44b5d72bSIngo Weinhold {
120*44b5d72bSIngo Weinhold 	return _kern_set_debugger_breakpoint(address, 0, 0, false);
121*44b5d72bSIngo Weinhold }
122*44b5d72bSIngo Weinhold 
123*44b5d72bSIngo Weinhold 
124*44b5d72bSIngo Weinhold status_t
125*44b5d72bSIngo Weinhold clear_debugger_breakpoint(void *address)
126*44b5d72bSIngo Weinhold {
127*44b5d72bSIngo Weinhold 	return _kern_clear_debugger_breakpoint(address, false);
128*44b5d72bSIngo Weinhold }
129*44b5d72bSIngo Weinhold 
130*44b5d72bSIngo Weinhold 
131*44b5d72bSIngo Weinhold status_t
132*44b5d72bSIngo Weinhold set_debugger_watchpoint(void *address, uint32 type, int32 length)
133*44b5d72bSIngo Weinhold {
134*44b5d72bSIngo Weinhold 	return _kern_set_debugger_breakpoint(address, type, length, true);
135*44b5d72bSIngo Weinhold }
136*44b5d72bSIngo Weinhold 
137*44b5d72bSIngo Weinhold 
138*44b5d72bSIngo Weinhold status_t
139*44b5d72bSIngo Weinhold clear_debugger_watchpoint(void *address)
140*44b5d72bSIngo Weinhold {
141*44b5d72bSIngo Weinhold 	return _kern_clear_debugger_breakpoint(address, true);
142*44b5d72bSIngo Weinhold }
143*44b5d72bSIngo Weinhold 
144*44b5d72bSIngo Weinhold 
1455af32e75SAxel Dörfler static void
1465af32e75SAxel Dörfler get_debug_string(const debug_string_entry *stringEntries,
1475af32e75SAxel Dörfler 	const char *defaultString, uint32 code, char *buffer, int32 bufferSize)
1485af32e75SAxel Dörfler {
1495af32e75SAxel Dörfler 	int i;
1505af32e75SAxel Dörfler 
1515af32e75SAxel Dörfler 	if (!buffer || bufferSize <= 0)
1525af32e75SAxel Dörfler 		return;
1535af32e75SAxel Dörfler 
1545af32e75SAxel Dörfler 	for (i = 0; stringEntries[i].string; i++) {
1555af32e75SAxel Dörfler 		if (stringEntries[i].code == code) {
1565af32e75SAxel Dörfler 			strlcpy(buffer, stringEntries[i].string, bufferSize);
1575af32e75SAxel Dörfler 			return;
1585af32e75SAxel Dörfler 		}
1595af32e75SAxel Dörfler 	}
1605af32e75SAxel Dörfler 
1615af32e75SAxel Dörfler 	snprintf(buffer, bufferSize, defaultString, code);
1625af32e75SAxel Dörfler }
1635af32e75SAxel Dörfler 
1645af32e75SAxel Dörfler 
1655af32e75SAxel Dörfler void
1665af32e75SAxel Dörfler get_debug_message_string(debug_debugger_message message, char *buffer,
1675af32e75SAxel Dörfler 	int32 bufferSize)
1685af32e75SAxel Dörfler {
1695af32e75SAxel Dörfler 	get_debug_string(sDebugMessageStrings, "Unknown message %lu",
1705af32e75SAxel Dörfler 		(uint32)message, buffer, bufferSize);
1715af32e75SAxel Dörfler }
1725af32e75SAxel Dörfler 
1735af32e75SAxel Dörfler 
1745af32e75SAxel Dörfler void
1755af32e75SAxel Dörfler get_debug_exception_string(debug_exception_type exception, char *buffer,
1765af32e75SAxel Dörfler 	int32 bufferSize)
1775af32e75SAxel Dörfler {
1785af32e75SAxel Dörfler 	get_debug_string(sDebugExceptionTypeStrings, "Unknown exception %lu",
1795af32e75SAxel Dörfler 		(uint32)exception, buffer, bufferSize);
1805af32e75SAxel Dörfler }
1815af32e75SAxel Dörfler 
1825af32e75SAxel Dörfler 
1835af32e75SAxel Dörfler //	#pragma mark -
1845af32e75SAxel Dörfler //	Debug.h functions
1855af32e75SAxel Dörfler 
1865af32e75SAxel Dörfler // TODO: verify these functions
1875af32e75SAxel Dörfler // TODO: add implementations for printfs?
1885af32e75SAxel Dörfler 
1895af32e75SAxel Dörfler 
1905af32e75SAxel Dörfler bool _rtDebugFlag = false;
1915af32e75SAxel Dörfler 
1925af32e75SAxel Dörfler bool
1935af32e75SAxel Dörfler _debugFlag(void)
1945af32e75SAxel Dörfler {
1955af32e75SAxel Dörfler 	return _rtDebugFlag;
1965af32e75SAxel Dörfler }
1975af32e75SAxel Dörfler 
1985af32e75SAxel Dörfler 
1995af32e75SAxel Dörfler bool
2005af32e75SAxel Dörfler _setDebugFlag(bool flag)
2015af32e75SAxel Dörfler {
2025af32e75SAxel Dörfler 	bool previous = _rtDebugFlag;
2035af32e75SAxel Dörfler 	_rtDebugFlag = flag;
2045af32e75SAxel Dörfler 	return previous;
2055af32e75SAxel Dörfler }
2065af32e75SAxel Dörfler 
2075af32e75SAxel Dörfler 
2085af32e75SAxel Dörfler int
2095af32e75SAxel Dörfler _debugPrintf(const char *fmt, ...)
2105af32e75SAxel Dörfler {
2115af32e75SAxel Dörfler 	va_list ap;
2125af32e75SAxel Dörfler 	int ret;
2135af32e75SAxel Dörfler 
2145af32e75SAxel Dörfler 	va_start(ap, fmt);
2155af32e75SAxel Dörfler 	ret = vfprintf(stdout, fmt, ap);
2165af32e75SAxel Dörfler 	va_end(ap);
2175af32e75SAxel Dörfler 
2185af32e75SAxel Dörfler 	return ret;
2195af32e75SAxel Dörfler }
2205af32e75SAxel Dörfler 
2215af32e75SAxel Dörfler 
2225af32e75SAxel Dörfler int
2235af32e75SAxel Dörfler _sPrintf(const char *fmt, ...)
2245af32e75SAxel Dörfler {
2255af32e75SAxel Dörfler 	char buffer[1024];
2265af32e75SAxel Dörfler 	va_list ap;
2275af32e75SAxel Dörfler 	int ret;
2285af32e75SAxel Dörfler 
2295af32e75SAxel Dörfler 	va_start(ap, fmt);
2305af32e75SAxel Dörfler 	ret = vsnprintf(buffer, sizeof(buffer), fmt, ap);
2315af32e75SAxel Dörfler 	va_end(ap);
2325af32e75SAxel Dörfler 
2335af32e75SAxel Dörfler 	if (ret >= 0)
2345af32e75SAxel Dörfler 		_kern_debug_output(buffer);
2355af32e75SAxel Dörfler 
2365af32e75SAxel Dörfler 	return ret;
2375af32e75SAxel Dörfler }
2385af32e75SAxel Dörfler 
2395af32e75SAxel Dörfler 
2405af32e75SAxel Dörfler int
2415af32e75SAxel Dörfler _xdebugPrintf(const char * fmt, ...)
2425af32e75SAxel Dörfler {
2435af32e75SAxel Dörfler 	va_list ap;
2445af32e75SAxel Dörfler 	int ret;
2455af32e75SAxel Dörfler 
2465af32e75SAxel Dörfler 	va_start(ap, fmt);
2475af32e75SAxel Dörfler 	ret = vfprintf(stdout, fmt, ap);
2485af32e75SAxel Dörfler 	va_end(ap);
2495af32e75SAxel Dörfler 
2505af32e75SAxel Dörfler 	return ret;
2515af32e75SAxel Dörfler }
2525af32e75SAxel Dörfler 
2535af32e75SAxel Dörfler 
2545af32e75SAxel Dörfler int
2555af32e75SAxel Dörfler _debuggerAssert(const char * file, int line, char * message)
2565af32e75SAxel Dörfler {
2575af32e75SAxel Dörfler 	puts("*** _debuggerAssert call - not yet implemented ***");
2585af32e75SAxel Dörfler 	printf("%s:%d:%s\n", file, line, message);
2595af32e75SAxel Dörfler 	return 0;
2605af32e75SAxel Dörfler }
2615af32e75SAxel Dörfler 
2625af32e75SAxel Dörfler // TODO: Remove. Temporary debug helper.
2635af32e75SAxel Dörfler // (accidently these are more or less the same as _sPrintf())
2645af32e75SAxel Dörfler 
2655af32e75SAxel Dörfler void
2665af32e75SAxel Dörfler debug_printf(const char *format, ...)
2675af32e75SAxel Dörfler {
2685af32e75SAxel Dörfler 	va_list list;
2695af32e75SAxel Dörfler 	va_start(list, format);
2705af32e75SAxel Dörfler 
2715af32e75SAxel Dörfler 	debug_vprintf(format, list);
2725af32e75SAxel Dörfler 
2735af32e75SAxel Dörfler 	va_end(list);
2745af32e75SAxel Dörfler }
2755af32e75SAxel Dörfler 
2765af32e75SAxel Dörfler void
2775af32e75SAxel Dörfler debug_vprintf(const char *format, va_list args)
2785af32e75SAxel Dörfler {
2795af32e75SAxel Dörfler 	char buffer[1024];
2805af32e75SAxel Dörfler 	vsnprintf(buffer, sizeof(buffer), format, args);
2815af32e75SAxel Dörfler 
2825af32e75SAxel Dörfler 	_kern_debug_output(buffer);
2835af32e75SAxel Dörfler }
2845af32e75SAxel Dörfler 
2855af32e75SAxel Dörfler 
286