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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2016 Joyent, Inc.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
29 * Format String Decoder
31 * This file provides the core engine for converting strings of format
32 * characters into formatted output. The various format dcmds invoke the
33 * mdb_fmt_print() function below with a target, address space identifier,
34 * address, count, and format character, and it reads the required data from
35 * the target and prints the formatted output to stdout. Since nearly two
36 * thirds of the format characters can be expressed as simple printf format
37 * strings, we implement the engine using the lookup table below. Each entry
38 * provides either a pointer to a printf format string or a pointer to a
39 * function to perform special processing. For the printf case, the
40 * corresponding data size in bytes is also supplied. The printf processing
41 * code handles 1, 2, 4, and 8-byte reads into an unsigned integer container
42 * of the given size, and then simply calls mdb_iob_printf with the integer
43 * and format string. This handles all printf cases, except when unsigned
44 * promotion of an integer type in the varargs list does not perform the
45 * conversion we require to get the proper result. With the current set of
46 * format characters, this case only occurs twice: we need a 4-byte float
47 * to get promoted to 8-byte double for the 'f' format so it can be
48 * correctly formatted by %f, and we need a 1-byte int8_t to get promoted
49 * with sign extension to a 4-byte int32_t for the 'v' format so it can be
50 * correctly formatted by %d. We provide explicit functions to handle these
51 * cases, as well as to handle special format characters such as 'i', etc.
52 * We also provide a cmd_formats() dcmd function below which prints a table
53 * of the output formats and their sizes. Format characters that provide
54 * custom functions provide their help description string explicitly. All
55 * the printf formats have their help strings generated automatically by
56 * our printf "unparser" mdb_iob_format2str().
59 #include <mdb/mdb_types.h>
60 #include <mdb/mdb_target.h>
61 #include <mdb/mdb_io.h>
62 #include <mdb/mdb_err.h>
63 #include <mdb/mdb_string.h>
64 #include <mdb/mdb_modapi.h>
67 #define FUNCP(p) ((void *)(p)) /* Cast to f_ptr type */
68 #define SZ_NONE ((size_t)-1L) /* Format does not change dot */
70 typedef mdb_tgt_addr_t
mdb_fmt_func_f(mdb_tgt_t
*,
71 mdb_tgt_as_t
, mdb_tgt_addr_t
, size_t);
74 * There are several 'special' characters that are handled outside of
75 * mdb_fmt_print(). These are characters that write (vwWZ) and characters that
76 * match (lLM). We include them here so that ::formats can display an
77 * appropriate message, but they are handled specially by write_arglist() and
78 * match_arglist() in mdb_cmds.c.
80 #define FMT_NONE 0x0 /* Format character is not supported */
81 #define FMT_FUNC 0x1 /* f_ptr is a mdb_fmt_func_f to call */
82 #define FMT_PRINTF 0x2 /* f_ptr is a const char * format string */
83 #define FMT_MATCH 0x4 /* Match command (not supported here) */
84 #define FMT_WRITE 0x8 /* Command writes to address space */
86 #define FMT_TYPE(x) ((x) & 0x7) /* Excludes modifying flags (FMT_WRITE) */
88 typedef struct mdb_fmt_desc
{
89 int f_type
; /* Type of format (see above) */
90 void *f_ptr
; /* Data pointer (see above) */
91 const char *f_help
; /* Additional help string */
92 size_t f_size
; /* Size of type in bytes, or SZ_NONE */
93 boolean_t f_float
; /* Is this a floating point type */
96 static const char help_plus
[] = "increment dot by the count";
97 static const char help_minus
[] = "decrement dot by the count";
98 static const char help_escchr
[] = "character using C character notation";
99 static const char help_swapint
[] = "swap bytes and shorts";
100 static const char help_dotinstr
[] = "address and disassembled instruction";
101 static const char help_instr
[] = "disassembled instruction";
102 static const char help_escstr
[] = "string using C string notation";
103 static const char help_time32
[] = "decoded time32_t";
104 static const char help_carat
[] = "decrement dot by increment * count";
105 static const char help_dot
[] = "dot as symbol+offset";
107 static const char help_f
[] = "float";
109 static const char help_swapshort
[] = "swap bytes";
110 static const char help_nl
[] = "newline";
111 static const char help_ws
[] = "whitespace";
112 static const char help_rawstr
[] = "raw string";
113 static const char help_tab
[] = "horizontal tab";
114 static const char help_sdbyte
[] = "decimal signed int";
115 static const char help_time64
[] = "decoded time64_t";
116 static const char help_binary
[] = "binary unsigned long long";
117 static const char help_hex64
[] = "hexadecimal long long";
118 static const char help_match32
[] = "int";
119 static const char help_match64
[] = "long long";
120 static const char help_match16
[] = "short";
121 static const char help_uintptr
[] = "hexadecimal uintptr_t";
122 static const char help_ctf
[] = "whose size is inferred by CTF info";
125 static mdb_tgt_addr_t
126 fmt_dot(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
128 uint_t oflags
= mdb_iob_getflags(mdb
.m_out
) & MDB_IOB_INDENT
;
131 mdb_iob_clrflags(mdb
.m_out
, oflags
);
133 if (mdb
.m_flags
& MDB_FL_PSYM
) {
135 mdb_iob_printf(mdb
.m_out
, "%-#16lla%16T", addr
);
137 (void) mdb_iob_snprintf(buf
, sizeof (buf
),
138 "%#llx:", (u_longlong_t
)addr
);
140 mdb_iob_printf(mdb
.m_out
, "%-16s%16T", buf
);
143 mdb_iob_setflags(mdb
.m_out
, oflags
);
144 mdb_nv_set_value(mdb
.m_rvalue
, addr
);
149 static mdb_tgt_addr_t
150 fmt_float(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
154 * We need to handle float as a special case because we need it to be
155 * promoted to a double by virtue of appearing as a parameter, and all
156 * our generic format handling below is based on integer types.
159 if (mdb_tgt_aread(t
, as
, &f
, sizeof (f
), addr
) != sizeof (f
)) {
160 warn("failed to read data from target");
163 mdb_iob_printf(mdb
.m_out
, "%e", f
);
171 static mdb_tgt_addr_t
172 fmt_plus(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
178 static mdb_tgt_addr_t
179 fmt_minus(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
185 static mdb_tgt_addr_t
186 fmt_carat(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
188 return (addr
- (mdb
.m_incr
* cnt
));
192 static mdb_tgt_addr_t
193 fmt_nl(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
196 mdb_iob_nl(mdb
.m_out
);
202 static mdb_tgt_addr_t
203 fmt_ws(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
205 mdb_iob_ws(mdb
.m_out
, cnt
);
210 static mdb_tgt_addr_t
211 fmt_tab(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
213 size_t ts
= mdb_iob_gettabstop(mdb
.m_out
);
215 mdb_iob_tabstop(mdb
.m_out
, cnt
);
216 mdb_iob_tab(mdb
.m_out
);
217 mdb_iob_tabstop(mdb
.m_out
, ts
);
222 static mdb_tgt_addr_t
223 fmt_rawstr(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
225 uint_t oflags
= mdb_iob_getflags(mdb
.m_out
) & MDB_IOB_INDENT
;
229 mdb_iob_clrflags(mdb
.m_out
, oflags
);
231 for (; cnt
-- != 0; addr
++) {
233 nbytes
= mdb_tgt_readstr(t
, as
, buf
, BUFSIZ
, addr
);
235 mdb_iob_puts(mdb
.m_out
, buf
);
236 addr
+= MIN(nbytes
, BUFSIZ
- 1);
237 } else if (nbytes
< 0) {
238 warn("failed to read data from target");
241 } while (nbytes
== BUFSIZ
);
244 mdb_iob_puts(mdb
.m_out
, "\\0");
247 mdb_iob_setflags(mdb
.m_out
, oflags
);
251 static mdb_tgt_addr_t
252 fmt_escstr(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
254 uint_t oflags
= mdb_iob_getflags(mdb
.m_out
) & MDB_IOB_INDENT
;
259 mdb_iob_clrflags(mdb
.m_out
, oflags
);
261 for (; cnt
-- != 0; addr
++) {
263 nbytes
= mdb_tgt_readstr(t
, as
, buf
, BUFSIZ
, addr
);
265 s
= strchr2esc(buf
, strlen(buf
));
266 mdb_iob_puts(mdb
.m_out
, s
);
268 addr
+= MIN(nbytes
, BUFSIZ
- 1);
269 } else if (nbytes
< 0) {
270 warn("failed to read data from target");
273 } while (nbytes
== BUFSIZ
);
276 mdb_iob_puts(mdb
.m_out
, "\\0");
279 mdb_iob_setflags(mdb
.m_out
, oflags
);
283 static mdb_tgt_addr_t
284 fmt_escchr(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
286 char *(*convert
)(const char *, size_t);
290 if (mdb
.m_flags
& MDB_FL_ADB
)
291 convert
= &strchr2adb
;
293 convert
= &strchr2esc
;
295 buf
= mdb_alloc(cnt
+ 1, UM_SLEEP
);
298 if ((nbytes
= mdb_tgt_aread(t
, as
, buf
, cnt
, addr
)) > 0) {
299 s
= convert(buf
, nbytes
);
300 mdb_iob_puts(mdb
.m_out
, s
);
305 mdb_free(buf
, cnt
+ 1);
309 static mdb_tgt_addr_t
310 fmt_swapshort(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
315 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
316 x
= (x
<< 8) | (x
>> 8);
317 mdb_iob_printf(mdb
.m_out
, "%-8x", x
);
318 mdb_nv_set_value(mdb
.m_rvalue
, x
);
321 warn("failed to read data from target");
328 static mdb_tgt_addr_t
329 fmt_swapint(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
334 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
335 x
= ((x
<< 24) | ((x
<< 8) & 0xff0000) |
336 ((x
>> 8) & 0xff00) | ((x
>> 24) & 0xff));
337 mdb_iob_printf(mdb
.m_out
, "%-16x", x
);
338 mdb_nv_set_value(mdb
.m_rvalue
, x
);
341 warn("failed to read data from target");
348 static mdb_tgt_addr_t
349 fmt_time32(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
354 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
355 mdb_iob_printf(mdb
.m_out
, "%-24Y", (time_t)x
);
356 mdb_nv_set_value(mdb
.m_rvalue
, x
);
359 warn("failed to read data from target");
366 static mdb_tgt_addr_t
367 fmt_time64(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
372 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
374 mdb_iob_printf(mdb
.m_out
, "%-24Y", (time_t)x
);
376 mdb_iob_printf(mdb
.m_out
, "%-24llR", x
);
378 mdb_nv_set_value(mdb
.m_rvalue
, x
);
381 warn("failed to read data from target");
388 static mdb_tgt_addr_t
389 fmt_sdbyte(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
394 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
395 mdb_iob_printf(mdb
.m_out
, "%-8d", (int32_t)x
);
396 mdb_nv_set_value(mdb
.m_rvalue
, (uint8_t)x
);
399 warn("failed to read data from target");
406 static mdb_tgt_addr_t
407 fmt_instr(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
413 naddr
= mdb_dis_ins2str(mdb
.m_disasm
, t
, as
,
414 buf
, sizeof (buf
), addr
);
416 return (addr
); /* If we didn't move, we failed */
417 mdb_iob_printf(mdb
.m_out
, "%s\n", buf
);
423 static mdb_tgt_addr_t
424 fmt_dotinstr(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
426 uint_t oflags
= mdb_iob_getflags(mdb
.m_out
) & MDB_IOB_INDENT
;
432 for (mdb_iob_clrflags(mdb
.m_out
, oflags
); cnt
-- != 0; addr
= naddr
) {
433 if (mdb_tgt_aread(t
, as
, &i
, sizeof (i
), addr
) != sizeof (i
)) {
434 warn("failed to read data from target");
435 break; /* Fail if we can't read instruction */
437 naddr
= mdb_dis_ins2str(mdb
.m_disasm
, t
, as
,
438 buf
, sizeof (buf
), addr
);
440 break; /* Fail if we didn't advance */
441 mdb_iob_printf(mdb
.m_out
, "%lx %x: %s\n", (long)addr
, i
, buf
);
444 mdb_iob_setflags(mdb
.m_out
, oflags
);
448 static mdb_tgt_addr_t
449 fmt_binary(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
454 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
455 mdb_iob_printf(mdb
.m_out
, "%-64s",
456 numtostr(x
, 2, NTOS_UNSIGNED
));
457 mdb_nv_set_value(mdb
.m_rvalue
, x
);
460 warn("failed to read data from target");
467 static mdb_tgt_addr_t
468 fmt_hex64(mdb_tgt_t
*t
, mdb_tgt_as_t as
, mdb_tgt_addr_t addr
, size_t cnt
)
470 const char *fmts
[] = { "%-16llx", "%-17llx" };
471 const uint64_t mask
= 0xf000000000000000ull
;
475 if (mdb_tgt_aread(t
, as
, &x
, sizeof (x
), addr
) == sizeof (x
)) {
476 mdb_iob_printf(mdb
.m_out
, fmts
[(x
& mask
) != 0], x
);
477 mdb_nv_set_value(mdb
.m_rvalue
, x
);
480 warn("failed to read data from target");
487 static const mdb_fmt_desc_t fmttab
[] = {
488 { FMT_NONE
, NULL
, NULL
, 0 }, /* 0 = NUL */
489 { FMT_NONE
, NULL
, NULL
, 0 }, /* 1 = SOH */
490 { FMT_NONE
, NULL
, NULL
, 0 }, /* 2 = STX */
491 { FMT_NONE
, NULL
, NULL
, 0 }, /* 3 = ETX */
492 { FMT_NONE
, NULL
, NULL
, 0 }, /* 4 = EOT */
493 { FMT_NONE
, NULL
, NULL
, 0 }, /* 5 = ENQ */
494 { FMT_NONE
, NULL
, NULL
, 0 }, /* 6 = ACK */
495 { FMT_NONE
, NULL
, NULL
, 0 }, /* 7 = BEL */
496 { FMT_NONE
, NULL
, NULL
, 0 }, /* 8 = BS */
497 { FMT_NONE
, NULL
, NULL
, 0 }, /* 9 = \t */
498 { FMT_NONE
, NULL
, NULL
, 0 }, /* 10 = \n */
499 { FMT_NONE
, NULL
, NULL
, 0 }, /* 11 = VT */
500 { FMT_NONE
, NULL
, NULL
, 0 }, /* 12 = FF */
501 { FMT_NONE
, NULL
, NULL
, 0 }, /* 13 = \r */
502 { FMT_NONE
, NULL
, NULL
, 0 }, /* 14 = SO */
503 { FMT_NONE
, NULL
, NULL
, 0 }, /* 15 = SI */
504 { FMT_NONE
, NULL
, NULL
, 0 }, /* 16 = DLE */
505 { FMT_NONE
, NULL
, NULL
, 0 }, /* 17 = DC1 */
506 { FMT_NONE
, NULL
, NULL
, 0 }, /* 18 = DC2 */
507 { FMT_NONE
, NULL
, NULL
, 0 }, /* 19 = DC3 */
508 { FMT_NONE
, NULL
, NULL
, 0 }, /* 20 = DC4 */
509 { FMT_NONE
, NULL
, NULL
, 0 }, /* 21 = NAK */
510 { FMT_NONE
, NULL
, NULL
, 0 }, /* 22 = EYC */
511 { FMT_NONE
, NULL
, NULL
, 0 }, /* 23 = ETB */
512 { FMT_NONE
, NULL
, NULL
, 0 }, /* 24 = CAN */
513 { FMT_NONE
, NULL
, NULL
, 0 }, /* 25 = EM */
514 { FMT_NONE
, NULL
, NULL
, 0 }, /* 26 = SUB */
515 { FMT_NONE
, NULL
, NULL
, 0 }, /* 27 = ESC */
516 { FMT_NONE
, NULL
, NULL
, 0 }, /* 28 = FS */
517 { FMT_NONE
, NULL
, NULL
, 0 }, /* 29 = GS */
518 { FMT_NONE
, NULL
, NULL
, 0 }, /* 30 = RS */
519 { FMT_NONE
, NULL
, NULL
, 0 }, /* 31 = US */
520 { FMT_NONE
, NULL
, NULL
, 0 }, /* 32 = SPACE */
521 { FMT_NONE
, NULL
, NULL
, 0 }, /* 33 = ! */
522 { FMT_NONE
, NULL
, NULL
, 0 }, /* 34 = " */
523 { FMT_NONE
, NULL
, NULL
, 0 }, /* 35 = # */
524 { FMT_NONE
, NULL
, NULL
, 0 }, /* 36 = $ */
525 { FMT_NONE
, NULL
, NULL
, 0 }, /* 37 = % */
526 { FMT_NONE
, NULL
, NULL
, 0 }, /* 38 = & */
527 { FMT_NONE
, NULL
, NULL
, 0 }, /* 39 = ' */
528 { FMT_NONE
, NULL
, NULL
, 0 }, /* 40 = ( */
529 { FMT_NONE
, NULL
, NULL
, 0 }, /* 41 = ) */
530 { FMT_NONE
, NULL
, NULL
, 0 }, /* 42 = * */
531 { FMT_FUNC
, FUNCP(fmt_plus
), help_plus
, 0 }, /* 43 = + */
532 { FMT_NONE
, NULL
, NULL
, 0 }, /* 44 = , */
533 { FMT_FUNC
, FUNCP(fmt_minus
), help_minus
, 0 }, /* 45 = - */
534 { FMT_NONE
, NULL
, NULL
, 0 }, /* 46 = . */
535 { FMT_NONE
, NULL
, NULL
, 0 }, /* 47 = / */
536 { FMT_NONE
, NULL
, NULL
, 0 }, /* 48 = 0 */
537 { FMT_NONE
, NULL
, NULL
, 0 }, /* 49 = 1 */
538 { FMT_NONE
, NULL
, NULL
, 0 }, /* 50 = 2 */
539 { FMT_NONE
, NULL
, NULL
, 0 }, /* 51 = 3 */
540 { FMT_NONE
, NULL
, NULL
, 0 }, /* 52 = 4 */
541 { FMT_NONE
, NULL
, NULL
, 0 }, /* 53 = 5 */
542 { FMT_NONE
, NULL
, NULL
, 0 }, /* 54 = 6 */
543 { FMT_NONE
, NULL
, NULL
, 0 }, /* 55 = 7 */
544 { FMT_NONE
, NULL
, NULL
, 0 }, /* 56 = 8 */
545 { FMT_NONE
, NULL
, NULL
, 0 }, /* 57 = 9 */
546 { FMT_NONE
, NULL
, NULL
, 0 }, /* 58 = : */
547 { FMT_NONE
, NULL
, NULL
, 0 }, /* 59 = ; */
548 { FMT_NONE
, NULL
, NULL
, 0 }, /* 60 = < */
549 { FMT_NONE
, NULL
, NULL
, 0 }, /* 61 = = */
550 { FMT_NONE
, NULL
, NULL
, 0 }, /* 62 = > */
551 { FMT_NONE
, NULL
, NULL
, 0 }, /* 63 = ? */
552 { FMT_NONE
, NULL
, NULL
, 0 }, /* 64 = @ */
553 { FMT_NONE
, NULL
, NULL
, 0 }, /* 65 = A */
554 { FMT_PRINTF
, "%-8x", NULL
, 1 }, /* 66 = B */
555 { FMT_FUNC
, FUNCP(fmt_escchr
), help_escchr
, 1 }, /* 67 = C */
556 { FMT_PRINTF
, "%-16d", NULL
, 4 }, /* 68 = D */
557 { FMT_PRINTF
, "%-16llu", NULL
, 8 }, /* 69 = E */
559 { FMT_NONE
, NULL
, NULL
, 0 }, /* 70 = F */
561 { FMT_PRINTF
, "%g", NULL
, sizeof (double), B_TRUE
}, /* 70 = F */
563 { FMT_PRINTF
, "%-16llo", NULL
, 8 }, /* 71 = G */
564 { FMT_FUNC
, FUNCP(fmt_swapint
), help_swapint
, 4 }, /* 72 = H */
565 { FMT_FUNC
, FUNCP(fmt_dotinstr
), help_dotinstr
, 0 }, /* 73 = I */
566 { FMT_FUNC
, FUNCP(fmt_hex64
), help_hex64
, 8 }, /* 74 = J */
568 { FMT_FUNC
, FUNCP(fmt_hex64
), help_uintptr
, 8 }, /* 75 = K (J) */
570 { FMT_PRINTF
, "%-16x", help_uintptr
, 4 }, /* 75 = K (X) */
572 { FMT_MATCH
, NULL
, help_match32
, 4 }, /* 76 = L */
573 { FMT_MATCH
, NULL
, help_match64
, 8 }, /* 77 = M */
574 { FMT_FUNC
, FUNCP(fmt_nl
), help_nl
, SZ_NONE
}, /* 78 = N */
575 { FMT_PRINTF
, "%-#16o", NULL
, 4 }, /* 79 = O */
576 { FMT_PRINTF
, "%-16a", NULL
, sizeof (uintptr_t) }, /* 80 = P */
577 { FMT_PRINTF
, "%-#16q", NULL
, 4 }, /* 81 = Q */
578 { FMT_FUNC
, FUNCP(fmt_binary
), help_binary
, 8 }, /* 82 = R */
579 { FMT_FUNC
, FUNCP(fmt_escstr
), help_escstr
, 0 }, /* 83 = S */
580 { FMT_FUNC
, FUNCP(fmt_tab
), help_tab
, SZ_NONE
}, /* 84 = T */
581 { FMT_PRINTF
, "%-16u", NULL
, 4 }, /* 85 = U */
582 { FMT_PRINTF
, "%-8u", NULL
, 1 }, /* 86 = V */
583 { FMT_PRINTF
|FMT_WRITE
, "%-16r", NULL
, 4 }, /* 87 = W */
584 { FMT_PRINTF
, "%-16x", NULL
, 4 }, /* 88 = X */
585 { FMT_FUNC
, FUNCP(fmt_time32
), help_time32
, 4 }, /* 89 = Y */
586 { FMT_FUNC
|FMT_WRITE
, FUNCP(fmt_hex64
), help_hex64
, 8 }, /* 90 = Z */
587 { FMT_NONE
, NULL
, NULL
, 0 }, /* 91 = [ */
588 { FMT_NONE
, NULL
, NULL
, 0 }, /* 92 = \ */
589 { FMT_NONE
, NULL
, NULL
, 0 }, /* 93 = ] */
590 { FMT_FUNC
, FUNCP(fmt_carat
), help_carat
, 0 }, /* 94 = ^ */
591 { FMT_NONE
, NULL
, NULL
, 0 }, /* 95 = _ */
592 { FMT_NONE
, NULL
, NULL
, 0 }, /* 96 = ` */
593 { FMT_FUNC
, FUNCP(fmt_dot
), help_dot
, SZ_NONE
}, /* 97 = a */
594 { FMT_PRINTF
, "%-#8o", NULL
, 1 }, /* 98 = b */
595 { FMT_PRINTF
, "%c", NULL
, 1 }, /* 99 = c */
596 { FMT_PRINTF
, "%-8hd", NULL
, 2 }, /* 100 = d */
597 { FMT_PRINTF
, "%-16lld", NULL
, 8 }, /* 101 = e */
599 { FMT_NONE
, NULL
, NULL
, 0 }, /* 102 = f */
601 { FMT_FUNC
, FUNCP(fmt_float
), help_f
, sizeof (float),
602 B_TRUE
}, /* 102 = f */
604 { FMT_PRINTF
, "%-16llq", NULL
, 8 }, /* 103 = g */
605 { FMT_FUNC
, FUNCP(fmt_swapshort
), help_swapshort
, 2 }, /* 104 = h */
606 { FMT_FUNC
, FUNCP(fmt_instr
), help_instr
, 0 }, /* 105 = i */
607 { FMT_NONE
, NULL
, NULL
, 0 }, /* 106 = j */
608 { FMT_NONE
, NULL
, NULL
, 0 }, /* 107 = k */
609 { FMT_MATCH
, NULL
, help_match16
, 2 }, /* 108 = l */
610 { FMT_NONE
, NULL
, NULL
, 0 }, /* 109 = m */
611 { FMT_FUNC
, FUNCP(fmt_nl
), help_nl
, SZ_NONE
}, /* 110 = n */
612 { FMT_PRINTF
, "%-#8ho", NULL
, 2 }, /* 111 = o */
613 { FMT_PRINTF
, "%-16a", NULL
, sizeof (uintptr_t) }, /* 112 = p */
614 { FMT_PRINTF
, "%-#8hq", NULL
, 2 }, /* 113 = q */
615 { FMT_FUNC
, FUNCP(fmt_ws
), help_ws
, SZ_NONE
}, /* 114 = r */
616 { FMT_FUNC
, FUNCP(fmt_rawstr
), help_rawstr
, 0 }, /* 115 = s */
617 { FMT_FUNC
, FUNCP(fmt_tab
), help_tab
, SZ_NONE
}, /* 116 = t */
618 { FMT_PRINTF
, "%-8hu", NULL
, 2 }, /* 117 = u */
619 { FMT_FUNC
|FMT_WRITE
, FUNCP(fmt_sdbyte
), help_sdbyte
, 1 }, /* 118 = v */
620 { FMT_PRINTF
|FMT_WRITE
, "%-8hr", NULL
, 2 }, /* 119 = w */
621 { FMT_PRINTF
, "%-8hx", NULL
, 2 }, /* 120 = x */
622 { FMT_FUNC
, FUNCP(fmt_time64
), help_time64
, 8 }, /* 121 = y */
623 { FMT_WRITE
, NULL
, help_ctf
, 0 }, /* 122 = z */
627 mdb_fmt_print(mdb_tgt_t
*t
, mdb_tgt_as_t as
,
628 mdb_tgt_addr_t addr
, size_t cnt
, char fmt
)
630 const mdb_fmt_desc_t
*fp
= &fmttab
[fmt
];
631 mdb_fmt_func_f
*funcp
;
643 if (fmt
< 0 || fmt
> (sizeof (fmttab
) / sizeof (fmttab
[0]))) {
644 warn("invalid format character -- '%c'\n", fmt
);
648 switch (FMT_TYPE(fp
->f_type
)) {
650 funcp
= (mdb_fmt_func_f
*)fp
->f_ptr
;
651 addr
= funcp(t
, as
, addr
, cnt
);
655 switch (fp
->f_size
) {
669 fail("format %c is defined using illegal size\n", fmt
);
672 if (fp
->f_float
== B_TRUE
) {
673 if (fp
->f_size
!= 8) {
674 fail("format %c is using illegal fp size\n",
682 if (mdb_tgt_aread(t
, as
, buf
, fp
->f_size
, addr
) !=
684 warn("failed to read data from target");
688 switch (fp
->f_size
) {
690 mdb_iob_printf(mdb
.m_out
, fp
->f_ptr
, u
.i1
);
694 mdb_iob_printf(mdb
.m_out
, fp
->f_ptr
, u
.i2
);
698 mdb_iob_printf(mdb
.m_out
, fp
->f_ptr
, u
.i4
);
703 mdb_iob_printf(mdb
.m_out
, fp
->f_ptr
,
706 mdb_iob_printf(mdb
.m_out
, fp
->f_ptr
,
713 mdb_nv_set_value(mdb
.m_rvalue
, rvalue
);
719 warn("invalid format character -- '%c'\n", fmt
);
727 cmd_formats(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
729 const mdb_fmt_desc_t
*fp
= &fmttab
[0];
733 if ((flags
& DCMD_ADDRSPEC
) || argc
!= 0)
736 for (i
= 0; i
< (sizeof (fmttab
) / sizeof (fmttab
[0])); i
++, fp
++) {
737 if (fp
->f_type
== FMT_NONE
)
740 write
= (fp
->f_type
& FMT_WRITE
) ? "write " : "";
742 if (fp
->f_type
& FMT_FUNC
)
743 mdb_printf("%c - %s%s", i
, write
, fp
->f_help
);
744 else if (fp
->f_type
& FMT_MATCH
)
745 mdb_printf("%c - match %s", i
, fp
->f_help
);
746 else if (fp
->f_help
!= NULL
)
747 mdb_printf("%c - %s%s", i
, write
, fp
->f_help
);
749 mdb_printf("%c - %s%s", i
, write
,
750 mdb_iob_format2str(fp
->f_ptr
));
752 switch (fp
->f_size
) {
757 mdb_printf(" (variable size)\n");
760 mdb_printf(" (1 byte)\n");
763 mdb_printf(" (%lu bytes)\n", fp
->f_size
);