xref: /onnv-gate/usr/src/cmd/mdb/common/modules/mdb_ds/mdb_ds.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * MDB developer support module.  This module is loaded automatically when the
31*0Sstevel@tonic-gate  * proc target is initialized and the target is mdb itself.  In the future, we
32*0Sstevel@tonic-gate  * should document these facilities in the answerbook to aid module developers.
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate /*
36*0Sstevel@tonic-gate  * The mere inclusion of sys/utsname.h causes _uname() and uname() to be
37*0Sstevel@tonic-gate  * defined on Intel, along with an external reference to _nuname().  Since we
38*0Sstevel@tonic-gate  * don't actually use uname (or utsname, for that matter) in this dmod, we'll
39*0Sstevel@tonic-gate  * prevent its inclusion.
40*0Sstevel@tonic-gate  */
41*0Sstevel@tonic-gate #define	_SYS_UTSNAME_H
42*0Sstevel@tonic-gate struct utsname;
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate #define	_MDB
45*0Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
46*0Sstevel@tonic-gate #include <mdb/mdb_frame.h>
47*0Sstevel@tonic-gate #include <mdb/mdb_io_impl.h>
48*0Sstevel@tonic-gate #include <mdb/mdb_target_impl.h>
49*0Sstevel@tonic-gate #include <kmdb/kmdb_wr_impl.h>
50*0Sstevel@tonic-gate #include <mdb/mdb.h>
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate static const mdb_t *
get_mdb(void)53*0Sstevel@tonic-gate get_mdb(void)
54*0Sstevel@tonic-gate {
55*0Sstevel@tonic-gate 	static mdb_t m;
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate 	if (mdb_readvar(&m, "mdb") == -1)
58*0Sstevel@tonic-gate 		mdb_warn("failed to read mdb_t state");
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 	return (&m);
61*0Sstevel@tonic-gate }
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate static int
cmd_stack(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)64*0Sstevel@tonic-gate cmd_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
65*0Sstevel@tonic-gate {
66*0Sstevel@tonic-gate 	const char sep[] =
67*0Sstevel@tonic-gate 	    "-----------------------------------------------------------------";
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC) {
70*0Sstevel@tonic-gate 		char buf[MDB_NV_NAMELEN + 1];
71*0Sstevel@tonic-gate 		uintptr_t sp, pc;
72*0Sstevel@tonic-gate 		mdb_idcmd_t idc;
73*0Sstevel@tonic-gate 		mdb_frame_t f;
74*0Sstevel@tonic-gate 		mdb_cmd_t c;
75*0Sstevel@tonic-gate 		mdb_arg_t *ap;
76*0Sstevel@tonic-gate 		size_t i;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 		if (mdb_vread(&f, sizeof (f), addr) == -1) {
79*0Sstevel@tonic-gate 			mdb_warn("failed to read frame at %p", addr);
80*0Sstevel@tonic-gate 			return (DCMD_ERR);
81*0Sstevel@tonic-gate 		}
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 		bzero(&c, sizeof (mdb_cmd_t));
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 		if (mdb_vread(&c, sizeof (c), (uintptr_t)f.f_cp) < 0 ||
86*0Sstevel@tonic-gate 		    mdb_vread(&idc, sizeof (idc), (uintptr_t)c.c_dcmd) < 0 ||
87*0Sstevel@tonic-gate 		    mdb_readstr(buf, sizeof (buf), (uintptr_t)idc.idc_name) < 1)
88*0Sstevel@tonic-gate 			(void) strcpy(buf, "?");
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 		mdb_printf("+>\tframe <%u> %p (%s", f.f_id, addr, buf);
91*0Sstevel@tonic-gate 		ap = mdb_alloc(c.c_argv.a_nelems * sizeof (mdb_arg_t), UM_GC);
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 		if (ap != NULL && mdb_vread(ap, c.c_argv.a_nelems *
94*0Sstevel@tonic-gate 		    sizeof (mdb_arg_t), (uintptr_t)c.c_argv.a_data) > 0) {
95*0Sstevel@tonic-gate 			for (i = 0; i < c.c_argv.a_nelems; i++) {
96*0Sstevel@tonic-gate 				switch (ap[i].a_type) {
97*0Sstevel@tonic-gate 				case MDB_TYPE_STRING:
98*0Sstevel@tonic-gate 					if (mdb_readstr(buf, sizeof (buf),
99*0Sstevel@tonic-gate 					    (uintptr_t)ap[i].a_un.a_str) > 0)
100*0Sstevel@tonic-gate 						mdb_printf(" %s", buf);
101*0Sstevel@tonic-gate 					else
102*0Sstevel@tonic-gate 						mdb_printf(" <str=%a>",
103*0Sstevel@tonic-gate 						    ap[i].a_un.a_str);
104*0Sstevel@tonic-gate 					break;
105*0Sstevel@tonic-gate 				case MDB_TYPE_IMMEDIATE:
106*0Sstevel@tonic-gate 					mdb_printf(" $[ 0x%llx ]",
107*0Sstevel@tonic-gate 					    ap[i].a_un.a_val);
108*0Sstevel@tonic-gate 					break;
109*0Sstevel@tonic-gate 				case MDB_TYPE_CHAR:
110*0Sstevel@tonic-gate 					mdb_printf(" '%c'", ap[i].a_un.a_char);
111*0Sstevel@tonic-gate 					break;
112*0Sstevel@tonic-gate 				default:
113*0Sstevel@tonic-gate 					mdb_printf(" <type=%d>", ap[i].a_type);
114*0Sstevel@tonic-gate 				}
115*0Sstevel@tonic-gate 			}
116*0Sstevel@tonic-gate 		}
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 		mdb_printf(")\n\tf_list = %-?p\tf_cmds = %p\n",
119*0Sstevel@tonic-gate 		    addr + OFFSETOF(mdb_frame_t, f_list),
120*0Sstevel@tonic-gate 		    addr + OFFSETOF(mdb_frame_t, f_cmds));
121*0Sstevel@tonic-gate 		mdb_printf("\tf_istk = %-?p\tf_ostk = %p\n",
122*0Sstevel@tonic-gate 		    addr + OFFSETOF(mdb_frame_t, f_istk),
123*0Sstevel@tonic-gate 		    addr + OFFSETOF(mdb_frame_t, f_ostk));
124*0Sstevel@tonic-gate 		mdb_printf("\tf_wcbs = %-?p\tf_mblks = %p\n",
125*0Sstevel@tonic-gate 		    f.f_wcbs, f.f_mblks);
126*0Sstevel@tonic-gate 		mdb_printf("\tf_pcmd = %-?p\tf_pcb = %p\n",
127*0Sstevel@tonic-gate 		    f.f_pcmd, addr + OFFSETOF(mdb_frame_t, f_pcb));
128*0Sstevel@tonic-gate 		mdb_printf("\tf_cp = %-?p\t\tf_flags = 0x%x\n\n",
129*0Sstevel@tonic-gate 		    f.f_cp, f.f_flags);
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate #if defined(__sparc)
132*0Sstevel@tonic-gate 		sp = ((uintptr_t *)f.f_pcb)[1];
133*0Sstevel@tonic-gate 		pc = ((uintptr_t *)f.f_pcb)[2];
134*0Sstevel@tonic-gate #elif defined(__amd64)
135*0Sstevel@tonic-gate 		sp = ((uintptr_t *)f.f_pcb)[5];
136*0Sstevel@tonic-gate 		pc = ((uintptr_t *)f.f_pcb)[7];
137*0Sstevel@tonic-gate #elif defined(__i386)
138*0Sstevel@tonic-gate 		sp = ((uintptr_t *)f.f_pcb)[3];
139*0Sstevel@tonic-gate 		pc = ((uintptr_t *)f.f_pcb)[5];
140*0Sstevel@tonic-gate #else
141*0Sstevel@tonic-gate #error	Unknown ISA
142*0Sstevel@tonic-gate #endif
143*0Sstevel@tonic-gate 		if (pc != 0)
144*0Sstevel@tonic-gate 			mdb_printf("      [ %0?lr %a() ]\n", sp, pc);
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 		mdb_set_dot(sp);
147*0Sstevel@tonic-gate 		mdb_inc_indent(8);
148*0Sstevel@tonic-gate 		mdb_eval("<.$C0");
149*0Sstevel@tonic-gate 		mdb_dec_indent(8);
150*0Sstevel@tonic-gate 		mdb_printf("%s\n", sep);
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	} else {
153*0Sstevel@tonic-gate 		mdb_printf("%s\n", sep);
154*0Sstevel@tonic-gate 		(void) mdb_walk_dcmd("mdb_frame", "mdb_stack", argc, argv);
155*0Sstevel@tonic-gate 	}
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	return (DCMD_OK);
158*0Sstevel@tonic-gate }
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate static int
cmd_frame(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)161*0Sstevel@tonic-gate cmd_frame(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
162*0Sstevel@tonic-gate {
163*0Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) && argc == 0)
164*0Sstevel@tonic-gate 		return (cmd_stack(addr, flags, argc, argv));
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	return (DCMD_USAGE);
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate /*ARGSUSED*/
170*0Sstevel@tonic-gate static int
cmd_iob(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)171*0Sstevel@tonic-gate cmd_iob(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
172*0Sstevel@tonic-gate {
173*0Sstevel@tonic-gate 	mdb_iob_t iob;
174*0Sstevel@tonic-gate 	mdb_io_t io;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC) || argc != 0)
177*0Sstevel@tonic-gate 		return (DCMD_USAGE);
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
180*0Sstevel@tonic-gate 		mdb_printf("%?s %6s %6s %?s %s\n",
181*0Sstevel@tonic-gate 		    "IOB", "NBYTES", "FLAGS", "IOP", "OPS");
182*0Sstevel@tonic-gate 	}
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	if (mdb_vread(&iob, sizeof (iob), addr) == -1 ||
185*0Sstevel@tonic-gate 	    mdb_vread(&io, sizeof (io), (uintptr_t)iob.iob_iop) == -1) {
186*0Sstevel@tonic-gate 		mdb_warn("failed to read iob at %p", addr);
187*0Sstevel@tonic-gate 		return (DCMD_ERR);
188*0Sstevel@tonic-gate 	}
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 	mdb_printf("%?p %6lu %6x %?p %a\n", addr, (ulong_t)iob.iob_nbytes,
191*0Sstevel@tonic-gate 	    iob.iob_flags, iob.iob_iop, io.io_ops);
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	return (DCMD_OK);
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate /*ARGSUSED*/
197*0Sstevel@tonic-gate static int
cmd_in(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)198*0Sstevel@tonic-gate cmd_in(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
199*0Sstevel@tonic-gate {
200*0Sstevel@tonic-gate 	mdb_printf("%p\n", get_mdb()->m_in);
201*0Sstevel@tonic-gate 	return (DCMD_OK);
202*0Sstevel@tonic-gate }
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate /*ARGSUSED*/
205*0Sstevel@tonic-gate static int
cmd_out(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)206*0Sstevel@tonic-gate cmd_out(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
207*0Sstevel@tonic-gate {
208*0Sstevel@tonic-gate 	mdb_printf("%p\n", get_mdb()->m_out);
209*0Sstevel@tonic-gate 	return (DCMD_OK);
210*0Sstevel@tonic-gate }
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate /*ARGSUSED*/
213*0Sstevel@tonic-gate static int
cmd_err(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)214*0Sstevel@tonic-gate cmd_err(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
215*0Sstevel@tonic-gate {
216*0Sstevel@tonic-gate 	mdb_printf("%p\n", get_mdb()->m_err);
217*0Sstevel@tonic-gate 	return (DCMD_OK);
218*0Sstevel@tonic-gate }
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate /*ARGSUSED*/
221*0Sstevel@tonic-gate static int
cmd_target(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)222*0Sstevel@tonic-gate cmd_target(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
223*0Sstevel@tonic-gate {
224*0Sstevel@tonic-gate 	mdb_tgt_t t;
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	if (argc != 0)
227*0Sstevel@tonic-gate 		return (DCMD_USAGE);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
230*0Sstevel@tonic-gate 		addr = (uintptr_t)get_mdb()->m_target;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	if (mdb_vread(&t, sizeof (t), addr) != sizeof (t)) {
233*0Sstevel@tonic-gate 		mdb_warn("failed to read target at %p", addr);
234*0Sstevel@tonic-gate 		return (DCMD_ERR);
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	mdb_printf("+>\ttarget %p (%a)\n", addr, t.t_ops);
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	mdb_printf("\tt_active = %-?p\tt_idle = %p\n",
240*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_tgt_t, t_active),
241*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_tgt_t, t_idle));
242*0Sstevel@tonic-gate 	mdb_printf("\tt_xdlist = %-?p\tt_module = %a\n",
243*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_tgt_t, t_xdlist), t.t_module);
244*0Sstevel@tonic-gate 	mdb_printf("\tt_pshandle = %-?p\tt_data = %p\n",
245*0Sstevel@tonic-gate 	    t.t_pshandle, t.t_data);
246*0Sstevel@tonic-gate 	mdb_printf("\tt_status = %-?p\tt_matched = %p\n",
247*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_tgt_t, t_status), t.t_matched);
248*0Sstevel@tonic-gate 	mdb_printf("\tt_flags = %-?x\tt_vecnt = 0t%u\n", t.t_flags, t.t_vecnt);
249*0Sstevel@tonic-gate 	mdb_printf("\tt_vepos = %-?d\tt_veneg = %d\n\n", t.t_vepos, t.t_veneg);
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	return (DCMD_OK);
252*0Sstevel@tonic-gate }
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate /*ARGSUSED*/
255*0Sstevel@tonic-gate static int
cmd_sespec(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)256*0Sstevel@tonic-gate cmd_sespec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
257*0Sstevel@tonic-gate {
258*0Sstevel@tonic-gate 	mdb_sespec_t se;
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
261*0Sstevel@tonic-gate 		return (DCMD_USAGE);
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 	if (mdb_vread(&se, sizeof (se), addr) != sizeof (se)) {
264*0Sstevel@tonic-gate 		mdb_warn("failed to read sespec at %p", addr);
265*0Sstevel@tonic-gate 		return (DCMD_ERR);
266*0Sstevel@tonic-gate 	}
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 	mdb_printf("+>\tsespec %p (%a)\n", addr, se.se_ops);
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	mdb_printf("\tse_selist = %-?p\tse_velist = %p\n",
271*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_sespec_t, se_selist),
272*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_sespec_t, se_velist));
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	mdb_printf("\tse_data = %-?p\tse_refs = %u\n",
275*0Sstevel@tonic-gate 	    se.se_data, se.se_refs);
276*0Sstevel@tonic-gate 	mdb_printf("\tse_state = %-?d\tse_errno = %d\n\n",
277*0Sstevel@tonic-gate 	    se.se_state, se.se_errno);
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	return (DCMD_OK);
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate /*ARGSUSED*/
283*0Sstevel@tonic-gate static int
cmd_vespec(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)284*0Sstevel@tonic-gate cmd_vespec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
285*0Sstevel@tonic-gate {
286*0Sstevel@tonic-gate 	mdb_vespec_t ve;
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
289*0Sstevel@tonic-gate 		return (DCMD_USAGE);
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 	if (mdb_vread(&ve, sizeof (ve), addr) != sizeof (ve)) {
292*0Sstevel@tonic-gate 		mdb_warn("failed to read vespec at %p", addr);
293*0Sstevel@tonic-gate 		return (DCMD_ERR);
294*0Sstevel@tonic-gate 	}
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	mdb_printf("+>\tvespec %p (id %d)\n", addr, ve.ve_id);
297*0Sstevel@tonic-gate 	mdb_printf("\tve_list = %-?p\tve_flags = 0x%x\n",
298*0Sstevel@tonic-gate 	    addr + OFFSETOF(mdb_vespec_t, ve_list), ve.ve_flags);
299*0Sstevel@tonic-gate 	mdb_printf("\tve_se = %-?p\tve_refs = %u\n", ve.ve_se, ve.ve_refs);
300*0Sstevel@tonic-gate 	mdb_printf("\tve_hits = %-?u\tve_lim = %u\n", ve.ve_hits, ve.ve_limit);
301*0Sstevel@tonic-gate 	mdb_printf("\tve_data = %-?p\tve_callback = %a\n",
302*0Sstevel@tonic-gate 	    ve.ve_data, ve.ve_callback);
303*0Sstevel@tonic-gate 	mdb_printf("\tve_args = %-?p\tve_dtor = %a\n\n",
304*0Sstevel@tonic-gate 	    ve.ve_args, ve.ve_dtor);
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	return (DCMD_OK);
307*0Sstevel@tonic-gate }
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate /*ARGSUSED*/
310*0Sstevel@tonic-gate static int
cmd_wr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)311*0Sstevel@tonic-gate cmd_wr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
312*0Sstevel@tonic-gate {
313*0Sstevel@tonic-gate 	char path[MAXPATHLEN];
314*0Sstevel@tonic-gate 	kmdb_wr_t wn;
315*0Sstevel@tonic-gate 	char dir;
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
318*0Sstevel@tonic-gate 		return (DCMD_USAGE);
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 	if (mdb_vread(&wn, sizeof (wn), addr) != sizeof (wn)) {
321*0Sstevel@tonic-gate 		mdb_warn("failed to read wr node at %p", addr);
322*0Sstevel@tonic-gate 		return (DCMD_ERR);
323*0Sstevel@tonic-gate 	}
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
326*0Sstevel@tonic-gate 		mdb_printf("%-9s %3s %?s %s\n",
327*0Sstevel@tonic-gate 		    "COMMAND", "ERR", "MODCTL", "NAME");
328*0Sstevel@tonic-gate 	}
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	dir = "><"[WR_ISACK(&wn) != 0];
331*0Sstevel@tonic-gate 	switch (WR_TASK(&wn)) {
332*0Sstevel@tonic-gate 	case WNTASK_DMOD_LOAD: {
333*0Sstevel@tonic-gate 		kmdb_wr_load_t dlr;
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 		if (mdb_vread(&dlr, sizeof (dlr), addr) != sizeof (dlr)) {
336*0Sstevel@tonic-gate 			mdb_warn("failed to read kmdb_wr_load_t at %p", addr);
337*0Sstevel@tonic-gate 			return (DCMD_ERR);
338*0Sstevel@tonic-gate 		}
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 		if (mdb_readstr(path, sizeof (path),
341*0Sstevel@tonic-gate 		    (uintptr_t)dlr.dlr_fname) < 0) {
342*0Sstevel@tonic-gate 			mdb_warn("failed to read path name at %p",
343*0Sstevel@tonic-gate 			    dlr.dlr_fname);
344*0Sstevel@tonic-gate 			*path = '\0';
345*0Sstevel@tonic-gate 		}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 		mdb_printf("%cload     %3d %?p %s\n", dir, dlr.dlr_errno,
348*0Sstevel@tonic-gate 		    dlr.dlr_modctl, path);
349*0Sstevel@tonic-gate 		break;
350*0Sstevel@tonic-gate 	}
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 	case WNTASK_DMOD_LOAD_ALL:
353*0Sstevel@tonic-gate 		mdb_printf("%cload all %3d\n", dir, wn.wn_errno);
354*0Sstevel@tonic-gate 		break;
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	case WNTASK_DMOD_UNLOAD: {
357*0Sstevel@tonic-gate 		kmdb_wr_unload_t dur;
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 		if (mdb_vread(&dur, sizeof (dur), addr) != sizeof (dur)) {
360*0Sstevel@tonic-gate 			mdb_warn("failed to read kmdb_wr_unload_t at %p", addr);
361*0Sstevel@tonic-gate 			return (DCMD_ERR);
362*0Sstevel@tonic-gate 		}
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 		if (mdb_readstr(path, sizeof (path),
365*0Sstevel@tonic-gate 		    (uintptr_t)dur.dur_modname) < 0) {
366*0Sstevel@tonic-gate 			mdb_warn("failed to read module name at %p",
367*0Sstevel@tonic-gate 			    dur.dur_modname);
368*0Sstevel@tonic-gate 			*path = '\0';
369*0Sstevel@tonic-gate 		}
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 		mdb_printf("%cunload   %3d %?p %s\n", dir, dur.dur_errno,
372*0Sstevel@tonic-gate 		    dur.dur_modctl, path);
373*0Sstevel@tonic-gate 		break;
374*0Sstevel@tonic-gate 	}
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 	case WNTASK_DMOD_PATH_CHANGE: {
377*0Sstevel@tonic-gate 		kmdb_wr_path_t dpth;
378*0Sstevel@tonic-gate 		uintptr_t pathp;
379*0Sstevel@tonic-gate 		int first = 1;
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate 		if (mdb_vread(&dpth, sizeof (dpth), addr) != sizeof (dpth)) {
382*0Sstevel@tonic-gate 			mdb_warn("failed to read kmdb_wr_path_t at %p", addr);
383*0Sstevel@tonic-gate 			return (DCMD_ERR);
384*0Sstevel@tonic-gate 		}
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 		mdb_printf("%cpath chg %3d ", dir, dpth.dpth_errno);
387*0Sstevel@tonic-gate 		for (;;) {
388*0Sstevel@tonic-gate 			if (mdb_vread(&pathp, sizeof (pathp),
389*0Sstevel@tonic-gate 			    (uintptr_t)dpth.dpth_path) != sizeof (pathp)) {
390*0Sstevel@tonic-gate 				mdb_warn("failed to read path pointer at %p",
391*0Sstevel@tonic-gate 				    dpth.dpth_path);
392*0Sstevel@tonic-gate 				break;
393*0Sstevel@tonic-gate 			}
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 			dpth.dpth_path++;
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 			if (pathp == NULL)
398*0Sstevel@tonic-gate 				break;
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 			if (mdb_readstr(path, sizeof (path), pathp) < 0) {
401*0Sstevel@tonic-gate 				mdb_warn("failed to read path at %p", pathp);
402*0Sstevel@tonic-gate 				*path = '\0';
403*0Sstevel@tonic-gate 			}
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 			mdb_printf("%s%s", (first ? "" : "\n             "),
406*0Sstevel@tonic-gate 			    path);
407*0Sstevel@tonic-gate 			first = 0;
408*0Sstevel@tonic-gate 		}
409*0Sstevel@tonic-gate 		mdb_printf("\n");
410*0Sstevel@tonic-gate 		break;
411*0Sstevel@tonic-gate 	}
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	default:
414*0Sstevel@tonic-gate 		mdb_warn("unknown task type %d\n", wn.wn_task);
415*0Sstevel@tonic-gate 		return (DCMD_ERR);
416*0Sstevel@tonic-gate 	}
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate 	return (DCMD_OK);
419*0Sstevel@tonic-gate }
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate static int
iob_stack_walk_init(mdb_walk_state_t * wsp)422*0Sstevel@tonic-gate iob_stack_walk_init(mdb_walk_state_t *wsp)
423*0Sstevel@tonic-gate {
424*0Sstevel@tonic-gate 	mdb_iob_stack_t stk;
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	if (mdb_vread(&stk, sizeof (stk), wsp->walk_addr) == -1) {
427*0Sstevel@tonic-gate 		mdb_warn("failed to read iob_stack at %p", wsp->walk_addr);
428*0Sstevel@tonic-gate 		return (WALK_ERR);
429*0Sstevel@tonic-gate 	}
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)stk.stk_top;
432*0Sstevel@tonic-gate 	return (WALK_NEXT);
433*0Sstevel@tonic-gate }
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate static int
iob_stack_walk_step(mdb_walk_state_t * wsp)436*0Sstevel@tonic-gate iob_stack_walk_step(mdb_walk_state_t *wsp)
437*0Sstevel@tonic-gate {
438*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
439*0Sstevel@tonic-gate 	mdb_iob_t iob;
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	if (addr == NULL)
442*0Sstevel@tonic-gate 		return (WALK_DONE);
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 	if (mdb_vread(&iob, sizeof (iob), addr) == -1) {
445*0Sstevel@tonic-gate 		mdb_warn("failed to read iob at %p", addr);
446*0Sstevel@tonic-gate 		return (WALK_ERR);
447*0Sstevel@tonic-gate 	}
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)iob.iob_next;
450*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &iob, wsp->walk_cbdata));
451*0Sstevel@tonic-gate }
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate static int
frame_walk_init(mdb_walk_state_t * wsp)454*0Sstevel@tonic-gate frame_walk_init(mdb_walk_state_t *wsp)
455*0Sstevel@tonic-gate {
456*0Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
457*0Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)get_mdb()->m_flist.ml_prev;
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 	return (WALK_NEXT);
460*0Sstevel@tonic-gate }
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate static int
frame_walk_step(mdb_walk_state_t * wsp)463*0Sstevel@tonic-gate frame_walk_step(mdb_walk_state_t *wsp)
464*0Sstevel@tonic-gate {
465*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
466*0Sstevel@tonic-gate 	mdb_frame_t f;
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 	if (addr == NULL)
469*0Sstevel@tonic-gate 		return (WALK_DONE);
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 	if (mdb_vread(&f, sizeof (f), addr) == -1) {
472*0Sstevel@tonic-gate 		mdb_warn("failed to read frame at %p", addr);
473*0Sstevel@tonic-gate 		return (WALK_ERR);
474*0Sstevel@tonic-gate 	}
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)f.f_list.ml_prev;
477*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &f, wsp->walk_cbdata));
478*0Sstevel@tonic-gate }
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate static int
target_walk_init(mdb_walk_state_t * wsp)481*0Sstevel@tonic-gate target_walk_init(mdb_walk_state_t *wsp)
482*0Sstevel@tonic-gate {
483*0Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
484*0Sstevel@tonic-gate 		wsp->walk_addr = (uintptr_t)get_mdb()->m_target;
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	return (WALK_NEXT);
487*0Sstevel@tonic-gate }
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate static int
target_walk_step(mdb_walk_state_t * wsp)490*0Sstevel@tonic-gate target_walk_step(mdb_walk_state_t *wsp)
491*0Sstevel@tonic-gate {
492*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
493*0Sstevel@tonic-gate 	mdb_tgt_t t;
494*0Sstevel@tonic-gate 
495*0Sstevel@tonic-gate 	if (addr == NULL)
496*0Sstevel@tonic-gate 		return (WALK_DONE);
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate 	if (mdb_vread(&t, sizeof (t), addr) == -1) {
499*0Sstevel@tonic-gate 		mdb_warn("failed to read target at %p", addr);
500*0Sstevel@tonic-gate 		return (WALK_ERR);
501*0Sstevel@tonic-gate 	}
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)t.t_tgtlist.ml_next;
504*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &t, wsp->walk_cbdata));
505*0Sstevel@tonic-gate }
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate static int
sespec_walk_step(mdb_walk_state_t * wsp)508*0Sstevel@tonic-gate sespec_walk_step(mdb_walk_state_t *wsp)
509*0Sstevel@tonic-gate {
510*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
511*0Sstevel@tonic-gate 	mdb_sespec_t s;
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 	if (addr == NULL)
514*0Sstevel@tonic-gate 		return (WALK_DONE);
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 	if (mdb_vread(&s, sizeof (s), addr) == -1) {
517*0Sstevel@tonic-gate 		mdb_warn("failed to read sespec at %p", addr);
518*0Sstevel@tonic-gate 		return (WALK_ERR);
519*0Sstevel@tonic-gate 	}
520*0Sstevel@tonic-gate 
521*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)s.se_selist.ml_next;
522*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &s, wsp->walk_cbdata));
523*0Sstevel@tonic-gate }
524*0Sstevel@tonic-gate 
525*0Sstevel@tonic-gate static int
vespec_walk_step(mdb_walk_state_t * wsp)526*0Sstevel@tonic-gate vespec_walk_step(mdb_walk_state_t *wsp)
527*0Sstevel@tonic-gate {
528*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
529*0Sstevel@tonic-gate 	mdb_vespec_t v;
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	if (addr == NULL)
532*0Sstevel@tonic-gate 		return (WALK_DONE);
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate 	if (mdb_vread(&v, sizeof (v), addr) == -1) {
535*0Sstevel@tonic-gate 		mdb_warn("failed to read vespec at %p", addr);
536*0Sstevel@tonic-gate 		return (WALK_ERR);
537*0Sstevel@tonic-gate 	}
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)v.ve_list.ml_next;
540*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &v, wsp->walk_cbdata));
541*0Sstevel@tonic-gate }
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate static int
se_matched_walk_step(mdb_walk_state_t * wsp)544*0Sstevel@tonic-gate se_matched_walk_step(mdb_walk_state_t *wsp)
545*0Sstevel@tonic-gate {
546*0Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
547*0Sstevel@tonic-gate 	mdb_sespec_t s;
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 	if (addr == NULL)
550*0Sstevel@tonic-gate 		return (WALK_DONE);
551*0Sstevel@tonic-gate 
552*0Sstevel@tonic-gate 	if (mdb_vread(&s, sizeof (s), addr) == -1) {
553*0Sstevel@tonic-gate 		mdb_warn("failed to read sespec at %p", addr);
554*0Sstevel@tonic-gate 		return (WALK_ERR);
555*0Sstevel@tonic-gate 	}
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)s.se_matched;
558*0Sstevel@tonic-gate 	return (wsp->walk_callback(addr, &s, wsp->walk_cbdata));
559*0Sstevel@tonic-gate }
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
562*0Sstevel@tonic-gate 	{ "mdb_stack", "?", "print debugger stack", cmd_stack },
563*0Sstevel@tonic-gate 	{ "mdb_frame", ":", "print debugger frame", cmd_frame },
564*0Sstevel@tonic-gate 	{ "mdb_iob", ":", "print i/o buffer information", cmd_iob },
565*0Sstevel@tonic-gate 	{ "mdb_in", NULL, "print stdin iob", cmd_in },
566*0Sstevel@tonic-gate 	{ "mdb_out", NULL, "print stdout iob", cmd_out },
567*0Sstevel@tonic-gate 	{ "mdb_err", NULL, "print stderr iob", cmd_err },
568*0Sstevel@tonic-gate 	{ "mdb_tgt", "?", "print current target", cmd_target },
569*0Sstevel@tonic-gate 	{ "mdb_sespec", ":", "print software event specifier", cmd_sespec },
570*0Sstevel@tonic-gate 	{ "mdb_vespec", ":", "print virtual event specifier", cmd_vespec },
571*0Sstevel@tonic-gate 	{ "kmdb_wr", NULL, "print a work queue entry", cmd_wr },
572*0Sstevel@tonic-gate 	{ NULL }
573*0Sstevel@tonic-gate };
574*0Sstevel@tonic-gate 
575*0Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
576*0Sstevel@tonic-gate 	{ "mdb_frame", "iterate over mdb_frame stack",
577*0Sstevel@tonic-gate 		frame_walk_init, frame_walk_step, NULL },
578*0Sstevel@tonic-gate 	{ "mdb_iob_stack", "iterate over mdb_iob_stack elements",
579*0Sstevel@tonic-gate 		iob_stack_walk_init, iob_stack_walk_step, NULL },
580*0Sstevel@tonic-gate 	{ "mdb_tgt", "iterate over active targets",
581*0Sstevel@tonic-gate 		target_walk_init, target_walk_step, NULL },
582*0Sstevel@tonic-gate 	{ "mdb_sespec", "iterate over software event specifiers",
583*0Sstevel@tonic-gate 		NULL, sespec_walk_step, NULL },
584*0Sstevel@tonic-gate 	{ "mdb_vespec", "iterate over virtual event specifiers",
585*0Sstevel@tonic-gate 		NULL, vespec_walk_step, NULL },
586*0Sstevel@tonic-gate 	{ "se_matched", "iterate over matched software event specifiers",
587*0Sstevel@tonic-gate 		NULL, se_matched_walk_step, NULL },
588*0Sstevel@tonic-gate 	{ NULL }
589*0Sstevel@tonic-gate };
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate const mdb_modinfo_t *
_mdb_init(void)594*0Sstevel@tonic-gate _mdb_init(void)
595*0Sstevel@tonic-gate {
596*0Sstevel@tonic-gate 	char buf[256];
597*0Sstevel@tonic-gate 	uintptr_t addr;
598*0Sstevel@tonic-gate 	int rcount;
599*0Sstevel@tonic-gate 	GElf_Sym sym;
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate 	if (mdb_lookup_by_name("mdb", &sym) == -1) {
602*0Sstevel@tonic-gate 		mdb_warn("failed to read mdb state structure");
603*0Sstevel@tonic-gate 		return (NULL);
604*0Sstevel@tonic-gate 	}
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	if (sym.st_size != sizeof (mdb_t)) {
607*0Sstevel@tonic-gate 		mdb_printf("mdb: WARNING: mdb_ds may not match mdb "
608*0Sstevel@tonic-gate 		    "implementation (mdb_t mismatch)\n");
609*0Sstevel@tonic-gate 	}
610*0Sstevel@tonic-gate 
611*0Sstevel@tonic-gate 	if (mdb_readvar(&addr, "_mdb_abort_str") != -1 && addr != NULL &&
612*0Sstevel@tonic-gate 	    mdb_readstr(buf, sizeof (buf), addr) > 0)
613*0Sstevel@tonic-gate 		mdb_printf("mdb: debugger failed with error: %s\n", buf);
614*0Sstevel@tonic-gate 
615*0Sstevel@tonic-gate 	if (mdb_readvar(&rcount, "_mdb_abort_rcount") != -1 && rcount != 0)
616*0Sstevel@tonic-gate 		mdb_printf("mdb: WARNING: resume executed %d times\n", rcount);
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	return (&modinfo);
619*0Sstevel@tonic-gate }
620