11a7c1b72Smws /*
21a7c1b72Smws  * CDDL HEADER START
31a7c1b72Smws  *
41a7c1b72Smws  * The contents of this file are subject to the terms of the
5*ac448965Sahl  * Common Development and Distribution License (the "License").
6*ac448965Sahl  * You may not use this file except in compliance with the License.
71a7c1b72Smws  *
81a7c1b72Smws  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91a7c1b72Smws  * or http://www.opensolaris.org/os/licensing.
101a7c1b72Smws  * See the License for the specific language governing permissions
111a7c1b72Smws  * and limitations under the License.
121a7c1b72Smws  *
131a7c1b72Smws  * When distributing Covered Code, include this CDDL HEADER in each
141a7c1b72Smws  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151a7c1b72Smws  * If applicable, add the following below this CDDL HEADER, with the
161a7c1b72Smws  * fields enclosed by brackets "[]" replaced with your own identifying
171a7c1b72Smws  * information: Portions Copyright [yyyy] [name of copyright owner]
181a7c1b72Smws  *
191a7c1b72Smws  * CDDL HEADER END
201a7c1b72Smws  */
21*ac448965Sahl 
221a7c1b72Smws /*
23*ac448965Sahl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
241a7c1b72Smws  * Use is subject to license terms.
251a7c1b72Smws  */
261a7c1b72Smws 
271a7c1b72Smws #include <mdb/mdb_modapi.h>
281a7c1b72Smws #include <dtrace.h>
291a7c1b72Smws 
301a7c1b72Smws extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
311a7c1b72Smws extern const char *dof_sec_name(uint32_t);
321a7c1b72Smws 
331a7c1b72Smws extern const mdb_walker_t kernel_walkers[];
341a7c1b72Smws extern const mdb_dcmd_t kernel_dcmds[];
351a7c1b72Smws 
361a7c1b72Smws /*ARGSUSED*/
371a7c1b72Smws static void
dis_log(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)381a7c1b72Smws dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
391a7c1b72Smws {
401a7c1b72Smws 	mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name,
411a7c1b72Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
421a7c1b72Smws }
431a7c1b72Smws 
441a7c1b72Smws /*ARGSUSED*/
451a7c1b72Smws static void
dis_branch(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)461a7c1b72Smws dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
471a7c1b72Smws {
481a7c1b72Smws 	mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr));
491a7c1b72Smws }
501a7c1b72Smws 
511a7c1b72Smws /*ARGSUSED*/
521a7c1b72Smws static void
dis_load(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)531a7c1b72Smws dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
541a7c1b72Smws {
551a7c1b72Smws 	mdb_printf("%-4s [%%r%u], %%r%u", name,
561a7c1b72Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
571a7c1b72Smws }
581a7c1b72Smws 
591a7c1b72Smws /*ARGSUSED*/
601a7c1b72Smws static void
dis_store(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)611a7c1b72Smws dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
621a7c1b72Smws {
631a7c1b72Smws 	mdb_printf("%-4s %%r%u, [%%r%u]", name,
641a7c1b72Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
651a7c1b72Smws }
661a7c1b72Smws 
671a7c1b72Smws /*ARGSUSED*/
681a7c1b72Smws static void
dis_str(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)691a7c1b72Smws dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
701a7c1b72Smws {
711a7c1b72Smws 	mdb_printf("%s", name);
721a7c1b72Smws }
731a7c1b72Smws 
741a7c1b72Smws /*ARGSUSED*/
751a7c1b72Smws static void
dis_r1rd(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)761a7c1b72Smws dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
771a7c1b72Smws {
781a7c1b72Smws 	mdb_printf("%-4s %%r%u, %%r%u", name,
791a7c1b72Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
801a7c1b72Smws }
811a7c1b72Smws 
821a7c1b72Smws /*ARGSUSED*/
831a7c1b72Smws static void
dis_cmp(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)841a7c1b72Smws dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
851a7c1b72Smws {
861a7c1b72Smws 	mdb_printf("%-4s %%r%u, %%r%u", name,
871a7c1b72Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_R2(instr));
881a7c1b72Smws }
891a7c1b72Smws 
901a7c1b72Smws /*ARGSUSED*/
911a7c1b72Smws static void
dis_tst(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)921a7c1b72Smws dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
931a7c1b72Smws {
941a7c1b72Smws 	mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr));
951a7c1b72Smws }
961a7c1b72Smws 
971a7c1b72Smws static const char *
dis_varname(const dtrace_difo_t * dp,uint_t id,uint_t scope)981a7c1b72Smws dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope)
991a7c1b72Smws {
1001a7c1b72Smws 	dtrace_difv_t *dvp;
1011a7c1b72Smws 	size_t varsize;
1021a7c1b72Smws 	caddr_t addr = NULL, str;
1031a7c1b72Smws 	uint_t i;
1041a7c1b72Smws 
1051a7c1b72Smws 	if (dp == NULL)
1061a7c1b72Smws 		return (NULL);
1071a7c1b72Smws 
1081a7c1b72Smws 	varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
1091a7c1b72Smws 	dvp = mdb_alloc(varsize, UM_SLEEP);
1101a7c1b72Smws 
1111a7c1b72Smws 	if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
1121a7c1b72Smws 		mdb_free(dvp, varsize);
1131a7c1b72Smws 		return ("<unreadable>");
1141a7c1b72Smws 	}
1151a7c1b72Smws 
1161a7c1b72Smws 	for (i = 0; i < dp->dtdo_varlen; i++) {
1171a7c1b72Smws 		if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) {
1181a7c1b72Smws 			if (dvp[i].dtdv_name < dp->dtdo_strlen)
1191a7c1b72Smws 				addr = dp->dtdo_strtab + dvp[i].dtdv_name;
1201a7c1b72Smws 			break;
1211a7c1b72Smws 		}
1221a7c1b72Smws 	}
1231a7c1b72Smws 
1241a7c1b72Smws 	mdb_free(dvp, varsize);
1251a7c1b72Smws 
1261a7c1b72Smws 	if (addr == NULL)
1271a7c1b72Smws 		return (NULL);
1281a7c1b72Smws 
1291a7c1b72Smws 	str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC);
1301a7c1b72Smws 
1311a7c1b72Smws 	for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) {
1321a7c1b72Smws 		if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1)
1331a7c1b72Smws 			return ("<unreadable>");
1341a7c1b72Smws 	}
1351a7c1b72Smws 
1361a7c1b72Smws 	return (str);
1371a7c1b72Smws }
1381a7c1b72Smws 
1391a7c1b72Smws static uint_t
dis_scope(const char * name)1401a7c1b72Smws dis_scope(const char *name)
1411a7c1b72Smws {
1421a7c1b72Smws 	switch (name[2]) {
1431a7c1b72Smws 	case 'l': return (DIFV_SCOPE_LOCAL);
1441a7c1b72Smws 	case 't': return (DIFV_SCOPE_THREAD);
1451a7c1b72Smws 	case 'g': return (DIFV_SCOPE_GLOBAL);
1461a7c1b72Smws 	default: return (-1u);
1471a7c1b72Smws 	}
1481a7c1b72Smws }
1491a7c1b72Smws 
1501a7c1b72Smws static void
dis_lda(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)1511a7c1b72Smws dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
1521a7c1b72Smws {
1531a7c1b72Smws 	uint_t var = DIF_INSTR_R1(instr);
1541a7c1b72Smws 	const char *vname;
1551a7c1b72Smws 
1561a7c1b72Smws 	mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name,
1571a7c1b72Smws 	    var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
1581a7c1b72Smws 
1591a7c1b72Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
1601a7c1b72Smws 		mdb_printf("\t\t! %s", vname);
1611a7c1b72Smws }
1621a7c1b72Smws 
1631a7c1b72Smws static void
dis_ldv(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)1641a7c1b72Smws dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
1651a7c1b72Smws {
1661a7c1b72Smws 	uint_t var = DIF_INSTR_VAR(instr);
1671a7c1b72Smws 	const char *vname;
1681a7c1b72Smws 
1691a7c1b72Smws 	mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr));
1701a7c1b72Smws 
1711a7c1b72Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
1721a7c1b72Smws 		mdb_printf("\t\t! %s", vname);
1731a7c1b72Smws }
1741a7c1b72Smws 
1751a7c1b72Smws static void
dis_stv(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)1761a7c1b72Smws dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
1771a7c1b72Smws {
1781a7c1b72Smws 	uint_t var = DIF_INSTR_VAR(instr);
1791a7c1b72Smws 	const char *vname;
1801a7c1b72Smws 
1811a7c1b72Smws 	mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var);
1821a7c1b72Smws 
1831a7c1b72Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
1841a7c1b72Smws 		mdb_printf("\t\t! %s", vname);
1851a7c1b72Smws }
1861a7c1b72Smws 
1871a7c1b72Smws static void
dis_setx(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)1881a7c1b72Smws dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
1891a7c1b72Smws {
1901a7c1b72Smws 	uint_t intptr = DIF_INSTR_INTEGER(instr);
1911a7c1b72Smws 
1921a7c1b72Smws 	mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name,
1931a7c1b72Smws 	    intptr, DIF_INSTR_RD(instr));
1941a7c1b72Smws 
1951a7c1b72Smws 	if (dp != NULL && intptr < dp->dtdo_intlen) {
1961a7c1b72Smws 		uint64_t *ip = mdb_alloc(dp->dtdo_intlen *
1971a7c1b72Smws 		    sizeof (uint64_t), UM_SLEEP | UM_GC);
1981a7c1b72Smws 
1991a7c1b72Smws 		if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t),
2001a7c1b72Smws 		    (uintptr_t)dp->dtdo_inttab) == -1)
2011a7c1b72Smws 			mdb_warn("failed to read data at %p", dp->dtdo_inttab);
2021a7c1b72Smws 		else
2031a7c1b72Smws 			mdb_printf("\t\t! 0x%llx", ip[intptr]);
2041a7c1b72Smws 	}
2051a7c1b72Smws }
2061a7c1b72Smws 
2071a7c1b72Smws static void
dis_sets(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)2081a7c1b72Smws dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
2091a7c1b72Smws {
2101a7c1b72Smws 	uint_t strptr = DIF_INSTR_STRING(instr);
2111a7c1b72Smws 
2121a7c1b72Smws 	mdb_printf("%-4s DIF_STRING[%u], %%r%u", name,
2131a7c1b72Smws 	    strptr, DIF_INSTR_RD(instr));
2141a7c1b72Smws 
2151a7c1b72Smws 	if (dp != NULL && strptr < dp->dtdo_strlen) {
2161a7c1b72Smws 		char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
2171a7c1b72Smws 
2181a7c1b72Smws 		if (mdb_vread(str, dp->dtdo_strlen,
2191a7c1b72Smws 		    (uintptr_t)dp->dtdo_strtab) == -1)
2201a7c1b72Smws 			mdb_warn("failed to read data at %p", dp->dtdo_strtab);
2211a7c1b72Smws 		else
2221a7c1b72Smws 			mdb_printf("\t\t! \"%s\"", str + strptr);
2231a7c1b72Smws 	}
2241a7c1b72Smws }
2251a7c1b72Smws 
2261a7c1b72Smws /*ARGSUSED*/
2271a7c1b72Smws static void
dis_ret(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)2281a7c1b72Smws dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
2291a7c1b72Smws {
2301a7c1b72Smws 	mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr));
2311a7c1b72Smws }
2321a7c1b72Smws 
2331a7c1b72Smws /*ARGSUSED*/
2341a7c1b72Smws static void
dis_call(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)2351a7c1b72Smws dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
2361a7c1b72Smws {
2371a7c1b72Smws 	uint_t subr = DIF_INSTR_SUBR(instr);
2381a7c1b72Smws 
2391a7c1b72Smws 	mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s",
2401a7c1b72Smws 	    name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr));
2411a7c1b72Smws }
2421a7c1b72Smws 
2431a7c1b72Smws /*ARGSUSED*/
2441a7c1b72Smws static void
dis_pushts(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)2451a7c1b72Smws dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
2461a7c1b72Smws {
2471a7c1b72Smws 	static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" };
2481a7c1b72Smws 	uint_t type = DIF_INSTR_TYPE(instr);
2491a7c1b72Smws 
2501a7c1b72Smws 	mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u",
2511a7c1b72Smws 	    name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr));
2521a7c1b72Smws 
2531a7c1b72Smws 	if (type < sizeof (tnames) / sizeof (tnames[0]))
254187eccf8Sbmc 		mdb_printf("\t\t! %s", tnames[type]);
2551a7c1b72Smws }
2561a7c1b72Smws 
2571a7c1b72Smws /*ARGSUSED*/
2581a7c1b72Smws static void
dis_xlate(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)2591a7c1b72Smws dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
2601a7c1b72Smws {
2611a7c1b72Smws 	mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name,
2621a7c1b72Smws 	    DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr));
2631a7c1b72Smws }
2641a7c1b72Smws 
2651a7c1b72Smws static char *
dis_typestr(const dtrace_diftype_t * t,char * buf,size_t len)2661a7c1b72Smws dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
2671a7c1b72Smws {
2681a7c1b72Smws 	char kind[8];
2691a7c1b72Smws 
2701a7c1b72Smws 	switch (t->dtdt_kind) {
2711a7c1b72Smws 	case DIF_TYPE_CTF:
2721a7c1b72Smws 		(void) strcpy(kind, "D type");
2731a7c1b72Smws 		break;
2741a7c1b72Smws 	case DIF_TYPE_STRING:
2751a7c1b72Smws 		(void) strcpy(kind, "string");
2761a7c1b72Smws 		break;
2771a7c1b72Smws 	default:
2781a7c1b72Smws 		(void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind);
2791a7c1b72Smws 	}
2801a7c1b72Smws 
2811a7c1b72Smws 	if (t->dtdt_flags & DIF_TF_BYREF) {
2821a7c1b72Smws 		(void) mdb_snprintf(buf, len,
2831a7c1b72Smws 		    "%s by ref (size %lu)",
2841a7c1b72Smws 		    kind, (ulong_t)t->dtdt_size);
2851a7c1b72Smws 	} else {
2861a7c1b72Smws 		(void) mdb_snprintf(buf, len, "%s (size %lu)",
2871a7c1b72Smws 		    kind, (ulong_t)t->dtdt_size);
2881a7c1b72Smws 	}
2891a7c1b72Smws 
2901a7c1b72Smws 	return (buf);
2911a7c1b72Smws }
2921a7c1b72Smws 
2931a7c1b72Smws static int
dis(uintptr_t addr,dtrace_difo_t * dp)2941a7c1b72Smws dis(uintptr_t addr, dtrace_difo_t *dp)
2951a7c1b72Smws {
2961a7c1b72Smws 	static const struct opent {
2971a7c1b72Smws 		const char *op_name;
2981a7c1b72Smws 		void (*op_func)(const dtrace_difo_t *,
2991a7c1b72Smws 		    const char *, dif_instr_t);
3001a7c1b72Smws 	} optab[] = {
3011a7c1b72Smws 		{ "(illegal opcode)", dis_str },
3021a7c1b72Smws 		{ "or", dis_log },		/* DIF_OP_OR */
3031a7c1b72Smws 		{ "xor", dis_log },		/* DIF_OP_XOR */
3041a7c1b72Smws 		{ "and", dis_log },		/* DIF_OP_AND */
3051a7c1b72Smws 		{ "sll", dis_log },		/* DIF_OP_SLL */
3061a7c1b72Smws 		{ "srl", dis_log },		/* DIF_OP_SRL */
3071a7c1b72Smws 		{ "sub", dis_log },		/* DIF_OP_SUB */
3081a7c1b72Smws 		{ "add", dis_log },		/* DIF_OP_ADD */
3091a7c1b72Smws 		{ "mul", dis_log },		/* DIF_OP_MUL */
3101a7c1b72Smws 		{ "sdiv", dis_log },		/* DIF_OP_SDIV */
3111a7c1b72Smws 		{ "udiv", dis_log },		/* DIF_OP_UDIV */
3121a7c1b72Smws 		{ "srem", dis_log },		/* DIF_OP_SREM */
3131a7c1b72Smws 		{ "urem", dis_log },		/* DIF_OP_UREM */
3141a7c1b72Smws 		{ "not", dis_r1rd },		/* DIF_OP_NOT */
3151a7c1b72Smws 		{ "mov", dis_r1rd },		/* DIF_OP_MOV */
3161a7c1b72Smws 		{ "cmp", dis_cmp },		/* DIF_OP_CMP */
3171a7c1b72Smws 		{ "tst", dis_tst },		/* DIF_OP_TST */
3181a7c1b72Smws 		{ "ba", dis_branch },		/* DIF_OP_BA */
3191a7c1b72Smws 		{ "be", dis_branch },		/* DIF_OP_BE */
3201a7c1b72Smws 		{ "bne", dis_branch },		/* DIF_OP_BNE */
3211a7c1b72Smws 		{ "bg", dis_branch },		/* DIF_OP_BG */
3221a7c1b72Smws 		{ "bgu", dis_branch },		/* DIF_OP_BGU */
3231a7c1b72Smws 		{ "bge", dis_branch },		/* DIF_OP_BGE */
3241a7c1b72Smws 		{ "bgeu", dis_branch },		/* DIF_OP_BGEU */
3251a7c1b72Smws 		{ "bl", dis_branch },		/* DIF_OP_BL */
3261a7c1b72Smws 		{ "blu", dis_branch },		/* DIF_OP_BLU */
3271a7c1b72Smws 		{ "ble", dis_branch },		/* DIF_OP_BLE */
3281a7c1b72Smws 		{ "bleu", dis_branch },		/* DIF_OP_BLEU */
3291a7c1b72Smws 		{ "ldsb", dis_load },		/* DIF_OP_LDSB */
3301a7c1b72Smws 		{ "ldsh", dis_load },		/* DIF_OP_LDSH */
3311a7c1b72Smws 		{ "ldsw", dis_load },		/* DIF_OP_LDSW */
3321a7c1b72Smws 		{ "ldub", dis_load },		/* DIF_OP_LDUB */
3331a7c1b72Smws 		{ "lduh", dis_load },		/* DIF_OP_LDUH */
3341a7c1b72Smws 		{ "lduw", dis_load },		/* DIF_OP_LDUW */
3351a7c1b72Smws 		{ "ldx", dis_load },		/* DIF_OP_LDX */
3361a7c1b72Smws 		{ "ret", dis_ret },		/* DIF_OP_RET */
3371a7c1b72Smws 		{ "nop", dis_str },		/* DIF_OP_NOP */
3381a7c1b72Smws 		{ "setx", dis_setx },		/* DIF_OP_SETX */
3391a7c1b72Smws 		{ "sets", dis_sets },		/* DIF_OP_SETS */
3401a7c1b72Smws 		{ "scmp", dis_cmp },		/* DIF_OP_SCMP */
3411a7c1b72Smws 		{ "ldga", dis_lda },		/* DIF_OP_LDGA */
3421a7c1b72Smws 		{ "ldgs", dis_ldv },		/* DIF_OP_LDGS */
3431a7c1b72Smws 		{ "stgs", dis_stv },		/* DIF_OP_STGS */
3441a7c1b72Smws 		{ "ldta", dis_lda },		/* DIF_OP_LDTA */
3451a7c1b72Smws 		{ "ldts", dis_ldv },		/* DIF_OP_LDTS */
3461a7c1b72Smws 		{ "stts", dis_stv },		/* DIF_OP_STTS */
3471a7c1b72Smws 		{ "sra", dis_log },		/* DIF_OP_SRA */
3481a7c1b72Smws 		{ "call", dis_call },		/* DIF_OP_CALL */
3491a7c1b72Smws 		{ "pushtr", dis_pushts },	/* DIF_OP_PUSHTR */
3501a7c1b72Smws 		{ "pushtv", dis_pushts },	/* DIF_OP_PUSHTV */
3511a7c1b72Smws 		{ "popts", dis_str },		/* DIF_OP_POPTS */
3521a7c1b72Smws 		{ "flushts", dis_str },		/* DIF_OP_FLUSHTS */
3531a7c1b72Smws 		{ "ldgaa", dis_ldv },		/* DIF_OP_LDGAA */
3541a7c1b72Smws 		{ "ldtaa", dis_ldv },		/* DIF_OP_LDTAA */
3551a7c1b72Smws 		{ "stgaa", dis_stv },		/* DIF_OP_STGAA */
3561a7c1b72Smws 		{ "sttaa", dis_stv },		/* DIF_OP_STTAA */
3571a7c1b72Smws 		{ "ldls", dis_ldv },		/* DIF_OP_LDLS */
3581a7c1b72Smws 		{ "stls", dis_stv },		/* DIF_OP_STLS */
3591a7c1b72Smws 		{ "allocs", dis_r1rd },		/* DIF_OP_ALLOCS */
3601a7c1b72Smws 		{ "copys", dis_log },		/* DIF_OP_COPYS */
3611a7c1b72Smws 		{ "stb", dis_store },		/* DIF_OP_STB */
3621a7c1b72Smws 		{ "sth", dis_store },		/* DIF_OP_STH */
3631a7c1b72Smws 		{ "stw", dis_store },		/* DIF_OP_STW */
3641a7c1b72Smws 		{ "stx", dis_store },		/* DIF_OP_STX */
3651a7c1b72Smws 		{ "uldsb", dis_load },		/* DIF_OP_ULDSB */
3661a7c1b72Smws 		{ "uldsh", dis_load },		/* DIF_OP_ULDSH */
3671a7c1b72Smws 		{ "uldsw", dis_load },		/* DIF_OP_ULDSW */
3681a7c1b72Smws 		{ "uldub", dis_load },		/* DIF_OP_ULDUB */
3691a7c1b72Smws 		{ "ulduh", dis_load },		/* DIF_OP_ULDUH */
3701a7c1b72Smws 		{ "ulduw", dis_load },		/* DIF_OP_ULDUW */
3711a7c1b72Smws 		{ "uldx", dis_load },		/* DIF_OP_ULDX */
3721a7c1b72Smws 		{ "rldsb", dis_load },		/* DIF_OP_RLDSB */
3731a7c1b72Smws 		{ "rldsh", dis_load },		/* DIF_OP_RLDSH */
3741a7c1b72Smws 		{ "rldsw", dis_load },		/* DIF_OP_RLDSW */
3751a7c1b72Smws 		{ "rldub", dis_load },		/* DIF_OP_RLDUB */
3761a7c1b72Smws 		{ "rlduh", dis_load },		/* DIF_OP_RLDUH */
3771a7c1b72Smws 		{ "rlduw", dis_load },		/* DIF_OP_RLDUW */
3781a7c1b72Smws 		{ "rldx", dis_load },		/* DIF_OP_RLDX */
3791a7c1b72Smws 		{ "xlate", dis_xlate },		/* DIF_OP_XLATE */
3801a7c1b72Smws 		{ "xlarg", dis_xlate },		/* DIF_OP_XLARG */
3811a7c1b72Smws 	};
3821a7c1b72Smws 
3831a7c1b72Smws 	dif_instr_t instr, opcode;
3841a7c1b72Smws 	const struct opent *op;
3851a7c1b72Smws 
3861a7c1b72Smws 	if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) {
3871a7c1b72Smws 		mdb_warn("failed to read DIF instruction at %p", addr);
3881a7c1b72Smws 		return (DCMD_ERR);
3891a7c1b72Smws 	}
3901a7c1b72Smws 
3911a7c1b72Smws 	opcode = DIF_INSTR_OP(instr);
3921a7c1b72Smws 
3931a7c1b72Smws 	if (opcode >= sizeof (optab) / sizeof (optab[0]))
3941a7c1b72Smws 		opcode = 0; /* force invalid opcode message */
3951a7c1b72Smws 
3961a7c1b72Smws 	op = &optab[opcode];
397187eccf8Sbmc 	mdb_printf("%0?p %08x ", addr, instr);
3981a7c1b72Smws 	op->op_func(dp, op->op_name, instr);
3991a7c1b72Smws 	mdb_printf("\n");
4001a7c1b72Smws 	mdb_set_dot(addr + sizeof (dif_instr_t));
4011a7c1b72Smws 
4021a7c1b72Smws 	return (DCMD_OK);
4031a7c1b72Smws }
4041a7c1b72Smws 
4051a7c1b72Smws /*ARGSUSED*/
4061a7c1b72Smws int
difo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4071a7c1b72Smws difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4081a7c1b72Smws {
4091a7c1b72Smws 	dtrace_difo_t difo, *dp = &difo;
4101a7c1b72Smws 	uintptr_t instr, limit;
4111a7c1b72Smws 	dtrace_difv_t *dvp;
4121a7c1b72Smws 	size_t varsize;
4131a7c1b72Smws 	ulong_t i;
4141a7c1b72Smws 	char type[64];
4151a7c1b72Smws 	char *str;
4161a7c1b72Smws 
4171a7c1b72Smws 	if (!(flags & DCMD_ADDRSPEC))
4181a7c1b72Smws 		return (DCMD_USAGE);
4191a7c1b72Smws 
4201a7c1b72Smws 	if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) {
4211a7c1b72Smws 		mdb_warn("couldn't read dtrace_difo_t at %p", addr);
4221a7c1b72Smws 		return (DCMD_ERR);
4231a7c1b72Smws 	}
4241a7c1b72Smws 
4251a7c1b72Smws 	mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
4261a7c1b72Smws 	    addr, dp->dtdo_refcnt);
427187eccf8Sbmc 	mdb_printf("%<b>%-?s %-8s %s%</b>\n", "ADDR", "OPCODE", "INSTRUCTION");
4281a7c1b72Smws 
4291a7c1b72Smws 	mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf);
4301a7c1b72Smws 	limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t);
4311a7c1b72Smws 
4321a7c1b72Smws 	while ((instr = mdb_get_dot()) < limit)
4331a7c1b72Smws 		dis(instr, dp);
4341a7c1b72Smws 
4351a7c1b72Smws 	if (dp->dtdo_varlen != 0) {
4361a7c1b72Smws 		mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n",
4371a7c1b72Smws 		    "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
4381a7c1b72Smws 	}
4391a7c1b72Smws 
4401a7c1b72Smws 	varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
4411a7c1b72Smws 	dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC);
4421a7c1b72Smws 
4431a7c1b72Smws 	if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
4441a7c1b72Smws 		mdb_warn("couldn't read dtdo_vartab");
4451a7c1b72Smws 		return (DCMD_ERR);
4461a7c1b72Smws 	}
4471a7c1b72Smws 
4481a7c1b72Smws 	str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
4491a7c1b72Smws 
4501a7c1b72Smws 	if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) {
4511a7c1b72Smws 		mdb_warn("couldn't read dtdo_strtab");
4521a7c1b72Smws 		return (DCMD_ERR);
4531a7c1b72Smws 	}
4541a7c1b72Smws 
4551a7c1b72Smws 	for (i = 0; i < dp->dtdo_varlen; i++) {
4561a7c1b72Smws 		dtrace_difv_t *v = &dvp[i];
4571a7c1b72Smws 		char kind[4], scope[4], flags[16] = { 0 };
4581a7c1b72Smws 
4591a7c1b72Smws 		switch (v->dtdv_kind) {
4601a7c1b72Smws 		case DIFV_KIND_ARRAY:
4611a7c1b72Smws 			(void) strcpy(kind, "arr");
4621a7c1b72Smws 			break;
4631a7c1b72Smws 		case DIFV_KIND_SCALAR:
4641a7c1b72Smws 			(void) strcpy(kind, "scl");
4651a7c1b72Smws 			break;
4661a7c1b72Smws 		default:
4671a7c1b72Smws 			(void) mdb_snprintf(kind, sizeof (kind),
4681a7c1b72Smws 			    "%u", v->dtdv_kind);
4691a7c1b72Smws 		}
4701a7c1b72Smws 
4711a7c1b72Smws 		switch (v->dtdv_scope) {
4721a7c1b72Smws 		case DIFV_SCOPE_GLOBAL:
4731a7c1b72Smws 			(void) strcpy(scope, "glb");
4741a7c1b72Smws 			break;
4751a7c1b72Smws 		case DIFV_SCOPE_THREAD:
4761a7c1b72Smws 			(void) strcpy(scope, "tls");
4771a7c1b72Smws 			break;
4781a7c1b72Smws 		case DIFV_SCOPE_LOCAL:
4791a7c1b72Smws 			(void) strcpy(scope, "loc");
4801a7c1b72Smws 			break;
4811a7c1b72Smws 		default:
4821a7c1b72Smws 			(void) mdb_snprintf(scope, sizeof (scope),
4831a7c1b72Smws 			    "%u", v->dtdv_scope);
4841a7c1b72Smws 		}
4851a7c1b72Smws 
4861a7c1b72Smws 		if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
4871a7c1b72Smws 			(void) mdb_snprintf(flags, sizeof (flags), "/0x%x",
4881a7c1b72Smws 			    v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
4891a7c1b72Smws 		}
4901a7c1b72Smws 
4911a7c1b72Smws 		if (v->dtdv_flags & DIFV_F_REF)
4921a7c1b72Smws 			(void) strcat(flags, "/r");
4931a7c1b72Smws 		if (v->dtdv_flags & DIFV_F_MOD)
4941a7c1b72Smws 			(void) strcat(flags, "/w");
4951a7c1b72Smws 
4961a7c1b72Smws 		mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n",
4971a7c1b72Smws 		    &str[v->dtdv_name],
4981a7c1b72Smws 		    v->dtdv_id, kind, scope, flags + 1,
4991a7c1b72Smws 		    dis_typestr(&v->dtdv_type, type, sizeof (type)));
5001a7c1b72Smws 	}
5011a7c1b72Smws 
5021a7c1b72Smws 	mdb_printf("\n%<b>RETURN%</b>\n%s\n\n",
5031a7c1b72Smws 	    dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
5041a7c1b72Smws 
5051a7c1b72Smws 	return (DCMD_OK);
5061a7c1b72Smws }
5071a7c1b72Smws 
5081a7c1b72Smws /*ARGSUSED*/
5091a7c1b72Smws int
difinstr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5101a7c1b72Smws difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5111a7c1b72Smws {
5121a7c1b72Smws 	if (!(flags & DCMD_ADDRSPEC))
5131a7c1b72Smws 		return (DCMD_USAGE);
5141a7c1b72Smws 
5151a7c1b72Smws 	return (dis(addr, NULL));
5161a7c1b72Smws }
5171a7c1b72Smws 
5181a7c1b72Smws /*ARGSUSED*/
5191a7c1b72Smws int
dof_hdr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5201a7c1b72Smws dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5211a7c1b72Smws {
5221a7c1b72Smws 	dof_hdr_t h;
5231a7c1b72Smws 
5241a7c1b72Smws 	if (argc != 0)
5251a7c1b72Smws 		return (DCMD_USAGE);
5261a7c1b72Smws 
5271a7c1b72Smws 	if (!(flags & DCMD_ADDRSPEC))
5281a7c1b72Smws 		addr = 0; /* assume base of file in file target */
5291a7c1b72Smws 
5301a7c1b72Smws 	if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) {
5311a7c1b72Smws 		mdb_warn("failed to read header at %p", addr);
5321a7c1b72Smws 		return (DCMD_ERR);
5331a7c1b72Smws 	}
5341a7c1b72Smws 
5351a7c1b72Smws 	mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n",
5361a7c1b72Smws 	    h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1],
5371a7c1b72Smws 	    h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]);
5381a7c1b72Smws 
5391a7c1b72Smws 	switch (h.dofh_ident[DOF_ID_MODEL]) {
5401a7c1b72Smws 	case DOF_MODEL_ILP32:
5411a7c1b72Smws 		mdb_printf("dofh_ident.id_model = ILP32\n");
5421a7c1b72Smws 		break;
5431a7c1b72Smws 	case DOF_MODEL_LP64:
5441a7c1b72Smws 		mdb_printf("dofh_ident.id_model = LP64\n");
5451a7c1b72Smws 		break;
5461a7c1b72Smws 	default:
5471a7c1b72Smws 		mdb_printf("dofh_ident.id_model = 0x%x\n",
5481a7c1b72Smws 		    h.dofh_ident[DOF_ID_MODEL]);
5491a7c1b72Smws 	}
5501a7c1b72Smws 
5511a7c1b72Smws 	switch (h.dofh_ident[DOF_ID_ENCODING]) {
5521a7c1b72Smws 	case DOF_ENCODE_LSB:
5531a7c1b72Smws 		mdb_printf("dofh_ident.id_encoding = LSB\n");
5541a7c1b72Smws 		break;
5551a7c1b72Smws 	case DOF_ENCODE_MSB:
5561a7c1b72Smws 		mdb_printf("dofh_ident.id_encoding = MSB\n");
5571a7c1b72Smws 		break;
5581a7c1b72Smws 	default:
5591a7c1b72Smws 		mdb_printf("dofh_ident.id_encoding = 0x%x\n",
5601a7c1b72Smws 		    h.dofh_ident[DOF_ID_ENCODING]);
5611a7c1b72Smws 	}
5621a7c1b72Smws 
5631a7c1b72Smws 	mdb_printf("dofh_ident.id_version = %u\n",
5641a7c1b72Smws 	    h.dofh_ident[DOF_ID_VERSION]);
5651a7c1b72Smws 	mdb_printf("dofh_ident.id_difvers = %u\n",
5661a7c1b72Smws 	    h.dofh_ident[DOF_ID_DIFVERS]);
5671a7c1b72Smws 	mdb_printf("dofh_ident.id_difireg = %u\n",
5681a7c1b72Smws 	    h.dofh_ident[DOF_ID_DIFIREG]);
5691a7c1b72Smws 	mdb_printf("dofh_ident.id_diftreg = %u\n",
5701a7c1b72Smws 	    h.dofh_ident[DOF_ID_DIFTREG]);
5711a7c1b72Smws 
5721a7c1b72Smws 	mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags);
5731a7c1b72Smws 	mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize);
5741a7c1b72Smws 	mdb_printf("dofh_secsize = %u\n", h.dofh_secsize);
5751a7c1b72Smws 	mdb_printf("dofh_secnum = %u\n", h.dofh_secnum);
5761a7c1b72Smws 	mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff);
5771a7c1b72Smws 	mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz);
5781a7c1b72Smws 	mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz);
5791a7c1b72Smws 
5801a7c1b72Smws 	return (DCMD_OK);
5811a7c1b72Smws }
5821a7c1b72Smws 
5831a7c1b72Smws /*ARGSUSED*/
5841a7c1b72Smws static int
dof_sec_walk(uintptr_t addr,void * ignored,int * sec)5851a7c1b72Smws dof_sec_walk(uintptr_t addr, void *ignored, int *sec)
5861a7c1b72Smws {
5871a7c1b72Smws 	mdb_printf("%3d ", (*sec)++);
5881a7c1b72Smws 	(void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL);
5891a7c1b72Smws 	return (WALK_NEXT);
5901a7c1b72Smws }
5911a7c1b72Smws 
5921a7c1b72Smws /*ARGSUSED*/
5931a7c1b72Smws int
dof_sec(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5941a7c1b72Smws dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5951a7c1b72Smws {
5961a7c1b72Smws 	const char *name;
5971a7c1b72Smws 	dof_sec_t s;
5981a7c1b72Smws 
5991a7c1b72Smws 	if (!(flags & DCMD_ADDRSPEC))
6001a7c1b72Smws 		mdb_printf("%<u>%-3s ", "NDX");
6011a7c1b72Smws 
6021a7c1b72Smws 	if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) {
6031a7c1b72Smws 		mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
6041a7c1b72Smws 		    "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET",
6051a7c1b72Smws 		    "SIZE");
6061a7c1b72Smws 	}
6071a7c1b72Smws 
6081a7c1b72Smws 	if (!(flags & DCMD_ADDRSPEC)) {
6091a7c1b72Smws 		int sec = 0;
6101a7c1b72Smws 
6111a7c1b72Smws 		if (mdb_walk("dof_sec",
6121a7c1b72Smws 		    (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) {
6131a7c1b72Smws 			mdb_warn("failed to walk dof_sec");
6141a7c1b72Smws 			return (DCMD_ERR);
6151a7c1b72Smws 		}
6161a7c1b72Smws 		return (DCMD_OK);
6171a7c1b72Smws 	}
6181a7c1b72Smws 
6191a7c1b72Smws 	if (argc != 0)
6201a7c1b72Smws 		return (DCMD_USAGE);
6211a7c1b72Smws 
6221a7c1b72Smws 	if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
6231a7c1b72Smws 		mdb_warn("failed to read section header at %p", addr);
6241a7c1b72Smws 		return (DCMD_ERR);
6251a7c1b72Smws 	}
6261a7c1b72Smws 
6271a7c1b72Smws 	mdb_printf("%?p ", addr);
6281a7c1b72Smws 
6291a7c1b72Smws 	if ((name = dof_sec_name(s.dofs_type)) != NULL)
6301a7c1b72Smws 		mdb_printf("%-10s ", name);
6311a7c1b72Smws 	else
6321a7c1b72Smws 		mdb_printf("%-10u ", s.dofs_type);
6331a7c1b72Smws 
6341a7c1b72Smws 	mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align,
6351a7c1b72Smws 	    s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size);
6361a7c1b72Smws 
6371a7c1b72Smws 	return (DCMD_OK);
6381a7c1b72Smws }
6391a7c1b72Smws 
6401a7c1b72Smws int
dof_sec_walk_init(mdb_walk_state_t * wsp)6411a7c1b72Smws dof_sec_walk_init(mdb_walk_state_t *wsp)
6421a7c1b72Smws {
6431a7c1b72Smws 	dof_hdr_t h, *hp;
6441a7c1b72Smws 	size_t size;
6451a7c1b72Smws 
6461a7c1b72Smws 	if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) {
6471a7c1b72Smws 		mdb_warn("failed to read DOF header at %p", wsp->walk_addr);
6481a7c1b72Smws 		return (WALK_ERR);
6491a7c1b72Smws 	}
6501a7c1b72Smws 
6511a7c1b72Smws 	size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum;
6521a7c1b72Smws 	hp = mdb_alloc(size, UM_SLEEP);
6531a7c1b72Smws 
6541a7c1b72Smws 	if (mdb_vread(hp, size, wsp->walk_addr) != size) {
6551a7c1b72Smws 		mdb_warn("failed to read DOF sections at %p", wsp->walk_addr);
6561a7c1b72Smws 		mdb_free(hp, size);
6571a7c1b72Smws 		return (WALK_ERR);
6581a7c1b72Smws 	}
6591a7c1b72Smws 
6601a7c1b72Smws 	wsp->walk_arg = (void *)0;
6611a7c1b72Smws 	wsp->walk_data = hp;
6621a7c1b72Smws 
6631a7c1b72Smws 	return (WALK_NEXT);
6641a7c1b72Smws }
6651a7c1b72Smws 
6661a7c1b72Smws int
dof_sec_walk_step(mdb_walk_state_t * wsp)6671a7c1b72Smws dof_sec_walk_step(mdb_walk_state_t *wsp)
6681a7c1b72Smws {
6691a7c1b72Smws 	uint_t i = (uintptr_t)wsp->walk_arg;
6701a7c1b72Smws 	size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i;
6711a7c1b72Smws 	dof_hdr_t *hp = wsp->walk_data;
6721a7c1b72Smws 	dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off);
6731a7c1b72Smws 
6741a7c1b72Smws 	if (i >= hp->dofh_secnum)
6751a7c1b72Smws 		return (WALK_DONE);
6761a7c1b72Smws 
6771a7c1b72Smws 	wsp->walk_arg = (void *)(uintptr_t)(i + 1);
6781a7c1b72Smws 	return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata));
6791a7c1b72Smws }
6801a7c1b72Smws 
6811a7c1b72Smws void
dof_sec_walk_fini(mdb_walk_state_t * wsp)6821a7c1b72Smws dof_sec_walk_fini(mdb_walk_state_t *wsp)
6831a7c1b72Smws {
6841a7c1b72Smws 	dof_hdr_t *hp = wsp->walk_data;
6851a7c1b72Smws 	mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum);
6861a7c1b72Smws }
6871a7c1b72Smws 
6881a7c1b72Smws /*ARGSUSED*/
6891a7c1b72Smws int
dof_ecbdesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6901a7c1b72Smws dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6911a7c1b72Smws {
6921a7c1b72Smws 	dof_ecbdesc_t e;
6931a7c1b72Smws 
6941a7c1b72Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
6951a7c1b72Smws 		return (DCMD_USAGE);
6961a7c1b72Smws 
6971a7c1b72Smws 	if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) {
6981a7c1b72Smws 		mdb_warn("failed to read ecbdesc at %p", addr);
6991a7c1b72Smws 		return (DCMD_ERR);
7001a7c1b72Smws 	}
7011a7c1b72Smws 
7021a7c1b72Smws 	mdb_printf("dofe_probes = %d\n", e.dofe_probes);
7031a7c1b72Smws 	mdb_printf("dofe_actions = %d\n", e.dofe_actions);
7041a7c1b72Smws 	mdb_printf("dofe_pred = %d\n", e.dofe_pred);
7051a7c1b72Smws 	mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg);
7061a7c1b72Smws 
7071a7c1b72Smws 	return (DCMD_OK);
7081a7c1b72Smws }
7091a7c1b72Smws 
7101a7c1b72Smws /*ARGSUSED*/
7111a7c1b72Smws int
dof_probedesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7121a7c1b72Smws dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7131a7c1b72Smws {
7141a7c1b72Smws 	dof_probedesc_t p;
7151a7c1b72Smws 
7161a7c1b72Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
7171a7c1b72Smws 		return (DCMD_USAGE);
7181a7c1b72Smws 
7191a7c1b72Smws 	if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) {
7201a7c1b72Smws 		mdb_warn("failed to read probedesc at %p", addr);
7211a7c1b72Smws 		return (DCMD_ERR);
7221a7c1b72Smws 	}
7231a7c1b72Smws 
7241a7c1b72Smws 	mdb_printf("dofp_strtab = %d\n", p.dofp_strtab);
7251a7c1b72Smws 	mdb_printf("dofp_provider = %u\n", p.dofp_provider);
7261a7c1b72Smws 	mdb_printf("dofp_mod = %u\n", p.dofp_mod);
7271a7c1b72Smws 	mdb_printf("dofp_func = %u\n", p.dofp_func);
7281a7c1b72Smws 	mdb_printf("dofp_name = %u\n", p.dofp_name);
7291a7c1b72Smws 	mdb_printf("dofp_id = %u\n", p.dofp_id);
7301a7c1b72Smws 
7311a7c1b72Smws 	return (DCMD_OK);
7321a7c1b72Smws }
7331a7c1b72Smws 
7341a7c1b72Smws /*ARGSUSED*/
7351a7c1b72Smws int
dof_actdesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7361a7c1b72Smws dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7371a7c1b72Smws {
7381a7c1b72Smws 	dof_actdesc_t a;
7391a7c1b72Smws 
7401a7c1b72Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
7411a7c1b72Smws 		return (DCMD_USAGE);
7421a7c1b72Smws 
7431a7c1b72Smws 	if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
7441a7c1b72Smws 		mdb_warn("failed to read actdesc at %p", addr);
7451a7c1b72Smws 		return (DCMD_ERR);
7461a7c1b72Smws 	}
7471a7c1b72Smws 
7481a7c1b72Smws 	mdb_printf("dofa_difo = %d\n", a.dofa_difo);
7491a7c1b72Smws 	mdb_printf("dofa_strtab = %d\n", a.dofa_strtab);
7501a7c1b72Smws 	mdb_printf("dofa_kind = %u\n", a.dofa_kind);
7511a7c1b72Smws 	mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple);
7521a7c1b72Smws 	mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg);
7531a7c1b72Smws 	mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg);
7541a7c1b72Smws 
7551a7c1b72Smws 	return (DCMD_OK);
7561a7c1b72Smws }
7571a7c1b72Smws 
7581a7c1b72Smws /*ARGSUSED*/
7591a7c1b72Smws int
dof_relohdr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7601a7c1b72Smws dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7611a7c1b72Smws {
7621a7c1b72Smws 	dof_relohdr_t r;
7631a7c1b72Smws 
7641a7c1b72Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
7651a7c1b72Smws 		return (DCMD_USAGE);
7661a7c1b72Smws 
7671a7c1b72Smws 	if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
7681a7c1b72Smws 		mdb_warn("failed to read relohdr at %p", addr);
7691a7c1b72Smws 		return (DCMD_ERR);
7701a7c1b72Smws 	}
7711a7c1b72Smws 
7721a7c1b72Smws 	mdb_printf("dofr_strtab = %d\n", r.dofr_strtab);
7731a7c1b72Smws 	mdb_printf("dofr_relsec = %d\n", r.dofr_relsec);
7741a7c1b72Smws 	mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec);
7751a7c1b72Smws 
7761a7c1b72Smws 	return (DCMD_OK);
7771a7c1b72Smws }
7781a7c1b72Smws 
7791a7c1b72Smws /*ARGSUSED*/
7801a7c1b72Smws int
dof_relodesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7811a7c1b72Smws dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7821a7c1b72Smws {
7831a7c1b72Smws 	dof_relodesc_t r;
7841a7c1b72Smws 
7851a7c1b72Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
7861a7c1b72Smws 		return (DCMD_USAGE);
7871a7c1b72Smws 
7881a7c1b72Smws 	if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
7891a7c1b72Smws 		mdb_warn("failed to read relodesc at %p", addr);
7901a7c1b72Smws 		return (DCMD_ERR);
7911a7c1b72Smws 	}
7921a7c1b72Smws 
7931a7c1b72Smws 	mdb_printf("dofr_name = %u\n", r.dofr_name);
7941a7c1b72Smws 	mdb_printf("dofr_type = %u\n", r.dofr_type);
7951a7c1b72Smws 	mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset);
7961a7c1b72Smws 	mdb_printf("dofr_data = 0x%llx\n", r.dofr_data);
7971a7c1b72Smws 
7981a7c1b72Smws 	return (DCMD_OK);
7991a7c1b72Smws }
8001a7c1b72Smws 
8011a7c1b72Smws static int
dof_sect_strtab(uintptr_t addr,dof_sec_t * sec)8021a7c1b72Smws dof_sect_strtab(uintptr_t addr, dof_sec_t *sec)
8031a7c1b72Smws {
8041a7c1b72Smws 	char *strtab;
8051a7c1b72Smws 	size_t sz, i;
8061a7c1b72Smws 
8071a7c1b72Smws 	sz = (size_t)sec->dofs_size;
8081a7c1b72Smws 	strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
8091a7c1b72Smws 	if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) {
8101a7c1b72Smws 		mdb_warn("failed to read string table");
8111a7c1b72Smws 		return (1);
8121a7c1b72Smws 	}
8131a7c1b72Smws 
8141a7c1b72Smws 	mdb_printf("size = %lx\n", sz);
8151a7c1b72Smws 
8161a7c1b72Smws 	for (i = 0; i < sz; i++) {
8171a7c1b72Smws 		if (strtab[i] == '\0')
8181a7c1b72Smws 			mdb_printf("\\0");
8191a7c1b72Smws 		else
8201a7c1b72Smws 			mdb_printf("%c", strtab[i]);
8211a7c1b72Smws 	}
8221a7c1b72Smws 
8231a7c1b72Smws 	mdb_printf("\n");
8241a7c1b72Smws 
8251a7c1b72Smws 	return (0);
8261a7c1b72Smws }
8271a7c1b72Smws 
8281a7c1b72Smws static int
dof_sect_provider(dof_hdr_t * dofh,uintptr_t addr,dof_sec_t * sec,dof_sec_t * dofs)829*ac448965Sahl dof_sect_provider(dof_hdr_t *dofh, uintptr_t addr, dof_sec_t *sec,
830*ac448965Sahl     dof_sec_t *dofs)
8311a7c1b72Smws {
8321a7c1b72Smws 	dof_provider_t pv;
8331a7c1b72Smws 	dof_probe_t *pb;
834*ac448965Sahl 	char *strtab, *p;
835*ac448965Sahl 	uint32_t *offs, *enoffs;
8361a7c1b72Smws 	uint8_t *args = NULL;
8371a7c1b72Smws 	size_t sz;
8381a7c1b72Smws 	int i, j;
8391a7c1b72Smws 	dof_stridx_t narg, xarg;
8401a7c1b72Smws 
841*ac448965Sahl 	sz = MIN(sec->dofs_size, sizeof (dof_provider_t));
842*ac448965Sahl 	if (mdb_vread(&pv, sz, addr + sec->dofs_offset) != sz) {
8431a7c1b72Smws 		mdb_warn("failed to read DOF provider");
8441a7c1b72Smws 		return (-1);
8451a7c1b72Smws 	}
8461a7c1b72Smws 
8471a7c1b72Smws 	sz = dofs[pv.dofpv_strtab].dofs_size;
8481a7c1b72Smws 	strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
8491a7c1b72Smws 	if (mdb_vread(strtab, sz, addr +
8501a7c1b72Smws 	    dofs[pv.dofpv_strtab].dofs_offset) != sz) {
8511a7c1b72Smws 		mdb_warn("failed to read string table");
8521a7c1b72Smws 		return (-1);
8531a7c1b72Smws 	}
8541a7c1b72Smws 
8551a7c1b72Smws 	mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset),
8561a7c1b72Smws 	    strtab + pv.dofpv_name);
8571a7c1b72Smws 
8581a7c1b72Smws 	sz = dofs[pv.dofpv_prargs].dofs_size;
8591a7c1b72Smws 	if (sz != 0) {
8601a7c1b72Smws 		args = mdb_alloc(sz, UM_SLEEP | UM_GC);
8611a7c1b72Smws 		if (mdb_vread(args, sz, addr +
8621a7c1b72Smws 		    dofs[pv.dofpv_prargs].dofs_offset) != sz) {
8631a7c1b72Smws 			mdb_warn("failed to read args");
8641a7c1b72Smws 			return (-1);
8651a7c1b72Smws 		}
8661a7c1b72Smws 	}
8671a7c1b72Smws 
8681a7c1b72Smws 	sz = dofs[pv.dofpv_proffs].dofs_size;
8691a7c1b72Smws 	offs = mdb_alloc(sz, UM_SLEEP | UM_GC);
8701a7c1b72Smws 	if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset)
8711a7c1b72Smws 	    != sz) {
872*ac448965Sahl 		mdb_warn("failed to read offsets");
8731a7c1b72Smws 		return (-1);
8741a7c1b72Smws 	}
8751a7c1b72Smws 
876*ac448965Sahl 	enoffs = NULL;
877*ac448965Sahl 	if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 ||
878*ac448965Sahl 	    pv.dofpv_prenoffs == 0) {
879*ac448965Sahl 		sz = dofs[pv.dofpv_prenoffs].dofs_size;
880*ac448965Sahl 		enoffs = mdb_alloc(sz, UM_SLEEP | UM_GC);
881*ac448965Sahl 		if (mdb_vread(enoffs, sz, addr +
882*ac448965Sahl 		    dofs[pv.dofpv_prenoffs].dofs_offset) != sz) {
883*ac448965Sahl 			mdb_warn("failed to read is-enabled offsets");
884*ac448965Sahl 			return (-1);
885*ac448965Sahl 		}
886*ac448965Sahl 	}
887*ac448965Sahl 
8881a7c1b72Smws 	sz = dofs[pv.dofpv_probes].dofs_size;
889*ac448965Sahl 	p = mdb_alloc(sz, UM_SLEEP | UM_GC);
890*ac448965Sahl 	if (mdb_vread(p, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) {
8911a7c1b72Smws 		mdb_warn("failed to read probes");
8921a7c1b72Smws 		return (-1);
8931a7c1b72Smws 	}
8941a7c1b72Smws 
8951a7c1b72Smws 	(void) mdb_inc_indent(2);
8961a7c1b72Smws 
8971a7c1b72Smws 	for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) {
898*ac448965Sahl 		pb = (dof_probe_t *)(uintptr_t)(p +
899*ac448965Sahl 		    i * dofs[pv.dofpv_probes].dofs_entsize);
900*ac448965Sahl 
9011a7c1b72Smws 		mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr +
9021a7c1b72Smws 		    dofs[pv.dofpv_probes].dofs_offset +
9031a7c1b72Smws 		    i * dofs[pv.dofpv_probes].dofs_entsize),
904*ac448965Sahl 		    strtab + pb->dofpr_func,
905*ac448965Sahl 		    strtab + pb->dofpr_name);
9061a7c1b72Smws 
9071a7c1b72Smws 		(void) mdb_inc_indent(2);
908*ac448965Sahl 		mdb_printf("addr: %p\n", (ulong_t)pb->dofpr_addr);
9091a7c1b72Smws 		mdb_printf("offs: ");
910*ac448965Sahl 		for (j = 0; j < pb->dofpr_noffs; j++) {
9111a7c1b72Smws 			mdb_printf("%s %x", "," + (j == 0),
912*ac448965Sahl 			    offs[pb->dofpr_offidx + j]);
9131a7c1b72Smws 		}
9141a7c1b72Smws 		mdb_printf("\n");
9151a7c1b72Smws 
916*ac448965Sahl 		if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
917*ac448965Sahl 			mdb_printf("enoffs: ");
918*ac448965Sahl 			if (enoffs == NULL) {
919*ac448965Sahl 				if (pb->dofpr_nenoffs != 0)
920*ac448965Sahl 					mdb_printf("<error>");
921*ac448965Sahl 			} else {
922*ac448965Sahl 				for (j = 0; j < pb->dofpr_nenoffs; j++) {
923*ac448965Sahl 					mdb_printf("%s %x", "," + (j == 0),
924*ac448965Sahl 					    enoffs[pb->dofpr_enoffidx + j]);
925*ac448965Sahl 				}
926*ac448965Sahl 			}
927*ac448965Sahl 			mdb_printf("\n");
928*ac448965Sahl 		}
929*ac448965Sahl 
9301a7c1b72Smws 		mdb_printf("nargs:");
931*ac448965Sahl 		narg = pb->dofpr_nargv;
932*ac448965Sahl 		for (j = 0; j < pb->dofpr_nargc; j++) {
9331a7c1b72Smws 			mdb_printf("%s %s", "," + (j == 0), strtab + narg);
9341a7c1b72Smws 			narg += strlen(strtab + narg) + 1;
9351a7c1b72Smws 		}
9361a7c1b72Smws 		mdb_printf("\n");
9371a7c1b72Smws 		mdb_printf("xargs:");
938*ac448965Sahl 		xarg = pb->dofpr_xargv;
939*ac448965Sahl 		for (j = 0; j < pb->dofpr_xargc; j++) {
9401a7c1b72Smws 			mdb_printf("%s %s", "," + (j == 0), strtab + xarg);
9411a7c1b72Smws 			xarg += strlen(strtab + xarg) + 1;
9421a7c1b72Smws 		}
9431a7c1b72Smws 		mdb_printf("\n");
9441a7c1b72Smws 		mdb_printf("map:  ");
945*ac448965Sahl 		for (j = 0; j < pb->dofpr_xargc; j++) {
9461a7c1b72Smws 			mdb_printf("%s %d->%d", "," + (j == 0),
947*ac448965Sahl 			    args[pb->dofpr_argidx + j], j);
9481a7c1b72Smws 		}
9491a7c1b72Smws 
9501a7c1b72Smws 		(void) mdb_dec_indent(2);
9511a7c1b72Smws 		mdb_printf("\n}\n");
9521a7c1b72Smws 	}
9531a7c1b72Smws 
9541a7c1b72Smws 	(void) mdb_dec_indent(2);
9551a7c1b72Smws 	mdb_printf("}\n");
9561a7c1b72Smws 
9571a7c1b72Smws 	return (0);
9581a7c1b72Smws }
9591a7c1b72Smws 
9601a7c1b72Smws static int
dof_sect_prargs(uintptr_t addr,dof_sec_t * sec)9611a7c1b72Smws dof_sect_prargs(uintptr_t addr, dof_sec_t *sec)
9621a7c1b72Smws {
9631a7c1b72Smws 	int i;
9641a7c1b72Smws 	uint8_t arg;
9651a7c1b72Smws 
9661a7c1b72Smws 	for (i = 0; i < sec->dofs_size; i++) {
9671a7c1b72Smws 		if (mdb_vread(&arg, sizeof (arg),
9681a7c1b72Smws 		    addr + sec->dofs_offset + i) != sizeof (arg)) {
9691a7c1b72Smws 			mdb_warn("failed to read argument");
9701a7c1b72Smws 			return (1);
9711a7c1b72Smws 		}
9721a7c1b72Smws 
9731a7c1b72Smws 		mdb_printf("%d ", arg);
9741a7c1b72Smws 
9751a7c1b72Smws 		if (i % 20 == 19)
9761a7c1b72Smws 			mdb_printf("\n");
9771a7c1b72Smws 	}
9781a7c1b72Smws 
9791a7c1b72Smws 	mdb_printf("\n");
9801a7c1b72Smws 
9811a7c1b72Smws 	return (0);
9821a7c1b72Smws }
9831a7c1b72Smws 
9841a7c1b72Smws /*ARGSUSED*/
9851a7c1b72Smws static int
dofdump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)9861a7c1b72Smws dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
9871a7c1b72Smws {
9881a7c1b72Smws 	dof_hdr_t dofh;
9891a7c1b72Smws 	dof_sec_t *dofs;
9901a7c1b72Smws 	const char *name;
9911a7c1b72Smws 	int i;
9921a7c1b72Smws 
9931a7c1b72Smws 	if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) {
9941a7c1b72Smws 		mdb_warn("failed to read DOF header");
9951a7c1b72Smws 		return (DCMD_ERR);
9961a7c1b72Smws 	}
9971a7c1b72Smws 
9981a7c1b72Smws 	dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum,
9991a7c1b72Smws 	    UM_SLEEP | UM_GC);
10001a7c1b72Smws 
10011a7c1b72Smws 	for (i = 0; i < dofh.dofh_secnum; i++) {
10021a7c1b72Smws 		if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff +
10031a7c1b72Smws 		    addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) {
10041a7c1b72Smws 			mdb_warn("failed to read DOF sections");
10051a7c1b72Smws 			return (DCMD_ERR);
10061a7c1b72Smws 		}
10071a7c1b72Smws 	}
10081a7c1b72Smws 
10091a7c1b72Smws 	for (i = 0; i < dofh.dofh_secnum; i++) {
10101a7c1b72Smws 		mdb_printf("%lx Section %d: ", (ulong_t)
10111a7c1b72Smws 		    (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i);
10121a7c1b72Smws 
10131a7c1b72Smws 		if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL)
10141a7c1b72Smws 			mdb_printf("%s\n", name);
10151a7c1b72Smws 		else
10161a7c1b72Smws 			mdb_printf("%u\n", dofs[i].dofs_type);
10171a7c1b72Smws 
10181a7c1b72Smws 		(void) mdb_inc_indent(2);
10191a7c1b72Smws 		switch (dofs[i].dofs_type) {
10201a7c1b72Smws 		case DOF_SECT_PROVIDER:
1021*ac448965Sahl 			(void) dof_sect_provider(&dofh, addr, &dofs[i], dofs);
10221a7c1b72Smws 			break;
10231a7c1b72Smws 		case DOF_SECT_STRTAB:
10241a7c1b72Smws 			(void) dof_sect_strtab(addr, &dofs[i]);
10251a7c1b72Smws 			break;
10261a7c1b72Smws 		case DOF_SECT_PRARGS:
10271a7c1b72Smws 			(void) dof_sect_prargs(addr, &dofs[i]);
10281a7c1b72Smws 			break;
10291a7c1b72Smws 		}
10301a7c1b72Smws 		(void) mdb_dec_indent(2);
10311a7c1b72Smws 
10321a7c1b72Smws 		mdb_printf("\n");
10331a7c1b72Smws 	}
10341a7c1b72Smws 
10351a7c1b72Smws 	return (DCMD_OK);
10361a7c1b72Smws }
10371a7c1b72Smws 
10381a7c1b72Smws static const mdb_dcmd_t common_dcmds[] = {
10391a7c1b72Smws 	{ "difinstr", ":", "disassemble a DIF instruction", difinstr },
10401a7c1b72Smws 	{ "difo", ":", "print a DIF object", difo },
10411a7c1b72Smws 	{ "dof_hdr", "?", "print a DOF header", dof_hdr },
10421a7c1b72Smws 	{ "dof_sec", ":", "print a DOF section header", dof_sec },
10431a7c1b72Smws 	{ "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc },
10441a7c1b72Smws 	{ "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc },
10451a7c1b72Smws 	{ "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc },
10461a7c1b72Smws 	{ "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr },
10471a7c1b72Smws 	{ "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc },
10481a7c1b72Smws 	{ "dofdump", ":", "dump DOF", dofdump },
10491a7c1b72Smws 	{ NULL }
10501a7c1b72Smws };
10511a7c1b72Smws 
10521a7c1b72Smws static const mdb_walker_t common_walkers[] = {
10531a7c1b72Smws 	{ "dof_sec", "walk DOF section header table given header address",
10541a7c1b72Smws 		dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini },
10551a7c1b72Smws 	{ NULL }
10561a7c1b72Smws };
10571a7c1b72Smws 
10581a7c1b72Smws static mdb_modinfo_t modinfo = {
10591a7c1b72Smws 	MDB_API_VERSION, NULL, NULL
10601a7c1b72Smws };
10611a7c1b72Smws 
10621a7c1b72Smws const mdb_modinfo_t *
_mdb_init(void)10631a7c1b72Smws _mdb_init(void)
10641a7c1b72Smws {
10651a7c1b72Smws 	uint_t d = 0, kd = 0, w = 0, kw = 0;
10661a7c1b72Smws 	const mdb_walker_t *wp;
10671a7c1b72Smws 	const mdb_dcmd_t *dp;
10681a7c1b72Smws 
10691a7c1b72Smws 	for (dp = common_dcmds; dp->dc_name != NULL; dp++)
10701a7c1b72Smws 		d++; /* count common dcmds */
10711a7c1b72Smws 
10721a7c1b72Smws 	for (wp = common_walkers; wp->walk_name != NULL; wp++)
10731a7c1b72Smws 		w++; /* count common walkers */
10741a7c1b72Smws 
10751a7c1b72Smws #ifdef _KERNEL
10761a7c1b72Smws 	for (dp = kernel_dcmds; dp->dc_name != NULL; dp++)
10771a7c1b72Smws 		kd++; /* count kernel dcmds */
10781a7c1b72Smws 
10791a7c1b72Smws 	for (wp = kernel_walkers; wp->walk_name != NULL; wp++)
10801a7c1b72Smws 		kw++; /* count common walkers */
10811a7c1b72Smws #endif
10821a7c1b72Smws 
10831a7c1b72Smws 	modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP);
10841a7c1b72Smws 	modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP);
10851a7c1b72Smws 
10861a7c1b72Smws 	bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d);
10871a7c1b72Smws 	bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w);
10881a7c1b72Smws 
10891a7c1b72Smws #ifdef _KERNEL
10901a7c1b72Smws 	bcopy(kernel_dcmds, (void *)
10911a7c1b72Smws 	    (modinfo.mi_dcmds + d), sizeof (*dp) * kd);
10921a7c1b72Smws 	bcopy(kernel_walkers, (void *)
10931a7c1b72Smws 	    (modinfo.mi_walkers + w), sizeof (*wp) * kw);
10941a7c1b72Smws #endif
10951a7c1b72Smws 	return (&modinfo);
10961a7c1b72Smws }
10971a7c1b72Smws 
10981a7c1b72Smws void
_mdb_fini(void)10991a7c1b72Smws _mdb_fini(void)
11001a7c1b72Smws {
11011a7c1b72Smws 	const mdb_walker_t *wp;
11021a7c1b72Smws 	const mdb_dcmd_t *dp;
11031a7c1b72Smws 	uint_t d = 0, w = 0;
11041a7c1b72Smws 
11051a7c1b72Smws 	for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++)
11061a7c1b72Smws 		d++;
11071a7c1b72Smws 
11081a7c1b72Smws 	for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++)
11091a7c1b72Smws 		w++;
11101a7c1b72Smws 
11111a7c1b72Smws 	mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1));
11121a7c1b72Smws 	mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1));
11131a7c1b72Smws }
1114