4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
28 * Copyright 2015 Joyent, Inc.
29 * Copyright (c) 2014 Nexenta Systems, Inc. All rights reserved.
32 #include <mdb/mdb_modapi.h>
33 #include <mdb/mdb_target.h>
34 #include <mdb/mdb_argvec.h>
35 #include <mdb/mdb_string.h>
36 #include <mdb/mdb_stdlib.h>
37 #include <mdb/mdb_err.h>
38 #include <mdb/mdb_debug.h>
39 #include <mdb/mdb_fmt.h>
40 #include <mdb/mdb_ctf.h>
41 #include <mdb/mdb_ctf_impl.h>
43 #include <mdb/mdb_tab.h>
45 #include <sys/isa_defs.h>
46 #include <sys/param.h>
47 #include <sys/sysmacros.h>
48 #include <netinet/in.h>
53 typedef struct holeinfo
{
54 ulong_t hi_offset
; /* expected offset */
55 uchar_t hi_isunion
; /* represents a union */
58 typedef struct printarg
{
59 mdb_tgt_t
*pa_tgt
; /* current target */
60 mdb_tgt_t
*pa_realtgt
; /* real target (for -i) */
61 mdb_tgt_t
*pa_immtgt
; /* immediate target (for -i) */
62 mdb_tgt_as_t pa_as
; /* address space to use for i/o */
63 mdb_tgt_addr_t pa_addr
; /* base address for i/o */
64 ulong_t pa_armemlim
; /* limit on array elements to print */
65 ulong_t pa_arstrlim
; /* limit on array chars to print */
66 const char *pa_delim
; /* element delimiter string */
67 const char *pa_prefix
; /* element prefix string */
68 const char *pa_suffix
; /* element suffix string */
69 holeinfo_t
*pa_holes
; /* hole detection information */
70 int pa_nholes
; /* size of holes array */
71 int pa_flags
; /* formatting flags (see below) */
72 int pa_depth
; /* previous depth */
73 int pa_nest
; /* array nesting depth */
74 int pa_tab
; /* tabstop width */
75 uint_t pa_maxdepth
; /* Limit max depth */
76 uint_t pa_nooutdepth
; /* don't print output past this depth */
79 #define PA_SHOWTYPE 0x001 /* print type name */
80 #define PA_SHOWBASETYPE 0x002 /* print base type name */
81 #define PA_SHOWNAME 0x004 /* print member name */
82 #define PA_SHOWADDR 0x008 /* print address */
83 #define PA_SHOWVAL 0x010 /* print value */
84 #define PA_SHOWHOLES 0x020 /* print holes in structs */
85 #define PA_INTHEX 0x040 /* print integer values in hex */
86 #define PA_INTDEC 0x080 /* print integer values in decimal */
87 #define PA_NOSYMBOLIC 0x100 /* don't print ptrs as func+offset */
90 (((e).cte_format & (CTF_INT_CHAR | CTF_INT_SIGNED)) == \
91 (CTF_INT_CHAR | CTF_INT_SIGNED) && (e).cte_bits == NBBY)
93 #define COMPOSITE_MASK ((1 << CTF_K_STRUCT) | \
94 (1 << CTF_K_UNION) | (1 << CTF_K_ARRAY))
95 #define IS_COMPOSITE(k) (((1 << k) & COMPOSITE_MASK) != 0)
97 #define SOU_MASK ((1 << CTF_K_STRUCT) | (1 << CTF_K_UNION))
98 #define IS_SOU(k) (((1 << k) & SOU_MASK) != 0)
100 #define MEMBER_DELIM_ERR -1
101 #define MEMBER_DELIM_DONE 0
102 #define MEMBER_DELIM_PTR 1
103 #define MEMBER_DELIM_DOT 2
104 #define MEMBER_DELIM_LBR 3
106 typedef int printarg_f(const char *, const char *,
107 mdb_ctf_id_t
, mdb_ctf_id_t
, ulong_t
, printarg_t
*);
109 static int elt_print(const char *, mdb_ctf_id_t
, mdb_ctf_id_t
, ulong_t
, int,
111 static void print_close_sou(printarg_t
*, int);
114 * Given an address, look up the symbol ID of the specified symbol in its
115 * containing module. We only support lookups for exact matches.
118 addr_to_sym(mdb_tgt_t
*t
, uintptr_t addr
, char *name
, size_t namelen
,
119 GElf_Sym
*symp
, mdb_syminfo_t
*sip
)
124 if (mdb_tgt_lookup_by_addr(t
, addr
, MDB_TGT_SYM_EXACT
, name
,
125 namelen
, NULL
, NULL
) == -1)
126 return (NULL
); /* address does not exactly match a symbol */
128 if ((p
= strrsplit(name
, '`')) != NULL
) {
129 if (mdb_tgt_lookup_by_name(t
, name
, p
, symp
, sip
) == -1)
134 if ((mp
= mdb_tgt_addr_to_map(t
, addr
)) == NULL
)
135 return (NULL
); /* address does not fall within a mapping */
137 if (mdb_tgt_lookup_by_name(t
, mp
->map_name
, name
, symp
, sip
) == -1)
144 * This lets dcmds be a little fancy with their processing of type arguments
145 * while still treating them more or less as a single argument.
146 * For example, if a command is invokes like this:
148 * ::<dcmd> proc_t ...
150 * this function will just copy "proc_t" into the provided buffer. If the
151 * command is instead invoked like this:
153 * ::<dcmd> struct proc ...
155 * this function will place the string "struct proc" into the provided buffer
156 * and increment the caller's argv and argc. This allows the caller to still
157 * treat the type argument logically as it would an other atomic argument.
160 args_to_typename(int *argcp
, const mdb_arg_t
**argvp
, char *buf
, size_t len
)
163 const mdb_arg_t
*argv
= *argvp
;
165 if (argc
< 1 || argv
->a_type
!= MDB_TYPE_STRING
)
168 if (strcmp(argv
->a_un
.a_str
, "struct") == 0 ||
169 strcmp(argv
->a_un
.a_str
, "enum") == 0 ||
170 strcmp(argv
->a_un
.a_str
, "union") == 0) {
172 mdb_warn("%s is not a valid type\n", argv
->a_un
.a_str
);
176 if (argv
[1].a_type
!= MDB_TYPE_STRING
)
179 (void) mdb_snprintf(buf
, len
, "%s %s",
180 argv
[0].a_un
.a_str
, argv
[1].a_un
.a_str
);
185 (void) mdb_snprintf(buf
, len
, "%s", argv
[0].a_un
.a_str
);
193 cmd_sizeof(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
196 char tn
[MDB_SYM_NAMLEN
];
199 if (flags
& DCMD_ADDRSPEC
)
202 if ((ret
= args_to_typename(&argc
, &argv
, tn
, sizeof (tn
))) != 0)
208 if (mdb_ctf_lookup_by_name(tn
, &id
) != 0) {
209 mdb_warn("failed to look up type %s", tn
);
213 if (flags
& DCMD_PIPE_OUT
)
214 mdb_printf("%#lr\n", mdb_ctf_type_size(id
));
216 mdb_printf("sizeof (%s) = %#lr\n", tn
, mdb_ctf_type_size(id
));
222 cmd_sizeof_tab(mdb_tab_cookie_t
*mcp
, uint_t flags
, int argc
,
223 const mdb_arg_t
*argv
)
225 char tn
[MDB_SYM_NAMLEN
];
228 if (argc
== 0 && !(flags
& DCMD_TAB_SPACE
))
231 if (argc
== 0 && (flags
& DCMD_TAB_SPACE
))
232 return (mdb_tab_complete_type(mcp
, NULL
, MDB_TABC_NOPOINT
));
234 if ((ret
= mdb_tab_typename(&argc
, &argv
, tn
, sizeof (tn
))) < 0)
238 return (mdb_tab_complete_type(mcp
, tn
, MDB_TABC_NOPOINT
));
245 cmd_offsetof(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
250 char tn
[MDB_SYM_NAMLEN
];
254 if (flags
& DCMD_ADDRSPEC
)
257 if ((ret
= args_to_typename(&argc
, &argv
, tn
, sizeof (tn
))) != 0)
260 if (argc
!= 2 || argv
[1].a_type
!= MDB_TYPE_STRING
)
263 if (mdb_ctf_lookup_by_name(tn
, &id
) != 0) {
264 mdb_warn("failed to look up type %s", tn
);
268 member
= argv
[1].a_un
.a_str
;
270 if (mdb_ctf_member_info(id
, member
, &off
, &id
) != 0) {
271 mdb_warn("failed to find member %s of type %s", member
, tn
);
275 if (flags
& DCMD_PIPE_OUT
) {
276 if (off
% NBBY
!= 0) {
277 mdb_warn("member %s of type %s is not byte-aligned\n",
281 mdb_printf("%#lr", off
/ NBBY
);
285 mdb_printf("offsetof (%s, %s) = %#lr",
286 tn
, member
, off
/ NBBY
);
288 mdb_printf(".%lr", off
% NBBY
);
290 if ((sz
= mdb_ctf_type_size(id
)) > 0)
291 mdb_printf(", sizeof (...->%s) = %#lr", member
, sz
);
300 enum_prefix_scan_cb(const char *name
, int value
, void *arg
)
305 * This function is called with every name in the enum. We make
306 * "arg" be the common prefix, if any.
309 if (strlcpy(arg
, name
, MDB_SYM_NAMLEN
) >= MDB_SYM_NAMLEN
)
314 while (*name
== *str
) {
317 str
--; /* don't smother a name completely */
326 return (str
== arg
); /* only continue if prefix is non-empty */
329 struct enum_p2_info
{
330 intmax_t e_value
; /* value we're processing */
331 char *e_buf
; /* buffer for holding names */
332 size_t e_size
; /* size of buffer */
333 size_t e_prefix
; /* length of initial prefix */
334 uint_t e_allprefix
; /* apply prefix to first guy, too */
335 uint_t e_bits
; /* bits seen */
336 uint8_t e_found
; /* have we seen anything? */
337 uint8_t e_first
; /* does buf contain the first one? */
338 uint8_t e_zero
; /* have we seen a zero value? */
342 enum_p2_cb(const char *name
, int bit_arg
, void *arg
)
344 struct enum_p2_info
*eiip
= arg
;
345 uintmax_t bit
= bit_arg
;
347 if (bit
!= 0 && !ISP2(bit
))
348 return (1); /* non-power-of-2; abort processing */
350 if ((bit
== 0 && eiip
->e_zero
) ||
351 (bit
!= 0 && (eiip
->e_bits
& bit
) != 0)) {
352 return (0); /* already seen this value */
360 if (eiip
->e_buf
!= NULL
&& (eiip
->e_value
& bit
) != 0) {
361 char *buf
= eiip
->e_buf
;
362 size_t prefix
= eiip
->e_prefix
;
365 (void) strlcat(buf
, "|", eiip
->e_size
);
367 if (eiip
->e_first
&& !eiip
->e_allprefix
&& prefix
> 0) {
368 char c1
= buf
[prefix
];
369 char c2
= buf
[prefix
+ 1];
372 mdb_printf("%s", buf
);
374 buf
[prefix
+ 1] = c2
;
375 mdb_printf("%s", buf
+ prefix
);
377 mdb_printf("%s", buf
);
381 /* skip the common prefix as necessary */
382 if ((eiip
->e_found
|| eiip
->e_allprefix
) &&
383 strlen(name
) > prefix
)
386 (void) strlcpy(eiip
->e_buf
, name
, eiip
->e_size
);
387 eiip
->e_first
= !eiip
->e_found
;
394 enum_is_p2(mdb_ctf_id_t id
)
396 struct enum_p2_info eii
;
397 bzero(&eii
, sizeof (eii
));
399 return (mdb_ctf_type_kind(id
) == CTF_K_ENUM
&&
400 mdb_ctf_enum_iter(id
, enum_p2_cb
, &eii
) == 0 &&
405 enum_value_print_p2(mdb_ctf_id_t id
, intmax_t value
, uint_t allprefix
)
407 struct enum_p2_info eii
;
408 char prefix
[MDB_SYM_NAMLEN
+ 2];
411 bzero(&eii
, sizeof (eii
));
415 eii
.e_size
= sizeof (prefix
);
416 eii
.e_allprefix
= allprefix
;
419 if (mdb_ctf_enum_iter(id
, enum_prefix_scan_cb
, prefix
) == 0)
420 eii
.e_prefix
= strlen(prefix
);
422 if (mdb_ctf_enum_iter(id
, enum_p2_cb
, &eii
) != 0 || eii
.e_bits
== 0)
425 missed
= (value
& ~(intmax_t)eii
.e_bits
);
428 /* push out any final value, with a | if we missed anything */
430 (void) strlcat(prefix
, "}", sizeof (prefix
));
432 (void) strlcat(prefix
, "|", sizeof (prefix
));
434 mdb_printf("%s", prefix
);
437 if (!eii
.e_found
|| missed
) {
438 mdb_printf("%#llx", missed
);
446 const char *e_string
; /* NULL for value searches */
452 #define E_PRETTY 0x01
454 #define E_SEARCH_STRING 0x04
455 #define E_SEARCH_VALUE 0x08
456 #define E_ELIDE_PREFIX 0x10
459 enum_print(struct enum_cbinfo
*info
, const char *name
, int value
)
461 uint_t flags
= info
->e_flags
;
462 uint_t elide_prefix
= (info
->e_flags
& E_ELIDE_PREFIX
);
464 if (name
!= NULL
&& info
->e_prefix
&& strlen(name
) > info
->e_prefix
)
465 name
+= info
->e_prefix
;
467 if (flags
& E_PRETTY
) {
468 uint_t indent
= 5 + ((flags
& E_HEX
) ? 8 : 11);
470 mdb_printf((flags
& E_HEX
)? "%8x " : "%11d ", value
);
471 (void) mdb_inc_indent(indent
);
473 mdb_iob_puts(mdb
.m_out
, name
);
475 (void) enum_value_print_p2(info
->e_id
, value
,
478 (void) mdb_dec_indent(indent
);
481 mdb_printf("%#r\n", value
);
486 enum_cb(const char *name
, int value
, void *arg
)
488 struct enum_cbinfo
*info
= arg
;
489 uint_t flags
= info
->e_flags
;
491 if (flags
& E_SEARCH_STRING
) {
492 if (strcmp(name
, info
->e_string
) != 0)
495 } else if (flags
& E_SEARCH_VALUE
) {
496 if (value
!= info
->e_value
)
500 enum_print(info
, name
, value
);
510 "Without an address and name, print all values for the enumeration \"enum\".\n"
511 "With an address, look up a particular value in \"enum\". With a name, look\n"
512 "up a particular name in \"enum\".\n");
514 (void) mdb_dec_indent(2);
515 mdb_printf("\n%<b>OPTIONS%</b>\n");
516 (void) mdb_inc_indent(2);
519 " -e remove common prefixes from enum names\n"
520 " -x report enum values in hexadecimal\n");
525 cmd_enum(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
527 struct enum_cbinfo info
;
529 char type
[MDB_SYM_NAMLEN
+ sizeof ("enum ")];
530 char tn2
[MDB_SYM_NAMLEN
+ sizeof ("enum ")];
531 char prefix
[MDB_SYM_NAMLEN
];
539 info
.e_flags
= (flags
& DCMD_PIPE_OUT
)? 0 : E_PRETTY
;
540 info
.e_string
= NULL
;
544 i
= mdb_getopts(argc
, argv
,
545 'e', MDB_OPT_SETBITS
, E_ELIDE_PREFIX
, &info
.e_flags
,
546 'x', MDB_OPT_SETBITS
, E_HEX
, &info
.e_flags
,
552 if ((i
= args_to_typename(&argc
, &argv
, type
, MDB_SYM_NAMLEN
)) != 0)
555 if (strchr(type
, ' ') == NULL
) {
557 * Check as an enumeration tag first, and fall back
558 * to checking for a typedef. Yes, this means that
559 * anonymous enumerations whose typedefs conflict with
560 * an enum tag can't be accessed. Don't do that.
562 (void) mdb_snprintf(tn2
, sizeof (tn2
), "enum %s", type
);
564 if (mdb_ctf_lookup_by_name(tn2
, &id
) == 0) {
565 (void) strcpy(type
, tn2
);
566 } else if (mdb_ctf_lookup_by_name(type
, &id
) != 0) {
567 mdb_warn("types '%s', '%s'", tn2
, type
);
571 if (mdb_ctf_lookup_by_name(type
, &id
) != 0) {
572 mdb_warn("'%s'", type
);
577 /* resolve it, and make sure we're looking at an enumeration */
578 if (mdb_ctf_type_resolve(id
, &idr
) == -1) {
579 mdb_warn("unable to resolve '%s'", type
);
582 if (mdb_ctf_type_kind(idr
) != CTF_K_ENUM
) {
583 mdb_warn("'%s': not an enumeration\n", type
);
593 if (flags
& DCMD_ADDRSPEC
) {
594 mdb_warn("may only specify one of: name, address\n");
598 if (argv
[1].a_type
== MDB_TYPE_STRING
) {
599 info
.e_flags
|= E_SEARCH_STRING
;
600 info
.e_string
= argv
[1].a_un
.a_str
;
601 } else if (argv
[1].a_type
== MDB_TYPE_IMMEDIATE
) {
602 info
.e_flags
|= E_SEARCH_VALUE
;
603 search
= argv
[1].a_un
.a_val
;
609 if (flags
& DCMD_ADDRSPEC
) {
610 info
.e_flags
|= E_SEARCH_VALUE
;
611 search
= mdb_get_dot();
614 if (info
.e_flags
& E_SEARCH_VALUE
) {
615 if ((int)search
!= search
) {
616 mdb_warn("value '%lld' out of enumeration range\n",
619 info
.e_value
= search
;
622 isp2
= enum_is_p2(idr
);
624 info
.e_flags
|= E_HEX
;
626 if (DCMD_HDRSPEC(flags
) && (info
.e_flags
& E_PRETTY
)) {
627 if (info
.e_flags
& E_HEX
)
628 mdb_printf("%<u>%8s %-64s%</u>\n", "VALUE", "NAME");
630 mdb_printf("%<u>%11s %-64s%</u>\n", "VALUE", "NAME");
633 /* if the enum is a power-of-two one, process it that way */
634 if ((info
.e_flags
& E_SEARCH_VALUE
) && isp2
) {
635 enum_print(&info
, NULL
, info
.e_value
);
640 if ((info
.e_flags
& E_ELIDE_PREFIX
) &&
641 mdb_ctf_enum_iter(id
, enum_prefix_scan_cb
, prefix
) == 0)
642 info
.e_prefix
= strlen(prefix
);
644 if (mdb_ctf_enum_iter(idr
, enum_cb
, &info
) == -1) {
645 mdb_warn("cannot walk '%s' as enum", type
);
649 if (info
.e_found
== 0 &&
650 (info
.e_flags
& (E_SEARCH_STRING
| E_SEARCH_VALUE
)) != 0) {
651 if (info
.e_flags
& E_SEARCH_STRING
)
652 mdb_warn("name \"%s\" not in '%s'\n", info
.e_string
,
655 mdb_warn("value %#lld not in '%s'\n", info
.e_value
,
665 setup_vcb(const char *name
, uintptr_t addr
)
670 if ((v
= mdb_nv_lookup(&mdb
.m_nv
, name
)) == NULL
) {
671 if ((p
= strbadid(name
)) != NULL
) {
672 mdb_warn("'%c' may not be used in a variable "
677 if ((v
= mdb_nv_insert(&mdb
.m_nv
, name
, NULL
, addr
, 0)) == NULL
)
680 if (v
->v_flags
& MDB_NV_RDONLY
) {
681 mdb_warn("variable %s is read-only\n", name
);
687 * If there already exists a vcb for this variable, we may be
688 * calling the dcmd in a loop. We only create a vcb for this
689 * variable on the first invocation.
691 if (mdb_vcb_find(v
, mdb
.m_frame
) == NULL
)
692 mdb_vcb_insert(mdb_vcb_create(v
), mdb
.m_frame
);
699 cmd_list(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
705 if (!(flags
& DCMD_ADDRSPEC
) || argc
== 0)
708 if (argv
->a_type
!= MDB_TYPE_STRING
) {
710 * We are being given a raw offset in lieu of a type and
711 * member; confirm the number of arguments and argument
714 if (argc
!= 1 || argv
->a_type
!= MDB_TYPE_IMMEDIATE
)
717 offset
= argv
->a_un
.a_val
;
722 if (offset
% sizeof (uintptr_t)) {
723 mdb_warn("offset must fall on a word boundary\n");
728 char buf
[MDB_SYM_NAMLEN
];
732 * Check that we were provided 2 arguments: a type name
733 * and a member of that type.
738 ret
= args_to_typename(&argc
, &argv
, buf
, sizeof (buf
));
745 member
= argv
->a_un
.a_str
;
746 offset
= mdb_ctf_offsetof_by_name(buf
, member
);
753 if (offset
% (sizeof (uintptr_t)) != 0) {
754 mdb_warn("%s is not a word-aligned member\n", member
);
760 * If we have any unchewed arguments, a variable name must be present.
763 if (argv
->a_type
!= MDB_TYPE_STRING
)
766 if ((ret
= setup_vcb(argv
->a_un
.a_str
, addr
)) != 0)
769 } else if (argc
!= 0) {
776 mdb_printf("%lr\n", a
);
778 if (mdb_vread(&tmp
, sizeof (tmp
), a
+ offset
) == -1) {
779 mdb_warn("failed to read next pointer from object %p",
785 } while (a
!= addr
&& a
!= NULL
);
791 cmd_array(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
794 ssize_t elemsize
= 0;
795 char tn
[MDB_SYM_NAMLEN
];
798 mdb_tgt_t
*t
= mdb
.m_target
;
801 mdb_syminfo_t s_info
;
803 if (!(flags
& DCMD_ADDRSPEC
))
807 ret
= args_to_typename(&argc
, &argv
, tn
, sizeof (tn
));
811 if (argc
== 1) /* unquoted compound type without count */
814 if (mdb_ctf_lookup_by_name(tn
, &id
) != 0) {
815 mdb_warn("failed to look up type %s", tn
);
819 if (argv
[1].a_type
== MDB_TYPE_IMMEDIATE
)
820 nelem
= argv
[1].a_un
.a_val
;
822 nelem
= mdb_strtoull(argv
[1].a_un
.a_str
);
824 elemsize
= mdb_ctf_type_size(id
);
825 } else if (addr_to_sym(t
, addr
, tn
, sizeof (tn
), &sym
, &s_info
)
826 != NULL
&& mdb_ctf_lookup_by_symbol(&sym
, &s_info
, &id
)
827 == 0 && mdb_ctf_type_kind(id
) == CTF_K_ARRAY
&&
828 mdb_ctf_array_info(id
, &ar
) != -1) {
829 elemsize
= mdb_ctf_type_size(id
) / ar
.mta_nelems
;
830 nelem
= ar
.mta_nelems
;
832 mdb_warn("no symbol information for %a", addr
);
836 if (argc
== 3 || argc
== 1) {
837 if (argv
[argc
- 1].a_type
!= MDB_TYPE_STRING
)
840 if ((ret
= setup_vcb(argv
[argc
- 1].a_un
.a_str
, addr
)) != 0)
843 } else if (argc
> 3) {
847 for (; nelem
> 0; nelem
--) {
848 mdb_printf("%lr\n", addr
);
849 addr
= addr
+ elemsize
;
856 * Print an integer bitfield in hexadecimal by reading the enclosing byte(s)
857 * and then shifting and masking the data in the lower bits of a uint64_t.
860 print_bitfield(ulong_t off
, printarg_t
*pap
, ctf_encoding_t
*ep
)
862 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
863 size_t size
= (ep
->cte_bits
+ (NBBY
- 1)) / NBBY
;
864 uint64_t mask
= (1ULL << ep
->cte_bits
) - 1;
866 uint8_t *buf
= (uint8_t *)&value
;
871 if (!(pap
->pa_flags
& PA_SHOWVAL
))
874 if (ep
->cte_bits
> sizeof (value
) * NBBY
- 1) {
875 mdb_printf("??? (invalid bitfield size %u)", ep
->cte_bits
);
880 * On big-endian machines, we need to adjust the buf pointer to refer
881 * to the lowest 'size' bytes in 'value', and we need shift based on
882 * the offset from the end of the data, not the offset of the start.
885 buf
+= sizeof (value
) - size
;
888 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, buf
, size
, addr
) != size
) {
889 mdb_warn("failed to read %lu bytes at %llx",
890 (ulong_t
)size
, addr
);
897 * Offsets are counted from opposite ends on little- and
898 * big-endian machines.
901 shift
= NBBY
- shift
;
905 * If the bits we want do not begin on a byte boundary, shift the data
906 * right so that the value is in the lowest 'cte_bits' of 'value'.
913 * We default to printing signed bitfields as decimals,
914 * and unsigned bitfields in hexadecimal. If they specify
915 * hexadecimal, we treat the field as unsigned.
917 if ((pap
->pa_flags
& PA_INTHEX
) ||
918 !(ep
->cte_format
& CTF_INT_SIGNED
)) {
919 format
= (pap
->pa_flags
& PA_INTDEC
)? "%#llu" : "%#llx";
921 int sshift
= sizeof (value
) * NBBY
- ep
->cte_bits
;
923 /* sign-extend value, and print as a signed decimal */
924 value
= ((int64_t)value
<< sshift
) >> sshift
;
927 mdb_printf(format
, value
);
933 * Print out a character or integer value. We use some simple heuristics,
934 * described below, to determine the appropriate radix to use for output.
937 print_int_val(const char *type
, ctf_encoding_t
*ep
, ulong_t off
,
940 static const char *const sformat
[] = { "%#d", "%#d", "%#d", "%#lld" };
941 static const char *const uformat
[] = { "%#u", "%#u", "%#u", "%#llu" };
942 static const char *const xformat
[] = { "%#x", "%#x", "%#x", "%#llx" };
944 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
945 const char *const *fsp
;
957 if (!(pap
->pa_flags
& PA_SHOWVAL
))
960 if (ep
->cte_format
& CTF_INT_VARARGS
) {
966 * If the size is not a power-of-two number of bytes in the range 1-8
967 * then we assume it is a bitfield and print it as such.
969 size
= ep
->cte_bits
/ NBBY
;
970 if (size
> 8 || (ep
->cte_bits
% NBBY
) != 0 || (size
& (size
- 1)) != 0)
971 return (print_bitfield(off
, pap
, ep
));
975 if (mdb_fmt_print(pap
->pa_tgt
, pap
->pa_as
,
976 addr
, 1, 'C') == addr
)
982 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &u
.i8
, size
, addr
) != size
) {
983 mdb_warn("failed to read %lu bytes at %llx",
984 (ulong_t
)size
, addr
);
989 * We pretty-print some integer based types. time_t values are
990 * printed as a calendar date and time, and IPv4 addresses as human
991 * readable dotted quads.
993 if (!(pap
->pa_flags
& (PA_INTHEX
| PA_INTDEC
))) {
994 if (strcmp(type
, "time_t") == 0 && u
.t
!= 0) {
995 mdb_printf("%Y", u
.t
);
998 if (strcmp(type
, "ipaddr_t") == 0 ||
999 strcmp(type
, "in_addr_t") == 0) {
1000 mdb_printf("%I", u
.I
);
1006 * The default format is hexadecimal.
1008 if (!(pap
->pa_flags
& PA_INTDEC
))
1010 else if (ep
->cte_format
& CTF_INT_SIGNED
)
1016 case sizeof (uint8_t):
1017 mdb_printf(fsp
[0], u
.i1
);
1019 case sizeof (uint16_t):
1020 mdb_printf(fsp
[1], u
.i2
);
1022 case sizeof (uint32_t):
1023 mdb_printf(fsp
[2], u
.i4
);
1025 case sizeof (uint64_t):
1026 mdb_printf(fsp
[3], u
.i8
);
1034 print_int(const char *type
, const char *name
, mdb_ctf_id_t id
,
1035 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1039 if (!(pap
->pa_flags
& PA_SHOWVAL
))
1042 if (mdb_ctf_type_encoding(base
, &e
) != 0) {
1043 mdb_printf("??? (%s)", mdb_strerror(errno
));
1047 return (print_int_val(type
, &e
, off
, pap
));
1051 * Print out a floating point value. We only provide support for floats in
1052 * the ANSI-C float, double, and long double formats.
1056 print_float(const char *type
, const char *name
, mdb_ctf_id_t id
,
1057 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1060 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
1069 if (!(pap
->pa_flags
& PA_SHOWVAL
))
1072 if (mdb_ctf_type_encoding(base
, &e
) == 0) {
1073 if (e
.cte_format
== CTF_FP_SINGLE
&&
1074 e
.cte_bits
== sizeof (float) * NBBY
) {
1075 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &u
.f
,
1076 sizeof (u
.f
), addr
) != sizeof (u
.f
)) {
1077 mdb_warn("failed to read float at %llx", addr
);
1080 mdb_printf("%s", doubletos(u
.f
, 7, 'e'));
1082 } else if (e
.cte_format
== CTF_FP_DOUBLE
&&
1083 e
.cte_bits
== sizeof (double) * NBBY
) {
1084 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &u
.d
,
1085 sizeof (u
.d
), addr
) != sizeof (u
.d
)) {
1086 mdb_warn("failed to read float at %llx", addr
);
1089 mdb_printf("%s", doubletos(u
.d
, 7, 'e'));
1091 } else if (e
.cte_format
== CTF_FP_LDOUBLE
&&
1092 e
.cte_bits
== sizeof (long double) * NBBY
) {
1093 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &u
.ld
,
1094 sizeof (u
.ld
), addr
) != sizeof (u
.ld
)) {
1095 mdb_warn("failed to read float at %llx", addr
);
1098 mdb_printf("%s", longdoubletos(&u
.ld
, 16, 'e'));
1101 mdb_printf("??? (unsupported FP format %u / %u bits\n",
1102 e
.cte_format
, e
.cte_bits
);
1105 mdb_printf("??? (%s)", mdb_strerror(errno
));
1107 mdb_printf("<FLOAT>");
1114 * Print out a pointer value as a symbol name + offset or a hexadecimal value.
1115 * If the pointer itself is a char *, we attempt to read a bit of the data
1116 * referenced by the pointer and display it if it is a printable ASCII string.
1120 print_ptr(const char *type
, const char *name
, mdb_ctf_id_t id
,
1121 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1123 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
1129 if (!(pap
->pa_flags
& PA_SHOWVAL
))
1132 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
,
1133 &value
, sizeof (value
), addr
) != sizeof (value
)) {
1134 mdb_warn("failed to read %s pointer at %llx", name
, addr
);
1138 if (pap
->pa_flags
& PA_NOSYMBOLIC
) {
1139 mdb_printf("%#lx", value
);
1143 mdb_printf("%a", value
);
1145 if (value
== NULL
|| strcmp(type
, "caddr_t") == 0)
1148 if (mdb_ctf_type_kind(base
) == CTF_K_POINTER
&&
1149 mdb_ctf_type_reference(base
, &base
) != -1 &&
1150 mdb_ctf_type_resolve(base
, &base
) != -1 &&
1151 mdb_ctf_type_encoding(base
, &e
) == 0 && IS_CHAR(e
)) {
1152 if ((len
= mdb_tgt_readstr(pap
->pa_realtgt
, pap
->pa_as
,
1153 buf
, sizeof (buf
), value
)) >= 0 && strisprint(buf
)) {
1154 if (len
== sizeof (buf
))
1155 (void) strabbr(buf
, sizeof (buf
));
1156 mdb_printf(" \"%s\"", buf
);
1165 * Print out a fixed-size array. We special-case arrays of characters
1166 * and attempt to print them out as ASCII strings if possible. For other
1167 * arrays, we iterate over a maximum of pa_armemlim members and call
1168 * mdb_ctf_type_visit() again on each element to print its value.
1172 print_array(const char *type
, const char *name
, mdb_ctf_id_t id
,
1173 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1175 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
1176 printarg_t pa
= *pap
;
1180 uint_t i
, kind
, limit
;
1185 if (!(pap
->pa_flags
& PA_SHOWVAL
))
1188 if (pap
->pa_depth
== pap
->pa_maxdepth
) {
1189 mdb_printf("[ ... ]");
1194 * Determine the base type and size of the array's content. If this
1195 * fails, we cannot print anything and just give up.
1197 if (mdb_ctf_array_info(base
, &r
) == -1 ||
1198 mdb_ctf_type_resolve(r
.mta_contents
, &base
) == -1 ||
1199 (eltsize
= mdb_ctf_type_size(base
)) == -1) {
1200 mdb_printf("[ ??? ] (%s)", mdb_strerror(errno
));
1205 * Read a few bytes and determine if the content appears to be
1206 * printable ASCII characters. If so, read the entire array and
1207 * attempt to display it as a string if it is printable.
1209 if ((pap
->pa_arstrlim
== MDB_ARR_NOLIMIT
||
1210 r
.mta_nelems
<= pap
->pa_arstrlim
) &&
1211 mdb_ctf_type_encoding(base
, &e
) == 0 && IS_CHAR(e
) &&
1212 mdb_tgt_readstr(pap
->pa_tgt
, pap
->pa_as
, buf
,
1213 MIN(sizeof (buf
), r
.mta_nelems
), addr
) > 0 && strisprint(buf
)) {
1215 str
= mdb_alloc(r
.mta_nelems
+ 1, UM_SLEEP
| UM_GC
);
1216 str
[r
.mta_nelems
] = '\0';
1218 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, str
,
1219 r
.mta_nelems
, addr
) != r
.mta_nelems
) {
1220 mdb_warn("failed to read char array at %llx", addr
);
1224 if (strisprint(str
)) {
1225 mdb_printf("[ \"%s\" ]", str
);
1230 if (pap
->pa_armemlim
!= MDB_ARR_NOLIMIT
)
1231 limit
= MIN(r
.mta_nelems
, pap
->pa_armemlim
);
1233 limit
= r
.mta_nelems
;
1236 mdb_printf("[ ... ]");
1240 kind
= mdb_ctf_type_kind(base
);
1241 sou
= IS_COMPOSITE(kind
);
1243 pa
.pa_addr
= addr
; /* set base address to start of array */
1244 pa
.pa_maxdepth
= pa
.pa_maxdepth
- pa
.pa_depth
- 1;
1245 pa
.pa_nest
+= pa
.pa_depth
+ 1; /* nesting level is current depth + 1 */
1246 pa
.pa_depth
= 0; /* reset depth to 0 for new scope */
1247 pa
.pa_prefix
= NULL
;
1253 pa
.pa_flags
&= ~(PA_SHOWTYPE
| PA_SHOWNAME
| PA_SHOWADDR
);
1258 for (i
= 0; i
< limit
; i
++, pa
.pa_addr
+= eltsize
) {
1259 if (i
== limit
- 1 && !sou
) {
1260 if (limit
< r
.mta_nelems
)
1261 pa
.pa_delim
= ", ... ]";
1266 if (mdb_ctf_type_visit(r
.mta_contents
, elt_print
, &pa
) == -1) {
1267 mdb_warn("failed to print array data");
1273 for (d
= pa
.pa_depth
- 1; d
>= 0; d
--)
1274 print_close_sou(&pa
, d
);
1276 if (limit
< r
.mta_nelems
) {
1277 mdb_printf("%*s... ]",
1278 (pap
->pa_depth
+ pap
->pa_nest
) * pap
->pa_tab
, "");
1281 (pap
->pa_depth
+ pap
->pa_nest
) * pap
->pa_tab
, "");
1285 /* copy the hole array info, since it may have been grown */
1286 pap
->pa_holes
= pa
.pa_holes
;
1287 pap
->pa_nholes
= pa
.pa_nholes
;
1293 * Print out a struct or union header. We need only print the open brace
1294 * because mdb_ctf_type_visit() itself will automatically recurse through
1295 * all members of the given struct or union.
1299 print_sou(const char *type
, const char *name
, mdb_ctf_id_t id
,
1300 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1302 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
1305 * We have pretty-printing for some structures where displaying
1306 * structure contents has no value.
1308 if (pap
->pa_flags
& PA_SHOWVAL
) {
1309 if (strcmp(type
, "in6_addr_t") == 0 ||
1310 strcmp(type
, "struct in6_addr") == 0) {
1313 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &in6addr
,
1314 sizeof (in6addr
), addr
) != sizeof (in6addr
)) {
1315 mdb_warn("failed to read %s pointer at %llx",
1319 mdb_printf("%N", &in6addr
);
1321 * Don't print anything further down in the
1324 pap
->pa_nooutdepth
= pap
->pa_depth
;
1327 if (strcmp(type
, "struct in_addr") == 0) {
1330 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &inaddr
,
1331 sizeof (inaddr
), addr
) != sizeof (inaddr
)) {
1332 mdb_warn("failed to read %s pointer at %llx",
1336 mdb_printf("%I", inaddr
);
1337 pap
->pa_nooutdepth
= pap
->pa_depth
;
1342 if (pap
->pa_depth
== pap
->pa_maxdepth
)
1343 mdb_printf("{ ... }");
1346 pap
->pa_delim
= "\n";
1351 * Print an enum value. We attempt to convert the value to the corresponding
1352 * enum name and print that if possible.
1356 print_enum(const char *type
, const char *name
, mdb_ctf_id_t id
,
1357 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1359 mdb_tgt_addr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
1362 int isp2
= enum_is_p2(base
);
1363 int flags
= pap
->pa_flags
| (isp2
? PA_INTHEX
: 0);
1365 if (!(flags
& PA_SHOWVAL
))
1368 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
,
1369 &value
, sizeof (value
), addr
) != sizeof (value
)) {
1370 mdb_warn("failed to read %s integer at %llx", name
, addr
);
1374 if (flags
& PA_INTHEX
)
1375 mdb_printf("%#x", value
);
1377 mdb_printf("%#d", value
);
1379 (void) mdb_inc_indent(8);
1382 if (!isp2
|| enum_value_print_p2(base
, value
, 0) != 0) {
1383 ename
= mdb_ctf_enum_name(base
, value
);
1384 if (ename
== NULL
) {
1387 mdb_printf("%s", ename
);
1390 (void) mdb_dec_indent(8);
1396 * This will only get called if the structure isn't found in any available CTF
1401 print_tag(const char *type
, const char *name
, mdb_ctf_id_t id
,
1402 mdb_ctf_id_t base
, ulong_t off
, printarg_t
*pap
)
1404 char basename
[MDB_SYM_NAMLEN
];
1406 if (pap
->pa_flags
& PA_SHOWVAL
)
1409 if (mdb_ctf_type_name(base
, basename
, sizeof (basename
)) != NULL
)
1410 mdb_printf("<forward declaration of %s>", basename
);
1412 mdb_printf("<forward declaration of unknown type>");
1418 print_hole(printarg_t
*pap
, int depth
, ulong_t off
, ulong_t endoff
)
1420 ulong_t bits
= endoff
- off
;
1421 ulong_t size
= bits
/ NBBY
;
1424 static const char *const name
= "<<HOLE>>";
1425 char type
[MDB_SYM_NAMLEN
];
1431 (size
& (size
- 1)) != 0);
1433 ASSERT(off
< endoff
);
1435 if (bits
> NBBY
* sizeof (uint64_t)) {
1439 * The hole is larger than the largest integer type. To
1440 * handle this, we split up the hole at 8-byte-aligned
1441 * boundaries, recursing to print each subsection. For
1442 * normal C structures, we'll loop at most twice.
1444 for (; off
< endoff
; off
= end
) {
1445 end
= P2END(off
, NBBY
* sizeof (uint64_t));
1449 ASSERT((end
- off
) <= NBBY
* sizeof (uint64_t));
1450 print_hole(pap
, depth
, off
, end
);
1452 ASSERT(end
== endoff
);
1458 (void) mdb_snprintf(type
, sizeof (type
), "unsigned");
1460 (void) mdb_snprintf(type
, sizeof (type
), "uint%d_t", bits
);
1462 if (pap
->pa_flags
& (PA_SHOWTYPE
| PA_SHOWNAME
| PA_SHOWADDR
))
1463 mdb_printf("%*s", (depth
+ pap
->pa_nest
) * pap
->pa_tab
, "");
1465 if (pap
->pa_flags
& PA_SHOWADDR
) {
1466 if (off
% NBBY
== 0)
1467 mdb_printf("%llx ", pap
->pa_addr
+ off
/ NBBY
);
1469 mdb_printf("%llx.%lx ",
1470 pap
->pa_addr
+ off
/ NBBY
, off
% NBBY
);
1473 if (pap
->pa_flags
& PA_SHOWTYPE
)
1474 mdb_printf("%s ", type
);
1476 if (pap
->pa_flags
& PA_SHOWNAME
)
1477 mdb_printf("%s", name
);
1479 if (bitfield
&& (pap
->pa_flags
& PA_SHOWTYPE
))
1480 mdb_printf(" :%d", bits
);
1482 mdb_printf("%s ", (pap
->pa_flags
& PA_SHOWVAL
)? " =" : "");
1485 * We fake up a ctf_encoding_t, and use print_int_val() to print
1486 * the value. Holes are always processed as unsigned integers.
1488 bzero(&e
, sizeof (e
));
1493 if (print_int_val(type
, &e
, off
, pap
) != 0)
1494 mdb_iob_discard(mdb
.m_out
);
1496 mdb_iob_puts(mdb
.m_out
, pap
->pa_delim
);
1500 * The print_close_sou() function is called for each structure or union
1501 * which has been completed. For structures, we detect and print any holes
1502 * before printing the closing brace.
1505 print_close_sou(printarg_t
*pap
, int newdepth
)
1507 int d
= newdepth
+ pap
->pa_nest
;
1509 if ((pap
->pa_flags
& PA_SHOWHOLES
) && !pap
->pa_holes
[d
].hi_isunion
) {
1510 ulong_t end
= pap
->pa_holes
[d
+ 1].hi_offset
;
1511 ulong_t expected
= pap
->pa_holes
[d
].hi_offset
;
1514 print_hole(pap
, newdepth
+ 1, end
, expected
);
1516 /* if the struct is an array element, print a comma after the } */
1517 mdb_printf("%*s}%s\n", d
* pap
->pa_tab
, "",
1518 (newdepth
== 0 && pap
->pa_nest
> 0)? "," : "");
1521 static printarg_f
*const printfuncs
[] = {
1522 print_int
, /* CTF_K_INTEGER */
1523 print_float
, /* CTF_K_FLOAT */
1524 print_ptr
, /* CTF_K_POINTER */
1525 print_array
, /* CTF_K_ARRAY */
1526 print_ptr
, /* CTF_K_FUNCTION */
1527 print_sou
, /* CTF_K_STRUCT */
1528 print_sou
, /* CTF_K_UNION */
1529 print_enum
, /* CTF_K_ENUM */
1530 print_tag
/* CTF_K_FORWARD */
1534 * The elt_print function is used as the mdb_ctf_type_visit callback. For
1535 * each element, we print an appropriate name prefix and then call the
1536 * print subroutine for this type class in the array above.
1539 elt_print(const char *name
, mdb_ctf_id_t id
, mdb_ctf_id_t base
,
1540 ulong_t off
, int depth
, void *data
)
1542 char type
[MDB_SYM_NAMLEN
+ sizeof (" <<12345678...>>")];
1544 printarg_t
*pap
= data
;
1546 for (d
= pap
->pa_depth
- 1; d
>= depth
; d
--) {
1547 if (d
< pap
->pa_nooutdepth
)
1548 print_close_sou(pap
, d
);
1552 * Reset pa_nooutdepth if we've come back out of the structure we
1553 * didn't want to print.
1555 if (depth
<= pap
->pa_nooutdepth
)
1556 pap
->pa_nooutdepth
= (uint_t
)-1;
1558 if (depth
> pap
->pa_maxdepth
|| depth
> pap
->pa_nooutdepth
)
1561 if (!mdb_ctf_type_valid(base
) ||
1562 (kind
= mdb_ctf_type_kind(base
)) == -1)
1563 return (-1); /* errno is set for us */
1565 if (mdb_ctf_type_name(id
, type
, MDB_SYM_NAMLEN
) == NULL
)
1566 (void) strcpy(type
, "(?)");
1568 if (pap
->pa_flags
& PA_SHOWBASETYPE
) {
1570 * If basetype is different and informative, concatenate
1571 * <<basetype>> (or <<baset...>> if it doesn't fit)
1573 * We just use the end of the buffer to store the type name, and
1574 * only connect it up if that's necessary.
1577 char *type_end
= type
+ strlen(type
);
1581 (void) strlcat(type
, " <<", sizeof (type
));
1583 basetype
= type
+ strlen(type
);
1584 sz
= sizeof (type
) - (basetype
- type
);
1586 *type_end
= '\0'; /* restore the end of type for strcmp() */
1588 if (mdb_ctf_type_name(base
, basetype
, sz
) != NULL
&&
1589 strcmp(basetype
, type
) != 0 &&
1590 strcmp(basetype
, "struct ") != 0 &&
1591 strcmp(basetype
, "enum ") != 0 &&
1592 strcmp(basetype
, "union ") != 0) {
1593 type_end
[0] = ' '; /* reconnect */
1594 if (strlcat(type
, ">>", sizeof (type
)) >= sizeof (type
))
1596 type
+ sizeof (type
) - 6, "...>>", 6);
1600 if (pap
->pa_flags
& PA_SHOWHOLES
) {
1605 int extra
= IS_COMPOSITE(kind
)? 1 : 0;
1608 * grow the hole array, if necessary
1610 if (pap
->pa_nest
+ depth
+ extra
>= pap
->pa_nholes
) {
1611 int new = MAX(MAX(8, pap
->pa_nholes
* 2),
1612 pap
->pa_nest
+ depth
+ extra
+ 1);
1614 holeinfo_t
*nhi
= mdb_zalloc(
1615 sizeof (*nhi
) * new, UM_NOSLEEP
| UM_GC
);
1617 bcopy(pap
->pa_holes
, nhi
,
1618 pap
->pa_nholes
* sizeof (*nhi
));
1620 pap
->pa_holes
= nhi
;
1621 pap
->pa_nholes
= new;
1624 hole
= &pap
->pa_holes
[depth
+ pap
->pa_nest
];
1626 if (depth
!= 0 && off
> hole
->hi_offset
)
1627 print_hole(pap
, depth
, hole
->hi_offset
, off
);
1629 /* compute the next expected offset */
1630 if (kind
== CTF_K_INTEGER
&&
1631 mdb_ctf_type_encoding(base
, &e
) == 0)
1632 newoff
= off
+ e
.cte_bits
;
1633 else if ((nsize
= mdb_ctf_type_size(base
)) >= 0)
1634 newoff
= off
+ nsize
* NBBY
;
1636 /* something bad happened, disable hole checking */
1637 newoff
= -1UL; /* ULONG_MAX */
1640 hole
->hi_offset
= newoff
;
1642 if (IS_COMPOSITE(kind
)) {
1643 hole
->hi_isunion
= (kind
== CTF_K_UNION
);
1645 hole
->hi_offset
= off
;
1649 if (pap
->pa_flags
& (PA_SHOWTYPE
| PA_SHOWNAME
| PA_SHOWADDR
))
1650 mdb_printf("%*s", (depth
+ pap
->pa_nest
) * pap
->pa_tab
, "");
1652 if (pap
->pa_flags
& PA_SHOWADDR
) {
1653 if (off
% NBBY
== 0)
1654 mdb_printf("%llx ", pap
->pa_addr
+ off
/ NBBY
);
1656 mdb_printf("%llx.%lx ",
1657 pap
->pa_addr
+ off
/ NBBY
, off
% NBBY
);
1660 if ((pap
->pa_flags
& PA_SHOWTYPE
)) {
1661 mdb_printf("%s", type
);
1663 * We want to avoid printing a trailing space when
1664 * dealing with pointers in a structure, so we end
1667 * label_t *t_onfault = 0
1669 * If depth is zero, always print the trailing space unless
1670 * we also have a prefix.
1672 if (type
[strlen(type
) - 1] != '*' ||
1673 (depth
== 0 && (!(pap
->pa_flags
& PA_SHOWNAME
) ||
1674 pap
->pa_prefix
== NULL
)))
1678 if (pap
->pa_flags
& PA_SHOWNAME
) {
1679 if (pap
->pa_prefix
!= NULL
&& depth
<= 1)
1680 mdb_printf("%s%s", pap
->pa_prefix
,
1681 (depth
== 0) ? "" : pap
->pa_suffix
);
1682 mdb_printf("%s", name
);
1685 if ((pap
->pa_flags
& PA_SHOWTYPE
) && kind
== CTF_K_INTEGER
) {
1688 if (mdb_ctf_type_encoding(base
, &e
) == 0) {
1689 ulong_t bits
= e
.cte_bits
;
1690 ulong_t size
= bits
/ NBBY
;
1692 if (bits
% NBBY
!= 0 ||
1695 size
!= mdb_ctf_type_size(base
))
1696 mdb_printf(" :%d", bits
);
1701 ((pap
->pa_flags
& PA_SHOWNAME
) && pap
->pa_prefix
!= NULL
))
1702 mdb_printf("%s ", pap
->pa_flags
& PA_SHOWVAL
? " =" : "");
1704 if (depth
== 0 && pap
->pa_prefix
!= NULL
)
1705 name
= pap
->pa_prefix
;
1707 pap
->pa_depth
= depth
;
1708 if (kind
<= CTF_K_UNKNOWN
|| kind
>= CTF_K_TYPEDEF
) {
1709 mdb_warn("unknown ctf for %s type %s kind %d\n",
1713 rc
= printfuncs
[kind
- 1](type
, name
, id
, base
, off
, pap
);
1716 mdb_iob_discard(mdb
.m_out
);
1718 mdb_iob_puts(mdb
.m_out
, pap
->pa_delim
);
1724 * Special semantics for pipelines.
1727 pipe_print(mdb_ctf_id_t id
, ulong_t off
, void *data
)
1729 printarg_t
*pap
= data
;
1731 static const char *const fsp
[] = { "%#r", "%#r", "%#r", "%#llr" };
1733 uintptr_t addr
= pap
->pa_addr
+ off
/ NBBY
;
1745 if (mdb_ctf_type_resolve(id
, &base
) == -1) {
1746 mdb_warn("could not resolve type");
1751 * If the user gives -a, then always print out the address of the
1754 if ((pap
->pa_flags
& PA_SHOWADDR
)) {
1755 mdb_printf("%#lr\n", addr
);
1760 switch (mdb_ctf_type_kind(base
)) {
1762 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
,
1763 &value
, sizeof (value
), addr
) != sizeof (value
)) {
1764 mdb_warn("failed to read pointer at %p", addr
);
1767 mdb_printf("%#lr\n", value
);
1771 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &enum_value
,
1772 sizeof (enum_value
), addr
) != sizeof (enum_value
)) {
1773 mdb_warn("failed to read enum at %llx", addr
);
1776 mdb_printf("%#r\n", enum_value
);
1780 if (mdb_ctf_type_encoding(base
, &e
) != 0) {
1781 mdb_warn("could not get type encoding\n");
1786 * For immediate values, we just print out the value.
1788 size
= e
.cte_bits
/ NBBY
;
1789 if (size
> 8 || (e
.cte_bits
% NBBY
) != 0 ||
1790 (size
& (size
- 1)) != 0) {
1791 return (print_bitfield(off
, pap
, &e
));
1794 if (mdb_tgt_aread(pap
->pa_tgt
, pap
->pa_as
, &u
.i8
, size
,
1796 mdb_warn("failed to read %lu bytes at %p",
1797 (ulong_t
)size
, pap
->pa_addr
);
1802 case sizeof (uint8_t):
1803 mdb_printf(fsp
[0], u
.i1
);
1805 case sizeof (uint16_t):
1806 mdb_printf(fsp
[1], u
.i2
);
1808 case sizeof (uint32_t):
1809 mdb_printf(fsp
[2], u
.i4
);
1811 case sizeof (uint64_t):
1812 mdb_printf(fsp
[3], u
.i8
);
1818 case CTF_K_FUNCTION
:
1826 * For these types, always print the address of the member
1828 mdb_printf("%#lr\n", addr
);
1832 mdb_warn("unknown type %d", mdb_ctf_type_kind(base
));
1840 parse_delimiter(char **strp
)
1844 return (MEMBER_DELIM_DONE
);
1848 return (MEMBER_DELIM_DOT
);
1852 return (MEMBER_DELIM_LBR
);
1856 if (**strp
== '>') {
1858 return (MEMBER_DELIM_PTR
);
1863 return (MEMBER_DELIM_ERR
);
1868 deref(printarg_t
*pap
, size_t size
)
1871 mdb_tgt_as_t as
= pap
->pa_as
;
1872 mdb_tgt_addr_t
*ap
= &pap
->pa_addr
;
1874 if (size
== sizeof (mdb_tgt_addr_t
)) {
1875 if (mdb_tgt_aread(mdb
.m_target
, as
, ap
, size
, *ap
) == -1) {
1876 mdb_warn("could not dereference pointer %llx\n", *ap
);
1880 if (mdb_tgt_aread(mdb
.m_target
, as
, &a32
, size
, *ap
) == -1) {
1881 mdb_warn("could not dereference pointer %x\n", *ap
);
1885 *ap
= (mdb_tgt_addr_t
)a32
;
1889 * We've dereferenced at least once, we must be on the real
1890 * target. If we were in the immediate target, reset to the real
1891 * target; it's reset as needed when we return to the print
1894 if (pap
->pa_tgt
== pap
->pa_immtgt
)
1895 pap
->pa_tgt
= pap
->pa_realtgt
;
1901 parse_member(printarg_t
*pap
, const char *str
, mdb_ctf_id_t id
,
1902 mdb_ctf_id_t
*idp
, ulong_t
*offp
, int *last_deref
)
1908 char *start
= (char *)str
;
1911 mdb_ctf_arinfo_t ar
;
1915 int non_array
= FALSE
;
1918 * id always has the unresolved type for printing error messages
1919 * that include the type; rid always has the resolved type for
1920 * use in mdb_ctf_* calls. It is possible for this command to fail,
1921 * however, if the resolved type is in the parent and it is currently
1922 * unavailable. Note that we also can't print out the name of the
1923 * type, since that would also rely on looking up the resolved name.
1925 if (mdb_ctf_type_resolve(id
, &rid
) != 0) {
1926 mdb_warn("failed to resolve type");
1930 delim
= parse_delimiter(&start
);
1932 * If the user fails to specify an initial delimiter, guess -> for
1933 * pointer types and . for non-pointer types.
1935 if (delim
== MEMBER_DELIM_ERR
)
1936 delim
= (mdb_ctf_type_kind(rid
) == CTF_K_POINTER
) ?
1937 MEMBER_DELIM_PTR
: MEMBER_DELIM_DOT
;
1939 *last_deref
= FALSE
;
1941 while (delim
!= MEMBER_DELIM_DONE
) {
1943 case MEMBER_DELIM_PTR
:
1944 kind
= mdb_ctf_type_kind(rid
);
1945 if (kind
!= CTF_K_POINTER
) {
1946 mdb_warn("%s is not a pointer type\n",
1947 mdb_ctf_type_name(id
, buf
, sizeof (buf
)));
1951 size
= mdb_ctf_type_size(id
);
1952 if (deref(pap
, size
) != 0)
1955 (void) mdb_ctf_type_reference(rid
, &id
);
1956 (void) mdb_ctf_type_resolve(id
, &rid
);
1961 case MEMBER_DELIM_DOT
:
1962 kind
= mdb_ctf_type_kind(rid
);
1963 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
) {
1964 mdb_warn("%s is not a struct or union type\n",
1965 mdb_ctf_type_name(id
, buf
, sizeof (buf
)));
1970 case MEMBER_DELIM_LBR
:
1971 end
= strchr(start
, ']');
1973 mdb_warn("no trailing ']'\n");
1977 (void) mdb_snprintf(member
, end
- start
+ 1, "%s",
1980 index
= mdb_strtoull(member
);
1982 switch (mdb_ctf_type_kind(rid
)) {
1984 size
= mdb_ctf_type_size(rid
);
1986 if (deref(pap
, size
) != 0)
1989 (void) mdb_ctf_type_reference(rid
, &id
);
1990 (void) mdb_ctf_type_resolve(id
, &rid
);
1992 size
= mdb_ctf_type_size(id
);
1994 mdb_warn("cannot dereference void "
1999 pap
->pa_addr
+= index
* size
;
2002 if (index
== 0 && non_array
)
2007 (void) mdb_ctf_array_info(rid
, &ar
);
2009 if (index
>= ar
.mta_nelems
) {
2010 mdb_warn("index %r is outside of "
2011 "array bounds [0 .. %r]\n",
2012 index
, ar
.mta_nelems
- 1);
2015 id
= ar
.mta_contents
;
2016 (void) mdb_ctf_type_resolve(id
, &rid
);
2018 size
= mdb_ctf_type_size(id
);
2020 mdb_warn("cannot dereference void "
2025 pap
->pa_addr
+= index
* size
;
2030 mdb_warn("cannot index into non-array, "
2031 "non-pointer type\n");
2036 delim
= parse_delimiter(&start
);
2039 case MEMBER_DELIM_ERR
:
2041 mdb_warn("'%c' is not a valid delimiter\n", *start
);
2045 *last_deref
= FALSE
;
2049 * Find the end of the member name; assume that a member
2050 * name is at least one character long.
2052 for (end
= start
+ 1; isalnum(*end
) || *end
== '_'; end
++)
2055 (void) mdb_snprintf(member
, end
- start
+ 1, "%s", start
);
2057 if (mdb_ctf_member_info(rid
, member
, &off
, &id
) != 0) {
2058 mdb_warn("failed to find member %s of %s", member
,
2059 mdb_ctf_type_name(id
, buf
, sizeof (buf
)));
2062 (void) mdb_ctf_type_resolve(id
, &rid
);
2064 pap
->pa_addr
+= off
/ NBBY
;
2067 delim
= parse_delimiter(&start
);
2077 cmd_print_tab_common(mdb_tab_cookie_t
*mcp
, uint_t flags
, int argc
,
2078 const mdb_arg_t
*argv
)
2080 char tn
[MDB_SYM_NAMLEN
];
2084 mdb_ctf_id_t id
, rid
;
2085 mdb_ctf_arinfo_t ar
;
2089 if (argc
== 0 && !(flags
& DCMD_TAB_SPACE
))
2092 if (argc
== 0 && (flags
& DCMD_TAB_SPACE
))
2093 return (mdb_tab_complete_type(mcp
, NULL
, MDB_TABC_NOPOINT
|
2096 if ((ret
= mdb_tab_typename(&argc
, &argv
, tn
, sizeof (tn
))) < 0)
2099 if (argc
== 1 && (!(flags
& DCMD_TAB_SPACE
) || ret
== 1))
2100 return (mdb_tab_complete_type(mcp
, tn
, MDB_TABC_NOPOINT
|
2103 if (argc
== 1 && (flags
& DCMD_TAB_SPACE
))
2104 return (mdb_tab_complete_member(mcp
, tn
, NULL
));
2107 * This is the reason that tab completion was created. We're going to go
2108 * along and walk the delimiters until we find something a member that
2109 * we don't recognize, at which point we'll try and tab complete it.
2110 * Note that ::print takes multiple args, so this is going to operate on
2111 * whatever the last arg that we have is.
2113 if (mdb_ctf_lookup_by_name(tn
, &id
) != 0)
2116 (void) mdb_ctf_type_resolve(id
, &rid
);
2117 start
= (char *)argv
[argc
-1].a_un
.a_str
;
2118 delim
= parse_delimiter(&start
);
2121 * If we hit the case where we actually have no delimiters, than we need
2122 * to make sure that we properly set up the fields the loops would.
2124 if (delim
== MEMBER_DELIM_DONE
)
2125 (void) mdb_snprintf(member
, sizeof (member
), "%s", start
);
2127 while (delim
!= MEMBER_DELIM_DONE
) {
2129 case MEMBER_DELIM_PTR
:
2130 kind
= mdb_ctf_type_kind(rid
);
2131 if (kind
!= CTF_K_POINTER
)
2134 (void) mdb_ctf_type_reference(rid
, &id
);
2135 (void) mdb_ctf_type_resolve(id
, &rid
);
2137 case MEMBER_DELIM_DOT
:
2138 kind
= mdb_ctf_type_kind(rid
);
2139 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
2142 case MEMBER_DELIM_LBR
:
2143 end
= strchr(start
, ']');
2145 * We're not going to try and tab complete the indexes
2146 * here. So for now, punt on it. Also, we're not going
2147 * to try and validate you're within the bounds, just
2148 * that you get the type you asked for.
2153 switch (mdb_ctf_type_kind(rid
)) {
2155 (void) mdb_ctf_type_reference(rid
, &id
);
2156 (void) mdb_ctf_type_resolve(id
, &rid
);
2159 (void) mdb_ctf_array_info(rid
, &ar
);
2160 id
= ar
.mta_contents
;
2161 (void) mdb_ctf_type_resolve(id
, &rid
);
2168 delim
= parse_delimiter(&start
);
2170 case MEMBER_DELIM_ERR
:
2175 for (end
= start
+ 1; isalnum(*end
) || *end
== '_'; end
++)
2178 (void) mdb_snprintf(member
, end
- start
+ 1, start
);
2181 * We are going to try to resolve this name as a member. There
2182 * are a few two different questions that we need to answer. The
2183 * first is do we recognize this member. The second is are we at
2184 * the end of the string. If we encounter a member that we don't
2185 * recognize before the end, then we have to error out and can't
2186 * complete it. But if there are no more delimiters then we can
2187 * try and complete it.
2189 ret
= mdb_ctf_member_info(rid
, member
, &dul
, &id
);
2191 delim
= parse_delimiter(&start
);
2192 if (ret
!= 0 && errno
== EMDB_CTFNOMEMB
) {
2193 if (delim
!= MEMBER_DELIM_DONE
)
2196 } else if (ret
!= 0)
2199 if (delim
== MEMBER_DELIM_DONE
)
2200 return (mdb_tab_complete_member_by_id(mcp
, rid
,
2203 (void) mdb_ctf_type_resolve(id
, &rid
);
2207 * If we've reached here, then we need to try and tab complete the last
2208 * field, which is currently member, based on the ctf type id that we
2209 * already have in rid.
2211 return (mdb_tab_complete_member_by_id(mcp
, rid
, member
));
2215 cmd_print_tab(mdb_tab_cookie_t
*mcp
, uint_t flags
, int argc
,
2216 const mdb_arg_t
*argv
)
2221 * This getopts is only here to make the tab completion work better when
2222 * including options in the ::print arguments. None of the values should
2223 * be used. This should only be updated with additional arguments, if
2224 * they are added to cmd_print.
2226 i
= mdb_getopts(argc
, argv
,
2227 'a', MDB_OPT_SETBITS
, PA_SHOWADDR
, &dummy
,
2228 'C', MDB_OPT_SETBITS
, TRUE
, &dummy
,
2229 'c', MDB_OPT_UINTPTR
, &dummy
,
2230 'd', MDB_OPT_SETBITS
, PA_INTDEC
, &dummy
,
2231 'h', MDB_OPT_SETBITS
, PA_SHOWHOLES
, &dummy
,
2232 'i', MDB_OPT_SETBITS
, TRUE
, &dummy
,
2233 'L', MDB_OPT_SETBITS
, TRUE
, &dummy
,
2234 'l', MDB_OPT_UINTPTR
, &dummy
,
2235 'n', MDB_OPT_SETBITS
, PA_NOSYMBOLIC
, &dummy
,
2236 'p', MDB_OPT_SETBITS
, TRUE
, &dummy
,
2237 's', MDB_OPT_UINTPTR
, &dummy
,
2238 'T', MDB_OPT_SETBITS
, PA_SHOWTYPE
| PA_SHOWBASETYPE
, &dummy
,
2239 't', MDB_OPT_SETBITS
, PA_SHOWTYPE
, &dummy
,
2240 'x', MDB_OPT_SETBITS
, PA_INTHEX
, &dummy
,
2246 return (cmd_print_tab_common(mcp
, flags
, argc
, argv
));
2250 * Recursively descend a print a given data structure. We create a struct of
2251 * the relevant print arguments and then call mdb_ctf_type_visit() to do the
2252 * traversal, using elt_print() as the callback for each element.
2256 cmd_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2258 uintptr_t opt_c
= MDB_ARR_NOLIMIT
, opt_l
= MDB_ARR_NOLIMIT
;
2259 uint_t opt_C
= FALSE
, opt_L
= FALSE
, opt_p
= FALSE
, opt_i
= FALSE
;
2260 uintptr_t opt_s
= (uintptr_t)-1ul;
2261 int uflags
= (flags
& DCMD_ADDRSPEC
) ? PA_SHOWVAL
: 0;
2265 mdb_tgt_t
*t
= mdb
.m_target
;
2269 char s_name
[MDB_SYM_NAMLEN
];
2270 mdb_syminfo_t s_info
;
2274 * If a new option is added, make sure the getopts above in
2275 * cmd_print_tab is also updated.
2277 i
= mdb_getopts(argc
, argv
,
2278 'a', MDB_OPT_SETBITS
, PA_SHOWADDR
, &uflags
,
2279 'C', MDB_OPT_SETBITS
, TRUE
, &opt_C
,
2280 'c', MDB_OPT_UINTPTR
, &opt_c
,
2281 'd', MDB_OPT_SETBITS
, PA_INTDEC
, &uflags
,
2282 'h', MDB_OPT_SETBITS
, PA_SHOWHOLES
, &uflags
,
2283 'i', MDB_OPT_SETBITS
, TRUE
, &opt_i
,
2284 'L', MDB_OPT_SETBITS
, TRUE
, &opt_L
,
2285 'l', MDB_OPT_UINTPTR
, &opt_l
,
2286 'n', MDB_OPT_SETBITS
, PA_NOSYMBOLIC
, &uflags
,
2287 'p', MDB_OPT_SETBITS
, TRUE
, &opt_p
,
2288 's', MDB_OPT_UINTPTR
, &opt_s
,
2289 'T', MDB_OPT_SETBITS
, PA_SHOWTYPE
| PA_SHOWBASETYPE
, &uflags
,
2290 't', MDB_OPT_SETBITS
, PA_SHOWTYPE
, &uflags
,
2291 'x', MDB_OPT_SETBITS
, PA_INTHEX
, &uflags
,
2294 if (uflags
& PA_INTHEX
)
2295 uflags
&= ~PA_INTDEC
; /* -x and -d are mutually exclusive */
2297 uflags
|= PA_SHOWNAME
;
2299 if (opt_p
&& opt_i
) {
2300 mdb_warn("-p and -i options are incompatible\n");
2307 if (argc
!= 0 && argv
->a_type
== MDB_TYPE_STRING
) {
2308 const char *t_name
= s_name
;
2311 if (strchr("+-", argv
->a_un
.a_str
[0]) != NULL
)
2312 return (DCMD_USAGE
);
2314 if ((ret
= args_to_typename(&argc
, &argv
, s_name
,
2315 sizeof (s_name
))) != 0)
2318 if (mdb_ctf_lookup_by_name(t_name
, &id
) != 0) {
2319 if (!(flags
& DCMD_ADDRSPEC
) || opt_i
||
2320 addr_to_sym(t
, addr
, s_name
, sizeof (s_name
),
2321 &sym
, &s_info
) == NULL
||
2322 mdb_ctf_lookup_by_symbol(&sym
, &s_info
, &id
) != 0) {
2324 mdb_warn("failed to look up type %s", t_name
);
2325 return (DCMD_ABORT
);
2332 } else if (!(flags
& DCMD_ADDRSPEC
) || opt_i
) {
2333 return (DCMD_USAGE
);
2335 } else if (addr_to_sym(t
, addr
, s_name
, sizeof (s_name
),
2336 &sym
, &s_info
) == NULL
) {
2337 mdb_warn("no symbol information for %a", addr
);
2340 } else if (mdb_ctf_lookup_by_symbol(&sym
, &s_info
, &id
) != 0) {
2341 mdb_warn("no type data available for %a [%u]", addr
,
2346 pa
.pa_tgt
= mdb
.m_target
;
2347 pa
.pa_realtgt
= pa
.pa_tgt
;
2348 pa
.pa_immtgt
= NULL
;
2349 pa
.pa_as
= opt_p
? MDB_TGT_AS_PHYS
: MDB_TGT_AS_VIRT
;
2350 pa
.pa_armemlim
= mdb
.m_armemlim
;
2351 pa
.pa_arstrlim
= mdb
.m_arstrlim
;
2353 pa
.pa_flags
= uflags
;
2356 pa
.pa_prefix
= NULL
;
2357 pa
.pa_suffix
= NULL
;
2361 pa
.pa_maxdepth
= opt_s
;
2362 pa
.pa_nooutdepth
= (uint_t
)-1;
2364 if ((flags
& DCMD_ADDRSPEC
) && !opt_i
)
2365 pa
.pa_addr
= opt_p
? mdb_get_dot() : addr
;
2370 const char *vargv
[2];
2371 uintmax_t dot
= mdb_get_dot();
2372 size_t outsize
= mdb_ctf_type_size(id
);
2373 vargv
[0] = (const char *)&dot
;
2374 vargv
[1] = (const char *)&outsize
;
2375 pa
.pa_immtgt
= mdb_tgt_create(mdb_value_tgt_create
,
2377 pa
.pa_tgt
= pa
.pa_immtgt
;
2380 if (opt_c
!= MDB_ARR_NOLIMIT
)
2381 pa
.pa_arstrlim
= opt_c
;
2383 pa
.pa_arstrlim
= MDB_ARR_NOLIMIT
;
2384 if (opt_l
!= MDB_ARR_NOLIMIT
)
2385 pa
.pa_armemlim
= opt_l
;
2387 pa
.pa_armemlim
= MDB_ARR_NOLIMIT
;
2390 for (i
= 0; i
< argc
; i
++) {
2395 char buf
[MDB_SYM_NAMLEN
];
2397 mdb_tgt_t
*oldtgt
= pa
.pa_tgt
;
2398 mdb_tgt_as_t oldas
= pa
.pa_as
;
2399 mdb_tgt_addr_t oldaddr
= pa
.pa_addr
;
2401 if (argv
->a_type
== MDB_TYPE_STRING
) {
2402 const char *member
= argv
[i
].a_un
.a_str
;
2405 if (parse_member(&pa
, member
, id
, &mid
,
2406 &off
, &last_deref
) != 0) {
2412 * If the member string ends with a "[0]"
2413 * (last_deref * is true) and the type is a
2414 * structure or union, * print "->" rather
2415 * than "[0]." in elt_print.
2417 (void) mdb_ctf_type_resolve(mid
, &rid
);
2418 kind
= mdb_ctf_type_kind(rid
);
2419 if (last_deref
&& IS_SOU(kind
)) {
2421 (void) mdb_snprintf(buf
, sizeof (buf
),
2423 end
= strrchr(buf
, '[');
2425 pa
.pa_suffix
= "->";
2427 } else if (IS_SOU(kind
)) {
2433 pa
.pa_prefix
= member
;
2437 moff
= (ulong_t
)argv
[i
].a_un
.a_val
;
2439 if (mdb_ctf_offset_to_name(id
, moff
* NBBY
,
2440 buf
, sizeof (buf
), 0, &mid
, &off
) == -1) {
2441 mdb_warn("invalid offset %lx\n", moff
);
2447 pa
.pa_addr
+= moff
- off
/ NBBY
;
2448 pa
.pa_suffix
= strlen(buf
) == 0 ? "" : ".";
2452 if (flags
& DCMD_PIPE_OUT
) {
2453 if (pipe_print(mid
, off
, &pa
) != 0) {
2454 mdb_warn("failed to print type");
2458 } else if (off
!= 0) {
2460 (void) mdb_ctf_type_resolve(mid
, &base
);
2462 if (elt_print("", mid
, base
, off
, 0,
2464 mdb_warn("failed to print type");
2469 if (mdb_ctf_type_visit(mid
, elt_print
,
2471 mdb_warn("failed to print type");
2476 for (d
= pa
.pa_depth
- 1; d
>= 0; d
--)
2477 print_close_sou(&pa
, d
);
2483 pa
.pa_addr
= oldaddr
;
2487 } else if (flags
& DCMD_PIPE_OUT
) {
2488 if (pipe_print(id
, 0, &pa
) != 0) {
2489 mdb_warn("failed to print type");
2494 if (mdb_ctf_type_visit(id
, elt_print
, &pa
) == -1) {
2495 mdb_warn("failed to print type");
2500 for (d
= pa
.pa_depth
- 1; d
>= 0; d
--)
2501 print_close_sou(&pa
, d
);
2504 mdb_set_dot(addr
+ mdb_ctf_type_size(id
));
2508 mdb_tgt_destroy(pa
.pa_immtgt
);
2516 "-a show address of object\n"
2517 "-C unlimit the length of character arrays\n"
2518 "-c limit limit the length of character arrays\n"
2519 "-d output values in decimal\n"
2520 "-h print holes in structures\n"
2521 "-i interpret address as data of the given type\n"
2522 "-L unlimit the length of standard arrays\n"
2523 "-l limit limit the length of standard arrays\n"
2524 "-n don't print pointers as symbol offsets\n"
2525 "-p interpret address as a physical memory address\n"
2526 "-s depth limit the recursion depth\n"
2527 "-T show type and <<base type>> of object\n"
2528 "-t show type of object\n"
2529 "-x output values in hexadecimal\n"
2531 "type may be omitted if the C type of addr can be inferred.\n"
2533 "Members may be specified with standard C syntax using the\n"
2534 "array indexing operator \"[index]\", structure member\n"
2535 "operator \".\", or structure pointer operator \"->\".\n"
2537 "Offsets must use the $[ expression ] syntax\n");
2541 printf_signed(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
,
2559 if (mdb_ctf_type_resolve(id
, &base
) == -1) {
2560 mdb_warn("could not resolve type");
2561 return (DCMD_ABORT
);
2564 switch (mdb_ctf_type_kind(base
)) {
2566 e
.cte_format
= CTF_INT_SIGNED
;
2568 e
.cte_bits
= mdb_ctf_type_size(id
) * NBBY
;
2571 if (mdb_ctf_type_encoding(base
, &e
) != 0) {
2572 mdb_warn("could not get type encoding");
2573 return (DCMD_ABORT
);
2577 mdb_warn("expected integer type\n");
2578 return (DCMD_ABORT
);
2582 sign
= e
.cte_format
& CTF_INT_SIGNED
;
2584 size
= e
.cte_bits
/ NBBY
;
2587 * Check to see if our life has been complicated by the presence of
2588 * a bitfield. If it has, we will print it using logic that is only
2589 * slightly different than that found in print_bitfield(), above. (In
2590 * particular, see the comments there for an explanation of the
2591 * endianness differences in this code.)
2593 if (size
> 8 || (e
.cte_bits
% NBBY
) != 0 ||
2594 (size
& (size
- 1)) != 0) {
2595 uint64_t mask
= (1ULL << e
.cte_bits
) - 1;
2597 uint8_t *buf
= (uint8_t *)&value
;
2601 * Round our size up one byte.
2603 size
= (e
.cte_bits
+ (NBBY
- 1)) / NBBY
;
2605 if (e
.cte_bits
> sizeof (value
) * NBBY
- 1) {
2606 mdb_printf("invalid bitfield size %u", e
.cte_bits
);
2607 return (DCMD_ABORT
);
2611 buf
+= sizeof (value
) - size
;
2615 if (mdb_vread(buf
, size
, addr
) == -1) {
2616 mdb_warn("failed to read %lu bytes at %p", size
, addr
);
2622 shift
= NBBY
- shift
;
2626 * If we have a bit offset within the byte, shift it down.
2628 if (off
% NBBY
!= 0)
2633 int sshift
= sizeof (value
) * NBBY
- e
.cte_bits
;
2634 value
= ((int64_t)value
<< sshift
) >> sshift
;
2637 mdb_printf(fmt
, value
);
2641 if (mdb_vread(&u
.i8
, size
, addr
) == -1) {
2642 mdb_warn("failed to read %lu bytes at %p", (ulong_t
)size
, addr
);
2647 case sizeof (uint8_t):
2648 mdb_printf(fmt
, (uint64_t)(sign
? u
.i1
: u
.ui1
));
2650 case sizeof (uint16_t):
2651 mdb_printf(fmt
, (uint64_t)(sign
? u
.i2
: u
.ui2
));
2653 case sizeof (uint32_t):
2654 mdb_printf(fmt
, (uint64_t)(sign
? u
.i4
: u
.ui4
));
2656 case sizeof (uint64_t):
2657 mdb_printf(fmt
, (uint64_t)(sign
? u
.i8
: u
.ui8
));
2665 printf_int(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
)
2667 return (printf_signed(id
, addr
, off
, fmt
, B_TRUE
));
2671 printf_uint(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
)
2673 return (printf_signed(id
, addr
, off
, fmt
, B_FALSE
));
2678 printf_uint32(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
)
2684 if (mdb_ctf_type_resolve(id
, &base
) == -1) {
2685 mdb_warn("could not resolve type\n");
2686 return (DCMD_ABORT
);
2689 if (mdb_ctf_type_kind(base
) != CTF_K_INTEGER
||
2690 mdb_ctf_type_encoding(base
, &e
) != 0 ||
2691 e
.cte_bits
/ NBBY
!= sizeof (value
)) {
2692 mdb_warn("expected 32-bit integer type\n");
2693 return (DCMD_ABORT
);
2696 if (mdb_vread(&value
, sizeof (value
), addr
) == -1) {
2697 mdb_warn("failed to read 32-bit value at %p", addr
);
2701 mdb_printf(fmt
, value
);
2708 printf_ptr(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
)
2713 if (mdb_ctf_type_resolve(id
, &base
) == -1) {
2714 mdb_warn("could not resolve type\n");
2715 return (DCMD_ABORT
);
2718 if (mdb_ctf_type_kind(base
) != CTF_K_POINTER
) {
2719 mdb_warn("expected pointer type\n");
2720 return (DCMD_ABORT
);
2723 if (mdb_vread(&value
, sizeof (value
), addr
) == -1) {
2724 mdb_warn("failed to read pointer at %llx", addr
);
2728 mdb_printf(fmt
, value
);
2735 printf_string(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
)
2742 if (mdb_ctf_type_resolve(id
, &base
) == -1) {
2743 mdb_warn("could not resolve type");
2744 return (DCMD_ABORT
);
2747 if (mdb_ctf_type_kind(base
) == CTF_K_POINTER
) {
2750 if (mdb_vread(&value
, sizeof (value
), addr
) == -1) {
2751 mdb_warn("failed to read pointer at %llx", addr
);
2755 if (mdb_readstr(buf
, sizeof (buf
) - 1, value
) < 0) {
2756 mdb_warn("failed to read string at %llx", value
);
2760 mdb_printf(fmt
, buf
);
2764 if (mdb_ctf_type_kind(base
) == CTF_K_ENUM
) {
2768 if (mdb_vread(&value
, sizeof (value
), addr
) == -1) {
2769 mdb_warn("failed to read pointer at %llx", addr
);
2773 if ((strval
= mdb_ctf_enum_name(id
, value
))) {
2774 mdb_printf(fmt
, strval
);
2776 (void) mdb_snprintf(buf
, sizeof (buf
), "<%d>", value
);
2777 mdb_printf(fmt
, buf
);
2783 if (mdb_ctf_type_kind(base
) != CTF_K_ARRAY
) {
2784 mdb_warn("exepected pointer or array type\n");
2785 return (DCMD_ABORT
);
2788 if (mdb_ctf_array_info(base
, &r
) == -1 ||
2789 mdb_ctf_type_resolve(r
.mta_contents
, &base
) == -1 ||
2790 (size
= mdb_ctf_type_size(base
)) == -1) {
2791 mdb_warn("can't determine array type");
2792 return (DCMD_ABORT
);
2796 mdb_warn("string format specifier requires "
2797 "an array of characters\n");
2798 return (DCMD_ABORT
);
2801 bzero(buf
, sizeof (buf
));
2803 if (mdb_vread(buf
, MIN(r
.mta_nelems
, sizeof (buf
) - 1), addr
) == -1) {
2804 mdb_warn("failed to read array at %p", addr
);
2808 mdb_printf(fmt
, buf
);
2815 printf_ipv6(mdb_ctf_id_t id
, uintptr_t addr
, ulong_t off
, char *fmt
)
2818 mdb_ctf_id_t ipv6_type
, ipv6_base
;
2821 if (mdb_ctf_lookup_by_name("in6_addr_t", &ipv6_type
) == -1) {
2822 mdb_warn("could not resolve in6_addr_t type\n");
2823 return (DCMD_ABORT
);
2826 if (mdb_ctf_type_resolve(id
, &base
) == -1) {
2827 mdb_warn("could not resolve type\n");
2828 return (DCMD_ABORT
);
2831 if (mdb_ctf_type_resolve(ipv6_type
, &ipv6_base
) == -1) {
2832 mdb_warn("could not resolve in6_addr_t type\n");
2833 return (DCMD_ABORT
);
2836 if (mdb_ctf_type_cmp(base
, ipv6_base
) != 0) {
2837 mdb_warn("requires argument of type in6_addr_t\n");
2838 return (DCMD_ABORT
);
2841 if (mdb_vread(&ipv6
, sizeof (ipv6
), addr
) == -1) {
2842 mdb_warn("couldn't read in6_addr_t at %p", addr
);
2846 mdb_printf(fmt
, &ipv6
);
2852 * To validate the format string specified to ::printf, we run the format
2853 * string through a very simple state machine that restricts us to a subset
2854 * of mdb_printf() functionality.
2857 PRINTF_NOFMT
= 1, /* no current format specifier */
2858 PRINTF_PERC
, /* processed '%' */
2859 PRINTF_FMT
, /* processing format specifier */
2860 PRINTF_LEFT
, /* processed '-', expecting width */
2861 PRINTF_WIDTH
, /* processing width */
2862 PRINTF_QUES
/* processed '?', expecting format */
2866 cmd_printf_tab(mdb_tab_cookie_t
*mcp
, uint_t flags
, int argc
,
2867 const mdb_arg_t
*argv
)
2873 * If argc doesn't have more than what should be the format string,
2880 * Because we aren't leveraging the lex and yacc engine, we have to
2881 * manually walk the arguments to find both the first and last
2882 * open/close quote of the format string.
2884 f
= strchr(argv
[0].a_un
.a_str
, '"');
2888 f
= strchr(f
+ 1, '"');
2892 for (ii
= 1; ii
< argc
; ii
++) {
2893 if (argv
[ii
].a_type
!= MDB_TYPE_STRING
)
2895 f
= strchr(argv
[ii
].a_un
.a_str
, '"');
2908 return (cmd_print_tab_common(mcp
, flags
, argc
, argv
));
2912 cmd_printf(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2914 char type
[MDB_SYM_NAMLEN
];
2915 int i
, nfmts
= 0, ret
;
2917 const char *fmt
, *member
;
2918 char **fmts
, *last
, *dest
, f
;
2919 int (**funcs
)(mdb_ctf_id_t
, uintptr_t, ulong_t
, char *);
2920 int state
= PRINTF_NOFMT
;
2923 if (!(flags
& DCMD_ADDRSPEC
))
2924 return (DCMD_USAGE
);
2926 bzero(&pa
, sizeof (pa
));
2927 pa
.pa_as
= MDB_TGT_AS_VIRT
;
2928 pa
.pa_realtgt
= pa
.pa_tgt
= mdb
.m_target
;
2930 if (argc
== 0 || argv
[0].a_type
!= MDB_TYPE_STRING
) {
2931 mdb_warn("expected a format string\n");
2932 return (DCMD_USAGE
);
2936 * Our first argument is a format string; rip it apart and run it
2937 * through our state machine to validate that our input is within the
2938 * subset of mdb_printf() format strings that we allow.
2940 fmt
= argv
[0].a_un
.a_str
;
2942 * 'dest' must be large enough to hold a copy of the format string,
2943 * plus a NUL and up to 2 additional characters for each conversion
2944 * in the format string. This gives us a bloat factor of 5/2 ~= 3.
2945 * e.g. "%d" (strlen of 2) --> "%lld\0" (need 5 bytes)
2947 dest
= mdb_zalloc(strlen(fmt
) * 3, UM_SLEEP
| UM_GC
);
2948 fmts
= mdb_zalloc(strlen(fmt
) * sizeof (char *), UM_SLEEP
| UM_GC
);
2949 funcs
= mdb_zalloc(strlen(fmt
) * sizeof (void *), UM_SLEEP
| UM_GC
);
2952 for (i
= 0; fmt
[i
] != '\0'; i
++) {
2953 *dest
++ = f
= fmt
[i
];
2957 state
= f
== '%' ? PRINTF_PERC
: PRINTF_NOFMT
;
2961 state
= f
== '-' ? PRINTF_LEFT
:
2962 f
>= '0' && f
<= '9' ? PRINTF_WIDTH
:
2963 f
== '?' ? PRINTF_QUES
:
2964 f
== '%' ? PRINTF_NOFMT
: PRINTF_FMT
;
2968 state
= f
>= '0' && f
<= '9' ? PRINTF_WIDTH
:
2969 f
== '?' ? PRINTF_QUES
: PRINTF_FMT
;
2973 state
= f
>= '0' && f
<= '9' ? PRINTF_WIDTH
:
2982 if (state
!= PRINTF_FMT
)
2988 * Now check that we have one of our valid format characters.
2994 funcs
[nfmts
] = printf_ptr
;
3000 funcs
[nfmts
] = printf_int
;
3006 funcs
[nfmts
] = printf_uint32
;
3010 funcs
[nfmts
] = printf_ipv6
;
3019 funcs
[nfmts
] = printf_uint
;
3025 funcs
[nfmts
] = printf_string
;
3029 funcs
[nfmts
] = sizeof (time_t) == sizeof (int) ?
3030 printf_uint32
: printf_uint
;
3034 mdb_warn("illegal format string at or near "
3035 "'%c' (position %d)\n", f
, i
+ 1);
3036 return (DCMD_ABORT
);
3041 fmts
[nfmts
++] = last
;
3043 state
= PRINTF_NOFMT
;
3050 * Now we expect a type name.
3052 if ((ret
= args_to_typename(&argc
, &argv
, type
, sizeof (type
))) != 0)
3058 if (mdb_ctf_lookup_by_name(type
, &id
) != 0) {
3059 mdb_warn("failed to look up type %s", type
);
3060 return (DCMD_ABORT
);
3064 mdb_warn("at least one member must be specified\n");
3065 return (DCMD_USAGE
);
3068 if (argc
!= nfmts
) {
3069 mdb_warn("%s format specifiers (found %d, expected %d)\n",
3070 argc
> nfmts
? "missing" : "extra", nfmts
, argc
);
3071 return (DCMD_ABORT
);
3074 for (i
= 0; i
< argc
; i
++) {
3079 if (argv
[i
].a_type
!= MDB_TYPE_STRING
) {
3080 mdb_warn("expected only type member arguments\n");
3081 return (DCMD_ABORT
);
3084 if (strcmp((member
= argv
[i
].a_un
.a_str
), ".") == 0) {
3086 * We allow "." to be specified to denote the current
3089 if (funcs
[i
] != printf_ptr
&& funcs
[i
] != printf_uint
&&
3090 funcs
[i
] != printf_int
) {
3091 mdb_warn("expected integer or pointer format "
3092 "specifier for '.'\n");
3093 return (DCMD_ABORT
);
3096 mdb_printf(fmts
[i
], mdb_get_dot());
3102 if (parse_member(&pa
, member
, id
, &mid
, &off
, &ignored
) != 0)
3103 return (DCMD_ABORT
);
3105 if ((ret
= funcs
[i
](mid
, pa
.pa_addr
, off
, fmts
[i
])) != 0) {
3106 mdb_warn("failed to print member '%s'\n", member
);
3111 mdb_printf("%s", last
);
3112 mdb_set_dot(addr
+ mdb_ctf_type_size(id
));
3117 static char _mdb_printf_help
[] =
3118 "The format string argument is a printf(3C)-like format string that is a\n"
3119 "subset of the format strings supported by mdb_printf(). The type argument\n"
3120 "is the name of a type to be used to interpret the memory referenced by dot.\n"
3121 "The member should either be a field in the specified structure, or the\n"
3122 "special member '.', denoting the value of dot (and treated as a pointer).\n"
3123 "The number of members must match the number of format specifiers in the\n"
3126 "The following format specifiers are recognized by ::printf:\n"
3128 " %% Prints the '%' symbol.\n"
3129 " %a Prints the member in symbolic form.\n"
3130 " %d Prints the member as a decimal integer. If the member is a signed\n"
3131 " integer type, the output will be signed.\n"
3132 " %H Prints the member as a human-readable size.\n"
3133 " %I Prints the member as an IPv4 address (must be 32-bit integer type).\n"
3134 " %N Prints the member as an IPv6 address (must be of type in6_addr_t).\n"
3135 " %o Prints the member as an unsigned octal integer.\n"
3136 " %p Prints the member as a pointer, in hexadecimal.\n"
3137 " %q Prints the member in signed octal. Honk if you ever use this!\n"
3138 " %r Prints the member as an unsigned value in the current output radix.\n"
3139 " %R Prints the member as a signed value in the current output radix.\n"
3140 " %s Prints the member as a string (requires a pointer or an array of\n"
3142 " %u Prints the member as an unsigned decimal integer.\n"
3143 " %x Prints the member in hexadecimal.\n"
3144 " %X Prints the member in hexadecimal, using the characters A-F as the\n"
3145 " digits for the values 10-15.\n"
3146 " %Y Prints the member as a time_t as the string "
3147 "'year month day HH:MM:SS'.\n"
3149 "The following field width specifiers are recognized by ::printf:\n"
3151 " %n Field width is set to the specified decimal value.\n"
3152 " %? Field width is set to the maximum width of a hexadecimal pointer\n"
3153 " value. This is 8 in an ILP32 environment, and 16 in an LP64\n"
3156 "The following flag specifers are recognized by ::printf:\n"
3158 " %- Left-justify the output within the specified field width. If the\n"
3159 " width of the output is less than the specified field width, the\n"
3160 " output will be padded with blanks on the right-hand side. Without\n"
3161 " %-, values are right-justified by default.\n"
3163 " %0 Zero-fill the output field if the output is right-justified and the\n"
3164 " width of the output is less than the specified field width. Without\n"
3165 " %0, right-justified values are prepended with blanks in order to\n"
3166 " fill the field.\n"
3171 "::printf \"%-6d %s\\n\" proc_t p_pidp->pid_id p_user.u_psargs\n"
3173 "::printf \"%?p %3d %a\\n\" kthread_t . t_pri t_startpc\n"
3175 "::printf \"%-40s %20s\\n\" zone_t zone_name zone_nodename\n"
3177 "::printf \"%Y %I\\n\" ire_t ire_create_time ire_u.ire4_u.ire4_addr\n"
3183 mdb_printf("%s", _mdb_printf_help
);