xref: /haiku/src/system/libroot/os/debug.c (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 /*
2  * Copyright 2002-2005, 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 	_kern_debugger(message);
62 }
63 
64 
65 int
66 disable_debugger(int state)
67 {
68 	return _kern_disable_debugger(state);
69 }
70 
71 
72 status_t
73 install_default_debugger(port_id debuggerPort)
74 {
75 	return _kern_install_default_debugger(debuggerPort);
76 }
77 
78 
79 port_id
80 install_team_debugger(team_id team, port_id debuggerPort)
81 {
82 	return _kern_install_team_debugger(team, debuggerPort);
83 }
84 
85 
86 status_t
87 remove_team_debugger(team_id team)
88 {
89 	return _kern_remove_team_debugger(team);
90 }
91 
92 
93 status_t
94 debug_thread(thread_id thread)
95 {
96 	return _kern_debug_thread(thread);
97 }
98 
99 
100 /**	\brief Suspends the thread until a debugger has been installed for this
101  *		   team.
102  *
103  *	As soon as this happens (immediately, if a debugger is already installed)
104  *	the thread stops for debugging. This is desirable for debuggers that spawn
105  *	their debugged teams via fork() and want the child to wait till they have
106  *	installed themselves as team debugger before continuing with exec*().
107  */
108 
109 void
110 wait_for_debugger(void)
111 {
112 	_kern_wait_for_debugger();
113 }
114 
115 
116 static void
117 get_debug_string(const debug_string_entry *stringEntries,
118 	const char *defaultString, uint32 code, char *buffer, int32 bufferSize)
119 {
120 	int i;
121 
122 	if (!buffer || bufferSize <= 0)
123 		return;
124 
125 	for (i = 0; stringEntries[i].string; i++) {
126 		if (stringEntries[i].code == code) {
127 			strlcpy(buffer, stringEntries[i].string, bufferSize);
128 			return;
129 		}
130 	}
131 
132 	snprintf(buffer, bufferSize, defaultString, code);
133 }
134 
135 
136 void
137 get_debug_message_string(debug_debugger_message message, char *buffer,
138 	int32 bufferSize)
139 {
140 	get_debug_string(sDebugMessageStrings, "Unknown message %lu",
141 		(uint32)message, buffer, bufferSize);
142 }
143 
144 
145 void
146 get_debug_exception_string(debug_exception_type exception, char *buffer,
147 	int32 bufferSize)
148 {
149 	get_debug_string(sDebugExceptionTypeStrings, "Unknown exception %lu",
150 		(uint32)exception, buffer, bufferSize);
151 }
152 
153 
154 //	#pragma mark -
155 //	Debug.h functions
156 
157 // TODO: verify these functions
158 // TODO: add implementations for printfs?
159 
160 
161 bool _rtDebugFlag = false;
162 
163 bool
164 _debugFlag(void)
165 {
166 	return _rtDebugFlag;
167 }
168 
169 
170 bool
171 _setDebugFlag(bool flag)
172 {
173 	bool previous = _rtDebugFlag;
174 	_rtDebugFlag = flag;
175 	return previous;
176 }
177 
178 
179 int
180 _debugPrintf(const char *fmt, ...)
181 {
182 	va_list ap;
183 	int ret;
184 
185 	va_start(ap, fmt);
186 	ret = vfprintf(stdout, fmt, ap);
187 	va_end(ap);
188 
189 	return ret;
190 }
191 
192 
193 int
194 _sPrintf(const char *fmt, ...)
195 {
196 	char buffer[1024];
197 	va_list ap;
198 	int ret;
199 
200 	va_start(ap, fmt);
201 	ret = vsnprintf(buffer, sizeof(buffer), fmt, ap);
202 	va_end(ap);
203 
204 	if (ret >= 0)
205 		_kern_debug_output(buffer);
206 
207 	return ret;
208 }
209 
210 
211 int
212 _xdebugPrintf(const char * fmt, ...)
213 {
214 	va_list ap;
215 	int ret;
216 
217 	va_start(ap, fmt);
218 	ret = vfprintf(stdout, fmt, ap);
219 	va_end(ap);
220 
221 	return ret;
222 }
223 
224 
225 int
226 _debuggerAssert(const char * file, int line, char * message)
227 {
228 	puts("*** _debuggerAssert call - not yet implemented ***");
229 	printf("%s:%d:%s\n", file, line, message);
230 	return 0;
231 }
232 
233 // TODO: Remove. Temporary debug helper.
234 // (accidently these are more or less the same as _sPrintf())
235 
236 void
237 debug_printf(const char *format, ...)
238 {
239 	va_list list;
240 	va_start(list, format);
241 
242 	debug_vprintf(format, list);
243 
244 	va_end(list);
245 }
246 
247 void
248 debug_vprintf(const char *format, va_list args)
249 {
250 	char buffer[1024];
251 	vsnprintf(buffer, sizeof(buffer), format, args);
252 
253 	_kern_debug_output(buffer);
254 }
255 
256 
257