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 17typedef struct debug_string_entry { 18 const char *string; 19 uint32 code; 20} debug_string_entry; 21 22static 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 41static 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 57bool _rtDebugFlag = true; 58 59 60void 61debugger(const char *message) 62{ 63 debug_printf("%" B_PRId32 ": DEBUGGER: %s\n", find_thread(NULL), message); 64 _kern_debugger(message); 65} 66 67 68int 69disable_debugger(int state) 70{ 71 return _kern_disable_debugger(state); 72} 73 74 75status_t 76install_default_debugger(port_id debuggerPort) 77{ 78 return _kern_install_default_debugger(debuggerPort); 79} 80 81 82port_id 83install_team_debugger(team_id team, port_id debuggerPort) 84{ 85 return _kern_install_team_debugger(team, debuggerPort); 86} 87 88 89status_t 90remove_team_debugger(team_id team) 91{ 92 return _kern_remove_team_debugger(team); 93} 94 95 96status_t 97debug_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 112void 113wait_for_debugger(void) 114{ 115 _kern_wait_for_debugger(); 116} 117 118 119status_t 120set_debugger_breakpoint(void *address) 121{ 122 return _kern_set_debugger_breakpoint(address, 0, 0, false); 123} 124 125 126status_t 127clear_debugger_breakpoint(void *address) 128{ 129 return _kern_clear_debugger_breakpoint(address, false); 130} 131 132 133status_t 134set_debugger_watchpoint(void *address, uint32 type, int32 length) 135{ 136 return _kern_set_debugger_breakpoint(address, type, length, true); 137} 138 139 140status_t 141clear_debugger_watchpoint(void *address) 142{ 143 return _kern_clear_debugger_breakpoint(address, true); 144} 145 146 147static void 148get_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 167void 168get_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 176void 177get_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 188bool 189_debugFlag(void) 190{ 191 return _rtDebugFlag; 192} 193 194 195bool 196_setDebugFlag(bool flag) 197{ 198 bool previous = _rtDebugFlag; 199 _rtDebugFlag = flag; 200 return previous; 201} 202 203 204int 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 221int 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 242int 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 256int 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 274void 275debug_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 285void 286debug_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 295void 296ktrace_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 307void 308ktrace_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