1 #pragma once
2 /**
3 * \file
4 * Debugger related definitions.
5 * \ingroup l4_api
6 */
7 /*
8 * (c) 2008-2011 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
9 * Alexander Warg <warg@os.inf.tu-dresden.de>
10 * economic rights: Technische Universität Dresden (Germany)
11 *
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU General Public License 2.
14 * Please see the COPYING-GPL-2 file for details.
15 *
16 * As a special exception, you may use this file as part of a free software
17 * library without restriction. Specifically, if other files instantiate
18 * templates or use macros or inline functions from this file, or you compile
19 * this file and link it with other files to produce an executable, this
20 * file does not by itself cause the resulting executable to be covered by
21 * the GNU General Public License. This exception does not however
22 * invalidate any other reasons why the executable file might be covered by
23 * the GNU General Public License.
24 */
25
26 #include <l4/sys/compiler.h>
27 #include <l4/sys/utcb.h>
28 #include <l4/sys/ipc.h>
29
30 /**
31 * \defgroup l4_debugger_api Kernel Debugger
32 * \ingroup api_calls_fiasco
33 * Kernel debugger related functionality.
34 * \attention This API is subject to change!
35 *
36 * This is a debugging facility, any call to any function might be invalid.
37 * Do not rely on it in any real code.
38 *
39 * \includefile{l4/sys/debugger.h}
40 *
41 */
42
43 /**
44 * Set the name of a kernel object.
45 * \ingroup l4_debugger_api
46 *
47 * \param cap Capability which refers to the kernel object.
48 * \param name Name of the kernel object that is e.g. displayed in the
49 * kernel debugger.
50 *
51 * This is a debugging facility, the call might be invalid.
52 */
53 L4_INLINE l4_msgtag_t
54 l4_debugger_set_object_name(l4_cap_idx_t cap, const char *name) L4_NOTHROW;
55
56 /**
57 * \internal
58 */
59 L4_INLINE l4_msgtag_t
60 l4_debugger_set_object_name_u(l4_cap_idx_t cap, const char *name, l4_utcb_t *utcb) L4_NOTHROW;
61
62 /**
63 * Get name of the kernel object with Id `id`.
64 *
65 * \param cap Capability of the debugger object.
66 * \param id Global id of the object whose name is asked.
67 * \param[out] name Buffer to copy the name into. The buffer must be
68 * allocated by the caller.
69 * \param size Length of the `name` buffer.
70 *
71 * \return Syscall return tag
72 */
73 L4_INLINE l4_msgtag_t
74 l4_debugger_get_object_name(l4_cap_idx_t cap, unsigned id,
75 char *name, unsigned size) L4_NOTHROW;
76
77 /**
78 * \internal
79 */
80 L4_INLINE l4_msgtag_t
81 l4_debugger_get_object_name_u(l4_cap_idx_t cap, unsigned id,
82 char *name, unsigned size,
83 l4_utcb_t *utcb) L4_NOTHROW;
84
85 /**
86 * Get the globally unique ID of the object behind a capability.
87 * \ingroup l4_debugger_api
88 *
89 * \param cap Capability
90 *
91 * \retval ~0UL Capability is not valid.
92 * \retval >=0 Global debugger id.
93 *
94 * This is a debugging facility, the call might be invalid.
95 */
96 L4_INLINE unsigned long
97 l4_debugger_global_id(l4_cap_idx_t cap) L4_NOTHROW;
98
99 /**
100 * \internal
101 */
102 L4_INLINE unsigned long
103 l4_debugger_global_id_u(l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW;
104
105 /**
106 * Get the globally unique ID of the object behind the kobject pointer.
107 * \ingroup l4_debugger_api
108 *
109 * \param cap Capability
110 * \param kobjp Kobject pointer
111 *
112 * \retval ~0UL The capability or the kobject pointer are invalid.
113 * \retval >=0 The globally unique id.
114 *
115 * This is a debugging facility, the call might be invalid.
116 */
117 L4_INLINE unsigned long
118 l4_debugger_kobj_to_id(l4_cap_idx_t cap, l4_addr_t kobjp) L4_NOTHROW;
119
120 /**
121 * \internal
122 */
123 L4_INLINE unsigned long
124 l4_debugger_kobj_to_id_u(l4_cap_idx_t cap, l4_addr_t kobjp, l4_utcb_t *utcb) L4_NOTHROW;
125
126 /**
127 * Query the log-id for a log type
128 *
129 * \param cap Debugger capability
130 * \param name Name to query for.
131 * \param idx Idx to start searching, start with 0
132 *
133 * \return positive ID, or negative error code
134 *
135 * This is a debugging facility, the call might be invalid.
136 */
137 L4_INLINE long
138 l4_debugger_query_log_typeid(l4_cap_idx_t cap, const char *name,
139 unsigned idx) L4_NOTHROW;
140
141 /**
142 * \internal
143 */
144 L4_INLINE long
145 l4_debugger_query_log_typeid_u(l4_cap_idx_t cap, const char *name,
146 unsigned idx, l4_utcb_t *utcb) L4_NOTHROW;
147
148 /**
149 * Query the name of a log type given the ID
150 *
151 * \param cap Debugger capability.
152 * \param idx ID to query.
153 * \param name Buffer to copy name to.
154 * \param namelen Buffer length of name.
155 * \param shortname Buffer to copy `shortname` to.
156 * \param shortnamelen Buffer length of `shortname`.
157 *
158 * \retval 0 Success
159 * \retval <0 Error
160 *
161 * This is a debugging facility, the call might be invalid.
162 */
163 L4_INLINE long
164 l4_debugger_query_log_name(l4_cap_idx_t cap, unsigned idx,
165 char *name, unsigned namelen,
166 char *shortname, unsigned shortnamelen) L4_NOTHROW;
167
168 /**
169 * \internal
170 */
171 L4_INLINE long
172 l4_debugger_query_log_name_u(l4_cap_idx_t cap, unsigned idx,
173 char *name, unsigned namelen,
174 char *shortname, unsigned shortnamelen,
175 l4_utcb_t *utcb) L4_NOTHROW;
176
177 /**
178 * Set or unset log.
179 *
180 * \param cap Debugger object.
181 * \param name Name of the log type.
182 * \param on_off 1: turn log on, 0: turn log off
183 *
184 * \return Syscall return tag
185 */
186 L4_INLINE l4_msgtag_t
187 l4_debugger_switch_log(l4_cap_idx_t cap, const char *name,
188 int on_off) L4_NOTHROW;
189
190 /**
191 * \internal
192 */
193 L4_INLINE l4_msgtag_t
194 l4_debugger_switch_log_u(l4_cap_idx_t cap, const char *name, int on_off,
195 l4_utcb_t *utcb) L4_NOTHROW;
196
197 enum
198 {
199 L4_DEBUGGER_NAME_SET_OP = 0UL,
200 L4_DEBUGGER_GLOBAL_ID_OP = 1UL,
201 L4_DEBUGGER_KOBJ_TO_ID_OP = 2UL,
202 L4_DEBUGGER_QUERY_LOG_TYPEID_OP = 3UL,
203 L4_DEBUGGER_SWITCH_LOG_OP = 4UL,
204 L4_DEBUGGER_NAME_GET_OP = 5UL,
205 L4_DEBUGGER_QUERY_LOG_NAME_OP = 6UL,
206 };
207
208 enum
209 {
210 L4_DEBUGGER_SWITCH_LOG_ON = 1,
211 L4_DEBUGGER_SWITCH_LOG_OFF = 0,
212 };
213
214 /* IMPLEMENTATION -----------------------------------------------------------*/
215
216 #include <l4/sys/kernel_object.h>
217
218 /**
219 * Copy a number of characters from the C string \b src to the C string \b dst.
220 *
221 * The resulting string \b dst is always '\0'-terminated unless \b maxlen is 0.
222 * If the C string in \b src is shorter than the buffer \b dst then the
223 * remaining bytes in \b dst are NOT initialized.
224 *
225 * \param dst Target buffer.
226 * \param src Source buffer.
227 * \param maxlen Maximum number of bytes written to the target buffer.
228 * \return The number of bytes written (including the terminating '\0'.
229 */
230 L4_INLINE unsigned
__strcpy_maxlen(char * dst,char const * src,unsigned maxlen)231 __strcpy_maxlen(char *dst, char const *src, unsigned maxlen)
232 {
233 unsigned i;
234 if (!maxlen)
235 return 0;
236
237 for (i = 0; i < maxlen - 1 && src[i]; ++i)
238 dst[i] = src[i];
239 dst[i] = '\0';
240
241 return i + 1;
242 }
243
244 L4_INLINE l4_msgtag_t
l4_debugger_set_object_name_u(l4_cap_idx_t cap,const char * name,l4_utcb_t * utcb)245 l4_debugger_set_object_name_u(l4_cap_idx_t cap,
246 const char *name, l4_utcb_t *utcb) L4_NOTHROW
247 {
248 unsigned i;
249 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_NAME_SET_OP;
250 i = __strcpy_maxlen((char *)&l4_utcb_mr_u(utcb)->mr[1], name,
251 (L4_UTCB_GENERIC_DATA_SIZE - 2) * sizeof(l4_umword_t));
252 i = l4_bytes_to_mwords(i);
253 return l4_invoke_debugger(cap, l4_msgtag(0, 1 + i, 0, 0), utcb);
254 }
255
256 L4_INLINE unsigned long
l4_debugger_global_id_u(l4_cap_idx_t cap,l4_utcb_t * utcb)257 l4_debugger_global_id_u(l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW
258 {
259 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_GLOBAL_ID_OP;
260 if (l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 1, 0, 0), utcb), utcb))
261 return ~0UL;
262 return l4_utcb_mr_u(utcb)->mr[0];
263 }
264
265 L4_INLINE unsigned long
l4_debugger_kobj_to_id_u(l4_cap_idx_t cap,l4_addr_t kobjp,l4_utcb_t * utcb)266 l4_debugger_kobj_to_id_u(l4_cap_idx_t cap, l4_addr_t kobjp, l4_utcb_t *utcb) L4_NOTHROW
267 {
268 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_KOBJ_TO_ID_OP;
269 l4_utcb_mr_u(utcb)->mr[1] = kobjp;
270 if (l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 2, 0, 0), utcb), utcb))
271 return ~0UL;
272 return l4_utcb_mr_u(utcb)->mr[0];
273 }
274
275 L4_INLINE long
l4_debugger_query_log_typeid_u(l4_cap_idx_t cap,const char * name,unsigned idx,l4_utcb_t * utcb)276 l4_debugger_query_log_typeid_u(l4_cap_idx_t cap, const char *name,
277 unsigned idx,
278 l4_utcb_t *utcb) L4_NOTHROW
279 {
280 unsigned i;
281 long e;
282 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_QUERY_LOG_TYPEID_OP;
283 l4_utcb_mr_u(utcb)->mr[1] = idx;
284 i = __strcpy_maxlen((char *)&l4_utcb_mr_u(utcb)->mr[2], name, 32);
285 i = l4_bytes_to_mwords(i);
286 e = l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 2 + i, 0, 0), utcb), utcb);
287 if (e < 0)
288 return e;
289 return l4_utcb_mr_u(utcb)->mr[0];
290 }
291
292 L4_INLINE long
l4_debugger_query_log_name_u(l4_cap_idx_t cap,unsigned idx,char * name,unsigned namelen,char * shortname,unsigned shortnamelen,l4_utcb_t * utcb)293 l4_debugger_query_log_name_u(l4_cap_idx_t cap, unsigned idx,
294 char *name, unsigned namelen,
295 char *shortname, unsigned shortnamelen,
296 l4_utcb_t *utcb) L4_NOTHROW
297 {
298 long e;
299 char const *n;
300 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_QUERY_LOG_NAME_OP;
301 l4_utcb_mr_u(utcb)->mr[1] = idx;
302 e = l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 2, 0, 0), utcb), utcb);
303 if (e < 0)
304 return e;
305 n = (char const *)&l4_utcb_mr_u(utcb)->mr[0];
306 __strcpy_maxlen(name, n, namelen);
307 __strcpy_maxlen(shortname, n + __builtin_strlen(n) + 1, shortnamelen);
308 return 0;
309 }
310
311
312 L4_INLINE l4_msgtag_t
l4_debugger_switch_log_u(l4_cap_idx_t cap,const char * name,int on_off,l4_utcb_t * utcb)313 l4_debugger_switch_log_u(l4_cap_idx_t cap, const char *name, int on_off,
314 l4_utcb_t *utcb) L4_NOTHROW
315 {
316 unsigned i;
317 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_SWITCH_LOG_OP;
318 l4_utcb_mr_u(utcb)->mr[1] = on_off;
319 i = __strcpy_maxlen((char *)&l4_utcb_mr_u(utcb)->mr[2], name, 32);
320 i = l4_bytes_to_mwords(i);
321 return l4_invoke_debugger(cap, l4_msgtag(0, 2 + i, 0, 0), utcb);
322 }
323
324 L4_INLINE l4_msgtag_t
l4_debugger_get_object_name_u(l4_cap_idx_t cap,unsigned id,char * name,unsigned size,l4_utcb_t * utcb)325 l4_debugger_get_object_name_u(l4_cap_idx_t cap, unsigned id,
326 char *name, unsigned size,
327 l4_utcb_t *utcb) L4_NOTHROW
328 {
329 l4_msgtag_t t;
330 l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_NAME_GET_OP;
331 l4_utcb_mr_u(utcb)->mr[1] = id;
332 t = l4_invoke_debugger(cap, l4_msgtag(0, 2, 0, 0), utcb);
333 __strcpy_maxlen(name, (char const *)&l4_utcb_mr_u(utcb)->mr[0], size);
334 return t;
335 }
336
337
338 L4_INLINE l4_msgtag_t
l4_debugger_set_object_name(l4_cap_idx_t cap,const char * name)339 l4_debugger_set_object_name(l4_cap_idx_t cap,
340 const char *name) L4_NOTHROW
341 {
342 return l4_debugger_set_object_name_u(cap, name, l4_utcb());
343 }
344
345 L4_INLINE unsigned long
l4_debugger_global_id(l4_cap_idx_t cap)346 l4_debugger_global_id(l4_cap_idx_t cap) L4_NOTHROW
347 {
348 return l4_debugger_global_id_u(cap, l4_utcb());
349 }
350
351 L4_INLINE unsigned long
l4_debugger_kobj_to_id(l4_cap_idx_t cap,l4_addr_t kobjp)352 l4_debugger_kobj_to_id(l4_cap_idx_t cap, l4_addr_t kobjp) L4_NOTHROW
353 {
354 return l4_debugger_kobj_to_id_u(cap, kobjp, l4_utcb());
355 }
356
357 L4_INLINE long
l4_debugger_query_log_typeid(l4_cap_idx_t cap,const char * name,unsigned idx)358 l4_debugger_query_log_typeid(l4_cap_idx_t cap, const char *name,
359 unsigned idx) L4_NOTHROW
360 {
361 return l4_debugger_query_log_typeid_u(cap, name, idx, l4_utcb());
362 }
363
364 L4_INLINE long
l4_debugger_query_log_name(l4_cap_idx_t cap,unsigned idx,char * name,unsigned namelen,char * shortname,unsigned shortnamelen)365 l4_debugger_query_log_name(l4_cap_idx_t cap, unsigned idx,
366 char *name, unsigned namelen,
367 char *shortname, unsigned shortnamelen) L4_NOTHROW
368 {
369 return l4_debugger_query_log_name_u(cap, idx, name, namelen,
370 shortname, shortnamelen, l4_utcb());
371 }
372
373 L4_INLINE l4_msgtag_t
l4_debugger_switch_log(l4_cap_idx_t cap,const char * name,int on_off)374 l4_debugger_switch_log(l4_cap_idx_t cap, const char *name,
375 int on_off) L4_NOTHROW
376 {
377 return l4_debugger_switch_log_u(cap, name, on_off, l4_utcb());
378 }
379
380 L4_INLINE l4_msgtag_t
l4_debugger_get_object_name(l4_cap_idx_t cap,unsigned id,char * name,unsigned size)381 l4_debugger_get_object_name(l4_cap_idx_t cap, unsigned id,
382 char *name, unsigned size) L4_NOTHROW
383 {
384 return l4_debugger_get_object_name_u(cap, id, name, size, l4_utcb());
385 }
386