xref: /onnv-gate/usr/src/cmd/mdb/common/modules/dtrace/dof.c (revision 265:a968e4ece133)
1*265Smws /*
2*265Smws  * CDDL HEADER START
3*265Smws  *
4*265Smws  * The contents of this file are subject to the terms of the
5*265Smws  * Common Development and Distribution License, Version 1.0 only
6*265Smws  * (the "License").  You may not use this file except in compliance
7*265Smws  * with the License.
8*265Smws  *
9*265Smws  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*265Smws  * or http://www.opensolaris.org/os/licensing.
11*265Smws  * See the License for the specific language governing permissions
12*265Smws  * and limitations under the License.
13*265Smws  *
14*265Smws  * When distributing Covered Code, include this CDDL HEADER in each
15*265Smws  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*265Smws  * If applicable, add the following below this CDDL HEADER, with the
17*265Smws  * fields enclosed by brackets "[]" replaced with your own identifying
18*265Smws  * information: Portions Copyright [yyyy] [name of copyright owner]
19*265Smws  *
20*265Smws  * CDDL HEADER END
21*265Smws  */
22*265Smws /*
23*265Smws  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*265Smws  * Use is subject to license terms.
25*265Smws  */
26*265Smws 
27*265Smws #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*265Smws 
29*265Smws #include <mdb/mdb_modapi.h>
30*265Smws #include <dtrace.h>
31*265Smws 
32*265Smws #ifdef _LP64
33*265Smws #define	DIFO_ADDRWIDTH		11
34*265Smws #else
35*265Smws #define	DIFO_ADDRWIDTH		8
36*265Smws #endif
37*265Smws 
38*265Smws extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
39*265Smws extern const char *dof_sec_name(uint32_t);
40*265Smws 
41*265Smws extern const mdb_walker_t kernel_walkers[];
42*265Smws extern const mdb_dcmd_t kernel_dcmds[];
43*265Smws 
44*265Smws /*ARGSUSED*/
45*265Smws static void
46*265Smws dis_log(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
47*265Smws {
48*265Smws 	mdb_printf("%-4s %%r%u, %%r%u, %%r%u", name,
49*265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
50*265Smws }
51*265Smws 
52*265Smws /*ARGSUSED*/
53*265Smws static void
54*265Smws dis_branch(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
55*265Smws {
56*265Smws 	mdb_printf("%-4s %u", name, DIF_INSTR_LABEL(instr));
57*265Smws }
58*265Smws 
59*265Smws /*ARGSUSED*/
60*265Smws static void
61*265Smws dis_load(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
62*265Smws {
63*265Smws 	mdb_printf("%-4s [%%r%u], %%r%u", name,
64*265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
65*265Smws }
66*265Smws 
67*265Smws /*ARGSUSED*/
68*265Smws static void
69*265Smws dis_store(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
70*265Smws {
71*265Smws 	mdb_printf("%-4s %%r%u, [%%r%u]", name,
72*265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
73*265Smws }
74*265Smws 
75*265Smws /*ARGSUSED*/
76*265Smws static void
77*265Smws dis_str(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
78*265Smws {
79*265Smws 	mdb_printf("%s", name);
80*265Smws }
81*265Smws 
82*265Smws /*ARGSUSED*/
83*265Smws static void
84*265Smws dis_r1rd(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
85*265Smws {
86*265Smws 	mdb_printf("%-4s %%r%u, %%r%u", name,
87*265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_RD(instr));
88*265Smws }
89*265Smws 
90*265Smws /*ARGSUSED*/
91*265Smws static void
92*265Smws dis_cmp(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
93*265Smws {
94*265Smws 	mdb_printf("%-4s %%r%u, %%r%u", name,
95*265Smws 	    DIF_INSTR_R1(instr), DIF_INSTR_R2(instr));
96*265Smws }
97*265Smws 
98*265Smws /*ARGSUSED*/
99*265Smws static void
100*265Smws dis_tst(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
101*265Smws {
102*265Smws 	mdb_printf("%-4s %%r%u", name, DIF_INSTR_R1(instr));
103*265Smws }
104*265Smws 
105*265Smws static const char *
106*265Smws dis_varname(const dtrace_difo_t *dp, uint_t id, uint_t scope)
107*265Smws {
108*265Smws 	dtrace_difv_t *dvp;
109*265Smws 	size_t varsize;
110*265Smws 	caddr_t addr = NULL, str;
111*265Smws 	uint_t i;
112*265Smws 
113*265Smws 	if (dp == NULL)
114*265Smws 		return (NULL);
115*265Smws 
116*265Smws 	varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
117*265Smws 	dvp = mdb_alloc(varsize, UM_SLEEP);
118*265Smws 
119*265Smws 	if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
120*265Smws 		mdb_free(dvp, varsize);
121*265Smws 		return ("<unreadable>");
122*265Smws 	}
123*265Smws 
124*265Smws 	for (i = 0; i < dp->dtdo_varlen; i++) {
125*265Smws 		if (dvp[i].dtdv_id == id && dvp[i].dtdv_scope == scope) {
126*265Smws 			if (dvp[i].dtdv_name < dp->dtdo_strlen)
127*265Smws 				addr = dp->dtdo_strtab + dvp[i].dtdv_name;
128*265Smws 			break;
129*265Smws 		}
130*265Smws 	}
131*265Smws 
132*265Smws 	mdb_free(dvp, varsize);
133*265Smws 
134*265Smws 	if (addr == NULL)
135*265Smws 		return (NULL);
136*265Smws 
137*265Smws 	str = mdb_zalloc(dp->dtdo_strlen + 1, UM_SLEEP | UM_GC);
138*265Smws 
139*265Smws 	for (i = 0; i == 0 || str[i - 1] != '\0'; i++, addr++) {
140*265Smws 		if (mdb_vread(&str[i], sizeof (char), (uintptr_t)addr) == -1)
141*265Smws 			return ("<unreadable>");
142*265Smws 	}
143*265Smws 
144*265Smws 	return (str);
145*265Smws }
146*265Smws 
147*265Smws static uint_t
148*265Smws dis_scope(const char *name)
149*265Smws {
150*265Smws 	switch (name[2]) {
151*265Smws 	case 'l': return (DIFV_SCOPE_LOCAL);
152*265Smws 	case 't': return (DIFV_SCOPE_THREAD);
153*265Smws 	case 'g': return (DIFV_SCOPE_GLOBAL);
154*265Smws 	default: return (-1u);
155*265Smws 	}
156*265Smws }
157*265Smws 
158*265Smws static void
159*265Smws dis_lda(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
160*265Smws {
161*265Smws 	uint_t var = DIF_INSTR_R1(instr);
162*265Smws 	const char *vname;
163*265Smws 
164*265Smws 	mdb_printf("%-4s DIF_VAR(%x), %%r%u, %%r%u", name,
165*265Smws 	    var, DIF_INSTR_R2(instr), DIF_INSTR_RD(instr));
166*265Smws 
167*265Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
168*265Smws 		mdb_printf("\t\t! %s", vname);
169*265Smws }
170*265Smws 
171*265Smws static void
172*265Smws dis_ldv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
173*265Smws {
174*265Smws 	uint_t var = DIF_INSTR_VAR(instr);
175*265Smws 	const char *vname;
176*265Smws 
177*265Smws 	mdb_printf("%-4s DIF_VAR(%x), %%r%u", name, var, DIF_INSTR_RD(instr));
178*265Smws 
179*265Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
180*265Smws 		mdb_printf("\t\t! %s", vname);
181*265Smws }
182*265Smws 
183*265Smws static void
184*265Smws dis_stv(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
185*265Smws {
186*265Smws 	uint_t var = DIF_INSTR_VAR(instr);
187*265Smws 	const char *vname;
188*265Smws 
189*265Smws 	mdb_printf("%-4s %%r%u, DIF_VAR(%x)", name, DIF_INSTR_RS(instr), var);
190*265Smws 
191*265Smws 	if ((vname = dis_varname(dp, var, dis_scope(name))) != NULL)
192*265Smws 		mdb_printf("\t\t! %s", vname);
193*265Smws }
194*265Smws 
195*265Smws static void
196*265Smws dis_setx(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
197*265Smws {
198*265Smws 	uint_t intptr = DIF_INSTR_INTEGER(instr);
199*265Smws 
200*265Smws 	mdb_printf("%-4s DIF_INTEGER[%u], %%r%u", name,
201*265Smws 	    intptr, DIF_INSTR_RD(instr));
202*265Smws 
203*265Smws 	if (dp != NULL && intptr < dp->dtdo_intlen) {
204*265Smws 		uint64_t *ip = mdb_alloc(dp->dtdo_intlen *
205*265Smws 		    sizeof (uint64_t), UM_SLEEP | UM_GC);
206*265Smws 
207*265Smws 		if (mdb_vread(ip, dp->dtdo_intlen * sizeof (uint64_t),
208*265Smws 		    (uintptr_t)dp->dtdo_inttab) == -1)
209*265Smws 			mdb_warn("failed to read data at %p", dp->dtdo_inttab);
210*265Smws 		else
211*265Smws 			mdb_printf("\t\t! 0x%llx", ip[intptr]);
212*265Smws 	}
213*265Smws }
214*265Smws 
215*265Smws static void
216*265Smws dis_sets(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
217*265Smws {
218*265Smws 	uint_t strptr = DIF_INSTR_STRING(instr);
219*265Smws 
220*265Smws 	mdb_printf("%-4s DIF_STRING[%u], %%r%u", name,
221*265Smws 	    strptr, DIF_INSTR_RD(instr));
222*265Smws 
223*265Smws 	if (dp != NULL && strptr < dp->dtdo_strlen) {
224*265Smws 		char *str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
225*265Smws 
226*265Smws 		if (mdb_vread(str, dp->dtdo_strlen,
227*265Smws 		    (uintptr_t)dp->dtdo_strtab) == -1)
228*265Smws 			mdb_warn("failed to read data at %p", dp->dtdo_strtab);
229*265Smws 		else
230*265Smws 			mdb_printf("\t\t! \"%s\"", str + strptr);
231*265Smws 	}
232*265Smws }
233*265Smws 
234*265Smws /*ARGSUSED*/
235*265Smws static void
236*265Smws dis_ret(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
237*265Smws {
238*265Smws 	mdb_printf("%-4s %%r%u", name, DIF_INSTR_RD(instr));
239*265Smws }
240*265Smws 
241*265Smws /*ARGSUSED*/
242*265Smws static void
243*265Smws dis_call(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
244*265Smws {
245*265Smws 	uint_t subr = DIF_INSTR_SUBR(instr);
246*265Smws 
247*265Smws 	mdb_printf("%-4s DIF_SUBR(%u), %%r%u\t\t! %s",
248*265Smws 	    name, subr, DIF_INSTR_RD(instr), dtrace_subrstr(NULL, subr));
249*265Smws }
250*265Smws 
251*265Smws /*ARGSUSED*/
252*265Smws static void
253*265Smws dis_pushts(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
254*265Smws {
255*265Smws 	static const char *const tnames[] = { "TYPE_CTF", "TYPE_STRING" };
256*265Smws 	uint_t type = DIF_INSTR_TYPE(instr);
257*265Smws 
258*265Smws 	mdb_printf("%-4s DIF_TYPE(%u), %%r%u, %%r%u",
259*265Smws 	    name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr));
260*265Smws 
261*265Smws 	if (type < sizeof (tnames) / sizeof (tnames[0]))
262*265Smws 		mdb_printf("\t! %s", tnames[type]);
263*265Smws }
264*265Smws 
265*265Smws /*ARGSUSED*/
266*265Smws static void
267*265Smws dis_xlate(const dtrace_difo_t *dp, const char *name, dif_instr_t instr)
268*265Smws {
269*265Smws 	mdb_printf("%-4s DIF_XLREF[%u], %%r%u", name,
270*265Smws 	    DIF_INSTR_XLREF(instr), DIF_INSTR_RD(instr));
271*265Smws }
272*265Smws 
273*265Smws static char *
274*265Smws dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
275*265Smws {
276*265Smws 	char kind[8];
277*265Smws 
278*265Smws 	switch (t->dtdt_kind) {
279*265Smws 	case DIF_TYPE_CTF:
280*265Smws 		(void) strcpy(kind, "D type");
281*265Smws 		break;
282*265Smws 	case DIF_TYPE_STRING:
283*265Smws 		(void) strcpy(kind, "string");
284*265Smws 		break;
285*265Smws 	default:
286*265Smws 		(void) mdb_snprintf(kind, sizeof (kind), "0x%x", t->dtdt_kind);
287*265Smws 	}
288*265Smws 
289*265Smws 	if (t->dtdt_flags & DIF_TF_BYREF) {
290*265Smws 		(void) mdb_snprintf(buf, len,
291*265Smws 		    "%s by ref (size %lu)",
292*265Smws 		    kind, (ulong_t)t->dtdt_size);
293*265Smws 	} else {
294*265Smws 		(void) mdb_snprintf(buf, len, "%s (size %lu)",
295*265Smws 		    kind, (ulong_t)t->dtdt_size);
296*265Smws 	}
297*265Smws 
298*265Smws 	return (buf);
299*265Smws }
300*265Smws 
301*265Smws static int
302*265Smws dis(uintptr_t addr, dtrace_difo_t *dp)
303*265Smws {
304*265Smws 	static const struct opent {
305*265Smws 		const char *op_name;
306*265Smws 		void (*op_func)(const dtrace_difo_t *,
307*265Smws 		    const char *, dif_instr_t);
308*265Smws 	} optab[] = {
309*265Smws 		{ "(illegal opcode)", dis_str },
310*265Smws 		{ "or", dis_log },		/* DIF_OP_OR */
311*265Smws 		{ "xor", dis_log },		/* DIF_OP_XOR */
312*265Smws 		{ "and", dis_log },		/* DIF_OP_AND */
313*265Smws 		{ "sll", dis_log },		/* DIF_OP_SLL */
314*265Smws 		{ "srl", dis_log },		/* DIF_OP_SRL */
315*265Smws 		{ "sub", dis_log },		/* DIF_OP_SUB */
316*265Smws 		{ "add", dis_log },		/* DIF_OP_ADD */
317*265Smws 		{ "mul", dis_log },		/* DIF_OP_MUL */
318*265Smws 		{ "sdiv", dis_log },		/* DIF_OP_SDIV */
319*265Smws 		{ "udiv", dis_log },		/* DIF_OP_UDIV */
320*265Smws 		{ "srem", dis_log },		/* DIF_OP_SREM */
321*265Smws 		{ "urem", dis_log },		/* DIF_OP_UREM */
322*265Smws 		{ "not", dis_r1rd },		/* DIF_OP_NOT */
323*265Smws 		{ "mov", dis_r1rd },		/* DIF_OP_MOV */
324*265Smws 		{ "cmp", dis_cmp },		/* DIF_OP_CMP */
325*265Smws 		{ "tst", dis_tst },		/* DIF_OP_TST */
326*265Smws 		{ "ba", dis_branch },		/* DIF_OP_BA */
327*265Smws 		{ "be", dis_branch },		/* DIF_OP_BE */
328*265Smws 		{ "bne", dis_branch },		/* DIF_OP_BNE */
329*265Smws 		{ "bg", dis_branch },		/* DIF_OP_BG */
330*265Smws 		{ "bgu", dis_branch },		/* DIF_OP_BGU */
331*265Smws 		{ "bge", dis_branch },		/* DIF_OP_BGE */
332*265Smws 		{ "bgeu", dis_branch },		/* DIF_OP_BGEU */
333*265Smws 		{ "bl", dis_branch },		/* DIF_OP_BL */
334*265Smws 		{ "blu", dis_branch },		/* DIF_OP_BLU */
335*265Smws 		{ "ble", dis_branch },		/* DIF_OP_BLE */
336*265Smws 		{ "bleu", dis_branch },		/* DIF_OP_BLEU */
337*265Smws 		{ "ldsb", dis_load },		/* DIF_OP_LDSB */
338*265Smws 		{ "ldsh", dis_load },		/* DIF_OP_LDSH */
339*265Smws 		{ "ldsw", dis_load },		/* DIF_OP_LDSW */
340*265Smws 		{ "ldub", dis_load },		/* DIF_OP_LDUB */
341*265Smws 		{ "lduh", dis_load },		/* DIF_OP_LDUH */
342*265Smws 		{ "lduw", dis_load },		/* DIF_OP_LDUW */
343*265Smws 		{ "ldx", dis_load },		/* DIF_OP_LDX */
344*265Smws 		{ "ret", dis_ret },		/* DIF_OP_RET */
345*265Smws 		{ "nop", dis_str },		/* DIF_OP_NOP */
346*265Smws 		{ "setx", dis_setx },		/* DIF_OP_SETX */
347*265Smws 		{ "sets", dis_sets },		/* DIF_OP_SETS */
348*265Smws 		{ "scmp", dis_cmp },		/* DIF_OP_SCMP */
349*265Smws 		{ "ldga", dis_lda },		/* DIF_OP_LDGA */
350*265Smws 		{ "ldgs", dis_ldv },		/* DIF_OP_LDGS */
351*265Smws 		{ "stgs", dis_stv },		/* DIF_OP_STGS */
352*265Smws 		{ "ldta", dis_lda },		/* DIF_OP_LDTA */
353*265Smws 		{ "ldts", dis_ldv },		/* DIF_OP_LDTS */
354*265Smws 		{ "stts", dis_stv },		/* DIF_OP_STTS */
355*265Smws 		{ "sra", dis_log },		/* DIF_OP_SRA */
356*265Smws 		{ "call", dis_call },		/* DIF_OP_CALL */
357*265Smws 		{ "pushtr", dis_pushts },	/* DIF_OP_PUSHTR */
358*265Smws 		{ "pushtv", dis_pushts },	/* DIF_OP_PUSHTV */
359*265Smws 		{ "popts", dis_str },		/* DIF_OP_POPTS */
360*265Smws 		{ "flushts", dis_str },		/* DIF_OP_FLUSHTS */
361*265Smws 		{ "ldgaa", dis_ldv },		/* DIF_OP_LDGAA */
362*265Smws 		{ "ldtaa", dis_ldv },		/* DIF_OP_LDTAA */
363*265Smws 		{ "stgaa", dis_stv },		/* DIF_OP_STGAA */
364*265Smws 		{ "sttaa", dis_stv },		/* DIF_OP_STTAA */
365*265Smws 		{ "ldls", dis_ldv },		/* DIF_OP_LDLS */
366*265Smws 		{ "stls", dis_stv },		/* DIF_OP_STLS */
367*265Smws 		{ "allocs", dis_r1rd },		/* DIF_OP_ALLOCS */
368*265Smws 		{ "copys", dis_log },		/* DIF_OP_COPYS */
369*265Smws 		{ "stb", dis_store },		/* DIF_OP_STB */
370*265Smws 		{ "sth", dis_store },		/* DIF_OP_STH */
371*265Smws 		{ "stw", dis_store },		/* DIF_OP_STW */
372*265Smws 		{ "stx", dis_store },		/* DIF_OP_STX */
373*265Smws 		{ "uldsb", dis_load },		/* DIF_OP_ULDSB */
374*265Smws 		{ "uldsh", dis_load },		/* DIF_OP_ULDSH */
375*265Smws 		{ "uldsw", dis_load },		/* DIF_OP_ULDSW */
376*265Smws 		{ "uldub", dis_load },		/* DIF_OP_ULDUB */
377*265Smws 		{ "ulduh", dis_load },		/* DIF_OP_ULDUH */
378*265Smws 		{ "ulduw", dis_load },		/* DIF_OP_ULDUW */
379*265Smws 		{ "uldx", dis_load },		/* DIF_OP_ULDX */
380*265Smws 		{ "rldsb", dis_load },		/* DIF_OP_RLDSB */
381*265Smws 		{ "rldsh", dis_load },		/* DIF_OP_RLDSH */
382*265Smws 		{ "rldsw", dis_load },		/* DIF_OP_RLDSW */
383*265Smws 		{ "rldub", dis_load },		/* DIF_OP_RLDUB */
384*265Smws 		{ "rlduh", dis_load },		/* DIF_OP_RLDUH */
385*265Smws 		{ "rlduw", dis_load },		/* DIF_OP_RLDUW */
386*265Smws 		{ "rldx", dis_load },		/* DIF_OP_RLDX */
387*265Smws 		{ "xlate", dis_xlate },		/* DIF_OP_XLATE */
388*265Smws 		{ "xlarg", dis_xlate },		/* DIF_OP_XLARG */
389*265Smws 	};
390*265Smws 
391*265Smws 	dif_instr_t instr, opcode;
392*265Smws 	const struct opent *op;
393*265Smws 
394*265Smws 	if (mdb_vread(&instr, sizeof (dif_instr_t), addr) == -1) {
395*265Smws 		mdb_warn("failed to read DIF instruction at %p", addr);
396*265Smws 		return (DCMD_ERR);
397*265Smws 	}
398*265Smws 
399*265Smws 	opcode = DIF_INSTR_OP(instr);
400*265Smws 
401*265Smws 	if (opcode >= sizeof (optab) / sizeof (optab[0]))
402*265Smws 		opcode = 0; /* force invalid opcode message */
403*265Smws 
404*265Smws 	op = &optab[opcode];
405*265Smws 	mdb_printf("%0*p %08x ", DIFO_ADDRWIDTH, addr, instr);
406*265Smws 	op->op_func(dp, op->op_name, instr);
407*265Smws 	mdb_printf("\n");
408*265Smws 	mdb_set_dot(addr + sizeof (dif_instr_t));
409*265Smws 
410*265Smws 	return (DCMD_OK);
411*265Smws }
412*265Smws 
413*265Smws /*ARGSUSED*/
414*265Smws int
415*265Smws difo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
416*265Smws {
417*265Smws 	dtrace_difo_t difo, *dp = &difo;
418*265Smws 	uintptr_t instr, limit;
419*265Smws 	dtrace_difv_t *dvp;
420*265Smws 	size_t varsize;
421*265Smws 	ulong_t i;
422*265Smws 	char type[64];
423*265Smws 	char *str;
424*265Smws 
425*265Smws 	if (!(flags & DCMD_ADDRSPEC))
426*265Smws 		return (DCMD_USAGE);
427*265Smws 
428*265Smws 	if (mdb_vread(dp, sizeof (dtrace_difo_t), addr) == -1) {
429*265Smws 		mdb_warn("couldn't read dtrace_difo_t at %p", addr);
430*265Smws 		return (DCMD_ERR);
431*265Smws 	}
432*265Smws 
433*265Smws 	mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
434*265Smws 	    addr, dp->dtdo_refcnt);
435*265Smws 	mdb_printf("%<b>%-*s %-8s %s%</b>\n", DIFO_ADDRWIDTH, "ADDR",
436*265Smws 	    "OPCODE", "INSTRUCTION");
437*265Smws 
438*265Smws 	mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf);
439*265Smws 	limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t);
440*265Smws 
441*265Smws 	while ((instr = mdb_get_dot()) < limit)
442*265Smws 		dis(instr, dp);
443*265Smws 
444*265Smws 	if (dp->dtdo_varlen != 0) {
445*265Smws 		mdb_printf("\n%<b>%-16s %-4s %-3s %-3s %-4s %s%</b>\n",
446*265Smws 		    "NAME", "ID", "KND", "SCP", "FLAG", "TYPE");
447*265Smws 	}
448*265Smws 
449*265Smws 	varsize = sizeof (dtrace_difv_t) * dp->dtdo_varlen;
450*265Smws 	dvp = mdb_alloc(varsize, UM_SLEEP | UM_GC);
451*265Smws 
452*265Smws 	if (mdb_vread(dvp, varsize, (uintptr_t)dp->dtdo_vartab) == -1) {
453*265Smws 		mdb_warn("couldn't read dtdo_vartab");
454*265Smws 		return (DCMD_ERR);
455*265Smws 	}
456*265Smws 
457*265Smws 	str = mdb_alloc(dp->dtdo_strlen, UM_SLEEP | UM_GC);
458*265Smws 
459*265Smws 	if (mdb_vread(str, dp->dtdo_strlen, (uintptr_t)dp->dtdo_strtab) == -1) {
460*265Smws 		mdb_warn("couldn't read dtdo_strtab");
461*265Smws 		return (DCMD_ERR);
462*265Smws 	}
463*265Smws 
464*265Smws 	for (i = 0; i < dp->dtdo_varlen; i++) {
465*265Smws 		dtrace_difv_t *v = &dvp[i];
466*265Smws 		char kind[4], scope[4], flags[16] = { 0 };
467*265Smws 
468*265Smws 		switch (v->dtdv_kind) {
469*265Smws 		case DIFV_KIND_ARRAY:
470*265Smws 			(void) strcpy(kind, "arr");
471*265Smws 			break;
472*265Smws 		case DIFV_KIND_SCALAR:
473*265Smws 			(void) strcpy(kind, "scl");
474*265Smws 			break;
475*265Smws 		default:
476*265Smws 			(void) mdb_snprintf(kind, sizeof (kind),
477*265Smws 			    "%u", v->dtdv_kind);
478*265Smws 		}
479*265Smws 
480*265Smws 		switch (v->dtdv_scope) {
481*265Smws 		case DIFV_SCOPE_GLOBAL:
482*265Smws 			(void) strcpy(scope, "glb");
483*265Smws 			break;
484*265Smws 		case DIFV_SCOPE_THREAD:
485*265Smws 			(void) strcpy(scope, "tls");
486*265Smws 			break;
487*265Smws 		case DIFV_SCOPE_LOCAL:
488*265Smws 			(void) strcpy(scope, "loc");
489*265Smws 			break;
490*265Smws 		default:
491*265Smws 			(void) mdb_snprintf(scope, sizeof (scope),
492*265Smws 			    "%u", v->dtdv_scope);
493*265Smws 		}
494*265Smws 
495*265Smws 		if (v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD)) {
496*265Smws 			(void) mdb_snprintf(flags, sizeof (flags), "/0x%x",
497*265Smws 			    v->dtdv_flags & ~(DIFV_F_REF | DIFV_F_MOD));
498*265Smws 		}
499*265Smws 
500*265Smws 		if (v->dtdv_flags & DIFV_F_REF)
501*265Smws 			(void) strcat(flags, "/r");
502*265Smws 		if (v->dtdv_flags & DIFV_F_MOD)
503*265Smws 			(void) strcat(flags, "/w");
504*265Smws 
505*265Smws 		mdb_printf("%-16s %-4x %-3s %-3s %-4s %s\n",
506*265Smws 		    &str[v->dtdv_name],
507*265Smws 		    v->dtdv_id, kind, scope, flags + 1,
508*265Smws 		    dis_typestr(&v->dtdv_type, type, sizeof (type)));
509*265Smws 	}
510*265Smws 
511*265Smws 	mdb_printf("\n%<b>RETURN%</b>\n%s\n\n",
512*265Smws 	    dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
513*265Smws 
514*265Smws 	return (DCMD_OK);
515*265Smws }
516*265Smws 
517*265Smws /*ARGSUSED*/
518*265Smws int
519*265Smws difinstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
520*265Smws {
521*265Smws 	if (!(flags & DCMD_ADDRSPEC))
522*265Smws 		return (DCMD_USAGE);
523*265Smws 
524*265Smws 	return (dis(addr, NULL));
525*265Smws }
526*265Smws 
527*265Smws /*ARGSUSED*/
528*265Smws int
529*265Smws dof_hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
530*265Smws {
531*265Smws 	dof_hdr_t h;
532*265Smws 
533*265Smws 	if (argc != 0)
534*265Smws 		return (DCMD_USAGE);
535*265Smws 
536*265Smws 	if (!(flags & DCMD_ADDRSPEC))
537*265Smws 		addr = 0; /* assume base of file in file target */
538*265Smws 
539*265Smws 	if (mdb_vread(&h, sizeof (h), addr) != sizeof (h)) {
540*265Smws 		mdb_warn("failed to read header at %p", addr);
541*265Smws 		return (DCMD_ERR);
542*265Smws 	}
543*265Smws 
544*265Smws 	mdb_printf("dofh_ident.id_magic = 0x%x, %c, %c, %c\n",
545*265Smws 	    h.dofh_ident[DOF_ID_MAG0], h.dofh_ident[DOF_ID_MAG1],
546*265Smws 	    h.dofh_ident[DOF_ID_MAG2], h.dofh_ident[DOF_ID_MAG3]);
547*265Smws 
548*265Smws 	switch (h.dofh_ident[DOF_ID_MODEL]) {
549*265Smws 	case DOF_MODEL_ILP32:
550*265Smws 		mdb_printf("dofh_ident.id_model = ILP32\n");
551*265Smws 		break;
552*265Smws 	case DOF_MODEL_LP64:
553*265Smws 		mdb_printf("dofh_ident.id_model = LP64\n");
554*265Smws 		break;
555*265Smws 	default:
556*265Smws 		mdb_printf("dofh_ident.id_model = 0x%x\n",
557*265Smws 		    h.dofh_ident[DOF_ID_MODEL]);
558*265Smws 	}
559*265Smws 
560*265Smws 	switch (h.dofh_ident[DOF_ID_ENCODING]) {
561*265Smws 	case DOF_ENCODE_LSB:
562*265Smws 		mdb_printf("dofh_ident.id_encoding = LSB\n");
563*265Smws 		break;
564*265Smws 	case DOF_ENCODE_MSB:
565*265Smws 		mdb_printf("dofh_ident.id_encoding = MSB\n");
566*265Smws 		break;
567*265Smws 	default:
568*265Smws 		mdb_printf("dofh_ident.id_encoding = 0x%x\n",
569*265Smws 		    h.dofh_ident[DOF_ID_ENCODING]);
570*265Smws 	}
571*265Smws 
572*265Smws 	mdb_printf("dofh_ident.id_version = %u\n",
573*265Smws 	    h.dofh_ident[DOF_ID_VERSION]);
574*265Smws 	mdb_printf("dofh_ident.id_difvers = %u\n",
575*265Smws 	    h.dofh_ident[DOF_ID_DIFVERS]);
576*265Smws 	mdb_printf("dofh_ident.id_difireg = %u\n",
577*265Smws 	    h.dofh_ident[DOF_ID_DIFIREG]);
578*265Smws 	mdb_printf("dofh_ident.id_diftreg = %u\n",
579*265Smws 	    h.dofh_ident[DOF_ID_DIFTREG]);
580*265Smws 
581*265Smws 	mdb_printf("dofh_flags = 0x%x\n", h.dofh_flags);
582*265Smws 	mdb_printf("dofh_hdrsize = %u\n", h.dofh_hdrsize);
583*265Smws 	mdb_printf("dofh_secsize = %u\n", h.dofh_secsize);
584*265Smws 	mdb_printf("dofh_secnum = %u\n", h.dofh_secnum);
585*265Smws 	mdb_printf("dofh_secoff = %llu\n", h.dofh_secoff);
586*265Smws 	mdb_printf("dofh_loadsz = %llu\n", h.dofh_loadsz);
587*265Smws 	mdb_printf("dofh_filesz = %llu\n", h.dofh_filesz);
588*265Smws 
589*265Smws 	return (DCMD_OK);
590*265Smws }
591*265Smws 
592*265Smws /*ARGSUSED*/
593*265Smws static int
594*265Smws dof_sec_walk(uintptr_t addr, void *ignored, int *sec)
595*265Smws {
596*265Smws 	mdb_printf("%3d ", (*sec)++);
597*265Smws 	(void) dof_sec(addr, DCMD_ADDRSPEC | DCMD_LOOP, 0, NULL);
598*265Smws 	return (WALK_NEXT);
599*265Smws }
600*265Smws 
601*265Smws /*ARGSUSED*/
602*265Smws int
603*265Smws dof_sec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
604*265Smws {
605*265Smws 	const char *name;
606*265Smws 	dof_sec_t s;
607*265Smws 
608*265Smws 	if (!(flags & DCMD_ADDRSPEC))
609*265Smws 		mdb_printf("%<u>%-3s ", "NDX");
610*265Smws 
611*265Smws 	if (!(flags & DCMD_ADDRSPEC) || DCMD_HDRSPEC(flags)) {
612*265Smws 		mdb_printf("%<u>%?s %-10s %-5s %-5s %-5s %-6s %-5s%</u>\n",
613*265Smws 		    "ADDR", "TYPE", "ALIGN", "FLAGS", "ENTSZ", "OFFSET",
614*265Smws 		    "SIZE");
615*265Smws 	}
616*265Smws 
617*265Smws 	if (!(flags & DCMD_ADDRSPEC)) {
618*265Smws 		int sec = 0;
619*265Smws 
620*265Smws 		if (mdb_walk("dof_sec",
621*265Smws 		    (mdb_walk_cb_t)dof_sec_walk, &sec) == -1) {
622*265Smws 			mdb_warn("failed to walk dof_sec");
623*265Smws 			return (DCMD_ERR);
624*265Smws 		}
625*265Smws 		return (DCMD_OK);
626*265Smws 	}
627*265Smws 
628*265Smws 	if (argc != 0)
629*265Smws 		return (DCMD_USAGE);
630*265Smws 
631*265Smws 	if (mdb_vread(&s, sizeof (s), addr) != sizeof (s)) {
632*265Smws 		mdb_warn("failed to read section header at %p", addr);
633*265Smws 		return (DCMD_ERR);
634*265Smws 	}
635*265Smws 
636*265Smws 	mdb_printf("%?p ", addr);
637*265Smws 
638*265Smws 	if ((name = dof_sec_name(s.dofs_type)) != NULL)
639*265Smws 		mdb_printf("%-10s ", name);
640*265Smws 	else
641*265Smws 		mdb_printf("%-10u ", s.dofs_type);
642*265Smws 
643*265Smws 	mdb_printf("%-5u %-#5x %-#5x %-6llx %-#5llx\n", s.dofs_align,
644*265Smws 	    s.dofs_flags, s.dofs_entsize, s.dofs_offset, s.dofs_size);
645*265Smws 
646*265Smws 	return (DCMD_OK);
647*265Smws }
648*265Smws 
649*265Smws int
650*265Smws dof_sec_walk_init(mdb_walk_state_t *wsp)
651*265Smws {
652*265Smws 	dof_hdr_t h, *hp;
653*265Smws 	size_t size;
654*265Smws 
655*265Smws 	if (mdb_vread(&h, sizeof (h), wsp->walk_addr) != sizeof (h)) {
656*265Smws 		mdb_warn("failed to read DOF header at %p", wsp->walk_addr);
657*265Smws 		return (WALK_ERR);
658*265Smws 	}
659*265Smws 
660*265Smws 	size = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * h.dofh_secnum;
661*265Smws 	hp = mdb_alloc(size, UM_SLEEP);
662*265Smws 
663*265Smws 	if (mdb_vread(hp, size, wsp->walk_addr) != size) {
664*265Smws 		mdb_warn("failed to read DOF sections at %p", wsp->walk_addr);
665*265Smws 		mdb_free(hp, size);
666*265Smws 		return (WALK_ERR);
667*265Smws 	}
668*265Smws 
669*265Smws 	wsp->walk_arg = (void *)0;
670*265Smws 	wsp->walk_data = hp;
671*265Smws 
672*265Smws 	return (WALK_NEXT);
673*265Smws }
674*265Smws 
675*265Smws int
676*265Smws dof_sec_walk_step(mdb_walk_state_t *wsp)
677*265Smws {
678*265Smws 	uint_t i = (uintptr_t)wsp->walk_arg;
679*265Smws 	size_t off = sizeof (dof_hdr_t) + sizeof (dof_sec_t) * i;
680*265Smws 	dof_hdr_t *hp = wsp->walk_data;
681*265Smws 	dof_sec_t *sp = (dof_sec_t *)((uintptr_t)hp + off);
682*265Smws 
683*265Smws 	if (i >= hp->dofh_secnum)
684*265Smws 		return (WALK_DONE);
685*265Smws 
686*265Smws 	wsp->walk_arg = (void *)(uintptr_t)(i + 1);
687*265Smws 	return (wsp->walk_callback(wsp->walk_addr + off, sp, wsp->walk_cbdata));
688*265Smws }
689*265Smws 
690*265Smws void
691*265Smws dof_sec_walk_fini(mdb_walk_state_t *wsp)
692*265Smws {
693*265Smws 	dof_hdr_t *hp = wsp->walk_data;
694*265Smws 	mdb_free(hp, sizeof (dof_hdr_t) + sizeof (dof_sec_t) * hp->dofh_secnum);
695*265Smws }
696*265Smws 
697*265Smws /*ARGSUSED*/
698*265Smws int
699*265Smws dof_ecbdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
700*265Smws {
701*265Smws 	dof_ecbdesc_t e;
702*265Smws 
703*265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
704*265Smws 		return (DCMD_USAGE);
705*265Smws 
706*265Smws 	if (mdb_vread(&e, sizeof (e), addr) != sizeof (e)) {
707*265Smws 		mdb_warn("failed to read ecbdesc at %p", addr);
708*265Smws 		return (DCMD_ERR);
709*265Smws 	}
710*265Smws 
711*265Smws 	mdb_printf("dofe_probes = %d\n", e.dofe_probes);
712*265Smws 	mdb_printf("dofe_actions = %d\n", e.dofe_actions);
713*265Smws 	mdb_printf("dofe_pred = %d\n", e.dofe_pred);
714*265Smws 	mdb_printf("dofe_uarg = 0x%llx\n", e.dofe_uarg);
715*265Smws 
716*265Smws 	return (DCMD_OK);
717*265Smws }
718*265Smws 
719*265Smws /*ARGSUSED*/
720*265Smws int
721*265Smws dof_probedesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
722*265Smws {
723*265Smws 	dof_probedesc_t p;
724*265Smws 
725*265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
726*265Smws 		return (DCMD_USAGE);
727*265Smws 
728*265Smws 	if (mdb_vread(&p, sizeof (p), addr) != sizeof (p)) {
729*265Smws 		mdb_warn("failed to read probedesc at %p", addr);
730*265Smws 		return (DCMD_ERR);
731*265Smws 	}
732*265Smws 
733*265Smws 	mdb_printf("dofp_strtab = %d\n", p.dofp_strtab);
734*265Smws 	mdb_printf("dofp_provider = %u\n", p.dofp_provider);
735*265Smws 	mdb_printf("dofp_mod = %u\n", p.dofp_mod);
736*265Smws 	mdb_printf("dofp_func = %u\n", p.dofp_func);
737*265Smws 	mdb_printf("dofp_name = %u\n", p.dofp_name);
738*265Smws 	mdb_printf("dofp_id = %u\n", p.dofp_id);
739*265Smws 
740*265Smws 	return (DCMD_OK);
741*265Smws }
742*265Smws 
743*265Smws /*ARGSUSED*/
744*265Smws int
745*265Smws dof_actdesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
746*265Smws {
747*265Smws 	dof_actdesc_t a;
748*265Smws 
749*265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
750*265Smws 		return (DCMD_USAGE);
751*265Smws 
752*265Smws 	if (mdb_vread(&a, sizeof (a), addr) != sizeof (a)) {
753*265Smws 		mdb_warn("failed to read actdesc at %p", addr);
754*265Smws 		return (DCMD_ERR);
755*265Smws 	}
756*265Smws 
757*265Smws 	mdb_printf("dofa_difo = %d\n", a.dofa_difo);
758*265Smws 	mdb_printf("dofa_strtab = %d\n", a.dofa_strtab);
759*265Smws 	mdb_printf("dofa_kind = %u\n", a.dofa_kind);
760*265Smws 	mdb_printf("dofa_ntuple = %u\n", a.dofa_ntuple);
761*265Smws 	mdb_printf("dofa_arg = 0x%llx\n", a.dofa_arg);
762*265Smws 	mdb_printf("dofa_uarg = 0x%llx\n", a.dofa_uarg);
763*265Smws 
764*265Smws 	return (DCMD_OK);
765*265Smws }
766*265Smws 
767*265Smws /*ARGSUSED*/
768*265Smws int
769*265Smws dof_relohdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
770*265Smws {
771*265Smws 	dof_relohdr_t r;
772*265Smws 
773*265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
774*265Smws 		return (DCMD_USAGE);
775*265Smws 
776*265Smws 	if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
777*265Smws 		mdb_warn("failed to read relohdr at %p", addr);
778*265Smws 		return (DCMD_ERR);
779*265Smws 	}
780*265Smws 
781*265Smws 	mdb_printf("dofr_strtab = %d\n", r.dofr_strtab);
782*265Smws 	mdb_printf("dofr_relsec = %d\n", r.dofr_relsec);
783*265Smws 	mdb_printf("dofr_tgtsec = %d\n", r.dofr_tgtsec);
784*265Smws 
785*265Smws 	return (DCMD_OK);
786*265Smws }
787*265Smws 
788*265Smws /*ARGSUSED*/
789*265Smws int
790*265Smws dof_relodesc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
791*265Smws {
792*265Smws 	dof_relodesc_t r;
793*265Smws 
794*265Smws 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
795*265Smws 		return (DCMD_USAGE);
796*265Smws 
797*265Smws 	if (mdb_vread(&r, sizeof (r), addr) != sizeof (r)) {
798*265Smws 		mdb_warn("failed to read relodesc at %p", addr);
799*265Smws 		return (DCMD_ERR);
800*265Smws 	}
801*265Smws 
802*265Smws 	mdb_printf("dofr_name = %u\n", r.dofr_name);
803*265Smws 	mdb_printf("dofr_type = %u\n", r.dofr_type);
804*265Smws 	mdb_printf("dofr_offset = 0x%llx\n", r.dofr_offset);
805*265Smws 	mdb_printf("dofr_data = 0x%llx\n", r.dofr_data);
806*265Smws 
807*265Smws 	return (DCMD_OK);
808*265Smws }
809*265Smws 
810*265Smws static int
811*265Smws dof_sect_strtab(uintptr_t addr, dof_sec_t *sec)
812*265Smws {
813*265Smws 	char *strtab;
814*265Smws 	size_t sz, i;
815*265Smws 
816*265Smws 	sz = (size_t)sec->dofs_size;
817*265Smws 	strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
818*265Smws 	if (mdb_vread(strtab, sz, addr + sec->dofs_offset) != sz) {
819*265Smws 		mdb_warn("failed to read string table");
820*265Smws 		return (1);
821*265Smws 	}
822*265Smws 
823*265Smws 	mdb_printf("size = %lx\n", sz);
824*265Smws 
825*265Smws 	for (i = 0; i < sz; i++) {
826*265Smws 		if (strtab[i] == '\0')
827*265Smws 			mdb_printf("\\0");
828*265Smws 		else
829*265Smws 			mdb_printf("%c", strtab[i]);
830*265Smws 	}
831*265Smws 
832*265Smws 	mdb_printf("\n");
833*265Smws 
834*265Smws 	return (0);
835*265Smws }
836*265Smws 
837*265Smws static int
838*265Smws dof_sect_provider(uintptr_t addr, dof_sec_t *sec, dof_sec_t *dofs)
839*265Smws {
840*265Smws 	dof_provider_t pv;
841*265Smws 	dof_probe_t *pb;
842*265Smws 	char *strtab;
843*265Smws 	uint32_t *offs;
844*265Smws 	uint8_t *args = NULL;
845*265Smws 	size_t sz;
846*265Smws 	int i, j;
847*265Smws 	dof_stridx_t narg, xarg;
848*265Smws 
849*265Smws 	if (mdb_vread(&pv, sizeof (dof_provider_t),
850*265Smws 	    addr + sec->dofs_offset) != sizeof (dof_provider_t)) {
851*265Smws 		mdb_warn("failed to read DOF provider");
852*265Smws 		return (-1);
853*265Smws 	}
854*265Smws 
855*265Smws 	sz = dofs[pv.dofpv_strtab].dofs_size;
856*265Smws 	strtab = mdb_alloc(sz, UM_SLEEP | UM_GC);
857*265Smws 	if (mdb_vread(strtab, sz, addr +
858*265Smws 	    dofs[pv.dofpv_strtab].dofs_offset) != sz) {
859*265Smws 		mdb_warn("failed to read string table");
860*265Smws 		return (-1);
861*265Smws 	}
862*265Smws 
863*265Smws 	mdb_printf("%lx provider %s {\n", (ulong_t)(addr + sec->dofs_offset),
864*265Smws 	    strtab + pv.dofpv_name);
865*265Smws 
866*265Smws 	sz = dofs[pv.dofpv_prargs].dofs_size;
867*265Smws 	if (sz != 0) {
868*265Smws 		args = mdb_alloc(sz, UM_SLEEP | UM_GC);
869*265Smws 		if (mdb_vread(args, sz, addr +
870*265Smws 		    dofs[pv.dofpv_prargs].dofs_offset) != sz) {
871*265Smws 			mdb_warn("failed to read args");
872*265Smws 			return (-1);
873*265Smws 		}
874*265Smws 	}
875*265Smws 
876*265Smws 	sz = dofs[pv.dofpv_proffs].dofs_size;
877*265Smws 	offs = mdb_alloc(sz, UM_SLEEP | UM_GC);
878*265Smws 	if (mdb_vread(offs, sz, addr + dofs[pv.dofpv_proffs].dofs_offset)
879*265Smws 	    != sz) {
880*265Smws 		mdb_warn("failed to read offs");
881*265Smws 		return (-1);
882*265Smws 	}
883*265Smws 
884*265Smws 	sz = dofs[pv.dofpv_probes].dofs_size;
885*265Smws 	pb = mdb_alloc(sz, UM_SLEEP | UM_GC);
886*265Smws 	if (mdb_vread(pb, sz, addr + dofs[pv.dofpv_probes].dofs_offset) != sz) {
887*265Smws 		mdb_warn("failed to read probes");
888*265Smws 		return (-1);
889*265Smws 	}
890*265Smws 
891*265Smws 	(void) mdb_inc_indent(2);
892*265Smws 
893*265Smws 	for (i = 0; i < sz / dofs[pv.dofpv_probes].dofs_entsize; i++) {
894*265Smws 		mdb_printf("%lx probe %s:%s {\n", (ulong_t)(addr +
895*265Smws 		    dofs[pv.dofpv_probes].dofs_offset +
896*265Smws 		    i * dofs[pv.dofpv_probes].dofs_entsize),
897*265Smws 		    strtab + pb[i].dofpr_func,
898*265Smws 		    strtab + pb[i].dofpr_name);
899*265Smws 
900*265Smws 		(void) mdb_inc_indent(2);
901*265Smws 		mdb_printf("addr: %p\n", (ulong_t)pb[i].dofpr_addr);
902*265Smws 		mdb_printf("offs: ");
903*265Smws 		for (j = 0; j < pb[i].dofpr_noffs; j++) {
904*265Smws 			mdb_printf("%s %x", "," + (j == 0),
905*265Smws 			    offs[pb[i].dofpr_offidx + j]);
906*265Smws 		}
907*265Smws 		mdb_printf("\n");
908*265Smws 
909*265Smws 		mdb_printf("nargs:");
910*265Smws 		narg = pb[i].dofpr_nargv;
911*265Smws 		for (j = 0; j < pb[i].dofpr_nargc; j++) {
912*265Smws 			mdb_printf("%s %s", "," + (j == 0), strtab + narg);
913*265Smws 			narg += strlen(strtab + narg) + 1;
914*265Smws 		}
915*265Smws 		mdb_printf("\n");
916*265Smws 		mdb_printf("xargs:");
917*265Smws 		xarg = pb[i].dofpr_xargv;
918*265Smws 		for (j = 0; j < pb[i].dofpr_xargc; j++) {
919*265Smws 			mdb_printf("%s %s", "," + (j == 0), strtab + xarg);
920*265Smws 			xarg += strlen(strtab + xarg) + 1;
921*265Smws 		}
922*265Smws 		mdb_printf("\n");
923*265Smws 		mdb_printf("map:  ");
924*265Smws 		for (j = 0; j < pb[i].dofpr_xargc; j++) {
925*265Smws 			mdb_printf("%s %d->%d", "," + (j == 0),
926*265Smws 			    args[pb[i].dofpr_argidx + j], j);
927*265Smws 		}
928*265Smws 
929*265Smws 		(void) mdb_dec_indent(2);
930*265Smws 		mdb_printf("\n}\n");
931*265Smws 	}
932*265Smws 
933*265Smws 	(void) mdb_dec_indent(2);
934*265Smws 	mdb_printf("}\n");
935*265Smws 
936*265Smws 	return (0);
937*265Smws }
938*265Smws 
939*265Smws static int
940*265Smws dof_sect_prargs(uintptr_t addr, dof_sec_t *sec)
941*265Smws {
942*265Smws 	int i;
943*265Smws 	uint8_t arg;
944*265Smws 
945*265Smws 	for (i = 0; i < sec->dofs_size; i++) {
946*265Smws 		if (mdb_vread(&arg, sizeof (arg),
947*265Smws 		    addr + sec->dofs_offset + i) != sizeof (arg)) {
948*265Smws 			mdb_warn("failed to read argument");
949*265Smws 			return (1);
950*265Smws 		}
951*265Smws 
952*265Smws 		mdb_printf("%d ", arg);
953*265Smws 
954*265Smws 		if (i % 20 == 19)
955*265Smws 			mdb_printf("\n");
956*265Smws 	}
957*265Smws 
958*265Smws 	mdb_printf("\n");
959*265Smws 
960*265Smws 	return (0);
961*265Smws }
962*265Smws 
963*265Smws /*ARGSUSED*/
964*265Smws static int
965*265Smws dofdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
966*265Smws {
967*265Smws 	dof_hdr_t dofh;
968*265Smws 	dof_sec_t *dofs;
969*265Smws 	const char *name;
970*265Smws 	int i;
971*265Smws 
972*265Smws 	if (mdb_vread(&dofh, sizeof (dof_hdr_t), addr) != sizeof (dof_hdr_t)) {
973*265Smws 		mdb_warn("failed to read DOF header");
974*265Smws 		return (DCMD_ERR);
975*265Smws 	}
976*265Smws 
977*265Smws 	dofs = mdb_alloc(sizeof (dof_sec_t) * dofh.dofh_secnum,
978*265Smws 	    UM_SLEEP | UM_GC);
979*265Smws 
980*265Smws 	for (i = 0; i < dofh.dofh_secnum; i++) {
981*265Smws 		if (mdb_vread(&dofs[i], sizeof (dof_sec_t), dofh.dofh_secoff +
982*265Smws 		    addr + i * dofh.dofh_secsize) != sizeof (dof_sec_t)) {
983*265Smws 			mdb_warn("failed to read DOF sections");
984*265Smws 			return (DCMD_ERR);
985*265Smws 		}
986*265Smws 	}
987*265Smws 
988*265Smws 	for (i = 0; i < dofh.dofh_secnum; i++) {
989*265Smws 		mdb_printf("%lx Section %d: ", (ulong_t)
990*265Smws 		    (dofh.dofh_secoff + addr + i * dofh.dofh_secsize), i);
991*265Smws 
992*265Smws 		if ((name = dof_sec_name(dofs[i].dofs_type)) != NULL)
993*265Smws 			mdb_printf("%s\n", name);
994*265Smws 		else
995*265Smws 			mdb_printf("%u\n", dofs[i].dofs_type);
996*265Smws 
997*265Smws 		(void) mdb_inc_indent(2);
998*265Smws 		switch (dofs[i].dofs_type) {
999*265Smws 		case DOF_SECT_PROVIDER:
1000*265Smws 			(void) dof_sect_provider(addr, &dofs[i], dofs);
1001*265Smws 			break;
1002*265Smws 		case DOF_SECT_STRTAB:
1003*265Smws 			(void) dof_sect_strtab(addr, &dofs[i]);
1004*265Smws 			break;
1005*265Smws 		case DOF_SECT_PRARGS:
1006*265Smws 			(void) dof_sect_prargs(addr, &dofs[i]);
1007*265Smws 			break;
1008*265Smws 		}
1009*265Smws 		(void) mdb_dec_indent(2);
1010*265Smws 
1011*265Smws 		mdb_printf("\n");
1012*265Smws 	}
1013*265Smws 
1014*265Smws 	return (DCMD_OK);
1015*265Smws }
1016*265Smws 
1017*265Smws static const mdb_dcmd_t common_dcmds[] = {
1018*265Smws 	{ "difinstr", ":", "disassemble a DIF instruction", difinstr },
1019*265Smws 	{ "difo", ":", "print a DIF object", difo },
1020*265Smws 	{ "dof_hdr", "?", "print a DOF header", dof_hdr },
1021*265Smws 	{ "dof_sec", ":", "print a DOF section header", dof_sec },
1022*265Smws 	{ "dof_ecbdesc", ":", "print a DOF ecbdesc", dof_ecbdesc },
1023*265Smws 	{ "dof_probedesc", ":", "print a DOF probedesc", dof_probedesc },
1024*265Smws 	{ "dof_actdesc", ":", "print a DOF actdesc", dof_actdesc },
1025*265Smws 	{ "dof_relohdr", ":", "print a DOF relocation header", dof_relohdr },
1026*265Smws 	{ "dof_relodesc", ":", "print a DOF relodesc", dof_relodesc },
1027*265Smws 	{ "dofdump", ":", "dump DOF", dofdump },
1028*265Smws 	{ NULL }
1029*265Smws };
1030*265Smws 
1031*265Smws static const mdb_walker_t common_walkers[] = {
1032*265Smws 	{ "dof_sec", "walk DOF section header table given header address",
1033*265Smws 		dof_sec_walk_init, dof_sec_walk_step, dof_sec_walk_fini },
1034*265Smws 	{ NULL }
1035*265Smws };
1036*265Smws 
1037*265Smws static mdb_modinfo_t modinfo = {
1038*265Smws 	MDB_API_VERSION, NULL, NULL
1039*265Smws };
1040*265Smws 
1041*265Smws const mdb_modinfo_t *
1042*265Smws _mdb_init(void)
1043*265Smws {
1044*265Smws 	uint_t d = 0, kd = 0, w = 0, kw = 0;
1045*265Smws 	const mdb_walker_t *wp;
1046*265Smws 	const mdb_dcmd_t *dp;
1047*265Smws 
1048*265Smws 	for (dp = common_dcmds; dp->dc_name != NULL; dp++)
1049*265Smws 		d++; /* count common dcmds */
1050*265Smws 
1051*265Smws 	for (wp = common_walkers; wp->walk_name != NULL; wp++)
1052*265Smws 		w++; /* count common walkers */
1053*265Smws 
1054*265Smws #ifdef _KERNEL
1055*265Smws 	for (dp = kernel_dcmds; dp->dc_name != NULL; dp++)
1056*265Smws 		kd++; /* count kernel dcmds */
1057*265Smws 
1058*265Smws 	for (wp = kernel_walkers; wp->walk_name != NULL; wp++)
1059*265Smws 		kw++; /* count common walkers */
1060*265Smws #endif
1061*265Smws 
1062*265Smws 	modinfo.mi_dcmds = mdb_zalloc(sizeof (*dp) * (d + kd + 1), UM_SLEEP);
1063*265Smws 	modinfo.mi_walkers = mdb_zalloc(sizeof (*wp) * (w + kw + 1), UM_SLEEP);
1064*265Smws 
1065*265Smws 	bcopy(common_dcmds, (void *)modinfo.mi_dcmds, sizeof (*dp) * d);
1066*265Smws 	bcopy(common_walkers, (void *)modinfo.mi_walkers, sizeof (*wp) * w);
1067*265Smws 
1068*265Smws #ifdef _KERNEL
1069*265Smws 	bcopy(kernel_dcmds, (void *)
1070*265Smws 	    (modinfo.mi_dcmds + d), sizeof (*dp) * kd);
1071*265Smws 	bcopy(kernel_walkers, (void *)
1072*265Smws 	    (modinfo.mi_walkers + w), sizeof (*wp) * kw);
1073*265Smws #endif
1074*265Smws 	return (&modinfo);
1075*265Smws }
1076*265Smws 
1077*265Smws void
1078*265Smws _mdb_fini(void)
1079*265Smws {
1080*265Smws 	const mdb_walker_t *wp;
1081*265Smws 	const mdb_dcmd_t *dp;
1082*265Smws 	uint_t d = 0, w = 0;
1083*265Smws 
1084*265Smws 	for (dp = modinfo.mi_dcmds; dp->dc_name != NULL; dp++)
1085*265Smws 		d++;
1086*265Smws 
1087*265Smws 	for (wp = modinfo.mi_walkers; wp->walk_name != NULL; wp++)
1088*265Smws 		w++;
1089*265Smws 
1090*265Smws 	mdb_free((void *)modinfo.mi_dcmds, sizeof (*dp) * (d + 1));
1091*265Smws 	mdb_free((void *)modinfo.mi_walkers, sizeof (*wp) * (w + 1));
1092*265Smws }
1093