4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * MDB developer support module. This module is loaded automatically when the
29 * proc target is initialized and the target is mdb itself. In the future, we
30 * should document these facilities in the answerbook to aid module developers.
34 #include <mdb/mdb_modapi.h>
35 #include <mdb/mdb_frame.h>
36 #include <mdb/mdb_io_impl.h>
37 #include <mdb/mdb_target_impl.h>
38 #include <kmdb/kmdb_wr_impl.h>
46 if (mdb_readvar(&m
, "mdb") == -1)
47 mdb_warn("failed to read mdb_t state");
53 cmd_stack(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
56 "-----------------------------------------------------------------";
58 if (flags
& DCMD_ADDRSPEC
) {
59 char buf
[MDB_NV_NAMELEN
+ 1];
67 if (mdb_vread(&f
, sizeof (f
), addr
) == -1) {
68 mdb_warn("failed to read frame at %p", addr
);
72 bzero(&c
, sizeof (mdb_cmd_t
));
74 if (mdb_vread(&c
, sizeof (c
), (uintptr_t)f
.f_cp
) < 0 ||
75 mdb_vread(&idc
, sizeof (idc
), (uintptr_t)c
.c_dcmd
) < 0 ||
76 mdb_readstr(buf
, sizeof (buf
), (uintptr_t)idc
.idc_name
) < 1)
77 (void) strcpy(buf
, "?");
79 mdb_printf("+>\tframe <%u> %p (%s", f
.f_id
, addr
, buf
);
80 ap
= mdb_alloc(c
.c_argv
.a_nelems
* sizeof (mdb_arg_t
), UM_GC
);
82 if (ap
!= NULL
&& mdb_vread(ap
, c
.c_argv
.a_nelems
*
83 sizeof (mdb_arg_t
), (uintptr_t)c
.c_argv
.a_data
) > 0) {
84 for (i
= 0; i
< c
.c_argv
.a_nelems
; i
++) {
85 switch (ap
[i
].a_type
) {
87 if (mdb_readstr(buf
, sizeof (buf
),
88 (uintptr_t)ap
[i
].a_un
.a_str
) > 0)
89 mdb_printf(" %s", buf
);
91 mdb_printf(" <str=%a>",
94 case MDB_TYPE_IMMEDIATE
:
95 mdb_printf(" $[ 0x%llx ]",
99 mdb_printf(" '%c'", ap
[i
].a_un
.a_char
);
102 mdb_printf(" <type=%d>", ap
[i
].a_type
);
107 mdb_printf(")\n\tf_list = %-?p\tf_cmds = %p\n",
108 addr
+ OFFSETOF(mdb_frame_t
, f_list
),
109 addr
+ OFFSETOF(mdb_frame_t
, f_cmds
));
110 mdb_printf("\tf_istk = %-?p\tf_ostk = %p\n",
111 addr
+ OFFSETOF(mdb_frame_t
, f_istk
),
112 addr
+ OFFSETOF(mdb_frame_t
, f_ostk
));
113 mdb_printf("\tf_wcbs = %-?p\tf_mblks = %p\n",
114 f
.f_wcbs
, f
.f_mblks
);
115 mdb_printf("\tf_pcmd = %-?p\tf_pcb = %p\n",
116 f
.f_pcmd
, addr
+ OFFSETOF(mdb_frame_t
, f_pcb
));
117 mdb_printf("\tf_cp = %-?p\t\tf_flags = 0x%x\n\n",
121 sp
= ((uintptr_t *)f
.f_pcb
)[1];
122 pc
= ((uintptr_t *)f
.f_pcb
)[2];
123 #elif defined(__amd64)
124 sp
= ((uintptr_t *)f
.f_pcb
)[5];
125 pc
= ((uintptr_t *)f
.f_pcb
)[7];
126 #elif defined(__i386)
127 sp
= ((uintptr_t *)f
.f_pcb
)[3];
128 pc
= ((uintptr_t *)f
.f_pcb
)[5];
133 mdb_printf(" [ %0?lr %a() ]\n", sp
, pc
);
139 mdb_printf("%s\n", sep
);
142 mdb_printf("%s\n", sep
);
143 (void) mdb_walk_dcmd("mdb_frame", "mdb_stack", argc
, argv
);
150 cmd_frame(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
152 if ((flags
& DCMD_ADDRSPEC
) && argc
== 0)
153 return (cmd_stack(addr
, flags
, argc
, argv
));
160 cmd_iob(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
165 if (!(flags
& DCMD_ADDRSPEC
) || argc
!= 0)
168 if (DCMD_HDRSPEC(flags
)) {
169 mdb_printf("%?s %6s %6s %?s %s\n",
170 "IOB", "NBYTES", "FLAGS", "IOP", "OPS");
173 if (mdb_vread(&iob
, sizeof (iob
), addr
) == -1 ||
174 mdb_vread(&io
, sizeof (io
), (uintptr_t)iob
.iob_iop
) == -1) {
175 mdb_warn("failed to read iob at %p", addr
);
179 mdb_printf("%?p %6lu %6x %?p %a\n", addr
, (ulong_t
)iob
.iob_nbytes
,
180 iob
.iob_flags
, iob
.iob_iop
, io
.io_ops
);
187 cmd_in(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
189 mdb_printf("%p\n", get_mdb()->m_in
);
195 cmd_out(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
197 mdb_printf("%p\n", get_mdb()->m_out
);
203 cmd_err(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
205 mdb_printf("%p\n", get_mdb()->m_err
);
211 cmd_target(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
218 if (!(flags
& DCMD_ADDRSPEC
))
219 addr
= (uintptr_t)get_mdb()->m_target
;
221 if (mdb_vread(&t
, sizeof (t
), addr
) != sizeof (t
)) {
222 mdb_warn("failed to read target at %p", addr
);
226 mdb_printf("+>\ttarget %p (%a)\n", addr
, t
.t_ops
);
228 mdb_printf("\tt_active = %-?p\tt_idle = %p\n",
229 addr
+ OFFSETOF(mdb_tgt_t
, t_active
),
230 addr
+ OFFSETOF(mdb_tgt_t
, t_idle
));
231 mdb_printf("\tt_xdlist = %-?p\tt_module = %a\n",
232 addr
+ OFFSETOF(mdb_tgt_t
, t_xdlist
), t
.t_module
);
233 mdb_printf("\tt_pshandle = %-?p\tt_data = %p\n",
234 t
.t_pshandle
, t
.t_data
);
235 mdb_printf("\tt_status = %-?p\tt_matched = %p\n",
236 addr
+ OFFSETOF(mdb_tgt_t
, t_status
), t
.t_matched
);
237 mdb_printf("\tt_flags = %-?x\tt_vecnt = 0t%u\n", t
.t_flags
, t
.t_vecnt
);
238 mdb_printf("\tt_vepos = %-?d\tt_veneg = %d\n\n", t
.t_vepos
, t
.t_veneg
);
245 cmd_sespec(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
249 if (argc
!= 0 || !(flags
& DCMD_ADDRSPEC
))
252 if (mdb_vread(&se
, sizeof (se
), addr
) != sizeof (se
)) {
253 mdb_warn("failed to read sespec at %p", addr
);
257 mdb_printf("+>\tsespec %p (%a)\n", addr
, se
.se_ops
);
259 mdb_printf("\tse_selist = %-?p\tse_velist = %p\n",
260 addr
+ OFFSETOF(mdb_sespec_t
, se_selist
),
261 addr
+ OFFSETOF(mdb_sespec_t
, se_velist
));
263 mdb_printf("\tse_data = %-?p\tse_refs = %u\n",
264 se
.se_data
, se
.se_refs
);
265 mdb_printf("\tse_state = %-?d\tse_errno = %d\n\n",
266 se
.se_state
, se
.se_errno
);
273 cmd_vespec(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
277 if (argc
!= 0 || !(flags
& DCMD_ADDRSPEC
))
280 if (mdb_vread(&ve
, sizeof (ve
), addr
) != sizeof (ve
)) {
281 mdb_warn("failed to read vespec at %p", addr
);
285 mdb_printf("+>\tvespec %p (id %d)\n", addr
, ve
.ve_id
);
286 mdb_printf("\tve_list = %-?p\tve_flags = 0x%x\n",
287 addr
+ OFFSETOF(mdb_vespec_t
, ve_list
), ve
.ve_flags
);
288 mdb_printf("\tve_se = %-?p\tve_refs = %u\n", ve
.ve_se
, ve
.ve_refs
);
289 mdb_printf("\tve_hits = %-?u\tve_lim = %u\n", ve
.ve_hits
, ve
.ve_limit
);
290 mdb_printf("\tve_data = %-?p\tve_callback = %a\n",
291 ve
.ve_data
, ve
.ve_callback
);
292 mdb_printf("\tve_args = %-?p\tve_dtor = %a\n\n",
293 ve
.ve_args
, ve
.ve_dtor
);
300 cmd_wr(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
302 char path
[MAXPATHLEN
];
306 if (argc
!= 0 || !(flags
& DCMD_ADDRSPEC
))
309 if (mdb_vread(&wn
, sizeof (wn
), addr
) != sizeof (wn
)) {
310 mdb_warn("failed to read wr node at %p", addr
);
314 if (DCMD_HDRSPEC(flags
)) {
315 mdb_printf("%-9s %3s %?s %s\n",
316 "COMMAND", "ERR", "MODCTL", "NAME");
319 dir
= "><"[WR_ISACK(&wn
) != 0];
320 switch (WR_TASK(&wn
)) {
321 case WNTASK_DMOD_LOAD
: {
324 if (mdb_vread(&dlr
, sizeof (dlr
), addr
) != sizeof (dlr
)) {
325 mdb_warn("failed to read kmdb_wr_load_t at %p", addr
);
329 if (mdb_readstr(path
, sizeof (path
),
330 (uintptr_t)dlr
.dlr_fname
) < 0) {
331 mdb_warn("failed to read path name at %p",
336 mdb_printf("%cload %3d %?p %s\n", dir
, dlr
.dlr_errno
,
337 dlr
.dlr_modctl
, path
);
341 case WNTASK_DMOD_LOAD_ALL
:
342 mdb_printf("%cload all %3d\n", dir
, wn
.wn_errno
);
345 case WNTASK_DMOD_UNLOAD
: {
346 kmdb_wr_unload_t dur
;
348 if (mdb_vread(&dur
, sizeof (dur
), addr
) != sizeof (dur
)) {
349 mdb_warn("failed to read kmdb_wr_unload_t at %p", addr
);
353 if (mdb_readstr(path
, sizeof (path
),
354 (uintptr_t)dur
.dur_modname
) < 0) {
355 mdb_warn("failed to read module name at %p",
360 mdb_printf("%cunload %3d %?p %s\n", dir
, dur
.dur_errno
,
361 dur
.dur_modctl
, path
);
365 case WNTASK_DMOD_PATH_CHANGE
: {
370 if (mdb_vread(&dpth
, sizeof (dpth
), addr
) != sizeof (dpth
)) {
371 mdb_warn("failed to read kmdb_wr_path_t at %p", addr
);
375 mdb_printf("%cpath chg %3d ", dir
, dpth
.dpth_errno
);
377 if (mdb_vread(&pathp
, sizeof (pathp
),
378 (uintptr_t)dpth
.dpth_path
) != sizeof (pathp
)) {
379 mdb_warn("failed to read path pointer at %p",
386 if (pathp
== (uintptr_t)NULL
)
389 if (mdb_readstr(path
, sizeof (path
), pathp
) < 0) {
390 mdb_warn("failed to read path at %p", pathp
);
394 mdb_printf("%s%s", (first
? "" : "\n "),
403 mdb_warn("unknown task type %d\n", wn
.wn_task
);
411 iob_stack_walk_init(mdb_walk_state_t
*wsp
)
415 if (mdb_vread(&stk
, sizeof (stk
), wsp
->walk_addr
) == -1) {
416 mdb_warn("failed to read iob_stack at %p", wsp
->walk_addr
);
420 wsp
->walk_addr
= (uintptr_t)stk
.stk_top
;
425 iob_stack_walk_step(mdb_walk_state_t
*wsp
)
427 uintptr_t addr
= wsp
->walk_addr
;
430 if (addr
== (uintptr_t)NULL
)
433 if (mdb_vread(&iob
, sizeof (iob
), addr
) == -1) {
434 mdb_warn("failed to read iob at %p", addr
);
438 wsp
->walk_addr
= (uintptr_t)iob
.iob_next
;
439 return (wsp
->walk_callback(addr
, &iob
, wsp
->walk_cbdata
));
443 frame_walk_init(mdb_walk_state_t
*wsp
)
445 if (wsp
->walk_addr
== (uintptr_t)NULL
)
446 wsp
->walk_addr
= (uintptr_t)get_mdb()->m_flist
.ml_prev
;
452 frame_walk_step(mdb_walk_state_t
*wsp
)
454 uintptr_t addr
= wsp
->walk_addr
;
457 if (addr
== (uintptr_t)NULL
)
460 if (mdb_vread(&f
, sizeof (f
), addr
) == -1) {
461 mdb_warn("failed to read frame at %p", addr
);
465 wsp
->walk_addr
= (uintptr_t)f
.f_list
.ml_prev
;
466 return (wsp
->walk_callback(addr
, &f
, wsp
->walk_cbdata
));
470 target_walk_init(mdb_walk_state_t
*wsp
)
472 if (wsp
->walk_addr
== (uintptr_t)NULL
)
473 wsp
->walk_addr
= (uintptr_t)get_mdb()->m_target
;
479 target_walk_step(mdb_walk_state_t
*wsp
)
481 uintptr_t addr
= wsp
->walk_addr
;
484 if (addr
== (uintptr_t)NULL
)
487 if (mdb_vread(&t
, sizeof (t
), addr
) == -1) {
488 mdb_warn("failed to read target at %p", addr
);
492 wsp
->walk_addr
= (uintptr_t)t
.t_tgtlist
.ml_next
;
493 return (wsp
->walk_callback(addr
, &t
, wsp
->walk_cbdata
));
497 sespec_walk_step(mdb_walk_state_t
*wsp
)
499 uintptr_t addr
= wsp
->walk_addr
;
502 if (addr
== (uintptr_t)NULL
)
505 if (mdb_vread(&s
, sizeof (s
), addr
) == -1) {
506 mdb_warn("failed to read sespec at %p", addr
);
510 wsp
->walk_addr
= (uintptr_t)s
.se_selist
.ml_next
;
511 return (wsp
->walk_callback(addr
, &s
, wsp
->walk_cbdata
));
515 vespec_walk_step(mdb_walk_state_t
*wsp
)
517 uintptr_t addr
= wsp
->walk_addr
;
520 if (addr
== (uintptr_t)NULL
)
523 if (mdb_vread(&v
, sizeof (v
), addr
) == -1) {
524 mdb_warn("failed to read vespec at %p", addr
);
528 wsp
->walk_addr
= (uintptr_t)v
.ve_list
.ml_next
;
529 return (wsp
->walk_callback(addr
, &v
, wsp
->walk_cbdata
));
533 se_matched_walk_step(mdb_walk_state_t
*wsp
)
535 uintptr_t addr
= wsp
->walk_addr
;
538 if (addr
== (uintptr_t)NULL
)
541 if (mdb_vread(&s
, sizeof (s
), addr
) == -1) {
542 mdb_warn("failed to read sespec at %p", addr
);
546 wsp
->walk_addr
= (uintptr_t)s
.se_matched
;
547 return (wsp
->walk_callback(addr
, &s
, wsp
->walk_cbdata
));
550 static const mdb_dcmd_t dcmds
[] = {
551 { "mdb_stack", "?", "print debugger stack", cmd_stack
},
552 { "mdb_frame", ":", "print debugger frame", cmd_frame
},
553 { "mdb_iob", ":", "print i/o buffer information", cmd_iob
},
554 { "mdb_in", NULL
, "print stdin iob", cmd_in
},
555 { "mdb_out", NULL
, "print stdout iob", cmd_out
},
556 { "mdb_err", NULL
, "print stderr iob", cmd_err
},
557 { "mdb_tgt", "?", "print current target", cmd_target
},
558 { "mdb_sespec", ":", "print software event specifier", cmd_sespec
},
559 { "mdb_vespec", ":", "print virtual event specifier", cmd_vespec
},
560 { "kmdb_wr", NULL
, "print a work queue entry", cmd_wr
},
564 static const mdb_walker_t walkers
[] = {
565 { "mdb_frame", "iterate over mdb_frame stack",
566 frame_walk_init
, frame_walk_step
, NULL
},
567 { "mdb_iob_stack", "iterate over mdb_iob_stack elements",
568 iob_stack_walk_init
, iob_stack_walk_step
, NULL
},
569 { "mdb_tgt", "iterate over active targets",
570 target_walk_init
, target_walk_step
, NULL
},
571 { "mdb_sespec", "iterate over software event specifiers",
572 NULL
, sespec_walk_step
, NULL
},
573 { "mdb_vespec", "iterate over virtual event specifiers",
574 NULL
, vespec_walk_step
, NULL
},
575 { "se_matched", "iterate over matched software event specifiers",
576 NULL
, se_matched_walk_step
, NULL
},
580 static const mdb_modinfo_t modinfo
= { MDB_API_VERSION
, dcmds
, walkers
};
582 const mdb_modinfo_t
*
590 if (mdb_lookup_by_name("mdb", &sym
) == -1) {
591 mdb_warn("failed to read mdb state structure");
595 if (sym
.st_size
!= sizeof (mdb_t
)) {
596 mdb_printf("mdb: WARNING: mdb_ds may not match mdb "
597 "implementation (mdb_t mismatch)\n");
600 if (mdb_readvar(&addr
, "_mdb_abort_str") != -1 &&
601 addr
!= (uintptr_t)NULL
&& mdb_readstr(buf
, sizeof (buf
), addr
) > 0)
602 mdb_printf("mdb: debugger failed with error: %s\n", buf
);
604 if (mdb_readvar(&rcount
, "_mdb_abort_rcount") != -1 && rcount
!= 0)
605 mdb_printf("mdb: WARNING: resume executed %d times\n", rcount
);