1 /* 2 * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <debugger.h> 8 #include <OS.h> 9 #include <Debug.h> 10 #include "syscalls.h" 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 17 typedef struct debug_string_entry { 18 const char *string; 19 uint32 code; 20 } debug_string_entry; 21 22 static const debug_string_entry sDebugMessageStrings[] = { 23 { "Thread not running", B_DEBUGGER_MESSAGE_THREAD_DEBUGGED }, 24 { "Debugger call", B_DEBUGGER_MESSAGE_DEBUGGER_CALL }, 25 { "Breakpoint hit", B_DEBUGGER_MESSAGE_BREAKPOINT_HIT }, 26 { "Watchpoint hit", B_DEBUGGER_MESSAGE_WATCHPOINT_HIT }, 27 { "Single step", B_DEBUGGER_MESSAGE_SINGLE_STEP }, 28 { "Before syscall", B_DEBUGGER_MESSAGE_PRE_SYSCALL }, 29 { "After syscall", B_DEBUGGER_MESSAGE_POST_SYSCALL }, 30 { "Signal received", B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED }, 31 { "Exception occurred", B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED }, 32 { "Team created", B_DEBUGGER_MESSAGE_TEAM_CREATED }, 33 { "Team deleted", B_DEBUGGER_MESSAGE_TEAM_DELETED }, 34 { "Thread created", B_DEBUGGER_MESSAGE_THREAD_CREATED }, 35 { "Thread created", B_DEBUGGER_MESSAGE_THREAD_DELETED }, 36 { "Image created", B_DEBUGGER_MESSAGE_IMAGE_CREATED }, 37 { "Image deleted", B_DEBUGGER_MESSAGE_IMAGE_DELETED }, 38 { NULL, 0 } 39 }; 40 41 static const debug_string_entry sDebugExceptionTypeStrings[] = { 42 { "Non-maskable interrupt", B_NON_MASKABLE_INTERRUPT }, 43 { "Machine check exception", B_MACHINE_CHECK_EXCEPTION }, 44 { "Segment violation", B_SEGMENT_VIOLATION }, 45 { "Alignment exception", B_ALIGNMENT_EXCEPTION }, 46 { "Divide error", B_DIVIDE_ERROR }, 47 { "Overflow exception", B_OVERFLOW_EXCEPTION }, 48 { "Bounds check exception", B_BOUNDS_CHECK_EXCEPTION }, 49 { "Invalid opcode exception", B_INVALID_OPCODE_EXCEPTION }, 50 { "Segment not present", B_SEGMENT_NOT_PRESENT }, 51 { "Stack fault", B_STACK_FAULT }, 52 { "General protection fault", B_GENERAL_PROTECTION_FAULT }, 53 { "Floating point exception", B_FLOATING_POINT_EXCEPTION }, 54 { NULL, 0 } 55 }; 56 57 58 void 59 debugger(const char *message) 60 { 61 _kern_debugger(message); 62 } 63 64 65 int 66 disable_debugger(int state) 67 { 68 return _kern_disable_debugger(state); 69 } 70 71 72 status_t 73 install_default_debugger(port_id debuggerPort) 74 { 75 return _kern_install_default_debugger(debuggerPort); 76 } 77 78 79 port_id 80 install_team_debugger(team_id team, port_id debuggerPort) 81 { 82 return _kern_install_team_debugger(team, debuggerPort); 83 } 84 85 86 status_t 87 remove_team_debugger(team_id team) 88 { 89 return _kern_remove_team_debugger(team); 90 } 91 92 93 status_t 94 debug_thread(thread_id thread) 95 { 96 return _kern_debug_thread(thread); 97 } 98 99 100 /** \brief Suspends the thread until a debugger has been installed for this 101 * team. 102 * 103 * As soon as this happens (immediately, if a debugger is already installed) 104 * the thread stops for debugging. This is desirable for debuggers that spawn 105 * their debugged teams via fork() and want the child to wait till they have 106 * installed themselves as team debugger before continuing with exec*(). 107 */ 108 109 void 110 wait_for_debugger(void) 111 { 112 _kern_wait_for_debugger(); 113 } 114 115 116 static void 117 get_debug_string(const debug_string_entry *stringEntries, 118 const char *defaultString, uint32 code, char *buffer, int32 bufferSize) 119 { 120 int i; 121 122 if (!buffer || bufferSize <= 0) 123 return; 124 125 for (i = 0; stringEntries[i].string; i++) { 126 if (stringEntries[i].code == code) { 127 strlcpy(buffer, stringEntries[i].string, bufferSize); 128 return; 129 } 130 } 131 132 snprintf(buffer, bufferSize, defaultString, code); 133 } 134 135 136 void 137 get_debug_message_string(debug_debugger_message message, char *buffer, 138 int32 bufferSize) 139 { 140 get_debug_string(sDebugMessageStrings, "Unknown message %lu", 141 (uint32)message, buffer, bufferSize); 142 } 143 144 145 void 146 get_debug_exception_string(debug_exception_type exception, char *buffer, 147 int32 bufferSize) 148 { 149 get_debug_string(sDebugExceptionTypeStrings, "Unknown exception %lu", 150 (uint32)exception, buffer, bufferSize); 151 } 152 153 154 // #pragma mark - 155 // Debug.h functions 156 157 // TODO: verify these functions 158 // TODO: add implementations for printfs? 159 160 161 bool _rtDebugFlag = false; 162 163 bool 164 _debugFlag(void) 165 { 166 return _rtDebugFlag; 167 } 168 169 170 bool 171 _setDebugFlag(bool flag) 172 { 173 bool previous = _rtDebugFlag; 174 _rtDebugFlag = flag; 175 return previous; 176 } 177 178 179 int 180 _debugPrintf(const char *fmt, ...) 181 { 182 va_list ap; 183 int ret; 184 185 va_start(ap, fmt); 186 ret = vfprintf(stdout, fmt, ap); 187 va_end(ap); 188 189 return ret; 190 } 191 192 193 int 194 _sPrintf(const char *fmt, ...) 195 { 196 char buffer[1024]; 197 va_list ap; 198 int ret; 199 200 va_start(ap, fmt); 201 ret = vsnprintf(buffer, sizeof(buffer), fmt, ap); 202 va_end(ap); 203 204 if (ret >= 0) 205 _kern_debug_output(buffer); 206 207 return ret; 208 } 209 210 211 int 212 _xdebugPrintf(const char * fmt, ...) 213 { 214 va_list ap; 215 int ret; 216 217 va_start(ap, fmt); 218 ret = vfprintf(stdout, fmt, ap); 219 va_end(ap); 220 221 return ret; 222 } 223 224 225 int 226 _debuggerAssert(const char * file, int line, char * message) 227 { 228 puts("*** _debuggerAssert call - not yet implemented ***"); 229 printf("%s:%d:%s\n", file, line, message); 230 return 0; 231 } 232 233 // TODO: Remove. Temporary debug helper. 234 // (accidently these are more or less the same as _sPrintf()) 235 236 void 237 debug_printf(const char *format, ...) 238 { 239 va_list list; 240 va_start(list, format); 241 242 debug_vprintf(format, list); 243 244 va_end(list); 245 } 246 247 void 248 debug_vprintf(const char *format, va_list args) 249 { 250 char buffer[1024]; 251 vsnprintf(buffer, sizeof(buffer), format, args); 252 253 _kern_debug_output(buffer); 254 } 255 256 257