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