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 (c) 2012 Joyent, Inc. All rights reserved.
  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 <gelf.h>
  41 
  42 #ifdef  __cplusplus
  43 extern "C" {
  44 #endif
  45 
  46 /*
  47  * Make sure that NULL, TRUE, FALSE, MIN, and MAX have the usual definitions
  48  * so module writers can depend on these macros and defines.
  49  */
  50 #ifndef NULL
  51 #if defined(_LP64) && !defined(__cplusplus)
  52 #define NULL    0L
  53 #else
  54 #define NULL    0
  55 #endif
  56 #endif
  57 
  58 #ifndef TRUE
  59 #define TRUE    1
  60 #endif
  61 
  62 #ifndef FALSE
  63 #define FALSE   0
  64 #endif
  65 
  66 #ifndef MIN
  67 #define MIN(x, y) ((x) < (y) ? (x) : (y))
  68 #endif
  69 
  70 #ifndef MAX
  71 #define MAX(x, y) ((x) > (y) ? (x) : (y))
  72 #endif
  73 
  74 #define MDB_API_VERSION 4       /* Current API version number */
  75 
  76 /*
  77  * Debugger command function flags:
  78  */
  79 #define DCMD_ADDRSPEC   0x01    /* Dcmd invoked with explicit address */
  80 #define DCMD_LOOP       0x02    /* Dcmd invoked in loop with ,cnt syntax */
  81 #define DCMD_LOOPFIRST  0x04    /* Dcmd invoked as first iteration of LOOP */
  82 #define DCMD_PIPE       0x08    /* Dcmd invoked with input from pipe */
  83 #define DCMD_PIPE_OUT   0x10    /* Dcmd invoked with output set to pipe */
  84 
  85 #define DCMD_HDRSPEC(fl)        (((fl) & DCMD_LOOPFIRST) || !((fl) & DCMD_LOOP))
  86 
  87 /*
  88  * Debugger tab command function flags
  89  */
  90 #define DCMD_TAB_SPACE  0x01    /* Tab cb invoked with trailing space */
  91 
  92 /*
  93  * Debugger command function return values:
  94  */
  95 #define DCMD_OK         0       /* Dcmd completed successfully */
  96 #define DCMD_ERR        1       /* Dcmd failed due to an error */
  97 #define DCMD_USAGE      2       /* Dcmd usage error; abort and print usage */
  98 #define DCMD_NEXT       3       /* Invoke next dcmd in precedence list */
  99 #define DCMD_ABORT      4       /* Dcmd failed; abort current loop or pipe */
 100 
 101 #define OFFSETOF(s, m)          (size_t)(&(((s *)0)->m))
 102 
 103 extern int mdb_prop_postmortem; /* Are we looking at a static dump? */
 104 extern int mdb_prop_kernel;     /* Are we looking at a kernel? */
 105 
 106 typedef enum {
 107         MDB_TYPE_STRING,        /* a_un.a_str is valid */
 108         MDB_TYPE_IMMEDIATE,     /* a_un.a_val is valid */
 109         MDB_TYPE_CHAR           /* a_un.a_char is valid */
 110 } mdb_type_t;
 111 
 112 typedef struct mdb_arg {
 113         mdb_type_t a_type;
 114         union {
 115                 const char *a_str;
 116                 uintmax_t a_val;
 117                 char a_char;
 118         } a_un;
 119 } mdb_arg_t;
 120 
 121 typedef struct mdb_tab_cookie mdb_tab_cookie_t;
 122 typedef int mdb_dcmd_f(uintptr_t, uint_t, int, const mdb_arg_t *);
 123 typedef int mdb_dcmd_tab_f(mdb_tab_cookie_t *, uint_t, int,
 124     const mdb_arg_t *);
 125 
 126 typedef struct mdb_dcmd {
 127         const char *dc_name;            /* Command name */
 128         const char *dc_usage;           /* Usage message (optional) */
 129         const char *dc_descr;           /* Description */
 130         mdb_dcmd_f *dc_funcp;           /* Command function */
 131         void (*dc_help)(void);          /* Command help function (or NULL) */
 132         mdb_dcmd_tab_f *dc_tabp;        /* Tab completion function */
 133 } mdb_dcmd_t;
 134 
 135 #define WALK_ERR        -1              /* Walk fatal error (terminate walk) */
 136 #define WALK_NEXT       0               /* Walk should continue to next step */
 137 #define WALK_DONE       1               /* Walk is complete (no errors) */
 138 
 139 typedef int (*mdb_walk_cb_t)(uintptr_t, const void *, void *);
 140 
 141 typedef struct mdb_walk_state {
 142         mdb_walk_cb_t walk_callback;    /* Callback to issue */
 143         void *walk_cbdata;              /* Callback private data */
 144         uintptr_t walk_addr;            /* Current address */
 145         void *walk_data;                /* Walk private data */
 146         void *walk_arg;                 /* Walk private argument */
 147         const void *walk_layer;         /* Data from underlying layer */
 148 } mdb_walk_state_t;
 149 
 150 typedef struct mdb_walker {
 151         const char *walk_name;          /* Walk type name */
 152         const char *walk_descr;         /* Walk description */
 153         int (*walk_init)(mdb_walk_state_t *);   /* Walk constructor */
 154         int (*walk_step)(mdb_walk_state_t *);   /* Walk iterator */
 155         void (*walk_fini)(mdb_walk_state_t *);  /* Walk destructor */
 156         void *walk_init_arg;            /* Walk constructor argument */
 157 } mdb_walker_t;
 158 
 159 typedef struct mdb_modinfo {
 160         ushort_t mi_dvers;              /* Debugger version number */
 161         const mdb_dcmd_t *mi_dcmds;     /* NULL-terminated list of dcmds */
 162         const mdb_walker_t *mi_walkers; /* NULL-terminated list of walks */
 163 } mdb_modinfo_t;
 164 
 165 typedef struct mdb_bitmask {
 166         const char *bm_name;            /* String name to print */
 167         u_longlong_t bm_mask;           /* Mask for bits */
 168         u_longlong_t bm_bits;           /* Result required for value & mask */
 169 } mdb_bitmask_t;
 170 
 171 typedef struct mdb_pipe {
 172         uintptr_t *pipe_data;           /* Array of pipe values */
 173         size_t pipe_len;                /* Array length */
 174 } mdb_pipe_t;
 175 
 176 typedef struct mdb_object {
 177         const char *obj_name;           /* name of object */
 178         const char *obj_fullname;       /* full name of object */
 179         uintptr_t obj_base;             /* base address of object */
 180         uintptr_t obj_size;             /* in memory size of object in bytes */
 181 } mdb_object_t;
 182 
 183 typedef struct mdb_symbol {
 184         const char *sym_name;           /* name of symbol */
 185         const char *sym_object;         /* name of containing object */
 186         const GElf_Sym *sym_sym;        /* ELF symbol information */
 187         uint_t sym_table;               /* symbol table id */
 188         uint_t sym_id;                  /* symbol identifier */
 189 } mdb_symbol_t;
 190 
 191 extern int mdb_pwalk(const char *, mdb_walk_cb_t, void *, uintptr_t);
 192 extern int mdb_walk(const char *, mdb_walk_cb_t, void *);
 193 
 194 extern int mdb_pwalk_dcmd(const char *, const char *,
 195         int, const mdb_arg_t *, uintptr_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 
 246 #define MDB_OPT_SETBITS 1                       /* Set specified flag bits */
 247 #define MDB_OPT_CLRBITS 2                       /* Clear specified flag bits */
 248 #define MDB_OPT_STR     3                       /* const char * argument */
 249 #define MDB_OPT_UINTPTR 4                       /* uintptr_t argument */
 250 #define MDB_OPT_UINT64  5                       /* uint64_t argument */
 251 #define MDB_OPT_UINTPTR_SET     6               /* boolean_t+uintptr_t args */
 252 
 253 extern int mdb_getopts(int, const mdb_arg_t *, ...);
 254 
 255 extern u_longlong_t mdb_strtoull(const char *);
 256 
 257 #define UM_NOSLEEP      0x0     /* Do not call failure handler; may fail */
 258 #define UM_SLEEP        0x1     /* Can block for memory; will always succeed */
 259 #define UM_GC           0x2     /* Garbage-collect this block automatically */
 260 
 261 extern void *mdb_alloc(size_t, uint_t);
 262 extern void *mdb_zalloc(size_t, uint_t);
 263 extern void mdb_free(void *, size_t);
 264 
 265 extern size_t mdb_snprintf(char *, size_t, const char *, ...);
 266 extern void mdb_printf(const char *, ...);
 267 extern void mdb_warn(const char *, ...);
 268 extern void mdb_flush(void);
 269 
 270 extern int mdb_ffs(uintmax_t);
 271 
 272 extern 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 
 286 typedef ssize_t (*mdb_dumpptr_cb_t)(void *, size_t, uintptr_t, void *);
 287 typedef ssize_t (*mdb_dump64_cb_t)(void *, size_t, uint64_t, void *);
 288 
 289 extern int mdb_dumpptr(uintptr_t, size_t, uint_t, mdb_dumpptr_cb_t, void *);
 290 extern int mdb_dump64(uint64_t, uint64_t, uint_t, mdb_dump64_cb_t, void *);
 291 
 292 extern const char *mdb_one_bit(int, int, int);
 293 extern const char *mdb_inval_bits(int, int, int);
 294 
 295 extern ulong_t mdb_inc_indent(ulong_t);
 296 extern ulong_t mdb_dec_indent(ulong_t);
 297 
 298 extern int mdb_eval(const char *);
 299 extern void mdb_set_dot(uintmax_t);
 300 extern uintmax_t mdb_get_dot(void);
 301 
 302 extern void mdb_get_pipe(mdb_pipe_t *);
 303 extern void mdb_set_pipe(const mdb_pipe_t *);
 304 
 305 extern ssize_t mdb_get_xdata(const char *, void *, size_t);
 306 
 307 typedef int (*mdb_object_cb_t)(mdb_object_t *, void *);
 308 extern 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 
 328 typedef int (*mdb_symbol_cb_t)(mdb_symbol_t *, void *);
 329 extern 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 
 339 extern int mdb_get_state(void);
 340 
 341 #define MDB_CALLBACK_STCHG      1
 342 #define MDB_CALLBACK_PROMPT     2
 343 
 344 typedef void (*mdb_callback_f)(void *);
 345 
 346 extern void *mdb_callback_add(int, mdb_callback_f, void *);
 347 extern 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  */
 357 extern void mdb_tab_insert(mdb_tab_cookie_t *, const char *);
 358 extern void mdb_tab_setmbase(mdb_tab_cookie_t *, const char *);
 359 
 360 /*
 361  * Tab completion utility functions for modules.
 362  */
 363 extern int mdb_tab_complete_type(mdb_tab_cookie_t *, const char *, uint_t);
 364 extern int mdb_tab_complete_member(mdb_tab_cookie_t *, const char *,
 365     const char *);
 366 extern int mdb_tab_typename(int *, const mdb_arg_t **, char *buf, size_t len);
 367 
 368 /*
 369  * Tab completion functions for common signatures.
 370  */
 371 extern int mdb_tab_complete_mt(mdb_tab_cookie_t *, uint_t, int,
 372     const mdb_arg_t *);
 373 
 374 extern size_t strlcat(char *, const char *, size_t);
 375 extern char *strcat(char *, const char *);
 376 extern char *strcpy(char *, const char *);
 377 extern char *strncpy(char *, const char *, size_t);
 378 
 379 /* Need to be consistent with <string.h> C++ definitions */
 380 #if __cplusplus >= 199711L
 381 extern const char *strchr(const char *, int);
 382 #ifndef _STRCHR_INLINE
 383 #define _STRCHR_INLINE
 384 extern "C++" {
 385         inline char *strchr(char *__s, int __c) {
 386                 return (char *)strchr((const char *)__s, __c);
 387         }
 388 }
 389 #endif  /* _STRCHR_INLINE */
 390 extern const char *strrchr(const char *, int);
 391 #ifndef _STRRCHR_INLINE
 392 #define _STRRCHR_INLINE
 393 extern  "C++" {
 394         inline char *strrchr(char *__s, int __c) {
 395                 return (char *)strrchr((const char *)__s, __c);
 396         }
 397 }
 398 #endif  /* _STRRCHR_INLINE */
 399 extern const char *strstr(const char *, const char *);
 400 #ifndef _STRSTR_INLINE
 401 #define _STRSTR_INLINE
 402 extern "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
 409 extern char *strchr(const char *, int);
 410 extern char *strrchr(const char *, int);
 411 extern char *strstr(const char *, const char *);
 412 #endif  /* __cplusplus >= 199711L */
 413 
 414 extern int strcmp(const char *, const char *);
 415 extern int strncmp(const char *, const char *, size_t);
 416 extern int strcasecmp(const char *, const char *);
 417 extern int strncasecmp(const char *, const char *, size_t);
 418 
 419 extern size_t strlen(const char *);
 420 
 421 extern int bcmp(const void *, const void *, size_t);
 422 extern void bcopy(const void *, void *, size_t);
 423 extern void bzero(void *, size_t);
 424 
 425 extern void *memcpy(void *, const void *, size_t);
 426 extern void *memmove(void *, const void *, size_t);
 427 extern int memcmp(const void *, const void *, size_t);
 428 /* Need to be consistent with <string.h> C++ definitions */
 429 #if __cplusplus >= 199711L
 430 extern const void *memchr(const void *, int, size_t);
 431 #ifndef _MEMCHR_INLINE
 432 #define _MEMCHR_INLINE
 433 extern "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
 440 extern void *memchr(const void *, int, size_t);
 441 #endif /* __cplusplus >= 199711L */
 442 extern void *memset(void *, int, size_t);
 443 extern void *memccpy(void *, const void *, int, size_t);
 444 
 445 extern void *bsearch(const void *, const void *, size_t, size_t,
 446     int (*)(const void *, const void *));
 447 
 448 extern 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 */