xref: /onnv-gate/usr/src/cmd/mdb/common/modules/dtrace/dof.c (revision 1710:2710bf829bf1)
1265Smws /*
2265Smws  * CDDL HEADER START
3265Smws  *
4265Smws  * The contents of this file are subject to the terms of the
5*1710Sahl  * Common Development and Distribution License (the "License").
6*1710Sahl  * You may not use this file except in compliance with the License.
7265Smws  *
8265Smws  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9265Smws  * or http://www.opensolaris.org/os/licensing.
10265Smws  * See the License for the specific language governing permissions
11265Smws  * and limitations under the License.
12265Smws  *
13265Smws  * When distributing Covered Code, include this CDDL HEADER in each
14265Smws  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15265Smws  * If applicable, add the following below this CDDL HEADER, with the
16265Smws  * fields enclosed by brackets "[]" replaced with your own identifying
17265Smws  * information: Portions Copyright [yyyy] [name of copyright owner]
18265Smws  *
19265Smws  * CDDL HEADER END
20265Smws  */
21*1710Sahl 
22265Smws /*
23*1710Sahl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24265Smws  * Use is subject to license terms.
25265Smws  */
26265Smws 
27265Smws #pragma ident	"%Z%%M%	%I%	%E% SMI"
28265Smws 
29265Smws #include <mdb/mdb_modapi.h>
30265Smws #include <dtrace.h>
31265Smws 
32265Smws extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
33265Smws extern const char *dof_sec_name(uint32_t);
34265Smws 
35265Smws extern const mdb_walker_t kernel_walkers[];
36265Smws extern const mdb_dcmd_t kernel_dcmds[];
37265Smws 
38265Smws /*ARGSUSED*/
39265Smws static void
dis_log(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)40265Smws dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
41265Smws {
42265Smws 	mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name,
43265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
44265Smws }
45265Smws 
46265Smws /*ARGSUSED*/
47265Smws static void
dis_branch(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)48265Smws dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
49265Smws {
50265Smws 	mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr));
51265Smws }
52265Smws 
53265Smws /*ARGSUSED*/
54265Smws static void
dis_load(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)55265Smws dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
56265Smws {
57265Smws 	mdb_printf("%-4s [%%r%u], %%r%u", name,
58265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
59265Smws }
60265Smws 
61265Smws /*ARGSUSED*/
62265Smws static void
dis_store(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)63265Smws dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
64265Smws {
65265Smws 	mdb_printf("%-4s %%r%u, [%%r%u]", name,
66265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
67265Smws }
68265Smws 
69265Smws /*ARGSUSED*/
70265Smws static void
dis_str(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)71265Smws dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
72265Smws {
73265Smws 	mdb_printf("%s", name);
74265Smws }
75265Smws 
76265Smws /*ARGSUSED*/
77265Smws static void
dis_r1rd(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)78265Smws dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
79265Smws {
80265Smws 	mdb_printf("%-4s %%r%u, %%r%u", name,
81265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
82265Smws }
83265Smws 
84265Smws /*ARGSUSED*/
85265Smws static void
dis_cmp(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)86265Smws dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
87265Smws {
88265Smws 	mdb_printf("%-4s %%r%u, %%r%u", name,
89265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_R2(instr));
90265Smws }
91265Smws 
92265Smws /*ARGSUSED*/
93265Smws static void
dis_tst(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)94265Smws dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
95265Smws {
96265Smws 	mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr));
97265Smws }
98265Smws 
99265Smws static const char *
dis_varname(const dtrace_difo_t * dp,uint_t id,uint_t scope)100265Smws dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope)
101265Smws {
102265Smws 	dtrace_difv_t *dvp;
103265Smws 	size_t varsize;
104265Smws 	caddr_t addr = NULL, str;
105265Smws 	uint_t i;
106265Smws 
107265Smws 	if (dp == NULL)
108265Smws 		return (NULL);
109265Smws 
110265Smws 	varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
111265Smws 	dvp = mdb_alloc(varsize, UM_SLEEP);
112265Smws 
113265Smws 	if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
114265Smws 		mdb_free(dvp, varsize);
115265Smws 		return ("<unreadable>");
116265Smws 	}
117265Smws 
118265Smws 	for (i = 0; i < dp->dtdo_varlen; i++) {
119265Smws 		if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) {
120265Smws 			if (dvp[i].dtdv_name < dp->dtdo_strlen)
121265Smws 				addr = dp->dtdo_strtab + dvp[i].dtdv_name;
122265Smws 			break;
123265Smws 		}
124265Smws 	}
125265Smws 
126265Smws 	mdb_free(dvp, varsize);
127265Smws 
128265Smws 	if (addr == NULL)
129265Smws 		return (NULL);
130265Smws 
131265Smws 	str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC);
132265Smws 
133265Smws 	for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) {
134265Smws 		if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1)
135265Smws 			return ("<unreadable>");
136265Smws 	}
137265Smws 
138265Smws 	return (str);
139265Smws }
140265Smws 
141265Smws static uint_t
dis_scope(const char * name)142265Smws dis_scope(const char *name)
143265Smws {
144265Smws 	switch (name[2]) {
145265Smws 	case 'l': return (DIFV_SCOPE_LOCAL);
146265Smws 	case 't': return (DIFV_SCOPE_THREAD);
147265Smws 	case 'g': return (DIFV_SCOPE_GLOBAL);
148265Smws 	default: return (-1u);
149265Smws 	}
150265Smws }
151265Smws 
152265Smws static void
dis_lda(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)153265Smws dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
154265Smws {
155265Smws 	uint_t var = DIF_INSTR_R1(instr);
156265Smws 	const char *vname;
157265Smws 
158265Smws 	mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name,
159265Smws 	    var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
160265Smws 
161265Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
162265Smws 		mdb_printf("\t\t! %s", vname);
163265Smws }
164265Smws 
165265Smws static void
dis_ldv(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)166265Smws dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
167265Smws {
168265Smws 	uint_t var = DIF_INSTR_VAR(instr);
169265Smws 	const char *vname;
170265Smws 
171265Smws 	mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr));
172265Smws 
173265Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
174265Smws 		mdb_printf("\t\t! %s", vname);
175265Smws }
176265Smws 
177265Smws static void
dis_stv(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)178265Smws dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
179265Smws {
180265Smws 	uint_t var = DIF_INSTR_VAR(instr);
181265Smws 	const char *vname;
182265Smws 
183265Smws 	mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var);
184265Smws 
185265Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
186265Smws 		mdb_printf("\t\t! %s", vname);
187265Smws }
188265Smws 
189265Smws static void
dis_setx(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)190265Smws dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
191265Smws {
192265Smws 	uint_t intptr = DIF_INSTR_INTEGER(instr);
193265Smws 
194265Smws 	mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name,
195265Smws 	    intptr, DIF_INSTR_RD(instr));
196265Smws 
197265Smws 	if (dp != NULL && intptr < dp->dtdo_intlen) {
198265Smws 		uint64_t *ip = mdb_alloc(dp->dtdo_intlen *
199265Smws 		    sizeof (uint64_t), UM_SLEEP | UM_GC);
200265Smws 
201265Smws 		if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t),
202265Smws 		    (uintptr_t)dp->dtdo_inttab) == -1)
203265Smws 			mdb_warn("failed to read data at %p", dp->dtdo_inttab);
204265Smws 		else
205265Smws 			mdb_printf("\t\t! 0x%llx", ip[intptr]);
206265Smws 	}
207265Smws }
208265Smws 
209265Smws static void
dis_sets(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)210265Smws dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
211265Smws {
212265Smws 	uint_t strptr = DIF_INSTR_STRING(instr);
213265Smws 
214265Smws 	mdb_printf("%-4s DIF_STRING[%u], %%r%u", name,
215265Smws 	    strptr, DIF_INSTR_RD(instr));
216265Smws 
217265Smws 	if (dp != NULL && strptr < dp->dtdo_strlen) {
218265Smws 		char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
219265Smws 
220265Smws 		if (mdb_vread(str, dp->dtdo_strlen,
221265Smws 		    (uintptr_t)dp->dtdo_strtab) == -1)
222265Smws 			mdb_warn("failed to read data at %p", dp->dtdo_strtab);
223265Smws 		else
224265Smws 			mdb_printf("\t\t! \"%s\"", str + strptr);
225265Smws 	}
226265Smws }
227265Smws 
228265Smws /*ARGSUSED*/
229265Smws static void
dis_ret(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)230265Smws dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
231265Smws {
232265Smws 	mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr));
233265Smws }
234265Smws 
235265Smws /*ARGSUSED*/
236265Smws static void
dis_call(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)237265Smws dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
238265Smws {
239265Smws 	uint_t subr = DIF_INSTR_SUBR(instr);
240265Smws 
241265Smws 	mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s",
242265Smws 	    name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr));
243265Smws }
244265Smws 
245265Smws /*ARGSUSED*/
246265Smws static void
dis_pushts(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)247265Smws dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
248265Smws {
249265Smws 	static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" };
250265Smws 	uint_t type = DIF_INSTR_TYPE(instr);
251265Smws 
252265Smws 	mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u",
253265Smws 	    name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr));
254265Smws 
255265Smws 	if (type < sizeof (tnames) / sizeof (tnames[0]))
256491Sbmc 		mdb_printf("\t\t! %s", tnames[type]);
257265Smws }
258265Smws 
259265Smws /*ARGSUSED*/
260265Smws static void
dis_xlate(const dtrace_difo_t * dp,const char * name,dif_instr_t instr)261265Smws dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
262265Smws {
263265Smws 	mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name,
264265Smws 	    DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr));
265265Smws }
266265Smws 
267265Smws static char *
dis_typestr(const dtrace_diftype_t * t,char * buf,size_t len)268265Smws dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
269265Smws {
270265Smws 	char kind[8];
271265Smws 
272265Smws 	switch (t->dtdt_kind) {
273265Smws 	case DIF_TYPE_CTF:
274265Smws 		(void) strcpy(kind, "D type");
275265Smws 		break;
276265Smws 	case DIF_TYPE_STRING:
277265Smws 		(void) strcpy(kind, "string");
278265Smws 		break;
279265Smws 	default:
280265Smws 		(void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind);
281265Smws 	}
282265Smws 
283265Smws 	if (t->dtdt_flags & DIF_TF_BYREF) {
284265Smws 		(void) mdb_snprintf(buf, len,
285265Smws 		    "%s by ref (size %lu)",
286265Smws 		    kind, (ulong_t)t->dtdt_size);
287265Smws 	} else {
288265Smws 		(void) mdb_snprintf(buf, len, "%s (size %lu)",
289265Smws 		    kind, (ulong_t)t->dtdt_size);
290265Smws 	}
291265Smws 
292265Smws 	return (buf);
293265Smws }
294265Smws 
295265Smws static int
dis(uintptr_t addr,dtrace_difo_t * dp)296265Smws dis(uintptr_t addr, dtrace_difo_t *dp)
297265Smws {
298265Smws 	static const struct opent {
299265Smws 		const char *op_name;
300265Smws 		void (*op_func)(const dtrace_difo_t *,
301265Smws 		    const char *, dif_instr_t);
302265Smws 	} optab[] = {
303265Smws 		{ "(illegal opcode)", dis_str },
304265Smws 		{ "or", dis_log },		/* DIF_OP_OR */
305265Smws 		{ "xor", dis_log },		/* DIF_OP_XOR */
306265Smws 		{ "and", dis_log },		/* DIF_OP_AND */
307265Smws 		{ "sll", dis_log },		/* DIF_OP_SLL */
308265Smws 		{ "srl", dis_log },		/* DIF_OP_SRL */
309265Smws 		{ "sub", dis_log },		/* DIF_OP_SUB */
310265Smws 		{ "add", dis_log },		/* DIF_OP_ADD */
311265Smws 		{ "mul", dis_log },		/* DIF_OP_MUL */
312265Smws 		{ "sdiv", dis_log },		/* DIF_OP_SDIV */
313265Smws 		{ "udiv", dis_log },		/* DIF_OP_UDIV */
314265Smws 		{ "srem", dis_log },		/* DIF_OP_SREM */
315265Smws 		{ "urem", dis_log },		/* DIF_OP_UREM */
316265Smws 		{ "not", dis_r1rd },		/* DIF_OP_NOT */
317265Smws 		{ "mov", dis_r1rd },		/* DIF_OP_MOV */
318265Smws 		{ "cmp", dis_cmp },		/* DIF_OP_CMP */
319265Smws 		{ "tst", dis_tst },		/* DIF_OP_TST */
320265Smws 		{ "ba", dis_branch },		/* DIF_OP_BA */
321265Smws 		{ "be", dis_branch },		/* DIF_OP_BE */
322265Smws 		{ "bne", dis_branch },		/* DIF_OP_BNE */
323265Smws 		{ "bg", dis_branch },		/* DIF_OP_BG */
324265Smws 		{ "bgu", dis_branch },		/* DIF_OP_BGU */
325265Smws 		{ "bge", dis_branch },		/* DIF_OP_BGE */
326265Smws 		{ "bgeu", dis_branch },		/* DIF_OP_BGEU */
327265Smws 		{ "bl", dis_branch },		/* DIF_OP_BL */
328265Smws 		{ "blu", dis_branch },		/* DIF_OP_BLU */
329265Smws 		{ "ble", dis_branch },		/* DIF_OP_BLE */
330265Smws 		{ "bleu", dis_branch },		/* DIF_OP_BLEU */
331265Smws 		{ "ldsb", dis_load },		/* DIF_OP_LDSB */
332265Smws 		{ "ldsh", dis_load },		/* DIF_OP_LDSH */
333265Smws 		{ "ldsw", dis_load },		/* DIF_OP_LDSW */
334265Smws 		{ "ldub", dis_load },		/* DIF_OP_LDUB */
335265Smws 		{ "lduh", dis_load },		/* DIF_OP_LDUH */
336265Smws 		{ "lduw", dis_load },		/* DIF_OP_LDUW */
337265Smws 		{ "ldx", dis_load },		/* DIF_OP_LDX */
338265Smws 		{ "ret", dis_ret },		/* DIF_OP_RET */
339265Smws 		{ "nop", dis_str },		/* DIF_OP_NOP */
340265Smws 		{ "setx", dis_setx },		/* DIF_OP_SETX */
341265Smws 		{ "sets", dis_sets },		/* DIF_OP_SETS */
342265Smws 		{ "scmp", dis_cmp },		/* DIF_OP_SCMP */
343265Smws 		{ "ldga", dis_lda },		/* DIF_OP_LDGA */
344265Smws 		{ "ldgs", dis_ldv },		/* DIF_OP_LDGS */
345265Smws 		{ "stgs", dis_stv },		/* DIF_OP_STGS */
346265Smws 		{ "ldta", dis_lda },		/* DIF_OP_LDTA */
347265Smws 		{ "ldts", dis_ldv },		/* DIF_OP_LDTS */
348265Smws 		{ "stts", dis_stv },		/* DIF_OP_STTS */
349265Smws 		{ "sra", dis_log },		/* DIF_OP_SRA */
350265Smws 		{ "call", dis_call },		/* DIF_OP_CALL */
351265Smws 		{ "pushtr", dis_pushts },	/* DIF_OP_PUSHTR */
352265Smws 		{ "pushtv", dis_pushts },	/* DIF_OP_PUSHTV */
353265Smws 		{ "popts", dis_str },		/* DIF_OP_POPTS */
354265Smws 		{ "flushts", dis_str },		/* DIF_OP_FLUSHTS */
355265Smws 		{ "ldgaa", dis_ldv },		/* DIF_OP_LDGAA */
356265Smws 		{ "ldtaa", dis_ldv },		/* DIF_OP_LDTAA */
357265Smws 		{ "stgaa", dis_stv },		/* DIF_OP_STGAA */
358265Smws 		{ "sttaa", dis_stv },		/* DIF_OP_STTAA */
359265Smws 		{ "ldls", dis_ldv },		/* DIF_OP_LDLS */
360265Smws 		{ "stls", dis_stv },		/* DIF_OP_STLS */
361265Smws 		{ "allocs", dis_r1rd },		/* DIF_OP_ALLOCS */
362265Smws 		{ "copys", dis_log },		/* DIF_OP_COPYS */
363265Smws 		{ "stb", dis_store },		/* DIF_OP_STB */
364265Smws 		{ "sth", dis_store },		/* DIF_OP_STH */
365265Smws 		{ "stw", dis_store },		/* DIF_OP_STW */
366265Smws 		{ "stx", dis_store },		/* DIF_OP_STX */
367265Smws 		{ "uldsb", dis_load },		/* DIF_OP_ULDSB */
368265Smws 		{ "uldsh", dis_load },		/* DIF_OP_ULDSH */
369265Smws 		{ "uldsw", dis_load },		/* DIF_OP_ULDSW */
370265Smws 		{ "uldub", dis_load },		/* DIF_OP_ULDUB */
371265Smws 		{ "ulduh", dis_load },		/* DIF_OP_ULDUH */
372265Smws 		{ "ulduw", dis_load },		/* DIF_OP_ULDUW */
373265Smws 		{ "uldx", dis_load },		/* DIF_OP_ULDX */
374265Smws 		{ "rldsb", dis_load },		/* DIF_OP_RLDSB */
375265Smws 		{ "rldsh", dis_load },		/* DIF_OP_RLDSH */
376265Smws 		{ "rldsw", dis_load },		/* DIF_OP_RLDSW */
377265Smws 		{ "rldub", dis_load },		/* DIF_OP_RLDUB */
378265Smws 		{ "rlduh", dis_load },		/* DIF_OP_RLDUH */
379265Smws 		{ "rlduw", dis_load },		/* DIF_OP_RLDUW */
380265Smws 		{ "rldx", dis_load },		/* DIF_OP_RLDX */
381265Smws 		{ "xlate", dis_xlate },		/* DIF_OP_XLATE */
382265Smws 		{ "xlarg", dis_xlate },		/* DIF_OP_XLARG */
383265Smws 	};
384265Smws 
385265Smws 	dif_instr_t instr, opcode;
386265Smws 	const struct opent *op;
387265Smws 
388265Smws 	if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) {
389265Smws 		mdb_warn("failed to read DIF instruction at %p", addr);
390265Smws 		return (DCMD_ERR);
391265Smws 	}
392265Smws 
393265Smws 	opcode = DIF_INSTR_OP(instr);
394265Smws 
395265Smws 	if (opcode >= sizeof (optab) / sizeof (optab[0]))
396265Smws 		opcode = 0; /* force invalid opcode message */
397265Smws 
398265Smws 	op = &optab[opcode];
399491Sbmc 	mdb_printf("%0?p %08x ", addr, instr);
400265Smws 	op->op_func(dp, op->op_name, instr);
401265Smws 	mdb_printf("\n");
402265Smws 	mdb_set_dot(addr + sizeof (dif_instr_t));
403265Smws 
404265Smws 	return (DCMD_OK);
405265Smws }
406265Smws 
407265Smws /*ARGSUSED*/
408265Smws int
difo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)409265Smws difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
410265Smws {
411265Smws 	dtrace_difo_t difo, *dp = &difo;
412265Smws 	uintptr_t instr, limit;
413265Smws 	dtrace_difv_t *dvp;
414265Smws 	size_t varsize;
415265Smws 	ulong_t i;
416265Smws 	char type[64];
417265Smws 	char *str;
418265Smws 
419265Smws 	if (!(flags & DCMD_ADDRSPEC))
420265Smws 		return (DCMD_USAGE);
421265Smws 
422265Smws 	if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) {
423265Smws 		mdb_warn("couldn't read dtrace_difo_t at %p", addr);
424265Smws 		return (DCMD_ERR);
425265Smws 	}
426265Smws 
427265Smws 	mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
428265Smws 	    addr, dp->dtdo_refcnt);
429491Sbmc 	mdb_printf("%<b>%-?s %-8s %s%</b>\n", "ADDR", "OPCODE", "INSTRUCTION");
430265Smws 
431265Smws 	mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf);
432265Smws 	limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t);
433265Smws 
434265Smws 	while ((instr = mdb_get_dot()) < limit)
435265Smws 		dis(instr, dp);
436265Smws 
437265Smws 	if (dp->dtdo_varlen != 0) {
438265Smws 		mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n",
439265Smws 		    "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
440265Smws 	}
441265Smws 
442265Smws 	varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
443265Smws 	dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC);
444265Smws 
445265Smws 	if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
446265Smws 		mdb_warn("couldn't read dtdo_vartab");
447265Smws 		return (DCMD_ERR);
448265Smws 	}
449265Smws 
450265Smws 	str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
451265Smws 
452265Smws 	if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) {
453265Smws 		mdb_warn("couldn't read dtdo_strtab");
454265Smws 		return (DCMD_ERR);
455265Smws 	}
456265Smws 
457265Smws 	for (i = 0; i < dp->dtdo_varlen; i++) {
458265Smws 		dtrace_difv_t *v = &dvp[i];
459265Smws 		char kind[4], scope[4], flags[16] = { 0 };
460265Smws 
461265Smws 		switch (v->dtdv_kind) {
462265Smws 		case DIFV_KIND_ARRAY:
463265Smws 			(void) strcpy(kind, "arr");
464265Smws 			break;
465265Smws 		case DIFV_KIND_SCALAR:
466265Smws 			(void) strcpy(kind, "scl");
467265Smws 			break;
468265Smws 		default:
469265Smws 			(void) mdb_snprintf(kind, sizeof (kind),
470265Smws 			    "%u", v->dtdv_kind);
471265Smws 		}
472265Smws 
473265Smws 		switch (v->dtdv_scope) {
474265Smws 		case DIFV_SCOPE_GLOBAL:
475265Smws 			(void) strcpy(scope, "glb");
476265Smws 			break;
477265Smws 		case DIFV_SCOPE_THREAD:
478265Smws 			(void) strcpy(scope, "tls");
479265Smws 			break;
480265Smws 		case DIFV_SCOPE_LOCAL:
481265Smws 			(void) strcpy(scope, "loc");
482265Smws 			break;
483265Smws 		default:
484265Smws 			(void) mdb_snprintf(scope, sizeof (scope),
485265Smws 			    "%u", v->dtdv_scope);
486265Smws 		}
487265Smws 
488265Smws 		if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
489265Smws 			(void) mdb_snprintf(flags, sizeof (flags), "/0x%x",
490265Smws 			    v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
491265Smws 		}
492265Smws 
493265Smws 		if (v->dtdv_flags & DIFV_F_REF)
494265Smws 			(void) strcat(flags, "/r");
495265Smws 		if (v->dtdv_flags & DIFV_F_MOD)
496265Smws 			(void) strcat(flags, "/w");
497265Smws 
498265Smws 		mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n",
499265Smws 		    &str[v->dtdv_name],
500265Smws 		    v->dtdv_id, kind, scope, flags + 1,
501265Smws 		    dis_typestr(&v->dtdv_type, type, sizeof (type)));
502265Smws 	}
503265Smws 
504265Smws 	mdb_printf("\n%<b>RETURN%</b>\n%s\n\n",
505265Smws 	    dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
506265Smws 
507265Smws 	return (DCMD_OK);
508265Smws }
509265Smws 
510265Smws /*ARGSUSED*/
511265Smws int
difinstr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)512265Smws difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
513265Smws {
514265Smws 	if (!(flags & DCMD_ADDRSPEC))
515265Smws 		return (DCMD_USAGE);
516265Smws 
517265Smws 	return (dis(addr, NULL));
518265Smws }
519265Smws 
520265Smws /*ARGSUSED*/
521265Smws int
dof_hdr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)522265Smws dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
523265Smws {
524265Smws 	dof_hdr_t h;
525265Smws 
526265Smws 	if (argc != 0)
527265Smws 		return (DCMD_USAGE);
528265Smws 
529265Smws 	if (!(flags & DCMD_ADDRSPEC))
530265Smws 		addr = 0; /* assume base of file in file target */
531265Smws 
532265Smws 	if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) {
533265Smws 		mdb_warn("failed to read header at %p", addr);
534265Smws 		return (DCMD_ERR);
535265Smws 	}
536265Smws 
537265Smws 	mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n",
538265Smws 	    h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1],
539265Smws 	    h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]);
540265Smws 
541265Smws 	switch (h.dofh_ident[DOF_ID_MODEL]) {
542265Smws 	case DOF_MODEL_ILP32:
543265Smws 		mdb_printf("dofh_ident.id_model = ILP32\n");
544265Smws 		break;
545265Smws 	case DOF_MODEL_LP64:
546265Smws 		mdb_printf("dofh_ident.id_model = LP64\n");
547265Smws 		break;
548265Smws 	default:
549265Smws 		mdb_printf("dofh_ident.id_model = 0x%x\n",
550265Smws 		    h.dofh_ident[DOF_ID_MODEL]);
551265Smws 	}
552265Smws 
553265Smws 	switch (h.dofh_ident[DOF_ID_ENCODING]) {
554265Smws 	case DOF_ENCODE_LSB:
555265Smws 		mdb_printf("dofh_ident.id_encoding = LSB\n");
556265Smws 		break;
557265Smws 	case DOF_ENCODE_MSB:
558265Smws 		mdb_printf("dofh_ident.id_encoding = MSB\n");
559265Smws 		break;
560265Smws 	default:
561265Smws 		mdb_printf("dofh_ident.id_encoding = 0x%x\n",
562265Smws 		    h.dofh_ident[DOF_ID_ENCODING]);
563265Smws 	}
564265Smws 
565265Smws 	mdb_printf("dofh_ident.id_version = %u\n",
566265Smws 	    h.dofh_ident[DOF_ID_VERSION]);
567265Smws 	mdb_printf("dofh_ident.id_difvers = %u\n",
568265Smws 	    h.dofh_ident[DOF_ID_DIFVERS]);
569265Smws 	mdb_printf("dofh_ident.id_difireg = %u\n",
570265Smws 	    h.dofh_ident[DOF_ID_DIFIREG]);
571265Smws 	mdb_printf("dofh_ident.id_diftreg = %u\n",
572265Smws 	    h.dofh_ident[DOF_ID_DIFTREG]);
573265Smws 
574265Smws 	mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags);
575265Smws 	mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize);
576265Smws 	mdb_printf("dofh_secsize = %u\n", h.dofh_secsize);
577265Smws 	mdb_printf("dofh_secnum = %u\n", h.dofh_secnum);
578265Smws 	mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff);
579265Smws 	mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz);
580265Smws 	mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz);
581265Smws 
582265Smws 	return (DCMD_OK);
583265Smws }
584265Smws 
585265Smws /*ARGSUSED*/
586265Smws static int
dof_sec_walk(uintptr_t addr,void * ignored,int * sec)587265Smws dof_sec_walk(uintptr_t addr, void *ignored, int *sec)
588265Smws {
589265Smws 	mdb_printf("%3d ", (*sec)++);
590265Smws 	(void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL);
591265Smws 	return (WALK_NEXT);
592265Smws }
593265Smws 
594265Smws /*ARGSUSED*/
595265Smws int
dof_sec(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)596265Smws dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
597265Smws {
598265Smws 	const char *name;
599265Smws 	dof_sec_t s;
600265Smws 
601265Smws 	if (!(flags & DCMD_ADDRSPEC))
602265Smws 		mdb_printf("%<u>%-3s ", "NDX");
603265Smws 
604265Smws 	if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) {
605265Smws 		mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
606265Smws 		    "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET",
607265Smws 		    "SIZE");
608265Smws 	}
609265Smws 
610265Smws 	if (!(flags & DCMD_ADDRSPEC)) {
611265Smws 		int sec = 0;
612265Smws 
613265Smws 		if (mdb_walk("dof_sec",
614265Smws 		    (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) {
615265Smws 			mdb_warn("failed to walk dof_sec");
616265Smws 			return (DCMD_ERR);
617265Smws 		}
618265Smws 		return (DCMD_OK);
619265Smws 	}
620265Smws 
621265Smws 	if (argc != 0)
622265Smws 		return (DCMD_USAGE);
623265Smws 
624265Smws 	if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
625265Smws 		mdb_warn("failed to read section header at %p", addr);
626265Smws 		return (DCMD_ERR);
627265Smws 	}
628265Smws 
629265Smws 	mdb_printf("%?p ", addr);
630265Smws 
631265Smws 	if ((name = dof_sec_name(s.dofs_type)) != NULL)
632265Smws 		mdb_printf("%-10s ", name);
633265Smws 	else
634265Smws 		mdb_printf("%-10u ", s.dofs_type);
635265Smws 
636265Smws 	mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align,
637265Smws 	    s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size);
638265Smws 
639265Smws 	return (DCMD_OK);
640265Smws }
641265Smws 
642265Smws int
dof_sec_walk_init(mdb_walk_state_t * wsp)643265Smws dof_sec_walk_init(mdb_walk_state_t *wsp)
644265Smws {
645265Smws 	dof_hdr_t h, *hp;
646265Smws 	size_t size;
647265Smws 
648265Smws 	if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) {
649265Smws 		mdb_warn("failed to read DOF header at %p", wsp->walk_addr);
650265Smws 		return (WALK_ERR);
651265Smws 	}
652265Smws 
653265Smws 	size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum;
654265Smws 	hp = mdb_alloc(size, UM_SLEEP);
655265Smws 
656265Smws 	if (mdb_vread(hp, size, wsp->walk_addr) != size) {
657265Smws 		mdb_warn("failed to read DOF sections at %p", wsp->walk_addr);
658265Smws 		mdb_free(hp, size);
659265Smws 		return (WALK_ERR);
660265Smws 	}
661265Smws 
662265Smws 	wsp->walk_arg = (void *)0;
663265Smws 	wsp->walk_data = hp;
664265Smws 
665265Smws 	return (WALK_NEXT);
666265Smws }
667265Smws 
668265Smws int
dof_sec_walk_step(mdb_walk_state_t * wsp)669265Smws dof_sec_walk_step(mdb_walk_state_t *wsp)
670265Smws {
671265Smws 	uint_t i = (uintptr_t)wsp->walk_arg;
672265Smws 	size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i;
673265Smws 	dof_hdr_t *hp = wsp->walk_data;
674265Smws 	dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off);
675265Smws 
676265Smws 	if (i >= hp->dofh_secnum)
677265Smws 		return (WALK_DONE);
678265Smws 
679265Smws 	wsp->walk_arg = (void *)(uintptr_t)(i + 1);
680265Smws 	return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata));
681265Smws }
682265Smws 
683265Smws void
dof_sec_walk_fini(mdb_walk_state_t * wsp)684265Smws dof_sec_walk_fini(mdb_walk_state_t *wsp)
685265Smws {
686265Smws 	dof_hdr_t *hp = wsp->walk_data;
687265Smws 	mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum);
688265Smws }
689265Smws 
690265Smws /*ARGSUSED*/
691265Smws int
dof_ecbdesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)692265Smws dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
693265Smws {
694265Smws 	dof_ecbdesc_t e;
695265Smws 
696265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
697265Smws 		return (DCMD_USAGE);
698265Smws 
699265Smws 	if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) {
700265Smws 		mdb_warn("failed to read ecbdesc at %p", addr);
701265Smws 		return (DCMD_ERR);
702265Smws 	}
703265Smws 
704265Smws 	mdb_printf("dofe_probes = %d\n", e.dofe_probes);
705265Smws 	mdb_printf("dofe_actions = %d\n", e.dofe_actions);
706265Smws 	mdb_printf("dofe_pred = %d\n", e.dofe_pred);
707265Smws 	mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg);
708265Smws 
709265Smws 	return (DCMD_OK);
710265Smws }
711265Smws 
712265Smws /*ARGSUSED*/
713265Smws int
dof_probedesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)714265Smws dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
715265Smws {
716265Smws 	dof_probedesc_t p;
717265Smws 
718265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
719265Smws 		return (DCMD_USAGE);
720265Smws 
721265Smws 	if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) {
722265Smws 		mdb_warn("failed to read probedesc at %p", addr);
723265Smws 		return (DCMD_ERR);
724265Smws 	}
725265Smws 
726265Smws 	mdb_printf("dofp_strtab = %d\n", p.dofp_strtab);
727265Smws 	mdb_printf("dofp_provider = %u\n", p.dofp_provider);
728265Smws 	mdb_printf("dofp_mod = %u\n", p.dofp_mod);
729265Smws 	mdb_printf("dofp_func = %u\n", p.dofp_func);
730265Smws 	mdb_printf("dofp_name = %u\n", p.dofp_name);
731265Smws 	mdb_printf("dofp_id = %u\n", p.dofp_id);
732265Smws 
733265Smws 	return (DCMD_OK);
734265Smws }
735265Smws 
736265Smws /*ARGSUSED*/
737265Smws int
dof_actdesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)738265Smws dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
739265Smws {
740265Smws 	dof_actdesc_t a;
741265Smws 
742265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
743265Smws 		return (DCMD_USAGE);
744265Smws 
745265Smws 	if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
746265Smws 		mdb_warn("failed to read actdesc at %p", addr);
747265Smws 		return (DCMD_ERR);
748265Smws 	}
749265Smws 
750265Smws 	mdb_printf("dofa_difo = %d\n", a.dofa_difo);
751265Smws 	mdb_printf("dofa_strtab = %d\n", a.dofa_strtab);
752265Smws 	mdb_printf("dofa_kind = %u\n", a.dofa_kind);
753265Smws 	mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple);
754265Smws 	mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg);
755265Smws 	mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg);
756265Smws 
757265Smws 	return (DCMD_OK);
758265Smws }
759265Smws 
760265Smws /*ARGSUSED*/
761265Smws int
dof_relohdr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)762265Smws dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
763265Smws {
764265Smws 	dof_relohdr_t r;
765265Smws 
766265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
767265Smws 		return (DCMD_USAGE);
768265Smws 
769265Smws 	if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
770265Smws 		mdb_warn("failed to read relohdr at %p", addr);
771265Smws 		return (DCMD_ERR);
772265Smws 	}
773265Smws 
774265Smws 	mdb_printf("dofr_strtab = %d\n", r.dofr_strtab);
775265Smws 	mdb_printf("dofr_relsec = %d\n", r.dofr_relsec);
776265Smws 	mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec);
777265Smws 
778265Smws 	return (DCMD_OK);
779265Smws }
780265Smws 
781265Smws /*ARGSUSED*/
782265Smws int
dof_relodesc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)783265Smws dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
784265Smws {
785265Smws 	dof_relodesc_t r;
786265Smws 
787265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
788265Smws 		return (DCMD_USAGE);
789265Smws 
790265Smws 	if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
791265Smws 		mdb_warn("failed to read relodesc at %p", addr);
792265Smws 		return (DCMD_ERR);
793265Smws 	}
794265Smws 
795265Smws 	mdb_printf("dofr_name = %u\n", r.dofr_name);
796265Smws 	mdb_printf("dofr_type = %u\n", r.dofr_type);
797265Smws 	mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset);
798265Smws 	mdb_printf("dofr_data = 0x%llx\n", r.dofr_data);
799265Smws 
800265Smws 	return (DCMD_OK);
801265Smws }
802265Smws 
803265Smws static int
dof_sect_strtab(uintptr_t addr,dof_sec_t * sec)804265Smws dof_sect_strtab(uintptr_t addr, dof_sec_t *sec)
805265Smws {
806265Smws 	char *strtab;
807265Smws 	size_t sz, i;
808265Smws 
809265Smws 	sz = (size_t)sec->dofs_size;
810265Smws 	strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
811265Smws 	if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) {
812265Smws 		mdb_warn("failed to read string table");
813265Smws 		return (1);
814265Smws 	}
815265Smws 
816265Smws 	mdb_printf("size = %lx\n", sz);
817265Smws 
818265Smws 	for (i = 0; i < sz; i++) {
819265Smws 		if (strtab[i] == '\0')
820265Smws 			mdb_printf("\\0");
821265Smws 		else
822265Smws 			mdb_printf("%c", strtab[i]);
823265Smws 	}
824265Smws 
825265Smws 	mdb_printf("\n");
826265Smws 
827265Smws 	return (0);
828265Smws }
829265Smws 
830265Smws static int
dof_sect_provider(dof_hdr_t * dofh,uintptr_t addr,dof_sec_t * sec,dof_sec_t * dofs)831*1710Sahl dof_sect_provider(dof_hdr_t *dofh, uintptr_t addr, dof_sec_t *sec,
832*1710Sahl     dof_sec_t *dofs)
833265Smws {
834265Smws 	dof_provider_t pv;
835265Smws 	dof_probe_t *pb;
836*1710Sahl 	char *strtab, *p;
837*1710Sahl 	uint32_t *offs, *enoffs;
838265Smws 	uint8_t *args = NULL;
839265Smws 	size_t sz;
840265Smws 	int i, j;
841265Smws 	dof_stridx_t narg, xarg;
842265Smws 
843*1710Sahl 	sz = MIN(sec->dofs_size, sizeof (dof_provider_t));
844*1710Sahl 	if (mdb_vread(&pv, sz, addr + sec->dofs_offset) != sz) {
845265Smws 		mdb_warn("failed to read DOF provider");
846265Smws 		return (-1);
847265Smws 	}
848265Smws 
849265Smws 	sz = dofs[pv.dofpv_strtab].dofs_size;
850265Smws 	strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
851265Smws 	if (mdb_vread(strtab, sz, addr +
852265Smws 	    dofs[pv.dofpv_strtab].dofs_offset) != sz) {
853265Smws 		mdb_warn("failed to read string table");
854265Smws 		return (-1);
855265Smws 	}
856265Smws 
857265Smws 	mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset),
858265Smws 	    strtab + pv.dofpv_name);
859265Smws 
860265Smws 	sz = dofs[pv.dofpv_prargs].dofs_size;
861265Smws 	if (sz != 0) {
862265Smws 		args = mdb_alloc(sz, UM_SLEEP | UM_GC);
863265Smws 		if (mdb_vread(args, sz, addr +
864265Smws 		    dofs[pv.dofpv_prargs].dofs_offset) != sz) {
865265Smws 			mdb_warn("failed to read args");
866265Smws 			return (-1);
867265Smws 		}
868265Smws 	}
869265Smws 
870265Smws 	sz = dofs[pv.dofpv_proffs].dofs_size;
871265Smws 	offs = mdb_alloc(sz, UM_SLEEP | UM_GC);
872265Smws 	if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset)
873265Smws 	    != sz) {
874*1710Sahl 		mdb_warn("failed to read offsets");
875265Smws 		return (-1);
876265Smws 	}
877265Smws 
878*1710Sahl 	enoffs = NULL;
879*1710Sahl 	if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 ||
880*1710Sahl 	    pv.dofpv_prenoffs == 0) {
881*1710Sahl 		sz = dofs[pv.dofpv_prenoffs].dofs_size;
882*1710Sahl 		enoffs = mdb_alloc(sz, UM_SLEEP | UM_GC);
883*1710Sahl 		if (mdb_vread(enoffs, sz, addr +
884*1710Sahl 		    dofs[pv.dofpv_prenoffs].dofs_offset) != sz) {
885*1710Sahl 			mdb_warn("failed to read is-enabled offsets");
886*1710Sahl 			return (-1);
887*1710Sahl 		}
888*1710Sahl 	}
889*1710Sahl 
890265Smws 	sz = dofs[pv.dofpv_probes].dofs_size;
891*1710Sahl 	p = mdb_alloc(sz, UM_SLEEP | UM_GC);
892*1710Sahl 	if (mdb_vread(p, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) {
893265Smws 		mdb_warn("failed to read probes");
894265Smws 		return (-1);
895265Smws 	}
896265Smws 
897265Smws 	(void) mdb_inc_indent(2);
898265Smws 
899265Smws 	for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) {
900*1710Sahl 		pb = (dof_probe_t *)(uintptr_t)(p +
901*1710Sahl 		    i * dofs[pv.dofpv_probes].dofs_entsize);
902*1710Sahl 
903265Smws 		mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr +
904265Smws 		    dofs[pv.dofpv_probes].dofs_offset +
905265Smws 		    i * dofs[pv.dofpv_probes].dofs_entsize),
906*1710Sahl 		    strtab + pb->dofpr_func,
907*1710Sahl 		    strtab + pb->dofpr_name);
908265Smws 
909265Smws 		(void) mdb_inc_indent(2);
910*1710Sahl 		mdb_printf("addr: %p\n", (ulong_t)pb->dofpr_addr);
911265Smws 		mdb_printf("offs: ");
912*1710Sahl 		for (j = 0; j < pb->dofpr_noffs; j++) {
913265Smws 			mdb_printf("%s %x", "," + (j == 0),
914*1710Sahl 			    offs[pb->dofpr_offidx + j]);
915265Smws 		}
916265Smws 		mdb_printf("\n");
917265Smws 
918*1710Sahl 		if (dofh->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1) {
919*1710Sahl 			mdb_printf("enoffs: ");
920*1710Sahl 			if (enoffs == NULL) {
921*1710Sahl 				if (pb->dofpr_nenoffs != 0)
922*1710Sahl 					mdb_printf("<error>");
923*1710Sahl 			} else {
924*1710Sahl 				for (j = 0; j < pb->dofpr_nenoffs; j++) {
925*1710Sahl 					mdb_printf("%s %x", "," + (j == 0),
926*1710Sahl 					    enoffs[pb->dofpr_enoffidx + j]);
927*1710Sahl 				}
928*1710Sahl 			}
929*1710Sahl 			mdb_printf("\n");
930*1710Sahl 		}
931*1710Sahl 
932265Smws 		mdb_printf("nargs:");
933*1710Sahl 		narg = pb->dofpr_nargv;
934*1710Sahl 		for (j = 0; j < pb->dofpr_nargc; j++) {
935265Smws 			mdb_printf("%s %s", "," + (j == 0), strtab + narg);
936265Smws 			narg += strlen(strtab + narg) + 1;
937265Smws 		}
938265Smws 		mdb_printf("\n");
939265Smws 		mdb_printf("xargs:");
940*1710Sahl 		xarg = pb->dofpr_xargv;
941*1710Sahl 		for (j = 0; j < pb->dofpr_xargc; j++) {
942265Smws 			mdb_printf("%s %s", "," + (j == 0), strtab + xarg);
943265Smws 			xarg += strlen(strtab + xarg) + 1;
944265Smws 		}
945265Smws 		mdb_printf("\n");
946265Smws 		mdb_printf("map:  ");
947*1710Sahl 		for (j = 0; j < pb->dofpr_xargc; j++) {
948265Smws 			mdb_printf("%s %d->%d", "," + (j == 0),
949*1710Sahl 			    args[pb->dofpr_argidx + j], j);
950265Smws 		}
951265Smws 
952265Smws 		(void) mdb_dec_indent(2);
953265Smws 		mdb_printf("\n}\n");
954265Smws 	}
955265Smws 
956265Smws 	(void) mdb_dec_indent(2);
957265Smws 	mdb_printf("}\n");
958265Smws 
959265Smws 	return (0);
960265Smws }
961265Smws 
962265Smws static int
dof_sect_prargs(uintptr_t addr,dof_sec_t * sec)963265Smws dof_sect_prargs(uintptr_t addr, dof_sec_t *sec)
964265Smws {
965265Smws 	int i;
966265Smws 	uint8_t arg;
967265Smws 
968265Smws 	for (i = 0; i < sec->dofs_size; i++) {
969265Smws 		if (mdb_vread(&arg, sizeof (arg),
970265Smws 		    addr + sec->dofs_offset + i) != sizeof (arg)) {
971265Smws 			mdb_warn("failed to read argument");
972265Smws 			return (1);
973265Smws 		}
974265Smws 
975265Smws 		mdb_printf("%d ", arg);
976265Smws 
977265Smws 		if (i % 20 == 19)
978265Smws 			mdb_printf("\n");
979265Smws 	}
980265Smws 
981265Smws 	mdb_printf("\n");
982265Smws 
983265Smws 	return (0);
984265Smws }
985265Smws 
986265Smws /*ARGSUSED*/
987265Smws static int
dofdump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)988265Smws dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
989265Smws {
990265Smws 	dof_hdr_t dofh;
991265Smws 	dof_sec_t *dofs;
992265Smws 	const char *name;
993265Smws 	int i;
994265Smws 
995265Smws 	if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) {
996265Smws 		mdb_warn("failed to read DOF header");
997265Smws 		return (DCMD_ERR);
998265Smws 	}
999265Smws 
1000265Smws 	dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum,
1001265Smws 	    UM_SLEEP | UM_GC);
1002265Smws 
1003265Smws 	for (i = 0; i < dofh.dofh_secnum; i++) {
1004265Smws 		if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff +
1005265Smws 		    addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) {
1006265Smws 			mdb_warn("failed to read DOF sections");
1007265Smws 			return (DCMD_ERR);
1008265Smws 		}
1009265Smws 	}
1010265Smws 
1011265Smws 	for (i = 0; i < dofh.dofh_secnum; i++) {
1012265Smws 		mdb_printf("%lx Section %d: ", (ulong_t)
1013265Smws 		    (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i);
1014265Smws 
1015265Smws 		if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL)
1016265Smws 			mdb_printf("%s\n", name);
1017265Smws 		else
1018265Smws 			mdb_printf("%u\n", dofs[i].dofs_type);
1019265Smws 
1020265Smws 		(void) mdb_inc_indent(2);
1021265Smws 		switch (dofs[i].dofs_type) {
1022265Smws 		case DOF_SECT_PROVIDER:
1023*1710Sahl 			(void) dof_sect_provider(&dofh, addr, &dofs[i], dofs);
1024265Smws 			break;
1025265Smws 		case DOF_SECT_STRTAB:
1026265Smws 			(void) dof_sect_strtab(addr, &dofs[i]);
1027265Smws 			break;
1028265Smws 		case DOF_SECT_PRARGS:
1029265Smws 			(void) dof_sect_prargs(addr, &dofs[i]);
1030265Smws 			break;
1031265Smws 		}
1032265Smws 		(void) mdb_dec_indent(2);
1033265Smws 
1034265Smws 		mdb_printf("\n");
1035265Smws 	}
1036265Smws 
1037265Smws 	return (DCMD_OK);
1038265Smws }
1039265Smws 
1040265Smws static const mdb_dcmd_t common_dcmds[] = {
1041265Smws 	{ "difinstr", ":", "disassemble a DIF instruction", difinstr },
1042265Smws 	{ "difo", ":", "print a DIF object", difo },
1043265Smws 	{ "dof_hdr", "?", "print a DOF header", dof_hdr },
1044265Smws 	{ "dof_sec", ":", "print a DOF section header", dof_sec },
1045265Smws 	{ "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc },
1046265Smws 	{ "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc },
1047265Smws 	{ "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc },
1048265Smws 	{ "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr },
1049265Smws 	{ "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc },
1050265Smws 	{ "dofdump", ":", "dump DOF", dofdump },
1051265Smws 	{ NULL }
1052265Smws };
1053265Smws 
1054265Smws static const mdb_walker_t common_walkers[] = {
1055265Smws 	{ "dof_sec", "walk DOF section header table given header address",
1056265Smws 		dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini },
1057265Smws 	{ NULL }
1058265Smws };
1059265Smws 
1060265Smws static mdb_modinfo_t modinfo = {
1061265Smws 	MDB_API_VERSION, NULL, NULL
1062265Smws };
1063265Smws 
1064265Smws const mdb_modinfo_t *
_mdb_init(void)1065265Smws _mdb_init(void)
1066265Smws {
1067265Smws 	uint_t d = 0, kd = 0, w = 0, kw = 0;
1068265Smws 	const mdb_walker_t *wp;
1069265Smws 	const mdb_dcmd_t *dp;
1070265Smws 
1071265Smws 	for (dp = common_dcmds; dp->dc_name != NULL; dp++)
1072265Smws 		d++; /* count common dcmds */
1073265Smws 
1074265Smws 	for (wp = common_walkers; wp->walk_name != NULL; wp++)
1075265Smws 		w++; /* count common walkers */
1076265Smws 
1077265Smws #ifdef _KERNEL
1078265Smws 	for (dp = kernel_dcmds; dp->dc_name != NULL; dp++)
1079265Smws 		kd++; /* count kernel dcmds */
1080265Smws 
1081265Smws 	for (wp = kernel_walkers; wp->walk_name != NULL; wp++)
1082265Smws 		kw++; /* count common walkers */
1083265Smws #endif
1084265Smws 
1085265Smws 	modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP);
1086265Smws 	modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP);
1087265Smws 
1088265Smws 	bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d);
1089265Smws 	bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w);
1090265Smws 
1091265Smws #ifdef _KERNEL
1092265Smws 	bcopy(kernel_dcmds, (void *)
1093265Smws 	    (modinfo.mi_dcmds + d), sizeof (*dp) * kd);
1094265Smws 	bcopy(kernel_walkers, (void *)
1095265Smws 	    (modinfo.mi_walkers + w), sizeof (*wp) * kw);
1096265Smws #endif
1097265Smws 	return (&modinfo);
1098265Smws }
1099265Smws 
1100265Smws void
_mdb_fini(void)1101265Smws _mdb_fini(void)
1102265Smws {
1103265Smws 	const mdb_walker_t *wp;
1104265Smws 	const mdb_dcmd_t *dp;
1105265Smws 	uint_t d = 0, w = 0;
1106265Smws 
1107265Smws 	for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++)
1108265Smws 		d++;
1109265Smws 
1110265Smws 	for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++)
1111265Smws 		w++;
1112265Smws 
1113265Smws 	mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1));
1114265Smws 	mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1));
1115265Smws }
1116