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) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 #include <sys/mdb_modapi.h>
  27 #include <limits.h>
  28 
  29 #include <fmd_trace.h>
  30 #include <fmd_module.h>
  31 #include <fmd_thread.h>
  32 #include <fmd_ustat.h>
  33 #include <fmd_event.h>
  34 #include <fmd_case.h>
  35 #include <fmd_buf.h>
  36 #include <fmd_asru.h>
  37 #include <fmd_ckpt.h>
  38 #include <fmd_timerq.h>
  39 #include <fmd_xprt.h>
  40 
  41 #include <fmd.h>
  42 
  43 typedef struct trwalk_state {
  44         struct trwalk_state *trw_next;
  45         fmd_tracebuf_t trw_data;
  46         pthread_t trw_tid;
  47         uintptr_t trw_base;
  48         const fmd_tracerec_t *trw_stop;
  49         fmd_tracerec_t *trw_xrec;
  50 } trwalk_state_t;
  51 
  52 typedef struct hashwalk_data {
  53         uintptr_t *hw_hash;
  54         uint_t hw_hashlen;
  55         uint_t hw_hashidx;
  56         const char *hw_name;
  57         void *hw_data;
  58         size_t hw_size;
  59         size_t hw_next;
  60 } hashwalk_data_t;
  61 
  62 static int fmd_stat(uintptr_t, uint_t, int, const mdb_arg_t *);
  63 static int fmd_ustat(uintptr_t, uint_t, int, const mdb_arg_t *);
  64 
  65 static int
  66 trwalk_init(mdb_walk_state_t *wsp)
  67 {
  68         uintptr_t addr;
  69         fmd_thread_t thr;
  70         fmd_t F;
  71 
  72         if (wsp->walk_addr != NULL) {
  73                 mdb_warn("fmd_trace only supports global walks\n");
  74                 return (WALK_ERR);
  75         }
  76 
  77         if (mdb_readvar(&F, "fmd") != sizeof (F)) {
  78                 mdb_warn("failed to read fmd meta-data");
  79                 return (WALK_ERR);
  80         }
  81 
  82         for (addr = (uintptr_t)F.d_thr_list.l_next; addr != NULL;
  83             addr = (uintptr_t)thr.thr_list.l_next) {
  84 
  85                 size_t len, ptr_off, end_off;
  86                 fmd_tracerec_t *buf;
  87                 trwalk_state_t *t;
  88 
  89                 if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) {
  90                         mdb_warn("failed to read thread at %p "
  91                             "(some trace data will be unavailable)", addr);
  92                         break;
  93                 }
  94 
  95                 t = mdb_zalloc(sizeof (trwalk_state_t), UM_SLEEP);
  96                 t->trw_next = wsp->walk_data;
  97                 wsp->walk_data = t;
  98 
  99                 (void) mdb_vread(&t->trw_data,
 100                     sizeof (t->trw_data), (uintptr_t)thr.thr_trdata);
 101 
 102                 if (t->trw_data.tb_recs == 0)
 103                         continue; /* no trace buffer allocated for thread */
 104 
 105                 len = t->trw_data.tb_recs * t->trw_data.tb_size;
 106                 buf = mdb_alloc(len, UM_SLEEP);
 107 
 108                 t->trw_tid = thr.thr_tid;
 109                 t->trw_base = (uintptr_t)t->trw_data.tb_buf;
 110 
 111                 if (mdb_vread(buf, len, t->trw_base) == -1) {
 112                         mdb_warn("failed to read buffer for t%u", t->trw_tid);
 113                         bzero(buf, len);
 114                 }
 115 
 116                 end_off = (uintptr_t)t->trw_data.tb_end - t->trw_base;
 117                 ptr_off = (uintptr_t)t->trw_data.tb_ptr - t->trw_base;
 118 
 119                 t->trw_data.tb_buf = buf;
 120                 t->trw_data.tb_end = (void *)((uintptr_t)buf + end_off);
 121                 t->trw_data.tb_ptr = (void *)((uintptr_t)buf + ptr_off);
 122 
 123                 if (t->trw_data.tb_ptr < t->trw_data.tb_buf ||
 124                     t->trw_data.tb_ptr > t->trw_data.tb_end) {
 125                         mdb_warn("trace record ptr for t%u is corrupt "
 126                             "(some data may be unavailable)\n", t->trw_tid);
 127                         t->trw_data.tb_ptr = t->trw_data.tb_buf;
 128                 }
 129 
 130                 t->trw_stop = t->trw_data.tb_ptr;
 131                 t->trw_xrec = mdb_alloc(
 132                     t->trw_data.tb_size + sizeof (uintptr_t), UM_SLEEP);
 133         }
 134 
 135         return (WALK_NEXT);
 136 }
 137 
 138 static fmd_tracerec_t *
 139 trwalk_nextrec(trwalk_state_t *t)
 140 {
 141         if (t->trw_stop == NULL)
 142                 return (t->trw_data.tb_ptr);
 143 
 144         if (t->trw_data.tb_ptr == t->trw_data.tb_buf)
 145                 t->trw_data.tb_ptr = t->trw_data.tb_end;
 146         else
 147                 t->trw_data.tb_ptr = (fmd_tracerec_t *)
 148                     ((uintptr_t)t->trw_data.tb_ptr - t->trw_data.tb_size);
 149 
 150         if (t->trw_data.tb_ptr == t->trw_stop)
 151                 t->trw_stop = NULL; /* mark buffer as empty */
 152 
 153         return (t->trw_data.tb_ptr);
 154 }
 155 
 156 static int
 157 trwalk_step(mdb_walk_state_t *wsp)
 158 {
 159         trwalk_state_t *t, *oldest_t;
 160         hrtime_t oldest_time = 0;
 161         fmd_tracerec_t *trp;
 162         int status;
 163 
 164         for (t = wsp->walk_data; t != NULL; t = t->trw_next) {
 165                 for (trp = t->trw_data.tb_ptr; t->trw_stop != NULL &&
 166                     trp->tr_time == 0; trp = trwalk_nextrec(t))
 167                         continue;
 168 
 169                 if (t->trw_stop == NULL)
 170                         continue; /* buffer has been emptied */
 171 
 172                 if (trp->tr_time > oldest_time) {
 173                         oldest_time = trp->tr_time;
 174                         oldest_t = t;
 175                 }
 176         }
 177 
 178         if (oldest_time == 0)
 179                 return (WALK_DONE);
 180 
 181         t = oldest_t;
 182         trp = t->trw_data.tb_ptr;
 183 
 184         bcopy(trp, t->trw_xrec, t->trw_data.tb_size);
 185         t->trw_xrec->tr_depth = MIN(trp->tr_depth, t->trw_data.tb_frames);
 186         t->trw_xrec->tr_stack[t->trw_xrec->tr_depth] = t->trw_tid;
 187 
 188         status = wsp->walk_callback((uintptr_t)trp - (uintptr_t)
 189             t->trw_data.tb_buf + t->trw_base, t->trw_xrec, wsp->walk_cbdata);
 190 
 191         (void) trwalk_nextrec(t);
 192         return (status);
 193 }
 194 
 195 static void
 196 trwalk_fini(mdb_walk_state_t *wsp)
 197 {
 198         trwalk_state_t *t, *u;
 199 
 200         for (t = wsp->walk_data; t != NULL; t = u) {
 201                 u = t->trw_next;
 202                 mdb_free(t->trw_data.tb_buf,
 203                     t->trw_data.tb_recs * t->trw_data.tb_size);
 204                 mdb_free(t->trw_xrec, t->trw_data.tb_size + sizeof (uintptr_t));
 205                 mdb_free(t, sizeof (trwalk_state_t));
 206         }
 207 }
 208 
 209 /*ARGSUSED*/
 210 static int
 211 trprint_msg(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid)
 212 {
 213         if (tid == 0)
 214                 mdb_printf("%3lu ", trp->tr_stack[trp->tr_depth]);
 215         else if (trp->tr_stack[trp->tr_depth] != tid)
 216                 return (WALK_NEXT);
 217 
 218         mdb_printf("%016llx %04x %-5u %s\n",
 219             trp->tr_time, 1 << trp->tr_tag, trp->tr_errno, trp->tr_msg);
 220 
 221         return (WALK_NEXT);
 222 }
 223 
 224 /*ARGSUSED*/
 225 static int
 226 trprint_cpp(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid)
 227 {
 228         char file[64];
 229 
 230         if (tid == 0)
 231                 mdb_printf("%3lu ", trp->tr_stack[trp->tr_depth]);
 232         else if (trp->tr_stack[trp->tr_depth] != tid)
 233                 return (WALK_NEXT);
 234 
 235         if (mdb_readstr(file, sizeof (file), (uintptr_t)trp->tr_file) <= 0)
 236                 (void) strcpy(file, "???");
 237 
 238         mdb_printf("%016llx %04x %s: %u\n",
 239             trp->tr_time, 1 << trp->tr_tag, file, trp->tr_line);
 240 
 241         return (WALK_NEXT);
 242 }
 243 
 244 static void
 245 trprint_stack(const fmd_tracerec_t *trp)
 246 {
 247         uint8_t i;
 248 
 249         for (i = 0; i < trp->tr_depth; i++)
 250                 mdb_printf("\t%a\n", trp->tr_stack[i]);
 251 
 252         if (trp->tr_depth != 0)
 253                 mdb_printf("\n");
 254 }
 255 
 256 static int
 257 trprint_msg_stack(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid)
 258 {
 259         int status = trprint_msg(addr, trp, tid);
 260         trprint_stack(trp);
 261         return (status);
 262 }
 263 
 264 static int
 265 trprint_cpp_stack(uintptr_t addr, const fmd_tracerec_t *trp, uintptr_t tid)
 266 {
 267         int status = trprint_cpp(addr, trp, tid);
 268         trprint_stack(trp);
 269         return (status);
 270 }
 271 
 272 static int
 273 fmd_trace(uintptr_t tid, uint_t flags, int argc, const mdb_arg_t *argv)
 274 {
 275         int (*func)(uintptr_t, const fmd_tracerec_t *, uintptr_t);
 276         uint_t opt_c = FALSE, opt_s = FALSE;
 277 
 278         if (mdb_getopts(argc, argv,
 279             'c', MDB_OPT_SETBITS, TRUE, &opt_c,
 280             's', MDB_OPT_SETBITS, TRUE, &opt_s, NULL) != argc)
 281                 return (DCMD_USAGE);
 282 
 283         if (!(flags & DCMD_ADDRSPEC)) {
 284                 mdb_printf("TID ");
 285                 tid = 0;
 286         }
 287 
 288         if (opt_c) {
 289                 mdb_printf("%-16s %-4s FILE:LINE\n", "TIME", "TAG");
 290                 func = opt_s ? trprint_cpp_stack : trprint_cpp;
 291         } else {
 292                 mdb_printf("%-16s %-4s %-5s MSG\n", "TIME", "TAG", "ERRNO");
 293                 func = opt_s ? trprint_msg_stack : trprint_msg;
 294         }
 295 
 296         if (mdb_walk("fmd_trace", (mdb_walk_cb_t)func, (void *)tid) == -1) {
 297                 mdb_warn("failed to walk fmd_trace");
 298                 return (DCMD_ERR);
 299         }
 300 
 301         return (DCMD_OK);
 302 }
 303 
 304 static int
 305 hash_walk_init(mdb_walk_state_t *wsp, uintptr_t addr, uint_t hashlen,
 306     const char *name, size_t size, size_t next)
 307 {
 308         hashwalk_data_t *hwp;
 309         size_t len = sizeof (uintptr_t) * hashlen;
 310 
 311         if (len == 0) {
 312                 mdb_warn("failed to walk hash: invalid hash length\n");
 313                 return (WALK_ERR);
 314         }
 315 
 316         hwp = mdb_alloc(sizeof (hashwalk_data_t), UM_SLEEP);
 317         hwp->hw_hash = mdb_zalloc(len, UM_SLEEP);
 318         (void) mdb_vread(hwp->hw_hash, len, addr);
 319         hwp->hw_hashlen = hashlen;
 320         hwp->hw_hashidx = 0;
 321         hwp->hw_name = name;
 322         hwp->hw_data = mdb_zalloc(size, UM_SLEEP);
 323         hwp->hw_size = size;
 324         hwp->hw_next = next;
 325 
 326         wsp->walk_addr = hwp->hw_hash[0];
 327         wsp->walk_data = hwp;
 328 
 329         return (WALK_NEXT);
 330 }
 331 
 332 static int
 333 hash_walk_step(mdb_walk_state_t *wsp)
 334 {
 335         hashwalk_data_t *hwp = wsp->walk_data;
 336         int rv;
 337 
 338         while (wsp->walk_addr == NULL) {
 339                 if (++hwp->hw_hashidx < hwp->hw_hashlen)
 340                         wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx];
 341                 else
 342                         return (WALK_DONE);
 343         }
 344 
 345         if (mdb_vread(hwp->hw_data, hwp->hw_size, wsp->walk_addr) == -1) {
 346                 mdb_warn("failed to read %s at %p",
 347                     hwp->hw_name, wsp->walk_addr);
 348                 return (WALK_ERR);
 349         }
 350 
 351         rv = wsp->walk_callback(wsp->walk_addr, hwp->hw_data, wsp->walk_cbdata);
 352         wsp->walk_addr = *(uintptr_t *)((uintptr_t)hwp->hw_data + hwp->hw_next);
 353         return (rv);
 354 }
 355 
 356 static void
 357 hash_walk_fini(mdb_walk_state_t *wsp)
 358 {
 359         hashwalk_data_t *hwp = wsp->walk_data;
 360 
 361         mdb_free(hwp->hw_hash, sizeof (uintptr_t) * hwp->hw_hashlen);
 362         mdb_free(hwp->hw_data, hwp->hw_size);
 363         mdb_free(hwp, sizeof (hashwalk_data_t));
 364 }
 365 
 366 static int
 367 ustat_walk_init(mdb_walk_state_t *wsp)
 368 {
 369         fmd_ustat_t us;
 370 
 371         if (mdb_vread(&us, sizeof (us), wsp->walk_addr) != sizeof (us)) {
 372                 mdb_warn("failed to read fmd_ustat_t at %p", wsp->walk_addr);
 373                 return (WALK_ERR);
 374         }
 375 
 376         return (hash_walk_init(wsp,
 377             (uintptr_t)us.us_hash, us.us_hashlen, NULL, 0, 0));
 378 }
 379 
 380 static int
 381 ustat_walk_step(mdb_walk_state_t *wsp)
 382 {
 383         hashwalk_data_t *hwp = wsp->walk_data;
 384         fmd_ustat_elem_t ue;
 385         fmd_stat_t s;
 386 
 387         while (wsp->walk_addr == NULL) {
 388                 if (++hwp->hw_hashidx < hwp->hw_hashlen)
 389                         wsp->walk_addr = hwp->hw_hash[hwp->hw_hashidx];
 390                 else
 391                         return (WALK_DONE);
 392         }
 393 
 394         if (mdb_vread(&ue, sizeof (ue), wsp->walk_addr) != sizeof (ue) ||
 395             mdb_vread(&s, sizeof (s), (uintptr_t)ue.use_stat) != sizeof (s)) {
 396                 mdb_warn("failed to read stat element at %p", wsp->walk_addr);
 397                 return (WALK_ERR);
 398         }
 399 
 400         wsp->walk_addr = (uintptr_t)ue.use_next;
 401 
 402         return (wsp->walk_callback(
 403             (uintptr_t)ue.use_stat, &s, wsp->walk_cbdata));
 404 }
 405 
 406 struct fmd_cmd_data {
 407         int argc;
 408         const mdb_arg_t *argv;
 409 };
 410 
 411 /* ARGSUSED */
 412 static int
 413 module_ustat(uintptr_t addr, const void *data, void *wsp)
 414 {
 415         fmd_module_t *modp = (fmd_module_t *)data;
 416         char name[PATH_MAX];
 417         const struct fmd_cmd_data *udp = wsp;
 418 
 419         if (mdb_readstr(name, sizeof (name), (uintptr_t)modp->mod_name) <= 0)
 420                 (void) mdb_snprintf(name, sizeof (name), "<%p>",
 421                     modp->mod_name);
 422         mdb_printf("%s\n", name);
 423         (void) fmd_ustat((uintptr_t)modp->mod_ustat,
 424             DCMD_ADDRSPEC | DCMD_LOOPFIRST, udp->argc, udp->argv);
 425         return (WALK_NEXT);
 426 }
 427 
 428 static int
 429 fmd_ustat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 430 {
 431         if (!(flags & DCMD_ADDRSPEC)) {
 432                 struct fmd_cmd_data ud;
 433 
 434                 ud.argc = argc;
 435                 ud.argv = argv;
 436                 if (mdb_walk("fmd_module", module_ustat, &ud) == -1) {
 437                         mdb_warn("failed to walk 'fmd_module'");
 438                         return (DCMD_ERR);
 439                 }
 440                 return (DCMD_OK);
 441         }
 442 
 443         if (mdb_pwalk_dcmd("fmd_ustat", "fmd_stat", argc, argv, addr) != 0) {
 444                 mdb_warn("failed to walk fmd_ustat at %p", addr);
 445                 return (DCMD_ERR);
 446         }
 447 
 448         return (DCMD_OK);
 449 }
 450 
 451 /* ARGSUSED */
 452 static int
 453 module_stat(uintptr_t addr, const void *data, void *wsp)
 454 {
 455         fmd_module_t *modp = (fmd_module_t *)data;
 456         char name[PATH_MAX];
 457         const struct fmd_cmd_data *udp = wsp;
 458         fmd_modstat_t *mod_stats;
 459 
 460         if (mdb_readstr(name, sizeof (name), (uintptr_t)modp->mod_name) <= 0) {
 461                 (void) mdb_snprintf(name, sizeof (name), "<%p>",
 462                     modp->mod_name);
 463         }
 464         mdb_printf("%s\n", name);
 465         mod_stats = modp->mod_stats;
 466         (void) fmd_stat((uintptr_t)&mod_stats->ms_loadtime,
 467             DCMD_ADDRSPEC | DCMD_LOOPFIRST, udp->argc, udp->argv);
 468         (void) fmd_stat((uintptr_t)&mod_stats->ms_snaptime,
 469             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 470         (void) fmd_stat((uintptr_t)&mod_stats->ms_accepted,
 471             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 472         (void) fmd_stat((uintptr_t)&mod_stats->ms_debugdrop,
 473             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 474         (void) fmd_stat((uintptr_t)&mod_stats->ms_memtotal,
 475             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 476         (void) fmd_stat((uintptr_t)&mod_stats->ms_memlimit,
 477             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 478         (void) fmd_stat((uintptr_t)&mod_stats->ms_buftotal,
 479             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 480         (void) fmd_stat((uintptr_t)&mod_stats->ms_buflimit,
 481             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 482         (void) fmd_stat((uintptr_t)&mod_stats->ms_thrtotal,
 483             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 484         (void) fmd_stat((uintptr_t)&mod_stats->ms_thrlimit,
 485             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 486         (void) fmd_stat((uintptr_t)&mod_stats->ms_doorthrtotal,
 487             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 488         (void) fmd_stat((uintptr_t)&mod_stats->ms_doorthrlimit,
 489             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 490         (void) fmd_stat((uintptr_t)&mod_stats->ms_caseopen,
 491             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 492         (void) fmd_stat((uintptr_t)&mod_stats->ms_casesolved,
 493             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 494         (void) fmd_stat((uintptr_t)&mod_stats->ms_caseclosed,
 495             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 496         (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_save,
 497             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 498         (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_restore,
 499             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 500         (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_zeroed,
 501             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 502         (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_cnt,
 503             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 504         (void) fmd_stat((uintptr_t)&mod_stats->ms_ckpt_time,
 505             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 506         (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtopen,
 507             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 508         (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtlimit,
 509             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 510         (void) fmd_stat((uintptr_t)&mod_stats->ms_xprtqlimit,
 511             DCMD_ADDRSPEC | DCMD_LOOP, udp->argc, udp->argv);
 512         return (WALK_NEXT);
 513 }
 514 
 515 /*ARGSUSED*/
 516 static int
 517 fmd_stat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 518 {
 519         char buf[512];
 520         fmd_stat_t s;
 521 
 522         if (argc != 0)
 523                 return (DCMD_USAGE);
 524 
 525         if (DCMD_HDRSPEC(flags))
 526                 mdb_printf("%<u>%-11s %-4s %-32s %s%</u>\n",
 527                     "ADDR", "TYPE", "NAME", "VALUE");
 528 
 529         if (!(flags & DCMD_ADDRSPEC)) {
 530                 struct fmd_cmd_data ud;
 531 
 532                 ud.argc = argc;
 533                 ud.argv = argv;
 534 
 535                 if (mdb_walk("fmd_module", module_stat, &ud) == -1) {
 536                         mdb_warn("failed to walk 'fmd_module'");
 537                         return (DCMD_ERR);
 538                 }
 539                 return (DCMD_OK);
 540         }
 541 
 542         if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
 543                 mdb_warn("failed to read statistic at %p", addr);
 544                 return (DCMD_ERR);
 545         }
 546 
 547         switch (s.fmds_type) {
 548         case FMD_TYPE_BOOL:
 549                 mdb_printf("%-11p %-4s %-32s %s\n", addr, "bool",
 550                     s.fmds_name, s.fmds_value.bool ? "true" : "false");
 551                 break;
 552         case FMD_TYPE_INT32:
 553                 mdb_printf("%-11p %-4s %-32s %d\n", addr, "i32",
 554                     s.fmds_name, s.fmds_value.i32);
 555                 break;
 556         case FMD_TYPE_UINT32:
 557                 mdb_printf("%-11p %-4s %-32s %u\n", addr, "ui32",
 558                     s.fmds_name, s.fmds_value.i32);
 559                 break;
 560         case FMD_TYPE_INT64:
 561                 mdb_printf("%-11p %-4s %-32s %lld\n", addr, "i64",
 562                     s.fmds_name, s.fmds_value.i64);
 563                 break;
 564         case FMD_TYPE_UINT64:
 565                 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "ui64",
 566                     s.fmds_name, s.fmds_value.ui64);
 567                 break;
 568         case FMD_TYPE_STRING:
 569                 if (mdb_readstr(buf, sizeof (buf),
 570                     (uintptr_t)s.fmds_value.str) < 0) {
 571                         (void) mdb_snprintf(buf, sizeof (buf), "<%p>",
 572                             s.fmds_value.str);
 573                 }
 574                 mdb_printf("%-11p %-4s %-32s %s\n", addr, "str",
 575                     s.fmds_name, buf);
 576                 break;
 577         case FMD_TYPE_TIME:
 578                 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "time",
 579                     s.fmds_name, s.fmds_value.ui64);
 580                 break;
 581         case FMD_TYPE_SIZE:
 582                 mdb_printf("%-11p %-4s %-32s %llu\n", addr, "size",
 583                     s.fmds_name, s.fmds_value.ui64);
 584                 break;
 585         default:
 586                 mdb_printf("%-11p %-4u %-32s ???\n", addr,
 587                     s.fmds_type, s.fmds_name);
 588                 break;
 589         }
 590 
 591         return (DCMD_OK);
 592 }
 593 
 594 /*ARGSUSED*/
 595 static int
 596 fmd_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 597 {
 598         char type[16], name[16];
 599         fmd_event_impl_t ev;
 600 
 601         if (argc != 0)
 602                 return (DCMD_USAGE);
 603 
 604         if (mdb_vread(&ev, sizeof (ev), addr) != sizeof (ev)) {
 605                 mdb_warn("failed to read fmd_event at %p", addr);
 606                 return (DCMD_ERR);
 607         }
 608 
 609         if (DCMD_HDRSPEC(flags)) {
 610                 mdb_printf("%<u>%-11s %-4s %-5s %-3s %-?s%</u>\n",
 611                     "ADDR", "TYPE", "STATE", "REF", "NVPAIR");
 612         }
 613 
 614         switch (ev.ev_type) {
 615         case FMD_EVT_PROTOCOL:
 616                 (void) strcpy(type, "PROT");
 617                 break;
 618         case FMD_EVT_GC:
 619                 (void) strcpy(type, "GC");
 620                 break;
 621         case FMD_EVT_CLOSE:
 622                 (void) strcpy(type, "CLSE");
 623                 break;
 624         case FMD_EVT_TIMEOUT:
 625                 (void) strcpy(type, "TIME");
 626                 break;
 627         case FMD_EVT_STATS:
 628                 (void) strcpy(type, "STAT");
 629                 break;
 630         case FMD_EVT_PUBLISH:
 631                 (void) strcpy(type, "PUBL");
 632                 break;
 633         case FMD_EVT_TOPO:
 634                 (void) strcpy(type, "TOPO");
 635                 break;
 636         default:
 637                 (void) mdb_snprintf(type, sizeof (type), "%u", ev.ev_type);
 638         }
 639 
 640         switch (ev.ev_state) {
 641         case FMD_EVS_RECEIVED:
 642                 (void) strcpy(name, "RECVD");
 643                 break;
 644         case FMD_EVS_ACCEPTED:
 645                 (void) strcpy(name, "ACCPT");
 646                 break;
 647         case FMD_EVS_DISCARDED:
 648                 (void) strcpy(name, "DSCRD");
 649                 break;
 650         case FMD_EVS_DIAGNOSED:
 651                 (void) strcpy(name, "DIAGN");
 652                 break;
 653         default:
 654                 (void) mdb_snprintf(name, sizeof (name), "%u", ev.ev_state);
 655         }
 656 
 657         mdb_printf("%-11p %-4s %-5s %-3u %p\n",
 658             addr, type, name, ev.ev_refs, ev.ev_nvl);
 659 
 660         return (DCMD_OK);
 661 }
 662 
 663 static int
 664 thread_walk_init(mdb_walk_state_t *wsp)
 665 {
 666         fmd_t F;
 667 
 668         if (mdb_readvar(&F, "fmd") != sizeof (F)) {
 669                 mdb_warn("failed to read fmd meta-data");
 670                 return (WALK_ERR);
 671         }
 672 
 673         wsp->walk_addr = (uintptr_t)F.d_thr_list.l_next;
 674         return (WALK_NEXT);
 675 }
 676 
 677 static int
 678 thread_walk_step(mdb_walk_state_t *wsp)
 679 {
 680         uintptr_t addr = wsp->walk_addr;
 681         fmd_thread_t t;
 682 
 683         if (addr == NULL)
 684                 return (WALK_DONE);
 685 
 686         if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) {
 687                 mdb_warn("failed to read fmd_thread at %p", addr);
 688                 return (WALK_ERR);
 689         }
 690 
 691         wsp->walk_addr = (uintptr_t)t.thr_list.l_next;
 692         return (wsp->walk_callback(addr, &t, wsp->walk_cbdata));
 693 }
 694 
 695 static int
 696 fmd_thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 697 {
 698         fmd_thread_t thr;
 699 
 700         if (!(flags & DCMD_ADDRSPEC))
 701                 return (mdb_walk_dcmd("fmd_thread", "fmd_thread", argc, argv));
 702 
 703         if (argc != 0)
 704                 return (DCMD_USAGE);
 705 
 706         if (mdb_vread(&thr, sizeof (thr), addr) != sizeof (thr)) {
 707                 mdb_warn("failed to read fmd_thread at %p", addr);
 708                 return (DCMD_ERR);
 709         }
 710 
 711         if (DCMD_HDRSPEC(flags)) {
 712                 mdb_printf("%<u>%-11s %-11s %-8s %-16s%</u>\n",
 713                     "ADDR", "MOD", "TID", "FUNC");
 714         }
 715 
 716         mdb_printf("%-11p %-11p %-8u %a\n",
 717             addr, thr.thr_mod, thr.thr_tid, thr.thr_func);
 718 
 719         return (DCMD_OK);
 720 }
 721 
 722 static int
 723 mod_walk_init(mdb_walk_state_t *wsp)
 724 {
 725         fmd_t F;
 726 
 727         if (mdb_readvar(&F, "fmd") != sizeof (F)) {
 728                 mdb_warn("failed to read fmd meta-data");
 729                 return (WALK_ERR);
 730         }
 731 
 732         wsp->walk_addr = (uintptr_t)F.d_mod_list.l_next;
 733         return (WALK_NEXT);
 734 }
 735 
 736 static int
 737 mod_walk_step(mdb_walk_state_t *wsp)
 738 {
 739         uintptr_t addr = wsp->walk_addr;
 740         fmd_module_t m;
 741 
 742         if (addr == NULL)
 743                 return (WALK_DONE);
 744 
 745         if (mdb_vread(&m, sizeof (m), addr) != sizeof (m)) {
 746                 mdb_warn("failed to read fmd_module at %p", addr);
 747                 return (WALK_ERR);
 748         }
 749 
 750         wsp->walk_addr = (uintptr_t)m.mod_list.l_next;
 751         return (wsp->walk_callback(addr, &m, wsp->walk_cbdata));
 752 }
 753 
 754 static int
 755 fmd_module(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 756 {
 757         fmd_module_t mod;
 758         char name[PATH_MAX];
 759 
 760         if (!(flags & DCMD_ADDRSPEC))
 761                 return (mdb_walk_dcmd("fmd_module", "fmd_module", argc, argv));
 762 
 763         if (argc != 0)
 764                 return (DCMD_USAGE);
 765 
 766         if (mdb_vread(&mod, sizeof (mod), addr) != sizeof (mod)) {
 767                 mdb_warn("failed to read fmd_module at %p", addr);
 768                 return (DCMD_ERR);
 769         }
 770 
 771         if (DCMD_HDRSPEC(flags)) {
 772                 mdb_printf("%<u>%-11s %-16s %-11s %-4s %-?s %-16s%</u>\n",
 773                     "ADDR", "OPS", "DATA", "FLAG", "USTAT", "NAME");
 774         }
 775 
 776         if (mdb_readstr(name, sizeof (name), (uintptr_t)mod.mod_name) <= 0)
 777                 (void) mdb_snprintf(name, sizeof (name), "<%p>", mod.mod_name);
 778 
 779         mdb_printf("%-11p %-16a %-11p 0x%02x %-?p %s\n", addr,
 780             mod.mod_ops, mod.mod_data, mod.mod_flags, mod.mod_ustat, name);
 781 
 782         return (DCMD_OK);
 783 }
 784 
 785 static int
 786 case_walk_init(mdb_walk_state_t *wsp)
 787 {
 788         fmd_module_t mod;
 789         fmd_case_hash_t ch;
 790         fmd_t F;
 791 
 792         if (wsp->walk_addr != NULL) {
 793                 if (mdb_vread(&mod, sizeof (mod), wsp->walk_addr) == -1) {
 794                         mdb_warn("failed to read module at %p", wsp->walk_addr);
 795                         return (WALK_ERR);
 796                 }
 797 
 798                 wsp->walk_addr = (uintptr_t)mod.mod_cases.l_next;
 799                 return (WALK_NEXT);
 800         }
 801 
 802         if (mdb_readvar(&F, "fmd") != sizeof (F) ||
 803             mdb_vread(&ch, sizeof (ch), (uintptr_t)F.d_cases) != sizeof (ch)) {
 804                 mdb_warn("failed to read fmd meta-data");
 805                 return (WALK_ERR);
 806         }
 807 
 808         return (hash_walk_init(wsp, (uintptr_t)ch.ch_hash, ch.ch_hashlen,
 809             "fmd_case", sizeof (fmd_case_impl_t),
 810             OFFSETOF(fmd_case_impl_t, ci_next)));
 811 }
 812 
 813 static int
 814 case_walk_step(mdb_walk_state_t *wsp)
 815 {
 816         uintptr_t addr = wsp->walk_addr;
 817         fmd_case_impl_t ci;
 818 
 819         if (wsp->walk_data != NULL)
 820                 return (hash_walk_step(wsp));
 821 
 822         if (addr == NULL)
 823                 return (WALK_DONE);
 824 
 825         if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) {
 826                 mdb_warn("failed to read fmd_case at %p", addr);
 827                 return (WALK_ERR);
 828         }
 829 
 830         wsp->walk_addr = (uintptr_t)ci.ci_list.l_next;
 831         return (wsp->walk_callback(addr, &ci, wsp->walk_cbdata));
 832 }
 833 
 834 static void
 835 case_walk_fini(mdb_walk_state_t *wsp)
 836 {
 837         if (wsp->walk_data != NULL)
 838                 hash_walk_fini(wsp);
 839 }
 840 
 841 static int
 842 fmd_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 843 {
 844         char uuid[48], name[16];
 845         fmd_case_impl_t ci;
 846 
 847         if (!(flags & DCMD_ADDRSPEC)) {
 848                 if (mdb_walk_dcmd("fmd_case", "fmd_case", argc, argv) != 0) {
 849                         mdb_warn("failed to walk fmd_case hash");
 850                         return (DCMD_ERR);
 851                 }
 852                 return (DCMD_OK);
 853         }
 854 
 855         if (mdb_vread(&ci, sizeof (ci), addr) != sizeof (ci)) {
 856                 mdb_warn("failed to read fmd_case at %p", addr);
 857                 return (DCMD_ERR);
 858         }
 859 
 860         if (DCMD_HDRSPEC(flags)) {
 861                 mdb_printf("%<u>%-11s %-5s %-3s %-?s %-36s%</u>\n",
 862                     "ADDR", "STATE", "REF", "DATA", "UUID");
 863         }
 864 
 865         if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)ci.ci_uuid) <= 0)
 866                 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", ci.ci_uuid);
 867 
 868         switch (ci.ci_state) {
 869         case FMD_CASE_UNSOLVED:
 870                 (void) strcpy(name, "UNSLV");
 871                 break;
 872         case FMD_CASE_SOLVED:
 873                 (void) strcpy(name, "SOLVE");
 874                 break;
 875         case FMD_CASE_CLOSE_WAIT:
 876                 (void) strcpy(name, "CWAIT");
 877                 break;
 878         case FMD_CASE_CLOSED:
 879                 (void) strcpy(name, "CLOSE");
 880                 break;
 881         case FMD_CASE_REPAIRED:
 882                 (void) strcpy(name, "RPAIR");
 883                 break;
 884         case FMD_CASE_RESOLVED:
 885                 (void) strcpy(name, "RSLVD");
 886                 break;
 887         default:
 888                 (void) mdb_snprintf(name, sizeof (name), "%u", ci.ci_state);
 889         }
 890 
 891         mdb_printf("%-11p %-5s %-3u %-?p %s\n",
 892             addr, name, ci.ci_refs, ci.ci_data, uuid);
 893 
 894         return (DCMD_OK);
 895 }
 896 
 897 static int
 898 buf_walk_init(mdb_walk_state_t *wsp)
 899 {
 900         fmd_buf_hash_t bh;
 901 
 902         if (mdb_vread(&bh, sizeof (bh), wsp->walk_addr) != sizeof (bh)) {
 903                 mdb_warn("failed to read fmd_buf_hash_t at %p", wsp->walk_addr);
 904                 return (WALK_ERR);
 905         }
 906 
 907         return (hash_walk_init(wsp, (uintptr_t)bh.bh_hash, bh.bh_hashlen,
 908             "fmd_buf", sizeof (fmd_buf_t), OFFSETOF(fmd_buf_t, buf_next)));
 909 }
 910 
 911 /*ARGSUSED*/
 912 static int
 913 fmd_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 914 {
 915         char name[PATH_MAX];
 916         fmd_buf_t b;
 917 
 918         if (argc != 0 || !(flags & DCMD_ADDRSPEC))
 919                 return (DCMD_USAGE);
 920 
 921         if (mdb_vread(&b, sizeof (b), addr) != sizeof (b)) {
 922                 mdb_warn("failed to read fmd_buf at %p", addr);
 923                 return (DCMD_ERR);
 924         }
 925 
 926         if (DCMD_HDRSPEC(flags)) {
 927                 mdb_printf("%<u>%-11s %-32s %-5s %-?s %s%</u>\n",
 928                     "ADDR", "NAME", "FLAGS", "DATA", "SIZE");
 929         }
 930 
 931         if (mdb_readstr(name, sizeof (name), (uintptr_t)b.buf_name) <= 0)
 932                 (void) mdb_snprintf(name, sizeof (name), "<%p>", b.buf_name);
 933 
 934         mdb_printf("%-11p %-32s %-#5x %-?p %lu\n",
 935             addr, name, b.buf_flags, b.buf_data, b.buf_size);
 936 
 937         return (DCMD_OK);
 938 }
 939 
 940 static int
 941 serd_walk_init(mdb_walk_state_t *wsp)
 942 {
 943         fmd_serd_hash_t sh;
 944 
 945         if (mdb_vread(&sh, sizeof (sh), wsp->walk_addr) != sizeof (sh)) {
 946                 mdb_warn("failed to read fmd_serd_hash at %p", wsp->walk_addr);
 947                 return (WALK_ERR);
 948         }
 949 
 950         return (hash_walk_init(wsp, (uintptr_t)sh.sh_hash, sh.sh_hashlen,
 951             "fmd_serd_eng", sizeof (fmd_serd_eng_t),
 952             OFFSETOF(fmd_serd_eng_t, sg_next)));
 953 }
 954 
 955 /* ARGSUSED */
 956 static int
 957 module_serd(uintptr_t addr, const void *data, void *wsp)
 958 {
 959         fmd_module_t *modp = (fmd_module_t *)data;
 960 
 961         if (modp->mod_serds.sh_count != 0) {
 962                 modp = (fmd_module_t *)addr;
 963                 (void) mdb_pwalk_dcmd("fmd_serd", "fmd_serd", 0, 0,
 964                     (uintptr_t)&modp->mod_serds);
 965         }
 966         return (WALK_NEXT);
 967 }
 968 
 969 /*ARGSUSED*/
 970 static int
 971 fmd_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 972 {
 973         char name[PATH_MAX];
 974         fmd_serd_eng_t sg;
 975 
 976         if (argc != 0)
 977                 return (DCMD_USAGE);
 978         if (!(flags & DCMD_ADDRSPEC)) {
 979                 if (mdb_walk("fmd_module", module_serd, 0) == -1) {
 980                         mdb_warn("failed to walk 'fmd_module'");
 981                         return (DCMD_ERR);
 982                 }
 983                 return (DCMD_OK);
 984         }
 985 
 986         if (mdb_vread(&sg, sizeof (sg), addr) != sizeof (sg)) {
 987                 mdb_warn("failed to read fmd_serd_eng at %p", addr);
 988                 return (DCMD_ERR);
 989         }
 990 
 991         if (DCMD_HDRSPEC(flags)) {
 992                 mdb_printf("%<u>%-11s %-32s %-3s F >%-2s %-16s%</u>\n",
 993                     "ADDR", "NAME", "CNT", "N", "T");
 994         }
 995 
 996         if (mdb_readstr(name, sizeof (name), (uintptr_t)sg.sg_name) <= 0)
 997                 (void) mdb_snprintf(name, sizeof (name), "<%p>", sg.sg_name);
 998 
 999         mdb_printf("%-11p %-32s %-3u %c >%-2u %lluns\n",
1000             addr, name, sg.sg_count, (sg.sg_flags & FMD_SERD_FIRED) ? 'F' : ' ',
1001             sg.sg_n, (u_longlong_t)sg.sg_t);
1002 
1003         return (DCMD_OK);
1004 }
1005 
1006 static int
1007 asru_walk_init(mdb_walk_state_t *wsp)
1008 {
1009         fmd_asru_hash_t ah;
1010         fmd_t F;
1011 
1012         if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) {
1013                 mdb_warn("failed to read fmd meta-data");
1014                 return (WALK_ERR);
1015         }
1016 
1017         if (wsp->walk_addr == NULL)
1018                 wsp->walk_addr = (uintptr_t)F.d_asrus;
1019 
1020         if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) {
1021                 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr);
1022                 return (WALK_ERR);
1023         }
1024 
1025         return (hash_walk_init(wsp, (uintptr_t)ah.ah_hash, ah.ah_hashlen,
1026             "fmd_asru", sizeof (fmd_asru_t), OFFSETOF(fmd_asru_t, asru_next)));
1027 }
1028 
1029 static int
1030 fmd_asru(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1031 {
1032         char uuid[48], name[PATH_MAX];
1033         fmd_asru_t a;
1034 
1035         if (!(flags & DCMD_ADDRSPEC)) {
1036                 if (mdb_walk_dcmd("fmd_asru", "fmd_asru", argc, argv) != 0) {
1037                         mdb_warn("failed to walk fmd_asru hash");
1038                         return (DCMD_ERR);
1039                 }
1040                 return (DCMD_OK);
1041         }
1042 
1043         if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
1044                 mdb_warn("failed to read fmd_asru at %p", addr);
1045                 return (DCMD_ERR);
1046         }
1047 
1048         if (DCMD_HDRSPEC(flags))
1049                 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME");
1050 
1051         if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.asru_uuid) <= 0)
1052                 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.asru_uuid);
1053         if (mdb_readstr(name, sizeof (name), (uintptr_t)a.asru_name) <= 0)
1054                 (void) mdb_snprintf(name, sizeof (name), "<%p>", a.asru_name);
1055 
1056         mdb_printf("%-8p %-36s %s\n", addr, uuid, name);
1057         return (DCMD_OK);
1058 }
1059 
1060 static int
1061 al_walk_init(mdb_walk_state_t *wsp)
1062 {
1063         fmd_asru_hash_t ah;
1064         fmd_t F;
1065 
1066         if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) {
1067                 mdb_warn("failed to read fmd meta-data");
1068                 return (WALK_ERR);
1069         }
1070 
1071         if (wsp->walk_addr == NULL)
1072                 wsp->walk_addr = (uintptr_t)F.d_asrus;
1073 
1074         if (mdb_vread(&ah, sizeof (ah), wsp->walk_addr) != sizeof (ah)) {
1075                 mdb_warn("failed to read asru_hash at %p", wsp->walk_addr);
1076                 return (WALK_ERR);
1077         }
1078 
1079         return (hash_walk_init(wsp, (uintptr_t)ah.ah_rsrc_hash, ah.ah_hashlen,
1080             "fmd_asru_link", sizeof (fmd_asru_link_t), OFFSETOF(fmd_asru_link_t,
1081             al_rsrc_next)));
1082 }
1083 
1084 static int
1085 fmd_asru_link(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1086 {
1087         char uuid[48], name[PATH_MAX];
1088         fmd_asru_link_t a;
1089 
1090         if (!(flags & DCMD_ADDRSPEC)) {
1091                 if (mdb_walk_dcmd("fmd_asru_link", "fmd_asru_link", argc,
1092                     argv) != 0) {
1093                         mdb_warn("failed to walk fmd_asru_link hash");
1094                         return (DCMD_ERR);
1095                 }
1096                 return (DCMD_OK);
1097         }
1098 
1099         if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
1100                 mdb_warn("failed to read fmd_asru_link at %p", addr);
1101                 return (DCMD_ERR);
1102         }
1103 
1104         if (DCMD_HDRSPEC(flags))
1105                 mdb_printf("%<u>%-8s %-36s %s%</u>\n", "ADDR", "UUID", "NAME");
1106 
1107         if (mdb_readstr(uuid, sizeof (uuid), (uintptr_t)a.al_uuid) <= 0)
1108                 (void) mdb_snprintf(uuid, sizeof (uuid), "<%p>", a.al_uuid);
1109         if (mdb_readstr(name, sizeof (name), (uintptr_t)a.al_rsrc_name) <= 0)
1110                 (void) mdb_snprintf(name, sizeof (name), "<%p>",
1111                     a.al_rsrc_name);
1112 
1113         mdb_printf("%-8p %-36s %s\n", addr, uuid, name);
1114         return (DCMD_OK);
1115 }
1116 
1117 /*ARGSUSED*/
1118 static int
1119 fcf_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1120 {
1121         fcf_hdr_t h;
1122 
1123         if (argc != 0)
1124                 return (DCMD_USAGE);
1125 
1126         if (!(flags & DCMD_ADDRSPEC))
1127                 addr = 0; /* assume base of file in file target */
1128 
1129         if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) {
1130                 mdb_warn("failed to read header at %p", addr);
1131                 return (DCMD_ERR);
1132         }
1133 
1134         mdb_printf("fcfh_ident.id_magic = 0x%x, %c, %c, %c\n",
1135             h.fcfh_ident[FCF_ID_MAG0], h.fcfh_ident[FCF_ID_MAG1],
1136             h.fcfh_ident[FCF_ID_MAG2], h.fcfh_ident[FCF_ID_MAG3]);
1137 
1138         switch (h.fcfh_ident[FCF_ID_MODEL]) {
1139         case FCF_MODEL_ILP32:
1140                 mdb_printf("fcfh_ident.id_model = ILP32\n");
1141                 break;
1142         case FCF_MODEL_LP64:
1143                 mdb_printf("fcfh_ident.id_model = LP64\n");
1144                 break;
1145         default:
1146                 mdb_printf("fcfh_ident.id_model = 0x%x\n",
1147                     h.fcfh_ident[FCF_ID_MODEL]);
1148         }
1149 
1150         switch (h.fcfh_ident[FCF_ID_ENCODING]) {
1151         case FCF_ENCODE_LSB:
1152                 mdb_printf("fcfh_ident.id_encoding = LSB\n");
1153                 break;
1154         case FCF_ENCODE_MSB:
1155                 mdb_printf("fcfh_ident.id_encoding = MSB\n");
1156                 break;
1157         default:
1158                 mdb_printf("fcfh_ident.id_encoding = 0x%x\n",
1159                     h.fcfh_ident[FCF_ID_ENCODING]);
1160         }
1161 
1162         mdb_printf("fcfh_ident.id_version = %u\n",
1163             h.fcfh_ident[FCF_ID_VERSION]);
1164 
1165         mdb_printf("fcfh_flags = 0x%x\n", h.fcfh_flags);
1166         mdb_printf("fcfh_hdrsize = %u\n", h.fcfh_hdrsize);
1167         mdb_printf("fcfh_secsize = %u\n", h.fcfh_secsize);
1168         mdb_printf("fcfh_secnum = %u\n", h.fcfh_secnum);
1169         mdb_printf("fcfh_secoff = %llu\n", h.fcfh_secoff);
1170         mdb_printf("fcfh_filesz = %llu\n", h.fcfh_filesz);
1171         mdb_printf("fcfh_cgen = %llu\n", h.fcfh_cgen);
1172 
1173         return (DCMD_OK);
1174 }
1175 
1176 static int fcf_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
1177 /*ARGSUSED*/
1178 static int
1179 fcf_sec_one(uintptr_t addr, void *ignored, uint_t *secp)
1180 {
1181 
1182         mdb_printf("%3d ", (*secp)++);
1183         (void) fcf_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL);
1184         return (WALK_NEXT);
1185 }
1186 
1187 /*ARGSUSED*/
1188 static int
1189 fcf_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1190 {
1191         static const char *const types[] = {
1192                 "none",         /* FCF_SECT_NONE */
1193                 "strtab",       /* FCF_SECT_STRTAB */
1194                 "module",       /* FCF_SECT_MODULE */
1195                 "case",         /* FCF_SECT_CASE */
1196                 "bufs",         /* FCF_SECT_BUFS */
1197                 "buffer",       /* FCF_SECT_BUFFER */
1198                 "serd",         /* FCF_SECT_SERD */
1199                 "events",       /* FCF_SECT_EVENTS */
1200                 "nvlists",      /* FCF_SECT_NVLISTS */
1201         };
1202 
1203         uint_t sec = 0;
1204         fcf_sec_t s;
1205 
1206         if (!(flags & DCMD_ADDRSPEC))
1207                 mdb_printf("%<u>%-3s ", "NDX");
1208 
1209         if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) {
1210                 mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
1211                     "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFF", "SIZE");
1212         }
1213 
1214         if (!(flags & DCMD_ADDRSPEC)) {
1215                 if (mdb_walk("fcf_sec", (mdb_walk_cb_t)fcf_sec_one, &sec) < 0) {
1216                         mdb_warn("failed to walk fcf_sec");
1217                         return (DCMD_ERR);
1218                 }
1219                 return (DCMD_OK);
1220         }
1221 
1222         if (argc != 0)
1223                 return (DCMD_USAGE);
1224 
1225         if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
1226                 mdb_warn("failed to read section header at %p", addr);
1227                 return (DCMD_ERR);
1228         }
1229 
1230         mdb_printf("%?p ", addr);
1231 
1232         if (s.fcfs_type < sizeof (types) / sizeof (types[0]))
1233                 mdb_printf("%-10s ", types[s.fcfs_type]);
1234         else
1235                 mdb_printf("%-10u ", s.fcfs_type);
1236 
1237         mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.fcfs_align,
1238             s.fcfs_flags, s.fcfs_entsize, s.fcfs_offset, s.fcfs_size);
1239 
1240         return (DCMD_OK);
1241 }
1242 
1243 static int
1244 fcf_sec_walk_init(mdb_walk_state_t *wsp)
1245 {
1246         fcf_hdr_t h, *hp;
1247         size_t size;
1248 
1249         if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) {
1250                 mdb_warn("failed to read FCF header at %p", wsp->walk_addr);
1251                 return (WALK_ERR);
1252         }
1253 
1254         size = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * h.fcfh_secnum;
1255         hp = mdb_alloc(size, UM_SLEEP);
1256 
1257         if (mdb_vread(hp, size, wsp->walk_addr) != size) {
1258                 mdb_warn("failed to read FCF sections at %p", wsp->walk_addr);
1259                 mdb_free(hp, size);
1260                 return (WALK_ERR);
1261         }
1262 
1263         wsp->walk_data = hp;
1264         wsp->walk_arg = 0;
1265 
1266         return (WALK_NEXT);
1267 }
1268 
1269 static int
1270 fcf_sec_walk_step(mdb_walk_state_t *wsp)
1271 {
1272         uint_t i = (uint_t)wsp->walk_arg;
1273         size_t off = sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * i;
1274         fcf_hdr_t *hp = wsp->walk_data;
1275         fcf_sec_t *sp = (fcf_sec_t *)((uintptr_t)hp + off);
1276 
1277         if (i >= hp->fcfh_secnum)
1278                 return (WALK_DONE);
1279 
1280         wsp->walk_arg = (void *)(i + 1);
1281         return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata));
1282 }
1283 
1284 static void
1285 fcf_sec_walk_fini(mdb_walk_state_t *wsp)
1286 {
1287         fcf_hdr_t *hp = wsp->walk_data;
1288         mdb_free(hp, sizeof (fcf_hdr_t) + sizeof (fcf_sec_t) * hp->fcfh_secnum);
1289 }
1290 
1291 /*ARGSUSED*/
1292 static int
1293 fcf_case(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1294 {
1295         fcf_case_t fcfc;
1296 
1297         if (argc != 0)
1298                 return (DCMD_USAGE);
1299 
1300         if (mdb_vread(&fcfc, sizeof (fcfc), addr) != sizeof (fcfc)) {
1301                 mdb_warn("failed to read case at %p", addr);
1302                 return (DCMD_ERR);
1303         }
1304 
1305         mdb_printf("fcfc_uuid = 0x%x\n", fcfc.fcfc_uuid);
1306         mdb_printf("fcfc_state = %u\n", fcfc.fcfc_state);
1307         mdb_printf("fcfc_bufs = %u\n", fcfc.fcfc_bufs);
1308         mdb_printf("fcfc_events = %u\n", fcfc.fcfc_events);
1309         mdb_printf("fcfc_suspects = %u\n", fcfc.fcfc_suspects);
1310 
1311         return (DCMD_OK);
1312 }
1313 
1314 /*ARGSUSED*/
1315 static int
1316 fcf_event(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1317 {
1318         fcf_event_t fcfe;
1319 
1320         if (argc != 0)
1321                 return (DCMD_USAGE);
1322 
1323         if (mdb_vread(&fcfe, sizeof (fcfe), addr) != sizeof (fcfe)) {
1324                 mdb_warn("failed to read event at %p", addr);
1325                 return (DCMD_ERR);
1326         }
1327 
1328         mdb_printf("fcfe_todsec = %llu (%Y)\n",
1329             fcfe.fcfe_todsec, (time_t)fcfe.fcfe_todsec);
1330         mdb_printf("fcfe_todnsec = %llu\n", fcfe.fcfe_todnsec);
1331         mdb_printf("fcfe_major = %u\n", fcfe.fcfe_major);
1332         mdb_printf("fcfe_minor = %u\n", fcfe.fcfe_minor);
1333         mdb_printf("fcfe_inode = %llu\n", fcfe.fcfe_inode);
1334         mdb_printf("fcfe_offset = %llu\n", fcfe.fcfe_offset);
1335 
1336         return (DCMD_OK);
1337 }
1338 
1339 /*ARGSUSED*/
1340 static int
1341 fcf_serd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1342 {
1343         fcf_serd_t fcfd;
1344 
1345         if (argc != 0)
1346                 return (DCMD_USAGE);
1347 
1348         if (mdb_vread(&fcfd, sizeof (fcfd), addr) != sizeof (fcfd)) {
1349                 mdb_warn("failed to read serd at %p", addr);
1350                 return (DCMD_ERR);
1351         }
1352 
1353         mdb_printf("fcfd_name = 0x%x\n", fcfd.fcfd_name);
1354         mdb_printf("fcfd_events = %u\n", fcfd.fcfd_events);
1355         mdb_printf("fcfd_n = >%u\n", fcfd.fcfd_n);
1356         mdb_printf("fcfd_t = %lluns\n", fcfd.fcfd_t);
1357 
1358         return (DCMD_OK);
1359 }
1360 
1361 static int
1362 tmq_walk_init(mdb_walk_state_t *wsp)
1363 {
1364         fmd_timerq_t tmq;
1365         fmd_t F;
1366 
1367         if (wsp->walk_addr == NULL && mdb_readvar(&F, "fmd") != sizeof (F)) {
1368                 mdb_warn("failed to read fmd meta-data");
1369                 return (WALK_ERR);
1370         }
1371 
1372         if (wsp->walk_addr == NULL)
1373                 wsp->walk_addr = (uintptr_t)F.d_timers;
1374 
1375         if (mdb_vread(&tmq, sizeof (tmq), wsp->walk_addr) != sizeof (tmq)) {
1376                 mdb_warn("failed to read timerq at %p", wsp->walk_addr);
1377                 return (WALK_ERR);
1378         }
1379 
1380         wsp->walk_addr = (uintptr_t)tmq.tmq_list.l_next;
1381         return (WALK_NEXT);
1382 }
1383 
1384 static int
1385 tmq_walk_step(mdb_walk_state_t *wsp)
1386 {
1387         uintptr_t addr = wsp->walk_addr;
1388         fmd_timer_t tmr;
1389 
1390         if (addr == NULL)
1391                 return (WALK_DONE);
1392 
1393         if (mdb_vread(&tmr, sizeof (tmr), addr) != sizeof (tmr)) {
1394                 mdb_warn("failed to read fmd_timer at %p", addr);
1395                 return (WALK_ERR);
1396         }
1397 
1398         wsp->walk_addr = (uintptr_t)tmr.tmr_list.l_next;
1399         return (wsp->walk_callback(addr, &tmr, wsp->walk_cbdata));
1400 }
1401 
1402 static int
1403 fmd_timer(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1404 {
1405         char name[32], func[MDB_SYM_NAMLEN];
1406         fmd_timer_t t;
1407 
1408         if (!(flags & DCMD_ADDRSPEC)) {
1409                 if (mdb_walk_dcmd("fmd_timerq", "fmd_timer", argc, argv) != 0) {
1410                         mdb_warn("failed to walk fmd_timerq");
1411                         return (DCMD_ERR);
1412                 }
1413                 return (DCMD_OK);
1414         }
1415 
1416         if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) {
1417                 mdb_warn("failed to read fmd_timer at %p", addr);
1418                 return (DCMD_ERR);
1419         }
1420 
1421         if (DCMD_HDRSPEC(flags)) {
1422                 mdb_printf("%<u>%-8s %-20s %-4s %-18s %-8s %s%</u>\n",
1423                     "ADDR", "MODULE", "ID", "HRTIME", "ARG", "FUNC");
1424         }
1425 
1426         if (mdb_readstr(name, sizeof (name), (uintptr_t)
1427             t.tmr_ids + OFFSETOF(fmd_idspace_t, ids_name)) <= 0)
1428                 (void) mdb_snprintf(name, sizeof (name), "<%p>", t.tmr_ids);
1429 
1430         if (mdb_lookup_by_addr((uintptr_t)t.tmr_func, MDB_SYM_FUZZY,
1431             func, sizeof (func), NULL) != 0)
1432                 (void) mdb_snprintf(func, sizeof (func), "<%p>", t.tmr_func);
1433 
1434         mdb_printf("%-8p %-20s %4d 0x%-16llx %-8p %s\n",
1435             addr, name, t.tmr_id, t.tmr_hrt, t.tmr_arg, func);
1436         return (DCMD_OK);
1437 }
1438 
1439 static int
1440 xprt_walk_init(mdb_walk_state_t *wsp)
1441 {
1442         fmd_module_t m;
1443 
1444         if (wsp->walk_addr == NULL) {
1445                 mdb_warn("transport walker requires fmd_module_t address\n");
1446                 return (WALK_ERR);
1447         }
1448 
1449         if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) {
1450                 mdb_warn("failed to read module at %p", wsp->walk_addr);
1451                 return (WALK_ERR);
1452         }
1453 
1454         wsp->walk_addr = (uintptr_t)m.mod_transports.l_next;
1455         return (WALK_NEXT);
1456 }
1457 
1458 static int
1459 xprt_walk_step(mdb_walk_state_t *wsp)
1460 {
1461         uintptr_t addr = wsp->walk_addr;
1462         fmd_xprt_impl_t xi;
1463 
1464         if (addr == NULL)
1465                 return (WALK_DONE);
1466 
1467         if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) {
1468                 mdb_warn("failed to read fmd_xprt at %p", addr);
1469                 return (WALK_ERR);
1470         }
1471 
1472         wsp->walk_addr = (uintptr_t)xi.xi_list.l_next;
1473         return (wsp->walk_callback(addr, &xi, wsp->walk_cbdata));
1474 }
1475 
1476 static int
1477 xpc_walk_init(mdb_walk_state_t *wsp)
1478 {
1479         fmd_xprt_class_hash_t xch;
1480 
1481         if (mdb_vread(&xch, sizeof (xch), wsp->walk_addr) != sizeof (xch)) {
1482                 mdb_warn("failed to read fmd_xprt_class_hash at %p",
1483                     wsp->walk_addr);
1484                 return (WALK_ERR);
1485         }
1486 
1487         return (hash_walk_init(wsp, (uintptr_t)xch.xch_hash, xch.xch_hashlen,
1488             "fmd_xprt_class", sizeof (fmd_xprt_class_t),
1489             OFFSETOF(fmd_xprt_class_t, xc_next)));
1490 }
1491 
1492 /*ARGSUSED*/
1493 static int
1494 fmd_xprt_class(uintptr_t addr, const void *data, void *arg)
1495 {
1496         const fmd_xprt_class_t *xcp = data;
1497         char name[1024];
1498 
1499         if (mdb_readstr(name, sizeof (name), (uintptr_t)xcp->xc_class) <= 0)
1500                 (void) mdb_snprintf(name, sizeof (name), "<%p>", xcp->xc_class);
1501 
1502         mdb_printf("%-8p %-4u %s\n", addr, xcp->xc_refs, name);
1503         return (WALK_NEXT);
1504 }
1505 
1506 static int
1507 fmd_xprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1508 {
1509         uint_t opt_s = FALSE, opt_l = FALSE, opt_r = FALSE, opt_u = FALSE;
1510         fmd_xprt_impl_t xi;
1511 
1512         if (mdb_getopts(argc, argv,
1513             'l', MDB_OPT_SETBITS, TRUE, &opt_l,
1514             'r', MDB_OPT_SETBITS, TRUE, &opt_r,
1515             's', MDB_OPT_SETBITS, TRUE, &opt_s,
1516             'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc)
1517                 return (DCMD_USAGE);
1518 
1519         if (!(flags & DCMD_ADDRSPEC)) {
1520                 if (mdb_walk_dcmd("fmd_xprt", "fmd_xprt", argc, argv) != 0) {
1521                         mdb_warn("failed to walk fmd_xprt");
1522                         return (DCMD_ERR);
1523                 }
1524                 return (DCMD_OK);
1525         }
1526 
1527         if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) {
1528                 mdb_warn("failed to read fmd_xprt at %p", addr);
1529                 return (DCMD_ERR);
1530         }
1531 
1532         if (DCMD_HDRSPEC(flags)) {
1533                 mdb_printf("%<u>%-8s %-4s %-4s %-5s %s%</u>\n",
1534                     "ADDR", "ID", "VERS", "FLAGS", "STATE");
1535         }
1536 
1537         mdb_printf("%-8p %-4d %-4u %-5x %a\n",
1538             addr, xi.xi_id, xi.xi_version, xi.xi_flags, xi.xi_state);
1539 
1540         if (opt_l | opt_s) {
1541                 (void) mdb_inc_indent(4);
1542                 mdb_printf("Local subscriptions requested by peer:\n");
1543                 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS");
1544                 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi,
1545                     addr + OFFSETOF(fmd_xprt_impl_t, xi_lsub));
1546                 (void) mdb_dec_indent(4);
1547         }
1548 
1549         if (opt_r | opt_s) {
1550                 (void) mdb_inc_indent(4);
1551                 mdb_printf("Remote subscriptions requested of peer:\n");
1552                 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS");
1553                 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi,
1554                     addr + OFFSETOF(fmd_xprt_impl_t, xi_rsub));
1555                 (void) mdb_dec_indent(4);
1556         }
1557 
1558         if (opt_u | opt_s) {
1559                 (void) mdb_inc_indent(4);
1560                 mdb_printf("Pending unsubscription acknowledgements:\n");
1561                 mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS");
1562                 (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi,
1563                     addr + OFFSETOF(fmd_xprt_impl_t, xi_usub));
1564                 (void) mdb_dec_indent(4);
1565         }
1566 
1567         return (DCMD_OK);
1568 }
1569 
1570 static int
1571 tsnap_walk_init(mdb_walk_state_t *wsp)
1572 {
1573         fmd_t F;
1574 
1575         if (mdb_readvar(&F, "fmd") != sizeof (F)) {
1576                 mdb_warn("failed to read fmd meta-data");
1577                 return (WALK_ERR);
1578         }
1579 
1580         wsp->walk_addr = (uintptr_t)F.d_topo_list.l_next;
1581         return (WALK_NEXT);
1582 }
1583 
1584 static int
1585 tsnap_walk_step(mdb_walk_state_t *wsp)
1586 {
1587         uintptr_t addr = wsp->walk_addr;
1588         fmd_topo_t ftp;
1589 
1590         if (addr == NULL)
1591                 return (WALK_DONE);
1592 
1593         if (mdb_vread(&ftp, sizeof (ftp), addr) != sizeof (ftp)) {
1594                 mdb_warn("failed to read fmd_topo_t at %p", addr);
1595                 return (WALK_ERR);
1596         }
1597 
1598         wsp->walk_addr = (uintptr_t)ftp.ft_list.l_next;
1599         return (wsp->walk_callback(addr, &ftp, wsp->walk_cbdata));
1600 }
1601 
1602 static int
1603 mq_walk_init(mdb_walk_state_t *wsp)
1604 {
1605         fmd_module_t m;
1606         struct fmd_eventq eq;
1607 
1608         if (wsp->walk_addr == NULL) {
1609                 mdb_warn("NULL fmd_module_t passed in");
1610                 return (WALK_ERR);
1611         }
1612 
1613         if (mdb_vread(&m, sizeof (m), wsp->walk_addr) != sizeof (m)) {
1614                 mdb_warn("failed to read fmd_module_t at %p", wsp->walk_addr);
1615                 return (WALK_ERR);
1616         }
1617         if (mdb_vread(&eq, sizeof (eq), (uintptr_t)m.mod_queue)
1618             != sizeof (eq)) {
1619                 mdb_warn("failed to read fmd_eventq at %p", wsp->walk_addr);
1620                 return (WALK_ERR);
1621         }
1622 
1623         wsp->walk_addr = (uintptr_t)eq.eq_list.l_next;
1624 
1625         return (WALK_NEXT);
1626 }
1627 
1628 static int
1629 mq_walk_step(mdb_walk_state_t *wsp)
1630 {
1631         uintptr_t addr = wsp->walk_addr;
1632         fmd_eventqelem_t eqe;
1633 
1634         if (addr == NULL)
1635                 return (WALK_DONE);
1636 
1637         if (mdb_vread(&eqe, sizeof (eqe), addr) != sizeof (eqe)) {
1638                 mdb_warn("failed to read fmd_eventqelem_t at %p", addr);
1639                 return (WALK_ERR);
1640         }
1641 
1642         wsp->walk_addr = (uintptr_t)eqe.eqe_list.l_next;
1643         return (wsp->walk_callback(addr, &eqe, wsp->walk_cbdata));
1644 }
1645 
1646 static const mdb_dcmd_t dcmds[] = {
1647         { "fcf_case", "?", "print a FCF case", fcf_case },
1648         { "fcf_event", "?", "print a FCF event", fcf_event },
1649         { "fcf_hdr", "?", "print a FCF header", fcf_hdr },
1650         { "fcf_sec", ":", "print a FCF section header", fcf_sec },
1651         { "fcf_serd", "?", "print a FCF serd engine", fcf_serd },
1652         { "fmd_trace", "?[-cs]", "display thread trace buffer(s)", fmd_trace },
1653         { "fmd_ustat", "[:]", "display statistics collection", fmd_ustat },
1654         { "fmd_stat", "[:]", "display statistic structure", fmd_stat },
1655         { "fmd_event", NULL, "display event structure", fmd_event },
1656         { "fmd_thread", "?", "display thread or list of threads", fmd_thread },
1657         { "fmd_module", "?", "display module or list of modules", fmd_module },
1658         { "fmd_case", ":", "display case file structure", fmd_case },
1659         { "fmd_buf", ":", "display buffer structure", fmd_buf },
1660         { "fmd_serd", "[:]", "display serd engine structure", fmd_serd },
1661         { "fmd_asru", "?", "display asru resource structure", fmd_asru },
1662         { "fmd_asru_link", "?", "display resource structure", fmd_asru_link },
1663         { "fmd_timer", "?", "display pending timer(s)", fmd_timer },
1664         { "fmd_xprt", "?[-lrsu]", "display event transport(s)", fmd_xprt },
1665         { NULL }
1666 };
1667 
1668 static const mdb_walker_t walkers[] = {
1669         { "fcf_sec", "walk FCF section header table given header address",
1670                 fcf_sec_walk_init, fcf_sec_walk_step, fcf_sec_walk_fini },
1671         { "fmd_trace", "walk per-thread trace buffers",
1672                 trwalk_init, trwalk_step, trwalk_fini },
1673         { "fmd_ustat", "walk per-collection statistics",
1674                 ustat_walk_init, ustat_walk_step, hash_walk_fini },
1675         { "fmd_thread", "walk list of all fmd_thread_t's",
1676                 thread_walk_init, thread_walk_step, NULL },
1677         { "fmd_module", "walk list of all fmd_module_t's",
1678                 mod_walk_init, mod_walk_step, NULL },
1679         { "fmd_case", "walk per-module case objects",
1680                 case_walk_init, case_walk_step, case_walk_fini },
1681         { "fmd_buf", "walk per-buf_hash buffers",
1682                 buf_walk_init, hash_walk_step, hash_walk_fini },
1683         { "fmd_serd", "walk per-serd_hash engines",
1684                 serd_walk_init, hash_walk_step, hash_walk_fini },
1685         { "fmd_asru", "walk asru resource hash",
1686                 asru_walk_init, hash_walk_step, hash_walk_fini },
1687         { "fmd_asru_link", "walk resource hash",
1688                 al_walk_init, hash_walk_step, hash_walk_fini },
1689         { "fmd_timerq", "walk timer queue",
1690                 tmq_walk_init, tmq_walk_step, NULL },
1691         { "fmd_xprt", "walk per-module list of transports",
1692                 xprt_walk_init, xprt_walk_step, NULL },
1693         { "fmd_xprt_class", "walk hash table of subscription classes",
1694                 xpc_walk_init, hash_walk_step, hash_walk_fini },
1695         { "fmd_topo", "walk fmd's list of topo snapshots",
1696                 tsnap_walk_init, tsnap_walk_step, NULL },
1697         { "fmd_mod_queue", "walk per-module event queue",
1698                 mq_walk_init, mq_walk_step, NULL },
1699         { NULL, NULL, NULL, NULL, NULL }
1700 };
1701 
1702 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
1703 
1704 const mdb_modinfo_t *
1705 _mdb_init(void)
1706 {
1707         return (&modinfo);
1708 }