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