xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_kvm.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Libkvm Kernel Target
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * The libkvm kernel target provides access to both crash dumps and live
33*7c478bd9Sstevel@tonic-gate  * kernels through /dev/ksyms and /dev/kmem, using the facilities provided by
34*7c478bd9Sstevel@tonic-gate  * the libkvm.so library.  The target-specific data structures are shared
35*7c478bd9Sstevel@tonic-gate  * between this file (common code) and the ISA-dependent parts of the target,
36*7c478bd9Sstevel@tonic-gate  * and so they are defined in the mdb_kvm.h header.  The target processes an
37*7c478bd9Sstevel@tonic-gate  * "executable" (/dev/ksyms or the unix.X file) which contains a primary
38*7c478bd9Sstevel@tonic-gate  * .symtab and .dynsym, and then also iterates over the krtld module chain in
39*7c478bd9Sstevel@tonic-gate  * the kernel in order to obtain a list of loaded modules and per-module symbol
40*7c478bd9Sstevel@tonic-gate  * tables.  To improve startup performance, the per-module symbol tables are
41*7c478bd9Sstevel@tonic-gate  * instantiated on-the-fly whenever an address lookup falls within the text
42*7c478bd9Sstevel@tonic-gate  * section of a given module.  The target also relies on services from the
43*7c478bd9Sstevel@tonic-gate  * mdb_ks (kernel support) module, which contains pieces of the implementation
44*7c478bd9Sstevel@tonic-gate  * that must be compiled against the kernel implementation.
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/panic.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h>
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
56*7c478bd9Sstevel@tonic-gate #include <libctf.h>
57*7c478bd9Sstevel@tonic-gate #include <string.h>
58*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
59*7c478bd9Sstevel@tonic-gate #include <errno.h>
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_target_impl.h>
62*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
63*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
64*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h>
65*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
66*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h>
67*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_ctf.h>
68*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_kvm.h>
69*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_module.h>
70*7c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define	KT_RELOC_BUF(buf, obase, nbase) \
73*7c478bd9Sstevel@tonic-gate 	((uintptr_t)(buf) - (uintptr_t)(obase) + (uintptr_t)(nbase))
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate #define	KT_BAD_BUF(buf, base, size) \
76*7c478bd9Sstevel@tonic-gate 	((uintptr_t)(buf) < (uintptr_t)(base) || \
77*7c478bd9Sstevel@tonic-gate 	((uintptr_t)(buf) >= (uintptr_t)(base) + (uintptr_t)(size)))
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate typedef struct kt_symarg {
80*7c478bd9Sstevel@tonic-gate 	mdb_tgt_sym_f *sym_cb;		/* Caller's callback function */
81*7c478bd9Sstevel@tonic-gate 	void *sym_data;			/* Callback function argument */
82*7c478bd9Sstevel@tonic-gate 	uint_t sym_type;		/* Symbol type/binding filter */
83*7c478bd9Sstevel@tonic-gate 	mdb_syminfo_t sym_info;		/* Symbol id and table id */
84*7c478bd9Sstevel@tonic-gate 	const char *sym_obj;		/* Containing object */
85*7c478bd9Sstevel@tonic-gate } kt_symarg_t;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate typedef struct kt_maparg {
88*7c478bd9Sstevel@tonic-gate 	mdb_tgt_t *map_target;		/* Target used for mapping iter */
89*7c478bd9Sstevel@tonic-gate 	mdb_tgt_map_f *map_cb;		/* Caller's callback function */
90*7c478bd9Sstevel@tonic-gate 	void *map_data;			/* Callback function argument */
91*7c478bd9Sstevel@tonic-gate } kt_maparg_t;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate static const char KT_RTLD_NAME[] = "krtld";
94*7c478bd9Sstevel@tonic-gate static const char KT_MODULE[] = "mdb_ks";
95*7c478bd9Sstevel@tonic-gate static const char KT_CTFPARENT[] = "genunix";
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate static void
98*7c478bd9Sstevel@tonic-gate kt_load_module(kt_data_t *kt, mdb_tgt_t *t, kt_module_t *km)
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate 	km->km_data = mdb_alloc(km->km_datasz, UM_SLEEP);
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_vread(t, km->km_data, km->km_datasz, km->km_symspace_va);
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	km->km_symbuf = (void *)
105*7c478bd9Sstevel@tonic-gate 	    KT_RELOC_BUF(km->km_symtab_va, km->km_symspace_va, km->km_data);
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	km->km_strtab = (char *)
108*7c478bd9Sstevel@tonic-gate 	    KT_RELOC_BUF(km->km_strtab_va, km->km_symspace_va, km->km_data);
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 	km->km_symtab = mdb_gelf_symtab_create_raw(&kt->k_file->gf_ehdr,
111*7c478bd9Sstevel@tonic-gate 	    &km->km_symtab_hdr, km->km_symbuf,
112*7c478bd9Sstevel@tonic-gate 	    &km->km_strtab_hdr, km->km_strtab, MDB_TGT_SYMTAB);
113*7c478bd9Sstevel@tonic-gate }
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate static void
116*7c478bd9Sstevel@tonic-gate kt_load_modules(kt_data_t *kt, mdb_tgt_t *t)
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate 	char name[MAXNAMELEN];
119*7c478bd9Sstevel@tonic-gate 	uintptr_t addr, head;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	struct module kmod;
122*7c478bd9Sstevel@tonic-gate 	struct modctl ctl;
123*7c478bd9Sstevel@tonic-gate 	Shdr symhdr, strhdr;
124*7c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	if (mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
129*7c478bd9Sstevel@tonic-gate 	    "modules", &sym, NULL) == -1) {
130*7c478bd9Sstevel@tonic-gate 		warn("failed to get 'modules' symbol");
131*7c478bd9Sstevel@tonic-gate 		return;
132*7c478bd9Sstevel@tonic-gate 	}
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &ctl, sizeof (ctl),
135*7c478bd9Sstevel@tonic-gate 	    MDB_TGT_OBJ_EXEC, "modules") != sizeof (ctl)) {
136*7c478bd9Sstevel@tonic-gate 		warn("failed to read 'modules' struct");
137*7c478bd9Sstevel@tonic-gate 		return;
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 	addr = head = (uintptr_t)sym.st_value;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	do {
143*7c478bd9Sstevel@tonic-gate 		if (addr == NULL)
144*7c478bd9Sstevel@tonic-gate 			break; /* Avoid spurious NULL pointers in list */
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &ctl, sizeof (ctl), addr) == -1) {
147*7c478bd9Sstevel@tonic-gate 			warn("failed to read modctl at %p", (void *)addr);
148*7c478bd9Sstevel@tonic-gate 			return;
149*7c478bd9Sstevel@tonic-gate 		}
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 		if (ctl.mod_mp == NULL)
152*7c478bd9Sstevel@tonic-gate 			continue; /* No associated krtld structure */
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT, name, MAXNAMELEN,
155*7c478bd9Sstevel@tonic-gate 		    (uintptr_t)ctl.mod_modname) <= 0) {
156*7c478bd9Sstevel@tonic-gate 			warn("failed to read module name at %p",
157*7c478bd9Sstevel@tonic-gate 			    (void *)ctl.mod_modname);
158*7c478bd9Sstevel@tonic-gate 			continue;
159*7c478bd9Sstevel@tonic-gate 		}
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 		mdb_dprintf(MDB_DBG_KMOD, "reading mod %s (%p)\n",
162*7c478bd9Sstevel@tonic-gate 		    name, (void *)addr);
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 		if (mdb_nv_lookup(&kt->k_modules, name) != NULL) {
165*7c478bd9Sstevel@tonic-gate 			warn("skipping duplicate module '%s', id=%d\n",
166*7c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
167*7c478bd9Sstevel@tonic-gate 			continue;
168*7c478bd9Sstevel@tonic-gate 		}
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &kmod, sizeof (kmod),
171*7c478bd9Sstevel@tonic-gate 		    (uintptr_t)ctl.mod_mp) == -1) {
172*7c478bd9Sstevel@tonic-gate 			warn("failed to read module at %p\n",
173*7c478bd9Sstevel@tonic-gate 			    (void *)ctl.mod_mp);
174*7c478bd9Sstevel@tonic-gate 			continue;
175*7c478bd9Sstevel@tonic-gate 		}
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 		if (kmod.symspace == NULL || kmod.symhdr == NULL ||
178*7c478bd9Sstevel@tonic-gate 		    kmod.strhdr == NULL) {
179*7c478bd9Sstevel@tonic-gate 			/*
180*7c478bd9Sstevel@tonic-gate 			 * If no buffer for the symbols has been allocated,
181*7c478bd9Sstevel@tonic-gate 			 * or the shdrs for .symtab and .strtab are missing,
182*7c478bd9Sstevel@tonic-gate 			 * then we're out of luck.
183*7c478bd9Sstevel@tonic-gate 			 */
184*7c478bd9Sstevel@tonic-gate 			continue;
185*7c478bd9Sstevel@tonic-gate 		}
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &symhdr, sizeof (Shdr),
188*7c478bd9Sstevel@tonic-gate 		    (uintptr_t)kmod.symhdr) == -1) {
189*7c478bd9Sstevel@tonic-gate 			warn("failed to read .symtab header for '%s', id=%d",
190*7c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
191*7c478bd9Sstevel@tonic-gate 			continue;
192*7c478bd9Sstevel@tonic-gate 		}
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &strhdr, sizeof (Shdr),
195*7c478bd9Sstevel@tonic-gate 		    (uintptr_t)kmod.strhdr) == -1) {
196*7c478bd9Sstevel@tonic-gate 			warn("failed to read .strtab header for '%s', id=%d",
197*7c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
198*7c478bd9Sstevel@tonic-gate 			continue;
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 		/*
202*7c478bd9Sstevel@tonic-gate 		 * Now get clever: f(*^ing krtld didn't used to bother updating
203*7c478bd9Sstevel@tonic-gate 		 * its own kmod.symsize value.  We know that prior to this bug
204*7c478bd9Sstevel@tonic-gate 		 * being fixed, symspace was a contiguous buffer containing
205*7c478bd9Sstevel@tonic-gate 		 * .symtab, .strtab, and the symbol hash table in that order.
206*7c478bd9Sstevel@tonic-gate 		 * So if symsize is zero, recompute it as the size of .symtab
207*7c478bd9Sstevel@tonic-gate 		 * plus the size of .strtab.  We don't need to load the hash
208*7c478bd9Sstevel@tonic-gate 		 * table anyway since we re-hash all the symbols internally.
209*7c478bd9Sstevel@tonic-gate 		 */
210*7c478bd9Sstevel@tonic-gate 		if (kmod.symsize == 0)
211*7c478bd9Sstevel@tonic-gate 			kmod.symsize = symhdr.sh_size + strhdr.sh_size;
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		/*
214*7c478bd9Sstevel@tonic-gate 		 * Similar logic can be used to make educated guesses
215*7c478bd9Sstevel@tonic-gate 		 * at the values of kmod.symtbl and kmod.strings.
216*7c478bd9Sstevel@tonic-gate 		 */
217*7c478bd9Sstevel@tonic-gate 		if (kmod.symtbl == NULL)
218*7c478bd9Sstevel@tonic-gate 			kmod.symtbl = kmod.symspace;
219*7c478bd9Sstevel@tonic-gate 		if (kmod.strings == NULL)
220*7c478bd9Sstevel@tonic-gate 			kmod.strings = kmod.symspace + symhdr.sh_size;
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 		/*
223*7c478bd9Sstevel@tonic-gate 		 * Make sure things seem reasonable before we proceed
224*7c478bd9Sstevel@tonic-gate 		 * to actually read and decipher the symspace.
225*7c478bd9Sstevel@tonic-gate 		 */
226*7c478bd9Sstevel@tonic-gate 		if (KT_BAD_BUF(kmod.symtbl, kmod.symspace, kmod.symsize) ||
227*7c478bd9Sstevel@tonic-gate 		    KT_BAD_BUF(kmod.strings, kmod.symspace, kmod.symsize)) {
228*7c478bd9Sstevel@tonic-gate 			warn("skipping module '%s', id=%d (corrupt symspace)\n",
229*7c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
230*7c478bd9Sstevel@tonic-gate 			continue;
231*7c478bd9Sstevel@tonic-gate 		}
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 		km = mdb_zalloc(sizeof (kt_module_t), UM_SLEEP);
234*7c478bd9Sstevel@tonic-gate 		km->km_name = strdup(name);
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 		(void) mdb_nv_insert(&kt->k_modules, km->km_name, NULL,
237*7c478bd9Sstevel@tonic-gate 		    (uintptr_t)km, MDB_NV_EXTNAME);
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		km->km_datasz = kmod.symsize;
240*7c478bd9Sstevel@tonic-gate 		km->km_symspace_va = (uintptr_t)kmod.symspace;
241*7c478bd9Sstevel@tonic-gate 		km->km_symtab_va = (uintptr_t)kmod.symtbl;
242*7c478bd9Sstevel@tonic-gate 		km->km_strtab_va = (uintptr_t)kmod.strings;
243*7c478bd9Sstevel@tonic-gate 		km->km_symtab_hdr = symhdr;
244*7c478bd9Sstevel@tonic-gate 		km->km_strtab_hdr = strhdr;
245*7c478bd9Sstevel@tonic-gate 		km->km_text_va = (uintptr_t)kmod.text;
246*7c478bd9Sstevel@tonic-gate 		km->km_text_size = kmod.text_size;
247*7c478bd9Sstevel@tonic-gate 		km->km_data_va = (uintptr_t)kmod.data;
248*7c478bd9Sstevel@tonic-gate 		km->km_data_size = kmod.data_size;
249*7c478bd9Sstevel@tonic-gate 		km->km_bss_va = (uintptr_t)kmod.bss;
250*7c478bd9Sstevel@tonic-gate 		km->km_bss_size = kmod.bss_size;
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 		if (kt->k_ctfvalid) {
253*7c478bd9Sstevel@tonic-gate 			km->km_ctf_va = (uintptr_t)kmod.ctfdata;
254*7c478bd9Sstevel@tonic-gate 			km->km_ctf_size = kmod.ctfsize;
255*7c478bd9Sstevel@tonic-gate 		}
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 		/*
258*7c478bd9Sstevel@tonic-gate 		 * Add the module to the end of the list of modules in load-
259*7c478bd9Sstevel@tonic-gate 		 * dependency order.  This is needed to load the corresponding
260*7c478bd9Sstevel@tonic-gate 		 * debugger modules in the same order for layering purposes.
261*7c478bd9Sstevel@tonic-gate 		 */
262*7c478bd9Sstevel@tonic-gate 		mdb_list_append(&kt->k_modlist, km);
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 		if (t->t_flags & MDB_TGT_F_PRELOAD) {
265*7c478bd9Sstevel@tonic-gate 			mdb_iob_printf(mdb.m_out, " %s", name);
266*7c478bd9Sstevel@tonic-gate 			mdb_iob_flush(mdb.m_out);
267*7c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
268*7c478bd9Sstevel@tonic-gate 		}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	} while ((addr = (uintptr_t)ctl.mod_next) != head);
271*7c478bd9Sstevel@tonic-gate }
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate int
274*7c478bd9Sstevel@tonic-gate kt_setflags(mdb_tgt_t *t, int flags)
275*7c478bd9Sstevel@tonic-gate {
276*7c478bd9Sstevel@tonic-gate 	int iochg = ((flags ^ t->t_flags) & MDB_TGT_F_ALLOWIO) &&
277*7c478bd9Sstevel@tonic-gate 	    !mdb_prop_postmortem;
278*7c478bd9Sstevel@tonic-gate 	int rwchg = (flags ^ t->t_flags) & MDB_TGT_F_RDWR;
279*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
280*7c478bd9Sstevel@tonic-gate 	const char *kvmfile;
281*7c478bd9Sstevel@tonic-gate 	kvm_t *cookie;
282*7c478bd9Sstevel@tonic-gate 	int mode;
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	if (!iochg && !rwchg)
285*7c478bd9Sstevel@tonic-gate 		return (0);
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	if (iochg) {
288*7c478bd9Sstevel@tonic-gate 		kvmfile = (flags & MDB_TGT_F_ALLOWIO) ? "/dev/allkmem" :
289*7c478bd9Sstevel@tonic-gate 		    "/dev/kmem";
290*7c478bd9Sstevel@tonic-gate 	} else {
291*7c478bd9Sstevel@tonic-gate 		kvmfile = kt->k_kvmfile;
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	mode = (flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	if ((cookie = kvm_open(kt->k_symfile, kvmfile, NULL, mode,
297*7c478bd9Sstevel@tonic-gate 	    mdb.m_pname)) == NULL) {
298*7c478bd9Sstevel@tonic-gate 		/* We failed to re-open, so don't change t_flags */
299*7c478bd9Sstevel@tonic-gate 		warn("failed to re-open target");
300*7c478bd9Sstevel@tonic-gate 		return (-1);
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	/*
304*7c478bd9Sstevel@tonic-gate 	 * We successfully reopened the target, so update k_kvmfile.  Also set
305*7c478bd9Sstevel@tonic-gate 	 * the RDWR and ALLOWIO bits in t_flags to match those in flags.
306*7c478bd9Sstevel@tonic-gate 	 */
307*7c478bd9Sstevel@tonic-gate 	(void) kvm_close(kt->k_cookie);
308*7c478bd9Sstevel@tonic-gate 	kt->k_cookie = cookie;
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	if (kvmfile != kt->k_kvmfile) {
311*7c478bd9Sstevel@tonic-gate 		strfree(kt->k_kvmfile);
312*7c478bd9Sstevel@tonic-gate 		kt->k_kvmfile = strdup(kvmfile);
313*7c478bd9Sstevel@tonic-gate 	}
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 	t->t_flags = (t->t_flags & ~(MDB_TGT_F_RDWR | MDB_TGT_F_ALLOWIO)) |
316*7c478bd9Sstevel@tonic-gate 	    (flags & (MDB_TGT_F_RDWR | MDB_TGT_F_ALLOWIO));
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	return (0);
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate /*
322*7c478bd9Sstevel@tonic-gate  * Determine which PIDs (if any) have their pages saved in the dump.  We
323*7c478bd9Sstevel@tonic-gate  * do this by looking for content flags in dump_flags in the header.  These
324*7c478bd9Sstevel@tonic-gate  * flags, which won't be set in older dumps, tell us whether a single process
325*7c478bd9Sstevel@tonic-gate  * has had its pages included in the dump.  If a single process has been
326*7c478bd9Sstevel@tonic-gate  * included, we need to get the PID for that process from the dump_pids
327*7c478bd9Sstevel@tonic-gate  * array in the dump.
328*7c478bd9Sstevel@tonic-gate  */
329*7c478bd9Sstevel@tonic-gate static int
330*7c478bd9Sstevel@tonic-gate kt_find_dump_contents(kt_data_t *kt)
331*7c478bd9Sstevel@tonic-gate {
332*7c478bd9Sstevel@tonic-gate 	dumphdr_t *dh = kt->k_dumphdr;
333*7c478bd9Sstevel@tonic-gate 	pid_t pid = -1;
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	if (dh->dump_flags & DF_ALL)
336*7c478bd9Sstevel@tonic-gate 		return (KT_DUMPCONTENT_ALL);
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	if (dh->dump_flags & DF_CURPROC) {
339*7c478bd9Sstevel@tonic-gate 		if ((pid = kt->k_dump_find_curproc()) == -1)
340*7c478bd9Sstevel@tonic-gate 			return (KT_DUMPCONTENT_INVALID);
341*7c478bd9Sstevel@tonic-gate 		else
342*7c478bd9Sstevel@tonic-gate 			return (pid);
343*7c478bd9Sstevel@tonic-gate 	} else {
344*7c478bd9Sstevel@tonic-gate 		return (KT_DUMPCONTENT_KERNEL);
345*7c478bd9Sstevel@tonic-gate 	}
346*7c478bd9Sstevel@tonic-gate }
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate static int
349*7c478bd9Sstevel@tonic-gate kt_dump_contains_proc(mdb_tgt_t *t, void *context)
350*7c478bd9Sstevel@tonic-gate {
351*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
352*7c478bd9Sstevel@tonic-gate 	pid_t (*f_pid)(uintptr_t);
353*7c478bd9Sstevel@tonic-gate 	pid_t reqpid;
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	switch (kt->k_dumpcontent) {
356*7c478bd9Sstevel@tonic-gate 	case KT_DUMPCONTENT_KERNEL:
357*7c478bd9Sstevel@tonic-gate 		return (0);
358*7c478bd9Sstevel@tonic-gate 	case KT_DUMPCONTENT_ALL:
359*7c478bd9Sstevel@tonic-gate 		return (1);
360*7c478bd9Sstevel@tonic-gate 	case KT_DUMPCONTENT_INVALID:
361*7c478bd9Sstevel@tonic-gate 		goto procnotfound;
362*7c478bd9Sstevel@tonic-gate 	default:
363*7c478bd9Sstevel@tonic-gate 		f_pid = (pid_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_pid");
364*7c478bd9Sstevel@tonic-gate 		if (f_pid == NULL)
365*7c478bd9Sstevel@tonic-gate 			goto procnotfound;
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 		reqpid = f_pid((uintptr_t)context);
368*7c478bd9Sstevel@tonic-gate 		if (reqpid == -1)
369*7c478bd9Sstevel@tonic-gate 			goto procnotfound;
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 		return (kt->k_dumpcontent == reqpid);
372*7c478bd9Sstevel@tonic-gate 	}
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate procnotfound:
375*7c478bd9Sstevel@tonic-gate 	warn("unable to determine whether dump contains proc %p\n", context);
376*7c478bd9Sstevel@tonic-gate 	return (1);
377*7c478bd9Sstevel@tonic-gate }
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate int
380*7c478bd9Sstevel@tonic-gate kt_setcontext(mdb_tgt_t *t, void *context)
381*7c478bd9Sstevel@tonic-gate {
382*7c478bd9Sstevel@tonic-gate 	if (context != NULL) {
383*7c478bd9Sstevel@tonic-gate 		const char *argv[2];
384*7c478bd9Sstevel@tonic-gate 		int argc = 0;
385*7c478bd9Sstevel@tonic-gate 		mdb_tgt_t *ct;
386*7c478bd9Sstevel@tonic-gate 		kt_data_t *kt = t->t_data;
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 		argv[argc++] = (const char *)context;
389*7c478bd9Sstevel@tonic-gate 		argv[argc] = NULL;
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 		if (kt->k_dumphdr != NULL &&
392*7c478bd9Sstevel@tonic-gate 		    !kt_dump_contains_proc(t, context)) {
393*7c478bd9Sstevel@tonic-gate 			warn("dump does not contain pages for proc %p\n",
394*7c478bd9Sstevel@tonic-gate 			    context);
395*7c478bd9Sstevel@tonic-gate 			return (-1);
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 		if ((ct = mdb_tgt_create(mdb_kproc_tgt_create,
399*7c478bd9Sstevel@tonic-gate 		    t->t_flags, argc, argv)) == NULL)
400*7c478bd9Sstevel@tonic-gate 			return (-1);
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 		mdb_printf("debugger context set to proc %p\n", context);
403*7c478bd9Sstevel@tonic-gate 		mdb_tgt_activate(ct);
404*7c478bd9Sstevel@tonic-gate 	} else
405*7c478bd9Sstevel@tonic-gate 		mdb_printf("debugger context set to kernel\n");
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 	return (0);
408*7c478bd9Sstevel@tonic-gate }
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate static int
411*7c478bd9Sstevel@tonic-gate kt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
412*7c478bd9Sstevel@tonic-gate {
413*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
414*7c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_stack(addr, flags, argc, argv));
415*7c478bd9Sstevel@tonic-gate }
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate static int
418*7c478bd9Sstevel@tonic-gate kt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
419*7c478bd9Sstevel@tonic-gate {
420*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
421*7c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_stackv(addr, flags, argc, argv));
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate static int
425*7c478bd9Sstevel@tonic-gate kt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
426*7c478bd9Sstevel@tonic-gate {
427*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
428*7c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_stackr(addr, flags, argc, argv));
429*7c478bd9Sstevel@tonic-gate }
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate static int
432*7c478bd9Sstevel@tonic-gate kt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
433*7c478bd9Sstevel@tonic-gate {
434*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
435*7c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_regs(addr, flags, argc, argv));
436*7c478bd9Sstevel@tonic-gate }
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
439*7c478bd9Sstevel@tonic-gate static int
440*7c478bd9Sstevel@tonic-gate kt_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
441*7c478bd9Sstevel@tonic-gate {
442*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
443*7c478bd9Sstevel@tonic-gate 	struct utsname uts;
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 	bzero(&uts, sizeof (uts));
446*7c478bd9Sstevel@tonic-gate 	(void) strcpy(uts.nodename, "unknown machine");
447*7c478bd9Sstevel@tonic-gate 	(void) kt_uname(mdb.m_target, &uts);
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	if (mdb_prop_postmortem) {
450*7c478bd9Sstevel@tonic-gate 		mdb_printf("debugging crash dump %s (%d-bit) from %s\n",
451*7c478bd9Sstevel@tonic-gate 		    kt->k_kvmfile, (int)(sizeof (void *) * NBBY), uts.nodename);
452*7c478bd9Sstevel@tonic-gate 	} else {
453*7c478bd9Sstevel@tonic-gate 		mdb_printf("debugging live kernel (%d-bit) on %s\n",
454*7c478bd9Sstevel@tonic-gate 		    (int)(sizeof (void *) * NBBY), uts.nodename);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	mdb_printf("operating system: %s %s (%s)\n",
458*7c478bd9Sstevel@tonic-gate 	    uts.release, uts.version, uts.machine);
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr) {
461*7c478bd9Sstevel@tonic-gate 		dumphdr_t *dh = kt->k_dumphdr;
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 		mdb_printf("panic message: %s\n", dh->dump_panicstring);
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 		kt->k_dump_print_content(dh, kt->k_dumpcontent);
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
469*7c478bd9Sstevel@tonic-gate }
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate static const mdb_dcmd_t kt_dcmds[] = {
472*7c478bd9Sstevel@tonic-gate 	{ "$c", "?[cnt]", "print stack backtrace", kt_stack },
473*7c478bd9Sstevel@tonic-gate 	{ "$C", "?[cnt]", "print stack backtrace", kt_stackv },
474*7c478bd9Sstevel@tonic-gate 	{ "$r", NULL, "print general-purpose registers", kt_regs },
475*7c478bd9Sstevel@tonic-gate 	{ "$?", NULL, "print status and registers", kt_regs },
476*7c478bd9Sstevel@tonic-gate 	{ "regs", NULL, "print general-purpose registers", kt_regs },
477*7c478bd9Sstevel@tonic-gate 	{ "stack", "?[cnt]", "print stack backtrace", kt_stack },
478*7c478bd9Sstevel@tonic-gate 	{ "stackregs", "?", "print stack backtrace and registers", kt_stackr },
479*7c478bd9Sstevel@tonic-gate 	{ "status", NULL, "print summary of current target", kt_status_dcmd },
480*7c478bd9Sstevel@tonic-gate 	{ NULL }
481*7c478bd9Sstevel@tonic-gate };
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate static uintmax_t
484*7c478bd9Sstevel@tonic-gate reg_disc_get(const mdb_var_t *v)
485*7c478bd9Sstevel@tonic-gate {
486*7c478bd9Sstevel@tonic-gate 	mdb_tgt_t *t = MDB_NV_COOKIE(v);
487*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
488*7c478bd9Sstevel@tonic-gate 	mdb_tgt_reg_t r = 0;
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_getareg(t, kt->k_tid, mdb_nv_get_name(v), &r);
491*7c478bd9Sstevel@tonic-gate 	return (r);
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate void
495*7c478bd9Sstevel@tonic-gate kt_activate(mdb_tgt_t *t)
496*7c478bd9Sstevel@tonic-gate {
497*7c478bd9Sstevel@tonic-gate 	static const mdb_nv_disc_t reg_disc = { NULL, reg_disc_get };
498*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
499*7c478bd9Sstevel@tonic-gate 	void *sym;
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	int oflag;
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	mdb_prop_postmortem = (kt->k_dumphdr != NULL);
504*7c478bd9Sstevel@tonic-gate 	mdb_prop_kernel = TRUE;
505*7c478bd9Sstevel@tonic-gate 	mdb_prop_datamodel = MDB_TGT_MODEL_NATIVE;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	if (kt->k_activated == FALSE) {
508*7c478bd9Sstevel@tonic-gate 		struct utsname u1, u2;
509*7c478bd9Sstevel@tonic-gate 		/*
510*7c478bd9Sstevel@tonic-gate 		 * If we're examining a crash dump, root is /, and uname(2)
511*7c478bd9Sstevel@tonic-gate 		 * does not match the utsname in the dump, issue a warning.
512*7c478bd9Sstevel@tonic-gate 		 * Note that we are assuming that the modules and macros in
513*7c478bd9Sstevel@tonic-gate 		 * /usr/lib are compiled against the kernel from uname -rv.
514*7c478bd9Sstevel@tonic-gate 		 */
515*7c478bd9Sstevel@tonic-gate 		if (mdb_prop_postmortem && strcmp(mdb.m_root, "/") == 0 &&
516*7c478bd9Sstevel@tonic-gate 		    uname(&u1) >= 0 && kt_uname(t, &u2) >= 0 &&
517*7c478bd9Sstevel@tonic-gate 		    (strcmp(u1.release, u2.release) ||
518*7c478bd9Sstevel@tonic-gate 		    strcmp(u1.version, u2.version))) {
519*7c478bd9Sstevel@tonic-gate 			mdb_warn("warning: dump is from %s %s %s; dcmds and "
520*7c478bd9Sstevel@tonic-gate 			    "macros may not match kernel implementation\n",
521*7c478bd9Sstevel@tonic-gate 			    u2.sysname, u2.release, u2.version);
522*7c478bd9Sstevel@tonic-gate 		}
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 		if (mdb_module_load(KT_MODULE, MDB_MOD_GLOBAL) < 0) {
525*7c478bd9Sstevel@tonic-gate 			warn("failed to load kernel support module -- "
526*7c478bd9Sstevel@tonic-gate 			    "some modules may not load\n");
527*7c478bd9Sstevel@tonic-gate 		}
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 		if (mdb_prop_postmortem) {
530*7c478bd9Sstevel@tonic-gate 			sym = dlsym(RTLD_NEXT, "mdb_dump_print_content");
531*7c478bd9Sstevel@tonic-gate 			if (sym != NULL)
532*7c478bd9Sstevel@tonic-gate 				kt->k_dump_print_content = (void (*)())sym;
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 			sym = dlsym(RTLD_NEXT, "mdb_dump_find_curproc");
535*7c478bd9Sstevel@tonic-gate 			if (sym != NULL)
536*7c478bd9Sstevel@tonic-gate 				kt->k_dump_find_curproc = (int (*)())sym;
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 			kt->k_dumpcontent = kt_find_dump_contents(kt);
539*7c478bd9Sstevel@tonic-gate 		}
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 		if (t->t_flags & MDB_TGT_F_PRELOAD) {
542*7c478bd9Sstevel@tonic-gate 			oflag = mdb_iob_getflags(mdb.m_out) & MDB_IOB_PGENABLE;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 			mdb_iob_clrflags(mdb.m_out, oflag);
545*7c478bd9Sstevel@tonic-gate 			mdb_iob_puts(mdb.m_out, "Preloading module symbols: [");
546*7c478bd9Sstevel@tonic-gate 			mdb_iob_flush(mdb.m_out);
547*7c478bd9Sstevel@tonic-gate 		}
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 		if (!(t->t_flags & MDB_TGT_F_NOLOAD))
550*7c478bd9Sstevel@tonic-gate 			kt_load_modules(kt, t);
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 		if (t->t_flags & MDB_TGT_F_PRELOAD) {
553*7c478bd9Sstevel@tonic-gate 			mdb_iob_puts(mdb.m_out, " ]\n");
554*7c478bd9Sstevel@tonic-gate 			mdb_iob_setflags(mdb.m_out, oflag);
555*7c478bd9Sstevel@tonic-gate 		}
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 		kt->k_activated = TRUE;
558*7c478bd9Sstevel@tonic-gate 	}
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_register_dcmds(t, &kt_dcmds[0], MDB_MOD_FORCE);
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 	/* Export some of our registers as named variables */
563*7c478bd9Sstevel@tonic-gate 	mdb_tgt_register_regvars(t, kt->k_rds, &reg_disc, MDB_NV_RDONLY);
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	mdb_tgt_elf_export(kt->k_file);
566*7c478bd9Sstevel@tonic-gate }
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate void
569*7c478bd9Sstevel@tonic-gate kt_deactivate(mdb_tgt_t *t)
570*7c478bd9Sstevel@tonic-gate {
571*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	const mdb_tgt_regdesc_t *rdp;
574*7c478bd9Sstevel@tonic-gate 	const mdb_dcmd_t *dcp;
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) {
577*7c478bd9Sstevel@tonic-gate 		mdb_var_t *v;
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 		if (!(rdp->rd_flags & MDB_TGT_R_EXPORT))
580*7c478bd9Sstevel@tonic-gate 			continue; /* Didn't export register as a variable */
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&mdb.m_nv, rdp->rd_name)) != NULL) {
583*7c478bd9Sstevel@tonic-gate 			v->v_flags &= ~MDB_NV_PERSIST;
584*7c478bd9Sstevel@tonic-gate 			mdb_nv_remove(&mdb.m_nv, v);
585*7c478bd9Sstevel@tonic-gate 		}
586*7c478bd9Sstevel@tonic-gate 	}
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	for (dcp = &kt_dcmds[0]; dcp->dc_name != NULL; dcp++) {
589*7c478bd9Sstevel@tonic-gate 		if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1)
590*7c478bd9Sstevel@tonic-gate 			warn("failed to remove dcmd %s", dcp->dc_name);
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	mdb_prop_postmortem = FALSE;
594*7c478bd9Sstevel@tonic-gate 	mdb_prop_kernel = FALSE;
595*7c478bd9Sstevel@tonic-gate 	mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN;
596*7c478bd9Sstevel@tonic-gate }
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
599*7c478bd9Sstevel@tonic-gate const char *
600*7c478bd9Sstevel@tonic-gate kt_name(mdb_tgt_t *t)
601*7c478bd9Sstevel@tonic-gate {
602*7c478bd9Sstevel@tonic-gate 	return ("kvm");
603*7c478bd9Sstevel@tonic-gate }
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate const char *
606*7c478bd9Sstevel@tonic-gate kt_platform(mdb_tgt_t *t)
607*7c478bd9Sstevel@tonic-gate {
608*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
609*7c478bd9Sstevel@tonic-gate 	return (kt->k_platform);
610*7c478bd9Sstevel@tonic-gate }
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate int
613*7c478bd9Sstevel@tonic-gate kt_uname(mdb_tgt_t *t, struct utsname *utsp)
614*7c478bd9Sstevel@tonic-gate {
615*7c478bd9Sstevel@tonic-gate 	return (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, utsp,
616*7c478bd9Sstevel@tonic-gate 	    sizeof (struct utsname), MDB_TGT_OBJ_EXEC, "utsname"));
617*7c478bd9Sstevel@tonic-gate }
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
620*7c478bd9Sstevel@tonic-gate int
621*7c478bd9Sstevel@tonic-gate kt_dmodel(mdb_tgt_t *t)
622*7c478bd9Sstevel@tonic-gate {
623*7c478bd9Sstevel@tonic-gate 	return (MDB_TGT_MODEL_NATIVE);
624*7c478bd9Sstevel@tonic-gate }
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate ssize_t
627*7c478bd9Sstevel@tonic-gate kt_aread(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf,
628*7c478bd9Sstevel@tonic-gate     size_t nbytes, mdb_tgt_addr_t addr)
629*7c478bd9Sstevel@tonic-gate {
630*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
631*7c478bd9Sstevel@tonic-gate 	ssize_t rval;
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	if ((rval = kt->k_aread(kt->k_cookie, addr, buf, nbytes, as)) == -1)
634*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	return (rval);
637*7c478bd9Sstevel@tonic-gate }
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate ssize_t
640*7c478bd9Sstevel@tonic-gate kt_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf,
641*7c478bd9Sstevel@tonic-gate     size_t nbytes, mdb_tgt_addr_t addr)
642*7c478bd9Sstevel@tonic-gate {
643*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
644*7c478bd9Sstevel@tonic-gate 	ssize_t rval;
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	if ((rval = kt->k_awrite(kt->k_cookie, addr, buf, nbytes, as)) == -1)
647*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 	return (rval);
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate ssize_t
653*7c478bd9Sstevel@tonic-gate kt_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
654*7c478bd9Sstevel@tonic-gate {
655*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
656*7c478bd9Sstevel@tonic-gate 	ssize_t rval;
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	if ((rval = kvm_kread(kt->k_cookie, addr, buf, nbytes)) == -1)
659*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	return (rval);
662*7c478bd9Sstevel@tonic-gate }
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate ssize_t
665*7c478bd9Sstevel@tonic-gate kt_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
666*7c478bd9Sstevel@tonic-gate {
667*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
668*7c478bd9Sstevel@tonic-gate 	ssize_t rval;
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate 	if ((rval = kvm_kwrite(kt->k_cookie, addr, buf, nbytes)) == -1)
671*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	return (rval);
674*7c478bd9Sstevel@tonic-gate }
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate ssize_t
677*7c478bd9Sstevel@tonic-gate kt_fread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
678*7c478bd9Sstevel@tonic-gate {
679*7c478bd9Sstevel@tonic-gate 	return (kt_vread(t, buf, nbytes, addr));
680*7c478bd9Sstevel@tonic-gate }
681*7c478bd9Sstevel@tonic-gate 
682*7c478bd9Sstevel@tonic-gate ssize_t
683*7c478bd9Sstevel@tonic-gate kt_fwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
684*7c478bd9Sstevel@tonic-gate {
685*7c478bd9Sstevel@tonic-gate 	return (kt_vwrite(t, buf, nbytes, addr));
686*7c478bd9Sstevel@tonic-gate }
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate ssize_t
689*7c478bd9Sstevel@tonic-gate kt_pread(mdb_tgt_t *t, void *buf, size_t nbytes, physaddr_t addr)
690*7c478bd9Sstevel@tonic-gate {
691*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
692*7c478bd9Sstevel@tonic-gate 	ssize_t rval;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	if ((rval = kt->k_pread(kt->k_cookie, addr, buf, nbytes)) == -1)
695*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 	return (rval);
698*7c478bd9Sstevel@tonic-gate }
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate ssize_t
701*7c478bd9Sstevel@tonic-gate kt_pwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, physaddr_t addr)
702*7c478bd9Sstevel@tonic-gate {
703*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
704*7c478bd9Sstevel@tonic-gate 	ssize_t rval;
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	if ((rval = kt->k_pwrite(kt->k_cookie, addr, buf, nbytes)) == -1)
707*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 	return (rval);
710*7c478bd9Sstevel@tonic-gate }
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate int
713*7c478bd9Sstevel@tonic-gate kt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap)
714*7c478bd9Sstevel@tonic-gate {
715*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	struct as *asp;
718*7c478bd9Sstevel@tonic-gate 	physaddr_t pa;
719*7c478bd9Sstevel@tonic-gate 	mdb_module_t *mod;
720*7c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
721*7c478bd9Sstevel@tonic-gate 	int (*fptr)(uintptr_t, struct as *, physaddr_t *);
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)as) {
724*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_PHYS:
725*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_FILE:
726*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_IO:
727*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
728*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_VIRT:
729*7c478bd9Sstevel@tonic-gate 		asp = kt->k_as;
730*7c478bd9Sstevel@tonic-gate 		break;
731*7c478bd9Sstevel@tonic-gate 	default:
732*7c478bd9Sstevel@tonic-gate 		asp = (struct as *)as;
733*7c478bd9Sstevel@tonic-gate 	}
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 	if ((pa = kvm_physaddr(kt->k_cookie, asp, va)) != -1ULL) {
736*7c478bd9Sstevel@tonic-gate 		*pap = pa;
737*7c478bd9Sstevel@tonic-gate 		return (0);
738*7c478bd9Sstevel@tonic-gate 	}
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 	if ((v = mdb_nv_lookup(&mdb.m_modules, "unix")) != NULL &&
741*7c478bd9Sstevel@tonic-gate 	    (mod = mdb_nv_get_cookie(v)) != NULL) {
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 		fptr = (int (*)(uintptr_t, struct as *, physaddr_t *))
744*7c478bd9Sstevel@tonic-gate 			dlsym(mod->mod_hdl, "platform_vtop");
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 		if ((fptr != NULL) && ((*fptr)(va, asp, pap) == 0))
747*7c478bd9Sstevel@tonic-gate 			return (0);
748*7c478bd9Sstevel@tonic-gate 	}
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	return (set_errno(EMDB_NOMAP));
751*7c478bd9Sstevel@tonic-gate }
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate int
754*7c478bd9Sstevel@tonic-gate kt_lookup_by_name(mdb_tgt_t *t, const char *obj, const char *name,
755*7c478bd9Sstevel@tonic-gate     GElf_Sym *symp, mdb_syminfo_t *sip)
756*7c478bd9Sstevel@tonic-gate {
757*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
758*7c478bd9Sstevel@tonic-gate 	kt_module_t *km, kmod;
759*7c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
760*7c478bd9Sstevel@tonic-gate 	int n;
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate 	/*
763*7c478bd9Sstevel@tonic-gate 	 * To simplify the implementation, we create a fake module on the stack
764*7c478bd9Sstevel@tonic-gate 	 * which is "prepended" to k_modlist and whose symtab is kt->k_symtab.
765*7c478bd9Sstevel@tonic-gate 	 */
766*7c478bd9Sstevel@tonic-gate 	kmod.km_symtab = kt->k_symtab;
767*7c478bd9Sstevel@tonic-gate 	kmod.km_list.ml_next = mdb_list_next(&kt->k_modlist);
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)obj) {
770*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EXEC:
771*7c478bd9Sstevel@tonic-gate 		km = &kmod;
772*7c478bd9Sstevel@tonic-gate 		n = 1;
773*7c478bd9Sstevel@tonic-gate 		break;
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EVERY:
776*7c478bd9Sstevel@tonic-gate 		km = &kmod;
777*7c478bd9Sstevel@tonic-gate 		n = mdb_nv_size(&kt->k_modules) + 1;
778*7c478bd9Sstevel@tonic-gate 		break;
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_RTLD:
781*7c478bd9Sstevel@tonic-gate 		obj = KT_RTLD_NAME;
782*7c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	default:
785*7c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&kt->k_modules, obj)) == NULL)
786*7c478bd9Sstevel@tonic-gate 			return (set_errno(EMDB_NOOBJ));
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 		km = mdb_nv_get_cookie(v);
789*7c478bd9Sstevel@tonic-gate 		n = 1;
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate 		if (km->km_symtab == NULL)
792*7c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
793*7c478bd9Sstevel@tonic-gate 	}
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	for (; n > 0; n--, km = mdb_list_next(km)) {
796*7c478bd9Sstevel@tonic-gate 		if (mdb_gelf_symtab_lookup_by_name(km->km_symtab, name,
797*7c478bd9Sstevel@tonic-gate 		    symp, &sip->sym_id) == 0) {
798*7c478bd9Sstevel@tonic-gate 			sip->sym_table = MDB_TGT_SYMTAB;
799*7c478bd9Sstevel@tonic-gate 			return (0);
800*7c478bd9Sstevel@tonic-gate 		}
801*7c478bd9Sstevel@tonic-gate 	}
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate 	return (set_errno(EMDB_NOSYM));
804*7c478bd9Sstevel@tonic-gate }
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate int
807*7c478bd9Sstevel@tonic-gate kt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags,
808*7c478bd9Sstevel@tonic-gate     char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip)
809*7c478bd9Sstevel@tonic-gate {
810*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
811*7c478bd9Sstevel@tonic-gate 	kt_module_t kmods[3], *kmods_begin = &kmods[0], *kmods_end;
812*7c478bd9Sstevel@tonic-gate 	const char *name;
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 	kt_module_t *km = &kmods[0];	/* Point km at first fake module */
815*7c478bd9Sstevel@tonic-gate 	kt_module_t *sym_km = NULL;	/* Module associated with best sym */
816*7c478bd9Sstevel@tonic-gate 	GElf_Sym sym;			/* Best symbol found so far if !exact */
817*7c478bd9Sstevel@tonic-gate 	uint_t symid;			/* ID of best symbol found so far */
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 	/*
820*7c478bd9Sstevel@tonic-gate 	 * To simplify the implementation, we create fake modules on the stack
821*7c478bd9Sstevel@tonic-gate 	 * that are "prepended" to k_modlist and whose symtab is set to
822*7c478bd9Sstevel@tonic-gate 	 * each of three special symbol tables, in order of precedence.
823*7c478bd9Sstevel@tonic-gate 	 */
824*7c478bd9Sstevel@tonic-gate 	km->km_symtab = mdb.m_prsym;
825*7c478bd9Sstevel@tonic-gate 
826*7c478bd9Sstevel@tonic-gate 	if (kt->k_symtab != NULL) {
827*7c478bd9Sstevel@tonic-gate 		km->km_list.ml_next = (mdb_list_t *)(km + 1);
828*7c478bd9Sstevel@tonic-gate 		km = mdb_list_next(km);
829*7c478bd9Sstevel@tonic-gate 		km->km_symtab = kt->k_symtab;
830*7c478bd9Sstevel@tonic-gate 	}
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 	if (kt->k_dynsym != NULL) {
833*7c478bd9Sstevel@tonic-gate 		km->km_list.ml_next = (mdb_list_t *)(km + 1);
834*7c478bd9Sstevel@tonic-gate 		km = mdb_list_next(km);
835*7c478bd9Sstevel@tonic-gate 		km->km_symtab = kt->k_dynsym;
836*7c478bd9Sstevel@tonic-gate 	}
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	km->km_list.ml_next = mdb_list_next(&kt->k_modlist);
839*7c478bd9Sstevel@tonic-gate 	kmods_end = km;
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate 	/*
842*7c478bd9Sstevel@tonic-gate 	 * Now iterate over the list of fake and real modules.  If the module
843*7c478bd9Sstevel@tonic-gate 	 * has no symbol table and the address is in the text section,
844*7c478bd9Sstevel@tonic-gate 	 * instantiate the module's symbol table.  In exact mode, we can
845*7c478bd9Sstevel@tonic-gate 	 * jump to 'found' immediately if we match.  Otherwise we continue
846*7c478bd9Sstevel@tonic-gate 	 * looking and improve our choice if we find a closer symbol.
847*7c478bd9Sstevel@tonic-gate 	 */
848*7c478bd9Sstevel@tonic-gate 	for (km = &kmods[0]; km != NULL; km = mdb_list_next(km)) {
849*7c478bd9Sstevel@tonic-gate 		if (km->km_symtab == NULL && addr >= km->km_text_va &&
850*7c478bd9Sstevel@tonic-gate 		    addr < km->km_text_va + km->km_text_size)
851*7c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 		if (mdb_gelf_symtab_lookup_by_addr(km->km_symtab, addr,
854*7c478bd9Sstevel@tonic-gate 		    flags, buf, nbytes, symp, &sip->sym_id) != 0 ||
855*7c478bd9Sstevel@tonic-gate 		    symp->st_value == 0)
856*7c478bd9Sstevel@tonic-gate 			continue;
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 		if (flags & MDB_TGT_SYM_EXACT) {
859*7c478bd9Sstevel@tonic-gate 			sym_km = km;
860*7c478bd9Sstevel@tonic-gate 			goto found;
861*7c478bd9Sstevel@tonic-gate 		}
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 		if (sym_km == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) {
864*7c478bd9Sstevel@tonic-gate 			sym_km = km;
865*7c478bd9Sstevel@tonic-gate 			sym = *symp;
866*7c478bd9Sstevel@tonic-gate 			symid = sip->sym_id;
867*7c478bd9Sstevel@tonic-gate 		}
868*7c478bd9Sstevel@tonic-gate 	}
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	if (sym_km == NULL)
871*7c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOSYMADDR));
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate 	*symp = sym; /* Copy our best symbol into the caller's symbol */
874*7c478bd9Sstevel@tonic-gate 	sip->sym_id = symid;
875*7c478bd9Sstevel@tonic-gate found:
876*7c478bd9Sstevel@tonic-gate 	/*
877*7c478bd9Sstevel@tonic-gate 	 * Once we've found something, copy the final name into the caller's
878*7c478bd9Sstevel@tonic-gate 	 * buffer and prefix it with the load object name if appropriate.
879*7c478bd9Sstevel@tonic-gate 	 */
880*7c478bd9Sstevel@tonic-gate 	name = mdb_gelf_sym_name(sym_km->km_symtab, symp);
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate 	if (sym_km < kmods_begin || sym_km > kmods_end) {
883*7c478bd9Sstevel@tonic-gate 		(void) mdb_snprintf(buf, nbytes, "%s`%s",
884*7c478bd9Sstevel@tonic-gate 		    sym_km->km_name, name);
885*7c478bd9Sstevel@tonic-gate 	} else if (nbytes > 0) {
886*7c478bd9Sstevel@tonic-gate 		(void) strncpy(buf, name, nbytes);
887*7c478bd9Sstevel@tonic-gate 		buf[nbytes - 1] = '\0';
888*7c478bd9Sstevel@tonic-gate 	}
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 	if (sym_km->km_symtab == mdb.m_prsym)
891*7c478bd9Sstevel@tonic-gate 		sip->sym_table = MDB_TGT_PRVSYM;
892*7c478bd9Sstevel@tonic-gate 	else
893*7c478bd9Sstevel@tonic-gate 		sip->sym_table = MDB_TGT_SYMTAB;
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate 	return (0);
896*7c478bd9Sstevel@tonic-gate }
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate static int
899*7c478bd9Sstevel@tonic-gate kt_symtab_func(void *data, const GElf_Sym *sym, const char *name, uint_t id)
900*7c478bd9Sstevel@tonic-gate {
901*7c478bd9Sstevel@tonic-gate 	kt_symarg_t *argp = data;
902*7c478bd9Sstevel@tonic-gate 
903*7c478bd9Sstevel@tonic-gate 	if (mdb_tgt_sym_match(sym, argp->sym_type)) {
904*7c478bd9Sstevel@tonic-gate 		argp->sym_info.sym_id = id;
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 		return (argp->sym_cb(argp->sym_data, sym, name,
907*7c478bd9Sstevel@tonic-gate 		    &argp->sym_info, argp->sym_obj));
908*7c478bd9Sstevel@tonic-gate 	}
909*7c478bd9Sstevel@tonic-gate 
910*7c478bd9Sstevel@tonic-gate 	return (0);
911*7c478bd9Sstevel@tonic-gate }
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate static void
914*7c478bd9Sstevel@tonic-gate kt_symtab_iter(mdb_gelf_symtab_t *gst, uint_t type, const char *obj,
915*7c478bd9Sstevel@tonic-gate     mdb_tgt_sym_f *cb, void *p)
916*7c478bd9Sstevel@tonic-gate {
917*7c478bd9Sstevel@tonic-gate 	kt_symarg_t arg;
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate 	arg.sym_cb = cb;
920*7c478bd9Sstevel@tonic-gate 	arg.sym_data = p;
921*7c478bd9Sstevel@tonic-gate 	arg.sym_type = type;
922*7c478bd9Sstevel@tonic-gate 	arg.sym_info.sym_table = gst->gst_tabid;
923*7c478bd9Sstevel@tonic-gate 	arg.sym_obj = obj;
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate 	mdb_gelf_symtab_iter(gst, kt_symtab_func, &arg);
926*7c478bd9Sstevel@tonic-gate }
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate int
929*7c478bd9Sstevel@tonic-gate kt_symbol_iter(mdb_tgt_t *t, const char *obj, uint_t which, uint_t type,
930*7c478bd9Sstevel@tonic-gate     mdb_tgt_sym_f *cb, void *data)
931*7c478bd9Sstevel@tonic-gate {
932*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
933*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate 	mdb_gelf_symtab_t *symtab = NULL;
936*7c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
937*7c478bd9Sstevel@tonic-gate 
938*7c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)obj) {
939*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EXEC:
940*7c478bd9Sstevel@tonic-gate 		if (which == MDB_TGT_SYMTAB)
941*7c478bd9Sstevel@tonic-gate 			symtab = kt->k_symtab;
942*7c478bd9Sstevel@tonic-gate 		else
943*7c478bd9Sstevel@tonic-gate 			symtab = kt->k_dynsym;
944*7c478bd9Sstevel@tonic-gate 		break;
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EVERY:
947*7c478bd9Sstevel@tonic-gate 		if (which == MDB_TGT_DYNSYM) {
948*7c478bd9Sstevel@tonic-gate 			symtab = kt->k_dynsym;
949*7c478bd9Sstevel@tonic-gate 			obj = MDB_TGT_OBJ_EXEC;
950*7c478bd9Sstevel@tonic-gate 			break;
951*7c478bd9Sstevel@tonic-gate 		}
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate 		mdb_nv_rewind(&kt->k_modules);
954*7c478bd9Sstevel@tonic-gate 		while ((v = mdb_nv_advance(&kt->k_modules)) != NULL) {
955*7c478bd9Sstevel@tonic-gate 			km = mdb_nv_get_cookie(v);
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate 			if (km->km_symtab == NULL)
958*7c478bd9Sstevel@tonic-gate 				kt_load_module(kt, t, km);
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 			if (km->km_symtab != NULL)
961*7c478bd9Sstevel@tonic-gate 				kt_symtab_iter(km->km_symtab, type,
962*7c478bd9Sstevel@tonic-gate 				    km->km_name, cb, data);
963*7c478bd9Sstevel@tonic-gate 		}
964*7c478bd9Sstevel@tonic-gate 		break;
965*7c478bd9Sstevel@tonic-gate 
966*7c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_RTLD:
967*7c478bd9Sstevel@tonic-gate 		obj = KT_RTLD_NAME;
968*7c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 	default:
971*7c478bd9Sstevel@tonic-gate 		v = mdb_nv_lookup(&kt->k_modules, obj);
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate 		if (v == NULL)
974*7c478bd9Sstevel@tonic-gate 			return (set_errno(EMDB_NOOBJ));
975*7c478bd9Sstevel@tonic-gate 
976*7c478bd9Sstevel@tonic-gate 		km = mdb_nv_get_cookie(v);
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 		if (km->km_symtab == NULL)
979*7c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
980*7c478bd9Sstevel@tonic-gate 
981*7c478bd9Sstevel@tonic-gate 		symtab = km->km_symtab;
982*7c478bd9Sstevel@tonic-gate 	}
983*7c478bd9Sstevel@tonic-gate 
984*7c478bd9Sstevel@tonic-gate 	if (symtab)
985*7c478bd9Sstevel@tonic-gate 		kt_symtab_iter(symtab, type, obj, cb, data);
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 	return (0);
988*7c478bd9Sstevel@tonic-gate }
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate static int
991*7c478bd9Sstevel@tonic-gate kt_mapping_walk(uintptr_t addr, const void *data, kt_maparg_t *marg)
992*7c478bd9Sstevel@tonic-gate {
993*7c478bd9Sstevel@tonic-gate 	/*
994*7c478bd9Sstevel@tonic-gate 	 * This is a bit sketchy but avoids problematic compilation of this
995*7c478bd9Sstevel@tonic-gate 	 * target against the current VM implementation.  Now that we have
996*7c478bd9Sstevel@tonic-gate 	 * vmem, we can make this less broken and more informative by changing
997*7c478bd9Sstevel@tonic-gate 	 * this code to invoke the vmem walker in the near future.
998*7c478bd9Sstevel@tonic-gate 	 */
999*7c478bd9Sstevel@tonic-gate 	const struct kt_seg {
1000*7c478bd9Sstevel@tonic-gate 		caddr_t s_base;
1001*7c478bd9Sstevel@tonic-gate 		size_t s_size;
1002*7c478bd9Sstevel@tonic-gate 	} *segp = (const struct kt_seg *)data;
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 	mdb_map_t map;
1005*7c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
1006*7c478bd9Sstevel@tonic-gate 	mdb_syminfo_t info;
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 	map.map_base = (uintptr_t)segp->s_base;
1009*7c478bd9Sstevel@tonic-gate 	map.map_size = segp->s_size;
1010*7c478bd9Sstevel@tonic-gate 	map.map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_W | MDB_TGT_MAP_X;
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate 	if (kt_lookup_by_addr(marg->map_target, addr, MDB_TGT_SYM_EXACT,
1013*7c478bd9Sstevel@tonic-gate 	    map.map_name, MDB_TGT_MAPSZ, &sym, &info) == -1) {
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate 		(void) mdb_iob_snprintf(map.map_name, MDB_TGT_MAPSZ,
1016*7c478bd9Sstevel@tonic-gate 		    "%lr", addr);
1017*7c478bd9Sstevel@tonic-gate 	}
1018*7c478bd9Sstevel@tonic-gate 
1019*7c478bd9Sstevel@tonic-gate 	return (marg->map_cb(marg->map_data, &map, map.map_name));
1020*7c478bd9Sstevel@tonic-gate }
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate int
1023*7c478bd9Sstevel@tonic-gate kt_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
1024*7c478bd9Sstevel@tonic-gate {
1025*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1026*7c478bd9Sstevel@tonic-gate 	kt_maparg_t m;
1027*7c478bd9Sstevel@tonic-gate 
1028*7c478bd9Sstevel@tonic-gate 	m.map_target = t;
1029*7c478bd9Sstevel@tonic-gate 	m.map_cb = func;
1030*7c478bd9Sstevel@tonic-gate 	m.map_data = private;
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate 	return (mdb_pwalk("seg", (mdb_walk_cb_t)kt_mapping_walk, &m,
1033*7c478bd9Sstevel@tonic-gate 	    (uintptr_t)kt->k_as));
1034*7c478bd9Sstevel@tonic-gate }
1035*7c478bd9Sstevel@tonic-gate 
1036*7c478bd9Sstevel@tonic-gate static const mdb_map_t *
1037*7c478bd9Sstevel@tonic-gate kt_module_to_map(kt_module_t *km, mdb_map_t *map)
1038*7c478bd9Sstevel@tonic-gate {
1039*7c478bd9Sstevel@tonic-gate 	(void) strncpy(map->map_name, km->km_name, MDB_TGT_MAPSZ);
1040*7c478bd9Sstevel@tonic-gate 	map->map_name[MDB_TGT_MAPSZ - 1] = '\0';
1041*7c478bd9Sstevel@tonic-gate 	map->map_base = km->km_text_va;
1042*7c478bd9Sstevel@tonic-gate 	map->map_size = km->km_text_size;
1043*7c478bd9Sstevel@tonic-gate 	map->map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_W | MDB_TGT_MAP_X;
1044*7c478bd9Sstevel@tonic-gate 
1045*7c478bd9Sstevel@tonic-gate 	return (map);
1046*7c478bd9Sstevel@tonic-gate }
1047*7c478bd9Sstevel@tonic-gate 
1048*7c478bd9Sstevel@tonic-gate int
1049*7c478bd9Sstevel@tonic-gate kt_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
1050*7c478bd9Sstevel@tonic-gate {
1051*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1052*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
1053*7c478bd9Sstevel@tonic-gate 	mdb_map_t m;
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
1056*7c478bd9Sstevel@tonic-gate 		if (func(private, kt_module_to_map(km, &m), km->km_name) == -1)
1057*7c478bd9Sstevel@tonic-gate 			break;
1058*7c478bd9Sstevel@tonic-gate 	}
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	return (0);
1061*7c478bd9Sstevel@tonic-gate }
1062*7c478bd9Sstevel@tonic-gate 
1063*7c478bd9Sstevel@tonic-gate const mdb_map_t *
1064*7c478bd9Sstevel@tonic-gate kt_addr_to_map(mdb_tgt_t *t, uintptr_t addr)
1065*7c478bd9Sstevel@tonic-gate {
1066*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1067*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
1068*7c478bd9Sstevel@tonic-gate 
1069*7c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
1070*7c478bd9Sstevel@tonic-gate 		if (addr - km->km_text_va < km->km_text_size ||
1071*7c478bd9Sstevel@tonic-gate 		    addr - km->km_data_va < km->km_data_size ||
1072*7c478bd9Sstevel@tonic-gate 		    addr - km->km_bss_va < km->km_bss_size)
1073*7c478bd9Sstevel@tonic-gate 			return (kt_module_to_map(km, &kt->k_map));
1074*7c478bd9Sstevel@tonic-gate 	}
1075*7c478bd9Sstevel@tonic-gate 
1076*7c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOMAP);
1077*7c478bd9Sstevel@tonic-gate 	return (NULL);
1078*7c478bd9Sstevel@tonic-gate }
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate const mdb_map_t *
1081*7c478bd9Sstevel@tonic-gate kt_name_to_map(mdb_tgt_t *t, const char *name)
1082*7c478bd9Sstevel@tonic-gate {
1083*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1084*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
1085*7c478bd9Sstevel@tonic-gate 	mdb_map_t m;
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 	/*
1088*7c478bd9Sstevel@tonic-gate 	 * If name is MDB_TGT_OBJ_EXEC, return the first module on the list,
1089*7c478bd9Sstevel@tonic-gate 	 * which will be unix since we keep k_modlist in load order.
1090*7c478bd9Sstevel@tonic-gate 	 */
1091*7c478bd9Sstevel@tonic-gate 	if (name == MDB_TGT_OBJ_EXEC)
1092*7c478bd9Sstevel@tonic-gate 		return (kt_module_to_map(mdb_list_next(&kt->k_modlist), &m));
1093*7c478bd9Sstevel@tonic-gate 
1094*7c478bd9Sstevel@tonic-gate 	if (name == MDB_TGT_OBJ_RTLD)
1095*7c478bd9Sstevel@tonic-gate 		name = KT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
1098*7c478bd9Sstevel@tonic-gate 		if (strcmp(name, km->km_name) == 0)
1099*7c478bd9Sstevel@tonic-gate 			return (kt_module_to_map(km, &m));
1100*7c478bd9Sstevel@tonic-gate 	}
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOOBJ);
1103*7c478bd9Sstevel@tonic-gate 	return (NULL);
1104*7c478bd9Sstevel@tonic-gate }
1105*7c478bd9Sstevel@tonic-gate 
1106*7c478bd9Sstevel@tonic-gate static ctf_file_t *
1107*7c478bd9Sstevel@tonic-gate kt_load_ctfdata(mdb_tgt_t *t, kt_module_t *km)
1108*7c478bd9Sstevel@tonic-gate {
1109*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1110*7c478bd9Sstevel@tonic-gate 	int err;
1111*7c478bd9Sstevel@tonic-gate 
1112*7c478bd9Sstevel@tonic-gate 	if (km->km_ctfp != NULL)
1113*7c478bd9Sstevel@tonic-gate 		return (km->km_ctfp);
1114*7c478bd9Sstevel@tonic-gate 
1115*7c478bd9Sstevel@tonic-gate 	if (km->km_ctf_va == NULL) {
1116*7c478bd9Sstevel@tonic-gate 		(void) set_errno(EMDB_NOCTF);
1117*7c478bd9Sstevel@tonic-gate 		return (NULL);
1118*7c478bd9Sstevel@tonic-gate 	}
1119*7c478bd9Sstevel@tonic-gate 
1120*7c478bd9Sstevel@tonic-gate 	if (km->km_symtab == NULL)
1121*7c478bd9Sstevel@tonic-gate 		kt_load_module(t->t_data, t, km);
1122*7c478bd9Sstevel@tonic-gate 
1123*7c478bd9Sstevel@tonic-gate 	if ((km->km_ctf_buf = mdb_alloc(km->km_ctf_size, UM_NOSLEEP)) == NULL) {
1124*7c478bd9Sstevel@tonic-gate 		warn("failed to allocate memory to load %s debugging "
1125*7c478bd9Sstevel@tonic-gate 		    "information", km->km_name);
1126*7c478bd9Sstevel@tonic-gate 		return (NULL);
1127*7c478bd9Sstevel@tonic-gate 	}
1128*7c478bd9Sstevel@tonic-gate 
1129*7c478bd9Sstevel@tonic-gate 	if (mdb_tgt_vread(t, km->km_ctf_buf, km->km_ctf_size,
1130*7c478bd9Sstevel@tonic-gate 	    km->km_ctf_va) != km->km_ctf_size) {
1131*7c478bd9Sstevel@tonic-gate 		warn("failed to read %lu bytes of debug data for %s at %p",
1132*7c478bd9Sstevel@tonic-gate 		    (ulong_t)km->km_ctf_size, km->km_name,
1133*7c478bd9Sstevel@tonic-gate 		    (void *)km->km_ctf_va);
1134*7c478bd9Sstevel@tonic-gate 		mdb_free(km->km_ctf_buf, km->km_ctf_size);
1135*7c478bd9Sstevel@tonic-gate 		km->km_ctf_buf = NULL;
1136*7c478bd9Sstevel@tonic-gate 		return (NULL);
1137*7c478bd9Sstevel@tonic-gate 	}
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate 	if ((km->km_ctfp = mdb_ctf_bufopen((const void *)km->km_ctf_buf,
1140*7c478bd9Sstevel@tonic-gate 	    km->km_ctf_size, km->km_symbuf, &km->km_symtab_hdr,
1141*7c478bd9Sstevel@tonic-gate 	    km->km_strtab, &km->km_strtab_hdr, &err)) == NULL) {
1142*7c478bd9Sstevel@tonic-gate 		mdb_free(km->km_ctf_buf, km->km_ctf_size);
1143*7c478bd9Sstevel@tonic-gate 		km->km_ctf_buf = NULL;
1144*7c478bd9Sstevel@tonic-gate 		(void) set_errno(ctf_to_errno(err));
1145*7c478bd9Sstevel@tonic-gate 		return (NULL);
1146*7c478bd9Sstevel@tonic-gate 	}
1147*7c478bd9Sstevel@tonic-gate 
1148*7c478bd9Sstevel@tonic-gate 	mdb_dprintf(MDB_DBG_KMOD, "loaded %lu bytes of CTF data for %s\n",
1149*7c478bd9Sstevel@tonic-gate 	    (ulong_t)km->km_ctf_size, km->km_name);
1150*7c478bd9Sstevel@tonic-gate 
1151*7c478bd9Sstevel@tonic-gate 	if (ctf_parent_name(km->km_ctfp) != NULL) {
1152*7c478bd9Sstevel@tonic-gate 		mdb_var_t *v;
1153*7c478bd9Sstevel@tonic-gate 
1154*7c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&kt->k_modules,
1155*7c478bd9Sstevel@tonic-gate 		    ctf_parent_name(km->km_ctfp))) == NULL) {
1156*7c478bd9Sstevel@tonic-gate 			warn("failed to load CTF data for %s - parent %s not "
1157*7c478bd9Sstevel@tonic-gate 			    "loaded\n", km->km_name,
1158*7c478bd9Sstevel@tonic-gate 			    ctf_parent_name(km->km_ctfp));
1159*7c478bd9Sstevel@tonic-gate 		}
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 		if (v != NULL) {
1162*7c478bd9Sstevel@tonic-gate 			kt_module_t *pm = mdb_nv_get_cookie(v);
1163*7c478bd9Sstevel@tonic-gate 
1164*7c478bd9Sstevel@tonic-gate 			if (pm->km_ctfp == NULL)
1165*7c478bd9Sstevel@tonic-gate 				(void) kt_load_ctfdata(t, pm);
1166*7c478bd9Sstevel@tonic-gate 
1167*7c478bd9Sstevel@tonic-gate 			if (pm->km_ctfp != NULL && ctf_import(km->km_ctfp,
1168*7c478bd9Sstevel@tonic-gate 			    pm->km_ctfp) == CTF_ERR) {
1169*7c478bd9Sstevel@tonic-gate 				warn("failed to import parent types into "
1170*7c478bd9Sstevel@tonic-gate 				    "%s: %s\n", km->km_name,
1171*7c478bd9Sstevel@tonic-gate 				    ctf_errmsg(ctf_errno(km->km_ctfp)));
1172*7c478bd9Sstevel@tonic-gate 			}
1173*7c478bd9Sstevel@tonic-gate 		}
1174*7c478bd9Sstevel@tonic-gate 	}
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate 	return (km->km_ctfp);
1177*7c478bd9Sstevel@tonic-gate }
1178*7c478bd9Sstevel@tonic-gate 
1179*7c478bd9Sstevel@tonic-gate ctf_file_t *
1180*7c478bd9Sstevel@tonic-gate kt_addr_to_ctf(mdb_tgt_t *t, uintptr_t addr)
1181*7c478bd9Sstevel@tonic-gate {
1182*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1183*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
1184*7c478bd9Sstevel@tonic-gate 
1185*7c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
1186*7c478bd9Sstevel@tonic-gate 		if (addr - km->km_text_va < km->km_text_size ||
1187*7c478bd9Sstevel@tonic-gate 		    addr - km->km_data_va < km->km_data_size ||
1188*7c478bd9Sstevel@tonic-gate 		    addr - km->km_bss_va < km->km_bss_size)
1189*7c478bd9Sstevel@tonic-gate 			return (kt_load_ctfdata(t, km));
1190*7c478bd9Sstevel@tonic-gate 	}
1191*7c478bd9Sstevel@tonic-gate 
1192*7c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOMAP);
1193*7c478bd9Sstevel@tonic-gate 	return (NULL);
1194*7c478bd9Sstevel@tonic-gate }
1195*7c478bd9Sstevel@tonic-gate 
1196*7c478bd9Sstevel@tonic-gate ctf_file_t *
1197*7c478bd9Sstevel@tonic-gate kt_name_to_ctf(mdb_tgt_t *t, const char *name)
1198*7c478bd9Sstevel@tonic-gate {
1199*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1200*7c478bd9Sstevel@tonic-gate 	kt_module_t *km;
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate 	if (name == MDB_TGT_OBJ_EXEC)
1203*7c478bd9Sstevel@tonic-gate 		name = KT_CTFPARENT; /* base CTF data is kept in genunix */
1204*7c478bd9Sstevel@tonic-gate 	else if (name == MDB_TGT_OBJ_RTLD)
1205*7c478bd9Sstevel@tonic-gate 		name = KT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */
1206*7c478bd9Sstevel@tonic-gate 
1207*7c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
1208*7c478bd9Sstevel@tonic-gate 		if (strcmp(name, km->km_name) == 0)
1209*7c478bd9Sstevel@tonic-gate 			return (kt_load_ctfdata(t, km));
1210*7c478bd9Sstevel@tonic-gate 	}
1211*7c478bd9Sstevel@tonic-gate 
1212*7c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOOBJ);
1213*7c478bd9Sstevel@tonic-gate 	return (NULL);
1214*7c478bd9Sstevel@tonic-gate }
1215*7c478bd9Sstevel@tonic-gate 
1216*7c478bd9Sstevel@tonic-gate int
1217*7c478bd9Sstevel@tonic-gate kt_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
1218*7c478bd9Sstevel@tonic-gate {
1219*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate 	bzero(tsp, sizeof (mdb_tgt_status_t));
1222*7c478bd9Sstevel@tonic-gate 	tsp->st_state = kt->k_dumphdr ? MDB_TGT_DEAD : MDB_TGT_RUNNING;
1223*7c478bd9Sstevel@tonic-gate 	return (0);
1224*7c478bd9Sstevel@tonic-gate }
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate static ssize_t
1227*7c478bd9Sstevel@tonic-gate kt_xd_dumphdr(mdb_tgt_t *t, void *buf, size_t nbytes)
1228*7c478bd9Sstevel@tonic-gate {
1229*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate 	if (buf == NULL && nbytes == 0)
1232*7c478bd9Sstevel@tonic-gate 		return (sizeof (dumphdr_t));
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr == NULL)
1235*7c478bd9Sstevel@tonic-gate 		return (set_errno(ENODATA));
1236*7c478bd9Sstevel@tonic-gate 
1237*7c478bd9Sstevel@tonic-gate 	nbytes = MIN(nbytes, sizeof (dumphdr_t));
1238*7c478bd9Sstevel@tonic-gate 	bcopy(kt->k_dumphdr, buf, nbytes);
1239*7c478bd9Sstevel@tonic-gate 
1240*7c478bd9Sstevel@tonic-gate 	return (nbytes);
1241*7c478bd9Sstevel@tonic-gate }
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate void
1244*7c478bd9Sstevel@tonic-gate kt_destroy(mdb_tgt_t *t)
1245*7c478bd9Sstevel@tonic-gate {
1246*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
1247*7c478bd9Sstevel@tonic-gate 	kt_module_t *km, *nkm;
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate 	(void) mdb_module_unload(KT_MODULE, 0);
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate 	if (kt->k_regs != NULL)
1252*7c478bd9Sstevel@tonic-gate 		mdb_free(kt->k_regs, kt->k_regsize);
1253*7c478bd9Sstevel@tonic-gate 
1254*7c478bd9Sstevel@tonic-gate 	if (kt->k_symtab != NULL)
1255*7c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_symtab);
1256*7c478bd9Sstevel@tonic-gate 
1257*7c478bd9Sstevel@tonic-gate 	if (kt->k_dynsym != NULL)
1258*7c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_dynsym);
1259*7c478bd9Sstevel@tonic-gate 
1260*7c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr != NULL)
1261*7c478bd9Sstevel@tonic-gate 		mdb_free(kt->k_dumphdr, sizeof (dumphdr_t));
1262*7c478bd9Sstevel@tonic-gate 
1263*7c478bd9Sstevel@tonic-gate 	mdb_gelf_destroy(kt->k_file);
1264*7c478bd9Sstevel@tonic-gate 	(void) kvm_close(kt->k_cookie);
1265*7c478bd9Sstevel@tonic-gate 
1266*7c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = nkm) {
1267*7c478bd9Sstevel@tonic-gate 		if (km->km_symtab)
1268*7c478bd9Sstevel@tonic-gate 			mdb_gelf_symtab_destroy(km->km_symtab);
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate 		if (km->km_data)
1271*7c478bd9Sstevel@tonic-gate 			mdb_free(km->km_data, km->km_datasz);
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 		if (km->km_ctfp)
1274*7c478bd9Sstevel@tonic-gate 			ctf_close(km->km_ctfp);
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate 		if (km->km_ctf_buf != NULL)
1277*7c478bd9Sstevel@tonic-gate 			mdb_free(km->km_ctf_buf, km->km_ctf_size);
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate 		nkm = mdb_list_next(km);
1280*7c478bd9Sstevel@tonic-gate 		strfree(km->km_name);
1281*7c478bd9Sstevel@tonic-gate 		mdb_free(km, sizeof (kt_module_t));
1282*7c478bd9Sstevel@tonic-gate 	}
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate 	mdb_nv_destroy(&kt->k_modules);
1285*7c478bd9Sstevel@tonic-gate 
1286*7c478bd9Sstevel@tonic-gate 	strfree(kt->k_kvmfile);
1287*7c478bd9Sstevel@tonic-gate 	strfree(kt->k_symfile);
1288*7c478bd9Sstevel@tonic-gate 
1289*7c478bd9Sstevel@tonic-gate 	mdb_free(kt, sizeof (kt_data_t));
1290*7c478bd9Sstevel@tonic-gate }
1291*7c478bd9Sstevel@tonic-gate 
1292*7c478bd9Sstevel@tonic-gate static int
1293*7c478bd9Sstevel@tonic-gate kt_data_stub(void)
1294*7c478bd9Sstevel@tonic-gate {
1295*7c478bd9Sstevel@tonic-gate 	return (-1);
1296*7c478bd9Sstevel@tonic-gate }
1297*7c478bd9Sstevel@tonic-gate 
1298*7c478bd9Sstevel@tonic-gate int
1299*7c478bd9Sstevel@tonic-gate mdb_kvm_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
1300*7c478bd9Sstevel@tonic-gate {
1301*7c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb_zalloc(sizeof (kt_data_t), UM_SLEEP);
1302*7c478bd9Sstevel@tonic-gate 	int oflag = (t->t_flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY;
1303*7c478bd9Sstevel@tonic-gate 
1304*7c478bd9Sstevel@tonic-gate 	struct utsname uts;
1305*7c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
1306*7c478bd9Sstevel@tonic-gate 	pgcnt_t pmem;
1307*7c478bd9Sstevel@tonic-gate 
1308*7c478bd9Sstevel@tonic-gate 	if (argc != 2)
1309*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
1310*7c478bd9Sstevel@tonic-gate 
1311*7c478bd9Sstevel@tonic-gate 	kt->k_symfile = strdup(argv[0]);
1312*7c478bd9Sstevel@tonic-gate 	kt->k_kvmfile = strdup(argv[1]);
1313*7c478bd9Sstevel@tonic-gate 
1314*7c478bd9Sstevel@tonic-gate 	if ((kt->k_cookie = kvm_open(kt->k_symfile, kt->k_kvmfile, NULL,
1315*7c478bd9Sstevel@tonic-gate 	    oflag, (char *)mdb.m_pname)) == NULL)
1316*7c478bd9Sstevel@tonic-gate 		goto err;
1317*7c478bd9Sstevel@tonic-gate 
1318*7c478bd9Sstevel@tonic-gate 	if ((kt->k_fio = mdb_fdio_create_path(NULL, kt->k_symfile,
1319*7c478bd9Sstevel@tonic-gate 	    O_RDONLY, 0)) == NULL) {
1320*7c478bd9Sstevel@tonic-gate 		mdb_warn("failed to open %s", kt->k_symfile);
1321*7c478bd9Sstevel@tonic-gate 		goto err;
1322*7c478bd9Sstevel@tonic-gate 	}
1323*7c478bd9Sstevel@tonic-gate 
1324*7c478bd9Sstevel@tonic-gate 	if ((kt->k_file = mdb_gelf_create(kt->k_fio,
1325*7c478bd9Sstevel@tonic-gate 	    ET_EXEC, GF_FILE)) == NULL) {
1326*7c478bd9Sstevel@tonic-gate 		mdb_io_destroy(kt->k_fio);
1327*7c478bd9Sstevel@tonic-gate 		goto err;
1328*7c478bd9Sstevel@tonic-gate 	}
1329*7c478bd9Sstevel@tonic-gate 
1330*7c478bd9Sstevel@tonic-gate 	kt->k_symtab =
1331*7c478bd9Sstevel@tonic-gate 	    mdb_gelf_symtab_create_file(kt->k_file, SHT_SYMTAB, MDB_TGT_SYMTAB);
1332*7c478bd9Sstevel@tonic-gate 
1333*7c478bd9Sstevel@tonic-gate 	kt->k_dynsym =
1334*7c478bd9Sstevel@tonic-gate 	    mdb_gelf_symtab_create_file(kt->k_file, SHT_DYNSYM, MDB_TGT_DYNSYM);
1335*7c478bd9Sstevel@tonic-gate 
1336*7c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "kas",
1337*7c478bd9Sstevel@tonic-gate 	    &sym, NULL) == -1) {
1338*7c478bd9Sstevel@tonic-gate 		warn("'kas' symbol is missing from kernel\n");
1339*7c478bd9Sstevel@tonic-gate 		goto err;
1340*7c478bd9Sstevel@tonic-gate 	}
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate 	kt->k_as = (struct as *)(uintptr_t)sym.st_value;
1343*7c478bd9Sstevel@tonic-gate 
1344*7c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "platform",
1345*7c478bd9Sstevel@tonic-gate 	    &sym, NULL) == -1) {
1346*7c478bd9Sstevel@tonic-gate 		warn("'platform' symbol is missing from kernel\n");
1347*7c478bd9Sstevel@tonic-gate 		goto err;
1348*7c478bd9Sstevel@tonic-gate 	}
1349*7c478bd9Sstevel@tonic-gate 
1350*7c478bd9Sstevel@tonic-gate 	if (kvm_kread(kt->k_cookie, sym.st_value,
1351*7c478bd9Sstevel@tonic-gate 	    kt->k_platform, MAXNAMELEN) <= 0) {
1352*7c478bd9Sstevel@tonic-gate 		warn("failed to read 'platform' string from kernel");
1353*7c478bd9Sstevel@tonic-gate 		goto err;
1354*7c478bd9Sstevel@tonic-gate 	}
1355*7c478bd9Sstevel@tonic-gate 
1356*7c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "utsname",
1357*7c478bd9Sstevel@tonic-gate 	    &sym, NULL) == -1) {
1358*7c478bd9Sstevel@tonic-gate 		warn("'utsname' symbol is missing from kernel\n");
1359*7c478bd9Sstevel@tonic-gate 		goto err;
1360*7c478bd9Sstevel@tonic-gate 	}
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate 	if (kvm_kread(kt->k_cookie, sym.st_value, &uts, sizeof (uts)) <= 0) {
1363*7c478bd9Sstevel@tonic-gate 		warn("failed to read 'utsname' struct from kernel");
1364*7c478bd9Sstevel@tonic-gate 		goto err;
1365*7c478bd9Sstevel@tonic-gate 	}
1366*7c478bd9Sstevel@tonic-gate 
1367*7c478bd9Sstevel@tonic-gate 	/*
1368*7c478bd9Sstevel@tonic-gate 	 * These libkvm symbols were not present in Solaris 2.6; as such
1369*7c478bd9Sstevel@tonic-gate 	 * we need to look them up manually using the run-time linker.
1370*7c478bd9Sstevel@tonic-gate 	 */
1371*7c478bd9Sstevel@tonic-gate 	kt->k_aread = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_aread");
1372*7c478bd9Sstevel@tonic-gate 	kt->k_awrite = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_awrite");
1373*7c478bd9Sstevel@tonic-gate 	kt->k_pread = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_pread");
1374*7c478bd9Sstevel@tonic-gate 	kt->k_pwrite = (ssize_t (*)()) dlsym(RTLD_DEFAULT, "kvm_pwrite");
1375*7c478bd9Sstevel@tonic-gate 
1376*7c478bd9Sstevel@tonic-gate 	/*
1377*7c478bd9Sstevel@tonic-gate 	 * If any of these functions are unavailable with the current
1378*7c478bd9Sstevel@tonic-gate 	 * bindings, replace them with calls to mdb_tgt_notsup().
1379*7c478bd9Sstevel@tonic-gate 	 */
1380*7c478bd9Sstevel@tonic-gate 	if (kt->k_aread == NULL)
1381*7c478bd9Sstevel@tonic-gate 		kt->k_aread = (ssize_t (*)())mdb_tgt_notsup;
1382*7c478bd9Sstevel@tonic-gate 	if (kt->k_awrite == NULL)
1383*7c478bd9Sstevel@tonic-gate 		kt->k_awrite = (ssize_t (*)())mdb_tgt_notsup;
1384*7c478bd9Sstevel@tonic-gate 	if (kt->k_pread == NULL)
1385*7c478bd9Sstevel@tonic-gate 		kt->k_pread = (ssize_t (*)())mdb_tgt_notsup;
1386*7c478bd9Sstevel@tonic-gate 	if (kt->k_pwrite == NULL)
1387*7c478bd9Sstevel@tonic-gate 		kt->k_pwrite = (ssize_t (*)())mdb_tgt_notsup;
1388*7c478bd9Sstevel@tonic-gate 
1389*7c478bd9Sstevel@tonic-gate 	kt->k_dump_print_content = (void (*)())kt_data_stub;
1390*7c478bd9Sstevel@tonic-gate 	kt->k_dump_find_curproc = kt_data_stub;
1391*7c478bd9Sstevel@tonic-gate 
1392*7c478bd9Sstevel@tonic-gate 	/*
1393*7c478bd9Sstevel@tonic-gate 	 * We set k_ctfvalid based on the presence of the CTF vmem arena
1394*7c478bd9Sstevel@tonic-gate 	 * symbol.  The CTF members were added to the end of struct module at
1395*7c478bd9Sstevel@tonic-gate 	 * the same time, so this allows us to know whether we can use them.
1396*7c478bd9Sstevel@tonic-gate 	 */
1397*7c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "ctf_arena", &sym,
1398*7c478bd9Sstevel@tonic-gate 	    NULL) == 0 && !(mdb.m_flags & MDB_FL_NOCTF))
1399*7c478bd9Sstevel@tonic-gate 		kt->k_ctfvalid = 1;
1400*7c478bd9Sstevel@tonic-gate 
1401*7c478bd9Sstevel@tonic-gate 	(void) mdb_nv_create(&kt->k_modules, UM_SLEEP);
1402*7c478bd9Sstevel@tonic-gate 	t->t_pshandle = kt->k_cookie;
1403*7c478bd9Sstevel@tonic-gate 	t->t_data = kt;
1404*7c478bd9Sstevel@tonic-gate 
1405*7c478bd9Sstevel@tonic-gate #if defined(__sparc)
1406*7c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
1407*7c478bd9Sstevel@tonic-gate 	kt_sparcv9_init(t);
1408*7c478bd9Sstevel@tonic-gate #else
1409*7c478bd9Sstevel@tonic-gate 	kt_sparcv7_init(t);
1410*7c478bd9Sstevel@tonic-gate #endif
1411*7c478bd9Sstevel@tonic-gate #elif defined(__amd64)
1412*7c478bd9Sstevel@tonic-gate 	kt_amd64_init(t);
1413*7c478bd9Sstevel@tonic-gate #elif defined(__i386)
1414*7c478bd9Sstevel@tonic-gate 	kt_ia32_init(t);
1415*7c478bd9Sstevel@tonic-gate #else
1416*7c478bd9Sstevel@tonic-gate #error	"unknown ISA"
1417*7c478bd9Sstevel@tonic-gate #endif
1418*7c478bd9Sstevel@tonic-gate 
1419*7c478bd9Sstevel@tonic-gate 	/*
1420*7c478bd9Sstevel@tonic-gate 	 * We read our representative thread ID (address) from the kernel's
1421*7c478bd9Sstevel@tonic-gate 	 * global panic_thread.  It will remain 0 if this is a live kernel.
1422*7c478bd9Sstevel@tonic-gate 	 */
1423*7c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &kt->k_tid, sizeof (void *),
1424*7c478bd9Sstevel@tonic-gate 	    MDB_TGT_OBJ_EXEC, "panic_thread");
1425*7c478bd9Sstevel@tonic-gate 
1426*7c478bd9Sstevel@tonic-gate 	if ((mdb.m_flags & MDB_FL_ADB) && mdb_tgt_readsym(t, MDB_TGT_AS_VIRT,
1427*7c478bd9Sstevel@tonic-gate 	    &pmem, sizeof (pmem), MDB_TGT_OBJ_EXEC, "physmem") == sizeof (pmem))
1428*7c478bd9Sstevel@tonic-gate 		mdb_printf("physmem %lx\n", (ulong_t)pmem);
1429*7c478bd9Sstevel@tonic-gate 
1430*7c478bd9Sstevel@tonic-gate 	/*
1431*7c478bd9Sstevel@tonic-gate 	 * If this is not a live kernel, read the dump header.  We don't have to
1432*7c478bd9Sstevel@tonic-gate 	 * sanity-check the header, as the kvm_open would not have succeeded
1433*7c478bd9Sstevel@tonic-gate 	 * otherwise.
1434*7c478bd9Sstevel@tonic-gate 	 */
1435*7c478bd9Sstevel@tonic-gate 	if (strcmp(kt->k_symfile, "/dev/ksyms") != 0) {
1436*7c478bd9Sstevel@tonic-gate 		mdb_io_t *vmcore;
1437*7c478bd9Sstevel@tonic-gate 
1438*7c478bd9Sstevel@tonic-gate 		kt->k_dumphdr = mdb_alloc(sizeof (dumphdr_t), UM_SLEEP);
1439*7c478bd9Sstevel@tonic-gate 
1440*7c478bd9Sstevel@tonic-gate 		if ((vmcore = mdb_fdio_create_path(NULL, kt->k_kvmfile,
1441*7c478bd9Sstevel@tonic-gate 		    O_RDONLY, 0)) == NULL) {
1442*7c478bd9Sstevel@tonic-gate 			mdb_warn("failed to open %s", kt->k_kvmfile);
1443*7c478bd9Sstevel@tonic-gate 			goto err;
1444*7c478bd9Sstevel@tonic-gate 		}
1445*7c478bd9Sstevel@tonic-gate 
1446*7c478bd9Sstevel@tonic-gate 		if (IOP_READ(vmcore, kt->k_dumphdr, sizeof (dumphdr_t)) !=
1447*7c478bd9Sstevel@tonic-gate 		    sizeof (dumphdr_t)) {
1448*7c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read dump header");
1449*7c478bd9Sstevel@tonic-gate 			mdb_io_destroy(vmcore);
1450*7c478bd9Sstevel@tonic-gate 			goto err;
1451*7c478bd9Sstevel@tonic-gate 		}
1452*7c478bd9Sstevel@tonic-gate 
1453*7c478bd9Sstevel@tonic-gate 		mdb_io_destroy(vmcore);
1454*7c478bd9Sstevel@tonic-gate 
1455*7c478bd9Sstevel@tonic-gate 		(void) mdb_tgt_xdata_insert(t, "dumphdr",
1456*7c478bd9Sstevel@tonic-gate 		    "dump header structure", kt_xd_dumphdr);
1457*7c478bd9Sstevel@tonic-gate 	}
1458*7c478bd9Sstevel@tonic-gate 
1459*7c478bd9Sstevel@tonic-gate 	return (0);
1460*7c478bd9Sstevel@tonic-gate 
1461*7c478bd9Sstevel@tonic-gate err:
1462*7c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr != NULL)
1463*7c478bd9Sstevel@tonic-gate 		mdb_free(kt->k_dumphdr, sizeof (dumphdr_t));
1464*7c478bd9Sstevel@tonic-gate 
1465*7c478bd9Sstevel@tonic-gate 	if (kt->k_symtab != NULL)
1466*7c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_symtab);
1467*7c478bd9Sstevel@tonic-gate 
1468*7c478bd9Sstevel@tonic-gate 	if (kt->k_dynsym != NULL)
1469*7c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_dynsym);
1470*7c478bd9Sstevel@tonic-gate 
1471*7c478bd9Sstevel@tonic-gate 	if (kt->k_file != NULL)
1472*7c478bd9Sstevel@tonic-gate 		mdb_gelf_destroy(kt->k_file);
1473*7c478bd9Sstevel@tonic-gate 
1474*7c478bd9Sstevel@tonic-gate 	if (kt->k_cookie != NULL)
1475*7c478bd9Sstevel@tonic-gate 		(void) kvm_close(kt->k_cookie);
1476*7c478bd9Sstevel@tonic-gate 
1477*7c478bd9Sstevel@tonic-gate 	mdb_free(kt, sizeof (kt_data_t));
1478*7c478bd9Sstevel@tonic-gate 	return (-1);
1479*7c478bd9Sstevel@tonic-gate }
1480