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