xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_cmds.c (revision bbf21555)
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
5af7034caSss  * Common Development and Distribution License (the "License").
6af7034caSss  * 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  */
21af7034caSss 
227c478bd9Sstevel@tonic-gate /*
234a1c2431SJonathan Adams  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
273b6e0a59SMatt Amdur /*
283b6e0a59SMatt Amdur  * Copyright (c) 2012 by Delphix. All rights reserved.
29089ef9c1SJason King  * Copyright 2021 Joyent, Inc.
30065c692aSJosef 'Jeff' Sipek  * Copyright (c) 2013 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
313d580edaSSerapheim Dimitropoulos  * Copyright (c) 2015, 2017 by Delphix. All rights reserved.
321700af3aSAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
333b6e0a59SMatt Amdur  */
343b6e0a59SMatt Amdur 
357c478bd9Sstevel@tonic-gate #include <sys/elf.h>
367c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <libproc.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <string.h>
417c478bd9Sstevel@tonic-gate #include <fcntl.h>
427c478bd9Sstevel@tonic-gate #include <errno.h>
437c478bd9Sstevel@tonic-gate #include <alloca.h>
447c478bd9Sstevel@tonic-gate #include <libctf.h>
457c478bd9Sstevel@tonic-gate #include <ctype.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h>
487c478bd9Sstevel@tonic-gate #include <mdb/mdb_argvec.h>
497c478bd9Sstevel@tonic-gate #include <mdb/mdb_nv.h>
507c478bd9Sstevel@tonic-gate #include <mdb/mdb_fmt.h>
517c478bd9Sstevel@tonic-gate #include <mdb/mdb_target.h>
527c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
537c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
547c478bd9Sstevel@tonic-gate #include <mdb/mdb_conf.h>
557c478bd9Sstevel@tonic-gate #include <mdb/mdb_module.h>
567c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
577c478bd9Sstevel@tonic-gate #include <mdb/mdb_stdlib.h>
587c478bd9Sstevel@tonic-gate #include <mdb/mdb_lex.h>
597c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h>
607c478bd9Sstevel@tonic-gate #include <mdb/mdb_help.h>
617c478bd9Sstevel@tonic-gate #include <mdb/mdb_disasm.h>
627c478bd9Sstevel@tonic-gate #include <mdb/mdb_frame.h>
637c478bd9Sstevel@tonic-gate #include <mdb/mdb_evset.h>
647c478bd9Sstevel@tonic-gate #include <mdb/mdb_print.h>
657c478bd9Sstevel@tonic-gate #include <mdb/mdb_nm.h>
667c478bd9Sstevel@tonic-gate #include <mdb/mdb_set.h>
677c478bd9Sstevel@tonic-gate #include <mdb/mdb_demangle.h>
687c478bd9Sstevel@tonic-gate #include <mdb/mdb_ctf.h>
694a1c2431SJonathan Adams #include <mdb/mdb_whatis.h>
704a1c2431SJonathan Adams #include <mdb/mdb_whatis_impl.h>
717c478bd9Sstevel@tonic-gate #include <mdb/mdb_macalias.h>
723b6e0a59SMatt Amdur #include <mdb/mdb_tab.h>
730a47c91cSRobert Mustacchi #include <mdb/mdb_typedef.h>
74089ef9c1SJason King #include <mdb/mdb_linkerset.h>
757c478bd9Sstevel@tonic-gate #ifdef _KMDB
767c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h>
777c478bd9Sstevel@tonic-gate #endif
787c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #ifdef __sparc
817c478bd9Sstevel@tonic-gate #define	SETHI_MASK	0xc1c00000
827c478bd9Sstevel@tonic-gate #define	SETHI_VALUE	0x01000000
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #define	IS_SETHI(machcode)	(((machcode) & SETHI_MASK) == SETHI_VALUE)
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #define	OP(machcode)	((machcode) >> 30)
877c478bd9Sstevel@tonic-gate #define	OP3(machcode)	(((machcode) >> 19) & 0x3f)
887c478bd9Sstevel@tonic-gate #define	RD(machcode)	(((machcode) >> 25) & 0x1f)
897c478bd9Sstevel@tonic-gate #define	RS1(machcode)	(((machcode) >> 14) & 0x1f)
907c478bd9Sstevel@tonic-gate #define	I(machcode)	(((machcode) >> 13) & 0x01)
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #define	IMM13(machcode)	((machcode) & 0x1fff)
937c478bd9Sstevel@tonic-gate #define	IMM22(machcode)	((machcode) & 0x3fffff)
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate #define	OP_ARITH_MEM_MASK	0x2
967c478bd9Sstevel@tonic-gate #define	OP_ARITH		0x2
977c478bd9Sstevel@tonic-gate #define	OP_MEM			0x3
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate #define	OP3_CC_MASK		0x10
1007c478bd9Sstevel@tonic-gate #define	OP3_COMPLEX_MASK	0x20
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate #define	OP3_ADD			0x00
1037c478bd9Sstevel@tonic-gate #define	OP3_OR			0x02
1047c478bd9Sstevel@tonic-gate #define	OP3_XOR			0x03
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate #ifndef	R_O7
1077c478bd9Sstevel@tonic-gate #define	R_O7	0xf
1087c478bd9Sstevel@tonic-gate #endif
1097c478bd9Sstevel@tonic-gate #endif /* __sparc */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
write_uint8(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t ull,uint_t rdback)1127c478bd9Sstevel@tonic-gate write_uint8(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t ull, uint_t rdback)
1137c478bd9Sstevel@tonic-gate {
1147c478bd9Sstevel@tonic-gate 	uint8_t o, n = (uint8_t)ull;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (rdback && mdb_tgt_aread(mdb.m_target, as, &o, sizeof (o),
1177c478bd9Sstevel@tonic-gate 	    addr) == -1)
1187c478bd9Sstevel@tonic-gate 		return (addr);
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	if (mdb_tgt_awrite(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1217c478bd9Sstevel@tonic-gate 		return (addr);
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if (rdback) {
1247c478bd9Sstevel@tonic-gate 		if (mdb_tgt_aread(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1257c478bd9Sstevel@tonic-gate 			return (addr);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 		mdb_iob_printf(mdb.m_out, "%-#*lla%16T%-#8x=%8T0x%x\n",
1287c478bd9Sstevel@tonic-gate 		    mdb_iob_getmargin(mdb.m_out), addr, o, n);
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	return (addr + sizeof (n));
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
write_uint16(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t ull,uint_t rdback)1357c478bd9Sstevel@tonic-gate write_uint16(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t ull, uint_t rdback)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate 	uint16_t o, n = (uint16_t)ull;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	if (rdback && mdb_tgt_aread(mdb.m_target, as, &o, sizeof (o),
1407c478bd9Sstevel@tonic-gate 	    addr) == -1)
1417c478bd9Sstevel@tonic-gate 		return (addr);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	if (mdb_tgt_awrite(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1447c478bd9Sstevel@tonic-gate 		return (addr);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (rdback) {
1477c478bd9Sstevel@tonic-gate 		if (mdb_tgt_aread(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1487c478bd9Sstevel@tonic-gate 			return (addr);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 		mdb_iob_printf(mdb.m_out, "%-#*lla%16T%-#8hx=%8T0x%hx\n",
1517c478bd9Sstevel@tonic-gate 		    mdb_iob_getmargin(mdb.m_out), addr, o, n);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	return (addr + sizeof (n));
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
write_uint32(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t ull,uint_t rdback)1587c478bd9Sstevel@tonic-gate write_uint32(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t ull, uint_t rdback)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	uint32_t o, n = (uint32_t)ull;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	if (rdback && mdb_tgt_aread(mdb.m_target, as, &o, sizeof (o),
1637c478bd9Sstevel@tonic-gate 	    addr) == -1)
1647c478bd9Sstevel@tonic-gate 		return (addr);
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (mdb_tgt_awrite(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1677c478bd9Sstevel@tonic-gate 		return (addr);
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	if (rdback) {
1707c478bd9Sstevel@tonic-gate 		if (mdb_tgt_aread(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1717c478bd9Sstevel@tonic-gate 			return (addr);
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 		mdb_iob_printf(mdb.m_out, "%-#*lla%16T%-#16x=%8T0x%x\n",
1747c478bd9Sstevel@tonic-gate 		    mdb_iob_getmargin(mdb.m_out), addr, o, n);
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	return (addr + sizeof (n));
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
write_uint64(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t n,uint_t rdback)1817c478bd9Sstevel@tonic-gate write_uint64(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t n, uint_t rdback)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate 	uint64_t o;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	if (rdback && mdb_tgt_aread(mdb.m_target, as, &o, sizeof (o),
1867c478bd9Sstevel@tonic-gate 	    addr) == -1)
1877c478bd9Sstevel@tonic-gate 		return (addr);
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	if (mdb_tgt_awrite(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1907c478bd9Sstevel@tonic-gate 		return (addr);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (rdback) {
1937c478bd9Sstevel@tonic-gate 		if (mdb_tgt_aread(mdb.m_target, as, &n, sizeof (n), addr) == -1)
1947c478bd9Sstevel@tonic-gate 			return (addr);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 		mdb_iob_printf(mdb.m_out, "%-#*lla%16T%-#24llx=%8T0x%llx\n",
1977c478bd9Sstevel@tonic-gate 		    mdb_iob_getmargin(mdb.m_out), addr, o, n);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	return (addr + sizeof (n));
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2033d580edaSSerapheim Dimitropoulos /*
2043d580edaSSerapheim Dimitropoulos  * Writes to objects of size 1, 2, 4, or 8 bytes. The function
2053d580edaSSerapheim Dimitropoulos  * doesn't care if the object is a number or not (e.g. it could
2063d580edaSSerapheim Dimitropoulos  * be a byte array, or a struct) as long as the size of the write
2073d580edaSSerapheim Dimitropoulos  * is one of the aforementioned ones.
2083d580edaSSerapheim Dimitropoulos  */
2093d580edaSSerapheim Dimitropoulos static mdb_tgt_addr_t
write_var_uint(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t val,size_t size,uint_t rdback)2103d580edaSSerapheim Dimitropoulos write_var_uint(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t val, size_t size,
2113d580edaSSerapheim Dimitropoulos     uint_t rdback)
2123d580edaSSerapheim Dimitropoulos {
2133d580edaSSerapheim Dimitropoulos 	if (size < sizeof (uint64_t)) {
2143d580edaSSerapheim Dimitropoulos 		uint64_t max_num = 1ULL << (size * NBBY);
2153d580edaSSerapheim Dimitropoulos 
2163d580edaSSerapheim Dimitropoulos 		if (val >= max_num) {
2173d580edaSSerapheim Dimitropoulos 			uint64_t write_len = 0;
2183d580edaSSerapheim Dimitropoulos 
2193d580edaSSerapheim Dimitropoulos 			/* count bytes needed for val */
2203d580edaSSerapheim Dimitropoulos 			while (val != 0) {
2213d580edaSSerapheim Dimitropoulos 				write_len++;
2223d580edaSSerapheim Dimitropoulos 				val >>= NBBY;
2233d580edaSSerapheim Dimitropoulos 			}
2243d580edaSSerapheim Dimitropoulos 
2253d580edaSSerapheim Dimitropoulos 			mdb_warn("value too big for the length of the write: "
2263d580edaSSerapheim Dimitropoulos 			    "supplied %llu bytes but maximum is %llu bytes\n",
2273d580edaSSerapheim Dimitropoulos 			    (u_longlong_t)write_len, (u_longlong_t)size);
2283d580edaSSerapheim Dimitropoulos 			return (addr);
2293d580edaSSerapheim Dimitropoulos 		}
2303d580edaSSerapheim Dimitropoulos 	}
2313d580edaSSerapheim Dimitropoulos 
2323d580edaSSerapheim Dimitropoulos 	switch (size) {
2333d580edaSSerapheim Dimitropoulos 	case 1:
2343d580edaSSerapheim Dimitropoulos 		return (write_uint8(as, addr, val, rdback));
2353d580edaSSerapheim Dimitropoulos 	case 2:
2363d580edaSSerapheim Dimitropoulos 		return (write_uint16(as, addr, val, rdback));
2373d580edaSSerapheim Dimitropoulos 	case 4:
2383d580edaSSerapheim Dimitropoulos 		return (write_uint32(as, addr, val, rdback));
2393d580edaSSerapheim Dimitropoulos 	case 8:
2403d580edaSSerapheim Dimitropoulos 		return (write_uint64(as, addr, val, rdback));
2413d580edaSSerapheim Dimitropoulos 	default:
2423d580edaSSerapheim Dimitropoulos 		mdb_warn("writes of size %u are not supported\n ", size);
2433d580edaSSerapheim Dimitropoulos 		return (addr);
2443d580edaSSerapheim Dimitropoulos 	}
2453d580edaSSerapheim Dimitropoulos }
2463d580edaSSerapheim Dimitropoulos 
2473d580edaSSerapheim Dimitropoulos static mdb_tgt_addr_t
write_ctf_uint(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t n,uint_t rdback)2483d580edaSSerapheim Dimitropoulos write_ctf_uint(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t n, uint_t rdback)
2493d580edaSSerapheim Dimitropoulos {
2503d580edaSSerapheim Dimitropoulos 	mdb_ctf_id_t mid;
2513d580edaSSerapheim Dimitropoulos 	size_t size;
2523d580edaSSerapheim Dimitropoulos 	ssize_t type_size;
2533d580edaSSerapheim Dimitropoulos 	int kind;
2543d580edaSSerapheim Dimitropoulos 
2553d580edaSSerapheim Dimitropoulos 	if (mdb_ctf_lookup_by_addr(addr, &mid) != 0) {
2563d580edaSSerapheim Dimitropoulos 		mdb_warn("no CTF data found at this address\n");
2573d580edaSSerapheim Dimitropoulos 		return (addr);
2583d580edaSSerapheim Dimitropoulos 	}
2593d580edaSSerapheim Dimitropoulos 
2603d580edaSSerapheim Dimitropoulos 	kind = mdb_ctf_type_kind(mid);
2613d580edaSSerapheim Dimitropoulos 	if (kind == CTF_ERR) {
2623d580edaSSerapheim Dimitropoulos 		mdb_warn("CTF data found but type kind could not be read");
2633d580edaSSerapheim Dimitropoulos 		return (addr);
2643d580edaSSerapheim Dimitropoulos 	}
2653d580edaSSerapheim Dimitropoulos 
2663d580edaSSerapheim Dimitropoulos 	if (kind == CTF_K_TYPEDEF) {
2673d580edaSSerapheim Dimitropoulos 		mdb_ctf_id_t temp_id;
2683d580edaSSerapheim Dimitropoulos 		if (mdb_ctf_type_resolve(mid, &temp_id) != 0) {
2693d580edaSSerapheim Dimitropoulos 			mdb_warn("failed to resolve type");
2703d580edaSSerapheim Dimitropoulos 			return (addr);
2713d580edaSSerapheim Dimitropoulos 		}
2723d580edaSSerapheim Dimitropoulos 		kind = mdb_ctf_type_kind(temp_id);
2733d580edaSSerapheim Dimitropoulos 	}
2743d580edaSSerapheim Dimitropoulos 
2753d580edaSSerapheim Dimitropoulos 	if (kind != CTF_K_INTEGER && kind != CTF_K_POINTER &&
2763d580edaSSerapheim Dimitropoulos 	    kind != CTF_K_ENUM) {
2773d580edaSSerapheim Dimitropoulos 		mdb_warn("CTF type should be integer, pointer, or enum\n");
2783d580edaSSerapheim Dimitropoulos 		return (addr);
2793d580edaSSerapheim Dimitropoulos 	}
2803d580edaSSerapheim Dimitropoulos 
2813d580edaSSerapheim Dimitropoulos 	type_size = mdb_ctf_type_size(mid);
2823d580edaSSerapheim Dimitropoulos 	if (type_size < 0) {
2833d580edaSSerapheim Dimitropoulos 		mdb_warn("CTF data found but size could not be read");
2843d580edaSSerapheim Dimitropoulos 		return (addr);
2853d580edaSSerapheim Dimitropoulos 	}
2863d580edaSSerapheim Dimitropoulos 	size = type_size;
2873d580edaSSerapheim Dimitropoulos 
2883d580edaSSerapheim Dimitropoulos 	return (write_var_uint(as, addr, n, size, rdback));
2893d580edaSSerapheim Dimitropoulos }
2903d580edaSSerapheim Dimitropoulos 
2917c478bd9Sstevel@tonic-gate static int
write_arglist(mdb_tgt_as_t as,mdb_tgt_addr_t addr,int argc,const mdb_arg_t * argv)2927c478bd9Sstevel@tonic-gate write_arglist(mdb_tgt_as_t as, mdb_tgt_addr_t addr,
2937c478bd9Sstevel@tonic-gate     int argc, const mdb_arg_t *argv)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	mdb_tgt_addr_t (*write_value)(mdb_tgt_as_t, mdb_tgt_addr_t,
2967c478bd9Sstevel@tonic-gate 	    uint64_t, uint_t);
2977c478bd9Sstevel@tonic-gate 	mdb_tgt_addr_t naddr;
2987c478bd9Sstevel@tonic-gate 	uintmax_t value;
2997c478bd9Sstevel@tonic-gate 	int rdback = mdb.m_flags & MDB_FL_READBACK;
3007c478bd9Sstevel@tonic-gate 	size_t i;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	if (argc == 1) {
3037c478bd9Sstevel@tonic-gate 		mdb_warn("expected value to write following %c\n",
3047c478bd9Sstevel@tonic-gate 		    argv->a_un.a_char);
3057c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	switch (argv->a_un.a_char) {
3097c478bd9Sstevel@tonic-gate 	case 'v':
3107c478bd9Sstevel@tonic-gate 		write_value = write_uint8;
3117c478bd9Sstevel@tonic-gate 		break;
3127c478bd9Sstevel@tonic-gate 	case 'w':
3137c478bd9Sstevel@tonic-gate 		write_value = write_uint16;
3147c478bd9Sstevel@tonic-gate 		break;
3153d580edaSSerapheim Dimitropoulos 	case 'z':
3163d580edaSSerapheim Dimitropoulos 		write_value = write_ctf_uint;
3173d580edaSSerapheim Dimitropoulos 		break;
3187c478bd9Sstevel@tonic-gate 	case 'W':
3197c478bd9Sstevel@tonic-gate 		write_value = write_uint32;
3207c478bd9Sstevel@tonic-gate 		break;
3217c478bd9Sstevel@tonic-gate 	case 'Z':
3227c478bd9Sstevel@tonic-gate 		write_value = write_uint64;
3237c478bd9Sstevel@tonic-gate 		break;
32424537d3eSToomas Soome 	default:
32524537d3eSToomas Soome 		write_value = NULL;
32624537d3eSToomas Soome 		break;
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	for (argv++, i = 1; i < argc; i++, argv++) {
3307c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_CHAR) {
3317c478bd9Sstevel@tonic-gate 			mdb_warn("expected immediate value instead of '%c'\n",
3327c478bd9Sstevel@tonic-gate 			    argv->a_un.a_char);
3337c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_STRING) {
3377c478bd9Sstevel@tonic-gate 			if (mdb_eval(argv->a_un.a_str) == -1) {
3387c478bd9Sstevel@tonic-gate 				mdb_warn("failed to write \"%s\"",
3397c478bd9Sstevel@tonic-gate 				    argv->a_un.a_str);
3407c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
3417c478bd9Sstevel@tonic-gate 			}
3427c478bd9Sstevel@tonic-gate 			value = mdb_nv_get_value(mdb.m_dot);
3437c478bd9Sstevel@tonic-gate 		} else
3447c478bd9Sstevel@tonic-gate 			value = argv->a_un.a_val;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 		mdb_nv_set_value(mdb.m_dot, addr);
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 		if ((naddr = write_value(as, addr, value, rdback)) == addr) {
3497c478bd9Sstevel@tonic-gate 			mdb_warn("failed to write %llr at address 0x%llx",
3507c478bd9Sstevel@tonic-gate 			    value, addr);
3517c478bd9Sstevel@tonic-gate 			mdb.m_incr = 0;
352bc07d1fdSCody Peter Mello 			return (DCMD_ERR);
3537c478bd9Sstevel@tonic-gate 		}
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		mdb.m_incr = naddr - addr;
3567c478bd9Sstevel@tonic-gate 		addr = naddr;
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
match_uint16(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t v64,uint64_t m64)3637c478bd9Sstevel@tonic-gate match_uint16(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t v64, uint64_t m64)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate 	uint16_t x, val = (uint16_t)v64, mask = (uint16_t)m64;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	for (; mdb_tgt_aread(mdb.m_target, as, &x,
3687c478bd9Sstevel@tonic-gate 	    sizeof (x), addr) == sizeof (x); addr += sizeof (x)) {
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		if ((x & mask) == val) {
3717c478bd9Sstevel@tonic-gate 			mdb_iob_printf(mdb.m_out, "%lla\n", addr);
3727c478bd9Sstevel@tonic-gate 			break;
3737c478bd9Sstevel@tonic-gate 		}
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 	return (addr);
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
match_uint32(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t v64,uint64_t m64)3797c478bd9Sstevel@tonic-gate match_uint32(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t v64, uint64_t m64)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 	uint32_t x, val = (uint32_t)v64, mask = (uint32_t)m64;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	for (; mdb_tgt_aread(mdb.m_target, as, &x,
3847c478bd9Sstevel@tonic-gate 	    sizeof (x), addr) == sizeof (x); addr += sizeof (x)) {
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 		if ((x & mask) == val) {
3877c478bd9Sstevel@tonic-gate 			mdb_iob_printf(mdb.m_out, "%lla\n", addr);
3887c478bd9Sstevel@tonic-gate 			break;
3897c478bd9Sstevel@tonic-gate 		}
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 	return (addr);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate static mdb_tgt_addr_t
match_uint64(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint64_t val,uint64_t mask)3957c478bd9Sstevel@tonic-gate match_uint64(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint64_t val, uint64_t mask)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate 	uint64_t x;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	for (; mdb_tgt_aread(mdb.m_target, as, &x,
4007c478bd9Sstevel@tonic-gate 	    sizeof (x), addr) == sizeof (x); addr += sizeof (x)) {
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 		if ((x & mask) == val) {
4037c478bd9Sstevel@tonic-gate 			mdb_iob_printf(mdb.m_out, "%lla\n", addr);
4047c478bd9Sstevel@tonic-gate 			break;
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 	return (addr);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate static int
match_arglist(mdb_tgt_as_t as,uint_t flags,mdb_tgt_addr_t addr,int argc,const mdb_arg_t * argv)4117c478bd9Sstevel@tonic-gate match_arglist(mdb_tgt_as_t as, uint_t flags, mdb_tgt_addr_t addr,
4127c478bd9Sstevel@tonic-gate     int argc, const mdb_arg_t *argv)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	mdb_tgt_addr_t (*match_value)(mdb_tgt_as_t, mdb_tgt_addr_t,
4157c478bd9Sstevel@tonic-gate 	    uint64_t, uint64_t);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	uint64_t args[2] = { 0, -1ULL }; /* [ value, mask ] */
4187c478bd9Sstevel@tonic-gate 	size_t i;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	if (argc < 2) {
4217c478bd9Sstevel@tonic-gate 		mdb_warn("expected value following %c\n", argv->a_un.a_char);
4227c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	if (argc > 3) {
4267c478bd9Sstevel@tonic-gate 		mdb_warn("only value and mask may follow %c\n",
4277c478bd9Sstevel@tonic-gate 		    argv->a_un.a_char);
4287c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	switch (argv->a_un.a_char) {
4327c478bd9Sstevel@tonic-gate 	case 'l':
4337c478bd9Sstevel@tonic-gate 		match_value = match_uint16;
4347c478bd9Sstevel@tonic-gate 		break;
4357c478bd9Sstevel@tonic-gate 	case 'L':
4367c478bd9Sstevel@tonic-gate 		match_value = match_uint32;
4377c478bd9Sstevel@tonic-gate 		break;
4387c478bd9Sstevel@tonic-gate 	case 'M':
4397c478bd9Sstevel@tonic-gate 		match_value = match_uint64;
4407c478bd9Sstevel@tonic-gate 		break;
44124537d3eSToomas Soome 	default:
44224537d3eSToomas Soome 		mdb_warn("unknown match value %c\n",
44324537d3eSToomas Soome 		    argv->a_un.a_char);
44424537d3eSToomas Soome 		return (DCMD_ERR);
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	for (argv++, i = 1; i < argc; i++, argv++) {
4487c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_CHAR) {
4497c478bd9Sstevel@tonic-gate 			mdb_warn("expected immediate value instead of '%c'\n",
4507c478bd9Sstevel@tonic-gate 			    argv->a_un.a_char);
4517c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_STRING) {
4557c478bd9Sstevel@tonic-gate 			if (mdb_eval(argv->a_un.a_str) == -1) {
4567c478bd9Sstevel@tonic-gate 				mdb_warn("failed to evaluate \"%s\"",
4577c478bd9Sstevel@tonic-gate 				    argv->a_un.a_str);
4587c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
4597c478bd9Sstevel@tonic-gate 			}
4607c478bd9Sstevel@tonic-gate 			args[i - 1] = mdb_nv_get_value(mdb.m_dot);
4617c478bd9Sstevel@tonic-gate 		} else
4627c478bd9Sstevel@tonic-gate 			args[i - 1] = argv->a_un.a_val;
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	addr = match_value(as, addr, args[0], args[1]);
4667c478bd9Sstevel@tonic-gate 	mdb_nv_set_value(mdb.m_dot, addr);
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	/*
4697c478bd9Sstevel@tonic-gate 	 * In adb(1), the match operators ignore any repeat count that has
4707c478bd9Sstevel@tonic-gate 	 * been applied to them.  We emulate this undocumented property
4717c478bd9Sstevel@tonic-gate 	 * by returning DCMD_ABORT if our input is not a pipeline.
4727c478bd9Sstevel@tonic-gate 	 */
4737c478bd9Sstevel@tonic-gate 	return ((flags & DCMD_PIPE) ? DCMD_OK : DCMD_ABORT);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate static int
argncmp(int argc,const mdb_arg_t * argv,const char * s)4777c478bd9Sstevel@tonic-gate argncmp(int argc, const mdb_arg_t *argv, const char *s)
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++, argc--, argv++) {
4807c478bd9Sstevel@tonic-gate 		if (argc == 0 || argv->a_type != MDB_TYPE_CHAR)
4817c478bd9Sstevel@tonic-gate 			return (FALSE);
4827c478bd9Sstevel@tonic-gate 		if (argv->a_un.a_char != *s)
4837c478bd9Sstevel@tonic-gate 			return (FALSE);
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 	return (TRUE);
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate static int
print_arglist(mdb_tgt_as_t as,mdb_tgt_addr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)4897c478bd9Sstevel@tonic-gate print_arglist(mdb_tgt_as_t as, mdb_tgt_addr_t addr, uint_t flags,
4907c478bd9Sstevel@tonic-gate     int argc, const mdb_arg_t *argv)
4917c478bd9Sstevel@tonic-gate {
4927c478bd9Sstevel@tonic-gate 	char buf[MDB_TGT_SYM_NAMLEN];
4937c478bd9Sstevel@tonic-gate 	mdb_tgt_addr_t oaddr = addr;
4947c478bd9Sstevel@tonic-gate 	mdb_tgt_addr_t naddr;
4957c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
4967c478bd9Sstevel@tonic-gate 	size_t i, n;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) {
4997c478bd9Sstevel@tonic-gate 		const char *fmt;
5007c478bd9Sstevel@tonic-gate 		int is_dis;
5017c478bd9Sstevel@tonic-gate 		/*
5027c478bd9Sstevel@tonic-gate 		 * This is nasty, but necessary for precise adb compatibility.
5037c478bd9Sstevel@tonic-gate 		 * Detect disassembly format by looking for "ai" or "ia":
5047c478bd9Sstevel@tonic-gate 		 */
5057c478bd9Sstevel@tonic-gate 		if (argncmp(argc, argv, "ai")) {
5067c478bd9Sstevel@tonic-gate 			fmt = "%-#*lla\n";
5077c478bd9Sstevel@tonic-gate 			is_dis = TRUE;
5087c478bd9Sstevel@tonic-gate 		} else if (argncmp(argc, argv, "ia")) {
5097c478bd9Sstevel@tonic-gate 			fmt = "%-#*lla";
5107c478bd9Sstevel@tonic-gate 			is_dis = TRUE;
5117c478bd9Sstevel@tonic-gate 		} else {
5127c478bd9Sstevel@tonic-gate 			fmt = "%-#*lla%16T";
5137c478bd9Sstevel@tonic-gate 			is_dis = FALSE;
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 		/*
5177c478bd9Sstevel@tonic-gate 		 * If symbolic decoding is on, disassembly is off, and the
5187c478bd9Sstevel@tonic-gate 		 * address exactly matches a symbol, print the symbol name:
5197c478bd9Sstevel@tonic-gate 		 */
5207c478bd9Sstevel@tonic-gate 		if ((mdb.m_flags & MDB_FL_PSYM) && !is_dis &&
5217c478bd9Sstevel@tonic-gate 		    (as == MDB_TGT_AS_VIRT || as == MDB_TGT_AS_FILE) &&
5227c478bd9Sstevel@tonic-gate 		    mdb_tgt_lookup_by_addr(mdb.m_target, (uintptr_t)addr,
5237c478bd9Sstevel@tonic-gate 		    MDB_TGT_SYM_EXACT, buf, sizeof (buf), &sym, NULL) == 0)
5247c478bd9Sstevel@tonic-gate 			mdb_iob_printf(mdb.m_out, "%s:\n", buf);
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		/*
5277c478bd9Sstevel@tonic-gate 		 * If this is a virtual address, cast it so that it reflects
5287c478bd9Sstevel@tonic-gate 		 * only the valid component of the address.
5297c478bd9Sstevel@tonic-gate 		 */
5307c478bd9Sstevel@tonic-gate 		if (as == MDB_TGT_AS_VIRT)
5317c478bd9Sstevel@tonic-gate 			addr = (uintptr_t)addr;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 		mdb_iob_printf(mdb.m_out, fmt,
5347c478bd9Sstevel@tonic-gate 		    (uint_t)mdb_iob_getmargin(mdb.m_out), addr);
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (argc == 0) {
5387c478bd9Sstevel@tonic-gate 		/*
5397c478bd9Sstevel@tonic-gate 		 * Yes, for you trivia buffs: if you use a format verb and give
5407c478bd9Sstevel@tonic-gate 		 * no format string, you get: X^"= "i ... note that in adb the
5417c478bd9Sstevel@tonic-gate 		 * the '=' verb once had 'z' as its default, but then 'z' was
5427c478bd9Sstevel@tonic-gate 		 * deleted (it was once an alias for 'i') and so =\n now calls
5437c478bd9Sstevel@tonic-gate 		 * scanform("z") and produces a 'bad modifier' message.
5447c478bd9Sstevel@tonic-gate 		 */
5457c478bd9Sstevel@tonic-gate 		static const mdb_arg_t def_argv[] = {
5467c478bd9Sstevel@tonic-gate 			{ MDB_TYPE_CHAR, MDB_INIT_CHAR('X') },
5477c478bd9Sstevel@tonic-gate 			{ MDB_TYPE_CHAR, MDB_INIT_CHAR('^') },
5487c478bd9Sstevel@tonic-gate 			{ MDB_TYPE_STRING, MDB_INIT_STRING("= ") },
5497c478bd9Sstevel@tonic-gate 			{ MDB_TYPE_CHAR, MDB_INIT_CHAR('i') }
5507c478bd9Sstevel@tonic-gate 		};
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		argc = sizeof (def_argv) / sizeof (mdb_arg_t);
5537c478bd9Sstevel@tonic-gate 		argv = def_argv;
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	mdb_iob_setflags(mdb.m_out, MDB_IOB_INDENT);
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	for (i = 0, n = 1; i < argc; i++, argv++) {
5597c478bd9Sstevel@tonic-gate 		switch (argv->a_type) {
5607c478bd9Sstevel@tonic-gate 		case MDB_TYPE_CHAR:
5617c478bd9Sstevel@tonic-gate 			naddr = mdb_fmt_print(mdb.m_target, as, addr, n,
5627c478bd9Sstevel@tonic-gate 			    argv->a_un.a_char);
5637c478bd9Sstevel@tonic-gate 			mdb.m_incr = naddr - addr;
5647c478bd9Sstevel@tonic-gate 			addr = naddr;
5657c478bd9Sstevel@tonic-gate 			n = 1;
5667c478bd9Sstevel@tonic-gate 			break;
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		case MDB_TYPE_IMMEDIATE:
5697c478bd9Sstevel@tonic-gate 			n = argv->a_un.a_val;
5707c478bd9Sstevel@tonic-gate 			break;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 		case MDB_TYPE_STRING:
5737c478bd9Sstevel@tonic-gate 			mdb_iob_puts(mdb.m_out, argv->a_un.a_str);
5747c478bd9Sstevel@tonic-gate 			n = 1;
5757c478bd9Sstevel@tonic-gate 			break;
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 	}
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	mdb.m_incr = addr - oaddr;
5807c478bd9Sstevel@tonic-gate 	mdb_iob_clrflags(mdb.m_out, MDB_IOB_INDENT);
5817c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate static int
print_common(mdb_tgt_as_t as,uint_t flags,int argc,const mdb_arg_t * argv)5857c478bd9Sstevel@tonic-gate print_common(mdb_tgt_as_t as, uint_t flags, int argc, const mdb_arg_t *argv)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate 	mdb_tgt_addr_t addr = mdb_nv_get_value(mdb.m_dot);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	if (argc != 0 && argv->a_type == MDB_TYPE_CHAR) {
5903d580edaSSerapheim Dimitropoulos 		if (strchr("vwzWZ", argv->a_un.a_char))
5917c478bd9Sstevel@tonic-gate 			return (write_arglist(as, addr, argc, argv));
5927c478bd9Sstevel@tonic-gate 		if (strchr("lLM", argv->a_un.a_char))
5937c478bd9Sstevel@tonic-gate 			return (match_arglist(as, flags, addr, argc, argv));
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	return (print_arglist(as, addr, flags, argc, argv));
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6007c478bd9Sstevel@tonic-gate static int
cmd_print_core(uintptr_t x,uint_t flags,int argc,const mdb_arg_t * argv)6017c478bd9Sstevel@tonic-gate cmd_print_core(uintptr_t x, uint_t flags, int argc, const mdb_arg_t *argv)
6027c478bd9Sstevel@tonic-gate {
6037c478bd9Sstevel@tonic-gate 	return (print_common(MDB_TGT_AS_VIRT, flags, argc, argv));
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate #ifndef _KMDB
6077c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6087c478bd9Sstevel@tonic-gate static int
cmd_print_object(uintptr_t x,uint_t flags,int argc,const mdb_arg_t * argv)6097c478bd9Sstevel@tonic-gate cmd_print_object(uintptr_t x, uint_t flags, int argc, const mdb_arg_t *argv)
6107c478bd9Sstevel@tonic-gate {
6117c478bd9Sstevel@tonic-gate 	return (print_common(MDB_TGT_AS_FILE, flags, argc, argv));
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate #endif
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6167c478bd9Sstevel@tonic-gate static int
cmd_print_phys(uintptr_t x,uint_t flags,int argc,const mdb_arg_t * argv)6177c478bd9Sstevel@tonic-gate cmd_print_phys(uintptr_t x, uint_t flags, int argc, const mdb_arg_t *argv)
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate 	return (print_common(MDB_TGT_AS_PHYS, flags, argc, argv));
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6237c478bd9Sstevel@tonic-gate static int
cmd_print_value(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)624bc07d1fdSCody Peter Mello cmd_print_value(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate 	uintmax_t ndot, dot = mdb_get_dot();
6277c478bd9Sstevel@tonic-gate 	const char *tgt_argv[1];
6287c478bd9Sstevel@tonic-gate 	mdb_tgt_t *t;
6297c478bd9Sstevel@tonic-gate 	size_t i, n;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	if (argc == 0) {
6327c478bd9Sstevel@tonic-gate 		mdb_warn("expected one or more format characters "
6337c478bd9Sstevel@tonic-gate 		    "following '='\n");
6347c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
6357c478bd9Sstevel@tonic-gate 	}
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	tgt_argv[0] = (const char *)&dot;
6387c478bd9Sstevel@tonic-gate 	t = mdb_tgt_create(mdb_value_tgt_create, 0, 1, tgt_argv);
6397c478bd9Sstevel@tonic-gate 	mdb_iob_setflags(mdb.m_out, MDB_IOB_INDENT);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	for (i = 0, n = 1; i < argc; i++, argv++) {
6427c478bd9Sstevel@tonic-gate 		switch (argv->a_type) {
6437c478bd9Sstevel@tonic-gate 		case MDB_TYPE_CHAR:
6447c478bd9Sstevel@tonic-gate 			ndot = mdb_fmt_print(t, MDB_TGT_AS_VIRT,
6457c478bd9Sstevel@tonic-gate 			    dot, n, argv->a_un.a_char);
6467c478bd9Sstevel@tonic-gate 			if (argv->a_un.a_char == '+' ||
6477c478bd9Sstevel@tonic-gate 			    argv->a_un.a_char == '-')
6487c478bd9Sstevel@tonic-gate 				dot = ndot;
6497c478bd9Sstevel@tonic-gate 			n = 1;
6507c478bd9Sstevel@tonic-gate 			break;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 		case MDB_TYPE_IMMEDIATE:
6537c478bd9Sstevel@tonic-gate 			n = argv->a_un.a_val;
6547c478bd9Sstevel@tonic-gate 			break;
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 		case MDB_TYPE_STRING:
6577c478bd9Sstevel@tonic-gate 			mdb_iob_puts(mdb.m_out, argv->a_un.a_str);
6587c478bd9Sstevel@tonic-gate 			n = 1;
6597c478bd9Sstevel@tonic-gate 			break;
6607c478bd9Sstevel@tonic-gate 		}
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	mdb_iob_clrflags(mdb.m_out, MDB_IOB_INDENT);
6647c478bd9Sstevel@tonic-gate 	mdb_nv_set_value(mdb.m_dot, dot);
6657c478bd9Sstevel@tonic-gate 	mdb.m_incr = 0;
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	mdb_tgt_destroy(t);
6687c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6727c478bd9Sstevel@tonic-gate static int
cmd_assign_variable(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6737c478bd9Sstevel@tonic-gate cmd_assign_variable(uintptr_t addr, uint_t flags,
6747c478bd9Sstevel@tonic-gate     int argc, const mdb_arg_t *argv)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate 	uintmax_t dot = mdb_nv_get_value(mdb.m_dot);
6777c478bd9Sstevel@tonic-gate 	const char *p;
6787c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	if (argc == 2) {
6817c478bd9Sstevel@tonic-gate 		if (argv->a_type != MDB_TYPE_CHAR) {
6827c478bd9Sstevel@tonic-gate 			mdb_warn("improper arguments following '>' operator\n");
6837c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
6847c478bd9Sstevel@tonic-gate 		}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 		switch (argv->a_un.a_char) {
6877c478bd9Sstevel@tonic-gate 		case 'c':
6887c478bd9Sstevel@tonic-gate 			addr = *((uchar_t *)&addr);
6897c478bd9Sstevel@tonic-gate 			break;
6907c478bd9Sstevel@tonic-gate 		case 's':
6917c478bd9Sstevel@tonic-gate 			addr = *((ushort_t *)&addr);
6927c478bd9Sstevel@tonic-gate 			break;
6937c478bd9Sstevel@tonic-gate 		case 'i':
6947c478bd9Sstevel@tonic-gate 			addr = *((uint_t *)&addr);
6957c478bd9Sstevel@tonic-gate 			break;
6967c478bd9Sstevel@tonic-gate 		case 'l':
6977c478bd9Sstevel@tonic-gate 			addr = *((ulong_t *)&addr);
6987c478bd9Sstevel@tonic-gate 			break;
6997c478bd9Sstevel@tonic-gate 		default:
7007c478bd9Sstevel@tonic-gate 			mdb_warn("%c is not a valid // modifier\n",
7017c478bd9Sstevel@tonic-gate 			    argv->a_un.a_char);
7027c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
7037c478bd9Sstevel@tonic-gate 		}
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 		dot = addr;
7067c478bd9Sstevel@tonic-gate 		argv++;
7077c478bd9Sstevel@tonic-gate 		argc--;
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING) {
7117c478bd9Sstevel@tonic-gate 		mdb_warn("expected single variable name following '>'\n");
7127c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
7137c478bd9Sstevel@tonic-gate 	}
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	if (strlen(argv->a_un.a_str) >= (size_t)MDB_NV_NAMELEN) {
7167c478bd9Sstevel@tonic-gate 		mdb_warn("variable names may not exceed %d characters\n",
7177c478bd9Sstevel@tonic-gate 		    MDB_NV_NAMELEN - 1);
7187c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	if ((p = strbadid(argv->a_un.a_str)) != NULL) {
7227c478bd9Sstevel@tonic-gate 		mdb_warn("'%c' may not be used in a variable name\n", *p);
7237c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
7247c478bd9Sstevel@tonic-gate 	}
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	if ((v = mdb_nv_lookup(&mdb.m_nv, argv->a_un.a_str)) == NULL)
7277c478bd9Sstevel@tonic-gate 		(void) mdb_nv_insert(&mdb.m_nv, argv->a_un.a_str, NULL, dot, 0);
7287c478bd9Sstevel@tonic-gate 	else
7297c478bd9Sstevel@tonic-gate 		mdb_nv_set_value(v, dot);
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	mdb.m_incr = 0;
7327c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate static int
print_soutype(const char * sou,uintptr_t addr,uint_t flags)7367c478bd9Sstevel@tonic-gate print_soutype(const char *sou, uintptr_t addr, uint_t flags)
7377c478bd9Sstevel@tonic-gate {
7387c478bd9Sstevel@tonic-gate 	static const char *prefixes[] = { "struct ", "union " };
7397c478bd9Sstevel@tonic-gate 	size_t namesz = 7 + strlen(sou) + 1;
7407c478bd9Sstevel@tonic-gate 	char *name = mdb_alloc(namesz, UM_SLEEP | UM_GC);
7417c478bd9Sstevel@tonic-gate 	mdb_ctf_id_t id;
7427c478bd9Sstevel@tonic-gate 	int i;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
7457c478bd9Sstevel@tonic-gate 		(void) mdb_snprintf(name, namesz, "%s%s", prefixes[i], sou);
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 		if (mdb_ctf_lookup_by_name(name, &id) == 0) {
7487c478bd9Sstevel@tonic-gate 			mdb_arg_t v;
7497c478bd9Sstevel@tonic-gate 			int rv;
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 			v.a_type = MDB_TYPE_STRING;
7527c478bd9Sstevel@tonic-gate 			v.a_un.a_str = name;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 			rv = mdb_call_dcmd("print", addr, flags, 1, &v);
7557c478bd9Sstevel@tonic-gate 			return (rv);
7567c478bd9Sstevel@tonic-gate 		}
7577c478bd9Sstevel@tonic-gate 	}
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	return (DCMD_ERR);
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate static int
print_type(const char * name,uintptr_t addr,uint_t flags)7637c478bd9Sstevel@tonic-gate print_type(const char *name, uintptr_t addr, uint_t flags)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate 	mdb_ctf_id_t id;
7667c478bd9Sstevel@tonic-gate 	char *sname;
7677c478bd9Sstevel@tonic-gate 	size_t snamesz;
7687c478bd9Sstevel@tonic-gate 	int rv;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
7717c478bd9Sstevel@tonic-gate 		addr = mdb_get_dot();
7727c478bd9Sstevel@tonic-gate 		flags |= DCMD_ADDRSPEC;
7737c478bd9Sstevel@tonic-gate 	}
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	if ((rv = print_soutype(name, addr, flags)) != DCMD_ERR)
7767c478bd9Sstevel@tonic-gate 		return (rv);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	snamesz = strlen(name) + 3;
7797c478bd9Sstevel@tonic-gate 	sname = mdb_zalloc(snamesz, UM_SLEEP | UM_GC);
7807c478bd9Sstevel@tonic-gate 	(void) mdb_snprintf(sname, snamesz, "%s_t", name);
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate 	if (mdb_ctf_lookup_by_name(sname, &id) == 0) {
7837c478bd9Sstevel@tonic-gate 		mdb_arg_t v;
7847c478bd9Sstevel@tonic-gate 		int rv;
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 		v.a_type = MDB_TYPE_STRING;
7877c478bd9Sstevel@tonic-gate 		v.a_un.a_str = sname;
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 		rv = mdb_call_dcmd("print", addr, flags, 1, &v);
7907c478bd9Sstevel@tonic-gate 		return (rv);
7917c478bd9Sstevel@tonic-gate 	}
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	sname[snamesz - 2] = 's';
7947c478bd9Sstevel@tonic-gate 	rv = print_soutype(sname, addr, flags);
7957c478bd9Sstevel@tonic-gate 	return (rv);
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate static int
exec_alias(const char * fname,uintptr_t addr,uint_t flags)7997c478bd9Sstevel@tonic-gate exec_alias(const char *fname, uintptr_t addr, uint_t flags)
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate 	const char *alias;
8027c478bd9Sstevel@tonic-gate 	int rv;
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	if ((alias = mdb_macalias_lookup(fname)) == NULL)
8057c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC) {
8087c478bd9Sstevel@tonic-gate 		size_t sz = sizeof (uintptr_t) * 2 + strlen(alias) + 1;
8097c478bd9Sstevel@tonic-gate 		char *addralias = mdb_alloc(sz, UM_SLEEP | UM_GC);
8107c478bd9Sstevel@tonic-gate 		(void) mdb_snprintf(addralias, sz, "%p%s", addr, alias);
8117c478bd9Sstevel@tonic-gate 		rv = mdb_eval(addralias);
8127c478bd9Sstevel@tonic-gate 	} else {
8137c478bd9Sstevel@tonic-gate 		rv = mdb_eval(alias);
8147c478bd9Sstevel@tonic-gate 	}
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	return (rv == -1 ? DCMD_ABORT : DCMD_OK);
8177c478bd9Sstevel@tonic-gate }
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8207c478bd9Sstevel@tonic-gate static int
cmd_src_file(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8217c478bd9Sstevel@tonic-gate cmd_src_file(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8227c478bd9Sstevel@tonic-gate {
8237c478bd9Sstevel@tonic-gate 	const char *fname;
8247c478bd9Sstevel@tonic-gate 	mdb_io_t *fio;
8257c478bd9Sstevel@tonic-gate 	int rv;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
8287c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	fname = argv->a_un.a_str;
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT) {
8337c478bd9Sstevel@tonic-gate 		mdb_warn("macro files cannot be used as input to a pipeline\n");
8347c478bd9Sstevel@tonic-gate 		return (DCMD_ABORT);
8357c478bd9Sstevel@tonic-gate 	}
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 	if ((fio = mdb_fdio_create_path(mdb.m_ipath, fname,
8387c478bd9Sstevel@tonic-gate 	    O_RDONLY, 0)) != NULL) {
8397c478bd9Sstevel@tonic-gate 		mdb_frame_t *fp = mdb.m_frame;
8407c478bd9Sstevel@tonic-gate 		int err;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 		mdb_iob_stack_push(&fp->f_istk, mdb.m_in, yylineno);
8437c478bd9Sstevel@tonic-gate 		mdb.m_in = mdb_iob_create(fio, MDB_IOB_RDONLY);
8447c478bd9Sstevel@tonic-gate 		err = mdb_run();
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 		ASSERT(fp == mdb.m_frame);
8477c478bd9Sstevel@tonic-gate 		mdb.m_in = mdb_iob_stack_pop(&fp->f_istk);
8487c478bd9Sstevel@tonic-gate 		yylineno = mdb_iob_lineno(mdb.m_in);
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 		if (err == MDB_ERR_PAGER && mdb.m_fmark != fp)
8517c478bd9Sstevel@tonic-gate 			longjmp(fp->f_pcb, err);
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 		if (err == MDB_ERR_QUIT || err == MDB_ERR_ABORT ||
8547c478bd9Sstevel@tonic-gate 		    err == MDB_ERR_SIGINT || err == MDB_ERR_OUTPUT)
8557c478bd9Sstevel@tonic-gate 			longjmp(fp->f_pcb, err);
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
8587c478bd9Sstevel@tonic-gate 	}
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	if ((rv = exec_alias(fname, addr, flags)) != DCMD_ERR ||
8617c478bd9Sstevel@tonic-gate 	    (rv = print_type(fname, addr, flags)) != DCMD_ERR)
8627c478bd9Sstevel@tonic-gate 		return (rv);
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	mdb_warn("failed to open %s (see ::help '$<')\n", fname);
8657c478bd9Sstevel@tonic-gate 	return (DCMD_ABORT);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate static int
cmd_exec_file(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)8697c478bd9Sstevel@tonic-gate cmd_exec_file(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
8707c478bd9Sstevel@tonic-gate {
8717c478bd9Sstevel@tonic-gate 	const char *fname;
8727c478bd9Sstevel@tonic-gate 	mdb_io_t *fio;
8737c478bd9Sstevel@tonic-gate 	int rv;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	/*
8767c478bd9Sstevel@tonic-gate 	 * The syntax [expr[,count]]$< with no trailing macro file name is
8777c478bd9Sstevel@tonic-gate 	 * magic in that if count is zero, this command won't be called and
8787c478bd9Sstevel@tonic-gate 	 * the expression is thus a no-op.  If count is non-zero, we get
8797c478bd9Sstevel@tonic-gate 	 * invoked with argc == 0, and this means abort the current macro.
8807c478bd9Sstevel@tonic-gate 	 * If our debugger stack depth is greater than one, we may be using
8817c478bd9Sstevel@tonic-gate 	 * $< from within a previous $<<, so in that case we set m_in to
8827c478bd9Sstevel@tonic-gate 	 * NULL to force this entire frame to be popped.
8837c478bd9Sstevel@tonic-gate 	 */
8847c478bd9Sstevel@tonic-gate 	if (argc == 0) {
8857c478bd9Sstevel@tonic-gate 		if (mdb_iob_stack_size(&mdb.m_frame->f_istk) != 0) {
8867c478bd9Sstevel@tonic-gate 			mdb_iob_destroy(mdb.m_in);
8877c478bd9Sstevel@tonic-gate 			mdb.m_in = mdb_iob_stack_pop(&mdb.m_frame->f_istk);
8887c478bd9Sstevel@tonic-gate 		} else if (mdb.m_depth > 1) {
8897c478bd9Sstevel@tonic-gate 			mdb_iob_destroy(mdb.m_in);
8907c478bd9Sstevel@tonic-gate 			mdb.m_in = NULL;
8917c478bd9Sstevel@tonic-gate 		} else
8927c478bd9Sstevel@tonic-gate 			mdb_warn("input stack is empty\n");
8937c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
8947c478bd9Sstevel@tonic-gate 	}
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	if ((flags & (DCMD_PIPE | DCMD_PIPE_OUT)) || mdb.m_depth == 1)
8977c478bd9Sstevel@tonic-gate 		return (cmd_src_file(addr, flags, argc, argv));
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
9007c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	fname = argv->a_un.a_str;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	if ((fio = mdb_fdio_create_path(mdb.m_ipath, fname,
9057c478bd9Sstevel@tonic-gate 	    O_RDONLY, 0)) != NULL) {
9067c478bd9Sstevel@tonic-gate 		mdb_iob_destroy(mdb.m_in);
9077c478bd9Sstevel@tonic-gate 		mdb.m_in = mdb_iob_create(fio, MDB_IOB_RDONLY);
9087c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
9097c478bd9Sstevel@tonic-gate 	}
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	if ((rv = exec_alias(fname, addr, flags)) != DCMD_ERR ||
9127c478bd9Sstevel@tonic-gate 	    (rv = print_type(fname, addr, flags)) != DCMD_ERR)
9137c478bd9Sstevel@tonic-gate 		return (rv);
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 	mdb_warn("failed to open %s (see ::help '$<')\n", fname);
9167c478bd9Sstevel@tonic-gate 	return (DCMD_ABORT);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate #ifndef _KMDB
9207c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9217c478bd9Sstevel@tonic-gate static int
cmd_cat(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)9227c478bd9Sstevel@tonic-gate cmd_cat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
9237c478bd9Sstevel@tonic-gate {
9247c478bd9Sstevel@tonic-gate 	int status = DCMD_OK;
9257c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];
9267c478bd9Sstevel@tonic-gate 	mdb_iob_t *iob;
9277c478bd9Sstevel@tonic-gate 	mdb_io_t *fio;
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
9307c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 	for (; argc-- != 0; argv++) {
9337c478bd9Sstevel@tonic-gate 		if (argv->a_type != MDB_TYPE_STRING) {
9347c478bd9Sstevel@tonic-gate 			mdb_warn("expected string argument\n");
9357c478bd9Sstevel@tonic-gate 			status = DCMD_ERR;
9367c478bd9Sstevel@tonic-gate 			continue;
9377c478bd9Sstevel@tonic-gate 		}
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 		if ((fio = mdb_fdio_create_path(NULL,
9407c478bd9Sstevel@tonic-gate 		    argv->a_un.a_str, O_RDONLY, 0)) == NULL) {
9417c478bd9Sstevel@tonic-gate 			mdb_warn("failed to open %s", argv->a_un.a_str);
9427c478bd9Sstevel@tonic-gate 			status = DCMD_ERR;
9437c478bd9Sstevel@tonic-gate 			continue;
9447c478bd9Sstevel@tonic-gate 		}
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 		iob = mdb_iob_create(fio, MDB_IOB_RDONLY);
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 		while (!(mdb_iob_getflags(iob) & (MDB_IOB_EOF | MDB_IOB_ERR))) {
9497c478bd9Sstevel@tonic-gate 			ssize_t len = mdb_iob_read(iob, buf, sizeof (buf));
9507c478bd9Sstevel@tonic-gate 			if (len > 0) {
9517c478bd9Sstevel@tonic-gate 				if (mdb_iob_write(mdb.m_out, buf, len) < 0) {
9527c478bd9Sstevel@tonic-gate 					if (errno != EPIPE)
9537c478bd9Sstevel@tonic-gate 						mdb_warn("write failed");
9547c478bd9Sstevel@tonic-gate 					status = DCMD_ERR;
9557c478bd9Sstevel@tonic-gate 					break;
9567c478bd9Sstevel@tonic-gate 				}
9577c478bd9Sstevel@tonic-gate 			}
9587c478bd9Sstevel@tonic-gate 		}
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 		if (mdb_iob_err(iob))
9617c478bd9Sstevel@tonic-gate 			mdb_warn("error while reading %s", mdb_iob_name(iob));
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 		mdb_iob_destroy(iob);
9647c478bd9Sstevel@tonic-gate 	}
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	return (status);
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate #endif
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9717c478bd9Sstevel@tonic-gate static int
cmd_grep(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)9727c478bd9Sstevel@tonic-gate cmd_grep(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
9737c478bd9Sstevel@tonic-gate {
9747c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
9757c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	if (mdb_eval(argv->a_un.a_str) == -1)
9787c478bd9Sstevel@tonic-gate 		return (DCMD_ABORT);
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	if (mdb_get_dot() != 0)
9817c478bd9Sstevel@tonic-gate 		mdb_printf("%lr\n", addr);
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9877c478bd9Sstevel@tonic-gate static int
cmd_map(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)9887c478bd9Sstevel@tonic-gate cmd_map(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
9897c478bd9Sstevel@tonic-gate {
9907c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
9917c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	if (mdb_eval(argv->a_un.a_str) == -1)
9947c478bd9Sstevel@tonic-gate 		return (DCMD_ABORT);
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	mdb_printf("%llr\n", mdb_get_dot());
9977c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10017c478bd9Sstevel@tonic-gate static int
cmd_notsup(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10027c478bd9Sstevel@tonic-gate cmd_notsup(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10037c478bd9Sstevel@tonic-gate {
10047c478bd9Sstevel@tonic-gate 	mdb_warn("command is not supported by current target\n");
10057c478bd9Sstevel@tonic-gate 	return (DCMD_ERR);
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10097c478bd9Sstevel@tonic-gate static int
cmd_quit(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10107c478bd9Sstevel@tonic-gate cmd_quit(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10117c478bd9Sstevel@tonic-gate {
10127c478bd9Sstevel@tonic-gate #ifdef _KMDB
10137c478bd9Sstevel@tonic-gate 	uint_t opt_u = FALSE;
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
10167c478bd9Sstevel@tonic-gate 	    'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc)
10177c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	if (opt_u) {
10207c478bd9Sstevel@tonic-gate 		if (mdb.m_flags & MDB_FL_NOUNLOAD) {
10217c478bd9Sstevel@tonic-gate 			warn("%s\n", mdb_strerror(EMDB_KNOUNLOAD));
10227c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
10237c478bd9Sstevel@tonic-gate 		}
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 		kmdb_kdi_set_unload_request();
10267c478bd9Sstevel@tonic-gate 	}
10277c478bd9Sstevel@tonic-gate #endif
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	longjmp(mdb.m_frame->f_pcb, MDB_ERR_QUIT);
10307c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
10317c478bd9Sstevel@tonic-gate 	return (DCMD_ERR);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate #ifdef _KMDB
10357c478bd9Sstevel@tonic-gate static void
quit_help(void)10367c478bd9Sstevel@tonic-gate quit_help(void)
10377c478bd9Sstevel@tonic-gate {
10387c478bd9Sstevel@tonic-gate 	mdb_printf(
10397c478bd9Sstevel@tonic-gate 	    "-u    unload the debugger (if not loaded at boot)\n");
10407c478bd9Sstevel@tonic-gate }
10417c478bd9Sstevel@tonic-gate #endif
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10447c478bd9Sstevel@tonic-gate static int
cmd_vars(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10457c478bd9Sstevel@tonic-gate cmd_vars(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10467c478bd9Sstevel@tonic-gate {
10477c478bd9Sstevel@tonic-gate 	uint_t opt_nz = FALSE, opt_tag = FALSE, opt_prt = FALSE;
10487c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
10517c478bd9Sstevel@tonic-gate 	    'n', MDB_OPT_SETBITS, TRUE, &opt_nz,
10527c478bd9Sstevel@tonic-gate 	    'p', MDB_OPT_SETBITS, TRUE, &opt_prt,
10537c478bd9Sstevel@tonic-gate 	    't', MDB_OPT_SETBITS, TRUE, &opt_tag, NULL) != argc)
10547c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 	mdb_nv_rewind(&mdb.m_nv);
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	while ((v = mdb_nv_advance(&mdb.m_nv)) != NULL) {
10597c478bd9Sstevel@tonic-gate 		if ((opt_tag == FALSE || (v->v_flags & MDB_NV_TAGGED)) &&
10607c478bd9Sstevel@tonic-gate 		    (opt_nz == FALSE || mdb_nv_get_value(v) != 0)) {
10617c478bd9Sstevel@tonic-gate 			if (opt_prt) {
10627c478bd9Sstevel@tonic-gate 				mdb_printf("%#llr>%s\n",
10637c478bd9Sstevel@tonic-gate 				    mdb_nv_get_value(v), mdb_nv_get_name(v));
10647c478bd9Sstevel@tonic-gate 			} else {
10657c478bd9Sstevel@tonic-gate 				mdb_printf("%s = %llr\n",
10667c478bd9Sstevel@tonic-gate 				    mdb_nv_get_name(v), mdb_nv_get_value(v));
10677c478bd9Sstevel@tonic-gate 			}
10687c478bd9Sstevel@tonic-gate 		}
10697c478bd9Sstevel@tonic-gate 	}
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
10727c478bd9Sstevel@tonic-gate }
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10757c478bd9Sstevel@tonic-gate static int
cmd_nzvars(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10767c478bd9Sstevel@tonic-gate cmd_nzvars(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10777c478bd9Sstevel@tonic-gate {
10787c478bd9Sstevel@tonic-gate 	uintmax_t value;
10797c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	if (argc != 0)
10827c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	mdb_nv_rewind(&mdb.m_nv);
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	while ((v = mdb_nv_advance(&mdb.m_nv)) != NULL) {
10877c478bd9Sstevel@tonic-gate 		if ((value = mdb_nv_get_value(v)) != 0)
10887c478bd9Sstevel@tonic-gate 			mdb_printf("%s = %llr\n", mdb_nv_get_name(v), value);
10897c478bd9Sstevel@tonic-gate 	}
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10957c478bd9Sstevel@tonic-gate static int
cmd_radix(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10967c478bd9Sstevel@tonic-gate cmd_radix(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate 	if (argc != 0)
10997c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC) {
11027c478bd9Sstevel@tonic-gate 		if (addr < 2 || addr > 16) {
11037c478bd9Sstevel@tonic-gate 			mdb_warn("expected radix from 2 to 16\n");
11047c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
11057c478bd9Sstevel@tonic-gate 		}
11067c478bd9Sstevel@tonic-gate 		mdb.m_radix = (int)addr;
11077c478bd9Sstevel@tonic-gate 	}
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	mdb_iob_printf(mdb.m_out, "radix = %d base ten\n", mdb.m_radix);
11107c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
11117c478bd9Sstevel@tonic-gate }
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11147c478bd9Sstevel@tonic-gate static int
cmd_symdist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11157c478bd9Sstevel@tonic-gate cmd_symdist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11167c478bd9Sstevel@tonic-gate {
11177c478bd9Sstevel@tonic-gate 	if (argc != 0)
11187c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
11217c478bd9Sstevel@tonic-gate 		mdb.m_symdist = addr;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	mdb_printf("symbol matching distance = %lr (%s)\n",
11247c478bd9Sstevel@tonic-gate 	    mdb.m_symdist, mdb.m_symdist ? "absolute mode" : "smart mode");
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11307c478bd9Sstevel@tonic-gate static int
cmd_pgwidth(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11317c478bd9Sstevel@tonic-gate cmd_pgwidth(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11327c478bd9Sstevel@tonic-gate {
11337c478bd9Sstevel@tonic-gate 	if (argc != 0)
11347c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
11377c478bd9Sstevel@tonic-gate 		mdb_iob_resize(mdb.m_out, mdb.m_out->iob_rows, addr);
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	mdb_printf("output page width = %lu\n", mdb.m_out->iob_cols);
11407c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11447c478bd9Sstevel@tonic-gate static int
cmd_reopen(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11457c478bd9Sstevel@tonic-gate cmd_reopen(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11467c478bd9Sstevel@tonic-gate {
11477c478bd9Sstevel@tonic-gate 	if (argc != 0)
11487c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 	if (mdb_tgt_setflags(mdb.m_target, MDB_TGT_F_RDWR) == -1) {
11517c478bd9Sstevel@tonic-gate 		mdb_warn("failed to re-open target for writing");
11527c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
11537c478bd9Sstevel@tonic-gate 	}
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11597c478bd9Sstevel@tonic-gate static int
print_xdata(void * ignored,const char * name,const char * desc,size_t nbytes)11607c478bd9Sstevel@tonic-gate print_xdata(void *ignored, const char *name, const char *desc, size_t nbytes)
11617c478bd9Sstevel@tonic-gate {
11627c478bd9Sstevel@tonic-gate 	mdb_printf("%-24s - %s (%lu bytes)\n", name, desc, (ulong_t)nbytes);
11637c478bd9Sstevel@tonic-gate 	return (0);
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11677c478bd9Sstevel@tonic-gate static int
cmd_xdata(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11687c478bd9Sstevel@tonic-gate cmd_xdata(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11697c478bd9Sstevel@tonic-gate {
11707c478bd9Sstevel@tonic-gate 	if (argc != 0 || (flags & DCMD_ADDRSPEC))
11717c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_xdata_iter(mdb.m_target, print_xdata, NULL);
11747c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
11757c478bd9Sstevel@tonic-gate }
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11787c478bd9Sstevel@tonic-gate static int
cmd_unset(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)11797c478bd9Sstevel@tonic-gate cmd_unset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
11807c478bd9Sstevel@tonic-gate {
11817c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
11827c478bd9Sstevel@tonic-gate 	size_t i;
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++) {
11857c478bd9Sstevel@tonic-gate 		if (argv[i].a_type != MDB_TYPE_STRING) {
11867c478bd9Sstevel@tonic-gate 			mdb_warn("bad option: arg %lu is not a string\n",
11877c478bd9Sstevel@tonic-gate 			    (ulong_t)i + 1);
11887c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
11897c478bd9Sstevel@tonic-gate 		}
11907c478bd9Sstevel@tonic-gate 	}
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++, argv++) {
11937c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&mdb.m_nv, argv->a_un.a_str)) == NULL)
11947c478bd9Sstevel@tonic-gate 			mdb_warn("variable '%s' not defined\n",
11957c478bd9Sstevel@tonic-gate 			    argv->a_un.a_str);
11967c478bd9Sstevel@tonic-gate 		else
11977c478bd9Sstevel@tonic-gate 			mdb_nv_remove(&mdb.m_nv, v);
11987c478bd9Sstevel@tonic-gate 	}
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
12017c478bd9Sstevel@tonic-gate }
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate #ifndef _KMDB
12047c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12057c478bd9Sstevel@tonic-gate static int
cmd_log(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)12067c478bd9Sstevel@tonic-gate cmd_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
12077c478bd9Sstevel@tonic-gate {
12087c478bd9Sstevel@tonic-gate 	uint_t opt_e = FALSE, opt_d = FALSE;
12097c478bd9Sstevel@tonic-gate 	const char *filename = NULL;
12107c478bd9Sstevel@tonic-gate 	int i;
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	i = mdb_getopts(argc, argv,
12137c478bd9Sstevel@tonic-gate 	    'd', MDB_OPT_SETBITS, TRUE, &opt_d,
12147c478bd9Sstevel@tonic-gate 	    'e', MDB_OPT_SETBITS, TRUE, &opt_e, NULL);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	if ((i != argc && i != argc - 1) || (opt_d && opt_e) ||
12177c478bd9Sstevel@tonic-gate 	    (i != argc && argv[i].a_type != MDB_TYPE_STRING) ||
12187c478bd9Sstevel@tonic-gate 	    (i != argc && opt_d == TRUE) || (flags & DCMD_ADDRSPEC))
12197c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	if (mdb.m_depth != 1) {
12227c478bd9Sstevel@tonic-gate 		mdb_warn("log may not be manipulated in this context\n");
12237c478bd9Sstevel@tonic-gate 		return (DCMD_ABORT);
12247c478bd9Sstevel@tonic-gate 	}
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 	if (i != argc)
12277c478bd9Sstevel@tonic-gate 		filename = argv[i].a_un.a_str;
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	/*
12307c478bd9Sstevel@tonic-gate 	 * If no arguments were specified, print the log file name (if any)
12317c478bd9Sstevel@tonic-gate 	 * and report whether the log is enabled or disabled.
12327c478bd9Sstevel@tonic-gate 	 */
12337c478bd9Sstevel@tonic-gate 	if (argc == 0) {
12347c478bd9Sstevel@tonic-gate 		if (mdb.m_log) {
12357c478bd9Sstevel@tonic-gate 			mdb_printf("%s: logging to \"%s\" is currently %s\n",
12367c478bd9Sstevel@tonic-gate 			    mdb.m_pname, IOP_NAME(mdb.m_log),
12377c478bd9Sstevel@tonic-gate 			    mdb.m_flags & MDB_FL_LOG ?  "enabled" : "disabled");
12387c478bd9Sstevel@tonic-gate 		} else
12397c478bd9Sstevel@tonic-gate 			mdb_printf("%s: no log is active\n", mdb.m_pname);
12407c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
12417c478bd9Sstevel@tonic-gate 	}
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 	/*
12447c478bd9Sstevel@tonic-gate 	 * If the -d option was specified, pop the log i/o object off the
12457c478bd9Sstevel@tonic-gate 	 * i/o stack of stdin, stdout, and stderr.
12467c478bd9Sstevel@tonic-gate 	 */
12477c478bd9Sstevel@tonic-gate 	if (opt_d) {
12487c478bd9Sstevel@tonic-gate 		if (mdb.m_flags & MDB_FL_LOG) {
12497c478bd9Sstevel@tonic-gate 			(void) mdb_iob_pop_io(mdb.m_in);
12507c478bd9Sstevel@tonic-gate 			(void) mdb_iob_pop_io(mdb.m_out);
12517c478bd9Sstevel@tonic-gate 			(void) mdb_iob_pop_io(mdb.m_err);
12527c478bd9Sstevel@tonic-gate 			mdb.m_flags &= ~MDB_FL_LOG;
12537c478bd9Sstevel@tonic-gate 		} else
12547c478bd9Sstevel@tonic-gate 			mdb_warn("logging is already disabled\n");
12557c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
12567c478bd9Sstevel@tonic-gate 	}
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	/*
12597c478bd9Sstevel@tonic-gate 	 * The -e option is the default: (re-)enable logging by pushing
12607c478bd9Sstevel@tonic-gate 	 * the log i/o object on to stdin, stdout, and stderr.  If we have
12617c478bd9Sstevel@tonic-gate 	 * a previous log file, we need to pop it and close it.  If we have
12627c478bd9Sstevel@tonic-gate 	 * no new log file, push the previous one back on.
12637c478bd9Sstevel@tonic-gate 	 */
12647c478bd9Sstevel@tonic-gate 	if (filename != NULL) {
12657c478bd9Sstevel@tonic-gate 		if (mdb.m_log != NULL) {
12667c478bd9Sstevel@tonic-gate 			if (mdb.m_flags & MDB_FL_LOG) {
12677c478bd9Sstevel@tonic-gate 				(void) mdb_iob_pop_io(mdb.m_in);
12687c478bd9Sstevel@tonic-gate 				(void) mdb_iob_pop_io(mdb.m_out);
12697c478bd9Sstevel@tonic-gate 				(void) mdb_iob_pop_io(mdb.m_err);
12707c478bd9Sstevel@tonic-gate 				mdb.m_flags &= ~MDB_FL_LOG;
12717c478bd9Sstevel@tonic-gate 			}
12727c478bd9Sstevel@tonic-gate 			mdb_io_rele(mdb.m_log);
12737c478bd9Sstevel@tonic-gate 		}
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 		mdb.m_log = mdb_fdio_create_path(NULL, filename,
12767c478bd9Sstevel@tonic-gate 		    O_CREAT | O_APPEND | O_WRONLY, 0666);
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 		if (mdb.m_log == NULL) {
12797c478bd9Sstevel@tonic-gate 			mdb_warn("failed to open %s", filename);
12807c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
12817c478bd9Sstevel@tonic-gate 		}
12827c478bd9Sstevel@tonic-gate 	}
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	if (mdb.m_log != NULL) {
12857c478bd9Sstevel@tonic-gate 		mdb_iob_push_io(mdb.m_in, mdb_logio_create(mdb.m_log));
12867c478bd9Sstevel@tonic-gate 		mdb_iob_push_io(mdb.m_out, mdb_logio_create(mdb.m_log));
12877c478bd9Sstevel@tonic-gate 		mdb_iob_push_io(mdb.m_err, mdb_logio_create(mdb.m_log));
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 		mdb_printf("%s: logging to \"%s\"\n", mdb.m_pname, filename);
12907c478bd9Sstevel@tonic-gate 		mdb.m_log = mdb_io_hold(mdb.m_log);
12917c478bd9Sstevel@tonic-gate 		mdb.m_flags |= MDB_FL_LOG;
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
12947c478bd9Sstevel@tonic-gate 	}
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	mdb_warn("no log file has been selected\n");
12977c478bd9Sstevel@tonic-gate 	return (DCMD_ERR);
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate static int
cmd_old_log(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)13017c478bd9Sstevel@tonic-gate cmd_old_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
13027c478bd9Sstevel@tonic-gate {
13037c478bd9Sstevel@tonic-gate 	if (argc == 0) {
13047c478bd9Sstevel@tonic-gate 		mdb_arg_t arg = { MDB_TYPE_STRING, MDB_INIT_STRING("-d") };
13057c478bd9Sstevel@tonic-gate 		return (cmd_log(addr, flags, 1, &arg));
13067c478bd9Sstevel@tonic-gate 	}
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 	return (cmd_log(addr, flags, argc, argv));
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate #endif
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13137c478bd9Sstevel@tonic-gate static int
cmd_load(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)13147c478bd9Sstevel@tonic-gate cmd_load(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
13157c478bd9Sstevel@tonic-gate {
13167c478bd9Sstevel@tonic-gate 	int i, mode = MDB_MOD_LOCAL;
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 	i = mdb_getopts(argc, argv,
13197c478bd9Sstevel@tonic-gate #ifdef _KMDB
13207c478bd9Sstevel@tonic-gate 	    'd', MDB_OPT_SETBITS, MDB_MOD_DEFER, &mode,
13217c478bd9Sstevel@tonic-gate #endif
13227c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, MDB_MOD_FORCE, &mode,
13237c478bd9Sstevel@tonic-gate 	    'g', MDB_OPT_SETBITS, MDB_MOD_GLOBAL, &mode,
13247c478bd9Sstevel@tonic-gate 	    's', MDB_OPT_SETBITS, MDB_MOD_SILENT, &mode,
13257c478bd9Sstevel@tonic-gate 	    NULL);
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	argc -= i;
13287c478bd9Sstevel@tonic-gate 	argv += i;
13297c478bd9Sstevel@tonic-gate 
13307c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || argc != 1 ||
13317c478bd9Sstevel@tonic-gate 	    argv->a_type != MDB_TYPE_STRING ||
13327c478bd9Sstevel@tonic-gate 	    strchr("+-", argv->a_un.a_str[0]) != NULL)
13337c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 	if (mdb_module_load(argv->a_un.a_str, mode) < 0)
13367c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
13397c478bd9Sstevel@tonic-gate }
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate static void
load_help(void)13427c478bd9Sstevel@tonic-gate load_help(void)
13437c478bd9Sstevel@tonic-gate {
13447c478bd9Sstevel@tonic-gate 	mdb_printf(
13457c478bd9Sstevel@tonic-gate #ifdef _KMDB
13467c478bd9Sstevel@tonic-gate 	    "-d    defer load until next continue\n"
13477c478bd9Sstevel@tonic-gate #endif
13487c478bd9Sstevel@tonic-gate 	    "-s    load module silently\n");
13497c478bd9Sstevel@tonic-gate }
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13527c478bd9Sstevel@tonic-gate static int
cmd_unload(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)13537c478bd9Sstevel@tonic-gate cmd_unload(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
13547c478bd9Sstevel@tonic-gate {
13557c478bd9Sstevel@tonic-gate 	int mode = 0;
13567c478bd9Sstevel@tonic-gate 	int i;
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate 	i = mdb_getopts(argc, argv,
13597c478bd9Sstevel@tonic-gate #ifdef _KMDB
13607c478bd9Sstevel@tonic-gate 	    'd', MDB_OPT_SETBITS, MDB_MOD_DEFER, &mode,
13617c478bd9Sstevel@tonic-gate #endif
13627c478bd9Sstevel@tonic-gate 	    NULL);
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 	argc -= i;
13657c478bd9Sstevel@tonic-gate 	argv += i;
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
13687c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	if (mdb_module_unload(argv->a_un.a_str, mode) == -1) {
13717c478bd9Sstevel@tonic-gate 		mdb_warn("failed to unload %s", argv->a_un.a_str);
13727c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
13737c478bd9Sstevel@tonic-gate 	}
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate #ifdef _KMDB
13797c478bd9Sstevel@tonic-gate static void
unload_help(void)13807c478bd9Sstevel@tonic-gate unload_help(void)
13817c478bd9Sstevel@tonic-gate {
13827c478bd9Sstevel@tonic-gate 	mdb_printf(
13837c478bd9Sstevel@tonic-gate 	    "-d    defer unload until next continue\n");
13847c478bd9Sstevel@tonic-gate }
13857c478bd9Sstevel@tonic-gate #endif
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate static int
cmd_dbmode(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)13887c478bd9Sstevel@tonic-gate cmd_dbmode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
13897c478bd9Sstevel@tonic-gate {
13907c478bd9Sstevel@tonic-gate 	if (argc > 1 || (argc != 0 && (flags & DCMD_ADDRSPEC)))
13917c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 	if (argc != 0) {
13947c478bd9Sstevel@tonic-gate 		if (argv->a_type != MDB_TYPE_STRING)
13957c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
13967c478bd9Sstevel@tonic-gate 		if ((addr = mdb_dstr2mode(argv->a_un.a_str)) != MDB_DBG_HELP)
13977c478bd9Sstevel@tonic-gate 			mdb_dmode(addr);
13987c478bd9Sstevel@tonic-gate 	} else if (flags & DCMD_ADDRSPEC)
13997c478bd9Sstevel@tonic-gate 		mdb_dmode(addr);
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 	mdb_printf("debugging mode = 0x%04x\n", mdb.m_debug);
14027c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
14037c478bd9Sstevel@tonic-gate }
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14067c478bd9Sstevel@tonic-gate static int
cmd_version(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14077c478bd9Sstevel@tonic-gate cmd_version(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14087c478bd9Sstevel@tonic-gate {
14097c478bd9Sstevel@tonic-gate #ifdef DEBUG
14107c478bd9Sstevel@tonic-gate 	mdb_printf("\r%s (DEBUG)\n", mdb_conf_version());
14117c478bd9Sstevel@tonic-gate #else
14127c478bd9Sstevel@tonic-gate 	mdb_printf("\r%s\n", mdb_conf_version());
14137c478bd9Sstevel@tonic-gate #endif
14147c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
14157c478bd9Sstevel@tonic-gate }
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14187c478bd9Sstevel@tonic-gate static int
cmd_algol(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14197c478bd9Sstevel@tonic-gate cmd_algol(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14207c478bd9Sstevel@tonic-gate {
14217c478bd9Sstevel@tonic-gate 	if (mdb.m_flags & MDB_FL_ADB)
14227c478bd9Sstevel@tonic-gate 		mdb_printf("No algol 68 here\n");
14237c478bd9Sstevel@tonic-gate 	else
14247c478bd9Sstevel@tonic-gate 		mdb_printf("No adb here\n");
14257c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
14267c478bd9Sstevel@tonic-gate }
14277c478bd9Sstevel@tonic-gate 
14287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14297c478bd9Sstevel@tonic-gate static int
cmd_obey(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14307c478bd9Sstevel@tonic-gate cmd_obey(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14317c478bd9Sstevel@tonic-gate {
14327c478bd9Sstevel@tonic-gate 	if (mdb.m_flags & MDB_FL_ADB)
14337c478bd9Sstevel@tonic-gate 		mdb_printf("CHAPTER 1\n");
14347c478bd9Sstevel@tonic-gate 	else
14357c478bd9Sstevel@tonic-gate 		mdb_printf("No Language H here\n");
14367c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14407c478bd9Sstevel@tonic-gate static int
print_global(void * data,const GElf_Sym * sym,const char * name,const mdb_syminfo_t * sip,const char * obj)14417c478bd9Sstevel@tonic-gate print_global(void *data, const GElf_Sym *sym, const char *name,
14427c478bd9Sstevel@tonic-gate     const mdb_syminfo_t *sip, const char *obj)
14437c478bd9Sstevel@tonic-gate {
14447c478bd9Sstevel@tonic-gate 	uintptr_t value;
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 	if (mdb_tgt_vread((mdb_tgt_t *)data, &value, sizeof (value),
14477c478bd9Sstevel@tonic-gate 	    (uintptr_t)sym->st_value) == sizeof (value))
14487c478bd9Sstevel@tonic-gate 		mdb_printf("%s(%llr):\t%lr\n", name, sym->st_value, value);
14497c478bd9Sstevel@tonic-gate 	else
14507c478bd9Sstevel@tonic-gate 		mdb_printf("%s(%llr):\t?\n", name, sym->st_value);
14517c478bd9Sstevel@tonic-gate 
14527c478bd9Sstevel@tonic-gate 	return (0);
14537c478bd9Sstevel@tonic-gate }
14547c478bd9Sstevel@tonic-gate 
14557c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14567c478bd9Sstevel@tonic-gate static int
cmd_globals(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14577c478bd9Sstevel@tonic-gate cmd_globals(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14587c478bd9Sstevel@tonic-gate {
14597c478bd9Sstevel@tonic-gate 	if (argc != 0)
14607c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_symbol_iter(mdb.m_target, MDB_TGT_OBJ_EVERY,
14637c478bd9Sstevel@tonic-gate 	    MDB_TGT_SYMTAB, MDB_TGT_BIND_GLOBAL | MDB_TGT_TYPE_OBJECT |
14647c478bd9Sstevel@tonic-gate 	    MDB_TGT_TYPE_FUNC, print_global, mdb.m_target);
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	return (0);
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14707c478bd9Sstevel@tonic-gate static int
cmd_eval(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14717c478bd9Sstevel@tonic-gate cmd_eval(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14727c478bd9Sstevel@tonic-gate {
14737c478bd9Sstevel@tonic-gate 	if (argc != 1 || argv->a_type != MDB_TYPE_STRING)
14747c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 	if (mdb_eval(argv->a_un.a_str) == -1)
14777c478bd9Sstevel@tonic-gate 		return (DCMD_ABORT);
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14837c478bd9Sstevel@tonic-gate static int
print_file(void * data,const GElf_Sym * sym,const char * name,const mdb_syminfo_t * sip,const char * obj)14847c478bd9Sstevel@tonic-gate print_file(void *data, const GElf_Sym *sym, const char *name,
14857c478bd9Sstevel@tonic-gate     const mdb_syminfo_t *sip, const char *obj)
14867c478bd9Sstevel@tonic-gate {
14877c478bd9Sstevel@tonic-gate 	int i = *((int *)data);
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	mdb_printf("%d\t%s\n", i++, name);
14907c478bd9Sstevel@tonic-gate 	*((int *)data) = i;
14917c478bd9Sstevel@tonic-gate 	return (0);
14927c478bd9Sstevel@tonic-gate }
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14957c478bd9Sstevel@tonic-gate static int
cmd_files(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)14967c478bd9Sstevel@tonic-gate cmd_files(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
14977c478bd9Sstevel@tonic-gate {
14987c478bd9Sstevel@tonic-gate 	int i = 1;
14997c478bd9Sstevel@tonic-gate 	const char *obj = MDB_TGT_OBJ_EVERY;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || argc > 1)
15027c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 	if (argc == 1) {
15057c478bd9Sstevel@tonic-gate 		if (argv->a_type != MDB_TYPE_STRING)
15067c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 		obj = argv->a_un.a_str;
15097c478bd9Sstevel@tonic-gate 	}
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_symbol_iter(mdb.m_target, obj, MDB_TGT_SYMTAB,
15127c478bd9Sstevel@tonic-gate 	    MDB_TGT_BIND_ANY | MDB_TGT_TYPE_FILE, print_file, &i);
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
15157c478bd9Sstevel@tonic-gate }
15167c478bd9Sstevel@tonic-gate 
15174a1c2431SJonathan Adams static const char *
map_name(const mdb_map_t * map,const char * name)15184a1c2431SJonathan Adams map_name(const mdb_map_t *map, const char *name)
15194a1c2431SJonathan Adams {
15204a1c2431SJonathan Adams 	if (map->map_flags & MDB_TGT_MAP_HEAP)
15214a1c2431SJonathan Adams 		return ("[ heap ]");
15224a1c2431SJonathan Adams 	if (name != NULL && name[0] != 0)
15234a1c2431SJonathan Adams 		return (name);
15244a1c2431SJonathan Adams 
15254a1c2431SJonathan Adams 	if (map->map_flags & MDB_TGT_MAP_SHMEM)
15264a1c2431SJonathan Adams 		return ("[ shmem ]");
15274a1c2431SJonathan Adams 	if (map->map_flags & MDB_TGT_MAP_STACK)
15284a1c2431SJonathan Adams 		return ("[ stack ]");
15294a1c2431SJonathan Adams 	if (map->map_flags & MDB_TGT_MAP_ANON)
15304a1c2431SJonathan Adams 		return ("[ anon ]");
1531d75f3745SJohn Levon 	if (map->map_name[0] == '\0')
1532d75f3745SJohn Levon 		return ("[ unknown ]");
1533d75f3745SJohn Levon 	return (map->map_name);
15344a1c2431SJonathan Adams }
15354a1c2431SJonathan Adams 
15367c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15377c478bd9Sstevel@tonic-gate static int
print_map(void * ignored,const mdb_map_t * map,const char * name)15387c478bd9Sstevel@tonic-gate print_map(void *ignored, const mdb_map_t *map, const char *name)
15397c478bd9Sstevel@tonic-gate {
15404a1c2431SJonathan Adams 	name = map_name(map, name);
15417c478bd9Sstevel@tonic-gate 
15424a1c2431SJonathan Adams 	mdb_printf("%?p %?p %?lx %s\n", map->map_base,
15434a1c2431SJonathan Adams 	    map->map_base + map->map_size, map->map_size, name);
15447c478bd9Sstevel@tonic-gate 	return (0);
15457c478bd9Sstevel@tonic-gate }
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate static int
cmd_mappings(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)15487c478bd9Sstevel@tonic-gate cmd_mappings(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
15497c478bd9Sstevel@tonic-gate {
15507c478bd9Sstevel@tonic-gate 	const mdb_map_t *m;
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 	if (argc > 1 || (argc != 0 && (flags & DCMD_ADDRSPEC)))
15537c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 	mdb_printf("%<u>%?s %?s %?s %s%</u>\n",
15567c478bd9Sstevel@tonic-gate 	    "BASE", "LIMIT", "SIZE", "NAME");
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC) {
15597c478bd9Sstevel@tonic-gate 		if ((m = mdb_tgt_addr_to_map(mdb.m_target, addr)) == NULL)
15607c478bd9Sstevel@tonic-gate 			mdb_warn("failed to obtain mapping");
15617c478bd9Sstevel@tonic-gate 		else
15627c478bd9Sstevel@tonic-gate 			(void) print_map(NULL, m, NULL);
15637c478bd9Sstevel@tonic-gate 
15647c478bd9Sstevel@tonic-gate 	} else if (argc != 0) {
15657c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_STRING)
15667c478bd9Sstevel@tonic-gate 			m = mdb_tgt_name_to_map(mdb.m_target, argv->a_un.a_str);
15677c478bd9Sstevel@tonic-gate 		else
15687c478bd9Sstevel@tonic-gate 			m = mdb_tgt_addr_to_map(mdb.m_target, argv->a_un.a_val);
15697c478bd9Sstevel@tonic-gate 
15707c478bd9Sstevel@tonic-gate 		if (m == NULL)
15717c478bd9Sstevel@tonic-gate 			mdb_warn("failed to obtain mapping");
15727c478bd9Sstevel@tonic-gate 		else
15737c478bd9Sstevel@tonic-gate 			(void) print_map(NULL, m, NULL);
15747c478bd9Sstevel@tonic-gate 
15757c478bd9Sstevel@tonic-gate 	} else if (mdb_tgt_mapping_iter(mdb.m_target, print_map, NULL) == -1)
15767c478bd9Sstevel@tonic-gate 		mdb_warn("failed to iterate over mappings");
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate 
15814a1c2431SJonathan Adams static int
whatis_map_callback(void * wp,const mdb_map_t * map,const char * name)15824a1c2431SJonathan Adams whatis_map_callback(void *wp, const mdb_map_t *map, const char *name)
15834a1c2431SJonathan Adams {
15844a1c2431SJonathan Adams 	mdb_whatis_t *w = wp;
15854a1c2431SJonathan Adams 	uintptr_t cur;
15864a1c2431SJonathan Adams 
15874a1c2431SJonathan Adams 	name = map_name(map, name);
15884a1c2431SJonathan Adams 
15894a1c2431SJonathan Adams 	while (mdb_whatis_match(w, map->map_base, map->map_size, &cur))
15904a1c2431SJonathan Adams 		mdb_whatis_report_address(w, cur, "in %s [%p,%p)\n",
15914a1c2431SJonathan Adams 		    name, map->map_base, map->map_base + map->map_size);
15924a1c2431SJonathan Adams 
15934a1c2431SJonathan Adams 	return (0);
15944a1c2431SJonathan Adams }
15954a1c2431SJonathan Adams 
15964a1c2431SJonathan Adams /*ARGSUSED*/
15974a1c2431SJonathan Adams int
whatis_run_mappings(mdb_whatis_t * w,void * ignored)15984a1c2431SJonathan Adams whatis_run_mappings(mdb_whatis_t *w, void *ignored)
15994a1c2431SJonathan Adams {
16004a1c2431SJonathan Adams 	(void) mdb_tgt_mapping_iter(mdb.m_target, whatis_map_callback, w);
16014a1c2431SJonathan Adams 	return (0);
16024a1c2431SJonathan Adams }
16034a1c2431SJonathan Adams 
16047c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16057c478bd9Sstevel@tonic-gate static int
objects_printversion(void * ignored,const mdb_map_t * map,const char * name)16067c478bd9Sstevel@tonic-gate objects_printversion(void *ignored, const mdb_map_t *map, const char *name)
16077c478bd9Sstevel@tonic-gate {
16087c478bd9Sstevel@tonic-gate 	ctf_file_t *ctfp;
16097c478bd9Sstevel@tonic-gate 	const char *version;
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	ctfp = mdb_tgt_name_to_ctf(mdb.m_target, name);
16127c478bd9Sstevel@tonic-gate 	if (ctfp == NULL || (version = ctf_label_topmost(ctfp)) == NULL)
16137c478bd9Sstevel@tonic-gate 		version = "Unknown";
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 	mdb_printf("%-28s %s\n", name, version);
16167c478bd9Sstevel@tonic-gate 	return (0);
16177c478bd9Sstevel@tonic-gate }
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16207c478bd9Sstevel@tonic-gate static int
cmd_objects(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)16217c478bd9Sstevel@tonic-gate cmd_objects(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
16227c478bd9Sstevel@tonic-gate {
16237c478bd9Sstevel@tonic-gate 	uint_t opt_v = FALSE;
16247c478bd9Sstevel@tonic-gate 	mdb_tgt_map_f *cb;
16257c478bd9Sstevel@tonic-gate 
16267c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv,
16277c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
16287c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
16297c478bd9Sstevel@tonic-gate 
16307c478bd9Sstevel@tonic-gate 	if (opt_v) {
16317c478bd9Sstevel@tonic-gate 		cb = objects_printversion;
16327c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%-28s %s%</u>\n", "NAME", "VERSION");
16337c478bd9Sstevel@tonic-gate 	} else {
16347c478bd9Sstevel@tonic-gate 		cb = print_map;
16357c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%?s %?s %?s %s%</u>\n",
16367c478bd9Sstevel@tonic-gate 		    "BASE", "LIMIT", "SIZE", "NAME");
16377c478bd9Sstevel@tonic-gate 	}
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 	if (mdb_tgt_object_iter(mdb.m_target, cb, NULL) == -1) {
16407c478bd9Sstevel@tonic-gate 		mdb_warn("failed to iterate over objects");
16417c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
16427c478bd9Sstevel@tonic-gate 	}
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
16457c478bd9Sstevel@tonic-gate }
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16487c478bd9Sstevel@tonic-gate static int
showrev_addversion(void * vers_nv,const mdb_map_t * ignored,const char * object)16497c478bd9Sstevel@tonic-gate showrev_addversion(void *vers_nv, const mdb_map_t *ignored, const char *object)
16507c478bd9Sstevel@tonic-gate {
16517c478bd9Sstevel@tonic-gate 	ctf_file_t *ctfp;
16527c478bd9Sstevel@tonic-gate 	const char *version = NULL;
16537c478bd9Sstevel@tonic-gate 	char *objname;
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 	objname = mdb_alloc(strlen(object) + 1, UM_SLEEP | UM_GC);
16567c478bd9Sstevel@tonic-gate 	(void) strcpy(objname, object);
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 	if ((ctfp = mdb_tgt_name_to_ctf(mdb.m_target, objname)) != NULL)
16597c478bd9Sstevel@tonic-gate 		version = ctf_label_topmost(ctfp);
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 	/*
16627c478bd9Sstevel@tonic-gate 	 * Not all objects have CTF and label data, so set version to "Unknown".
16637c478bd9Sstevel@tonic-gate 	 */
16647c478bd9Sstevel@tonic-gate 	if (version == NULL)
16657c478bd9Sstevel@tonic-gate 		version = "Unknown";
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	(void) mdb_nv_insert(vers_nv, version, NULL, (uintptr_t)objname,
16687c478bd9Sstevel@tonic-gate 	    MDB_NV_OVERLOAD);
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate 	return (0);
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate static int
showrev_ispatch(const char * s)16747c478bd9Sstevel@tonic-gate showrev_ispatch(const char *s)
16757c478bd9Sstevel@tonic-gate {
16767c478bd9Sstevel@tonic-gate 	if (s == NULL)
16777c478bd9Sstevel@tonic-gate 		return (0);
16787c478bd9Sstevel@tonic-gate 
16797c478bd9Sstevel@tonic-gate 	if (*s == 'T')
16807c478bd9Sstevel@tonic-gate 		s++; /* skip T for T-patch */
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++) {
16837c478bd9Sstevel@tonic-gate 		if ((*s < '0' || *s > '9') && *s != '-')
16847c478bd9Sstevel@tonic-gate 			return (0);
16857c478bd9Sstevel@tonic-gate 	}
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate 	return (1);
16887c478bd9Sstevel@tonic-gate }
16897c478bd9Sstevel@tonic-gate 
16907c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16917c478bd9Sstevel@tonic-gate static int
showrev_printobject(mdb_var_t * v,void * ignored)16927c478bd9Sstevel@tonic-gate showrev_printobject(mdb_var_t *v, void *ignored)
16937c478bd9Sstevel@tonic-gate {
16947c478bd9Sstevel@tonic-gate 	mdb_printf("%s ", MDB_NV_COOKIE(v));
16957c478bd9Sstevel@tonic-gate 	return (0);
16967c478bd9Sstevel@tonic-gate }
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate static int
showrev_printversion(mdb_var_t * v,void * showall)16997c478bd9Sstevel@tonic-gate showrev_printversion(mdb_var_t *v, void *showall)
17007c478bd9Sstevel@tonic-gate {
17017c478bd9Sstevel@tonic-gate 	const char *version = mdb_nv_get_name(v);
17027c478bd9Sstevel@tonic-gate 	int patch;
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 	patch = showrev_ispatch(version);
17057c478bd9Sstevel@tonic-gate 	if (patch || (uintptr_t)showall) {
17067c478bd9Sstevel@tonic-gate 		mdb_printf("%s: %s  Objects: ",
17077c478bd9Sstevel@tonic-gate 		    (patch ? "Patch" : "Version"), version);
17087c478bd9Sstevel@tonic-gate 		(void) mdb_inc_indent(2);
17097c478bd9Sstevel@tonic-gate 
17107c478bd9Sstevel@tonic-gate 		mdb_nv_defn_iter(v, showrev_printobject, NULL);
17117c478bd9Sstevel@tonic-gate 
17127c478bd9Sstevel@tonic-gate 		(void) mdb_dec_indent(2);
17137c478bd9Sstevel@tonic-gate 		mdb_printf("\n");
17147c478bd9Sstevel@tonic-gate 	}
17157c478bd9Sstevel@tonic-gate 
17167c478bd9Sstevel@tonic-gate 	return (0);
17177c478bd9Sstevel@tonic-gate }
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate /*
17207c478bd9Sstevel@tonic-gate  * Display version information for each object in the system.
17217c478bd9Sstevel@tonic-gate  * Print information about patches only, unless showall is TRUE.
17227c478bd9Sstevel@tonic-gate  */
17237c478bd9Sstevel@tonic-gate static int
showrev_objectversions(int showall)17247c478bd9Sstevel@tonic-gate showrev_objectversions(int showall)
17257c478bd9Sstevel@tonic-gate {
17267c478bd9Sstevel@tonic-gate 	mdb_nv_t vers_nv;
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate 	(void) mdb_nv_create(&vers_nv, UM_SLEEP | UM_GC);
17297c478bd9Sstevel@tonic-gate 	if (mdb_tgt_object_iter(mdb.m_target, showrev_addversion,
17307c478bd9Sstevel@tonic-gate 	    &vers_nv) == -1) {
17317c478bd9Sstevel@tonic-gate 		mdb_warn("failed to iterate over objects");
17327c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
17337c478bd9Sstevel@tonic-gate 	}
17347c478bd9Sstevel@tonic-gate 
17357c478bd9Sstevel@tonic-gate 	mdb_nv_sort_iter(&vers_nv, showrev_printversion,
17367c478bd9Sstevel@tonic-gate 	    (void *)(uintptr_t)showall, UM_SLEEP | UM_GC);
17377c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
17387c478bd9Sstevel@tonic-gate }
17397c478bd9Sstevel@tonic-gate 
17407c478bd9Sstevel@tonic-gate /*
1741*bbf21555SRichard Lowe  * Display information similar to what showrev(8) displays when invoked
17427c478bd9Sstevel@tonic-gate  * with no arguments.
17437c478bd9Sstevel@tonic-gate  */
17447c478bd9Sstevel@tonic-gate static int
showrev_sysinfo(void)17457c478bd9Sstevel@tonic-gate showrev_sysinfo(void)
17467c478bd9Sstevel@tonic-gate {
17477c478bd9Sstevel@tonic-gate 	const char *s;
17487c478bd9Sstevel@tonic-gate 	int rc;
17497c478bd9Sstevel@tonic-gate 	struct utsname u;
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 	if ((rc = mdb_tgt_uname(mdb.m_target, &u)) != -1) {
17527c478bd9Sstevel@tonic-gate 		mdb_printf("Hostname: %s\n", u.nodename);
17537c478bd9Sstevel@tonic-gate 		mdb_printf("Release: %s\n", u.release);
17547c478bd9Sstevel@tonic-gate 		mdb_printf("Kernel architecture: %s\n", u.machine);
17557c478bd9Sstevel@tonic-gate 	}
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 	/*
1758*bbf21555SRichard Lowe 	 * Match the order of the showrev(8) output and put "Application
17597c478bd9Sstevel@tonic-gate 	 * architecture" before "Kernel version"
17607c478bd9Sstevel@tonic-gate 	 */
17617c478bd9Sstevel@tonic-gate 	if ((s = mdb_tgt_isa(mdb.m_target)) != NULL)
17627c478bd9Sstevel@tonic-gate 		mdb_printf("Application architecture: %s\n", s);
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 	if (rc != -1)
17657c478bd9Sstevel@tonic-gate 		mdb_printf("Kernel version: %s %s %s %s\n",
17667c478bd9Sstevel@tonic-gate 		    u.sysname, u.release, u.machine, u.version);
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate 	if ((s = mdb_tgt_platform(mdb.m_target)) != NULL)
17697c478bd9Sstevel@tonic-gate 		mdb_printf("Platform: %s\n", s);
17707c478bd9Sstevel@tonic-gate 
17717c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
17727c478bd9Sstevel@tonic-gate }
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate /*ARGSUSED*/
17757c478bd9Sstevel@tonic-gate static int
cmd_showrev(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)17767c478bd9Sstevel@tonic-gate cmd_showrev(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
17777c478bd9Sstevel@tonic-gate {
17787c478bd9Sstevel@tonic-gate 	uint_t opt_p = FALSE, opt_v = FALSE;
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv,
17817c478bd9Sstevel@tonic-gate 	    'p', MDB_OPT_SETBITS, TRUE, &opt_p,
17827c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
17837c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
17847c478bd9Sstevel@tonic-gate 
17857c478bd9Sstevel@tonic-gate 	if (opt_p || opt_v)
17867c478bd9Sstevel@tonic-gate 		return (showrev_objectversions(opt_v));
17877c478bd9Sstevel@tonic-gate 	else
17887c478bd9Sstevel@tonic-gate 		return (showrev_sysinfo());
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate #ifdef __sparc
17927c478bd9Sstevel@tonic-gate static void
findsym_output(uintptr_t * symlist,uintptr_t value,uintptr_t location)17937c478bd9Sstevel@tonic-gate findsym_output(uintptr_t *symlist, uintptr_t value, uintptr_t location)
17947c478bd9Sstevel@tonic-gate {
17957c478bd9Sstevel@tonic-gate 	uintptr_t	*symbolp;
17967c478bd9Sstevel@tonic-gate 
17977c478bd9Sstevel@tonic-gate 	for (symbolp = symlist; *symbolp; symbolp++)
17987c478bd9Sstevel@tonic-gate 		if (value == *symbolp)
17997c478bd9Sstevel@tonic-gate 			mdb_printf("found %a at %a\n", value, location);
18007c478bd9Sstevel@tonic-gate }
18017c478bd9Sstevel@tonic-gate 
18027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
18037c478bd9Sstevel@tonic-gate static int
findsym_cb(void * data,const GElf_Sym * sym,const char * name,const mdb_syminfo_t * sip,const char * obj)18047c478bd9Sstevel@tonic-gate findsym_cb(void *data, const GElf_Sym *sym, const char *name,
18057c478bd9Sstevel@tonic-gate     const mdb_syminfo_t *sip, const char *obj)
18067c478bd9Sstevel@tonic-gate {
18077c478bd9Sstevel@tonic-gate 	uint32_t	*text;
18087c478bd9Sstevel@tonic-gate 	int		len;
18097c478bd9Sstevel@tonic-gate 	int		i;
18107c478bd9Sstevel@tonic-gate 	int		j;
18117c478bd9Sstevel@tonic-gate 	uint8_t		rd;
18127c478bd9Sstevel@tonic-gate 	uintptr_t	value;
18137c478bd9Sstevel@tonic-gate 	int32_t		imm13;
18147c478bd9Sstevel@tonic-gate 	uint8_t		op;
18157c478bd9Sstevel@tonic-gate 	uint8_t		op3;
18167c478bd9Sstevel@tonic-gate 	uintptr_t	*symlist = data;
18177c478bd9Sstevel@tonic-gate 	size_t		size = sym->st_size;
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	/*
18207c478bd9Sstevel@tonic-gate 	 * if the size of the symbol is 0, then this symbol must be for an
18217c478bd9Sstevel@tonic-gate 	 * alternate entry point or just some global label. We will,
18227c478bd9Sstevel@tonic-gate 	 * therefore, get back to the text that follows this symbol in
18237c478bd9Sstevel@tonic-gate 	 * some other symbol
18247c478bd9Sstevel@tonic-gate 	 */
18257c478bd9Sstevel@tonic-gate 	if (size == 0)
18267c478bd9Sstevel@tonic-gate 		return (0);
18277c478bd9Sstevel@tonic-gate 
18287c478bd9Sstevel@tonic-gate 	if (sym->st_shndx == SHN_UNDEF)
18297c478bd9Sstevel@tonic-gate 		return (0);
18307c478bd9Sstevel@tonic-gate 
18317c478bd9Sstevel@tonic-gate 	text = alloca(size);
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 	if (mdb_vread(text, size, sym->st_value) == -1) {
18347c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read text for %s", name);
18357c478bd9Sstevel@tonic-gate 		return (0);
18367c478bd9Sstevel@tonic-gate 	}
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 	len = size / 4;
18397c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
18407c478bd9Sstevel@tonic-gate 		if (!IS_SETHI(text[i]))
18417c478bd9Sstevel@tonic-gate 			continue;
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate 		rd = RD(text[i]);
18447c478bd9Sstevel@tonic-gate 		value = IMM22(text[i]) << 10;
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate 		/*
18477c478bd9Sstevel@tonic-gate 		 * see if we already have a match with just the sethi
18487c478bd9Sstevel@tonic-gate 		 */
18497c478bd9Sstevel@tonic-gate 		findsym_output(symlist, value, sym->st_value + i * 4);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 		/*
185263360950Smp 		 * search from the sethi on until we hit a relevant instr
18537c478bd9Sstevel@tonic-gate 		 */
18547c478bd9Sstevel@tonic-gate 		for (j = i + 1; j < len; j++) {
18557c478bd9Sstevel@tonic-gate 			if ((op = OP(text[j])) & OP_ARITH_MEM_MASK) {
18567c478bd9Sstevel@tonic-gate 				op3 = OP3(text[j]);
18577c478bd9Sstevel@tonic-gate 
18587c478bd9Sstevel@tonic-gate 				if (RS1(text[j]) != rd)
18597c478bd9Sstevel@tonic-gate 					goto instr_end;
18607c478bd9Sstevel@tonic-gate 
18617c478bd9Sstevel@tonic-gate 				/*
18627c478bd9Sstevel@tonic-gate 				 * This is a simple tool; we only deal
18637c478bd9Sstevel@tonic-gate 				 * with operations which take immediates
18647c478bd9Sstevel@tonic-gate 				 */
18657c478bd9Sstevel@tonic-gate 				if (I(text[j]) == 0)
18667c478bd9Sstevel@tonic-gate 					goto instr_end;
18677c478bd9Sstevel@tonic-gate 
18687c478bd9Sstevel@tonic-gate 				/*
18697c478bd9Sstevel@tonic-gate 				 * sign extend the immediate value
18707c478bd9Sstevel@tonic-gate 				 */
18717c478bd9Sstevel@tonic-gate 				imm13 = IMM13(text[j]);
18727c478bd9Sstevel@tonic-gate 				imm13 <<= 19;
18737c478bd9Sstevel@tonic-gate 				imm13 >>= 19;
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate 				if (op == OP_ARITH) {
18767c478bd9Sstevel@tonic-gate 					/* arithmetic operations */
18777c478bd9Sstevel@tonic-gate 					if (op3 & OP3_COMPLEX_MASK)
18787c478bd9Sstevel@tonic-gate 						goto instr_end;
18797c478bd9Sstevel@tonic-gate 
18807c478bd9Sstevel@tonic-gate 					switch (op3 & ~OP3_CC_MASK) {
18817c478bd9Sstevel@tonic-gate 					case OP3_OR:
18827c478bd9Sstevel@tonic-gate 						value |= imm13;
18837c478bd9Sstevel@tonic-gate 						break;
18847c478bd9Sstevel@tonic-gate 					case OP3_ADD:
18857c478bd9Sstevel@tonic-gate 						value += imm13;
18867c478bd9Sstevel@tonic-gate 						break;
18877c478bd9Sstevel@tonic-gate 					case OP3_XOR:
18887c478bd9Sstevel@tonic-gate 						value ^= imm13;
18897c478bd9Sstevel@tonic-gate 						break;
18907c478bd9Sstevel@tonic-gate 					default:
18917c478bd9Sstevel@tonic-gate 						goto instr_end;
18927c478bd9Sstevel@tonic-gate 					}
18937c478bd9Sstevel@tonic-gate 				} else {
18947c478bd9Sstevel@tonic-gate 					/* loads and stores */
18957c478bd9Sstevel@tonic-gate 					/* op3 == OP_MEM */
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 					value += imm13;
18987c478bd9Sstevel@tonic-gate 				}
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 				findsym_output(symlist, value,
19017c478bd9Sstevel@tonic-gate 				    sym->st_value + j * 4);
19027c478bd9Sstevel@tonic-gate instr_end:
19037c478bd9Sstevel@tonic-gate 				/*
19047c478bd9Sstevel@tonic-gate 				 * if we're clobbering rd, break
19057c478bd9Sstevel@tonic-gate 				 */
19067c478bd9Sstevel@tonic-gate 				if (RD(text[j]) == rd)
19077c478bd9Sstevel@tonic-gate 					break;
19087c478bd9Sstevel@tonic-gate 			} else if (IS_SETHI(text[j])) {
19097c478bd9Sstevel@tonic-gate 				if (RD(text[j]) == rd)
19107c478bd9Sstevel@tonic-gate 					break;
19117c478bd9Sstevel@tonic-gate 			} else if (OP(text[j]) == 1) {
19127c478bd9Sstevel@tonic-gate 				/*
19137c478bd9Sstevel@tonic-gate 				 * see if a call clobbers an %o or %g
19147c478bd9Sstevel@tonic-gate 				 */
19157c478bd9Sstevel@tonic-gate 				if (rd <= R_O7)
19167c478bd9Sstevel@tonic-gate 					break;
19177c478bd9Sstevel@tonic-gate 			}
19187c478bd9Sstevel@tonic-gate 		}
19197c478bd9Sstevel@tonic-gate 	}
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate 	return (0);
19227c478bd9Sstevel@tonic-gate }
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate static int
cmd_findsym(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)19257c478bd9Sstevel@tonic-gate cmd_findsym(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
19267c478bd9Sstevel@tonic-gate {
19277c478bd9Sstevel@tonic-gate 	uintptr_t *symlist;
19287c478bd9Sstevel@tonic-gate 	uint_t optg = FALSE;
19297c478bd9Sstevel@tonic-gate 	uint_t type;
19307c478bd9Sstevel@tonic-gate 	int len, i;
19317c478bd9Sstevel@tonic-gate 
19327c478bd9Sstevel@tonic-gate 	i = mdb_getopts(argc, argv, 'g', MDB_OPT_SETBITS, TRUE, &optg, NULL);
19337c478bd9Sstevel@tonic-gate 
19347c478bd9Sstevel@tonic-gate 	argc -= i;
19357c478bd9Sstevel@tonic-gate 	argv += i;
19367c478bd9Sstevel@tonic-gate 
19377c478bd9Sstevel@tonic-gate 	len = argc + ((flags & DCMD_ADDRSPEC) ? 1 : 0) + 1;
19387c478bd9Sstevel@tonic-gate 
19397c478bd9Sstevel@tonic-gate 	if (len <= 1)
19407c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
19417c478bd9Sstevel@tonic-gate 
19427c478bd9Sstevel@tonic-gate 	/*
19437c478bd9Sstevel@tonic-gate 	 * Set up a NULL-terminated symbol list, and then iterate over the
19447c478bd9Sstevel@tonic-gate 	 * symbol table, scanning each function for references to these symbols.
19457c478bd9Sstevel@tonic-gate 	 */
19467c478bd9Sstevel@tonic-gate 	symlist = mdb_alloc(len * sizeof (uintptr_t), UM_SLEEP | UM_GC);
19477c478bd9Sstevel@tonic-gate 	len = 0;
19487c478bd9Sstevel@tonic-gate 
19497c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++, argv++) {
19507c478bd9Sstevel@tonic-gate 		const char *str = argv->a_un.a_str;
19517c478bd9Sstevel@tonic-gate 		uintptr_t value;
19527c478bd9Sstevel@tonic-gate 		GElf_Sym sym;
19537c478bd9Sstevel@tonic-gate 
19547c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_STRING) {
19557c478bd9Sstevel@tonic-gate 			if (strchr("+-", str[0]) != NULL)
19567c478bd9Sstevel@tonic-gate 				return (DCMD_USAGE);
19577c478bd9Sstevel@tonic-gate 			else if (str[0] >= '0' && str[0] <= '9')
19587c478bd9Sstevel@tonic-gate 				value = mdb_strtoull(str);
19597c478bd9Sstevel@tonic-gate 			else if (mdb_lookup_by_name(str, &sym) != 0) {
19607c478bd9Sstevel@tonic-gate 				mdb_warn("symbol '%s' not found", str);
19617c478bd9Sstevel@tonic-gate 				return (DCMD_USAGE);
19627c478bd9Sstevel@tonic-gate 			} else
19637c478bd9Sstevel@tonic-gate 				value = sym.st_value;
19647c478bd9Sstevel@tonic-gate 		} else
19657c478bd9Sstevel@tonic-gate 			value = argv[i].a_un.a_val;
19667c478bd9Sstevel@tonic-gate 
196759b05390SToomas Soome 		if (value != (uintptr_t)NULL)
19687c478bd9Sstevel@tonic-gate 			symlist[len++] = value;
19697c478bd9Sstevel@tonic-gate 	}
19707c478bd9Sstevel@tonic-gate 
19717c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
19727c478bd9Sstevel@tonic-gate 		symlist[len++] = addr;
19737c478bd9Sstevel@tonic-gate 
197459b05390SToomas Soome 	symlist[len] = (uintptr_t)NULL;
19757c478bd9Sstevel@tonic-gate 
19767c478bd9Sstevel@tonic-gate 	if (optg)
19777c478bd9Sstevel@tonic-gate 		type = MDB_TGT_BIND_GLOBAL | MDB_TGT_TYPE_FUNC;
19787c478bd9Sstevel@tonic-gate 	else
19797c478bd9Sstevel@tonic-gate 		type = MDB_TGT_BIND_ANY | MDB_TGT_TYPE_FUNC;
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 	if (mdb_tgt_symbol_iter(mdb.m_target, MDB_TGT_OBJ_EVERY,
19827c478bd9Sstevel@tonic-gate 	    MDB_TGT_SYMTAB, type, findsym_cb, symlist) == -1) {
19837c478bd9Sstevel@tonic-gate 		mdb_warn("failed to iterate over symbol table");
19847c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
19857c478bd9Sstevel@tonic-gate 	}
19867c478bd9Sstevel@tonic-gate 
19877c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
19887c478bd9Sstevel@tonic-gate }
19897c478bd9Sstevel@tonic-gate #endif /* __sparc */
19907c478bd9Sstevel@tonic-gate 
19917c478bd9Sstevel@tonic-gate static int
dis_str2addr(const char * s,uintptr_t * addr)19927c478bd9Sstevel@tonic-gate dis_str2addr(const char *s, uintptr_t *addr)
19937c478bd9Sstevel@tonic-gate {
19947c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate 	if (s[0] >= '0' && s[0] <= '9') {
19977c478bd9Sstevel@tonic-gate 		*addr = (uintptr_t)mdb_strtoull(s);
19987c478bd9Sstevel@tonic-gate 		return (0);
19997c478bd9Sstevel@tonic-gate 	}
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate 	if (mdb_tgt_lookup_by_name(mdb.m_target,
20027c478bd9Sstevel@tonic-gate 	    MDB_TGT_OBJ_EVERY, s, &sym, NULL) == -1) {
20037c478bd9Sstevel@tonic-gate 		mdb_warn("symbol '%s' not found\n", s);
20047c478bd9Sstevel@tonic-gate 		return (-1);
20057c478bd9Sstevel@tonic-gate 	}
20067c478bd9Sstevel@tonic-gate 
20077c478bd9Sstevel@tonic-gate 	*addr = (uintptr_t)sym.st_value;
20087c478bd9Sstevel@tonic-gate 	return (0);
20097c478bd9Sstevel@tonic-gate }
20107c478bd9Sstevel@tonic-gate 
20117c478bd9Sstevel@tonic-gate static int
cmd_dis(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)20127c478bd9Sstevel@tonic-gate cmd_dis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
20137c478bd9Sstevel@tonic-gate {
20147c478bd9Sstevel@tonic-gate 	mdb_tgt_t *tgt = mdb.m_target;
20157c478bd9Sstevel@tonic-gate 	mdb_disasm_t *dis = mdb.m_disasm;
20167c478bd9Sstevel@tonic-gate 
20177c478bd9Sstevel@tonic-gate 	uintptr_t oaddr, naddr;
20187c478bd9Sstevel@tonic-gate 	mdb_tgt_as_t as;
20197c478bd9Sstevel@tonic-gate 	mdb_tgt_status_t st;
20207c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];
20217c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
20227c478bd9Sstevel@tonic-gate 	int i;
20237c478bd9Sstevel@tonic-gate 
20247c478bd9Sstevel@tonic-gate 	uint_t opt_f = FALSE;		/* File-mode off by default */
20257c478bd9Sstevel@tonic-gate 	uint_t opt_w = FALSE;		/* Window mode off by default */
20267c478bd9Sstevel@tonic-gate 	uint_t opt_a = FALSE;		/* Raw-address mode off by default */
2027af7034caSss 	uint_t opt_b = FALSE;		/* Address & symbols off by default */
20287c478bd9Sstevel@tonic-gate 	uintptr_t n = -1UL;		/* Length of window in instructions */
20297c478bd9Sstevel@tonic-gate 	uintptr_t eaddr = 0;		/* Ending address; 0 if limited by n */
20307c478bd9Sstevel@tonic-gate 
20317c478bd9Sstevel@tonic-gate 	i = mdb_getopts(argc, argv,
20327c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &opt_f,
20337c478bd9Sstevel@tonic-gate 	    'w', MDB_OPT_SETBITS, TRUE, &opt_w,
20347c478bd9Sstevel@tonic-gate 	    'a', MDB_OPT_SETBITS, TRUE, &opt_a,
2035af7034caSss 	    'b', MDB_OPT_SETBITS, TRUE, &opt_b,
20367c478bd9Sstevel@tonic-gate 	    'n', MDB_OPT_UINTPTR, &n, NULL);
20377c478bd9Sstevel@tonic-gate 
20387c478bd9Sstevel@tonic-gate 	/*
20397c478bd9Sstevel@tonic-gate 	 * Disgusting argument post-processing ... basically the idea is to get
20407c478bd9Sstevel@tonic-gate 	 * the target address into addr, which we do by using the specified
20417c478bd9Sstevel@tonic-gate 	 * expression value, looking up a string as a symbol name, or by
20427c478bd9Sstevel@tonic-gate 	 * using the address specified as dot.
20437c478bd9Sstevel@tonic-gate 	 */
20447c478bd9Sstevel@tonic-gate 	if (i != argc) {
20457c478bd9Sstevel@tonic-gate 		if (argc != 0 && (argc - i) == 1) {
20467c478bd9Sstevel@tonic-gate 			if (argv[i].a_type == MDB_TYPE_STRING) {
20477c478bd9Sstevel@tonic-gate 				if (argv[i].a_un.a_str[0] == '-')
20487c478bd9Sstevel@tonic-gate 					return (DCMD_USAGE);
20497c478bd9Sstevel@tonic-gate 
20507c478bd9Sstevel@tonic-gate 				if (dis_str2addr(argv[i].a_un.a_str, &addr))
20517c478bd9Sstevel@tonic-gate 					return (DCMD_ERR);
20527c478bd9Sstevel@tonic-gate 			} else
20537c478bd9Sstevel@tonic-gate 				addr = argv[i].a_un.a_val;
20547c478bd9Sstevel@tonic-gate 		} else
20557c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
20567c478bd9Sstevel@tonic-gate 	}
20577c478bd9Sstevel@tonic-gate 
20587c478bd9Sstevel@tonic-gate 	/*
20597c478bd9Sstevel@tonic-gate 	 * If we're not in window mode yet, and some type of arguments were
20607c478bd9Sstevel@tonic-gate 	 * specified, see if the address corresponds nicely to a function.
20617c478bd9Sstevel@tonic-gate 	 * If not, turn on window mode; otherwise disassemble the function.
20627c478bd9Sstevel@tonic-gate 	 */
20637c478bd9Sstevel@tonic-gate 	if (opt_w == FALSE && (argc != i || (flags & DCMD_ADDRSPEC))) {
20647c478bd9Sstevel@tonic-gate 		if (mdb_tgt_lookup_by_addr(tgt, addr,
20657c478bd9Sstevel@tonic-gate 		    MDB_TGT_SYM_EXACT, buf, sizeof (buf), &sym, NULL) == 0 &&
20667c478bd9Sstevel@tonic-gate 		    GELF_ST_TYPE(sym.st_info) == STT_FUNC) {
20677c478bd9Sstevel@tonic-gate 			/*
20687c478bd9Sstevel@tonic-gate 			 * If the symbol has a size then set our end address to
20697c478bd9Sstevel@tonic-gate 			 * be the end of the function symbol we just located.
20707c478bd9Sstevel@tonic-gate 			 */
20717c478bd9Sstevel@tonic-gate 			if (sym.st_size != 0)
20727c478bd9Sstevel@tonic-gate 				eaddr = addr + (uintptr_t)sym.st_size;
20737c478bd9Sstevel@tonic-gate 		} else
20747c478bd9Sstevel@tonic-gate 			opt_w = TRUE;
20757c478bd9Sstevel@tonic-gate 	}
20767c478bd9Sstevel@tonic-gate 
20777c478bd9Sstevel@tonic-gate 	/*
20787c478bd9Sstevel@tonic-gate 	 * Window-mode doesn't make sense in a loop.
20797c478bd9Sstevel@tonic-gate 	 */
20807c478bd9Sstevel@tonic-gate 	if (flags & DCMD_LOOP)
20817c478bd9Sstevel@tonic-gate 		opt_w = FALSE;
20827c478bd9Sstevel@tonic-gate 
20837c478bd9Sstevel@tonic-gate 	/*
20847c478bd9Sstevel@tonic-gate 	 * If -n was explicit, limit output to n instructions;
20857c478bd9Sstevel@tonic-gate 	 * otherwise set n to some reasonable default
20867c478bd9Sstevel@tonic-gate 	 */
20877c478bd9Sstevel@tonic-gate 	if (n != -1UL)
20887c478bd9Sstevel@tonic-gate 		eaddr = 0;
20897c478bd9Sstevel@tonic-gate 	else
20907c478bd9Sstevel@tonic-gate 		n = 10;
20917c478bd9Sstevel@tonic-gate 
20927c478bd9Sstevel@tonic-gate 	/*
20937c478bd9Sstevel@tonic-gate 	 * If the state is IDLE (i.e. no address space), turn on -f.
20947c478bd9Sstevel@tonic-gate 	 */
20957c478bd9Sstevel@tonic-gate 	if (mdb_tgt_status(tgt, &st) == 0 && st.st_state == MDB_TGT_IDLE)
20967c478bd9Sstevel@tonic-gate 		opt_f = TRUE;
20977c478bd9Sstevel@tonic-gate 
20987c478bd9Sstevel@tonic-gate 	if (opt_f)
20997c478bd9Sstevel@tonic-gate 		as = MDB_TGT_AS_FILE;
21007c478bd9Sstevel@tonic-gate 	else
21019c3024a3SHans Rosenfeld 		as = MDB_TGT_AS_VIRT_I;
21027c478bd9Sstevel@tonic-gate 
21037c478bd9Sstevel@tonic-gate 	if (opt_w == FALSE) {
21047c478bd9Sstevel@tonic-gate 		n++;
21057c478bd9Sstevel@tonic-gate 		while ((eaddr == 0 && n-- != 0) || (addr < eaddr)) {
21067c478bd9Sstevel@tonic-gate 			naddr = mdb_dis_ins2str(dis, tgt, as,
21077c478bd9Sstevel@tonic-gate 			    buf, sizeof (buf), addr);
21087c478bd9Sstevel@tonic-gate 			if (naddr == addr)
21097c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
21107c478bd9Sstevel@tonic-gate 			if (opt_a)
21117c478bd9Sstevel@tonic-gate 				mdb_printf("%-#32p%8T%s\n", addr, buf);
2112af7034caSss 			else if (opt_b)
21134cf73299SJosef 'Jeff' Sipek 				mdb_printf("%-#?p  %-#32a%8T%s\n",
2114af7034caSss 				    addr, addr, buf);
21157c478bd9Sstevel@tonic-gate 			else
21167c478bd9Sstevel@tonic-gate 				mdb_printf("%-#32a%8T%s\n", addr, buf);
21177c478bd9Sstevel@tonic-gate 			addr = naddr;
21187c478bd9Sstevel@tonic-gate 		}
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	} else {
21217c478bd9Sstevel@tonic-gate #ifdef __sparc
21227c478bd9Sstevel@tonic-gate 		if (addr & 0x3) {
21237c478bd9Sstevel@tonic-gate 			mdb_warn("address is not properly aligned\n");
21247c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
21257c478bd9Sstevel@tonic-gate 		}
21267c478bd9Sstevel@tonic-gate #endif
21277c478bd9Sstevel@tonic-gate 
21287c478bd9Sstevel@tonic-gate 		for (oaddr = mdb_dis_previns(dis, tgt, as, addr, n);
21297c478bd9Sstevel@tonic-gate 		    oaddr < addr; oaddr = naddr) {
21307c478bd9Sstevel@tonic-gate 			naddr = mdb_dis_ins2str(dis, tgt, as,
21317c478bd9Sstevel@tonic-gate 			    buf, sizeof (buf), oaddr);
21327c478bd9Sstevel@tonic-gate 			if (naddr == oaddr)
21337c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
21347c478bd9Sstevel@tonic-gate 			if (opt_a)
21357c478bd9Sstevel@tonic-gate 				mdb_printf("%-#32p%8T%s\n", oaddr, buf);
2136af7034caSss 			else if (opt_b)
21374cf73299SJosef 'Jeff' Sipek 				mdb_printf("%-#?p  %-#32a%8T%s\n",
2138af7034caSss 				    oaddr, oaddr, buf);
21397c478bd9Sstevel@tonic-gate 			else
21407c478bd9Sstevel@tonic-gate 				mdb_printf("%-#32a%8T%s\n", oaddr, buf);
21417c478bd9Sstevel@tonic-gate 		}
21427c478bd9Sstevel@tonic-gate 
21437c478bd9Sstevel@tonic-gate 		if ((naddr = mdb_dis_ins2str(dis, tgt, as,
21447c478bd9Sstevel@tonic-gate 		    buf, sizeof (buf), addr)) == addr)
21457c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
21467c478bd9Sstevel@tonic-gate 
21477c478bd9Sstevel@tonic-gate 		mdb_printf("%<b>");
21487c478bd9Sstevel@tonic-gate 		mdb_flush();
21497c478bd9Sstevel@tonic-gate 		if (opt_a)
21507c478bd9Sstevel@tonic-gate 			mdb_printf("%-#32p%8T%s%", addr, buf);
2151af7034caSss 		else if (opt_b)
21524cf73299SJosef 'Jeff' Sipek 			mdb_printf("%-#?p  %-#32a%8T%s", addr, addr, buf);
21537c478bd9Sstevel@tonic-gate 		else
21547c478bd9Sstevel@tonic-gate 			mdb_printf("%-#32a%8T%s%", addr, buf);
21557c478bd9Sstevel@tonic-gate 		mdb_printf("%</b>\n");
21567c478bd9Sstevel@tonic-gate 
21577c478bd9Sstevel@tonic-gate 		for (addr = naddr; n-- != 0; addr = naddr) {
21587c478bd9Sstevel@tonic-gate 			naddr = mdb_dis_ins2str(dis, tgt, as,
21597c478bd9Sstevel@tonic-gate 			    buf, sizeof (buf), addr);
21607c478bd9Sstevel@tonic-gate 			if (naddr == addr)
21617c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
21627c478bd9Sstevel@tonic-gate 			if (opt_a)
21637c478bd9Sstevel@tonic-gate 				mdb_printf("%-#32p%8T%s\n", addr, buf);
2164af7034caSss 			else if (opt_b)
21654cf73299SJosef 'Jeff' Sipek 				mdb_printf("%-#?p  %-#32a%8T%s\n",
2166af7034caSss 				    addr, addr, buf);
21677c478bd9Sstevel@tonic-gate 			else
21687c478bd9Sstevel@tonic-gate 				mdb_printf("%-#32a%8T%s\n", addr, buf);
21697c478bd9Sstevel@tonic-gate 		}
21707c478bd9Sstevel@tonic-gate 	}
21717c478bd9Sstevel@tonic-gate 
21727c478bd9Sstevel@tonic-gate 	mdb_set_dot(addr);
21737c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
21747c478bd9Sstevel@tonic-gate }
21757c478bd9Sstevel@tonic-gate 
21767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
21777c478bd9Sstevel@tonic-gate static int
walk_step(uintptr_t addr,const void * data,void * private)21787c478bd9Sstevel@tonic-gate walk_step(uintptr_t addr, const void *data, void *private)
21797c478bd9Sstevel@tonic-gate {
218028e4da25SMatthew Ahrens 	mdb_printf("%#lr\n", addr);
21817c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
21827c478bd9Sstevel@tonic-gate }
21837c478bd9Sstevel@tonic-gate 
21847c478bd9Sstevel@tonic-gate static int
cmd_walk(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)21857c478bd9Sstevel@tonic-gate cmd_walk(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
21867c478bd9Sstevel@tonic-gate {
21877c478bd9Sstevel@tonic-gate 	int status;
21887c478bd9Sstevel@tonic-gate 
21897c478bd9Sstevel@tonic-gate 	if (argc < 1 || argc > 2 || argv[0].a_type != MDB_TYPE_STRING ||
21907c478bd9Sstevel@tonic-gate 	    argv[argc - 1].a_type != MDB_TYPE_STRING)
21917c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 	if (argc > 1) {
21947c478bd9Sstevel@tonic-gate 		const char *name = argv[1].a_un.a_str;
21957c478bd9Sstevel@tonic-gate 		mdb_var_t *v = mdb_nv_lookup(&mdb.m_nv, name);
21967c478bd9Sstevel@tonic-gate 		const char *p;
21977c478bd9Sstevel@tonic-gate 
21987c478bd9Sstevel@tonic-gate 		if (v != NULL && (v->v_flags & MDB_NV_RDONLY) != 0) {
21997c478bd9Sstevel@tonic-gate 			mdb_warn("variable %s is read-only\n", name);
22007c478bd9Sstevel@tonic-gate 			return (DCMD_ABORT);
22017c478bd9Sstevel@tonic-gate 		}
22027c478bd9Sstevel@tonic-gate 
22037c478bd9Sstevel@tonic-gate 		if (v == NULL && (p = strbadid(name)) != NULL) {
22047c478bd9Sstevel@tonic-gate 			mdb_warn("'%c' may not be used in a variable "
22057c478bd9Sstevel@tonic-gate 			    "name\n", *p);
22067c478bd9Sstevel@tonic-gate 			return (DCMD_ABORT);
22077c478bd9Sstevel@tonic-gate 		}
22087c478bd9Sstevel@tonic-gate 
22097c478bd9Sstevel@tonic-gate 		if (v == NULL && (v = mdb_nv_insert(&mdb.m_nv,
22107c478bd9Sstevel@tonic-gate 		    name, NULL, 0, 0)) == NULL)
22117c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
22127c478bd9Sstevel@tonic-gate 
22137c478bd9Sstevel@tonic-gate 		/*
22147c478bd9Sstevel@tonic-gate 		 * If there already exists a vcb for this variable, we may be
22157c478bd9Sstevel@tonic-gate 		 * calling ::walk in a loop.  We only create a vcb for this
22167c478bd9Sstevel@tonic-gate 		 * variable on the first invocation.
22177c478bd9Sstevel@tonic-gate 		 */
22187c478bd9Sstevel@tonic-gate 		if (mdb_vcb_find(v, mdb.m_frame) == NULL)
22197c478bd9Sstevel@tonic-gate 			mdb_vcb_insert(mdb_vcb_create(v), mdb.m_frame);
22207c478bd9Sstevel@tonic-gate 	}
22217c478bd9Sstevel@tonic-gate 
22227c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
22237c478bd9Sstevel@tonic-gate 		status = mdb_pwalk(argv->a_un.a_str, walk_step, NULL, addr);
22247c478bd9Sstevel@tonic-gate 	else
22257c478bd9Sstevel@tonic-gate 		status = mdb_walk(argv->a_un.a_str, walk_step, NULL);
22267c478bd9Sstevel@tonic-gate 
22277c478bd9Sstevel@tonic-gate 	if (status == -1) {
22287c478bd9Sstevel@tonic-gate 		mdb_warn("failed to perform walk");
22297c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
22307c478bd9Sstevel@tonic-gate 	}
22317c478bd9Sstevel@tonic-gate 
22327c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
22337c478bd9Sstevel@tonic-gate }
22347c478bd9Sstevel@tonic-gate 
22353b6e0a59SMatt Amdur static int
cmd_walk_tab(mdb_tab_cookie_t * mcp,uint_t flags,int argc,const mdb_arg_t * argv)22363b6e0a59SMatt Amdur cmd_walk_tab(mdb_tab_cookie_t *mcp, uint_t flags, int argc,
22373b6e0a59SMatt Amdur     const mdb_arg_t *argv)
22383b6e0a59SMatt Amdur {
22393b6e0a59SMatt Amdur 	if (argc > 1)
22403b6e0a59SMatt Amdur 		return (1);
22413b6e0a59SMatt Amdur 
22423b6e0a59SMatt Amdur 	if (argc == 1) {
22433b6e0a59SMatt Amdur 		ASSERT(argv[0].a_type == MDB_TYPE_STRING);
22443b6e0a59SMatt Amdur 		return (mdb_tab_complete_walker(mcp, argv[0].a_un.a_str));
22453b6e0a59SMatt Amdur 	}
22463b6e0a59SMatt Amdur 
22473b6e0a59SMatt Amdur 	if (argc == 0 && flags & DCMD_TAB_SPACE)
22483b6e0a59SMatt Amdur 		return (mdb_tab_complete_walker(mcp, NULL));
22493b6e0a59SMatt Amdur 
22503b6e0a59SMatt Amdur 	return (1);
22513b6e0a59SMatt Amdur }
22523b6e0a59SMatt Amdur 
22537c478bd9Sstevel@tonic-gate static ssize_t
mdb_partial_xread(void * buf,size_t nbytes,uintptr_t addr,void * arg)22547c478bd9Sstevel@tonic-gate mdb_partial_xread(void *buf, size_t nbytes, uintptr_t addr, void *arg)
22557c478bd9Sstevel@tonic-gate {
22567c478bd9Sstevel@tonic-gate 	ssize_t (*fp)(mdb_tgt_t *, const void *, size_t, uintptr_t) =
22577c478bd9Sstevel@tonic-gate 	    (ssize_t (*)(mdb_tgt_t *, const void *, size_t, uintptr_t))arg;
22587c478bd9Sstevel@tonic-gate 
22597c478bd9Sstevel@tonic-gate 	return (fp(mdb.m_target, buf, nbytes, addr));
22607c478bd9Sstevel@tonic-gate }
22617c478bd9Sstevel@tonic-gate 
22627c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
22637c478bd9Sstevel@tonic-gate static ssize_t
mdb_partial_pread(void * buf,size_t nbytes,physaddr_t addr,void * arg)22647c478bd9Sstevel@tonic-gate mdb_partial_pread(void *buf, size_t nbytes, physaddr_t addr, void *arg)
22657c478bd9Sstevel@tonic-gate {
22667c478bd9Sstevel@tonic-gate 	return (mdb_tgt_pread(mdb.m_target, buf, nbytes, addr));
22677c478bd9Sstevel@tonic-gate }
22687c478bd9Sstevel@tonic-gate 
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate static int
cmd_dump(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)22717c478bd9Sstevel@tonic-gate cmd_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
22727c478bd9Sstevel@tonic-gate {
22737c478bd9Sstevel@tonic-gate 	uint_t dflags =
22747c478bd9Sstevel@tonic-gate 	    MDB_DUMP_ALIGN | MDB_DUMP_NEWDOT | MDB_DUMP_ASCII | MDB_DUMP_HEADER;
22757c478bd9Sstevel@tonic-gate 	uint_t phys = FALSE;
22767c478bd9Sstevel@tonic-gate 	uint_t file = FALSE;
22777c478bd9Sstevel@tonic-gate 	uintptr_t group = 4;
2278f11ba53fSDan Kimmel 	uintptr_t length = 0;
22797c478bd9Sstevel@tonic-gate 	uintptr_t width = 1;
22807c478bd9Sstevel@tonic-gate 	mdb_tgt_status_t st;
22817c478bd9Sstevel@tonic-gate 	int error;
22827c478bd9Sstevel@tonic-gate 
22837c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
22847c478bd9Sstevel@tonic-gate 	    'e', MDB_OPT_SETBITS, MDB_DUMP_ENDIAN, &dflags,
22857c478bd9Sstevel@tonic-gate 	    'f', MDB_OPT_SETBITS, TRUE, &file,
22867c478bd9Sstevel@tonic-gate 	    'g', MDB_OPT_UINTPTR, &group,
2287f11ba53fSDan Kimmel 	    'l', MDB_OPT_UINTPTR, &length,
22887c478bd9Sstevel@tonic-gate 	    'p', MDB_OPT_SETBITS, TRUE, &phys,
22897c478bd9Sstevel@tonic-gate 	    'q', MDB_OPT_CLRBITS, MDB_DUMP_ASCII, &dflags,
22907c478bd9Sstevel@tonic-gate 	    'r', MDB_OPT_SETBITS, MDB_DUMP_RELATIVE, &dflags,
22917c478bd9Sstevel@tonic-gate 	    's', MDB_OPT_SETBITS, MDB_DUMP_SQUISH, &dflags,
22927c478bd9Sstevel@tonic-gate 	    't', MDB_OPT_SETBITS, MDB_DUMP_TRIM, &dflags,
22937c478bd9Sstevel@tonic-gate 	    'u', MDB_OPT_CLRBITS, MDB_DUMP_ALIGN, &dflags,
22947c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, MDB_DUMP_PEDANT, &dflags,
22957c478bd9Sstevel@tonic-gate 	    'w', MDB_OPT_UINTPTR, &width, NULL) != argc)
22967c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
22977c478bd9Sstevel@tonic-gate 
22987c478bd9Sstevel@tonic-gate 	if ((phys && file) ||
22997c478bd9Sstevel@tonic-gate 	    (width == 0) || (width > 0x10) ||
2300f11ba53fSDan Kimmel 	    (group == 0) || (group > 0x100) ||
2301f11ba53fSDan Kimmel 	    (mdb.m_dcount > 1 && length > 0))
23027c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
2303f11ba53fSDan Kimmel 	if (length == 0)
2304f11ba53fSDan Kimmel 		length = mdb.m_dcount;
23057c478bd9Sstevel@tonic-gate 
23067c478bd9Sstevel@tonic-gate 	/*
23077c478bd9Sstevel@tonic-gate 	 * If neither -f nor -p were specified and the state is IDLE (i.e. no
23087c478bd9Sstevel@tonic-gate 	 * address space), turn on -p.  This is so we can read large files.
23097c478bd9Sstevel@tonic-gate 	 */
23107c478bd9Sstevel@tonic-gate 	if (phys == FALSE && file == FALSE && mdb_tgt_status(mdb.m_target,
23117c478bd9Sstevel@tonic-gate 	    &st) == 0 && st.st_state == MDB_TGT_IDLE)
23127c478bd9Sstevel@tonic-gate 		phys = TRUE;
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	dflags |= MDB_DUMP_GROUP(group) | MDB_DUMP_WIDTH(width);
23157c478bd9Sstevel@tonic-gate 	if (phys)
2316f11ba53fSDan Kimmel 		error = mdb_dump64(mdb_get_dot(), length, dflags,
23177c478bd9Sstevel@tonic-gate 		    mdb_partial_pread, NULL);
23187c478bd9Sstevel@tonic-gate 	else if (file)
2319f11ba53fSDan Kimmel 		error = mdb_dumpptr(addr, length, dflags,
23207c478bd9Sstevel@tonic-gate 		    mdb_partial_xread, (void *)mdb_tgt_fread);
23217c478bd9Sstevel@tonic-gate 	else
2322f11ba53fSDan Kimmel 		error = mdb_dumpptr(addr, length, dflags,
23237c478bd9Sstevel@tonic-gate 		    mdb_partial_xread, (void *)mdb_tgt_vread);
23247c478bd9Sstevel@tonic-gate 
23257c478bd9Sstevel@tonic-gate 	return (((flags & DCMD_LOOP) || (error == -1)) ? DCMD_ABORT : DCMD_OK);
23267c478bd9Sstevel@tonic-gate }
23277c478bd9Sstevel@tonic-gate 
23287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
23297c478bd9Sstevel@tonic-gate static int
cmd_echo(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)23307c478bd9Sstevel@tonic-gate cmd_echo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
23317c478bd9Sstevel@tonic-gate {
23327c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
23337c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
23347c478bd9Sstevel@tonic-gate 
23357c478bd9Sstevel@tonic-gate 	for (; argc-- != 0; argv++) {
23367c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_STRING)
23377c478bd9Sstevel@tonic-gate 			mdb_printf("%s ", argv->a_un.a_str);
23387c478bd9Sstevel@tonic-gate 		else
23397c478bd9Sstevel@tonic-gate 			mdb_printf("%llr ", argv->a_un.a_val);
23407c478bd9Sstevel@tonic-gate 	}
23417c478bd9Sstevel@tonic-gate 
23427c478bd9Sstevel@tonic-gate 	mdb_printf("\n");
23437c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
23447c478bd9Sstevel@tonic-gate }
23457c478bd9Sstevel@tonic-gate 
23467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
23477c478bd9Sstevel@tonic-gate static int
cmd_head(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)23487c478bd9Sstevel@tonic-gate cmd_head(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
23497c478bd9Sstevel@tonic-gate {
23507c478bd9Sstevel@tonic-gate 	uint64_t cnt = 10;
23517c478bd9Sstevel@tonic-gate 	const char *c;
23527c478bd9Sstevel@tonic-gate 	mdb_pipe_t p;
23537c478bd9Sstevel@tonic-gate 
2354d75f3745SJohn Levon 	if (!(flags & DCMD_PIPE))
23557c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
23567c478bd9Sstevel@tonic-gate 
23577c478bd9Sstevel@tonic-gate 	if (argc == 1 || argc == 2) {
23587c478bd9Sstevel@tonic-gate 		const char *num;
23597c478bd9Sstevel@tonic-gate 
23607c478bd9Sstevel@tonic-gate 		if (argc == 1) {
23617c478bd9Sstevel@tonic-gate 			if (argv[0].a_type != MDB_TYPE_STRING ||
23627c478bd9Sstevel@tonic-gate 			    *argv[0].a_un.a_str != '-')
23637c478bd9Sstevel@tonic-gate 				return (DCMD_USAGE);
23647c478bd9Sstevel@tonic-gate 
23657c478bd9Sstevel@tonic-gate 			num = argv[0].a_un.a_str + 1;
23667c478bd9Sstevel@tonic-gate 
23677c478bd9Sstevel@tonic-gate 		} else {
23687c478bd9Sstevel@tonic-gate 			if (argv[0].a_type != MDB_TYPE_STRING ||
23697c478bd9Sstevel@tonic-gate 			    strcmp(argv[0].a_un.a_str, "-n") != 0)
23707c478bd9Sstevel@tonic-gate 				return (DCMD_USAGE);
23717c478bd9Sstevel@tonic-gate 
23727c478bd9Sstevel@tonic-gate 			num = argv[1].a_un.a_str;
23737c478bd9Sstevel@tonic-gate 		}
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate 		for (cnt = 0, c = num; *c != '\0' && isdigit(*c); c++)
23767c478bd9Sstevel@tonic-gate 			cnt = cnt * 10 + (*c - '0');
23777c478bd9Sstevel@tonic-gate 
23787c478bd9Sstevel@tonic-gate 		if (*c != '\0')
23797c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
23807c478bd9Sstevel@tonic-gate 
23817c478bd9Sstevel@tonic-gate 	} else if (argc != 0) {
23827c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
23837c478bd9Sstevel@tonic-gate 	}
23847c478bd9Sstevel@tonic-gate 
23857c478bd9Sstevel@tonic-gate 	mdb_get_pipe(&p);
23867c478bd9Sstevel@tonic-gate 
23877c478bd9Sstevel@tonic-gate 	if (p.pipe_data == NULL)
23887c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
23897c478bd9Sstevel@tonic-gate 	p.pipe_len = MIN(p.pipe_len, cnt);
23907c478bd9Sstevel@tonic-gate 
23917c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT) {
23927c478bd9Sstevel@tonic-gate 		mdb_set_pipe(&p);
23937c478bd9Sstevel@tonic-gate 	} else {
23947c478bd9Sstevel@tonic-gate 		while (p.pipe_len-- > 0)
23957c478bd9Sstevel@tonic-gate 			mdb_printf("%lx\n", *p.pipe_data++);
23967c478bd9Sstevel@tonic-gate 	}
23977c478bd9Sstevel@tonic-gate 
23987c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
23997c478bd9Sstevel@tonic-gate }
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate static void
head_help(void)24027c478bd9Sstevel@tonic-gate head_help(void)
24037c478bd9Sstevel@tonic-gate {
24047c478bd9Sstevel@tonic-gate 	mdb_printf(
24057c478bd9Sstevel@tonic-gate 	    "-n num\n or\n"
24067c478bd9Sstevel@tonic-gate 	    "-num   pass only the first `num' elements in the pipe.\n"
24077c478bd9Sstevel@tonic-gate 	    "\n%<b>Note:%</b> `num' is a decimal number.\n");
24087c478bd9Sstevel@tonic-gate }
24097c478bd9Sstevel@tonic-gate 
24107c478bd9Sstevel@tonic-gate static int
cmd_typeset(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)24117c478bd9Sstevel@tonic-gate cmd_typeset(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
24127c478bd9Sstevel@tonic-gate {
24137c478bd9Sstevel@tonic-gate 	int add_tag = 0, del_tag = 0;
24147c478bd9Sstevel@tonic-gate 	const char *p;
24157c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
24167c478bd9Sstevel@tonic-gate 
24177c478bd9Sstevel@tonic-gate 	if (argc == 0)
24187c478bd9Sstevel@tonic-gate 		return (cmd_vars(addr, flags, argc, argv));
24197c478bd9Sstevel@tonic-gate 
24207c478bd9Sstevel@tonic-gate 	if (argv->a_type == MDB_TYPE_STRING && (argv->a_un.a_str[0] == '-' ||
24217c478bd9Sstevel@tonic-gate 	    argv->a_un.a_str[0] == '+')) {
24227c478bd9Sstevel@tonic-gate 		if (argv->a_un.a_str[1] != 't')
24237c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
24247c478bd9Sstevel@tonic-gate 		if (argv->a_un.a_str[0] == '-')
24257c478bd9Sstevel@tonic-gate 			add_tag++;
24267c478bd9Sstevel@tonic-gate 		else
24277c478bd9Sstevel@tonic-gate 			del_tag++;
24287c478bd9Sstevel@tonic-gate 		argc--;
24297c478bd9Sstevel@tonic-gate 		argv++;
24307c478bd9Sstevel@tonic-gate 	}
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
24337c478bd9Sstevel@tonic-gate 		addr = 0; /* set variables to zero unless explicit addr given */
24347c478bd9Sstevel@tonic-gate 
24357c478bd9Sstevel@tonic-gate 	for (; argc-- != 0; argv++) {
24367c478bd9Sstevel@tonic-gate 		if (argv->a_type != MDB_TYPE_STRING)
24377c478bd9Sstevel@tonic-gate 			continue;
24387c478bd9Sstevel@tonic-gate 
24397c478bd9Sstevel@tonic-gate 		if (argv->a_un.a_str[0] == '-' || argv->a_un.a_str[0] == '+') {
24407c478bd9Sstevel@tonic-gate 			mdb_warn("ignored bad option -- %s\n",
24417c478bd9Sstevel@tonic-gate 			    argv->a_un.a_str);
24427c478bd9Sstevel@tonic-gate 			continue;
24437c478bd9Sstevel@tonic-gate 		}
24447c478bd9Sstevel@tonic-gate 
24457c478bd9Sstevel@tonic-gate 		if ((p = strbadid(argv->a_un.a_str)) != NULL) {
24467c478bd9Sstevel@tonic-gate 			mdb_warn("'%c' may not be used in a variable "
24477c478bd9Sstevel@tonic-gate 			    "name\n", *p);
24487c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
24497c478bd9Sstevel@tonic-gate 		}
24507c478bd9Sstevel@tonic-gate 
24517c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&mdb.m_nv, argv->a_un.a_str)) == NULL) {
24527c478bd9Sstevel@tonic-gate 			v = mdb_nv_insert(&mdb.m_nv, argv->a_un.a_str,
24537c478bd9Sstevel@tonic-gate 			    NULL, addr, 0);
24547c478bd9Sstevel@tonic-gate 		} else if (flags & DCMD_ADDRSPEC)
24557c478bd9Sstevel@tonic-gate 			mdb_nv_set_value(v, addr);
24567c478bd9Sstevel@tonic-gate 
24577c478bd9Sstevel@tonic-gate 		if (v != NULL) {
24587c478bd9Sstevel@tonic-gate 			if (add_tag)
24597c478bd9Sstevel@tonic-gate 				v->v_flags |= MDB_NV_TAGGED;
24607c478bd9Sstevel@tonic-gate 			if (del_tag)
24617c478bd9Sstevel@tonic-gate 				v->v_flags &= ~MDB_NV_TAGGED;
24627c478bd9Sstevel@tonic-gate 		}
24637c478bd9Sstevel@tonic-gate 	}
24647c478bd9Sstevel@tonic-gate 
24657c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
24667c478bd9Sstevel@tonic-gate }
24677c478bd9Sstevel@tonic-gate 
24687c478bd9Sstevel@tonic-gate #ifndef _KMDB
24697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24707c478bd9Sstevel@tonic-gate static int
cmd_context(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)24717c478bd9Sstevel@tonic-gate cmd_context(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
24727c478bd9Sstevel@tonic-gate {
24737c478bd9Sstevel@tonic-gate 	if (argc != 0 || !(flags & DCMD_ADDRSPEC))
24747c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
24757c478bd9Sstevel@tonic-gate 
24767c478bd9Sstevel@tonic-gate 	if (mdb_tgt_setcontext(mdb.m_target, (void *)addr) == 0)
24777c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
24787c478bd9Sstevel@tonic-gate 
24797c478bd9Sstevel@tonic-gate 	return (DCMD_ERR);
24807c478bd9Sstevel@tonic-gate }
24817c478bd9Sstevel@tonic-gate #endif
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24847c478bd9Sstevel@tonic-gate static int
cmd_prompt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)24857c478bd9Sstevel@tonic-gate cmd_prompt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
24867c478bd9Sstevel@tonic-gate {
24877c478bd9Sstevel@tonic-gate 	const char *p = "";
24887c478bd9Sstevel@tonic-gate 
24897c478bd9Sstevel@tonic-gate 	if (argc != 0) {
24907c478bd9Sstevel@tonic-gate 		if (argc > 1 || argv->a_type != MDB_TYPE_STRING)
24917c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
24927c478bd9Sstevel@tonic-gate 		p = argv->a_un.a_str;
24937c478bd9Sstevel@tonic-gate 	}
24947c478bd9Sstevel@tonic-gate 
24957c478bd9Sstevel@tonic-gate 	(void) mdb_set_prompt(p);
24967c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
24977c478bd9Sstevel@tonic-gate }
24987c478bd9Sstevel@tonic-gate 
24997c478bd9Sstevel@tonic-gate /*ARGSUSED*/
25007c478bd9Sstevel@tonic-gate static int
cmd_term(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)25017c478bd9Sstevel@tonic-gate cmd_term(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
25027c478bd9Sstevel@tonic-gate {
25037c478bd9Sstevel@tonic-gate 	mdb_printf("%s\n", mdb.m_termtype);
25047c478bd9Sstevel@tonic-gate 
25057c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
25067c478bd9Sstevel@tonic-gate }
25077c478bd9Sstevel@tonic-gate 
25087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
25097c478bd9Sstevel@tonic-gate static int
cmd_vtop(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)25107c478bd9Sstevel@tonic-gate cmd_vtop(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
25117c478bd9Sstevel@tonic-gate {
25127c478bd9Sstevel@tonic-gate 	physaddr_t pa;
25137c478bd9Sstevel@tonic-gate 	mdb_tgt_as_t as = MDB_TGT_AS_VIRT;
25147c478bd9Sstevel@tonic-gate 
25157c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv, 'a', MDB_OPT_UINTPTR, (uintptr_t *)&as,
25167c478bd9Sstevel@tonic-gate 	    NULL) != argc)
25177c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
25187c478bd9Sstevel@tonic-gate 
25197c478bd9Sstevel@tonic-gate 	if (mdb_tgt_vtop(mdb.m_target, as, addr, &pa) == -1) {
25207c478bd9Sstevel@tonic-gate 		mdb_warn("failed to get physical mapping");
25217c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
25227c478bd9Sstevel@tonic-gate 	}
25237c478bd9Sstevel@tonic-gate 
25247c478bd9Sstevel@tonic-gate 	if (flags & DCMD_PIPE_OUT)
25257c478bd9Sstevel@tonic-gate 		mdb_printf("%llr\n", pa);
25267c478bd9Sstevel@tonic-gate 	else
25277c478bd9Sstevel@tonic-gate 		mdb_printf("virtual %lr mapped to physical %llr\n", addr, pa);
25287c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
25297c478bd9Sstevel@tonic-gate }
25307c478bd9Sstevel@tonic-gate 
25317c478bd9Sstevel@tonic-gate #define	EVENTS_OPT_A	0x1	/* ::events -a (show all events) */
25327c478bd9Sstevel@tonic-gate #define	EVENTS_OPT_V	0x2	/* ::events -v (verbose display) */
25337c478bd9Sstevel@tonic-gate 
25347c478bd9Sstevel@tonic-gate static const char *
event_action(const mdb_tgt_spec_desc_t * sp)25357c478bd9Sstevel@tonic-gate event_action(const mdb_tgt_spec_desc_t *sp)
25367c478bd9Sstevel@tonic-gate {
25377c478bd9Sstevel@tonic-gate 	if (!(sp->spec_flags & MDB_TGT_SPEC_HIDDEN) && sp->spec_data != NULL)
25387c478bd9Sstevel@tonic-gate 		return (sp->spec_data);
25397c478bd9Sstevel@tonic-gate 
25407c478bd9Sstevel@tonic-gate 	return ("-");
25417c478bd9Sstevel@tonic-gate }
25427c478bd9Sstevel@tonic-gate 
25437c478bd9Sstevel@tonic-gate static void
print_evsep(void)25447c478bd9Sstevel@tonic-gate print_evsep(void)
25457c478bd9Sstevel@tonic-gate {
25467c478bd9Sstevel@tonic-gate 	static const char dash20[] = "--------------------";
25477c478bd9Sstevel@tonic-gate 	mdb_printf("----- - -- -- -- %s%s --%s\n", dash20, dash20, dash20);
25487c478bd9Sstevel@tonic-gate }
25497c478bd9Sstevel@tonic-gate 
25507c478bd9Sstevel@tonic-gate /*ARGSUSED*/
25517c478bd9Sstevel@tonic-gate static int
print_event(mdb_tgt_t * t,void * private,int vid,void * data)25527c478bd9Sstevel@tonic-gate print_event(mdb_tgt_t *t, void *private, int vid, void *data)
25537c478bd9Sstevel@tonic-gate {
25547c478bd9Sstevel@tonic-gate 	uint_t opts = (uint_t)(uintptr_t)private;
25557c478bd9Sstevel@tonic-gate 	mdb_tgt_spec_desc_t sp;
25567c478bd9Sstevel@tonic-gate 	char s1[41], s2[22];
25577c478bd9Sstevel@tonic-gate 	const char *s2str;
25587c478bd9Sstevel@tonic-gate 	int visible;
25597c478bd9Sstevel@tonic-gate 
25607c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_vespec_info(t, vid, &sp, s1, sizeof (s1));
25617c478bd9Sstevel@tonic-gate 	visible = !(sp.spec_flags & (MDB_TGT_SPEC_HIDDEN|MDB_TGT_SPEC_DELETED));
25627c478bd9Sstevel@tonic-gate 
25637c478bd9Sstevel@tonic-gate 	if ((opts & EVENTS_OPT_A) || visible) {
25647c478bd9Sstevel@tonic-gate 		int encoding = (!(sp.spec_flags & MDB_TGT_SPEC_DISABLED)) |
25657c478bd9Sstevel@tonic-gate 		    (!(sp.spec_flags & MDB_TGT_SPEC_MATCHED) << 1);
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate 		char ldelim = "<<(["[encoding];
25687c478bd9Sstevel@tonic-gate 		char rdelim = ">>)]"[encoding];
25697c478bd9Sstevel@tonic-gate 
25707c478bd9Sstevel@tonic-gate 		char state = "0-+*!"[sp.spec_state];
25717c478bd9Sstevel@tonic-gate 
25727c478bd9Sstevel@tonic-gate 		char tflag = "T "[!(sp.spec_flags & MDB_TGT_SPEC_STICKY)];
25737c478bd9Sstevel@tonic-gate 		char aflag = "d "[!(sp.spec_flags & MDB_TGT_SPEC_AUTODIS)];
25747c478bd9Sstevel@tonic-gate 
25757c478bd9Sstevel@tonic-gate 		if (sp.spec_flags & MDB_TGT_SPEC_TEMPORARY)
25767c478bd9Sstevel@tonic-gate 			tflag = 't'; /* TEMP takes precedence over STICKY */
25777c478bd9Sstevel@tonic-gate 		if (sp.spec_flags & MDB_TGT_SPEC_AUTODEL)
25787c478bd9Sstevel@tonic-gate 			aflag = 'D'; /* AUTODEL takes precedence over AUTODIS */
25797c478bd9Sstevel@tonic-gate 		if (sp.spec_flags & MDB_TGT_SPEC_AUTOSTOP)
25807c478bd9Sstevel@tonic-gate 			aflag = 's'; /* AUTOSTOP takes precedence over both */
25817c478bd9Sstevel@tonic-gate 
25827c478bd9Sstevel@tonic-gate 		if (opts & EVENTS_OPT_V) {
25837c478bd9Sstevel@tonic-gate 			if (sp.spec_state == MDB_TGT_SPEC_IDLE ||
25847c478bd9Sstevel@tonic-gate 			    sp.spec_state == MDB_TGT_SPEC_ERROR)
25857c478bd9Sstevel@tonic-gate 				s2str = mdb_strerror(sp.spec_errno);
25867c478bd9Sstevel@tonic-gate 			else
25877c478bd9Sstevel@tonic-gate 				s2str = "-";
25887c478bd9Sstevel@tonic-gate 		} else
25897c478bd9Sstevel@tonic-gate 			s2str = event_action(&sp);
25907c478bd9Sstevel@tonic-gate 
25917c478bd9Sstevel@tonic-gate 		if (mdb_snprintf(s2, sizeof (s2), "%s", s2str) >= sizeof (s2))
25927c478bd9Sstevel@tonic-gate 			(void) strabbr(s2, sizeof (s2));
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 		if (vid > -10 && vid < 10)
25957c478bd9Sstevel@tonic-gate 			mdb_printf("%c%2d %c", ldelim, vid, rdelim);
25967c478bd9Sstevel@tonic-gate 		else
25977c478bd9Sstevel@tonic-gate 			mdb_printf("%c%3d%c", ldelim, vid, rdelim);
25987c478bd9Sstevel@tonic-gate 
25997c478bd9Sstevel@tonic-gate 		mdb_printf(" %c %c%c %2u %2u %-40s %-21s\n",
26007c478bd9Sstevel@tonic-gate 		    state, tflag, aflag, sp.spec_hits, sp.spec_limit, s1, s2);
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate 		if (opts & EVENTS_OPT_V) {
26037c478bd9Sstevel@tonic-gate 			mdb_printf("%-17s%s\n", "", event_action(&sp));
26047c478bd9Sstevel@tonic-gate 			print_evsep();
26057c478bd9Sstevel@tonic-gate 		}
26067c478bd9Sstevel@tonic-gate 	}
26077c478bd9Sstevel@tonic-gate 
26087c478bd9Sstevel@tonic-gate 	return (0);
26097c478bd9Sstevel@tonic-gate }
26107c478bd9Sstevel@tonic-gate 
26117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
26127c478bd9Sstevel@tonic-gate static int
cmd_events(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)26137c478bd9Sstevel@tonic-gate cmd_events(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
26147c478bd9Sstevel@tonic-gate {
26157c478bd9Sstevel@tonic-gate 	uint_t opts = 0;
26167c478bd9Sstevel@tonic-gate 
26177c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv,
26187c478bd9Sstevel@tonic-gate 	    'a', MDB_OPT_SETBITS, EVENTS_OPT_A, &opts,
26197c478bd9Sstevel@tonic-gate 	    'v', MDB_OPT_SETBITS, EVENTS_OPT_V, &opts, NULL) != argc)
26207c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
26217c478bd9Sstevel@tonic-gate 
26227c478bd9Sstevel@tonic-gate 
26237c478bd9Sstevel@tonic-gate 	if (opts & EVENTS_OPT_V) {
26247c478bd9Sstevel@tonic-gate 		mdb_printf("   ID S TA HT LM %-40s %-21s\n%-17s%s\n",
26257c478bd9Sstevel@tonic-gate 		    "Description", "Status", "", "Action");
26267c478bd9Sstevel@tonic-gate 	} else {
26277c478bd9Sstevel@tonic-gate 		mdb_printf("   ID S TA HT LM %-40s %-21s\n",
26287c478bd9Sstevel@tonic-gate 		    "Description", "Action");
26297c478bd9Sstevel@tonic-gate 	}
26307c478bd9Sstevel@tonic-gate 
26317c478bd9Sstevel@tonic-gate 	print_evsep();
26327c478bd9Sstevel@tonic-gate 	return (mdb_tgt_vespec_iter(mdb.m_target, print_event,
26337c478bd9Sstevel@tonic-gate 	    (void *)(uintptr_t)opts));
26347c478bd9Sstevel@tonic-gate }
26357c478bd9Sstevel@tonic-gate 
26367c478bd9Sstevel@tonic-gate static int
tgt_status(const mdb_tgt_status_t * tsp)26377c478bd9Sstevel@tonic-gate tgt_status(const mdb_tgt_status_t *tsp)
26387c478bd9Sstevel@tonic-gate {
26397c478bd9Sstevel@tonic-gate 	const char *format;
26407c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];
26417c478bd9Sstevel@tonic-gate 
26427c478bd9Sstevel@tonic-gate 	if (tsp->st_flags & MDB_TGT_BUSY)
26437c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
26447c478bd9Sstevel@tonic-gate 
26457c478bd9Sstevel@tonic-gate 	if (tsp->st_pc != 0) {
26469c3024a3SHans Rosenfeld 		if (mdb_dis_ins2str(mdb.m_disasm, mdb.m_target,
26479c3024a3SHans Rosenfeld 		    MDB_TGT_AS_VIRT_I, buf, sizeof (buf), tsp->st_pc) !=
26489c3024a3SHans Rosenfeld 		    tsp->st_pc)
26497c478bd9Sstevel@tonic-gate 			format = "target stopped at:\n%-#16a%8T%s\n";
26507c478bd9Sstevel@tonic-gate 		else
26517c478bd9Sstevel@tonic-gate 			format = "target stopped at %a:\n";
26527c478bd9Sstevel@tonic-gate 		mdb_warn(format, tsp->st_pc, buf);
26537c478bd9Sstevel@tonic-gate 	}
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate 	switch (tsp->st_state) {
26567c478bd9Sstevel@tonic-gate 	case MDB_TGT_IDLE:
26577c478bd9Sstevel@tonic-gate 		mdb_warn("target is idle\n");
26587c478bd9Sstevel@tonic-gate 		break;
26597c478bd9Sstevel@tonic-gate 	case MDB_TGT_RUNNING:
26607c478bd9Sstevel@tonic-gate 		if (tsp->st_flags & MDB_TGT_DSTOP)
26617c478bd9Sstevel@tonic-gate 			mdb_warn("target is running, stop directive pending\n");
26627c478bd9Sstevel@tonic-gate 		else
26637c478bd9Sstevel@tonic-gate 			mdb_warn("target is running\n");
26647c478bd9Sstevel@tonic-gate 		break;
26657c478bd9Sstevel@tonic-gate 	case MDB_TGT_STOPPED:
26667c478bd9Sstevel@tonic-gate 		if (tsp->st_pc == 0)
26677c478bd9Sstevel@tonic-gate 			mdb_warn("target is stopped\n");
26687c478bd9Sstevel@tonic-gate 		break;
26697c478bd9Sstevel@tonic-gate 	case MDB_TGT_UNDEAD:
26707c478bd9Sstevel@tonic-gate 		mdb_warn("target has terminated\n");
26717c478bd9Sstevel@tonic-gate 		break;
26727c478bd9Sstevel@tonic-gate 	case MDB_TGT_DEAD:
26737c478bd9Sstevel@tonic-gate 		mdb_warn("target is a core dump\n");
26747c478bd9Sstevel@tonic-gate 		break;
26757c478bd9Sstevel@tonic-gate 	case MDB_TGT_LOST:
26767c478bd9Sstevel@tonic-gate 		mdb_warn("target is no longer under debugger control\n");
26777c478bd9Sstevel@tonic-gate 		break;
26787c478bd9Sstevel@tonic-gate 	}
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	mdb_set_dot(tsp->st_pc);
26817c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
26827c478bd9Sstevel@tonic-gate }
26837c478bd9Sstevel@tonic-gate 
26847c478bd9Sstevel@tonic-gate /*
26857c478bd9Sstevel@tonic-gate  * mdb continue/step commands take an optional signal argument, but the
26867c478bd9Sstevel@tonic-gate  * corresponding kmdb versions don't.
26877c478bd9Sstevel@tonic-gate  */
26887c478bd9Sstevel@tonic-gate #ifdef _KMDB
26897c478bd9Sstevel@tonic-gate #define	CONT_MAXARGS	0	/* no optional SIG argument */
26907c478bd9Sstevel@tonic-gate #else
26917c478bd9Sstevel@tonic-gate #define	CONT_MAXARGS	1
26927c478bd9Sstevel@tonic-gate #endif
26937c478bd9Sstevel@tonic-gate 
26947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
26957c478bd9Sstevel@tonic-gate static int
cmd_cont_common(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,int (* t_cont)(mdb_tgt_t *,mdb_tgt_status_t *),const char * name)26967c478bd9Sstevel@tonic-gate cmd_cont_common(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
26977c478bd9Sstevel@tonic-gate     int (*t_cont)(mdb_tgt_t *, mdb_tgt_status_t *), const char *name)
26987c478bd9Sstevel@tonic-gate {
26997c478bd9Sstevel@tonic-gate 	mdb_tgt_t *t = mdb.m_target;
27007c478bd9Sstevel@tonic-gate 	mdb_tgt_status_t st;
27017c478bd9Sstevel@tonic-gate 	int sig = 0;
27027c478bd9Sstevel@tonic-gate 
27037c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || argc > CONT_MAXARGS)
27047c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
27057c478bd9Sstevel@tonic-gate 
27067c478bd9Sstevel@tonic-gate 	if (argc > 0) {
27077c478bd9Sstevel@tonic-gate 		if (argv->a_type == MDB_TYPE_STRING) {
27087c478bd9Sstevel@tonic-gate 			if (proc_str2sig(argv->a_un.a_str, &sig) == -1) {
27097c478bd9Sstevel@tonic-gate 				mdb_warn("invalid signal name -- %s\n",
27107c478bd9Sstevel@tonic-gate 				    argv->a_un.a_str);
27117c478bd9Sstevel@tonic-gate 				return (DCMD_USAGE);
27127c478bd9Sstevel@tonic-gate 			}
27137c478bd9Sstevel@tonic-gate 		} else
27147c478bd9Sstevel@tonic-gate 			sig = (int)(intmax_t)argv->a_un.a_val;
27157c478bd9Sstevel@tonic-gate 	}
27167c478bd9Sstevel@tonic-gate 
27177c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_status(t, &st);
27187c478bd9Sstevel@tonic-gate 
27197c478bd9Sstevel@tonic-gate 	if (st.st_state == MDB_TGT_IDLE && mdb_tgt_run(t, 0, NULL) == -1) {
27207c478bd9Sstevel@tonic-gate 		if (errno != EMDB_TGT)
27217c478bd9Sstevel@tonic-gate 			mdb_warn("failed to create new target");
27227c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
27237c478bd9Sstevel@tonic-gate 	}
27247c478bd9Sstevel@tonic-gate 
27257c478bd9Sstevel@tonic-gate 	if (sig != 0 && mdb_tgt_signal(t, sig) == -1) {
27267c478bd9Sstevel@tonic-gate 		mdb_warn("failed to post signal %d", sig);
27277c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
27287c478bd9Sstevel@tonic-gate 	}
27297c478bd9Sstevel@tonic-gate 
27307c478bd9Sstevel@tonic-gate 	if (st.st_state == MDB_TGT_IDLE && t_cont == &mdb_tgt_step) {
27317c478bd9Sstevel@tonic-gate 		(void) mdb_tgt_status(t, &st);
27327c478bd9Sstevel@tonic-gate 		return (tgt_status(&st));
27337c478bd9Sstevel@tonic-gate 	}
27347c478bd9Sstevel@tonic-gate 
27357c478bd9Sstevel@tonic-gate 	if (t_cont(t, &st) == -1) {
27367c478bd9Sstevel@tonic-gate 		if (errno != EMDB_TGT)
27377c478bd9Sstevel@tonic-gate 			mdb_warn("failed to %s target", name);
27387c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
27397c478bd9Sstevel@tonic-gate 	}
27407c478bd9Sstevel@tonic-gate 
27417c478bd9Sstevel@tonic-gate 	return (tgt_status(&st));
27427c478bd9Sstevel@tonic-gate }
27437c478bd9Sstevel@tonic-gate 
27447c478bd9Sstevel@tonic-gate static int
cmd_step(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)27457c478bd9Sstevel@tonic-gate cmd_step(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
27467c478bd9Sstevel@tonic-gate {
27477c478bd9Sstevel@tonic-gate 	int (*func)(mdb_tgt_t *, mdb_tgt_status_t *) = &mdb_tgt_step;
27487c478bd9Sstevel@tonic-gate 	const char *name = "single-step";
27497c478bd9Sstevel@tonic-gate 
27507c478bd9Sstevel@tonic-gate 	if (argc > 0 && argv->a_type == MDB_TYPE_STRING) {
27517c478bd9Sstevel@tonic-gate 		if (strcmp(argv->a_un.a_str, "out") == 0) {
27527c478bd9Sstevel@tonic-gate 			func = &mdb_tgt_step_out;
27537c478bd9Sstevel@tonic-gate 			name = "step (out)";
27547c478bd9Sstevel@tonic-gate 			argv++;
27557c478bd9Sstevel@tonic-gate 			argc--;
27567c478bd9Sstevel@tonic-gate 		} else if (strcmp(argv->a_un.a_str, "over") == 0) {
27577c478bd9Sstevel@tonic-gate 			func = &mdb_tgt_next;
27587c478bd9Sstevel@tonic-gate 			name = "step (over)";
27597c478bd9Sstevel@tonic-gate 			argv++;
27607c478bd9Sstevel@tonic-gate 			argc--;
27617c478bd9Sstevel@tonic-gate 		}
27627c478bd9Sstevel@tonic-gate 	}
27637c478bd9Sstevel@tonic-gate 
27647c478bd9Sstevel@tonic-gate 	return (cmd_cont_common(addr, flags, argc, argv, func, name));
27657c478bd9Sstevel@tonic-gate }
27667c478bd9Sstevel@tonic-gate 
27677c478bd9Sstevel@tonic-gate static int
cmd_step_out(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)27687c478bd9Sstevel@tonic-gate cmd_step_out(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
27697c478bd9Sstevel@tonic-gate {
27707c478bd9Sstevel@tonic-gate 	return (cmd_cont_common(addr, flags, argc, argv,
27717c478bd9Sstevel@tonic-gate 	    &mdb_tgt_step_out, "step (out)"));
27727c478bd9Sstevel@tonic-gate }
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate static int
cmd_next(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)27757c478bd9Sstevel@tonic-gate cmd_next(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
27767c478bd9Sstevel@tonic-gate {
27777c478bd9Sstevel@tonic-gate 	return (cmd_cont_common(addr, flags, argc, argv,
27787c478bd9Sstevel@tonic-gate 	    &mdb_tgt_next, "step (over)"));
27797c478bd9Sstevel@tonic-gate }
27807c478bd9Sstevel@tonic-gate 
27817c478bd9Sstevel@tonic-gate static int
cmd_cont(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)27827c478bd9Sstevel@tonic-gate cmd_cont(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
27837c478bd9Sstevel@tonic-gate {
27847c478bd9Sstevel@tonic-gate 	return (cmd_cont_common(addr, flags, argc, argv,
27857c478bd9Sstevel@tonic-gate 	    &mdb_tgt_continue, "continue"));
27867c478bd9Sstevel@tonic-gate }
27877c478bd9Sstevel@tonic-gate 
27887c478bd9Sstevel@tonic-gate #ifndef _KMDB
27897c478bd9Sstevel@tonic-gate /*ARGSUSED*/
27907c478bd9Sstevel@tonic-gate static int
cmd_run(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)27917c478bd9Sstevel@tonic-gate cmd_run(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
27927c478bd9Sstevel@tonic-gate {
27937c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
27947c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
27957c478bd9Sstevel@tonic-gate 
27967c478bd9Sstevel@tonic-gate 	if (mdb_tgt_run(mdb.m_target, argc, argv) == -1) {
27977c478bd9Sstevel@tonic-gate 		if (errno != EMDB_TGT)
27987c478bd9Sstevel@tonic-gate 			mdb_warn("failed to create new target");
27997c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
28007c478bd9Sstevel@tonic-gate 	}
2801892ad162SToomas Soome 	return (cmd_cont(0, 0, 0, NULL));
28027c478bd9Sstevel@tonic-gate }
28037c478bd9Sstevel@tonic-gate #endif
28047c478bd9Sstevel@tonic-gate 
28057c478bd9Sstevel@tonic-gate /*
28067c478bd9Sstevel@tonic-gate  * To simplify the implementation of :d, :z, and ::delete, we use the sp
28077c478bd9Sstevel@tonic-gate  * parameter to store the criteria for what to delete.  If spec_base is set,
28087c478bd9Sstevel@tonic-gate  * we delete vespecs with a matching address.  If spec_id is set, we delete
28097c478bd9Sstevel@tonic-gate  * vespecs with a matching id.  Otherwise, we delete all vespecs.  We bump
28107c478bd9Sstevel@tonic-gate  * sp->spec_size so the caller can tell how many vespecs were deleted.
28117c478bd9Sstevel@tonic-gate  */
28127c478bd9Sstevel@tonic-gate static int
ve_delete(mdb_tgt_t * t,mdb_tgt_spec_desc_t * sp,int vid,void * data)28137c478bd9Sstevel@tonic-gate ve_delete(mdb_tgt_t *t, mdb_tgt_spec_desc_t *sp, int vid, void *data)
28147c478bd9Sstevel@tonic-gate {
28157c478bd9Sstevel@tonic-gate 	mdb_tgt_spec_desc_t spec;
28167c478bd9Sstevel@tonic-gate 	int status = -1;
28177c478bd9Sstevel@tonic-gate 
28187c478bd9Sstevel@tonic-gate 	if (vid < 0)
28197c478bd9Sstevel@tonic-gate 		return (0); /* skip over target implementation events */
28207c478bd9Sstevel@tonic-gate 
2821892ad162SToomas Soome 	if (sp->spec_base != 0) {
28227c478bd9Sstevel@tonic-gate 		(void) mdb_tgt_vespec_info(t, vid, &spec, NULL, 0);
28237c478bd9Sstevel@tonic-gate 		if (sp->spec_base - spec.spec_base < spec.spec_size)
28247c478bd9Sstevel@tonic-gate 			status = mdb_tgt_vespec_delete(t, vid);
28257c478bd9Sstevel@tonic-gate 	} else if (sp->spec_id == 0) {
28267c478bd9Sstevel@tonic-gate 		(void) mdb_tgt_vespec_info(t, vid, &spec, NULL, 0);
28277c478bd9Sstevel@tonic-gate 		if (!(spec.spec_flags & MDB_TGT_SPEC_STICKY))
28287c478bd9Sstevel@tonic-gate 			status = mdb_tgt_vespec_delete(t, vid);
28297c478bd9Sstevel@tonic-gate 	} else if (sp->spec_id == vid)
28307c478bd9Sstevel@tonic-gate 		status = mdb_tgt_vespec_delete(t, vid);
28317c478bd9Sstevel@tonic-gate 
28327c478bd9Sstevel@tonic-gate 	if (status == 0) {
28337c478bd9Sstevel@tonic-gate 		if (data != NULL)
28347c478bd9Sstevel@tonic-gate 			strfree(data);
28357c478bd9Sstevel@tonic-gate 		sp->spec_size++;
28367c478bd9Sstevel@tonic-gate 	}
28377c478bd9Sstevel@tonic-gate 
28387c478bd9Sstevel@tonic-gate 	return (0);
28397c478bd9Sstevel@tonic-gate }
28407c478bd9Sstevel@tonic-gate 
28417c478bd9Sstevel@tonic-gate static int
ve_delete_spec(mdb_tgt_spec_desc_t * sp)28427c478bd9Sstevel@tonic-gate ve_delete_spec(mdb_tgt_spec_desc_t *sp)
28437c478bd9Sstevel@tonic-gate {
28447c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_vespec_iter(mdb.m_target,
28457c478bd9Sstevel@tonic-gate 	    (mdb_tgt_vespec_f *)ve_delete, sp);
28467c478bd9Sstevel@tonic-gate 
28477c478bd9Sstevel@tonic-gate 	if (sp->spec_size == 0) {
2848892ad162SToomas Soome 		if (sp->spec_id != 0 || sp->spec_base != 0)
28497c478bd9Sstevel@tonic-gate 			mdb_warn("no traced events matched description\n");
28507c478bd9Sstevel@tonic-gate 	}
28517c478bd9Sstevel@tonic-gate 
28527c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
28537c478bd9Sstevel@tonic-gate }
28547c478bd9Sstevel@tonic-gate 
28557c478bd9Sstevel@tonic-gate /*ARGSUSED*/
28567c478bd9Sstevel@tonic-gate static int
cmd_zapall(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)28577c478bd9Sstevel@tonic-gate cmd_zapall(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
28587c478bd9Sstevel@tonic-gate {
28597c478bd9Sstevel@tonic-gate 	mdb_tgt_spec_desc_t spec;
28607c478bd9Sstevel@tonic-gate 
28617c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || argc != 0)
28627c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
28637c478bd9Sstevel@tonic-gate 
28647c478bd9Sstevel@tonic-gate 	bzero(&spec, sizeof (spec));
28657c478bd9Sstevel@tonic-gate 	return (ve_delete_spec(&spec));
28667c478bd9Sstevel@tonic-gate }
28677c478bd9Sstevel@tonic-gate 
28687c478bd9Sstevel@tonic-gate static int
cmd_delete(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)28697c478bd9Sstevel@tonic-gate cmd_delete(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
28707c478bd9Sstevel@tonic-gate {
28717c478bd9Sstevel@tonic-gate 	mdb_tgt_spec_desc_t spec;
28727c478bd9Sstevel@tonic-gate 
28737c478bd9Sstevel@tonic-gate 	if (((flags & DCMD_ADDRSPEC) && argc > 0) || argc > 1)
28747c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
28757c478bd9Sstevel@tonic-gate 
28767c478bd9Sstevel@tonic-gate 	bzero(&spec, sizeof (spec));
28777c478bd9Sstevel@tonic-gate 
28787c478bd9Sstevel@tonic-gate 	if (flags & DCMD_ADDRSPEC)
28797c478bd9Sstevel@tonic-gate 		spec.spec_base = addr;
28807c478bd9Sstevel@tonic-gate 	else if (argc == 0)
28817c478bd9Sstevel@tonic-gate 		spec.spec_base = mdb_get_dot();
28827c478bd9Sstevel@tonic-gate 	else if (argv->a_type == MDB_TYPE_STRING &&
28837c478bd9Sstevel@tonic-gate 	    strcmp(argv->a_un.a_str, "all") != 0)
28844585130bSYuri Pankov 		spec.spec_id = (int)(intmax_t)mdb_strtonum(argv->a_un.a_str,
28854585130bSYuri Pankov 		    10);
28867c478bd9Sstevel@tonic-gate 	else if (argv->a_type == MDB_TYPE_IMMEDIATE)
28877c478bd9Sstevel@tonic-gate 		spec.spec_id = (int)(intmax_t)argv->a_un.a_val;
28887c478bd9Sstevel@tonic-gate 
28897c478bd9Sstevel@tonic-gate 	return (ve_delete_spec(&spec));
28907c478bd9Sstevel@tonic-gate }
28917c478bd9Sstevel@tonic-gate 
28923d580edaSSerapheim Dimitropoulos static int
cmd_write(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)28933d580edaSSerapheim Dimitropoulos cmd_write(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
28943d580edaSSerapheim Dimitropoulos {
28953d580edaSSerapheim Dimitropoulos 	mdb_tgt_as_t as;
28963d580edaSSerapheim Dimitropoulos 	int rdback = mdb.m_flags & MDB_FL_READBACK;
28973d580edaSSerapheim Dimitropoulos 	mdb_tgt_addr_t naddr;
28983d580edaSSerapheim Dimitropoulos 	size_t forced_size = 0;
28993d580edaSSerapheim Dimitropoulos 	boolean_t opt_p, opt_o, opt_l;
29003d580edaSSerapheim Dimitropoulos 	uint64_t val = 0;
29013d580edaSSerapheim Dimitropoulos 	int i;
29023d580edaSSerapheim Dimitropoulos 
29033d580edaSSerapheim Dimitropoulos 	opt_p = opt_o = opt_l = B_FALSE;
29043d580edaSSerapheim Dimitropoulos 
29053d580edaSSerapheim Dimitropoulos 	i = mdb_getopts(argc, argv,
29063d580edaSSerapheim Dimitropoulos 	    'p', MDB_OPT_SETBITS, B_TRUE, &opt_p,
29073d580edaSSerapheim Dimitropoulos 	    'o', MDB_OPT_SETBITS, B_TRUE, &opt_o,
29083d580edaSSerapheim Dimitropoulos 	    'l', MDB_OPT_UINTPTR_SET, &opt_l, (uintptr_t *)&forced_size, NULL);
29093d580edaSSerapheim Dimitropoulos 
29103d580edaSSerapheim Dimitropoulos 	if (!(flags & DCMD_ADDRSPEC))
29113d580edaSSerapheim Dimitropoulos 		return (DCMD_USAGE);
29123d580edaSSerapheim Dimitropoulos 
29133d580edaSSerapheim Dimitropoulos 	if (opt_p && opt_o) {
29143d580edaSSerapheim Dimitropoulos 		mdb_warn("-o and -p are incompatible\n");
29153d580edaSSerapheim Dimitropoulos 		return (DCMD_USAGE);
29163d580edaSSerapheim Dimitropoulos 	}
29173d580edaSSerapheim Dimitropoulos 
29183d580edaSSerapheim Dimitropoulos 	argc -= i;
29193d580edaSSerapheim Dimitropoulos 	argv += i;
29203d580edaSSerapheim Dimitropoulos 
29213d580edaSSerapheim Dimitropoulos 	if (argc == 0)
29223d580edaSSerapheim Dimitropoulos 		return (DCMD_USAGE);
29233d580edaSSerapheim Dimitropoulos 
29243d580edaSSerapheim Dimitropoulos 	switch (argv[0].a_type) {
29253d580edaSSerapheim Dimitropoulos 	case MDB_TYPE_STRING:
29263d580edaSSerapheim Dimitropoulos 		val = mdb_strtoull(argv[0].a_un.a_str);
29273d580edaSSerapheim Dimitropoulos 		break;
29283d580edaSSerapheim Dimitropoulos 	case MDB_TYPE_IMMEDIATE:
29293d580edaSSerapheim Dimitropoulos 		val = argv[0].a_un.a_val;
29303d580edaSSerapheim Dimitropoulos 		break;
29313d580edaSSerapheim Dimitropoulos 	default:
29323d580edaSSerapheim Dimitropoulos 		return (DCMD_USAGE);
29333d580edaSSerapheim Dimitropoulos 	}
29343d580edaSSerapheim Dimitropoulos 
29353d580edaSSerapheim Dimitropoulos 	if (opt_p)
29363d580edaSSerapheim Dimitropoulos 		as = MDB_TGT_AS_PHYS;
29373d580edaSSerapheim Dimitropoulos 	else if (opt_o)
29383d580edaSSerapheim Dimitropoulos 		as = MDB_TGT_AS_FILE;
29393d580edaSSerapheim Dimitropoulos 	else
29403d580edaSSerapheim Dimitropoulos 		as = MDB_TGT_AS_VIRT;
29413d580edaSSerapheim Dimitropoulos 
29423d580edaSSerapheim Dimitropoulos 	if (opt_l)
29433d580edaSSerapheim Dimitropoulos 		naddr = write_var_uint(as, addr, val, forced_size, rdback);
29443d580edaSSerapheim Dimitropoulos 	else
29453d580edaSSerapheim Dimitropoulos 		naddr = write_ctf_uint(as, addr, val, rdback);
29463d580edaSSerapheim Dimitropoulos 
29473d580edaSSerapheim Dimitropoulos 	if (addr == naddr) {
29483d580edaSSerapheim Dimitropoulos 		mdb_warn("failed to write %llr at address %#llx", val, addr);
29493d580edaSSerapheim Dimitropoulos 		return (DCMD_ERR);
29503d580edaSSerapheim Dimitropoulos 	}
29513d580edaSSerapheim Dimitropoulos 
29523d580edaSSerapheim Dimitropoulos 	return (DCMD_OK);
29533d580edaSSerapheim Dimitropoulos }
29543d580edaSSerapheim Dimitropoulos 
29553d580edaSSerapheim Dimitropoulos void
write_help(void)29563d580edaSSerapheim Dimitropoulos write_help(void)
29573d580edaSSerapheim Dimitropoulos {
29583d580edaSSerapheim Dimitropoulos 	mdb_printf(
29593d580edaSSerapheim Dimitropoulos 	    "-l length  force a write with the specified length in bytes\n"
29603d580edaSSerapheim Dimitropoulos 	    "-o         write data to the object file location specified\n"
29613d580edaSSerapheim Dimitropoulos 	    "-p         write data to the physical address specified\n"
29623d580edaSSerapheim Dimitropoulos 	    "\n"
29633d580edaSSerapheim Dimitropoulos 	    "Attempts to write the given value to the address provided.\n"
29643d580edaSSerapheim Dimitropoulos 	    "If -l is not specified, the address must be the position of a\n"
29653d580edaSSerapheim Dimitropoulos 	    "symbol that is either of integer, pointer, or enum type. The\n"
29663d580edaSSerapheim Dimitropoulos 	    "type and the size of the symbol are inferred by the CTF found\n"
29673d580edaSSerapheim Dimitropoulos 	    "in the provided address. The length of the write is guaranteed\n"
29683d580edaSSerapheim Dimitropoulos 	    "to be the inferred size of the symbol.\n"
29693d580edaSSerapheim Dimitropoulos 	    "\n"
29703d580edaSSerapheim Dimitropoulos 	    "If no CTF data exists, or the address provided is not a symbol\n"
29713d580edaSSerapheim Dimitropoulos 	    "of integer or pointer type, then the write fails. At that point\n"
29723d580edaSSerapheim Dimitropoulos 	    "the user can force the write by using the '-l' option and\n"
29733d580edaSSerapheim Dimitropoulos 	    "specifying its length.\n"
29743d580edaSSerapheim Dimitropoulos 	    "\n"
29753d580edaSSerapheim Dimitropoulos 	    "Note that forced writes with a length that are bigger than\n"
29763d580edaSSerapheim Dimitropoulos 	    "the size of the biggest data pointer supported are not allowed."
29773d580edaSSerapheim Dimitropoulos 	    "\n");
29783d580edaSSerapheim Dimitropoulos }
29793d580edaSSerapheim Dimitropoulos 
29807c478bd9Sstevel@tonic-gate static void
srcexec_file_help(void)29817c478bd9Sstevel@tonic-gate srcexec_file_help(void)
29827c478bd9Sstevel@tonic-gate {
29837c478bd9Sstevel@tonic-gate 	mdb_printf(
29847c478bd9Sstevel@tonic-gate "The library of macros delivered with previous versions of Solaris have been\n"
29857c478bd9Sstevel@tonic-gate "superseded by the dcmds and walkers provided by MDB.  See ::help for\n"
29867c478bd9Sstevel@tonic-gate "commands that can be used to list the available dcmds and walkers.\n"
29877c478bd9Sstevel@tonic-gate "\n"
29887c478bd9Sstevel@tonic-gate "Aliases have been created for several of the more popular macros.  To see\n"
29897c478bd9Sstevel@tonic-gate "the list of aliased macros, as well as their native MDB equivalents,\n"
29907c478bd9Sstevel@tonic-gate "type $M.\n");
29917c478bd9Sstevel@tonic-gate 
29927c478bd9Sstevel@tonic-gate #ifdef _KMDB
29937c478bd9Sstevel@tonic-gate 	mdb_printf(
29947c478bd9Sstevel@tonic-gate "When invoked, the $< and $<< dcmds will consult the macro alias list.  If an\n"
29957c478bd9Sstevel@tonic-gate "alias cannot be found, an attempt will be made to locate a data type whose\n"
29967c478bd9Sstevel@tonic-gate "name corresponds to the requested macro.  If such a type can be found, it\n"
29977c478bd9Sstevel@tonic-gate "will be displayed using the ::print dcmd.\n");
29987c478bd9Sstevel@tonic-gate #else
29997c478bd9Sstevel@tonic-gate 	mdb_printf(
30007c478bd9Sstevel@tonic-gate "When invoked, the $< and $<< dcmds will first attempt to locate a macro with\n"
30017c478bd9Sstevel@tonic-gate "the indicated name.  If no macro can be found, and if no alias exists for\n"
30027c478bd9Sstevel@tonic-gate "this macro, an attempt will be made to locate a data type whose name\n"
30037c478bd9Sstevel@tonic-gate "corresponds to the requested macro.  If such a type can be found, it will be\n"
30047c478bd9Sstevel@tonic-gate "displayed using the ::print dcmd.\n");
30057c478bd9Sstevel@tonic-gate #endif
30067c478bd9Sstevel@tonic-gate }
30077c478bd9Sstevel@tonic-gate 
30087c478bd9Sstevel@tonic-gate static void
events_help(void)30097c478bd9Sstevel@tonic-gate events_help(void)
30107c478bd9Sstevel@tonic-gate {
30117c478bd9Sstevel@tonic-gate 	mdb_printf("Options:\n"
30127c478bd9Sstevel@tonic-gate 	    "-a       show all events, including internal debugger events\n"
30137c478bd9Sstevel@tonic-gate 	    "-v       show verbose display, including inactivity reason\n"
30147c478bd9Sstevel@tonic-gate 	    "\nOutput Columns:\n"
30157c478bd9Sstevel@tonic-gate 	    "ID       decimal event specifier id number:\n"
30167c478bd9Sstevel@tonic-gate 	    "    [ ]  event tracing is enabled\n"
30177c478bd9Sstevel@tonic-gate 	    "    ( )  event tracing is disabled\n"
30187c478bd9Sstevel@tonic-gate 	    "    < >  target is currently stopped on this type of event\n\n"
30197c478bd9Sstevel@tonic-gate 	    "S        event specifier state:\n"
30207c478bd9Sstevel@tonic-gate 	    "     -   event specifier is idle (not applicable yet)\n"
30217c478bd9Sstevel@tonic-gate 	    "     +   event specifier is active\n"
30227c478bd9Sstevel@tonic-gate 	    "     *   event specifier is armed (target program running)\n"
30237c478bd9Sstevel@tonic-gate 	    "     !   error occurred while attempting to arm event\n\n"
30247c478bd9Sstevel@tonic-gate 	    "TA       event specifier flags:\n"
30257c478bd9Sstevel@tonic-gate 	    "     t   event specifier is temporary (delete at next stop)\n"
30267c478bd9Sstevel@tonic-gate 	    "     T   event specifier is sticky (::delete all has no effect)\n"
30277c478bd9Sstevel@tonic-gate 	    "     d   event specifier will be disabled when HT = LM\n"
30287c478bd9Sstevel@tonic-gate 	    "     D   event specifier will be deleted when HT = LM\n"
30297c478bd9Sstevel@tonic-gate 	    "     s   target will automatically stop when HT = LM\n\n"
30307c478bd9Sstevel@tonic-gate 	    "HT       hit count (number of times event has occurred)\n"
30317c478bd9Sstevel@tonic-gate 	    "LM       hit limit (limit for autostop, disable, delete)\n");
30327c478bd9Sstevel@tonic-gate }
30337c478bd9Sstevel@tonic-gate 
30347c478bd9Sstevel@tonic-gate static void
dump_help(void)30357c478bd9Sstevel@tonic-gate dump_help(void)
30367c478bd9Sstevel@tonic-gate {
30377c478bd9Sstevel@tonic-gate 	mdb_printf(
30387c478bd9Sstevel@tonic-gate 	    "-e    adjust for endianness\n"
30397c478bd9Sstevel@tonic-gate 	    "      (assumes 4-byte words; use -g to change word size)\n"
30407c478bd9Sstevel@tonic-gate #ifdef _KMDB
30417c478bd9Sstevel@tonic-gate 	    "-f    no effect\n"
30427c478bd9Sstevel@tonic-gate #else
30437c478bd9Sstevel@tonic-gate 	    "-f    dump from object file\n"
30447c478bd9Sstevel@tonic-gate #endif
30457c478bd9Sstevel@tonic-gate 	    "-g n  display bytes in groups of n\n"
30467c478bd9Sstevel@tonic-gate 	    "      (default is 4; n must be a power of 2, divide line width)\n"
3047f11ba53fSDan Kimmel 	    "-l n  display n bytes\n"
3048f11ba53fSDan Kimmel 	    "      (default is 1; rounded up to multiple of line width)\n"
30497c478bd9Sstevel@tonic-gate 	    "-p    dump from physical memory\n"
30507c478bd9Sstevel@tonic-gate 	    "-q    don't print ASCII\n"
30517c478bd9Sstevel@tonic-gate 	    "-r    use relative numbering (automatically sets -u)\n"
30527c478bd9Sstevel@tonic-gate 	    "-s    elide repeated lines\n"
30537c478bd9Sstevel@tonic-gate 	    "-t    only read from and display contents of specified addresses\n"
30547c478bd9Sstevel@tonic-gate 	    "      (default is to read and print entire lines)\n"
30557c478bd9Sstevel@tonic-gate 	    "-u    un-align output\n"
30567c478bd9Sstevel@tonic-gate 	    "      (default is to align output at paragraph boundary)\n"
30577c478bd9Sstevel@tonic-gate 	    "-w n  display n 16-byte paragraphs per line\n"
30587c478bd9Sstevel@tonic-gate 	    "      (default is 1, maximum is 16)\n");
30597c478bd9Sstevel@tonic-gate }
30607c478bd9Sstevel@tonic-gate 
30617c478bd9Sstevel@tonic-gate /*
30627c478bd9Sstevel@tonic-gate  * Table of built-in dcmds associated with the root 'mdb' module.  Future
30637c478bd9Sstevel@tonic-gate  * expansion of this program should be done here, or through the external
30647c478bd9Sstevel@tonic-gate  * loadable module interface.
30657c478bd9Sstevel@tonic-gate  */
30667c478bd9Sstevel@tonic-gate const mdb_dcmd_t mdb_dcmd_builtins[] = {
30677c478bd9Sstevel@tonic-gate 
30687c478bd9Sstevel@tonic-gate 	/*
30697c478bd9Sstevel@tonic-gate 	 * dcmds common to both mdb and kmdb
30707c478bd9Sstevel@tonic-gate 	 */
30717c478bd9Sstevel@tonic-gate 	{ ">", "variable-name", "assign variable", cmd_assign_variable },
30727c478bd9Sstevel@tonic-gate 	{ "/", "fmt-list", "format data from virtual as", cmd_print_core },
30737c478bd9Sstevel@tonic-gate 	{ "\\", "fmt-list", "format data from physical as", cmd_print_phys },
30747c478bd9Sstevel@tonic-gate 	{ "@", "fmt-list", "format data from physical as", cmd_print_phys },
30757c478bd9Sstevel@tonic-gate 	{ "=", "fmt-list", "format immediate value", cmd_print_value },
30767c478bd9Sstevel@tonic-gate 	{ "$<", "macro-name", "replace input with macro",
30777c478bd9Sstevel@tonic-gate 	    cmd_exec_file, srcexec_file_help },
30787c478bd9Sstevel@tonic-gate 	{ "$<<", "macro-name", "source macro",
30797c478bd9Sstevel@tonic-gate 	    cmd_src_file, srcexec_file_help},
30807c478bd9Sstevel@tonic-gate 	{ "$%", NULL, NULL, cmd_quit },
30817c478bd9Sstevel@tonic-gate 	{ "$?", NULL, "print status and registers", cmd_notsup },
30827c478bd9Sstevel@tonic-gate 	{ "$a", NULL, NULL, cmd_algol },
30837c478bd9Sstevel@tonic-gate 	{ "$b", "[-av]", "list traced software events",
30847c478bd9Sstevel@tonic-gate 	    cmd_events, events_help },
30857c478bd9Sstevel@tonic-gate 	{ "$c", "?[cnt]", "print stack backtrace", cmd_notsup },
30867c478bd9Sstevel@tonic-gate 	{ "$C", "?[cnt]", "print stack backtrace", cmd_notsup },
30877c478bd9Sstevel@tonic-gate 	{ "$d", NULL, "get/set default output radix", cmd_radix },
30887c478bd9Sstevel@tonic-gate 	{ "$D", "?[mode,...]", NULL, cmd_dbmode },
30897c478bd9Sstevel@tonic-gate 	{ "$e", NULL, "print listing of global symbols", cmd_globals },
30907c478bd9Sstevel@tonic-gate 	{ "$f", NULL, "print listing of source files", cmd_files },
30917c478bd9Sstevel@tonic-gate 	{ "$m", "?[name]", "print address space mappings", cmd_mappings },
30927c478bd9Sstevel@tonic-gate 	{ "$M", NULL, "list macro aliases", cmd_macalias_list },
30937c478bd9Sstevel@tonic-gate 	{ "$P", "[prompt]", "set debugger prompt string", cmd_prompt },
30947c478bd9Sstevel@tonic-gate 	{ "$q", NULL, "quit debugger", cmd_quit },
30957c478bd9Sstevel@tonic-gate 	{ "$Q", NULL, "quit debugger", cmd_quit },
30967c478bd9Sstevel@tonic-gate 	{ "$r", NULL, "print general-purpose registers", cmd_notsup },
30977c478bd9Sstevel@tonic-gate 	{ "$s", NULL, "get/set symbol matching distance", cmd_symdist },
30987c478bd9Sstevel@tonic-gate 	{ "$v", NULL, "print non-zero variables", cmd_nzvars },
30997c478bd9Sstevel@tonic-gate 	{ "$V", "[mode]", "get/set disassembly mode", cmd_dismode },
31007c478bd9Sstevel@tonic-gate 	{ "$w", NULL, "get/set output page width", cmd_pgwidth },
31017c478bd9Sstevel@tonic-gate 	{ "$W", NULL, "re-open target in write mode", cmd_reopen },
31027c478bd9Sstevel@tonic-gate 	{ ":a", ":[cmd...]", "set read access watchpoint", cmd_oldwpr },
31037c478bd9Sstevel@tonic-gate 	{ ":b", ":[cmd...]", "breakpoint at the specified address", cmd_oldbp },
31047c478bd9Sstevel@tonic-gate 	{ ":d", "?[id|all]", "delete traced software events", cmd_delete },
31057c478bd9Sstevel@tonic-gate 	{ ":p", ":[cmd...]", "set execute access watchpoint", cmd_oldwpx },
31067c478bd9Sstevel@tonic-gate 	{ ":S", NULL, NULL, cmd_step },
31077c478bd9Sstevel@tonic-gate 	{ ":w", ":[cmd...]", "set write access watchpoint", cmd_oldwpw },
31087c478bd9Sstevel@tonic-gate 	{ ":z", NULL, "delete all traced software events", cmd_zapall },
31097c478bd9Sstevel@tonic-gate 	{ "array", ":[type count] [variable]", "print each array element's "
31107c478bd9Sstevel@tonic-gate 	    "address", cmd_array },
31117c478bd9Sstevel@tonic-gate 	{ "bp", "?[+/-dDestT] [-c cmd] [-n count] sym ...", "breakpoint at the "
31127c478bd9Sstevel@tonic-gate 	    "specified addresses or symbols", cmd_bp, bp_help },
31131700af3aSAndy Fiddaman 	{ "dcmds", "[[-n] pattern]",
31141700af3aSAndy Fiddaman 	    "list available debugger commands", cmd_dcmds, cmd_dcmds_help },
31157c478bd9Sstevel@tonic-gate 	{ "delete", "?[id|all]", "delete traced software events", cmd_delete },
3116af7034caSss 	{ "dis", "?[-abfw] [-n cnt] [addr]", "disassemble near addr", cmd_dis },
31177c478bd9Sstevel@tonic-gate 	{ "disasms", NULL, "list available disassemblers", cmd_disasms },
31187c478bd9Sstevel@tonic-gate 	{ "dismode", "[mode]", "get/set disassembly mode", cmd_dismode },
31197c478bd9Sstevel@tonic-gate 	{ "dmods", "[-l] [mod]", "list loaded debugger modules", cmd_dmods },
3120f11ba53fSDan Kimmel 	{ "dump", "?[-eqrstu] [-f|-p] [-g bytes] [-l bytes] [-w paragraphs]",
31217c478bd9Sstevel@tonic-gate 	    "dump memory from specified address", cmd_dump, dump_help },
31227c478bd9Sstevel@tonic-gate 	{ "echo", "args ...", "echo arguments", cmd_echo },
3123e0ad97e3SJonathan Adams 	{ "enum", "?[-ex] enum [name]", "print an enumeration", cmd_enum,
3124e0ad97e3SJonathan Adams 	    enum_help },
31257c478bd9Sstevel@tonic-gate 	{ "eval", "command", "evaluate the specified command", cmd_eval },
31267c478bd9Sstevel@tonic-gate 	{ "events", "[-av]", "list traced software events",
31277c478bd9Sstevel@tonic-gate 	    cmd_events, events_help },
31287c478bd9Sstevel@tonic-gate 	{ "evset", "?[+/-dDestT] [-c cmd] [-n count] id ...",
31297c478bd9Sstevel@tonic-gate 	    "set software event specifier attributes", cmd_evset, evset_help },
31307c478bd9Sstevel@tonic-gate 	{ "files", "[object]", "print listing of source files", cmd_files },
31317c478bd9Sstevel@tonic-gate #ifdef __sparc
31327c478bd9Sstevel@tonic-gate 	{ "findsym", "?[-g] [symbol|addr ...]", "search for symbol references "
31337c478bd9Sstevel@tonic-gate 	    "in all known functions", cmd_findsym, NULL },
31347c478bd9Sstevel@tonic-gate #endif
31357c478bd9Sstevel@tonic-gate 	{ "formats", NULL, "list format specifiers", cmd_formats },
31367c478bd9Sstevel@tonic-gate 	{ "grep", "?expr", "print dot if expression is true", cmd_grep },
31377c478bd9Sstevel@tonic-gate 	{ "head", "-num|-n num", "limit number of elements in pipe", cmd_head,
31387c478bd9Sstevel@tonic-gate 	    head_help },
31392f045fd6SRobert Mustacchi 	{ "help", "[cmd]", "list commands/command help", cmd_help, NULL,
31402f045fd6SRobert Mustacchi 	    cmd_help_tab },
3141089ef9c1SJason King 	{ "linkerset", "[name]", "display linkersets", cmd_linkerset,
3142089ef9c1SJason King 	    linkerset_help, cmd_linkerset_tab },
31437c478bd9Sstevel@tonic-gate 	{ "list", "?type member [variable]",
31443b6e0a59SMatt Amdur 	    "walk list using member as link pointer", cmd_list, NULL,
31453b6e0a59SMatt Amdur 	    mdb_tab_complete_mt },
31467c478bd9Sstevel@tonic-gate 	{ "map", "?expr", "print dot after evaluating expression", cmd_map },
31477c478bd9Sstevel@tonic-gate 	{ "mappings", "?[name]", "print address space mappings", cmd_mappings },
31487c478bd9Sstevel@tonic-gate 	{ "nm", "?[-DPdghnopuvx] [-f format] [-t types] [object]",
31497c478bd9Sstevel@tonic-gate 	    "print symbols", cmd_nm, nm_help },
31507c478bd9Sstevel@tonic-gate 	{ "nmadd", ":[-fo] [-e end] [-s size] name",
31517c478bd9Sstevel@tonic-gate 	    "add name to private symbol table", cmd_nmadd, nmadd_help },
31527c478bd9Sstevel@tonic-gate 	{ "nmdel", "name", "remove name from private symbol table", cmd_nmdel },
31537c478bd9Sstevel@tonic-gate 	{ "obey", NULL, NULL, cmd_obey },
31547c478bd9Sstevel@tonic-gate 	{ "objects", "[-v]", "print load objects information", cmd_objects },
31557c478bd9Sstevel@tonic-gate 	{ "offsetof", "type member", "print the offset of a given struct "
31563b6e0a59SMatt Amdur 	    "or union member", cmd_offsetof, NULL, mdb_tab_complete_mt },
31577c478bd9Sstevel@tonic-gate 	{ "print", "?[-aCdhiLptx] [-c lim] [-l lim] [type] [member|offset ...]",
31583b6e0a59SMatt Amdur 	    "print the contents of a data structure", cmd_print, print_help,
31593b6e0a59SMatt Amdur 	    cmd_print_tab },
31603ddcfaddSBryan Cantrill 	{ "printf", "?format type member ...", "print and format the "
31612f045fd6SRobert Mustacchi 	    "member(s) of a data structure", cmd_printf, printf_help,
31622f045fd6SRobert Mustacchi 	    cmd_printf_tab },
31637c478bd9Sstevel@tonic-gate 	{ "regs", NULL, "print general purpose registers", cmd_notsup },
31647c478bd9Sstevel@tonic-gate 	{ "set", "[-wF] [+/-o opt] [-s dist] [-I path] [-L path] [-P prompt]",
31657c478bd9Sstevel@tonic-gate 	    "get/set debugger properties", cmd_set },
31667c478bd9Sstevel@tonic-gate 	{ "showrev", "[-pv]", "print version information", cmd_showrev },
31673b6e0a59SMatt Amdur 	{ "sizeof", "type", "print the size of a type", cmd_sizeof, NULL,
31683b6e0a59SMatt Amdur 	    cmd_sizeof_tab },
31697c478bd9Sstevel@tonic-gate 	{ "stack", "?[cnt]", "print stack backtrace", cmd_notsup },
31707c478bd9Sstevel@tonic-gate 	{ "stackregs", "?", "print stack backtrace and registers",
31717c478bd9Sstevel@tonic-gate 	    cmd_notsup },
31727c478bd9Sstevel@tonic-gate 	{ "status", NULL, "print summary of current target", cmd_notsup },
31737c478bd9Sstevel@tonic-gate 	{ "term", NULL, "display current terminal type", cmd_term },
31747c478bd9Sstevel@tonic-gate 	{ "typeset", "[+/-t] var ...", "set variable attributes", cmd_typeset },
31752becb8cdSRobert Mustacchi 	{ "typedef", "[-c model | -d | -l | -r file | -w file ] [type] [name]",
31760a47c91cSRobert Mustacchi 		"create synthetic types", cmd_typedef, cmd_typedef_help },
3177c71ad176SRobert Mustacchi 	{ "typelist", NULL, "list known types", cmd_typelist },
31787c478bd9Sstevel@tonic-gate 	{ "unset", "[name ...]", "unset variables", cmd_unset },
31797c478bd9Sstevel@tonic-gate 	{ "vars", "[-npt]", "print listing of variables", cmd_vars },
31807c478bd9Sstevel@tonic-gate 	{ "version", NULL, "print debugger version string", cmd_version },
31817c478bd9Sstevel@tonic-gate 	{ "vtop", ":[-a as]", "print physical mapping of virtual address",
31827c478bd9Sstevel@tonic-gate 	    cmd_vtop },
31833b6e0a59SMatt Amdur 	{ "walk", "?name [variable]", "walk data structure", cmd_walk, NULL,
31843b6e0a59SMatt Amdur 	    cmd_walk_tab },
31851700af3aSAndy Fiddaman 	{ "walkers", "[[-n] pattern]", "list available walkers",
31861700af3aSAndy Fiddaman 	    cmd_walkers, cmd_walkers_help },
31874a1c2431SJonathan Adams 	{ "whatis", ":[-aikqv]", "given an address, return information",
31884a1c2431SJonathan Adams 	    cmd_whatis, whatis_help },
31897c478bd9Sstevel@tonic-gate 	{ "whence", "[-v] name ...", "show source of walk or dcmd", cmd_which },
31907c478bd9Sstevel@tonic-gate 	{ "which", "[-v] name ...", "show source of walk or dcmd", cmd_which },
31913d580edaSSerapheim Dimitropoulos 	{ "write", "?[-op] [-l len] value",
31923d580edaSSerapheim Dimitropoulos 	    "write value to the provided memory location", cmd_write,
31933d580edaSSerapheim Dimitropoulos 	    write_help },
31947c478bd9Sstevel@tonic-gate 	{ "xdata", NULL, "print list of external data buffers", cmd_xdata },
31957c478bd9Sstevel@tonic-gate 
31967c478bd9Sstevel@tonic-gate #ifdef _KMDB
31977c478bd9Sstevel@tonic-gate 	/*
31987c478bd9Sstevel@tonic-gate 	 * dcmds specific to kmdb, or which have kmdb-specific arguments
31997c478bd9Sstevel@tonic-gate 	 */
32007c478bd9Sstevel@tonic-gate 	{ "?", "fmt-list", "format data from virtual as", cmd_print_core },
32017c478bd9Sstevel@tonic-gate 	{ ":c", NULL, "continue target execution", cmd_cont },
32027c478bd9Sstevel@tonic-gate 	{ ":e", NULL, "step target over next instruction", cmd_next },
32037c478bd9Sstevel@tonic-gate 	{ ":s", NULL, "single-step target to next instruction", cmd_step },
32047c478bd9Sstevel@tonic-gate 	{ ":u", NULL, "step target out of current function", cmd_step_out },
32057c478bd9Sstevel@tonic-gate 	{ "cont", NULL, "continue target execution", cmd_cont },
32067c478bd9Sstevel@tonic-gate 	{ "load", "[-sd] module", "load debugger module", cmd_load, load_help },
32077c478bd9Sstevel@tonic-gate 	{ "next", NULL, "step target over next instruction", cmd_next },
32087c478bd9Sstevel@tonic-gate 	{ "quit", "[-u]", "quit debugger", cmd_quit, quit_help },
32097c478bd9Sstevel@tonic-gate 	{ "step", "[ over | out ]",
32107c478bd9Sstevel@tonic-gate 	    "single-step target to next instruction", cmd_step },
32117c478bd9Sstevel@tonic-gate 	{ "unload", "[-d] module", "unload debugger module", cmd_unload,
32127c478bd9Sstevel@tonic-gate 	    unload_help },
32137c478bd9Sstevel@tonic-gate 	{ "wp", ":[+/-dDelstT] [-rwx] [-pi] [-c cmd] [-n count] [-L size]",
32147c478bd9Sstevel@tonic-gate 	    "set a watchpoint at the specified address", cmd_wp, wp_help },
32157c478bd9Sstevel@tonic-gate 
32167c478bd9Sstevel@tonic-gate #else
32177c478bd9Sstevel@tonic-gate 	/*
32187c478bd9Sstevel@tonic-gate 	 * dcmds specific to mdb, or which have mdb-specific arguments
32197c478bd9Sstevel@tonic-gate 	 */
32207c478bd9Sstevel@tonic-gate 	{ "?", "fmt-list", "format data from object file", cmd_print_object },
32217c478bd9Sstevel@tonic-gate 	{ "$>", "[file]", "log session to a file", cmd_old_log },
32226a6cfa5dSJason King 	{ "$g", "?", "get/set demangling options", cmd_demflags },
32236a6cfa5dSJason King 	{ "$G", NULL, "enable/disable demangling support", cmd_demangle },
32247c478bd9Sstevel@tonic-gate 	{ "$i", NULL, "print signals that are ignored", cmd_notsup },
32257c478bd9Sstevel@tonic-gate 	{ "$l", NULL, "print the representative thread's lwp id", cmd_notsup },
32267c478bd9Sstevel@tonic-gate 	{ "$p", ":", "change debugger target context", cmd_context },
32277c478bd9Sstevel@tonic-gate 	{ "$x", NULL, "print floating point registers", cmd_notsup },
32287c478bd9Sstevel@tonic-gate 	{ "$X", NULL, "print floating point registers", cmd_notsup },
32297c478bd9Sstevel@tonic-gate 	{ "$y", NULL, "print floating point registers", cmd_notsup },
32307c478bd9Sstevel@tonic-gate 	{ "$Y", NULL, "print floating point registers", cmd_notsup },
32317c478bd9Sstevel@tonic-gate 	{ ":A", "?[core|pid]", "attach to process or core file", cmd_notsup },
32327c478bd9Sstevel@tonic-gate 	{ ":c", "[SIG]", "continue target execution", cmd_cont },
32337c478bd9Sstevel@tonic-gate 	{ ":e", "[SIG]", "step target over next instruction", cmd_next },
32347c478bd9Sstevel@tonic-gate 	{ ":i", ":", "ignore signal (delete all matching events)", cmd_notsup },
32357c478bd9Sstevel@tonic-gate 	{ ":k", NULL, "forcibly kill and release target", cmd_notsup },
32367c478bd9Sstevel@tonic-gate 	{ ":t", "?[+/-dDestT] [-c cmd] [-n count] SIG ...", "stop on delivery "
32377c478bd9Sstevel@tonic-gate 	    "of the specified signals", cmd_sigbp, sigbp_help },
32387c478bd9Sstevel@tonic-gate 	{ ":r", "[ args ... ]", "run a new target process", cmd_run },
32397c478bd9Sstevel@tonic-gate 	{ ":R", NULL, "release the previously attached process", cmd_notsup },
32407c478bd9Sstevel@tonic-gate 	{ ":s", "[SIG]", "single-step target to next instruction", cmd_step },
32417c478bd9Sstevel@tonic-gate 	{ ":u", "[SIG]", "step target out of current function", cmd_step_out },
32427c478bd9Sstevel@tonic-gate 	{ "attach", "?[core|pid]",
32437c478bd9Sstevel@tonic-gate 	    "attach to process or core file", cmd_notsup },
32447c478bd9Sstevel@tonic-gate 	{ "cat", "[file ...]", "concatenate and display files", cmd_cat },
32457c478bd9Sstevel@tonic-gate 	{ "cont", "[SIG]", "continue target execution", cmd_cont },
32467c478bd9Sstevel@tonic-gate 	{ "context", ":", "change debugger target context", cmd_context },
32477c478bd9Sstevel@tonic-gate 	{ "dem", "name ...", "demangle C++ symbol names", cmd_demstr },
32487c478bd9Sstevel@tonic-gate 	{ "fltbp", "?[+/-dDestT] [-c cmd] [-n count] fault ...",
32497c478bd9Sstevel@tonic-gate 	    "stop on machine fault", cmd_fltbp, fltbp_help },
32507c478bd9Sstevel@tonic-gate 	{ "fpregs", NULL, "print floating point registers", cmd_notsup },
32517c478bd9Sstevel@tonic-gate 	{ "kill", NULL, "forcibly kill and release target", cmd_notsup },
32527c478bd9Sstevel@tonic-gate 	{ "load", "[-s] module", "load debugger module", cmd_load, load_help },
32537c478bd9Sstevel@tonic-gate 	{ "log", "[-d | [-e] file]", "log session to a file", cmd_log },
32547c478bd9Sstevel@tonic-gate 	{ "next", "[SIG]", "step target over next instruction", cmd_next },
32557c478bd9Sstevel@tonic-gate 	{ "quit", NULL, "quit debugger", cmd_quit },
32567c478bd9Sstevel@tonic-gate 	{ "release", NULL,
32577c478bd9Sstevel@tonic-gate 	    "release the previously attached process", cmd_notsup },
32587c478bd9Sstevel@tonic-gate 	{ "run", "[ args ... ]", "run a new target process", cmd_run },
32597c478bd9Sstevel@tonic-gate 	{ "sigbp", "?[+/-dDestT] [-c cmd] [-n count] SIG ...", "stop on "
32607c478bd9Sstevel@tonic-gate 	    "delivery of the specified signals", cmd_sigbp, sigbp_help },
32617c478bd9Sstevel@tonic-gate 	{ "step", "[ over | out ] [SIG]",
32627c478bd9Sstevel@tonic-gate 	    "single-step target to next instruction", cmd_step },
32637c478bd9Sstevel@tonic-gate 	{ "sysbp", "?[+/-dDestT] [-io] [-c cmd] [-n count] syscall ...",
32647c478bd9Sstevel@tonic-gate 	    "stop on entry or exit from system call", cmd_sysbp, sysbp_help },
32657c478bd9Sstevel@tonic-gate 	{ "unload", "module", "unload debugger module", cmd_unload },
32667c478bd9Sstevel@tonic-gate 	{ "wp", ":[+/-dDelstT] [-rwx] [-c cmd] [-n count] [-L size]",
32677c478bd9Sstevel@tonic-gate 	    "set a watchpoint at the specified address", cmd_wp, wp_help },
32687c478bd9Sstevel@tonic-gate #endif
32697c478bd9Sstevel@tonic-gate 
32707c478bd9Sstevel@tonic-gate 	{ NULL }
32717c478bd9Sstevel@tonic-gate };
3272