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