1 /* 2 * Copyright 2002-2008, 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 bool _rtDebugFlag = true; 58 59 60 void 61 debugger(const char *message) 62 { 63 debug_printf("%" B_PRId32 ": DEBUGGER: %s\n", find_thread(NULL), message); 64 _kern_debugger(message); 65 } 66 67 68 int 69 disable_debugger(int state) 70 { 71 return _kern_disable_debugger(state); 72 } 73 74 75 status_t 76 install_default_debugger(port_id debuggerPort) 77 { 78 return _kern_install_default_debugger(debuggerPort); 79 } 80 81 82 port_id 83 install_team_debugger(team_id team, port_id debuggerPort) 84 { 85 return _kern_install_team_debugger(team, debuggerPort); 86 } 87 88 89 status_t 90 remove_team_debugger(team_id team) 91 { 92 return _kern_remove_team_debugger(team); 93 } 94 95 96 status_t 97 debug_thread(thread_id thread) 98 { 99 return _kern_debug_thread(thread); 100 } 101 102 103 /** \brief Suspends the thread until a debugger has been installed for this 104 * team. 105 * 106 * As soon as this happens (immediately, if a debugger is already installed) 107 * the thread stops for debugging. This is desirable for debuggers that spawn 108 * their debugged teams via fork() and want the child to wait till they have 109 * installed themselves as team debugger before continuing with exec*(). 110 */ 111 112 void 113 wait_for_debugger(void) 114 { 115 _kern_wait_for_debugger(); 116 } 117 118 119 status_t 120 set_debugger_breakpoint(void *address) 121 { 122 return _kern_set_debugger_breakpoint(address, 0, 0, false); 123 } 124 125 126 status_t 127 clear_debugger_breakpoint(void *address) 128 { 129 return _kern_clear_debugger_breakpoint(address, false); 130 } 131 132 133 status_t 134 set_debugger_watchpoint(void *address, uint32 type, int32 length) 135 { 136 return _kern_set_debugger_breakpoint(address, type, length, true); 137 } 138 139 140 status_t 141 clear_debugger_watchpoint(void *address) 142 { 143 return _kern_clear_debugger_breakpoint(address, true); 144 } 145 146 147 static void 148 get_debug_string(const debug_string_entry *stringEntries, 149 const char *defaultString, uint32 code, char *buffer, int32 bufferSize) 150 { 151 int i; 152 153 if (!buffer || bufferSize <= 0) 154 return; 155 156 for (i = 0; stringEntries[i].string; i++) { 157 if (stringEntries[i].code == code) { 158 strlcpy(buffer, stringEntries[i].string, bufferSize); 159 return; 160 } 161 } 162 163 snprintf(buffer, bufferSize, defaultString, code); 164 } 165 166 167 void 168 get_debug_message_string(debug_debugger_message message, char *buffer, 169 int32 bufferSize) 170 { 171 get_debug_string(sDebugMessageStrings, "Unknown message %lu", 172 (uint32)message, buffer, bufferSize); 173 } 174 175 176 void 177 get_debug_exception_string(debug_exception_type exception, char *buffer, 178 int32 bufferSize) 179 { 180 get_debug_string(sDebugExceptionTypeStrings, "Unknown exception %lu", 181 (uint32)exception, buffer, bufferSize); 182 } 183 184 185 // #pragma mark - Debug.h functions 186 187 188 bool 189 _debugFlag(void) 190 { 191 return _rtDebugFlag; 192 } 193 194 195 bool 196 _setDebugFlag(bool flag) 197 { 198 bool previous = _rtDebugFlag; 199 _rtDebugFlag = flag; 200 return previous; 201 } 202 203 204 int 205 _debugPrintf(const char *fmt, ...) 206 { 207 va_list ap; 208 int ret; 209 210 if (!_rtDebugFlag) 211 return 0; 212 213 va_start(ap, fmt); 214 ret = vfprintf(stdout, fmt, ap); 215 va_end(ap); 216 217 return ret; 218 } 219 220 221 int 222 _sPrintf(const char *fmt, ...) 223 { 224 char buffer[512]; 225 va_list ap; 226 int ret; 227 228 if (!_rtDebugFlag) 229 return 0; 230 231 va_start(ap, fmt); 232 ret = vsnprintf(buffer, sizeof(buffer), fmt, ap); 233 va_end(ap); 234 235 if (ret >= 0) 236 _kern_debug_output(buffer); 237 238 return ret; 239 } 240 241 242 int 243 _xdebugPrintf(const char *fmt, ...) 244 { 245 va_list ap; 246 int ret; 247 248 va_start(ap, fmt); 249 ret = vfprintf(stdout, fmt, ap); 250 va_end(ap); 251 252 return ret; 253 } 254 255 256 int 257 _debuggerAssert(const char *file, int line, const char *message) 258 { 259 char buffer[1024]; 260 snprintf(buffer, sizeof(buffer), 261 "Assert failed: File: %s, Line: %d, %s", 262 file, line, message); 263 264 debug_printf("%" B_PRId32 ": ASSERT: %s:%d %s\n", find_thread(NULL), file, 265 line, buffer); 266 _kern_debugger(buffer); 267 268 return 0; 269 } 270 271 // TODO: Remove. Temporary debug helper. 272 // (accidently these are more or less the same as _sPrintf()) 273 274 void 275 debug_printf(const char *format, ...) 276 { 277 va_list list; 278 va_start(list, format); 279 280 debug_vprintf(format, list); 281 282 va_end(list); 283 } 284 285 void 286 debug_vprintf(const char *format, va_list args) 287 { 288 char buffer[1024]; 289 vsnprintf(buffer, sizeof(buffer), format, args); 290 291 _kern_debug_output(buffer); 292 } 293 294 295 void 296 ktrace_printf(const char *format, ...) 297 { 298 va_list list; 299 va_start(list, format); 300 301 ktrace_vprintf(format, list); 302 303 va_end(list); 304 } 305 306 307 void 308 ktrace_vprintf(const char *format, va_list args) 309 { 310 char buffer[1024]; 311 vsnprintf(buffer, sizeof(buffer), format, args); 312 313 _kern_ktrace_output(buffer); 314 } 315