15af32e75SAxel Dörfler /*
2d401b8f0SAxel Dörfler * Copyright 2002-2008, 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
57d401b8f0SAxel Dörfler bool _rtDebugFlag = true;
58d401b8f0SAxel Dörfler
595af32e75SAxel Dörfler
605af32e75SAxel Dörfler void
debugger(const char * message)615af32e75SAxel Dörfler debugger(const char *message)
625af32e75SAxel Dörfler {
63*e453c0f4SAlex Smith debug_printf("%" B_PRId32 ": DEBUGGER: %s\n", find_thread(NULL), message);
645af32e75SAxel Dörfler _kern_debugger(message);
655af32e75SAxel Dörfler }
665af32e75SAxel Dörfler
675af32e75SAxel Dörfler
68758b1d0eSIngo Weinhold int
disable_debugger(int state)695af32e75SAxel Dörfler disable_debugger(int state)
705af32e75SAxel Dörfler {
715af32e75SAxel Dörfler return _kern_disable_debugger(state);
725af32e75SAxel Dörfler }
735af32e75SAxel Dörfler
745af32e75SAxel Dörfler
755af32e75SAxel Dörfler status_t
install_default_debugger(port_id debuggerPort)765af32e75SAxel Dörfler install_default_debugger(port_id debuggerPort)
775af32e75SAxel Dörfler {
785af32e75SAxel Dörfler return _kern_install_default_debugger(debuggerPort);
795af32e75SAxel Dörfler }
805af32e75SAxel Dörfler
815af32e75SAxel Dörfler
825af32e75SAxel Dörfler port_id
install_team_debugger(team_id team,port_id debuggerPort)835af32e75SAxel Dörfler install_team_debugger(team_id team, port_id debuggerPort)
845af32e75SAxel Dörfler {
855af32e75SAxel Dörfler return _kern_install_team_debugger(team, debuggerPort);
865af32e75SAxel Dörfler }
875af32e75SAxel Dörfler
885af32e75SAxel Dörfler
895af32e75SAxel Dörfler status_t
remove_team_debugger(team_id team)905af32e75SAxel Dörfler remove_team_debugger(team_id team)
915af32e75SAxel Dörfler {
925af32e75SAxel Dörfler return _kern_remove_team_debugger(team);
935af32e75SAxel Dörfler }
945af32e75SAxel Dörfler
955af32e75SAxel Dörfler
965af32e75SAxel Dörfler status_t
debug_thread(thread_id thread)975af32e75SAxel Dörfler debug_thread(thread_id thread)
985af32e75SAxel Dörfler {
995af32e75SAxel Dörfler return _kern_debug_thread(thread);
1005af32e75SAxel Dörfler }
1015af32e75SAxel Dörfler
1025af32e75SAxel Dörfler
1035af32e75SAxel Dörfler /** \brief Suspends the thread until a debugger has been installed for this
1045af32e75SAxel Dörfler * team.
1055af32e75SAxel Dörfler *
1065af32e75SAxel Dörfler * As soon as this happens (immediately, if a debugger is already installed)
1075af32e75SAxel Dörfler * the thread stops for debugging. This is desirable for debuggers that spawn
1085af32e75SAxel Dörfler * their debugged teams via fork() and want the child to wait till they have
1095af32e75SAxel Dörfler * installed themselves as team debugger before continuing with exec*().
1105af32e75SAxel Dörfler */
1115af32e75SAxel Dörfler
1125af32e75SAxel Dörfler void
wait_for_debugger(void)1135af32e75SAxel Dörfler wait_for_debugger(void)
1145af32e75SAxel Dörfler {
1155af32e75SAxel Dörfler _kern_wait_for_debugger();
1165af32e75SAxel Dörfler }
1175af32e75SAxel Dörfler
1185af32e75SAxel Dörfler
11944b5d72bSIngo Weinhold status_t
set_debugger_breakpoint(void * address)12044b5d72bSIngo Weinhold set_debugger_breakpoint(void *address)
12144b5d72bSIngo Weinhold {
12244b5d72bSIngo Weinhold return _kern_set_debugger_breakpoint(address, 0, 0, false);
12344b5d72bSIngo Weinhold }
12444b5d72bSIngo Weinhold
12544b5d72bSIngo Weinhold
12644b5d72bSIngo Weinhold status_t
clear_debugger_breakpoint(void * address)12744b5d72bSIngo Weinhold clear_debugger_breakpoint(void *address)
12844b5d72bSIngo Weinhold {
12944b5d72bSIngo Weinhold return _kern_clear_debugger_breakpoint(address, false);
13044b5d72bSIngo Weinhold }
13144b5d72bSIngo Weinhold
13244b5d72bSIngo Weinhold
13344b5d72bSIngo Weinhold status_t
set_debugger_watchpoint(void * address,uint32 type,int32 length)13444b5d72bSIngo Weinhold set_debugger_watchpoint(void *address, uint32 type, int32 length)
13544b5d72bSIngo Weinhold {
13644b5d72bSIngo Weinhold return _kern_set_debugger_breakpoint(address, type, length, true);
13744b5d72bSIngo Weinhold }
13844b5d72bSIngo Weinhold
13944b5d72bSIngo Weinhold
14044b5d72bSIngo Weinhold status_t
clear_debugger_watchpoint(void * address)14144b5d72bSIngo Weinhold clear_debugger_watchpoint(void *address)
14244b5d72bSIngo Weinhold {
14344b5d72bSIngo Weinhold return _kern_clear_debugger_breakpoint(address, true);
14444b5d72bSIngo Weinhold }
14544b5d72bSIngo Weinhold
14644b5d72bSIngo Weinhold
1475af32e75SAxel Dörfler static void
get_debug_string(const debug_string_entry * stringEntries,const char * defaultString,uint32 code,char * buffer,int32 bufferSize)1485af32e75SAxel Dörfler get_debug_string(const debug_string_entry *stringEntries,
1495af32e75SAxel Dörfler const char *defaultString, uint32 code, char *buffer, int32 bufferSize)
1505af32e75SAxel Dörfler {
1515af32e75SAxel Dörfler int i;
1525af32e75SAxel Dörfler
1535af32e75SAxel Dörfler if (!buffer || bufferSize <= 0)
1545af32e75SAxel Dörfler return;
1555af32e75SAxel Dörfler
1565af32e75SAxel Dörfler for (i = 0; stringEntries[i].string; i++) {
1575af32e75SAxel Dörfler if (stringEntries[i].code == code) {
1585af32e75SAxel Dörfler strlcpy(buffer, stringEntries[i].string, bufferSize);
1595af32e75SAxel Dörfler return;
1605af32e75SAxel Dörfler }
1615af32e75SAxel Dörfler }
1625af32e75SAxel Dörfler
1635af32e75SAxel Dörfler snprintf(buffer, bufferSize, defaultString, code);
1645af32e75SAxel Dörfler }
1655af32e75SAxel Dörfler
1665af32e75SAxel Dörfler
1675af32e75SAxel Dörfler void
get_debug_message_string(debug_debugger_message message,char * buffer,int32 bufferSize)1685af32e75SAxel Dörfler get_debug_message_string(debug_debugger_message message, char *buffer,
1695af32e75SAxel Dörfler int32 bufferSize)
1705af32e75SAxel Dörfler {
1715af32e75SAxel Dörfler get_debug_string(sDebugMessageStrings, "Unknown message %lu",
1725af32e75SAxel Dörfler (uint32)message, buffer, bufferSize);
1735af32e75SAxel Dörfler }
1745af32e75SAxel Dörfler
1755af32e75SAxel Dörfler
1765af32e75SAxel Dörfler void
get_debug_exception_string(debug_exception_type exception,char * buffer,int32 bufferSize)1775af32e75SAxel Dörfler get_debug_exception_string(debug_exception_type exception, char *buffer,
1785af32e75SAxel Dörfler int32 bufferSize)
1795af32e75SAxel Dörfler {
1805af32e75SAxel Dörfler get_debug_string(sDebugExceptionTypeStrings, "Unknown exception %lu",
1815af32e75SAxel Dörfler (uint32)exception, buffer, bufferSize);
1825af32e75SAxel Dörfler }
1835af32e75SAxel Dörfler
1845af32e75SAxel Dörfler
185d401b8f0SAxel Dörfler // #pragma mark - Debug.h functions
1865af32e75SAxel Dörfler
1875af32e75SAxel Dörfler
1885af32e75SAxel Dörfler bool
_debugFlag(void)1895af32e75SAxel Dörfler _debugFlag(void)
1905af32e75SAxel Dörfler {
1915af32e75SAxel Dörfler return _rtDebugFlag;
1925af32e75SAxel Dörfler }
1935af32e75SAxel Dörfler
1945af32e75SAxel Dörfler
1955af32e75SAxel Dörfler bool
_setDebugFlag(bool flag)1965af32e75SAxel Dörfler _setDebugFlag(bool flag)
1975af32e75SAxel Dörfler {
1985af32e75SAxel Dörfler bool previous = _rtDebugFlag;
1995af32e75SAxel Dörfler _rtDebugFlag = flag;
2005af32e75SAxel Dörfler return previous;
2015af32e75SAxel Dörfler }
2025af32e75SAxel Dörfler
2035af32e75SAxel Dörfler
2045af32e75SAxel Dörfler int
_debugPrintf(const char * fmt,...)2055af32e75SAxel Dörfler _debugPrintf(const char *fmt, ...)
2065af32e75SAxel Dörfler {
2075af32e75SAxel Dörfler va_list ap;
2085af32e75SAxel Dörfler int ret;
2095af32e75SAxel Dörfler
210d401b8f0SAxel Dörfler if (!_rtDebugFlag)
211d401b8f0SAxel Dörfler return 0;
212d401b8f0SAxel Dörfler
2135af32e75SAxel Dörfler va_start(ap, fmt);
2145af32e75SAxel Dörfler ret = vfprintf(stdout, fmt, ap);
2155af32e75SAxel Dörfler va_end(ap);
2165af32e75SAxel Dörfler
2175af32e75SAxel Dörfler return ret;
2185af32e75SAxel Dörfler }
2195af32e75SAxel Dörfler
2205af32e75SAxel Dörfler
2215af32e75SAxel Dörfler int
_sPrintf(const char * fmt,...)2225af32e75SAxel Dörfler _sPrintf(const char *fmt, ...)
2235af32e75SAxel Dörfler {
224d401b8f0SAxel Dörfler char buffer[512];
2255af32e75SAxel Dörfler va_list ap;
2265af32e75SAxel Dörfler int ret;
2275af32e75SAxel Dörfler
228d401b8f0SAxel Dörfler if (!_rtDebugFlag)
229d401b8f0SAxel Dörfler return 0;
230d401b8f0SAxel Dörfler
2315af32e75SAxel Dörfler va_start(ap, fmt);
2325af32e75SAxel Dörfler ret = vsnprintf(buffer, sizeof(buffer), fmt, ap);
2335af32e75SAxel Dörfler va_end(ap);
2345af32e75SAxel Dörfler
2355af32e75SAxel Dörfler if (ret >= 0)
2365af32e75SAxel Dörfler _kern_debug_output(buffer);
2375af32e75SAxel Dörfler
2385af32e75SAxel Dörfler return ret;
2395af32e75SAxel Dörfler }
2405af32e75SAxel Dörfler
2415af32e75SAxel Dörfler
2425af32e75SAxel Dörfler int
_xdebugPrintf(const char * fmt,...)2435af32e75SAxel Dörfler _xdebugPrintf(const char *fmt, ...)
2445af32e75SAxel Dörfler {
2455af32e75SAxel Dörfler va_list ap;
2465af32e75SAxel Dörfler int ret;
2475af32e75SAxel Dörfler
2485af32e75SAxel Dörfler va_start(ap, fmt);
2495af32e75SAxel Dörfler ret = vfprintf(stdout, fmt, ap);
2505af32e75SAxel Dörfler va_end(ap);
2515af32e75SAxel Dörfler
2525af32e75SAxel Dörfler return ret;
2535af32e75SAxel Dörfler }
2545af32e75SAxel Dörfler
2555af32e75SAxel Dörfler
2565af32e75SAxel Dörfler int
_debuggerAssert(const char * file,int line,const char * message)2579073b0dcSIngo Weinhold _debuggerAssert(const char *file, int line, const char *message)
2585af32e75SAxel Dörfler {
25959456447SStefano Ceccherini char buffer[1024];
26059456447SStefano Ceccherini snprintf(buffer, sizeof(buffer),
26159456447SStefano Ceccherini "Assert failed: File: %s, Line: %d, %s",
26259456447SStefano Ceccherini file, line, message);
26359456447SStefano Ceccherini
264*e453c0f4SAlex Smith debug_printf("%" B_PRId32 ": ASSERT: %s:%d %s\n", find_thread(NULL), file,
265*e453c0f4SAlex Smith line, buffer);
26659456447SStefano Ceccherini _kern_debugger(buffer);
26759456447SStefano Ceccherini
2685af32e75SAxel Dörfler return 0;
2695af32e75SAxel Dörfler }
2705af32e75SAxel Dörfler
2715af32e75SAxel Dörfler // TODO: Remove. Temporary debug helper.
2725af32e75SAxel Dörfler // (accidently these are more or less the same as _sPrintf())
2735af32e75SAxel Dörfler
2745af32e75SAxel Dörfler void
debug_printf(const char * format,...)2755af32e75SAxel Dörfler debug_printf(const char *format, ...)
2765af32e75SAxel Dörfler {
2775af32e75SAxel Dörfler va_list list;
2785af32e75SAxel Dörfler va_start(list, format);
2795af32e75SAxel Dörfler
2805af32e75SAxel Dörfler debug_vprintf(format, list);
2815af32e75SAxel Dörfler
2825af32e75SAxel Dörfler va_end(list);
2835af32e75SAxel Dörfler }
2845af32e75SAxel Dörfler
2855af32e75SAxel Dörfler void
debug_vprintf(const char * format,va_list args)2865af32e75SAxel Dörfler debug_vprintf(const char *format, va_list args)
2875af32e75SAxel Dörfler {
2885af32e75SAxel Dörfler char buffer[1024];
2895af32e75SAxel Dörfler vsnprintf(buffer, sizeof(buffer), format, args);
2905af32e75SAxel Dörfler
2915af32e75SAxel Dörfler _kern_debug_output(buffer);
2925af32e75SAxel Dörfler }
2935af32e75SAxel Dörfler
2945af32e75SAxel Dörfler
295a54c125eSIngo Weinhold void
ktrace_printf(const char * format,...)296a54c125eSIngo Weinhold ktrace_printf(const char *format, ...)
297a54c125eSIngo Weinhold {
298a54c125eSIngo Weinhold va_list list;
299a54c125eSIngo Weinhold va_start(list, format);
300a54c125eSIngo Weinhold
301a54c125eSIngo Weinhold ktrace_vprintf(format, list);
302a54c125eSIngo Weinhold
303a54c125eSIngo Weinhold va_end(list);
304a54c125eSIngo Weinhold }
305a54c125eSIngo Weinhold
306a54c125eSIngo Weinhold
307a54c125eSIngo Weinhold void
ktrace_vprintf(const char * format,va_list args)308a54c125eSIngo Weinhold ktrace_vprintf(const char *format, va_list args)
309a54c125eSIngo Weinhold {
310a54c125eSIngo Weinhold char buffer[1024];
311a54c125eSIngo Weinhold vsnprintf(buffer, sizeof(buffer), format, args);
312a54c125eSIngo Weinhold
313a54c125eSIngo Weinhold _kern_ktrace_output(buffer);
314a54c125eSIngo Weinhold }
315