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