dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / mdb_ds / mdb_ds.c
blobca973b00a97c63ec38463d193e2ca63fb645487a
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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.
33 #define _MDB
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>
39 #include <mdb/mdb.h>
41 static const mdb_t *
42 get_mdb(void)
44 static mdb_t m;
46 if (mdb_readvar(&m, "mdb") == -1)
47 mdb_warn("failed to read mdb_t state");
49 return (&m);
52 static int
53 cmd_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
55 const char sep[] =
56 "-----------------------------------------------------------------";
58 if (flags & DCMD_ADDRSPEC) {
59 char buf[MDB_NV_NAMELEN + 1];
60 uintptr_t sp, pc;
61 mdb_idcmd_t idc;
62 mdb_frame_t f;
63 mdb_cmd_t c;
64 mdb_arg_t *ap;
65 size_t i;
67 if (mdb_vread(&f, sizeof (f), addr) == -1) {
68 mdb_warn("failed to read frame at %p", addr);
69 return (DCMD_ERR);
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) {
86 case MDB_TYPE_STRING:
87 if (mdb_readstr(buf, sizeof (buf),
88 (uintptr_t)ap[i].a_un.a_str) > 0)
89 mdb_printf(" %s", buf);
90 else
91 mdb_printf(" <str=%a>",
92 ap[i].a_un.a_str);
93 break;
94 case MDB_TYPE_IMMEDIATE:
95 mdb_printf(" $[ 0x%llx ]",
96 ap[i].a_un.a_val);
97 break;
98 case MDB_TYPE_CHAR:
99 mdb_printf(" '%c'", ap[i].a_un.a_char);
100 break;
101 default:
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",
118 f.f_cp, f.f_flags);
120 #if defined(__sparc)
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];
129 #else
130 #error Unknown ISA
131 #endif
132 if (pc != 0)
133 mdb_printf(" [ %0?lr %a() ]\n", sp, pc);
135 mdb_set_dot(sp);
136 mdb_inc_indent(8);
137 mdb_eval("<.$C0");
138 mdb_dec_indent(8);
139 mdb_printf("%s\n", sep);
141 } else {
142 mdb_printf("%s\n", sep);
143 (void) mdb_walk_dcmd("mdb_frame", "mdb_stack", argc, argv);
146 return (DCMD_OK);
149 static int
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));
155 return (DCMD_USAGE);
158 /*ARGSUSED*/
159 static int
160 cmd_iob(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
162 mdb_iob_t iob;
163 mdb_io_t io;
165 if (!(flags & DCMD_ADDRSPEC) || argc != 0)
166 return (DCMD_USAGE);
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);
176 return (DCMD_ERR);
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);
182 return (DCMD_OK);
185 /*ARGSUSED*/
186 static int
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);
190 return (DCMD_OK);
193 /*ARGSUSED*/
194 static int
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);
198 return (DCMD_OK);
201 /*ARGSUSED*/
202 static int
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);
206 return (DCMD_OK);
209 /*ARGSUSED*/
210 static int
211 cmd_target(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
213 mdb_tgt_t t;
215 if (argc != 0)
216 return (DCMD_USAGE);
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);
223 return (DCMD_ERR);
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);
240 return (DCMD_OK);
243 /*ARGSUSED*/
244 static int
245 cmd_sespec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
247 mdb_sespec_t se;
249 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
250 return (DCMD_USAGE);
252 if (mdb_vread(&se, sizeof (se), addr) != sizeof (se)) {
253 mdb_warn("failed to read sespec at %p", addr);
254 return (DCMD_ERR);
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);
268 return (DCMD_OK);
271 /*ARGSUSED*/
272 static int
273 cmd_vespec(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
275 mdb_vespec_t ve;
277 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
278 return (DCMD_USAGE);
280 if (mdb_vread(&ve, sizeof (ve), addr) != sizeof (ve)) {
281 mdb_warn("failed to read vespec at %p", addr);
282 return (DCMD_ERR);
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);
295 return (DCMD_OK);
298 /*ARGSUSED*/
299 static int
300 cmd_wr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
302 char path[MAXPATHLEN];
303 kmdb_wr_t wn;
304 char dir;
306 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
307 return (DCMD_USAGE);
309 if (mdb_vread(&wn, sizeof (wn), addr) != sizeof (wn)) {
310 mdb_warn("failed to read wr node at %p", addr);
311 return (DCMD_ERR);
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: {
322 kmdb_wr_load_t dlr;
324 if (mdb_vread(&dlr, sizeof (dlr), addr) != sizeof (dlr)) {
325 mdb_warn("failed to read kmdb_wr_load_t at %p", addr);
326 return (DCMD_ERR);
329 if (mdb_readstr(path, sizeof (path),
330 (uintptr_t)dlr.dlr_fname) < 0) {
331 mdb_warn("failed to read path name at %p",
332 dlr.dlr_fname);
333 *path = '\0';
336 mdb_printf("%cload %3d %?p %s\n", dir, dlr.dlr_errno,
337 dlr.dlr_modctl, path);
338 break;
341 case WNTASK_DMOD_LOAD_ALL:
342 mdb_printf("%cload all %3d\n", dir, wn.wn_errno);
343 break;
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);
350 return (DCMD_ERR);
353 if (mdb_readstr(path, sizeof (path),
354 (uintptr_t)dur.dur_modname) < 0) {
355 mdb_warn("failed to read module name at %p",
356 dur.dur_modname);
357 *path = '\0';
360 mdb_printf("%cunload %3d %?p %s\n", dir, dur.dur_errno,
361 dur.dur_modctl, path);
362 break;
365 case WNTASK_DMOD_PATH_CHANGE: {
366 kmdb_wr_path_t dpth;
367 uintptr_t pathp;
368 int first = 1;
370 if (mdb_vread(&dpth, sizeof (dpth), addr) != sizeof (dpth)) {
371 mdb_warn("failed to read kmdb_wr_path_t at %p", addr);
372 return (DCMD_ERR);
375 mdb_printf("%cpath chg %3d ", dir, dpth.dpth_errno);
376 for (;;) {
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",
380 dpth.dpth_path);
381 break;
384 dpth.dpth_path++;
386 if (pathp == (uintptr_t)NULL)
387 break;
389 if (mdb_readstr(path, sizeof (path), pathp) < 0) {
390 mdb_warn("failed to read path at %p", pathp);
391 *path = '\0';
394 mdb_printf("%s%s", (first ? "" : "\n "),
395 path);
396 first = 0;
398 mdb_printf("\n");
399 break;
402 default:
403 mdb_warn("unknown task type %d\n", wn.wn_task);
404 return (DCMD_ERR);
407 return (DCMD_OK);
410 static int
411 iob_stack_walk_init(mdb_walk_state_t *wsp)
413 mdb_iob_stack_t stk;
415 if (mdb_vread(&stk, sizeof (stk), wsp->walk_addr) == -1) {
416 mdb_warn("failed to read iob_stack at %p", wsp->walk_addr);
417 return (WALK_ERR);
420 wsp->walk_addr = (uintptr_t)stk.stk_top;
421 return (WALK_NEXT);
424 static int
425 iob_stack_walk_step(mdb_walk_state_t *wsp)
427 uintptr_t addr = wsp->walk_addr;
428 mdb_iob_t iob;
430 if (addr == (uintptr_t)NULL)
431 return (WALK_DONE);
433 if (mdb_vread(&iob, sizeof (iob), addr) == -1) {
434 mdb_warn("failed to read iob at %p", addr);
435 return (WALK_ERR);
438 wsp->walk_addr = (uintptr_t)iob.iob_next;
439 return (wsp->walk_callback(addr, &iob, wsp->walk_cbdata));
442 static int
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;
448 return (WALK_NEXT);
451 static int
452 frame_walk_step(mdb_walk_state_t *wsp)
454 uintptr_t addr = wsp->walk_addr;
455 mdb_frame_t f;
457 if (addr == (uintptr_t)NULL)
458 return (WALK_DONE);
460 if (mdb_vread(&f, sizeof (f), addr) == -1) {
461 mdb_warn("failed to read frame at %p", addr);
462 return (WALK_ERR);
465 wsp->walk_addr = (uintptr_t)f.f_list.ml_prev;
466 return (wsp->walk_callback(addr, &f, wsp->walk_cbdata));
469 static int
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;
475 return (WALK_NEXT);
478 static int
479 target_walk_step(mdb_walk_state_t *wsp)
481 uintptr_t addr = wsp->walk_addr;
482 mdb_tgt_t t;
484 if (addr == (uintptr_t)NULL)
485 return (WALK_DONE);
487 if (mdb_vread(&t, sizeof (t), addr) == -1) {
488 mdb_warn("failed to read target at %p", addr);
489 return (WALK_ERR);
492 wsp->walk_addr = (uintptr_t)t.t_tgtlist.ml_next;
493 return (wsp->walk_callback(addr, &t, wsp->walk_cbdata));
496 static int
497 sespec_walk_step(mdb_walk_state_t *wsp)
499 uintptr_t addr = wsp->walk_addr;
500 mdb_sespec_t s;
502 if (addr == (uintptr_t)NULL)
503 return (WALK_DONE);
505 if (mdb_vread(&s, sizeof (s), addr) == -1) {
506 mdb_warn("failed to read sespec at %p", addr);
507 return (WALK_ERR);
510 wsp->walk_addr = (uintptr_t)s.se_selist.ml_next;
511 return (wsp->walk_callback(addr, &s, wsp->walk_cbdata));
514 static int
515 vespec_walk_step(mdb_walk_state_t *wsp)
517 uintptr_t addr = wsp->walk_addr;
518 mdb_vespec_t v;
520 if (addr == (uintptr_t)NULL)
521 return (WALK_DONE);
523 if (mdb_vread(&v, sizeof (v), addr) == -1) {
524 mdb_warn("failed to read vespec at %p", addr);
525 return (WALK_ERR);
528 wsp->walk_addr = (uintptr_t)v.ve_list.ml_next;
529 return (wsp->walk_callback(addr, &v, wsp->walk_cbdata));
532 static int
533 se_matched_walk_step(mdb_walk_state_t *wsp)
535 uintptr_t addr = wsp->walk_addr;
536 mdb_sespec_t s;
538 if (addr == (uintptr_t)NULL)
539 return (WALK_DONE);
541 if (mdb_vread(&s, sizeof (s), addr) == -1) {
542 mdb_warn("failed to read sespec at %p", addr);
543 return (WALK_ERR);
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 },
561 { NULL }
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 },
577 { NULL }
580 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
582 const mdb_modinfo_t *
583 _mdb_init(void)
585 char buf[256];
586 uintptr_t addr;
587 int rcount;
588 GElf_Sym sym;
590 if (mdb_lookup_by_name("mdb", &sym) == -1) {
591 mdb_warn("failed to read mdb state structure");
592 return (NULL);
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);
607 return (&modinfo);