17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*a727d47aSjwadams * Common Development and Distribution License (the "License").
6*a727d47aSjwadams * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*a727d47aSjwadams * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * Format String Decoder
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate * This file provides the core engine for converting strings of format
327c478bd9Sstevel@tonic-gate * characters into formatted output. The various format dcmds invoke the
337c478bd9Sstevel@tonic-gate * mdb_fmt_print() function below with a target, address space identifier,
347c478bd9Sstevel@tonic-gate * address, count, and format character, and it reads the required data from
357c478bd9Sstevel@tonic-gate * the target and prints the formatted output to stdout. Since nearly two
367c478bd9Sstevel@tonic-gate * thirds of the format characters can be expressed as simple printf format
377c478bd9Sstevel@tonic-gate * strings, we implement the engine using the lookup table below. Each entry
387c478bd9Sstevel@tonic-gate * provides either a pointer to a printf format string or a pointer to a
397c478bd9Sstevel@tonic-gate * function to perform special processing. For the printf case, the
407c478bd9Sstevel@tonic-gate * corresponding data size in bytes is also supplied. The printf processing
417c478bd9Sstevel@tonic-gate * code handles 1, 2, 4, and 8-byte reads into an unsigned integer container
427c478bd9Sstevel@tonic-gate * of the given size, and then simply calls mdb_iob_printf with the integer
437c478bd9Sstevel@tonic-gate * and format string. This handles all printf cases, except when unsigned
447c478bd9Sstevel@tonic-gate * promotion of an integer type in the varargs list does not perform the
457c478bd9Sstevel@tonic-gate * conversion we require to get the proper result. With the current set of
467c478bd9Sstevel@tonic-gate * format characters, this case only occurs twice: we need a 4-byte float
477c478bd9Sstevel@tonic-gate * to get promoted to 8-byte double for the 'f' format so it can be
487c478bd9Sstevel@tonic-gate * correctly formatted by %f, and we need a 1-byte int8_t to get promoted
497c478bd9Sstevel@tonic-gate * with sign extension to a 4-byte int32_t for the 'v' format so it can be
507c478bd9Sstevel@tonic-gate * correctly formatted by %d. We provide explicit functions to handle these
517c478bd9Sstevel@tonic-gate * cases, as well as to handle special format characters such as 'i', etc.
527c478bd9Sstevel@tonic-gate * We also provide a cmd_formats() dcmd function below which prints a table
537c478bd9Sstevel@tonic-gate * of the output formats and their sizes. Format characters that provide
547c478bd9Sstevel@tonic-gate * custom functions provide their help description string explicitly. All
557c478bd9Sstevel@tonic-gate * the printf formats have their help strings generated automatically by
567c478bd9Sstevel@tonic-gate * our printf "unparser" mdb_iob_format2str().
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate #include <mdb/mdb_types.h>
607c478bd9Sstevel@tonic-gate #include <mdb/mdb_target.h>
617c478bd9Sstevel@tonic-gate #include <mdb/mdb_io.h>
627c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
637c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h>
647c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
657c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate #define FUNCP(p) ((void *)(p)) /* Cast to f_ptr type */
687c478bd9Sstevel@tonic-gate #define SZ_NONE ((size_t)-1L) /* Format does not change dot */
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate typedef mdb_tgt_addr_t mdb_fmt_func_f(mdb_tgt_t *,
717c478bd9Sstevel@tonic-gate mdb_tgt_as_t, mdb_tgt_addr_t, size_t);
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * There are several 'special' characters that are handled outside of
757c478bd9Sstevel@tonic-gate * mdb_fmt_print(). These are characters that write (vwWZ) and characters that
767c478bd9Sstevel@tonic-gate * match (lLM). We include them here so that ::formats can display an
777c478bd9Sstevel@tonic-gate * appropriate message, but they are handled specially by write_arglist() and
787c478bd9Sstevel@tonic-gate * match_arglist() in mdb_cmds.c.
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate #define FMT_NONE 0x0 /* Format character is not supported */
817c478bd9Sstevel@tonic-gate #define FMT_FUNC 0x1 /* f_ptr is a mdb_fmt_func_f to call */
827c478bd9Sstevel@tonic-gate #define FMT_PRINTF 0x2 /* f_ptr is a const char * format string */
837c478bd9Sstevel@tonic-gate #define FMT_MATCH 0x4 /* Match command (not supported here) */
847c478bd9Sstevel@tonic-gate #define FMT_WRITE 0x8 /* Command writes to address space */
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate #define FMT_TYPE(x) ((x) & 0x7) /* Excludes modifying flags (FMT_WRITE) */
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate typedef struct mdb_fmt_desc {
897c478bd9Sstevel@tonic-gate int f_type; /* Type of format (see above) */
907c478bd9Sstevel@tonic-gate void *f_ptr; /* Data pointer (see above) */
917c478bd9Sstevel@tonic-gate const char *f_help; /* Additional help string */
927c478bd9Sstevel@tonic-gate size_t f_size; /* Size of type in bytes, or SZ_NONE */
937c478bd9Sstevel@tonic-gate } mdb_fmt_desc_t;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate static const char help_plus[] = "increment dot by the count";
967c478bd9Sstevel@tonic-gate static const char help_minus[] = "decrement dot by the count";
977c478bd9Sstevel@tonic-gate static const char help_escchr[] = "character using C character notation";
987c478bd9Sstevel@tonic-gate static const char help_swapint[] = "swap bytes and shorts";
997c478bd9Sstevel@tonic-gate static const char help_dotinstr[] = "address and disassembled instruction";
1007c478bd9Sstevel@tonic-gate static const char help_instr[] = "disassembled instruction";
1017c478bd9Sstevel@tonic-gate static const char help_escstr[] = "string using C string notation";
1027c478bd9Sstevel@tonic-gate static const char help_time32[] = "decoded time32_t";
1037c478bd9Sstevel@tonic-gate static const char help_carat[] = "decrement dot by increment * count";
1047c478bd9Sstevel@tonic-gate static const char help_dot[] = "dot as symbol+offset";
1057c478bd9Sstevel@tonic-gate #ifndef _KMDB
1067c478bd9Sstevel@tonic-gate static const char help_f[] = "float";
1077c478bd9Sstevel@tonic-gate #endif
1087c478bd9Sstevel@tonic-gate static const char help_swapshort[] = "swap bytes";
1097c478bd9Sstevel@tonic-gate static const char help_nl[] = "newline";
1107c478bd9Sstevel@tonic-gate static const char help_ws[] = "whitespace";
1117c478bd9Sstevel@tonic-gate static const char help_rawstr[] = "raw string";
1127c478bd9Sstevel@tonic-gate static const char help_tab[] = "horizontal tab";
1137c478bd9Sstevel@tonic-gate static const char help_sdbyte[] = "decimal signed int";
1147c478bd9Sstevel@tonic-gate static const char help_time64[] = "decoded time64_t";
1157c478bd9Sstevel@tonic-gate static const char help_binary[] = "binary unsigned long long";
1167c478bd9Sstevel@tonic-gate static const char help_hex64[] = "hexadecimal long long";
1177c478bd9Sstevel@tonic-gate static const char help_match32[] = "int";
1187c478bd9Sstevel@tonic-gate static const char help_match64[] = "long long";
1197c478bd9Sstevel@tonic-gate static const char help_match16[] = "short";
1207c478bd9Sstevel@tonic-gate static const char help_uintptr[] = "hexadecimal uintptr_t";
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1237c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_dot(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)1247c478bd9Sstevel@tonic-gate fmt_dot(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate uint_t oflags = mdb_iob_getflags(mdb.m_out) & MDB_IOB_INDENT;
1277c478bd9Sstevel@tonic-gate char buf[24];
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, oflags);
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate if (mdb.m_flags & MDB_FL_PSYM) {
1327c478bd9Sstevel@tonic-gate while (cnt-- != 0)
1337c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-#16lla%16T", addr);
1347c478bd9Sstevel@tonic-gate } else {
1357c478bd9Sstevel@tonic-gate (void) mdb_iob_snprintf(buf, sizeof (buf),
1367c478bd9Sstevel@tonic-gate "%#llx:", (u_longlong_t)addr);
1377c478bd9Sstevel@tonic-gate while (cnt-- != 0)
1387c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-16s%16T", buf);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, oflags);
1427c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, addr);
1437c478bd9Sstevel@tonic-gate return (addr);
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate #ifndef _KMDB
1477c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_float(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)1487c478bd9Sstevel@tonic-gate fmt_float(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate float f;
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * We need to handle float as a special case because we need it to be
1537c478bd9Sstevel@tonic-gate * promoted to a double by virtue of appearing as a parameter, and all
1547c478bd9Sstevel@tonic-gate * our generic format handling below is based on integer types.
1557c478bd9Sstevel@tonic-gate */
1567c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
1577c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &f, sizeof (f), addr) != sizeof (f)) {
1587c478bd9Sstevel@tonic-gate warn("failed to read data from target");
1597c478bd9Sstevel@tonic-gate break;
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%e", f);
1627c478bd9Sstevel@tonic-gate addr += sizeof (f);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate return (addr);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate #endif
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1697c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_plus(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)1707c478bd9Sstevel@tonic-gate fmt_plus(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
1717c478bd9Sstevel@tonic-gate {
1727c478bd9Sstevel@tonic-gate return (addr + cnt);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1767c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_minus(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)1777c478bd9Sstevel@tonic-gate fmt_minus(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate return (addr - cnt);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1837c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_carat(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)1847c478bd9Sstevel@tonic-gate fmt_carat(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate return (addr - (mdb.m_incr * cnt));
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1907c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_nl(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)1917c478bd9Sstevel@tonic-gate fmt_nl(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate while (cnt-- != 0)
1947c478bd9Sstevel@tonic-gate mdb_iob_nl(mdb.m_out);
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate return (addr);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2007c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_ws(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)2017c478bd9Sstevel@tonic-gate fmt_ws(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
2027c478bd9Sstevel@tonic-gate {
2037c478bd9Sstevel@tonic-gate mdb_iob_ws(mdb.m_out, cnt);
2047c478bd9Sstevel@tonic-gate return (addr);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2087c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_tab(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)2097c478bd9Sstevel@tonic-gate fmt_tab(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate size_t ts = mdb_iob_gettabstop(mdb.m_out);
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate mdb_iob_tabstop(mdb.m_out, cnt);
2147c478bd9Sstevel@tonic-gate mdb_iob_tab(mdb.m_out);
2157c478bd9Sstevel@tonic-gate mdb_iob_tabstop(mdb.m_out, ts);
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate return (addr);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_rawstr(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)2217c478bd9Sstevel@tonic-gate fmt_rawstr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate uint_t oflags = mdb_iob_getflags(mdb.m_out) & MDB_IOB_INDENT;
2247c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
2257c478bd9Sstevel@tonic-gate ssize_t nbytes;
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, oflags);
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate for (; cnt-- != 0; addr++) {
2307c478bd9Sstevel@tonic-gate do {
2317c478bd9Sstevel@tonic-gate nbytes = mdb_tgt_readstr(t, as, buf, BUFSIZ, addr);
2327c478bd9Sstevel@tonic-gate if (nbytes > 0) {
2337c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, buf);
2347c478bd9Sstevel@tonic-gate addr += MIN(nbytes, BUFSIZ - 1);
2357c478bd9Sstevel@tonic-gate } else if (nbytes < 0) {
2367c478bd9Sstevel@tonic-gate warn("failed to read data from target");
2377c478bd9Sstevel@tonic-gate goto out;
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate } while (nbytes == BUFSIZ);
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate if (cnt != 0)
2427c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, "\\0");
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate out:
2457c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, oflags);
2467c478bd9Sstevel@tonic-gate return (addr);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_escstr(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)2507c478bd9Sstevel@tonic-gate fmt_escstr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate uint_t oflags = mdb_iob_getflags(mdb.m_out) & MDB_IOB_INDENT;
2537c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
2547c478bd9Sstevel@tonic-gate ssize_t nbytes;
2557c478bd9Sstevel@tonic-gate char *s;
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate mdb_iob_clrflags(mdb.m_out, oflags);
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate for (; cnt-- != 0; addr++) {
2607c478bd9Sstevel@tonic-gate do {
2617c478bd9Sstevel@tonic-gate nbytes = mdb_tgt_readstr(t, as, buf, BUFSIZ, addr);
2627c478bd9Sstevel@tonic-gate if (nbytes > 0) {
2637c478bd9Sstevel@tonic-gate s = strchr2esc(buf, strlen(buf));
2647c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, s);
2657c478bd9Sstevel@tonic-gate strfree(s);
2667c478bd9Sstevel@tonic-gate addr += MIN(nbytes, BUFSIZ - 1);
2677c478bd9Sstevel@tonic-gate } else if (nbytes < 0) {
2687c478bd9Sstevel@tonic-gate warn("failed to read data from target");
2697c478bd9Sstevel@tonic-gate goto out;
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate } while (nbytes == BUFSIZ);
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate if (cnt != 0)
2747c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, "\\0");
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate out:
2777c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, oflags);
2787c478bd9Sstevel@tonic-gate return (addr);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_escchr(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)2827c478bd9Sstevel@tonic-gate fmt_escchr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate char *(*convert)(const char *, size_t);
2857c478bd9Sstevel@tonic-gate ssize_t nbytes;
2867c478bd9Sstevel@tonic-gate char *buf, *s;
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate if (mdb.m_flags & MDB_FL_ADB)
2897c478bd9Sstevel@tonic-gate convert = &strchr2adb;
2907c478bd9Sstevel@tonic-gate else
2917c478bd9Sstevel@tonic-gate convert = &strchr2esc;
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate buf = mdb_alloc(cnt + 1, UM_SLEEP);
2947c478bd9Sstevel@tonic-gate buf[cnt] = 0;
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate if ((nbytes = mdb_tgt_aread(t, as, buf, cnt, addr)) > 0) {
2977c478bd9Sstevel@tonic-gate s = convert(buf, nbytes);
2987c478bd9Sstevel@tonic-gate mdb_iob_puts(mdb.m_out, s);
2997c478bd9Sstevel@tonic-gate strfree(s);
3007c478bd9Sstevel@tonic-gate addr += nbytes;
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate mdb_free(buf, cnt + 1);
3047c478bd9Sstevel@tonic-gate return (addr);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_swapshort(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)3087c478bd9Sstevel@tonic-gate fmt_swapshort(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate ushort_t x;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
3137c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
3147c478bd9Sstevel@tonic-gate x = (x << 8) | (x >> 8);
3157c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-8x", x);
3167c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, x);
3177c478bd9Sstevel@tonic-gate addr += sizeof (x);
3187c478bd9Sstevel@tonic-gate } else {
3197c478bd9Sstevel@tonic-gate warn("failed to read data from target");
3207c478bd9Sstevel@tonic-gate break;
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate return (addr);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_swapint(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)3277c478bd9Sstevel@tonic-gate fmt_swapint(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate uint_t x;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
3327c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
3337c478bd9Sstevel@tonic-gate x = ((x << 24) | ((x << 8) & 0xff0000) |
3347c478bd9Sstevel@tonic-gate ((x >> 8) & 0xff00) | ((x >> 24) & 0xff));
3357c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-16x", x);
3367c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, x);
3377c478bd9Sstevel@tonic-gate addr += sizeof (x);
3387c478bd9Sstevel@tonic-gate } else {
3397c478bd9Sstevel@tonic-gate warn("failed to read data from target");
3407c478bd9Sstevel@tonic-gate break;
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate return (addr);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_time32(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)3477c478bd9Sstevel@tonic-gate fmt_time32(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
3487c478bd9Sstevel@tonic-gate {
349*a727d47aSjwadams int32_t x;
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
3527c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
3537c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-24Y", (time_t)x);
3547c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, x);
3557c478bd9Sstevel@tonic-gate addr += sizeof (x);
3567c478bd9Sstevel@tonic-gate } else {
3577c478bd9Sstevel@tonic-gate warn("failed to read data from target");
3587c478bd9Sstevel@tonic-gate break;
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate return (addr);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_time64(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)3657c478bd9Sstevel@tonic-gate fmt_time64(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
3667c478bd9Sstevel@tonic-gate {
367*a727d47aSjwadams int64_t x;
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
3707c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
371*a727d47aSjwadams if ((time_t)x == x)
3727c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-24Y", (time_t)x);
373*a727d47aSjwadams else
374*a727d47aSjwadams mdb_iob_printf(mdb.m_out, "%-24llR", x);
375*a727d47aSjwadams
3767c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, x);
3777c478bd9Sstevel@tonic-gate addr += sizeof (x);
3787c478bd9Sstevel@tonic-gate } else {
3797c478bd9Sstevel@tonic-gate warn("failed to read data from target");
3807c478bd9Sstevel@tonic-gate break;
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate return (addr);
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_sdbyte(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)3877c478bd9Sstevel@tonic-gate fmt_sdbyte(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate int8_t x;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
3927c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
3937c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-8d", (int32_t)x);
3947c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, (uint8_t)x);
3957c478bd9Sstevel@tonic-gate addr += sizeof (x);
3967c478bd9Sstevel@tonic-gate } else {
3977c478bd9Sstevel@tonic-gate warn("failed to read data from target");
3987c478bd9Sstevel@tonic-gate break;
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate return (addr);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_instr(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)4057c478bd9Sstevel@tonic-gate fmt_instr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
4087c478bd9Sstevel@tonic-gate uintptr_t naddr;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
4117c478bd9Sstevel@tonic-gate naddr = mdb_dis_ins2str(mdb.m_disasm, t, as,
4127c478bd9Sstevel@tonic-gate buf, sizeof (buf), addr);
4137c478bd9Sstevel@tonic-gate if (naddr == addr)
4147c478bd9Sstevel@tonic-gate return (addr); /* If we didn't move, we failed */
4157c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%s\n", buf);
4167c478bd9Sstevel@tonic-gate addr = naddr;
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate return (addr);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_dotinstr(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)4227c478bd9Sstevel@tonic-gate fmt_dotinstr(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate uint_t oflags = mdb_iob_getflags(mdb.m_out) & MDB_IOB_INDENT;
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
4277c478bd9Sstevel@tonic-gate uintptr_t naddr;
4287c478bd9Sstevel@tonic-gate uint32_t i;
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate for (mdb_iob_clrflags(mdb.m_out, oflags); cnt-- != 0; addr = naddr) {
4317c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &i, sizeof (i), addr) != sizeof (i)) {
4327c478bd9Sstevel@tonic-gate warn("failed to read data from target");
4337c478bd9Sstevel@tonic-gate break; /* Fail if we can't read instruction */
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate naddr = mdb_dis_ins2str(mdb.m_disasm, t, as,
4367c478bd9Sstevel@tonic-gate buf, sizeof (buf), addr);
4377c478bd9Sstevel@tonic-gate if (naddr == addr)
4387c478bd9Sstevel@tonic-gate break; /* Fail if we didn't advance */
4397c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%lx %x: %s\n", (long)addr, i, buf);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate mdb_iob_setflags(mdb.m_out, oflags);
4437c478bd9Sstevel@tonic-gate return (addr);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_binary(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)4477c478bd9Sstevel@tonic-gate fmt_binary(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate uint64_t x;
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
4527c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
4537c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, "%-64s",
4547c478bd9Sstevel@tonic-gate numtostr(x, 2, NTOS_UNSIGNED));
4557c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, x);
4567c478bd9Sstevel@tonic-gate addr += sizeof (x);
4577c478bd9Sstevel@tonic-gate } else {
4587c478bd9Sstevel@tonic-gate warn("failed to read data from target");
4597c478bd9Sstevel@tonic-gate break;
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate return (addr);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
fmt_hex64(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt)4667c478bd9Sstevel@tonic-gate fmt_hex64(mdb_tgt_t *t, mdb_tgt_as_t as, mdb_tgt_addr_t addr, size_t cnt)
4677c478bd9Sstevel@tonic-gate {
4687c478bd9Sstevel@tonic-gate const char *fmts[] = { "%-16llx", "%-17llx" };
4697c478bd9Sstevel@tonic-gate const uint64_t mask = 0xf000000000000000ull;
4707c478bd9Sstevel@tonic-gate uint64_t x;
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
4737c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, &x, sizeof (x), addr) == sizeof (x)) {
4747c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, fmts[(x & mask) != 0], x);
4757c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, x);
4767c478bd9Sstevel@tonic-gate addr += sizeof (x);
4777c478bd9Sstevel@tonic-gate } else {
4787c478bd9Sstevel@tonic-gate warn("failed to read data from target");
4797c478bd9Sstevel@tonic-gate break;
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate return (addr);
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate static const mdb_fmt_desc_t fmttab[] = {
4867c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 0 = NUL */
4877c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 1 = SOH */
4887c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 2 = STX */
4897c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 3 = ETX */
4907c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 4 = EOT */
4917c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 5 = ENQ */
4927c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 6 = ACK */
4937c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 7 = BEL */
4947c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 8 = BS */
4957c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 9 = \t */
4967c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 10 = \n */
4977c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 11 = VT */
4987c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 12 = FF */
4997c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 13 = \r */
5007c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 14 = SO */
5017c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 15 = SI */
5027c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 16 = DLE */
5037c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 17 = DC1 */
5047c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 18 = DC2 */
5057c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 19 = DC3 */
5067c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 20 = DC4 */
5077c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 21 = NAK */
5087c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 22 = EYC */
5097c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 23 = ETB */
5107c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 24 = CAN */
5117c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 25 = EM */
5127c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 26 = SUB */
5137c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 27 = ESC */
5147c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 28 = FS */
5157c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 29 = GS */
5167c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 30 = RS */
5177c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 31 = US */
5187c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 32 = SPACE */
5197c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 33 = ! */
5207c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 34 = " */
5217c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 35 = # */
5227c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 36 = $ */
5237c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 37 = % */
5247c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 38 = & */
5257c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 39 = ' */
5267c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 40 = ( */
5277c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 41 = ) */
5287c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 42 = * */
5297c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_plus), help_plus, 0 }, /* 43 = + */
5307c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 44 = , */
5317c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_minus), help_minus, 0 }, /* 45 = - */
5327c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 46 = . */
5337c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 47 = / */
5347c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 48 = 0 */
5357c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 49 = 1 */
5367c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 50 = 2 */
5377c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 51 = 3 */
5387c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 52 = 4 */
5397c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 53 = 5 */
5407c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 54 = 6 */
5417c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 55 = 7 */
5427c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 56 = 8 */
5437c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 57 = 9 */
5447c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 58 = : */
5457c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 59 = ; */
5467c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 60 = < */
5477c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 61 = = */
5487c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 62 = > */
5497c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 63 = ? */
5507c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 64 = @ */
5517c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 65 = A */
5527c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-8x", NULL, 1 }, /* 66 = B */
5537c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_escchr), help_escchr, 1 }, /* 67 = C */
5547c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16d", NULL, 4 }, /* 68 = D */
5557c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16llu", NULL, 8 }, /* 69 = E */
5567c478bd9Sstevel@tonic-gate #ifdef _KMDB
5577c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 70 = F */
5587c478bd9Sstevel@tonic-gate #else
5597c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%g", NULL, sizeof (double) }, /* 70 = F */
5607c478bd9Sstevel@tonic-gate #endif
5617c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16llo", NULL, 8 }, /* 71 = G */
5627c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_swapint), help_swapint, 4 }, /* 72 = H */
5637c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_dotinstr), help_dotinstr, 0 }, /* 73 = I */
5647c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_hex64), help_hex64, 8 }, /* 74 = J */
5657c478bd9Sstevel@tonic-gate #ifdef _LP64
5667c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_hex64), help_uintptr, 8 }, /* 75 = K (J) */
5677c478bd9Sstevel@tonic-gate #else
5687c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16x", help_uintptr, 4 }, /* 75 = K (X) */
5697c478bd9Sstevel@tonic-gate #endif
5707c478bd9Sstevel@tonic-gate { FMT_MATCH, NULL, help_match32, 4 }, /* 76 = L */
5717c478bd9Sstevel@tonic-gate { FMT_MATCH, NULL, help_match64, 8 }, /* 77 = M */
5727c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_nl), help_nl, SZ_NONE }, /* 78 = N */
5737c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-#16o", NULL, 4 }, /* 79 = O */
5747c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16a", NULL, sizeof (uintptr_t) }, /* 80 = P */
5757c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-#16q", NULL, 4 }, /* 81 = Q */
5767c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_binary), help_binary, 8 }, /* 82 = R */
5777c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_escstr), help_escstr, 0 }, /* 83 = S */
5787c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_tab), help_tab, SZ_NONE }, /* 84 = T */
5797c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16u", NULL, 4 }, /* 85 = U */
5807c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-8u", NULL, 1 }, /* 86 = V */
5817c478bd9Sstevel@tonic-gate { FMT_PRINTF|FMT_WRITE, "%-16r", NULL, 4 }, /* 87 = W */
5827c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16x", NULL, 4 }, /* 88 = X */
5837c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_time32), help_time32, 4 }, /* 89 = Y */
5847c478bd9Sstevel@tonic-gate { FMT_FUNC|FMT_WRITE, FUNCP(fmt_hex64), help_hex64, 8 }, /* 90 = Z */
5857c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 91 = [ */
5867c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 92 = \ */
5877c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 93 = ] */
5887c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_carat), help_carat, 0 }, /* 94 = ^ */
5897c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 95 = _ */
5907c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 96 = ` */
5917c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_dot), help_dot, SZ_NONE }, /* 97 = a */
5927c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-#8o", NULL, 1 }, /* 98 = b */
5937c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%c", NULL, 1 }, /* 99 = c */
5947c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-8hd", NULL, 2 }, /* 100 = d */
5957c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16lld", NULL, 8 }, /* 101 = e */
5967c478bd9Sstevel@tonic-gate #ifdef _KMDB
5977c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 102 = f */
5987c478bd9Sstevel@tonic-gate #else
5997c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_float), help_f, sizeof (float) }, /* 102 = f */
6007c478bd9Sstevel@tonic-gate #endif
6017c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16llq", NULL, 8 }, /* 103 = g */
6027c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_swapshort), help_swapshort, 2 }, /* 104 = h */
6037c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_instr), help_instr, 0 }, /* 105 = i */
6047c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 106 = j */
6057c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 107 = k */
6067c478bd9Sstevel@tonic-gate { FMT_MATCH, NULL, help_match16, 2 }, /* 108 = l */
6077c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 109 = m */
6087c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_nl), help_nl, SZ_NONE }, /* 110 = n */
6097c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-#8ho", NULL, 2 }, /* 111 = o */
6107c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-16a", NULL, sizeof (uintptr_t) }, /* 112 = p */
6117c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-#8hq", NULL, 2 }, /* 113 = q */
6127c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_ws), help_ws, SZ_NONE }, /* 114 = r */
6137c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_rawstr), help_rawstr, 0 }, /* 115 = s */
6147c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_tab), help_tab, SZ_NONE }, /* 116 = t */
6157c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-8hu", NULL, 2 }, /* 117 = u */
6167c478bd9Sstevel@tonic-gate { FMT_FUNC|FMT_WRITE, FUNCP(fmt_sdbyte), help_sdbyte, 1 }, /* 118 = v */
6177c478bd9Sstevel@tonic-gate { FMT_PRINTF|FMT_WRITE, "%-8hr", NULL, 2 }, /* 119 = w */
6187c478bd9Sstevel@tonic-gate { FMT_PRINTF, "%-8hx", NULL, 2 }, /* 120 = x */
6197c478bd9Sstevel@tonic-gate { FMT_FUNC, FUNCP(fmt_time64), help_time64, 8 }, /* 121 = y */
6207c478bd9Sstevel@tonic-gate { FMT_NONE, NULL, NULL, 0 }, /* 122 = z */
6217c478bd9Sstevel@tonic-gate };
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate mdb_tgt_addr_t
mdb_fmt_print(mdb_tgt_t * t,mdb_tgt_as_t as,mdb_tgt_addr_t addr,size_t cnt,char fmt)6247c478bd9Sstevel@tonic-gate mdb_fmt_print(mdb_tgt_t *t, mdb_tgt_as_t as,
6257c478bd9Sstevel@tonic-gate mdb_tgt_addr_t addr, size_t cnt, char fmt)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate const mdb_fmt_desc_t *fp = &fmttab[fmt];
6287c478bd9Sstevel@tonic-gate mdb_fmt_func_f *funcp;
6297c478bd9Sstevel@tonic-gate uintmax_t rvalue;
6307c478bd9Sstevel@tonic-gate void *buf;
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate union {
6337c478bd9Sstevel@tonic-gate uint64_t i8;
6347c478bd9Sstevel@tonic-gate uint32_t i4;
6357c478bd9Sstevel@tonic-gate uint16_t i2;
6367c478bd9Sstevel@tonic-gate uint8_t i1;
6377c478bd9Sstevel@tonic-gate } u;
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate if (fmt < 0 || fmt > (sizeof (fmttab) / sizeof (fmttab[0]))) {
6407c478bd9Sstevel@tonic-gate warn("invalid format character -- '%c'\n", fmt);
6417c478bd9Sstevel@tonic-gate return (addr);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate switch (FMT_TYPE(fp->f_type)) {
6457c478bd9Sstevel@tonic-gate case FMT_FUNC:
6467c478bd9Sstevel@tonic-gate funcp = (mdb_fmt_func_f *)fp->f_ptr;
6477c478bd9Sstevel@tonic-gate addr = funcp(t, as, addr, cnt);
6487c478bd9Sstevel@tonic-gate break;
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate case FMT_PRINTF:
6517c478bd9Sstevel@tonic-gate switch (fp->f_size) {
6527c478bd9Sstevel@tonic-gate case 1:
6537c478bd9Sstevel@tonic-gate buf = &u.i1;
6547c478bd9Sstevel@tonic-gate break;
6557c478bd9Sstevel@tonic-gate case 2:
6567c478bd9Sstevel@tonic-gate buf = &u.i2;
6577c478bd9Sstevel@tonic-gate break;
6587c478bd9Sstevel@tonic-gate case 4:
6597c478bd9Sstevel@tonic-gate buf = &u.i4;
6607c478bd9Sstevel@tonic-gate break;
6617c478bd9Sstevel@tonic-gate case 8:
6627c478bd9Sstevel@tonic-gate buf = &u.i8;
6637c478bd9Sstevel@tonic-gate break;
6647c478bd9Sstevel@tonic-gate default:
6657c478bd9Sstevel@tonic-gate fail("format %c is defined using illegal size\n", fmt);
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate while (cnt-- != 0) {
6697c478bd9Sstevel@tonic-gate if (mdb_tgt_aread(t, as, buf, fp->f_size, addr) !=
6707c478bd9Sstevel@tonic-gate fp->f_size) {
6717c478bd9Sstevel@tonic-gate warn("failed to read data from target");
6727c478bd9Sstevel@tonic-gate return (addr);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate switch (fp->f_size) {
6767c478bd9Sstevel@tonic-gate case 1:
6777c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, fp->f_ptr, u.i1);
6787c478bd9Sstevel@tonic-gate rvalue = u.i1;
6797c478bd9Sstevel@tonic-gate break;
6807c478bd9Sstevel@tonic-gate case 2:
6817c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, fp->f_ptr, u.i2);
6827c478bd9Sstevel@tonic-gate rvalue = u.i2;
6837c478bd9Sstevel@tonic-gate break;
6847c478bd9Sstevel@tonic-gate case 4:
6857c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, fp->f_ptr, u.i4);
6867c478bd9Sstevel@tonic-gate rvalue = u.i4;
6877c478bd9Sstevel@tonic-gate break;
6887c478bd9Sstevel@tonic-gate case 8:
6897c478bd9Sstevel@tonic-gate mdb_iob_printf(mdb.m_out, fp->f_ptr, u.i8);
6907c478bd9Sstevel@tonic-gate rvalue = u.i8;
6917c478bd9Sstevel@tonic-gate break;
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate mdb_nv_set_value(mdb.m_rvalue, rvalue);
6957c478bd9Sstevel@tonic-gate addr += fp->f_size;
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate break;
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate default:
7007c478bd9Sstevel@tonic-gate warn("invalid format character -- '%c'\n", fmt);
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate return (addr);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7077c478bd9Sstevel@tonic-gate int
cmd_formats(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)7087c478bd9Sstevel@tonic-gate cmd_formats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7097c478bd9Sstevel@tonic-gate {
7107c478bd9Sstevel@tonic-gate const mdb_fmt_desc_t *fp = &fmttab[0];
7117c478bd9Sstevel@tonic-gate int i;
7127c478bd9Sstevel@tonic-gate const char *write;
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) || argc != 0)
7157c478bd9Sstevel@tonic-gate return (DCMD_USAGE);
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate for (i = 0; i < (sizeof (fmttab) / sizeof (fmttab[0])); i++, fp++) {
7187c478bd9Sstevel@tonic-gate if (fp->f_type == FMT_NONE)
7197c478bd9Sstevel@tonic-gate continue;
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate write = (fp->f_type & FMT_WRITE) ? "write " : "";
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate if (fp->f_type & FMT_FUNC)
7247c478bd9Sstevel@tonic-gate mdb_printf("%c - %s%s", i, write, fp->f_help);
7257c478bd9Sstevel@tonic-gate else if (fp->f_type & FMT_MATCH)
7267c478bd9Sstevel@tonic-gate mdb_printf("%c - match %s", i, fp->f_help);
7277c478bd9Sstevel@tonic-gate else if (fp->f_help != NULL)
7287c478bd9Sstevel@tonic-gate mdb_printf("%c - %s%s", i, write, fp->f_help);
7297c478bd9Sstevel@tonic-gate else
7307c478bd9Sstevel@tonic-gate mdb_printf("%c - %s%s", i, write,
7317c478bd9Sstevel@tonic-gate mdb_iob_format2str(fp->f_ptr));
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate switch (fp->f_size) {
7347c478bd9Sstevel@tonic-gate case SZ_NONE:
7357c478bd9Sstevel@tonic-gate mdb_printf("\n");
7367c478bd9Sstevel@tonic-gate break;
7377c478bd9Sstevel@tonic-gate case 0:
7387c478bd9Sstevel@tonic-gate mdb_printf(" (variable size)\n");
7397c478bd9Sstevel@tonic-gate break;
7407c478bd9Sstevel@tonic-gate case 1:
7417c478bd9Sstevel@tonic-gate mdb_printf(" (1 byte)\n");
7427c478bd9Sstevel@tonic-gate break;
7437c478bd9Sstevel@tonic-gate default:
7447c478bd9Sstevel@tonic-gate mdb_printf(" (%lu bytes)\n", fp->f_size);
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate return (DCMD_OK);
7497c478bd9Sstevel@tonic-gate }
750