xref: /haiku/src/system/libroot/os/debug.c (revision 9ecf9d1c1d4888d341a6eac72112c72d1ae3a4cb)
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