18a40a695Sgavinm /*
28a40a695Sgavinm  * CDDL HEADER START
38a40a695Sgavinm  *
48a40a695Sgavinm  * The contents of this file are subject to the terms of the
58a40a695Sgavinm  * Common Development and Distribution License (the "License").
68a40a695Sgavinm  * You may not use this file except in compliance with the License.
78a40a695Sgavinm  *
88a40a695Sgavinm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98a40a695Sgavinm  * or http://www.opensolaris.org/os/licensing.
108a40a695Sgavinm  * See the License for the specific language governing permissions
118a40a695Sgavinm  * and limitations under the License.
128a40a695Sgavinm  *
138a40a695Sgavinm  * When distributing Covered Code, include this CDDL HEADER in each
148a40a695Sgavinm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158a40a695Sgavinm  * If applicable, add the following below this CDDL HEADER, with the
168a40a695Sgavinm  * fields enclosed by brackets "[]" replaced with your own identifying
178a40a695Sgavinm  * information: Portions Copyright [yyyy] [name of copyright owner]
188a40a695Sgavinm  *
198a40a695Sgavinm  * CDDL HEADER END
208a40a695Sgavinm  */
218a40a695Sgavinm 
228a40a695Sgavinm /*
23888e0559SRobert Johnston  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
248a40a695Sgavinm  * Use is subject to license terms.
25*3b442230SJordan Paige Hendricks  *
26*3b442230SJordan Paige Hendricks  * Copyright 2019 Joyent, Inc.
278a40a695Sgavinm  */
288a40a695Sgavinm 
298a40a695Sgavinm #include <sys/mdb_modapi.h>
308a40a695Sgavinm 
318a40a695Sgavinm #include <lut.h>
328a40a695Sgavinm #include <itree.h>
336cb1ca52Saf #include "ipath_impl.h"
346cb1ca52Saf #include "lut_impl.h"
356cb1ca52Saf #include "config_impl.h"
366cb1ca52Saf #include "stats_impl.h"
378a40a695Sgavinm 
388a40a695Sgavinm #define	LUT_SIZE_INIT	300
398a40a695Sgavinm #define	LUT_SIZE_INCR	100
408a40a695Sgavinm 
418a40a695Sgavinm struct lut_cp {
428a40a695Sgavinm 	uintptr_t lutcp_addr;
438a40a695Sgavinm 	struct lut lutcp_lut;
448a40a695Sgavinm };
458a40a695Sgavinm 
468a40a695Sgavinm #define	LCPSZ	sizeof (struct lut_cp)
478a40a695Sgavinm 
488a40a695Sgavinm struct lut_dump_desc {
498a40a695Sgavinm 	struct lut_cp *ld_array;
508a40a695Sgavinm 	int ld_arraysz;
518a40a695Sgavinm 	int ld_nents;
528a40a695Sgavinm };
538a40a695Sgavinm 
548a40a695Sgavinm static void
lut_dump_array_alloc(struct lut_dump_desc * lddp)558a40a695Sgavinm lut_dump_array_alloc(struct lut_dump_desc *lddp)
568a40a695Sgavinm {
578a40a695Sgavinm 	struct lut_cp *new;
588a40a695Sgavinm 
598a40a695Sgavinm 	if (lddp->ld_array == NULL) {
608a40a695Sgavinm 		lddp->ld_arraysz = LUT_SIZE_INIT;
618a40a695Sgavinm 		lddp->ld_array = mdb_zalloc(LUT_SIZE_INIT * LCPSZ, UM_SLEEP);
628a40a695Sgavinm 		return;
638a40a695Sgavinm 	}
648a40a695Sgavinm 
658a40a695Sgavinm 	new = mdb_zalloc((lddp->ld_arraysz + LUT_SIZE_INCR) * LCPSZ, UM_SLEEP);
668a40a695Sgavinm 	bcopy(lddp->ld_array, new, lddp->ld_arraysz * LCPSZ);
678a40a695Sgavinm 	mdb_free(lddp->ld_array, lddp->ld_arraysz * LCPSZ);
688a40a695Sgavinm 	lddp->ld_array = new;
698a40a695Sgavinm 	lddp->ld_arraysz += LUT_SIZE_INCR;
708a40a695Sgavinm }
718a40a695Sgavinm 
728a40a695Sgavinm static void
lut_dump_array_free(struct lut_dump_desc * lddp)738a40a695Sgavinm lut_dump_array_free(struct lut_dump_desc *lddp)
748a40a695Sgavinm {
758a40a695Sgavinm 	if (lddp->ld_array != NULL) {
768a40a695Sgavinm 		mdb_free(lddp->ld_array, lddp->ld_arraysz * LCPSZ);
778a40a695Sgavinm 		lddp->ld_array = NULL;
788a40a695Sgavinm 	}
798a40a695Sgavinm }
808a40a695Sgavinm 
818a40a695Sgavinm static void
lut_collect_addent(uintptr_t addr,struct lut * ent,struct lut_dump_desc * lddp)828a40a695Sgavinm lut_collect_addent(uintptr_t addr, struct lut *ent, struct lut_dump_desc *lddp)
838a40a695Sgavinm {
848a40a695Sgavinm 	struct lut_cp *lcp;
858a40a695Sgavinm 
868a40a695Sgavinm 	if (lddp->ld_nents == lddp->ld_arraysz)
878a40a695Sgavinm 		lut_dump_array_alloc(lddp);
888a40a695Sgavinm 
898a40a695Sgavinm 	lcp = &lddp->ld_array[lddp->ld_nents++];
908a40a695Sgavinm 
918a40a695Sgavinm 	lcp->lutcp_addr = addr;
928a40a695Sgavinm 	bcopy(ent, &lcp->lutcp_lut, sizeof (struct lut));
938a40a695Sgavinm }
948a40a695Sgavinm 
958a40a695Sgavinm static int
eft_lut_walk(uintptr_t root,struct lut_dump_desc * lddp)968a40a695Sgavinm eft_lut_walk(uintptr_t root, struct lut_dump_desc *lddp)
978a40a695Sgavinm {
988a40a695Sgavinm 	struct lut lutent;
998a40a695Sgavinm 
1008a40a695Sgavinm 	if (root) {
1018a40a695Sgavinm 		if (mdb_vread(&lutent, sizeof (struct lut), root) !=
1028a40a695Sgavinm 		    sizeof (struct lut)) {
1038a40a695Sgavinm 			mdb_warn("failed to read struct lut at %p", root);
1048a40a695Sgavinm 			return (WALK_ERR);
1058a40a695Sgavinm 		}
1068a40a695Sgavinm 
1078a40a695Sgavinm 		if (eft_lut_walk((uintptr_t)lutent.lut_left, lddp) != WALK_NEXT)
1088a40a695Sgavinm 			return (WALK_ERR);
1098a40a695Sgavinm 
1108a40a695Sgavinm 		lut_collect_addent(root, &lutent, lddp);
1118a40a695Sgavinm 
1128a40a695Sgavinm 		if (eft_lut_walk((uintptr_t)lutent.lut_right, lddp) !=
1138a40a695Sgavinm 		    WALK_NEXT)
1148a40a695Sgavinm 			return (WALK_ERR);
1158a40a695Sgavinm 	}
1168a40a695Sgavinm 	return (WALK_NEXT);
1178a40a695Sgavinm }
1188a40a695Sgavinm 
1198a40a695Sgavinm static int
lut_collect(uintptr_t addr,struct lut_dump_desc * lddp)1208a40a695Sgavinm lut_collect(uintptr_t addr, struct lut_dump_desc *lddp)
1218a40a695Sgavinm {
1228a40a695Sgavinm 	lut_dump_array_alloc(lddp);
1238a40a695Sgavinm 
1248a40a695Sgavinm 	if (eft_lut_walk(addr, lddp) != WALK_NEXT) {
1258a40a695Sgavinm 		lut_dump_array_free(lddp);
1268a40a695Sgavinm 		return (WALK_ERR);
1278a40a695Sgavinm 	} else {
1288a40a695Sgavinm 		return (WALK_NEXT);	/* caller must free dump array */
1298a40a695Sgavinm 	}
1308a40a695Sgavinm }
1318a40a695Sgavinm 
1328a40a695Sgavinm static int
lut_walk_init(mdb_walk_state_t * wsp)1338a40a695Sgavinm lut_walk_init(mdb_walk_state_t *wsp)
1348a40a695Sgavinm {
135940f2f58SToomas Soome 	if (wsp->walk_addr == 0) {
1368a40a695Sgavinm 		mdb_warn("lut walker requires a lut table address\n");
1378a40a695Sgavinm 		return (WALK_ERR);
1388a40a695Sgavinm 	}
1398a40a695Sgavinm 
1408a40a695Sgavinm 	wsp->walk_data = mdb_zalloc(sizeof (struct lut_dump_desc), UM_SLEEP);
1418a40a695Sgavinm 	wsp->walk_arg = 0;
1428a40a695Sgavinm 
1438a40a695Sgavinm 	if (lut_collect(wsp->walk_addr, wsp->walk_data) == WALK_NEXT) {
1448a40a695Sgavinm 		return (WALK_NEXT);
1458a40a695Sgavinm 	} else {
1468a40a695Sgavinm 		mdb_warn("failed to suck in full lut\n");
1478a40a695Sgavinm 		mdb_free(wsp->walk_data, sizeof (struct lut_dump_desc));
1488a40a695Sgavinm 		return (WALK_ERR);
1498a40a695Sgavinm 	}
1508a40a695Sgavinm }
1518a40a695Sgavinm 
1528a40a695Sgavinm static int
lut_walk_step(mdb_walk_state_t * wsp)1538a40a695Sgavinm lut_walk_step(mdb_walk_state_t *wsp)
1548a40a695Sgavinm {
1558a40a695Sgavinm 	struct lut_dump_desc *lddp = wsp->walk_data;
1568a40a695Sgavinm 	int *ip = (int *)&wsp->walk_arg;
1578a40a695Sgavinm 	struct lut_cp *lcp = &lddp->ld_array[*ip];
1588a40a695Sgavinm 
1598a40a695Sgavinm 	if (*ip == lddp->ld_nents)
1608a40a695Sgavinm 		return (WALK_DONE);
1618a40a695Sgavinm 
1628a40a695Sgavinm 	++*ip;
1638a40a695Sgavinm 
1648a40a695Sgavinm 	return (wsp->walk_callback(lcp->lutcp_addr, &lcp->lutcp_lut,
1658a40a695Sgavinm 	    wsp->walk_cbdata));
1668a40a695Sgavinm }
1678a40a695Sgavinm 
1686cb1ca52Saf static int
ipath_walk_init(mdb_walk_state_t * wsp)1696cb1ca52Saf ipath_walk_init(mdb_walk_state_t *wsp)
1706cb1ca52Saf {
1716cb1ca52Saf 	struct ipath *ipath;
1726cb1ca52Saf 
1736cb1ca52Saf 	ipath = mdb_alloc(sizeof (struct ipath), UM_SLEEP);
1746cb1ca52Saf 
1756cb1ca52Saf 	if (mdb_vread((void *)ipath, sizeof (struct ipath),
1766cb1ca52Saf 	    wsp->walk_addr) != sizeof (struct ipath)) {
1776cb1ca52Saf 		mdb_warn("failed to read struct ipath at %p", wsp->walk_addr);
1786cb1ca52Saf 		return (WALK_ERR);
1796cb1ca52Saf 	}
1806cb1ca52Saf 	wsp->walk_data = (void *)ipath;
1816cb1ca52Saf 
1826cb1ca52Saf 	if (ipath->s == NULL)
1836cb1ca52Saf 		return (WALK_DONE);
1846cb1ca52Saf 	else
1856cb1ca52Saf 		return (WALK_NEXT);
1866cb1ca52Saf }
1876cb1ca52Saf 
1886cb1ca52Saf static void
ipath_walk_fini(mdb_walk_state_t * wsp)1896cb1ca52Saf ipath_walk_fini(mdb_walk_state_t *wsp)
1906cb1ca52Saf {
1916cb1ca52Saf 	mdb_free(wsp->walk_data, sizeof (struct ipath));
1926cb1ca52Saf }
1936cb1ca52Saf 
1946cb1ca52Saf static int
ipath_walk_step(mdb_walk_state_t * wsp)1956cb1ca52Saf ipath_walk_step(mdb_walk_state_t *wsp)
1966cb1ca52Saf {
1976cb1ca52Saf 	int status;
1986cb1ca52Saf 	struct ipath *ipath = (struct ipath *)wsp->walk_data;
1996cb1ca52Saf 	struct ipath *ip = (struct ipath *)wsp->walk_addr;
2006cb1ca52Saf 
2016cb1ca52Saf 	if (ip == NULL || ipath->s == NULL)
2026cb1ca52Saf 		return (WALK_DONE);
2036cb1ca52Saf 
2046cb1ca52Saf 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
2056cb1ca52Saf 	    wsp->walk_cbdata);
2066cb1ca52Saf 
2076cb1ca52Saf 	wsp->walk_addr = (uintptr_t)(ip + 1);
2086cb1ca52Saf 
2096cb1ca52Saf 	if (mdb_vread(wsp->walk_data, sizeof (struct ipath),
2106cb1ca52Saf 	    wsp->walk_addr) != sizeof (struct ipath)) {
2116cb1ca52Saf 		mdb_warn("failed to read struct ipath at %p", wsp->walk_addr);
2126cb1ca52Saf 		return (WALK_ERR);
2136cb1ca52Saf 	}
2146cb1ca52Saf 
2156cb1ca52Saf 	return (status);
2166cb1ca52Saf }
2176cb1ca52Saf 
2188a40a695Sgavinm static void
lut_walk_fini(mdb_walk_state_t * wsp)2198a40a695Sgavinm lut_walk_fini(mdb_walk_state_t *wsp)
2208a40a695Sgavinm {
2218a40a695Sgavinm 	struct lut_dump_desc *lddp = wsp->walk_data;
2228a40a695Sgavinm 
2238a40a695Sgavinm 	lut_dump_array_free(lddp);
2248a40a695Sgavinm 	mdb_free(lddp, sizeof (struct lut_dump_desc));
2258a40a695Sgavinm }
2268a40a695Sgavinm 
2276cb1ca52Saf /*ARGSUSED*/
2286cb1ca52Saf static int
ipath_node(uintptr_t addr,const void * data,void * arg)2296cb1ca52Saf ipath_node(uintptr_t addr, const void *data, void *arg)
2306cb1ca52Saf {
2316cb1ca52Saf 	struct ipath *ipath = (struct ipath *)data;
2326cb1ca52Saf 	char buf[128];
2336cb1ca52Saf 
234888e0559SRobert Johnston 	if (mdb_readstr(buf, (size_t)sizeof (buf), (uintptr_t)ipath->s) < 0)
235888e0559SRobert Johnston 		(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
236888e0559SRobert Johnston 		    ipath->s);
237888e0559SRobert Johnston 
2386cb1ca52Saf 	mdb_printf("/%s=%d", buf, ipath->i);
2396cb1ca52Saf 	return (DCMD_OK);
2406cb1ca52Saf }
2416cb1ca52Saf 
2426cb1ca52Saf /*ARGSUSED*/
2436cb1ca52Saf static int
ipath(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2446cb1ca52Saf ipath(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2456cb1ca52Saf {
2466cb1ca52Saf 	if (argc)
2476cb1ca52Saf 		return (DCMD_USAGE);
2486cb1ca52Saf 	if (!(flags & DCMD_ADDRSPEC))
2496cb1ca52Saf 		addr = mdb_get_dot();
2506cb1ca52Saf 	if (mdb_pwalk("eft_ipath", ipath_node, NULL, addr) != 0)
2516cb1ca52Saf 		return (DCMD_ERR);
2526cb1ca52Saf 	return (DCMD_OK);
2536cb1ca52Saf }
2546cb1ca52Saf 
2556cb1ca52Saf /*ARGSUSED*/
2566cb1ca52Saf static int
eft_count(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2576cb1ca52Saf eft_count(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2586cb1ca52Saf {
2596cb1ca52Saf 	struct lut lut;
2606cb1ca52Saf 	struct istat_entry istat_entry;
2616cb1ca52Saf 	struct stats count;
2626cb1ca52Saf 	GElf_Sym sym;
2636cb1ca52Saf 	char buf[128];
2646cb1ca52Saf 
2656cb1ca52Saf 	if (argc)
2666cb1ca52Saf 		return (DCMD_USAGE);
2676cb1ca52Saf 	if (!(flags & DCMD_ADDRSPEC)) {
2686cb1ca52Saf 		if (mdb_lookup_by_obj(MDB_OBJ_EVERY, "Istats", &sym) == -1 ||
2696cb1ca52Saf 		    sym.st_size != sizeof (addr))
2706cb1ca52Saf 			return (DCMD_ERR);
2716cb1ca52Saf 		if (mdb_vread(&addr, sizeof (addr),
2726cb1ca52Saf 		    (uintptr_t)sym.st_value) != sizeof (addr))
2736cb1ca52Saf 			return (DCMD_ERR);
274940f2f58SToomas Soome 		if (addr == 0)
2756cb1ca52Saf 			return (DCMD_OK);
2766cb1ca52Saf 		if (mdb_pwalk_dcmd("lut", "eft_count", argc, argv, addr) != 0)
2776cb1ca52Saf 			return (DCMD_ERR);
2786cb1ca52Saf 		return (DCMD_OK);
2796cb1ca52Saf 	}
2806cb1ca52Saf 
2816cb1ca52Saf 	if (mdb_vread(&lut, sizeof (struct lut), addr) != sizeof (struct lut)) {
2826cb1ca52Saf 		mdb_warn("failed to read struct lut at %p", addr);
2836cb1ca52Saf 		return (DCMD_ERR);
2846cb1ca52Saf 	}
2856cb1ca52Saf 	if (mdb_vread(&istat_entry, sizeof (struct istat_entry),
2866cb1ca52Saf 	    (uintptr_t)lut.lut_lhs) != sizeof (struct istat_entry)) {
2876cb1ca52Saf 		mdb_warn("failed to read struct istat_entry at %p", addr);
2886cb1ca52Saf 		return (DCMD_ERR);
2896cb1ca52Saf 	}
2906cb1ca52Saf 	if (mdb_vread(&count, sizeof (struct stats),
2916cb1ca52Saf 	    (uintptr_t)lut.lut_rhs) != sizeof (struct stats)) {
2926cb1ca52Saf 		mdb_warn("failed to read struct stats at %p", addr);
2936cb1ca52Saf 		return (DCMD_ERR);
2946cb1ca52Saf 	}
2956cb1ca52Saf 
296888e0559SRobert Johnston 	if (mdb_readstr(buf, (size_t)sizeof (buf),
297888e0559SRobert Johnston 	    (uintptr_t)istat_entry.ename) < 0)
298888e0559SRobert Johnston 		(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
299888e0559SRobert Johnston 		    istat_entry.ename);
300888e0559SRobert Johnston 
3016cb1ca52Saf 	mdb_printf("%s@", buf);
3026cb1ca52Saf 	(void) ipath((uintptr_t)istat_entry.ipath, DCMD_ADDRSPEC, 0, NULL);
3036cb1ca52Saf 	mdb_printf(" %d\n", count.fmd_stats.fmds_value.i32);
3046cb1ca52Saf 	return (DCMD_OK);
3056cb1ca52Saf }
3066cb1ca52Saf 
3076cb1ca52Saf /*ARGSUSED*/
3086cb1ca52Saf static int
eft_time(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3096cb1ca52Saf eft_time(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3106cb1ca52Saf {
3116cb1ca52Saf 	unsigned long long val;
3126cb1ca52Saf 	unsigned long long ull;
3136cb1ca52Saf 	int opt_p = 0;
3146cb1ca52Saf 
3156cb1ca52Saf 	if (!(flags & DCMD_ADDRSPEC))
3166cb1ca52Saf 		addr = mdb_get_dot();
3176cb1ca52Saf 	ull = addr;
3186cb1ca52Saf 	if (argc) {
3196cb1ca52Saf 		if (mdb_getopts(argc, argv,
3206cb1ca52Saf 		    'l', MDB_OPT_UINT64, &ull,
321*3b442230SJordan Paige Hendricks 		    'p', MDB_OPT_SETBITS, TRUE, &opt_p, MDB_OPT_UINT64,
322*3b442230SJordan Paige Hendricks 		    NULL) != argc) {
3236cb1ca52Saf 			return (DCMD_USAGE);
3246cb1ca52Saf 		}
3256cb1ca52Saf 	}
3266cb1ca52Saf 	if (opt_p) {
3276cb1ca52Saf 		if (mdb_vread(&ull, sizeof (ull), addr) != sizeof (ull)) {
3286cb1ca52Saf 			mdb_warn("failed to read timeval at %p", addr);
3296cb1ca52Saf 			return (DCMD_ERR);
3306cb1ca52Saf 		}
3316cb1ca52Saf 	}
3326cb1ca52Saf #define	NOREMAINDER(den, num, val) (((val) = ((den) / (num))) * (num) == (den))
3336cb1ca52Saf 	if (ull == 0)
3346cb1ca52Saf 		mdb_printf("0us");
3356cb1ca52Saf 	else if (ull >= TIMEVAL_EVENTUALLY)
3366cb1ca52Saf 		mdb_printf("infinity");
3376cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*365, val))
3386cb1ca52Saf 		mdb_printf("%lluyear%s", val, (val == 1) ? "" : "s");
3396cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*30, val))
3406cb1ca52Saf 		mdb_printf("%llumonth%s", val, (val == 1) ? "" : "s");
3416cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL*60*60*24*7, val))
3426cb1ca52Saf 		mdb_printf("%lluweek%s", val, (val == 1) ? "" : "s");
3436cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL*60*60*24, val))
3446cb1ca52Saf 		mdb_printf("%lluday%s", val, (val == 1) ? "" : "s");
3456cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL*60*60, val))
3466cb1ca52Saf 		mdb_printf("%lluhour%s", val, (val == 1) ? "" : "s");
3476cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL*60, val))
3486cb1ca52Saf 		mdb_printf("%lluminute%s", val, (val == 1) ? "" : "s");
3496cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000000ULL, val))
3506cb1ca52Saf 		mdb_printf("%llusecond%s", val, (val == 1) ? "" : "s");
3516cb1ca52Saf 	else if (NOREMAINDER(ull, 1000000ULL, val))
3526cb1ca52Saf 		mdb_printf("%llums", val);
3536cb1ca52Saf 	else if (NOREMAINDER(ull, 1000ULL, val))
3546cb1ca52Saf 		mdb_printf("%lluus", val);
3556cb1ca52Saf 	else
3566cb1ca52Saf 		mdb_printf("%lluns", ull);
3576cb1ca52Saf 
3586cb1ca52Saf 	return (DCMD_OK);
3596cb1ca52Saf }
3606cb1ca52Saf 
3616cb1ca52Saf /*ARGSUSED*/
3626cb1ca52Saf static int
eft_node(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3636cb1ca52Saf eft_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3646cb1ca52Saf {
3656cb1ca52Saf 	struct node node;
3666cb1ca52Saf 	int opt_v = 0;
3676cb1ca52Saf 	char buf[128];
3686cb1ca52Saf 
3696cb1ca52Saf 	if (!(flags & DCMD_ADDRSPEC))
3706cb1ca52Saf 		addr = mdb_get_dot();
3716cb1ca52Saf 	if (argc) {
3726cb1ca52Saf 		if (mdb_getopts(argc, argv,
3736cb1ca52Saf 		    'v', MDB_OPT_SETBITS, TRUE, &opt_v,
3746cb1ca52Saf 		    NULL) != argc) {
3756cb1ca52Saf 			return (DCMD_USAGE);
3766cb1ca52Saf 		}
3776cb1ca52Saf 	}
378940f2f58SToomas Soome 	if (addr == 0)
3796cb1ca52Saf 		return (DCMD_OK);
3806cb1ca52Saf 	if (mdb_vread(&node, sizeof (node), addr) != sizeof (node)) {
3816cb1ca52Saf 		mdb_warn("failed to read struct node at %p", addr);
3826cb1ca52Saf 		return (DCMD_ERR);
3836cb1ca52Saf 	}
3846cb1ca52Saf 	if (opt_v) {
385888e0559SRobert Johnston 		if (mdb_readstr(buf, (size_t)sizeof (buf),
386888e0559SRobert Johnston 		    (uintptr_t)node.file) < 0)
387888e0559SRobert Johnston 			(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
388888e0559SRobert Johnston 			    node.file);
389888e0559SRobert Johnston 
3906cb1ca52Saf 		mdb_printf("%s len %d\n", buf, node.line);
3916cb1ca52Saf 	}
3926cb1ca52Saf 	switch (node.t) {
3936cb1ca52Saf 	case T_NOTHING:			/* used to keep going on error cases */
3946cb1ca52Saf 		mdb_printf("nothing");
3956cb1ca52Saf 		break;
3966cb1ca52Saf 	case T_NAME:			/* identifiers, sometimes chained */
397888e0559SRobert Johnston 		if (mdb_readstr(buf, (size_t)sizeof (buf),
398888e0559SRobert Johnston 		    (uintptr_t)node.u.name.s) < 0)
399888e0559SRobert Johnston 			(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
400888e0559SRobert Johnston 			    node.u.name.s);
401888e0559SRobert Johnston 
4026cb1ca52Saf 		mdb_printf("%s", buf);
4036cb1ca52Saf 		if (node.u.name.cp) {
4046cb1ca52Saf 			struct config cp;
4056cb1ca52Saf 			if (mdb_vread(&cp, sizeof (cp),
4066cb1ca52Saf 			    (uintptr_t)node.u.name.cp) != sizeof (cp)) {
4076cb1ca52Saf 				mdb_warn("failed to read struct config at %p",
4086cb1ca52Saf 				    node.u.name.cp);
4096cb1ca52Saf 				return (DCMD_ERR);
4106cb1ca52Saf 			}
4116cb1ca52Saf 			mdb_printf("%d", cp.num);
4126cb1ca52Saf 		} else if (node.u.name.it == IT_HORIZONTAL) {
4136cb1ca52Saf 			if (node.u.name.child && !node.u.name.childgen) {
4146cb1ca52Saf 				mdb_printf("<");
4156cb1ca52Saf 				(void) eft_node((uintptr_t)node.u.name.child,
4166cb1ca52Saf 				    DCMD_ADDRSPEC, 0, NULL);
4176cb1ca52Saf 				mdb_printf(">");
4186cb1ca52Saf 			} else {
4196cb1ca52Saf 				mdb_printf("<> ");
4206cb1ca52Saf 			}
4216cb1ca52Saf 		} else if (node.u.name.child) {
4226cb1ca52Saf 			mdb_printf("[");
4236cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.name.child,
4246cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
4256cb1ca52Saf 			mdb_printf("]");
4266cb1ca52Saf 		}
4276cb1ca52Saf 		if (node.u.name.next) {
4286cb1ca52Saf 			if (node.u.name.it == IT_ENAME)
4296cb1ca52Saf 				mdb_printf(".");
4306cb1ca52Saf 			else
4316cb1ca52Saf 				mdb_printf("/");
4326cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.name.next,
4336cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
4346cb1ca52Saf 		}
4356cb1ca52Saf 		break;
4366cb1ca52Saf 	case T_GLOBID:			/* globals (e.g. $a) */
437888e0559SRobert Johnston 		if (mdb_readstr(buf, (size_t)sizeof (buf),
438888e0559SRobert Johnston 		    (uintptr_t)node.u.globid.s) < 0)
439888e0559SRobert Johnston 			(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
440888e0559SRobert Johnston 			    node.u.globid.s);
441888e0559SRobert Johnston 
4426cb1ca52Saf 		mdb_printf("$%s", buf);
4436cb1ca52Saf 		break;
4446cb1ca52Saf 	case T_EVENT:			/* class@path{expr} */
4456cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.event.ename, DCMD_ADDRSPEC, 0,
4466cb1ca52Saf 		    NULL);
4476cb1ca52Saf 		mdb_printf("@");
4486cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.event.epname, DCMD_ADDRSPEC,
4496cb1ca52Saf 		    0, NULL);
4506cb1ca52Saf 		if (node.u.event.eexprlist) {
4516cb1ca52Saf 			mdb_printf(" { ");
4526cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.event.eexprlist,
4536cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
4546cb1ca52Saf 			mdb_printf(" }");
4556cb1ca52Saf 		}
4566cb1ca52Saf 		break;
4576cb1ca52Saf 	case T_ENGINE:			/* upset threshold engine (e.g. SERD) */
4586cb1ca52Saf 		mdb_printf("engine ");
4596cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.event.ename, DCMD_ADDRSPEC, 0,
4606cb1ca52Saf 		    NULL);
4616cb1ca52Saf 		break;
4626cb1ca52Saf 	case T_ASRU:			/* ASRU declaration */
4636cb1ca52Saf 		mdb_printf("asru ");
4646cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
4656cb1ca52Saf 		    NULL);
4666cb1ca52Saf 		if (node.u.stmt.nvpairs) {
4676cb1ca52Saf 			mdb_printf(" ");
4686cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
4696cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
4706cb1ca52Saf 
4716cb1ca52Saf 		}
4726cb1ca52Saf 		break;
4736cb1ca52Saf 	case T_FRU:			/* FRU declaration */
4746cb1ca52Saf 		mdb_printf("fru ");
4756cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
4766cb1ca52Saf 		    NULL);
4776cb1ca52Saf 		if (node.u.stmt.nvpairs) {
4786cb1ca52Saf 			mdb_printf(" ");
4796cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
4806cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
4816cb1ca52Saf 
4826cb1ca52Saf 		}
4836cb1ca52Saf 		break;
4846cb1ca52Saf 	case T_TIMEVAL:			/* num w/time suffix (ns internally) */
4856cb1ca52Saf 		{
4866cb1ca52Saf 			mdb_arg_t mdb_arg[2];
4876cb1ca52Saf 			mdb_arg[0].a_type = MDB_TYPE_STRING;
4886cb1ca52Saf 			mdb_arg[0].a_un.a_str = "-l";
4896cb1ca52Saf 			mdb_arg[1].a_type = MDB_TYPE_IMMEDIATE;
4906cb1ca52Saf 			mdb_arg[1].a_un.a_val = node.u.ull;
4916cb1ca52Saf 			(void) eft_time((uintptr_t)0, 0, 2, mdb_arg);
4926cb1ca52Saf 			break;
4936cb1ca52Saf 		}
4946cb1ca52Saf 	case T_NUM:			/* num (ull internally) */
4956cb1ca52Saf 		mdb_printf("%llu", node.u.ull);
4966cb1ca52Saf 		break;
4976cb1ca52Saf 	case T_QUOTE:			/* quoted string */
498888e0559SRobert Johnston 		if (mdb_readstr(buf, (size_t)sizeof (buf),
499888e0559SRobert Johnston 		    (uintptr_t)node.u.quote.s) < 0)
500888e0559SRobert Johnston 			(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
501888e0559SRobert Johnston 			    node.u.quote.s);
502888e0559SRobert Johnston 
5036cb1ca52Saf 		mdb_printf("\"%s\"", buf);
5046cb1ca52Saf 		break;
5056cb1ca52Saf 	case T_FUNC:			/* func(arglist) */
506888e0559SRobert Johnston 		if (mdb_readstr(buf, (size_t)sizeof (buf),
507888e0559SRobert Johnston 		    (uintptr_t)node.u.func.s) < 0)
508888e0559SRobert Johnston 			(void) mdb_snprintf(buf, (size_t)sizeof (buf), "<%p>",
509888e0559SRobert Johnston 			    node.u.func.s);
510888e0559SRobert Johnston 
5116cb1ca52Saf 		mdb_printf("%s(", buf);
5126cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.func.arglist, DCMD_ADDRSPEC,
5136cb1ca52Saf 		    0, NULL);
5146cb1ca52Saf 		mdb_printf(")");
5156cb1ca52Saf 		break;
5166cb1ca52Saf 	case T_NVPAIR:			/* name=value pair in decl */
5176cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5186cb1ca52Saf 		    NULL);
5196cb1ca52Saf 		mdb_printf(" = ");
5206cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5216cb1ca52Saf 		    NULL);
5226cb1ca52Saf 		break;
5236cb1ca52Saf 	case T_ASSIGN:			/* assignment statement */
5246cb1ca52Saf 		mdb_printf("(");
5256cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5266cb1ca52Saf 		    NULL);
5276cb1ca52Saf 		mdb_printf(" = ");
5286cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5296cb1ca52Saf 		    NULL);
5306cb1ca52Saf 		mdb_printf(")");
5316cb1ca52Saf 		break;
5326cb1ca52Saf 	case T_CONDIF:			/* a and T_CONDELSE in (a ? b : c ) */
5336cb1ca52Saf 		mdb_printf("(");
5346cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5356cb1ca52Saf 		    NULL);
5366cb1ca52Saf 		mdb_printf(" ? ");
5376cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5386cb1ca52Saf 		    NULL);
5396cb1ca52Saf 		mdb_printf(")");
5406cb1ca52Saf 		break;
5416cb1ca52Saf 	case T_CONDELSE:		/* lists b and c in (a ? b : c ) */
5426cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5436cb1ca52Saf 		    NULL);
5446cb1ca52Saf 		mdb_printf(" : ");
5456cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5466cb1ca52Saf 		    NULL);
5476cb1ca52Saf 		break;
5486cb1ca52Saf 	case T_NOT:			/* boolean ! operator */
5496cb1ca52Saf 		mdb_printf("!");
5506cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5516cb1ca52Saf 		    NULL);
5526cb1ca52Saf 		break;
5536cb1ca52Saf 	case T_AND:			/* boolean && operator */
5546cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5556cb1ca52Saf 		    NULL);
5566cb1ca52Saf 		mdb_printf(" && ");
5576cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5586cb1ca52Saf 		    NULL);
5596cb1ca52Saf 		break;
5606cb1ca52Saf 	case T_OR:			/* boolean || operator */
5616cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5626cb1ca52Saf 		    NULL);
5636cb1ca52Saf 		mdb_printf(" || ");
5646cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5656cb1ca52Saf 		    NULL);
5666cb1ca52Saf 		break;
5676cb1ca52Saf 	case T_EQ:			/* boolean == operator */
5686cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5696cb1ca52Saf 		    NULL);
5706cb1ca52Saf 		mdb_printf(" == ");
5716cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5726cb1ca52Saf 		    NULL);
5736cb1ca52Saf 		break;
5746cb1ca52Saf 	case T_NE:			/* boolean != operator */
5756cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5766cb1ca52Saf 		    NULL);
5776cb1ca52Saf 		mdb_printf(" != ");
5786cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5796cb1ca52Saf 		    NULL);
5806cb1ca52Saf 		break;
5816cb1ca52Saf 	case T_SUB:			/* integer - operator */
5826cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5836cb1ca52Saf 		    NULL);
5846cb1ca52Saf 		mdb_printf(" - ");
5856cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5866cb1ca52Saf 		    NULL);
5876cb1ca52Saf 		break;
5886cb1ca52Saf 	case T_ADD:			/* integer + operator */
5896cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5906cb1ca52Saf 		    NULL);
5916cb1ca52Saf 		mdb_printf(" + ");
5926cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
5936cb1ca52Saf 		    NULL);
5946cb1ca52Saf 		break;
5956cb1ca52Saf 	case T_MUL:			/* integer * operator */
5966cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
5976cb1ca52Saf 		    NULL);
5986cb1ca52Saf 		mdb_printf(" * ");
5996cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6006cb1ca52Saf 		    NULL);
6016cb1ca52Saf 		break;
6026cb1ca52Saf 	case T_DIV:			/* integer / operator */
6036cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6046cb1ca52Saf 		    NULL);
6056cb1ca52Saf 		mdb_printf(" / ");
6066cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6076cb1ca52Saf 		    NULL);
6086cb1ca52Saf 		break;
6096cb1ca52Saf 	case T_MOD:			/* integer % operator */
6106cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6116cb1ca52Saf 		    NULL);
6126cb1ca52Saf 		mdb_printf(" % ");
6136cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6146cb1ca52Saf 		    NULL);
6156cb1ca52Saf 		break;
6166cb1ca52Saf 	case T_LT:			/* boolean < operator */
6176cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6186cb1ca52Saf 		    NULL);
6196cb1ca52Saf 		mdb_printf(" < ");
6206cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6216cb1ca52Saf 		    NULL);
6226cb1ca52Saf 		break;
6236cb1ca52Saf 	case T_LE:			/* boolean <= operator */
6246cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6256cb1ca52Saf 		    NULL);
6266cb1ca52Saf 		mdb_printf(" <= ");
6276cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6286cb1ca52Saf 		    NULL);
6296cb1ca52Saf 		break;
6306cb1ca52Saf 	case T_GT:			/* boolean > operator */
6316cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6326cb1ca52Saf 		    NULL);
6336cb1ca52Saf 		mdb_printf(" > ");
6346cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6356cb1ca52Saf 		    NULL);
6366cb1ca52Saf 		break;
6376cb1ca52Saf 	case T_GE:			/* boolean >= operator */
6386cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6396cb1ca52Saf 		    NULL);
6406cb1ca52Saf 		mdb_printf(" >= ");
6416cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6426cb1ca52Saf 		    NULL);
6436cb1ca52Saf 		break;
6446cb1ca52Saf 	case T_BITAND:			/* bitwise & operator */
6456cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6466cb1ca52Saf 		    NULL);
6476cb1ca52Saf 		mdb_printf(" & ");
6486cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6496cb1ca52Saf 		    NULL);
6506cb1ca52Saf 		break;
6516cb1ca52Saf 	case T_BITOR:			/* bitwise | operator */
6526cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6536cb1ca52Saf 		    NULL);
6546cb1ca52Saf 		mdb_printf(" | ");
6556cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6566cb1ca52Saf 		    NULL);
6576cb1ca52Saf 		break;
6586cb1ca52Saf 	case T_BITXOR:			/* bitwise ^ operator */
6596cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6606cb1ca52Saf 		    NULL);
6616cb1ca52Saf 		mdb_printf(" ^ ");
6626cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6636cb1ca52Saf 		    NULL);
6646cb1ca52Saf 		break;
6656cb1ca52Saf 	case T_BITNOT:			/* bitwise ~ operator */
6666cb1ca52Saf 		mdb_printf(" ~");
6676cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6686cb1ca52Saf 		    NULL);
6696cb1ca52Saf 		break;
6706cb1ca52Saf 	case T_LSHIFT:			/* bitwise << operator */
6716cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6726cb1ca52Saf 		    NULL);
6736cb1ca52Saf 		mdb_printf(" << ");
6746cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6756cb1ca52Saf 		    NULL);
6766cb1ca52Saf 		break;
6776cb1ca52Saf 	case T_RSHIFT:			/* bitwise >> operator */
6786cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
6796cb1ca52Saf 		    NULL);
6806cb1ca52Saf 		mdb_printf(" >> ");
6816cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
6826cb1ca52Saf 		    NULL);
6836cb1ca52Saf 		break;
6846cb1ca52Saf 	case T_ARROW:			/* lhs (N)->(K) rhs */
6856cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.arrow.lhs, DCMD_ADDRSPEC, 0,
6866cb1ca52Saf 		    NULL);
6876cb1ca52Saf 		if (node.u.arrow.nnp) {
6886cb1ca52Saf 			mdb_printf("(");
6896cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.arrow.nnp,
6906cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
6916cb1ca52Saf 			mdb_printf(")");
6926cb1ca52Saf 		}
6936cb1ca52Saf 		mdb_printf("->");
6946cb1ca52Saf 		if (node.u.arrow.knp) {
6956cb1ca52Saf 			mdb_printf("(");
6966cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.arrow.knp,
6976cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
6986cb1ca52Saf 			mdb_printf(")");
6996cb1ca52Saf 		}
7006cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.arrow.rhs, DCMD_ADDRSPEC, 0,
7016cb1ca52Saf 		    NULL);
7026cb1ca52Saf 		break;
7036cb1ca52Saf 	case T_LIST:			/* comma-separated list */
7046cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.left, DCMD_ADDRSPEC, 0,
7056cb1ca52Saf 		    NULL);
7066cb1ca52Saf 		mdb_printf(", ");
7076cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.expr.right, DCMD_ADDRSPEC, 0,
7086cb1ca52Saf 		    NULL);
7096cb1ca52Saf 		break;
7106cb1ca52Saf 	case T_FAULT:			/* fault declaration */
7116cb1ca52Saf 		mdb_printf("fault.");
7126cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7136cb1ca52Saf 		    NULL);
7146cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7156cb1ca52Saf 			mdb_printf(" ");
7166cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7176cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7186cb1ca52Saf 
7196cb1ca52Saf 		}
7206cb1ca52Saf 		break;
7216cb1ca52Saf 	case T_UPSET:			/* upset declaration */
7226cb1ca52Saf 		mdb_printf("upset.");
7236cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7246cb1ca52Saf 		    NULL);
7256cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7266cb1ca52Saf 			mdb_printf(" ");
7276cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7286cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7296cb1ca52Saf 
7306cb1ca52Saf 		}
7316cb1ca52Saf 		break;
7326cb1ca52Saf 	case T_DEFECT:			/* defect declaration */
7336cb1ca52Saf 		mdb_printf("defect.");
7346cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7356cb1ca52Saf 		    NULL);
7366cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7376cb1ca52Saf 			mdb_printf(" ");
7386cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7396cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7406cb1ca52Saf 
7416cb1ca52Saf 		}
7426cb1ca52Saf 		break;
7436cb1ca52Saf 	case T_ERROR:			/* error declaration */
7446cb1ca52Saf 		mdb_printf("error.");
7456cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7466cb1ca52Saf 		    NULL);
7476cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7486cb1ca52Saf 			mdb_printf(" ");
7496cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7506cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7516cb1ca52Saf 
7526cb1ca52Saf 		}
7536cb1ca52Saf 		break;
7546cb1ca52Saf 	case T_EREPORT:			/* ereport declaration */
7556cb1ca52Saf 		mdb_printf("ereport.");
7566cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7576cb1ca52Saf 		    NULL);
7586cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7596cb1ca52Saf 			mdb_printf(" ");
7606cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7616cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7626cb1ca52Saf 
7636cb1ca52Saf 		}
7646cb1ca52Saf 		break;
7656cb1ca52Saf 	case T_SERD:			/* SERD engine declaration */
7666cb1ca52Saf 		mdb_printf("serd.");
7676cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7686cb1ca52Saf 		    NULL);
7696cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7706cb1ca52Saf 			mdb_printf(" ");
7716cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7726cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7736cb1ca52Saf 
7746cb1ca52Saf 		} else if (node.u.stmt.lutp) {
7756cb1ca52Saf 			if (mdb_pwalk_dcmd("lut", "eft_node", 0, NULL,
7766cb1ca52Saf 			    (uintptr_t)node.u.stmt.lutp) != 0)
7776cb1ca52Saf 				return (DCMD_ERR);
7786cb1ca52Saf 		}
7796cb1ca52Saf 		break;
7806cb1ca52Saf 	case T_STAT:			/* STAT engine declaration */
7816cb1ca52Saf 		mdb_printf("stat.");
7826cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7836cb1ca52Saf 		    NULL);
7846cb1ca52Saf 		if (node.u.stmt.nvpairs) {
7856cb1ca52Saf 			mdb_printf(" ");
7866cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
7876cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
7886cb1ca52Saf 
7896cb1ca52Saf 		} else if (node.u.stmt.lutp) {
7906cb1ca52Saf 			if (mdb_pwalk_dcmd("lut", "eft_node", 0, NULL,
7916cb1ca52Saf 			    (uintptr_t)node.u.stmt.lutp) != 0)
7926cb1ca52Saf 				return (DCMD_ERR);
7936cb1ca52Saf 		}
7946cb1ca52Saf 		break;
7956cb1ca52Saf 	case T_PROP:			/* prop statement */
7966cb1ca52Saf 		mdb_printf("prop ");
7976cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
7986cb1ca52Saf 		    NULL);
7996cb1ca52Saf 		break;
8006cb1ca52Saf 	case T_MASK:			/* mask statement */
8016cb1ca52Saf 		mdb_printf("mask ");
8026cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
8036cb1ca52Saf 		    NULL);
8046cb1ca52Saf 		break;
8056cb1ca52Saf 	case T_CONFIG:			/* config statement */
8066cb1ca52Saf 		mdb_printf("config ");
8076cb1ca52Saf 		(void) eft_node((uintptr_t)node.u.stmt.np, DCMD_ADDRSPEC, 0,
8086cb1ca52Saf 		    NULL);
8096cb1ca52Saf 		if (node.u.stmt.nvpairs) {
8106cb1ca52Saf 			mdb_printf(" ");
8116cb1ca52Saf 			(void) eft_node((uintptr_t)node.u.stmt.nvpairs,
8126cb1ca52Saf 			    DCMD_ADDRSPEC, 0, NULL);
8136cb1ca52Saf 
8146cb1ca52Saf 		}
8156cb1ca52Saf 		break;
8166cb1ca52Saf 	default:
8176cb1ca52Saf 		mdb_printf("not a eversholt node\n");
8186cb1ca52Saf 		break;
8196cb1ca52Saf 	}
8206cb1ca52Saf 	return (DCMD_OK);
8216cb1ca52Saf }
8226cb1ca52Saf 
8238a40a695Sgavinm static const mdb_walker_t walkers[] = {
8248a40a695Sgavinm 	{ "lut", "walk a lookup table", lut_walk_init, lut_walk_step,
8258a40a695Sgavinm 	    lut_walk_fini, NULL },
8266cb1ca52Saf 	{ "eft_ipath", "walk ipath", ipath_walk_init, ipath_walk_step,
8276cb1ca52Saf 	    ipath_walk_fini, NULL },
8288a40a695Sgavinm 	{ NULL, NULL, NULL, NULL, NULL, NULL }
8298a40a695Sgavinm };
8308a40a695Sgavinm 
8316cb1ca52Saf static const mdb_dcmd_t dcmds[] = {
8326cb1ca52Saf 	{ "eft_ipath", "?", "print an ipath", ipath },
8336cb1ca52Saf 	{ "eft_count", "?", "print eversholt stats", eft_count },
8346cb1ca52Saf 	{ "eft_node", "?[-v]", "print eversholt node", eft_node },
8356cb1ca52Saf 	{ "eft_time", "?[-p][-l time]", "print eversholt timeval", eft_time },
8366cb1ca52Saf 	{ NULL }
8376cb1ca52Saf };
8386cb1ca52Saf 
8396cb1ca52Saf static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
8408a40a695Sgavinm 
8418a40a695Sgavinm const mdb_modinfo_t *
_mdb_init(void)8428a40a695Sgavinm _mdb_init(void)
8438a40a695Sgavinm {
8448a40a695Sgavinm 	return (&modinfo);
8458a40a695Sgavinm }
846