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