1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2013 by Delphix. All rights reserved.
25  * Copyright 2019 Joyent, Inc.
26  * Copyright 2023 RackTop Systems, Inc.
27  * Copyright 2023 OmniOS Community Edition (OmniOSce) Association.
28  * Copyright 2024 Oxide Computer Company
29  */
30 
31 #ifndef	_MDB_MODAPI_H
32 #define	_MDB_MODAPI_H
33 
34 /*
35  * MDB Module API
36  *
37  * The debugger provides a set of interfaces for use in writing loadable
38  * debugger modules.  Modules that call functions not listed in this header
39  * file may not be compatible with future versions of the debugger.
40  */
41 
42 #include <sys/types.h>
43 #include <sys/null.h>
44 #include <gelf.h>
45 
46 #ifdef	__cplusplus
47 extern "C" {
48 #endif
49 
50 /*
51  * Make sure that TRUE, FALSE, MIN, and MAX have the usual definitions
52  * so module writers can depend on these macros and defines.
53  * Make sure NULL is available to module writers by including <sys/null.h>.
54  */
55 
56 #ifndef TRUE
57 #define	TRUE	1
58 #endif
59 
60 #ifndef FALSE
61 #define	FALSE	0
62 #endif
63 
64 #ifndef MIN
65 #define	MIN(x, y) ((x) < (y) ? (x) : (y))
66 #endif
67 
68 #ifndef MAX
69 #define	MAX(x, y) ((x) > (y) ? (x) : (y))
70 #endif
71 
72 #define	MDB_API_VERSION	5	/* Current API version number */
73 
74 /*
75  * Debugger command function flags:
76  */
77 #define	DCMD_ADDRSPEC	0x01	/* Dcmd invoked with explicit address */
78 #define	DCMD_LOOP	0x02	/* Dcmd invoked in loop with ,cnt syntax */
79 #define	DCMD_LOOPFIRST	0x04	/* Dcmd invoked as first iteration of LOOP */
80 #define	DCMD_PIPE	0x08	/* Dcmd invoked with input from pipe */
81 #define	DCMD_PIPE_OUT	0x10	/* Dcmd invoked with output set to pipe */
82 
83 #define	DCMD_HDRSPEC(fl)	(((fl) & DCMD_LOOPFIRST) || !((fl) & DCMD_LOOP))
84 
85 /*
86  * Debugger tab command function flags
87  */
88 #define	DCMD_TAB_SPACE	0x01	/* Tab cb invoked with trailing space */
89 
90 /*
91  * Debugger command function return values:
92  */
93 #define	DCMD_OK		0	/* Dcmd completed successfully */
94 #define	DCMD_ERR	1	/* Dcmd failed due to an error */
95 #define	DCMD_USAGE	2	/* Dcmd usage error; abort and print usage */
96 #define	DCMD_NEXT	3	/* Invoke next dcmd in precedence list */
97 #define	DCMD_ABORT	4	/* Dcmd failed; abort current loop or pipe */
98 
99 #define	OFFSETOF(s, m)		(size_t)(&(((s *)0)->m))
100 
101 extern int mdb_prop_postmortem;	/* Are we looking at a static dump? */
102 extern int mdb_prop_kernel;	/* Are we looking at a kernel? */
103 
104 typedef enum {
105 	MDB_TYPE_STRING,	/* a_un.a_str is valid */
106 	MDB_TYPE_IMMEDIATE,	/* a_un.a_val is valid */
107 	MDB_TYPE_CHAR		/* a_un.a_char is valid */
108 } mdb_type_t;
109 
110 typedef struct mdb_arg {
111 	mdb_type_t a_type;
112 	union {
113 		const char *a_str;
114 		uintmax_t a_val;
115 		char a_char;
116 	} a_un;
117 } mdb_arg_t;
118 
119 typedef struct mdb_tab_cookie mdb_tab_cookie_t;
120 typedef int mdb_dcmd_f(uintptr_t, uint_t, int, const mdb_arg_t *);
121 typedef int mdb_dcmd_tab_f(mdb_tab_cookie_t *, uint_t, int,
122     const mdb_arg_t *);
123 
124 typedef struct mdb_dcmd {
125 	const char *dc_name;		/* Command name */
126 	const char *dc_usage;		/* Usage message (optional) */
127 	const char *dc_descr;		/* Description */
128 	mdb_dcmd_f *dc_funcp;		/* Command function */
129 	void (*dc_help)(void);		/* Command help function (or NULL) */
130 	mdb_dcmd_tab_f *dc_tabp;	/* Tab completion function */
131 } mdb_dcmd_t;
132 
133 #define	WALK_ERR	-1		/* Walk fatal error (terminate walk) */
134 #define	WALK_NEXT	0		/* Walk should continue to next step */
135 #define	WALK_DONE	1		/* Walk is complete (no errors) */
136 
137 typedef int (*mdb_walk_cb_t)(uintptr_t, const void *, void *);
138 
139 typedef struct mdb_walk_state {
140 	mdb_walk_cb_t walk_callback;	/* Callback to issue */
141 	void *walk_cbdata;		/* Callback private data */
142 	uintptr_t walk_addr;		/* Current address */
143 	void *walk_data;		/* Walk private data */
144 	void *walk_arg;			/* Walk private argument */
145 	const void *walk_layer;		/* Data from underlying layer */
146 } mdb_walk_state_t;
147 
148 typedef struct mdb_walker {
149 	const char *walk_name;		/* Walk type name */
150 	const char *walk_descr;		/* Walk description */
151 	int (*walk_init)(mdb_walk_state_t *);	/* Walk constructor */
152 	int (*walk_step)(mdb_walk_state_t *);	/* Walk iterator */
153 	void (*walk_fini)(mdb_walk_state_t *);	/* Walk destructor */
154 	void *walk_init_arg;		/* Walk constructor argument */
155 } mdb_walker_t;
156 
157 typedef struct mdb_modinfo {
158 	ushort_t mi_dvers;		/* Debugger version number */
159 	const mdb_dcmd_t *mi_dcmds;	/* NULL-terminated list of dcmds */
160 	const mdb_walker_t *mi_walkers;	/* NULL-terminated list of walks */
161 } mdb_modinfo_t;
162 
163 typedef struct mdb_bitmask {
164 	const char *bm_name;		/* String name to print */
165 	u_longlong_t bm_mask;		/* Mask for bits */
166 	u_longlong_t bm_bits;		/* Result required for value & mask */
167 } mdb_bitmask_t;
168 
169 typedef struct mdb_pipe {
170 	uintptr_t *pipe_data;		/* Array of pipe values */
171 	size_t pipe_len;		/* Array length */
172 } mdb_pipe_t;
173 
174 typedef struct mdb_object {
175 	const char *obj_name;		/* name of object */
176 	const char *obj_fullname;	/* full name of object */
177 	uintptr_t obj_base;		/* base address of object */
178 	uintptr_t obj_size;		/* in memory size of object in bytes */
179 } mdb_object_t;
180 
181 typedef struct mdb_symbol {
182 	const char *sym_name;		/* name of symbol */
183 	const char *sym_object;		/* name of containing object */
184 	const GElf_Sym *sym_sym;	/* ELF symbol information */
185 	uint_t sym_table;		/* symbol table id */
186 	uint_t sym_id;			/* symbol identifier */
187 } mdb_symbol_t;
188 
189 extern int mdb_pwalk(const char *, mdb_walk_cb_t, void *, uintptr_t);
190 extern int mdb_walk(const char *, mdb_walk_cb_t, void *);
191 
192 extern int mdb_pwalk_dcmd(const char *, const char *,
193 	int, const mdb_arg_t *, uintptr_t);
194 extern int mdb_fpwalk_dcmd(const char *, const char *,
195 	int, const mdb_arg_t *, uintptr_t, uint_t);
196 
197 extern int mdb_walk_dcmd(const char *, const char *, int, const mdb_arg_t *);
198 
199 extern int mdb_layered_walk(const char *, mdb_walk_state_t *);
200 
201 extern int mdb_call_dcmd(const char *, uintptr_t,
202 	uint_t, int, const mdb_arg_t *);
203 
204 extern int mdb_add_walker(const mdb_walker_t *);
205 extern int mdb_remove_walker(const char *);
206 
207 extern ssize_t mdb_vread(void *, size_t, uintptr_t);
208 extern ssize_t mdb_vwrite(const void *, size_t, uintptr_t);
209 
210 extern ssize_t mdb_aread(void *, size_t, uintptr_t, void *);
211 extern ssize_t mdb_awrite(const void *, size_t, uintptr_t, void *);
212 
213 extern ssize_t mdb_fread(void *, size_t, uintptr_t);
214 extern ssize_t mdb_fwrite(const void *, size_t, uintptr_t);
215 
216 extern ssize_t mdb_pread(void *, size_t, uint64_t);
217 extern ssize_t mdb_pwrite(const void *, size_t, uint64_t);
218 
219 extern ssize_t mdb_readstr(char *, size_t, uintptr_t);
220 extern ssize_t mdb_writestr(const char *, uintptr_t);
221 
222 extern ssize_t mdb_readsym(void *, size_t, const char *);
223 extern ssize_t mdb_writesym(const void *, size_t, const char *);
224 
225 extern ssize_t mdb_readvar(void *, const char *);
226 extern ssize_t mdb_writevar(const void *, const char *);
227 
228 #define	MDB_SYM_NAMLEN	1024			/* Recommended max name len */
229 
230 #define	MDB_SYM_FUZZY	0			/* Match closest address */
231 #define	MDB_SYM_EXACT	1			/* Match exact address only */
232 
233 #define	MDB_OBJ_EXEC	((const char *)0L)	/* Primary executable file */
234 #define	MDB_OBJ_RTLD	((const char *)1L)	/* Run-time link-editor */
235 #define	MDB_OBJ_EVERY	((const char *)-1L)	/* All known symbols */
236 
237 extern int mdb_lookup_by_name(const char *, GElf_Sym *);
238 extern int mdb_lookup_by_obj(const char *, const char *, GElf_Sym *);
239 extern int mdb_lookup_by_addr(uintptr_t, uint_t, char *, size_t, GElf_Sym *);
240 
241 typedef uintptr_t mdb_tid_t;
242 typedef uint64_t mdb_reg_t;
243 
244 extern int mdb_getareg(mdb_tid_t, const char *, mdb_reg_t *);
245 extern int mdb_thread_name(mdb_tid_t, char *, size_t);
246 
247 #define	MDB_OPT_SETBITS	1			/* Set specified flag bits */
248 #define	MDB_OPT_CLRBITS	2			/* Clear specified flag bits */
249 #define	MDB_OPT_STR	3			/* const char * argument */
250 #define	MDB_OPT_UINTPTR	4			/* uintptr_t argument */
251 #define	MDB_OPT_UINT64	5			/* uint64_t argument */
252 #define	MDB_OPT_UINTPTR_SET	6		/* boolean_t+uintptr_t args */
253 
254 extern int mdb_getopts(int, const mdb_arg_t *, ...) __sentinel(0);
255 
256 extern u_longlong_t mdb_strtoull(const char *);
257 
258 #define	UM_NOSLEEP	0x0	/* Do not call failure handler; may fail */
259 #define	UM_SLEEP	0x1	/* Can block for memory; will always succeed */
260 #define	UM_GC		0x2	/* Garbage-collect this block automatically */
261 
262 extern void *mdb_alloc(size_t, uint_t);
263 extern void *mdb_zalloc(size_t, uint_t);
264 extern void mdb_free(void *, size_t);
265 
266 #define	MDB_NICENUM_BUFLEN 6
267 
268 extern int mdb_snprintfrac(char *, int, uint64_t, uint64_t, int);
269 extern void mdb_nicenum(uint64_t, char *);
270 extern void mdb_nicetime(int64_t, char *, size_t);
271 
272 extern size_t mdb_snprintf(char *, size_t, const char *, ...);
273 extern void mdb_printf(const char *, ...);
274 extern void mdb_warn(const char *, ...);
275 extern void mdb_flush(void);
276 
277 extern int mdb_ffs(uintmax_t);
278 
279 extern void mdb_nhconvert(void *, const void *, size_t);
280 
281 #define	MDB_DUMP_RELATIVE	0x0001	/* Start numbering at 0 */
282 #define	MDB_DUMP_ALIGN		0x0002	/* Enforce paragraph alignment */
283 #define	MDB_DUMP_PEDANT		0x0004	/* Full-width addresses */
284 #define	MDB_DUMP_ASCII		0x0008	/* Display ASCII values */
285 #define	MDB_DUMP_HEADER		0x0010	/* Display a header */
286 #define	MDB_DUMP_TRIM		0x0020	/* Trim at boundaries */
287 #define	MDB_DUMP_SQUISH		0x0040	/* Eliminate redundant lines */
288 #define	MDB_DUMP_NEWDOT		0x0080	/* Update dot when done */
289 #define	MDB_DUMP_ENDIAN		0x0100	/* Adjust for endianness */
290 #define	MDB_DUMP_WIDTH(x)	((((x) - 1) & 0xf) << 16) /* paragraphs/line */
291 #define	MDB_DUMP_GROUP(x)	((((x) - 1) & 0xff) << 20) /* bytes/group */
292 
293 typedef ssize_t (*mdb_dumpptr_cb_t)(void *, size_t, uintptr_t, void *);
294 typedef ssize_t (*mdb_dump64_cb_t)(void *, size_t, uint64_t, void *);
295 
296 extern int mdb_dumpptr(uintptr_t, size_t, uint_t, mdb_dumpptr_cb_t, void *);
297 extern int mdb_dump64(uint64_t, uint64_t, uint_t, mdb_dump64_cb_t, void *);
298 
299 extern const char *mdb_one_bit(int, int, int);
300 extern const char *mdb_inval_bits(int, int, int);
301 
302 extern ulong_t mdb_inc_indent(ulong_t);
303 extern ulong_t mdb_dec_indent(ulong_t);
304 
305 extern int mdb_eval(const char *);
306 extern void mdb_set_dot(uintmax_t);
307 extern uintmax_t mdb_get_dot(void);
308 
309 extern void mdb_get_pipe(mdb_pipe_t *);
310 extern void mdb_set_pipe(const mdb_pipe_t *);
311 
312 extern ssize_t mdb_get_xdata(const char *, void *, size_t);
313 
314 typedef int (*mdb_object_cb_t)(mdb_object_t *, void *);
315 extern int mdb_object_iter(mdb_object_cb_t, void *);
316 
317 #define	MDB_SYMTAB		1	/* Normal symbol table (.symtab) */
318 #define	MDB_DYNSYM		2	/* Dynamic symbol table (.dynsym) */
319 
320 #define	MDB_BIND_LOCAL		0x0001	/* Local (static-scope) symbols */
321 #define	MDB_BIND_GLOBAL		0x0002	/* Global symbols */
322 #define	MDB_BIND_WEAK		0x0004	/* Weak binding symbols */
323 #define	MDB_BIND_ANY		0x0007	/* Any of the above */
324 
325 #define	MDB_TYPE_NOTYPE		0x0100	/* Symbol has no type */
326 #define	MDB_TYPE_OBJECT		0x0200	/* Symbol refers to data */
327 #define	MDB_TYPE_FUNC		0x0400	/* Symbol refers to text */
328 #define	MDB_TYPE_SECT		0x0800	/* Symbol refers to a section */
329 #define	MDB_TYPE_FILE		0x1000	/* Symbol refers to a source file */
330 #define	MDB_TYPE_COMMON		0x2000	/* Symbol refers to a common block */
331 #define	MDB_TYPE_TLS		0x4000	/* Symbol refers to TLS */
332 
333 #define	MDB_TYPE_ANY		0x7f00	/* Any of the above */
334 
335 typedef int (*mdb_symbol_cb_t)(mdb_symbol_t *, void *);
336 extern int mdb_symbol_iter(const char *, uint_t, uint_t, mdb_symbol_cb_t,
337     void *);
338 
339 #define	MDB_STATE_IDLE		0	/* Target is idle (not running yet) */
340 #define	MDB_STATE_RUNNING	1	/* Target is currently executing */
341 #define	MDB_STATE_STOPPED	2	/* Target is stopped */
342 #define	MDB_STATE_UNDEAD	3	/* Target is undead (zombie) */
343 #define	MDB_STATE_DEAD		4	/* Target is dead (core dump) */
344 #define	MDB_STATE_LOST		5	/* Target lost by debugger */
345 
346 extern int mdb_get_state(void);
347 
348 #define	MDB_CALLBACK_STCHG	1
349 #define	MDB_CALLBACK_PROMPT	2
350 
351 typedef void (*mdb_callback_f)(void *);
352 
353 extern void *mdb_callback_add(int, mdb_callback_f, void *);
354 extern void mdb_callback_remove(void *);
355 
356 #define	MDB_TABC_ALL_TYPES	0x1	/* Include array types in type output */
357 #define	MDB_TABC_MEMBERS	0x2	/* Tab comp. types with members */
358 #define	MDB_TABC_NOPOINT	0x4	/* Tab comp. everything but pointers */
359 #define	MDB_TABC_NOARRAY	0x8	/* Don't include array data in output */
360 
361 /*
362  * Module's interaction path
363  */
364 extern void mdb_tab_insert(mdb_tab_cookie_t *, const char *);
365 extern void mdb_tab_setmbase(mdb_tab_cookie_t *, const char *);
366 
367 /*
368  * Tab completion utility functions for modules.
369  */
370 extern int mdb_tab_complete_type(mdb_tab_cookie_t *, const char *, uint_t);
371 extern int mdb_tab_complete_member(mdb_tab_cookie_t *, const char *,
372     const char *);
373 extern int mdb_tab_typename(int *, const mdb_arg_t **, char *buf, size_t len);
374 
375 /*
376  * Tab completion functions for common signatures.
377  */
378 extern int mdb_tab_complete_mt(mdb_tab_cookie_t *, uint_t, int,
379     const mdb_arg_t *);
380 
381 extern size_t strlcat(char *, const char *, size_t);
382 extern char *strcat(char *, const char *);
383 extern char *strcpy(char *, const char *);
384 extern char *strncpy(char *, const char *, size_t);
385 
386 /* Need to be consistent with <string.h> C++ definitions */
387 #if __cplusplus >= 199711L
388 extern const char *strchr(const char *, int);
389 #ifndef	_STRCHR_INLINE
390 #define	_STRCHR_INLINE
391 extern "C++" {
strchr(char * __s,int __c)392 	inline char *strchr(char *__s, int __c) {
393 		return (char *)strchr((const char *)__s, __c);
394 	}
395 }
396 #endif	/* _STRCHR_INLINE */
397 extern const char *strrchr(const char *, int);
398 #ifndef	_STRRCHR_INLINE
399 #define	_STRRCHR_INLINE
400 extern	"C++" {
strrchr(char * __s,int __c)401 	inline char *strrchr(char *__s, int __c) {
402 		return (char *)strrchr((const char *)__s, __c);
403 	}
404 }
405 #endif	/* _STRRCHR_INLINE */
406 extern const char *strstr(const char *, const char *);
407 #ifndef	_STRSTR_INLINE
408 #define	_STRSTR_INLINE
409 extern "C++" {
strstr(char * __s1,const char * __s2)410 	inline char *strstr(char *__s1, const char *__s2) {
411 		return (char *)strstr((const char *)__s1, __s2);
412 	}
413 }
414 #endif	/* _STRSTR_INLINE */
415 #else
416 extern char *strchr(const char *, int);
417 extern char *strrchr(const char *, int);
418 extern char *strstr(const char *, const char *);
419 #endif	/* __cplusplus >= 199711L */
420 
421 extern int strcmp(const char *, const char *);
422 extern int strncmp(const char *, const char *, size_t);
423 extern int strcasecmp(const char *, const char *);
424 extern int strncasecmp(const char *, const char *, size_t);
425 
426 extern size_t strlen(const char *);
427 
428 extern int bcmp(const void *, const void *, size_t);
429 extern void bcopy(const void *, void *, size_t);
430 extern void bzero(void *, size_t);
431 
432 extern void *memcpy(void *, const void *, size_t);
433 extern void *memmove(void *, const void *, size_t);
434 extern int memcmp(const void *, const void *, size_t);
435 /* Need to be consistent with <string.h> C++ definitions */
436 #if __cplusplus >= 199711L
437 extern const void *memchr(const void *, int, size_t);
438 #ifndef _MEMCHR_INLINE
439 #define	_MEMCHR_INLINE
440 extern "C++" {
memchr(void * __s,int __c,size_t __n)441 	inline void *memchr(void * __s, int __c, size_t __n) {
442 		return (void *)memchr((const void *)__s, __c, __n);
443 	}
444 }
445 #endif  /* _MEMCHR_INLINE */
446 #else
447 extern void *memchr(const void *, int, size_t);
448 #endif /* __cplusplus >= 199711L */
449 extern void *memset(void *, int, size_t);
450 extern void *memccpy(void *, const void *, int, size_t);
451 
452 extern void *bsearch(const void *, const void *, size_t, size_t,
453     int (*)(const void *, const void *));
454 
455 extern void qsort(void *, size_t, size_t,
456     int (*)(const void *, const void *));
457 
458 #ifdef	__cplusplus
459 }
460 #endif
461 
462 #endif	/* _MDB_MODAPI_H */
463