xref: /titanic_52/usr/src/cmd/mdb/common/mdb/mdb_fmt.c (revision a727d47a89ceb54faa3aecb01ab9b1a7961d6a79)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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