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 static void 118 get_debug_string(const debug_string_entry *stringEntries, 119 const char *defaultString, uint32 code, char *buffer, int32 bufferSize) 120 { 121 int i; 122 123 if (!buffer || bufferSize <= 0) 124 return; 125 126 for (i = 0; stringEntries[i].string; i++) { 127 if (stringEntries[i].code == code) { 128 strlcpy(buffer, stringEntries[i].string, bufferSize); 129 return; 130 } 131 } 132 133 snprintf(buffer, bufferSize, defaultString, code); 134 } 135 136 137 void 138 get_debug_message_string(debug_debugger_message message, char *buffer, 139 int32 bufferSize) 140 { 141 get_debug_string(sDebugMessageStrings, "Unknown message %lu", 142 (uint32)message, buffer, bufferSize); 143 } 144 145 146 void 147 get_debug_exception_string(debug_exception_type exception, char *buffer, 148 int32 bufferSize) 149 { 150 get_debug_string(sDebugExceptionTypeStrings, "Unknown exception %lu", 151 (uint32)exception, buffer, bufferSize); 152 } 153 154 155 // #pragma mark - 156 // Debug.h functions 157 158 // TODO: verify these functions 159 // TODO: add implementations for printfs? 160 161 162 bool _rtDebugFlag = false; 163 164 bool 165 _debugFlag(void) 166 { 167 return _rtDebugFlag; 168 } 169 170 171 bool 172 _setDebugFlag(bool flag) 173 { 174 bool previous = _rtDebugFlag; 175 _rtDebugFlag = flag; 176 return previous; 177 } 178 179 180 int 181 _debugPrintf(const char *fmt, ...) 182 { 183 va_list ap; 184 int ret; 185 186 va_start(ap, fmt); 187 ret = vfprintf(stdout, fmt, ap); 188 va_end(ap); 189 190 return ret; 191 } 192 193 194 int 195 _sPrintf(const char *fmt, ...) 196 { 197 char buffer[1024]; 198 va_list ap; 199 int ret; 200 201 va_start(ap, fmt); 202 ret = vsnprintf(buffer, sizeof(buffer), fmt, ap); 203 va_end(ap); 204 205 if (ret >= 0) 206 _kern_debug_output(buffer); 207 208 return ret; 209 } 210 211 212 int 213 _xdebugPrintf(const char * fmt, ...) 214 { 215 va_list ap; 216 int ret; 217 218 va_start(ap, fmt); 219 ret = vfprintf(stdout, fmt, ap); 220 va_end(ap); 221 222 return ret; 223 } 224 225 226 int 227 _debuggerAssert(const char * file, int line, char * message) 228 { 229 puts("*** _debuggerAssert call - not yet implemented ***"); 230 printf("%s:%d:%s\n", file, line, message); 231 return 0; 232 } 233 234 // TODO: Remove. Temporary debug helper. 235 // (accidently these are more or less the same as _sPrintf()) 236 237 void 238 debug_printf(const char *format, ...) 239 { 240 va_list list; 241 va_start(list, format); 242 243 debug_vprintf(format, list); 244 245 va_end(list); 246 } 247 248 void 249 debug_vprintf(const char *format, va_list args) 250 { 251 char buffer[1024]; 252 vsnprintf(buffer, sizeof(buffer), format, args); 253 254 _kern_debug_output(buffer); 255 } 256 257 258