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 *)˙
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