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
debugger(const char * message)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
disable_debugger(int state)69 disable_debugger(int state)
70 {
71 return _kern_disable_debugger(state);
72 }
73
74
75 status_t
install_default_debugger(port_id debuggerPort)76 install_default_debugger(port_id debuggerPort)
77 {
78 return _kern_install_default_debugger(debuggerPort);
79 }
80
81
82 port_id
install_team_debugger(team_id team,port_id debuggerPort)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
remove_team_debugger(team_id team)90 remove_team_debugger(team_id team)
91 {
92 return _kern_remove_team_debugger(team);
93 }
94
95
96 status_t
debug_thread(thread_id thread)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
wait_for_debugger(void)113 wait_for_debugger(void)
114 {
115 _kern_wait_for_debugger();
116 }
117
118
119 status_t
set_debugger_breakpoint(void * address)120 set_debugger_breakpoint(void *address)
121 {
122 return _kern_set_debugger_breakpoint(address, 0, 0, false);
123 }
124
125
126 status_t
clear_debugger_breakpoint(void * address)127 clear_debugger_breakpoint(void *address)
128 {
129 return _kern_clear_debugger_breakpoint(address, false);
130 }
131
132
133 status_t
set_debugger_watchpoint(void * address,uint32 type,int32 length)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
clear_debugger_watchpoint(void * address)141 clear_debugger_watchpoint(void *address)
142 {
143 return _kern_clear_debugger_breakpoint(address, true);
144 }
145
146
147 static void
get_debug_string(const debug_string_entry * stringEntries,const char * defaultString,uint32 code,char * buffer,int32 bufferSize)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
get_debug_message_string(debug_debugger_message message,char * buffer,int32 bufferSize)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
get_debug_exception_string(debug_exception_type exception,char * buffer,int32 bufferSize)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
_debugFlag(void)189 _debugFlag(void)
190 {
191 return _rtDebugFlag;
192 }
193
194
195 bool
_setDebugFlag(bool flag)196 _setDebugFlag(bool flag)
197 {
198 bool previous = _rtDebugFlag;
199 _rtDebugFlag = flag;
200 return previous;
201 }
202
203
204 int
_debugPrintf(const char * fmt,...)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
_sPrintf(const char * fmt,...)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
_xdebugPrintf(const char * fmt,...)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
_debuggerAssert(const char * file,int line,const char * message)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
debug_printf(const char * format,...)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
debug_vprintf(const char * format,va_list args)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
ktrace_printf(const char * format,...)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
ktrace_vprintf(const char * format,va_list args)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