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