xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_kvm.c (revision 8eb8717cc9dc99bdd784b74c994bea7ef5e60f92)
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
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f6e214c7SGavin Maltby  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
251320caf7SBryan Cantrill /*
26*8eb8717cSJohn Levon  * Copyright 2019 Joyent, Inc.
271320caf7SBryan Cantrill  */
281320caf7SBryan Cantrill 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Libkvm Kernel Target
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * The libkvm kernel target provides access to both crash dumps and live
337c478bd9Sstevel@tonic-gate  * kernels through /dev/ksyms and /dev/kmem, using the facilities provided by
347c478bd9Sstevel@tonic-gate  * the libkvm.so library.  The target-specific data structures are shared
357c478bd9Sstevel@tonic-gate  * between this file (common code) and the ISA-dependent parts of the target,
367c478bd9Sstevel@tonic-gate  * and so they are defined in the mdb_kvm.h header.  The target processes an
377c478bd9Sstevel@tonic-gate  * "executable" (/dev/ksyms or the unix.X file) which contains a primary
387c478bd9Sstevel@tonic-gate  * .symtab and .dynsym, and then also iterates over the krtld module chain in
397c478bd9Sstevel@tonic-gate  * the kernel in order to obtain a list of loaded modules and per-module symbol
407c478bd9Sstevel@tonic-gate  * tables.  To improve startup performance, the per-module symbol tables are
417c478bd9Sstevel@tonic-gate  * instantiated on-the-fly whenever an address lookup falls within the text
427c478bd9Sstevel@tonic-gate  * section of a given module.  The target also relies on services from the
437c478bd9Sstevel@tonic-gate  * mdb_ks (kernel support) module, which contains pieces of the implementation
447c478bd9Sstevel@tonic-gate  * that must be compiled against the kernel implementation.
457c478bd9Sstevel@tonic-gate  */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
487c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
497c478bd9Sstevel@tonic-gate #include <sys/kobj_impl.h>
507c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
517c478bd9Sstevel@tonic-gate #include <sys/panic.h>
527c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h>
537c478bd9Sstevel@tonic-gate #include <sys/dumpadm.h>
54*8eb8717cSJohn Levon #include <sys/uuid.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <dlfcn.h>
577c478bd9Sstevel@tonic-gate #include <libctf.h>
587c478bd9Sstevel@tonic-gate #include <string.h>
597c478bd9Sstevel@tonic-gate #include <fcntl.h>
607c478bd9Sstevel@tonic-gate #include <errno.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include <mdb/mdb_target_impl.h>
637c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h>
647c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
657c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h>
667c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
677c478bd9Sstevel@tonic-gate #include <mdb/mdb_io_impl.h>
687c478bd9Sstevel@tonic-gate #include <mdb/mdb_ctf.h>
697c478bd9Sstevel@tonic-gate #include <mdb/mdb_kvm.h>
707c478bd9Sstevel@tonic-gate #include <mdb/mdb_module.h>
71843e1988Sjohnlev #include <mdb/mdb_kb.h>
72*8eb8717cSJohn Levon #include <mdb/mdb_ks.h>
737c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #define	KT_RELOC_BUF(buf, obase, nbase) \
767c478bd9Sstevel@tonic-gate 	((uintptr_t)(buf) - (uintptr_t)(obase) + (uintptr_t)(nbase))
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	KT_BAD_BUF(buf, base, size) \
797c478bd9Sstevel@tonic-gate 	((uintptr_t)(buf) < (uintptr_t)(base) || \
807c478bd9Sstevel@tonic-gate 	((uintptr_t)(buf) >= (uintptr_t)(base) + (uintptr_t)(size)))
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate typedef struct kt_symarg {
837c478bd9Sstevel@tonic-gate 	mdb_tgt_sym_f *sym_cb;		/* Caller's callback function */
847c478bd9Sstevel@tonic-gate 	void *sym_data;			/* Callback function argument */
857c478bd9Sstevel@tonic-gate 	uint_t sym_type;		/* Symbol type/binding filter */
867c478bd9Sstevel@tonic-gate 	mdb_syminfo_t sym_info;		/* Symbol id and table id */
877c478bd9Sstevel@tonic-gate 	const char *sym_obj;		/* Containing object */
887c478bd9Sstevel@tonic-gate } kt_symarg_t;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate typedef struct kt_maparg {
917c478bd9Sstevel@tonic-gate 	mdb_tgt_t *map_target;		/* Target used for mapping iter */
927c478bd9Sstevel@tonic-gate 	mdb_tgt_map_f *map_cb;		/* Caller's callback function */
937c478bd9Sstevel@tonic-gate 	void *map_data;			/* Callback function argument */
947c478bd9Sstevel@tonic-gate } kt_maparg_t;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate static const char KT_MODULE[] = "mdb_ks";
977c478bd9Sstevel@tonic-gate static const char KT_CTFPARENT[] = "genunix";
987c478bd9Sstevel@tonic-gate 
99*8eb8717cSJohn Levon static void (*print_buildversion)(void);
100*8eb8717cSJohn Levon 
1017c478bd9Sstevel@tonic-gate static void
1027c478bd9Sstevel@tonic-gate kt_load_module(kt_data_t *kt, mdb_tgt_t *t, kt_module_t *km)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	km->km_data = mdb_alloc(km->km_datasz, UM_SLEEP);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_vread(t, km->km_data, km->km_datasz, km->km_symspace_va);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	km->km_symbuf = (void *)
1097c478bd9Sstevel@tonic-gate 	    KT_RELOC_BUF(km->km_symtab_va, km->km_symspace_va, km->km_data);
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	km->km_strtab = (char *)
1127c478bd9Sstevel@tonic-gate 	    KT_RELOC_BUF(km->km_strtab_va, km->km_symspace_va, km->km_data);
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	km->km_symtab = mdb_gelf_symtab_create_raw(&kt->k_file->gf_ehdr,
1157c478bd9Sstevel@tonic-gate 	    &km->km_symtab_hdr, km->km_symbuf,
1167c478bd9Sstevel@tonic-gate 	    &km->km_strtab_hdr, km->km_strtab, MDB_TGT_SYMTAB);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate static void
1207c478bd9Sstevel@tonic-gate kt_load_modules(kt_data_t *kt, mdb_tgt_t *t)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate 	char name[MAXNAMELEN];
1237c478bd9Sstevel@tonic-gate 	uintptr_t addr, head;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	struct module kmod;
1267c478bd9Sstevel@tonic-gate 	struct modctl ctl;
1277c478bd9Sstevel@tonic-gate 	Shdr symhdr, strhdr;
1287c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	kt_module_t *km;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	if (mdb_tgt_lookup_by_name(t, MDB_TGT_OBJ_EXEC,
1337c478bd9Sstevel@tonic-gate 	    "modules", &sym, NULL) == -1) {
1347c478bd9Sstevel@tonic-gate 		warn("failed to get 'modules' symbol");
1357c478bd9Sstevel@tonic-gate 		return;
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	if (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &ctl, sizeof (ctl),
1397c478bd9Sstevel@tonic-gate 	    MDB_TGT_OBJ_EXEC, "modules") != sizeof (ctl)) {
1407c478bd9Sstevel@tonic-gate 		warn("failed to read 'modules' struct");
1417c478bd9Sstevel@tonic-gate 		return;
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	addr = head = (uintptr_t)sym.st_value;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	do {
147892ad162SToomas Soome 		if (addr == 0)
1487c478bd9Sstevel@tonic-gate 			break; /* Avoid spurious NULL pointers in list */
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &ctl, sizeof (ctl), addr) == -1) {
1517c478bd9Sstevel@tonic-gate 			warn("failed to read modctl at %p", (void *)addr);
1527c478bd9Sstevel@tonic-gate 			return;
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 		if (ctl.mod_mp == NULL)
1567c478bd9Sstevel@tonic-gate 			continue; /* No associated krtld structure */
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 		if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT, name, MAXNAMELEN,
1597c478bd9Sstevel@tonic-gate 		    (uintptr_t)ctl.mod_modname) <= 0) {
1607c478bd9Sstevel@tonic-gate 			warn("failed to read module name at %p",
1617c478bd9Sstevel@tonic-gate 			    (void *)ctl.mod_modname);
1627c478bd9Sstevel@tonic-gate 			continue;
1637c478bd9Sstevel@tonic-gate 		}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 		mdb_dprintf(MDB_DBG_KMOD, "reading mod %s (%p)\n",
1667c478bd9Sstevel@tonic-gate 		    name, (void *)addr);
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		if (mdb_nv_lookup(&kt->k_modules, name) != NULL) {
1697c478bd9Sstevel@tonic-gate 			warn("skipping duplicate module '%s', id=%d\n",
1707c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
1717c478bd9Sstevel@tonic-gate 			continue;
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &kmod, sizeof (kmod),
1757c478bd9Sstevel@tonic-gate 		    (uintptr_t)ctl.mod_mp) == -1) {
1767c478bd9Sstevel@tonic-gate 			warn("failed to read module at %p\n",
1777c478bd9Sstevel@tonic-gate 			    (void *)ctl.mod_mp);
1787c478bd9Sstevel@tonic-gate 			continue;
1797c478bd9Sstevel@tonic-gate 		}
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 		if (kmod.symspace == NULL || kmod.symhdr == NULL ||
1827c478bd9Sstevel@tonic-gate 		    kmod.strhdr == NULL) {
1837c478bd9Sstevel@tonic-gate 			/*
1847c478bd9Sstevel@tonic-gate 			 * If no buffer for the symbols has been allocated,
1857c478bd9Sstevel@tonic-gate 			 * or the shdrs for .symtab and .strtab are missing,
1867c478bd9Sstevel@tonic-gate 			 * then we're out of luck.
1877c478bd9Sstevel@tonic-gate 			 */
1887c478bd9Sstevel@tonic-gate 			continue;
1897c478bd9Sstevel@tonic-gate 		}
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &symhdr, sizeof (Shdr),
1927c478bd9Sstevel@tonic-gate 		    (uintptr_t)kmod.symhdr) == -1) {
1937c478bd9Sstevel@tonic-gate 			warn("failed to read .symtab header for '%s', id=%d",
1947c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
1957c478bd9Sstevel@tonic-gate 			continue;
1967c478bd9Sstevel@tonic-gate 		}
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 		if (mdb_tgt_vread(t, &strhdr, sizeof (Shdr),
1997c478bd9Sstevel@tonic-gate 		    (uintptr_t)kmod.strhdr) == -1) {
2007c478bd9Sstevel@tonic-gate 			warn("failed to read .strtab header for '%s', id=%d",
2017c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
2027c478bd9Sstevel@tonic-gate 			continue;
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 		/*
2067c478bd9Sstevel@tonic-gate 		 * Now get clever: f(*^ing krtld didn't used to bother updating
2077c478bd9Sstevel@tonic-gate 		 * its own kmod.symsize value.  We know that prior to this bug
2087c478bd9Sstevel@tonic-gate 		 * being fixed, symspace was a contiguous buffer containing
2097c478bd9Sstevel@tonic-gate 		 * .symtab, .strtab, and the symbol hash table in that order.
2107c478bd9Sstevel@tonic-gate 		 * So if symsize is zero, recompute it as the size of .symtab
2117c478bd9Sstevel@tonic-gate 		 * plus the size of .strtab.  We don't need to load the hash
2127c478bd9Sstevel@tonic-gate 		 * table anyway since we re-hash all the symbols internally.
2137c478bd9Sstevel@tonic-gate 		 */
2147c478bd9Sstevel@tonic-gate 		if (kmod.symsize == 0)
2157c478bd9Sstevel@tonic-gate 			kmod.symsize = symhdr.sh_size + strhdr.sh_size;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 		/*
2187c478bd9Sstevel@tonic-gate 		 * Similar logic can be used to make educated guesses
2197c478bd9Sstevel@tonic-gate 		 * at the values of kmod.symtbl and kmod.strings.
2207c478bd9Sstevel@tonic-gate 		 */
2217c478bd9Sstevel@tonic-gate 		if (kmod.symtbl == NULL)
2227c478bd9Sstevel@tonic-gate 			kmod.symtbl = kmod.symspace;
2237c478bd9Sstevel@tonic-gate 		if (kmod.strings == NULL)
2247c478bd9Sstevel@tonic-gate 			kmod.strings = kmod.symspace + symhdr.sh_size;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 		/*
2277c478bd9Sstevel@tonic-gate 		 * Make sure things seem reasonable before we proceed
2287c478bd9Sstevel@tonic-gate 		 * to actually read and decipher the symspace.
2297c478bd9Sstevel@tonic-gate 		 */
2307c478bd9Sstevel@tonic-gate 		if (KT_BAD_BUF(kmod.symtbl, kmod.symspace, kmod.symsize) ||
2317c478bd9Sstevel@tonic-gate 		    KT_BAD_BUF(kmod.strings, kmod.symspace, kmod.symsize)) {
2327c478bd9Sstevel@tonic-gate 			warn("skipping module '%s', id=%d (corrupt symspace)\n",
2337c478bd9Sstevel@tonic-gate 			    name, ctl.mod_id);
2347c478bd9Sstevel@tonic-gate 			continue;
2357c478bd9Sstevel@tonic-gate 		}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 		km = mdb_zalloc(sizeof (kt_module_t), UM_SLEEP);
2387c478bd9Sstevel@tonic-gate 		km->km_name = strdup(name);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		(void) mdb_nv_insert(&kt->k_modules, km->km_name, NULL,
2417c478bd9Sstevel@tonic-gate 		    (uintptr_t)km, MDB_NV_EXTNAME);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 		km->km_datasz = kmod.symsize;
2447c478bd9Sstevel@tonic-gate 		km->km_symspace_va = (uintptr_t)kmod.symspace;
2457c478bd9Sstevel@tonic-gate 		km->km_symtab_va = (uintptr_t)kmod.symtbl;
2467c478bd9Sstevel@tonic-gate 		km->km_strtab_va = (uintptr_t)kmod.strings;
2477c478bd9Sstevel@tonic-gate 		km->km_symtab_hdr = symhdr;
2487c478bd9Sstevel@tonic-gate 		km->km_strtab_hdr = strhdr;
2497c478bd9Sstevel@tonic-gate 		km->km_text_va = (uintptr_t)kmod.text;
2507c478bd9Sstevel@tonic-gate 		km->km_text_size = kmod.text_size;
2517c478bd9Sstevel@tonic-gate 		km->km_data_va = (uintptr_t)kmod.data;
2527c478bd9Sstevel@tonic-gate 		km->km_data_size = kmod.data_size;
2537c478bd9Sstevel@tonic-gate 		km->km_bss_va = (uintptr_t)kmod.bss;
2547c478bd9Sstevel@tonic-gate 		km->km_bss_size = kmod.bss_size;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		if (kt->k_ctfvalid) {
2577c478bd9Sstevel@tonic-gate 			km->km_ctf_va = (uintptr_t)kmod.ctfdata;
2587c478bd9Sstevel@tonic-gate 			km->km_ctf_size = kmod.ctfsize;
2597c478bd9Sstevel@tonic-gate 		}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 		/*
2627c478bd9Sstevel@tonic-gate 		 * Add the module to the end of the list of modules in load-
2637c478bd9Sstevel@tonic-gate 		 * dependency order.  This is needed to load the corresponding
2647c478bd9Sstevel@tonic-gate 		 * debugger modules in the same order for layering purposes.
2657c478bd9Sstevel@tonic-gate 		 */
2667c478bd9Sstevel@tonic-gate 		mdb_list_append(&kt->k_modlist, km);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		if (t->t_flags & MDB_TGT_F_PRELOAD) {
2697c478bd9Sstevel@tonic-gate 			mdb_iob_printf(mdb.m_out, " %s", name);
2707c478bd9Sstevel@tonic-gate 			mdb_iob_flush(mdb.m_out);
2717c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	} while ((addr = (uintptr_t)ctl.mod_next) != head);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate int
2787c478bd9Sstevel@tonic-gate kt_setflags(mdb_tgt_t *t, int flags)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate 	int iochg = ((flags ^ t->t_flags) & MDB_TGT_F_ALLOWIO) &&
2817c478bd9Sstevel@tonic-gate 	    !mdb_prop_postmortem;
2827c478bd9Sstevel@tonic-gate 	int rwchg = (flags ^ t->t_flags) & MDB_TGT_F_RDWR;
2837c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
2847c478bd9Sstevel@tonic-gate 	const char *kvmfile;
285843e1988Sjohnlev 	void *cookie;
2867c478bd9Sstevel@tonic-gate 	int mode;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	if (!iochg && !rwchg)
2897c478bd9Sstevel@tonic-gate 		return (0);
2907c478bd9Sstevel@tonic-gate 
291843e1988Sjohnlev 	if (kt->k_xpv_domu) {
292843e1988Sjohnlev 		warn("read-only target");
293843e1988Sjohnlev 		return (-1);
294843e1988Sjohnlev 	}
295843e1988Sjohnlev 
2967c478bd9Sstevel@tonic-gate 	if (iochg) {
2977c478bd9Sstevel@tonic-gate 		kvmfile = (flags & MDB_TGT_F_ALLOWIO) ? "/dev/allkmem" :
2987c478bd9Sstevel@tonic-gate 		    "/dev/kmem";
2997c478bd9Sstevel@tonic-gate 	} else {
3007c478bd9Sstevel@tonic-gate 		kvmfile = kt->k_kvmfile;
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	mode = (flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY;
3047c478bd9Sstevel@tonic-gate 
305843e1988Sjohnlev 	if ((cookie = kt->k_kb_ops->kb_open(kt->k_symfile, kvmfile, NULL, mode,
3067c478bd9Sstevel@tonic-gate 	    mdb.m_pname)) == NULL) {
3077c478bd9Sstevel@tonic-gate 		/* We failed to re-open, so don't change t_flags */
3087c478bd9Sstevel@tonic-gate 		warn("failed to re-open target");
3097c478bd9Sstevel@tonic-gate 		return (-1);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/*
3137c478bd9Sstevel@tonic-gate 	 * We successfully reopened the target, so update k_kvmfile.  Also set
3147c478bd9Sstevel@tonic-gate 	 * the RDWR and ALLOWIO bits in t_flags to match those in flags.
3157c478bd9Sstevel@tonic-gate 	 */
316843e1988Sjohnlev 	(void) kt->k_kb_ops->kb_close(kt->k_cookie);
3177c478bd9Sstevel@tonic-gate 	kt->k_cookie = cookie;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	if (kvmfile != kt->k_kvmfile) {
3207c478bd9Sstevel@tonic-gate 		strfree(kt->k_kvmfile);
3217c478bd9Sstevel@tonic-gate 		kt->k_kvmfile = strdup(kvmfile);
3227c478bd9Sstevel@tonic-gate 	}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	t->t_flags = (t->t_flags & ~(MDB_TGT_F_RDWR | MDB_TGT_F_ALLOWIO)) |
3257c478bd9Sstevel@tonic-gate 	    (flags & (MDB_TGT_F_RDWR | MDB_TGT_F_ALLOWIO));
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	return (0);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate /*
3317c478bd9Sstevel@tonic-gate  * Determine which PIDs (if any) have their pages saved in the dump.  We
3327c478bd9Sstevel@tonic-gate  * do this by looking for content flags in dump_flags in the header.  These
3337c478bd9Sstevel@tonic-gate  * flags, which won't be set in older dumps, tell us whether a single process
3347c478bd9Sstevel@tonic-gate  * has had its pages included in the dump.  If a single process has been
3357c478bd9Sstevel@tonic-gate  * included, we need to get the PID for that process from the dump_pids
3367c478bd9Sstevel@tonic-gate  * array in the dump.
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate static int
3397c478bd9Sstevel@tonic-gate kt_find_dump_contents(kt_data_t *kt)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	dumphdr_t *dh = kt->k_dumphdr;
3427c478bd9Sstevel@tonic-gate 	pid_t pid = -1;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	if (dh->dump_flags & DF_ALL)
3457c478bd9Sstevel@tonic-gate 		return (KT_DUMPCONTENT_ALL);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (dh->dump_flags & DF_CURPROC) {
3487c478bd9Sstevel@tonic-gate 		if ((pid = kt->k_dump_find_curproc()) == -1)
3497c478bd9Sstevel@tonic-gate 			return (KT_DUMPCONTENT_INVALID);
3507c478bd9Sstevel@tonic-gate 		else
3517c478bd9Sstevel@tonic-gate 			return (pid);
3527c478bd9Sstevel@tonic-gate 	} else {
3537c478bd9Sstevel@tonic-gate 		return (KT_DUMPCONTENT_KERNEL);
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate static int
3587c478bd9Sstevel@tonic-gate kt_dump_contains_proc(mdb_tgt_t *t, void *context)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
3617c478bd9Sstevel@tonic-gate 	pid_t (*f_pid)(uintptr_t);
3627c478bd9Sstevel@tonic-gate 	pid_t reqpid;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	switch (kt->k_dumpcontent) {
3657c478bd9Sstevel@tonic-gate 	case KT_DUMPCONTENT_KERNEL:
3667c478bd9Sstevel@tonic-gate 		return (0);
3677c478bd9Sstevel@tonic-gate 	case KT_DUMPCONTENT_ALL:
3687c478bd9Sstevel@tonic-gate 		return (1);
3697c478bd9Sstevel@tonic-gate 	case KT_DUMPCONTENT_INVALID:
3707c478bd9Sstevel@tonic-gate 		goto procnotfound;
3717c478bd9Sstevel@tonic-gate 	default:
3727c478bd9Sstevel@tonic-gate 		f_pid = (pid_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_pid");
3737c478bd9Sstevel@tonic-gate 		if (f_pid == NULL)
3747c478bd9Sstevel@tonic-gate 			goto procnotfound;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 		reqpid = f_pid((uintptr_t)context);
3777c478bd9Sstevel@tonic-gate 		if (reqpid == -1)
3787c478bd9Sstevel@tonic-gate 			goto procnotfound;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 		return (kt->k_dumpcontent == reqpid);
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate procnotfound:
3847c478bd9Sstevel@tonic-gate 	warn("unable to determine whether dump contains proc %p\n", context);
3857c478bd9Sstevel@tonic-gate 	return (1);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate int
3897c478bd9Sstevel@tonic-gate kt_setcontext(mdb_tgt_t *t, void *context)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	if (context != NULL) {
3927c478bd9Sstevel@tonic-gate 		const char *argv[2];
3937c478bd9Sstevel@tonic-gate 		int argc = 0;
3947c478bd9Sstevel@tonic-gate 		mdb_tgt_t *ct;
3957c478bd9Sstevel@tonic-gate 		kt_data_t *kt = t->t_data;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		argv[argc++] = (const char *)context;
3987c478bd9Sstevel@tonic-gate 		argv[argc] = NULL;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 		if (kt->k_dumphdr != NULL &&
4017c478bd9Sstevel@tonic-gate 		    !kt_dump_contains_proc(t, context)) {
4027c478bd9Sstevel@tonic-gate 			warn("dump does not contain pages for proc %p\n",
4037c478bd9Sstevel@tonic-gate 			    context);
4047c478bd9Sstevel@tonic-gate 			return (-1);
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 		if ((ct = mdb_tgt_create(mdb_kproc_tgt_create,
4087c478bd9Sstevel@tonic-gate 		    t->t_flags, argc, argv)) == NULL)
4097c478bd9Sstevel@tonic-gate 			return (-1);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 		mdb_printf("debugger context set to proc %p\n", context);
4127c478bd9Sstevel@tonic-gate 		mdb_tgt_activate(ct);
4137c478bd9Sstevel@tonic-gate 	} else
4147c478bd9Sstevel@tonic-gate 		mdb_printf("debugger context set to kernel\n");
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	return (0);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate static int
4207c478bd9Sstevel@tonic-gate kt_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
4237c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_stack(addr, flags, argc, argv));
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate static int
4277c478bd9Sstevel@tonic-gate kt_stackv(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
4307c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_stackv(addr, flags, argc, argv));
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate static int
4347c478bd9Sstevel@tonic-gate kt_stackr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
4377c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_stackr(addr, flags, argc, argv));
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate static int
4417c478bd9Sstevel@tonic-gate kt_regs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
444843e1988Sjohnlev 
445843e1988Sjohnlev 	if (argc != 0 || (flags & DCMD_ADDRSPEC))
446843e1988Sjohnlev 		return (DCMD_USAGE);
447843e1988Sjohnlev 
448843e1988Sjohnlev 	addr = (uintptr_t)kt->k_regs;
449843e1988Sjohnlev 
4507c478bd9Sstevel@tonic-gate 	return (kt->k_dcmd_regs(addr, flags, argc, argv));
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate 
453843e1988Sjohnlev #ifdef __x86
454843e1988Sjohnlev static int
455843e1988Sjohnlev kt_cpustack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
456843e1988Sjohnlev {
457843e1988Sjohnlev 	kt_data_t *kt = mdb.m_target->t_data;
458843e1988Sjohnlev 	return (kt->k_dcmd_cpustack(addr, flags, argc, argv));
459843e1988Sjohnlev }
460843e1988Sjohnlev 
461843e1988Sjohnlev static int
462843e1988Sjohnlev kt_cpuregs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
463843e1988Sjohnlev {
464843e1988Sjohnlev 	kt_data_t *kt = mdb.m_target->t_data;
465843e1988Sjohnlev 	return (kt->k_dcmd_cpuregs(addr, flags, argc, argv));
466843e1988Sjohnlev }
467843e1988Sjohnlev #endif /* __x86 */
468843e1988Sjohnlev 
4697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4707c478bd9Sstevel@tonic-gate static int
4717c478bd9Sstevel@tonic-gate kt_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb.m_target->t_data;
4747c478bd9Sstevel@tonic-gate 	struct utsname uts;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	bzero(&uts, sizeof (uts));
4777c478bd9Sstevel@tonic-gate 	(void) strcpy(uts.nodename, "unknown machine");
4787c478bd9Sstevel@tonic-gate 	(void) kt_uname(mdb.m_target, &uts);
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (mdb_prop_postmortem) {
481843e1988Sjohnlev 		mdb_printf("debugging %scrash dump %s (%d-bit) from %s\n",
482843e1988Sjohnlev 		    kt->k_xpv_domu ? "domain " : "", kt->k_kvmfile,
483843e1988Sjohnlev 		    (int)(sizeof (void *) * NBBY), uts.nodename);
4847c478bd9Sstevel@tonic-gate 	} else {
4857c478bd9Sstevel@tonic-gate 		mdb_printf("debugging live kernel (%d-bit) on %s\n",
4867c478bd9Sstevel@tonic-gate 		    (int)(sizeof (void *) * NBBY), uts.nodename);
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	mdb_printf("operating system: %s %s (%s)\n",
4907c478bd9Sstevel@tonic-gate 	    uts.release, uts.version, uts.machine);
4917c478bd9Sstevel@tonic-gate 
492*8eb8717cSJohn Levon 	if (print_buildversion != NULL)
493*8eb8717cSJohn Levon 		print_buildversion();
494*8eb8717cSJohn Levon 
4957c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr) {
4967c478bd9Sstevel@tonic-gate 		dumphdr_t *dh = kt->k_dumphdr;
4977c478bd9Sstevel@tonic-gate 
498f6e214c7SGavin Maltby 		mdb_printf("image uuid: %s\n", dh->dump_uuid[0] != '\0' ?
499f6e214c7SGavin Maltby 		    dh->dump_uuid : "(not set)");
5007c478bd9Sstevel@tonic-gate 		mdb_printf("panic message: %s\n", dh->dump_panicstring);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 		kt->k_dump_print_content(dh, kt->k_dumpcontent);
503f6e214c7SGavin Maltby 	} else {
504*8eb8717cSJohn Levon 		char uuid[UUID_PRINTABLE_STRING_LENGTH];
505f6e214c7SGavin Maltby 
506*8eb8717cSJohn Levon 		if (mdb_readsym(uuid, sizeof (uuid),
507*8eb8717cSJohn Levon 		    "dump_osimage_uuid") == sizeof (uuid) &&
508*8eb8717cSJohn Levon 		    uuid[sizeof (uuid) - 1] == '\0') {
509*8eb8717cSJohn Levon 			mdb_printf("image uuid: %s\n", uuid[0] != '\0' ?
510*8eb8717cSJohn Levon 			    uuid : "(not set)");
511f6e214c7SGavin Maltby 		}
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate static const mdb_dcmd_t kt_dcmds[] = {
5187c478bd9Sstevel@tonic-gate 	{ "$c", "?[cnt]", "print stack backtrace", kt_stack },
5197c478bd9Sstevel@tonic-gate 	{ "$C", "?[cnt]", "print stack backtrace", kt_stackv },
5207c478bd9Sstevel@tonic-gate 	{ "$r", NULL, "print general-purpose registers", kt_regs },
5217c478bd9Sstevel@tonic-gate 	{ "$?", NULL, "print status and registers", kt_regs },
5227c478bd9Sstevel@tonic-gate 	{ "regs", NULL, "print general-purpose registers", kt_regs },
5237c478bd9Sstevel@tonic-gate 	{ "stack", "?[cnt]", "print stack backtrace", kt_stack },
5247c478bd9Sstevel@tonic-gate 	{ "stackregs", "?", "print stack backtrace and registers", kt_stackr },
525843e1988Sjohnlev #ifdef __x86
526843e1988Sjohnlev 	{ "cpustack", "?[-v] [-c cpuid] [cnt]", "print stack backtrace for a "
527843e1988Sjohnlev 	    "specific CPU", kt_cpustack },
528843e1988Sjohnlev 	{ "cpuregs", "?[-c cpuid]", "print general-purpose registers for a "
529843e1988Sjohnlev 	    "specific CPU", kt_cpuregs },
530843e1988Sjohnlev #endif
5317c478bd9Sstevel@tonic-gate 	{ "status", NULL, "print summary of current target", kt_status_dcmd },
5327c478bd9Sstevel@tonic-gate 	{ NULL }
5337c478bd9Sstevel@tonic-gate };
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate static uintmax_t
5367c478bd9Sstevel@tonic-gate reg_disc_get(const mdb_var_t *v)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	mdb_tgt_t *t = MDB_NV_COOKIE(v);
5397c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
5407c478bd9Sstevel@tonic-gate 	mdb_tgt_reg_t r = 0;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_getareg(t, kt->k_tid, mdb_nv_get_name(v), &r);
5437c478bd9Sstevel@tonic-gate 	return (r);
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate 
546ae115bc7Smrj static kt_module_t *
547ae115bc7Smrj kt_module_by_name(kt_data_t *kt, const char *name)
548ae115bc7Smrj {
549ae115bc7Smrj 	kt_module_t *km;
550ae115bc7Smrj 
551ae115bc7Smrj 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
552ae115bc7Smrj 		if (strcmp(name, km->km_name) == 0)
553ae115bc7Smrj 			return (km);
554ae115bc7Smrj 	}
555ae115bc7Smrj 
556ae115bc7Smrj 	return (NULL);
557ae115bc7Smrj }
558ae115bc7Smrj 
5597c478bd9Sstevel@tonic-gate void
5607c478bd9Sstevel@tonic-gate kt_activate(mdb_tgt_t *t)
5617c478bd9Sstevel@tonic-gate {
5627c478bd9Sstevel@tonic-gate 	static const mdb_nv_disc_t reg_disc = { NULL, reg_disc_get };
5637c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
5647c478bd9Sstevel@tonic-gate 	void *sym;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	int oflag;
5677c478bd9Sstevel@tonic-gate 
568843e1988Sjohnlev 	mdb_prop_postmortem = kt->k_xpv_domu || (kt->k_dumphdr != NULL);
5697c478bd9Sstevel@tonic-gate 	mdb_prop_kernel = TRUE;
5707c478bd9Sstevel@tonic-gate 	mdb_prop_datamodel = MDB_TGT_MODEL_NATIVE;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	if (kt->k_activated == FALSE) {
5737c478bd9Sstevel@tonic-gate 		struct utsname u1, u2;
5747c478bd9Sstevel@tonic-gate 		/*
5757c478bd9Sstevel@tonic-gate 		 * If we're examining a crash dump, root is /, and uname(2)
5767c478bd9Sstevel@tonic-gate 		 * does not match the utsname in the dump, issue a warning.
5777c478bd9Sstevel@tonic-gate 		 * Note that we are assuming that the modules and macros in
5787c478bd9Sstevel@tonic-gate 		 * /usr/lib are compiled against the kernel from uname -rv.
5797c478bd9Sstevel@tonic-gate 		 */
5807c478bd9Sstevel@tonic-gate 		if (mdb_prop_postmortem && strcmp(mdb.m_root, "/") == 0 &&
5817c478bd9Sstevel@tonic-gate 		    uname(&u1) >= 0 && kt_uname(t, &u2) >= 0 &&
5827c478bd9Sstevel@tonic-gate 		    (strcmp(u1.release, u2.release) ||
5837c478bd9Sstevel@tonic-gate 		    strcmp(u1.version, u2.version))) {
5847c478bd9Sstevel@tonic-gate 			mdb_warn("warning: dump is from %s %s %s; dcmds and "
5857c478bd9Sstevel@tonic-gate 			    "macros may not match kernel implementation\n",
5867c478bd9Sstevel@tonic-gate 			    u2.sysname, u2.release, u2.version);
5877c478bd9Sstevel@tonic-gate 		}
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 		if (mdb_module_load(KT_MODULE, MDB_MOD_GLOBAL) < 0) {
5907c478bd9Sstevel@tonic-gate 			warn("failed to load kernel support module -- "
5917c478bd9Sstevel@tonic-gate 			    "some modules may not load\n");
5927c478bd9Sstevel@tonic-gate 		}
5937c478bd9Sstevel@tonic-gate 
594*8eb8717cSJohn Levon 		print_buildversion = (void (*)(void))dlsym(RTLD_NEXT,
595*8eb8717cSJohn Levon 		    "mdb_print_buildversion");
596*8eb8717cSJohn Levon 
597843e1988Sjohnlev 		if (mdb_prop_postmortem && kt->k_dumphdr != NULL) {
5987c478bd9Sstevel@tonic-gate 			sym = dlsym(RTLD_NEXT, "mdb_dump_print_content");
5997c478bd9Sstevel@tonic-gate 			if (sym != NULL)
6007c478bd9Sstevel@tonic-gate 				kt->k_dump_print_content = (void (*)())sym;
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			sym = dlsym(RTLD_NEXT, "mdb_dump_find_curproc");
6037c478bd9Sstevel@tonic-gate 			if (sym != NULL)
6047c478bd9Sstevel@tonic-gate 				kt->k_dump_find_curproc = (int (*)())sym;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 			kt->k_dumpcontent = kt_find_dump_contents(kt);
6077c478bd9Sstevel@tonic-gate 		}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 		if (t->t_flags & MDB_TGT_F_PRELOAD) {
6107c478bd9Sstevel@tonic-gate 			oflag = mdb_iob_getflags(mdb.m_out) & MDB_IOB_PGENABLE;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 			mdb_iob_clrflags(mdb.m_out, oflag);
6137c478bd9Sstevel@tonic-gate 			mdb_iob_puts(mdb.m_out, "Preloading module symbols: [");
6147c478bd9Sstevel@tonic-gate 			mdb_iob_flush(mdb.m_out);
6157c478bd9Sstevel@tonic-gate 		}
6167c478bd9Sstevel@tonic-gate 
617ae115bc7Smrj 		if (!(t->t_flags & MDB_TGT_F_NOLOAD)) {
6187c478bd9Sstevel@tonic-gate 			kt_load_modules(kt, t);
6197c478bd9Sstevel@tonic-gate 
620ae115bc7Smrj 			/*
621ae115bc7Smrj 			 * Determine where the CTF data for krtld is. If krtld
622ae115bc7Smrj 			 * is rolled into unix, force load the MDB krtld
623ae115bc7Smrj 			 * module.
624ae115bc7Smrj 			 */
625ae115bc7Smrj 			kt->k_rtld_name = "krtld";
626ae115bc7Smrj 
627ae115bc7Smrj 			if (kt_module_by_name(kt, "krtld") == NULL) {
628ae115bc7Smrj 				(void) mdb_module_load("krtld", MDB_MOD_SILENT);
629ae115bc7Smrj 				kt->k_rtld_name = "unix";
630ae115bc7Smrj 			}
631ae115bc7Smrj 		}
632ae115bc7Smrj 
633ae115bc7Smrj 
6347c478bd9Sstevel@tonic-gate 		if (t->t_flags & MDB_TGT_F_PRELOAD) {
6357c478bd9Sstevel@tonic-gate 			mdb_iob_puts(mdb.m_out, " ]\n");
6367c478bd9Sstevel@tonic-gate 			mdb_iob_setflags(mdb.m_out, oflag);
6377c478bd9Sstevel@tonic-gate 		}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 		kt->k_activated = TRUE;
6407c478bd9Sstevel@tonic-gate 	}
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_register_dcmds(t, &kt_dcmds[0], MDB_MOD_FORCE);
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	/* Export some of our registers as named variables */
6457c478bd9Sstevel@tonic-gate 	mdb_tgt_register_regvars(t, kt->k_rds, &reg_disc, MDB_NV_RDONLY);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	mdb_tgt_elf_export(kt->k_file);
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate void
6517c478bd9Sstevel@tonic-gate kt_deactivate(mdb_tgt_t *t)
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	const mdb_tgt_regdesc_t *rdp;
6567c478bd9Sstevel@tonic-gate 	const mdb_dcmd_t *dcp;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	for (rdp = kt->k_rds; rdp->rd_name != NULL; rdp++) {
6597c478bd9Sstevel@tonic-gate 		mdb_var_t *v;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 		if (!(rdp->rd_flags & MDB_TGT_R_EXPORT))
6627c478bd9Sstevel@tonic-gate 			continue; /* Didn't export register as a variable */
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&mdb.m_nv, rdp->rd_name)) != NULL) {
6657c478bd9Sstevel@tonic-gate 			v->v_flags &= ~MDB_NV_PERSIST;
6667c478bd9Sstevel@tonic-gate 			mdb_nv_remove(&mdb.m_nv, v);
6677c478bd9Sstevel@tonic-gate 		}
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	for (dcp = &kt_dcmds[0]; dcp->dc_name != NULL; dcp++) {
6717c478bd9Sstevel@tonic-gate 		if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1)
6727c478bd9Sstevel@tonic-gate 			warn("failed to remove dcmd %s", dcp->dc_name);
6737c478bd9Sstevel@tonic-gate 	}
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	mdb_prop_postmortem = FALSE;
6767c478bd9Sstevel@tonic-gate 	mdb_prop_kernel = FALSE;
6777c478bd9Sstevel@tonic-gate 	mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN;
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6817c478bd9Sstevel@tonic-gate const char *
6827c478bd9Sstevel@tonic-gate kt_name(mdb_tgt_t *t)
6837c478bd9Sstevel@tonic-gate {
6847c478bd9Sstevel@tonic-gate 	return ("kvm");
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate const char *
6887c478bd9Sstevel@tonic-gate kt_platform(mdb_tgt_t *t)
6897c478bd9Sstevel@tonic-gate {
6907c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
6917c478bd9Sstevel@tonic-gate 	return (kt->k_platform);
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate int
6957c478bd9Sstevel@tonic-gate kt_uname(mdb_tgt_t *t, struct utsname *utsp)
6967c478bd9Sstevel@tonic-gate {
6977c478bd9Sstevel@tonic-gate 	return (mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, utsp,
6987c478bd9Sstevel@tonic-gate 	    sizeof (struct utsname), MDB_TGT_OBJ_EXEC, "utsname"));
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7027c478bd9Sstevel@tonic-gate int
7037c478bd9Sstevel@tonic-gate kt_dmodel(mdb_tgt_t *t)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate 	return (MDB_TGT_MODEL_NATIVE);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate ssize_t
7097c478bd9Sstevel@tonic-gate kt_aread(mdb_tgt_t *t, mdb_tgt_as_t as, void *buf,
7107c478bd9Sstevel@tonic-gate     size_t nbytes, mdb_tgt_addr_t addr)
7117c478bd9Sstevel@tonic-gate {
7127c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
7137c478bd9Sstevel@tonic-gate 	ssize_t rval;
7147c478bd9Sstevel@tonic-gate 
715843e1988Sjohnlev 	if ((rval = kt->k_kb_ops->kb_aread(kt->k_cookie, addr, buf,
716843e1988Sjohnlev 	    nbytes, as)) == -1)
7177c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	return (rval);
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate ssize_t
7237c478bd9Sstevel@tonic-gate kt_awrite(mdb_tgt_t *t, mdb_tgt_as_t as, const void *buf,
7247c478bd9Sstevel@tonic-gate     size_t nbytes, mdb_tgt_addr_t addr)
7257c478bd9Sstevel@tonic-gate {
7267c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
7277c478bd9Sstevel@tonic-gate 	ssize_t rval;
7287c478bd9Sstevel@tonic-gate 
729843e1988Sjohnlev 	if ((rval = kt->k_kb_ops->kb_awrite(kt->k_cookie, addr, buf,
730843e1988Sjohnlev 	    nbytes, as)) == -1)
7317c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	return (rval);
7347c478bd9Sstevel@tonic-gate }
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate ssize_t
7377c478bd9Sstevel@tonic-gate kt_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
7407c478bd9Sstevel@tonic-gate 	ssize_t rval;
7417c478bd9Sstevel@tonic-gate 
742843e1988Sjohnlev 	if ((rval = kt->k_kb_ops->kb_kread(kt->k_cookie, addr, buf,
743843e1988Sjohnlev 	    nbytes)) == -1)
7447c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	return (rval);
7477c478bd9Sstevel@tonic-gate }
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate ssize_t
7507c478bd9Sstevel@tonic-gate kt_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
7517c478bd9Sstevel@tonic-gate {
7527c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
7537c478bd9Sstevel@tonic-gate 	ssize_t rval;
7547c478bd9Sstevel@tonic-gate 
755843e1988Sjohnlev 	if ((rval = kt->k_kb_ops->kb_kwrite(kt->k_cookie, addr, buf,
756843e1988Sjohnlev 	    nbytes)) == -1)
7577c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	return (rval);
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate ssize_t
7637c478bd9Sstevel@tonic-gate kt_fread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate 	return (kt_vread(t, buf, nbytes, addr));
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate ssize_t
7697c478bd9Sstevel@tonic-gate kt_fwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	return (kt_vwrite(t, buf, nbytes, addr));
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate ssize_t
7757c478bd9Sstevel@tonic-gate kt_pread(mdb_tgt_t *t, void *buf, size_t nbytes, physaddr_t addr)
7767c478bd9Sstevel@tonic-gate {
7777c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
7787c478bd9Sstevel@tonic-gate 	ssize_t rval;
7797c478bd9Sstevel@tonic-gate 
780843e1988Sjohnlev 	if ((rval = kt->k_kb_ops->kb_pread(kt->k_cookie, addr, buf,
781843e1988Sjohnlev 	    nbytes)) == -1)
7827c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 	return (rval);
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate ssize_t
7887c478bd9Sstevel@tonic-gate kt_pwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, physaddr_t addr)
7897c478bd9Sstevel@tonic-gate {
7907c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
7917c478bd9Sstevel@tonic-gate 	ssize_t rval;
7927c478bd9Sstevel@tonic-gate 
793843e1988Sjohnlev 	if ((rval = kt->k_kb_ops->kb_pwrite(kt->k_cookie, addr, buf,
794843e1988Sjohnlev 	    nbytes)) == -1)
7957c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOMAP));
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	return (rval);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate int
8017c478bd9Sstevel@tonic-gate kt_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap)
8027c478bd9Sstevel@tonic-gate {
8037c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 	struct as *asp;
8067c478bd9Sstevel@tonic-gate 	physaddr_t pa;
8077c478bd9Sstevel@tonic-gate 	mdb_module_t *mod;
8087c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
8097c478bd9Sstevel@tonic-gate 	int (*fptr)(uintptr_t, struct as *, physaddr_t *);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)as) {
8127c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_PHYS:
8137c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_FILE:
8147c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_IO:
8157c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
8167c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_AS_VIRT:
8177c478bd9Sstevel@tonic-gate 		asp = kt->k_as;
8187c478bd9Sstevel@tonic-gate 		break;
8197c478bd9Sstevel@tonic-gate 	default:
8207c478bd9Sstevel@tonic-gate 		asp = (struct as *)as;
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 
823843e1988Sjohnlev 	if ((pa = kt->k_kb_ops->kb_vtop(kt->k_cookie, asp, va)) != -1ULL) {
8247c478bd9Sstevel@tonic-gate 		*pap = pa;
8257c478bd9Sstevel@tonic-gate 		return (0);
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	if ((v = mdb_nv_lookup(&mdb.m_modules, "unix")) != NULL &&
8297c478bd9Sstevel@tonic-gate 	    (mod = mdb_nv_get_cookie(v)) != NULL) {
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 		fptr = (int (*)(uintptr_t, struct as *, physaddr_t *))
832843e1988Sjohnlev 		    dlsym(mod->mod_hdl, "platform_vtop");
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		if ((fptr != NULL) && ((*fptr)(va, asp, pap) == 0))
8357c478bd9Sstevel@tonic-gate 			return (0);
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	return (set_errno(EMDB_NOMAP));
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate int
8427c478bd9Sstevel@tonic-gate kt_lookup_by_name(mdb_tgt_t *t, const char *obj, const char *name,
8437c478bd9Sstevel@tonic-gate     GElf_Sym *symp, mdb_syminfo_t *sip)
8447c478bd9Sstevel@tonic-gate {
8457c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
8467c478bd9Sstevel@tonic-gate 	kt_module_t *km, kmod;
8477c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
8487c478bd9Sstevel@tonic-gate 	int n;
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	/*
8517c478bd9Sstevel@tonic-gate 	 * To simplify the implementation, we create a fake module on the stack
8527c478bd9Sstevel@tonic-gate 	 * which is "prepended" to k_modlist and whose symtab is kt->k_symtab.
8537c478bd9Sstevel@tonic-gate 	 */
8547c478bd9Sstevel@tonic-gate 	kmod.km_symtab = kt->k_symtab;
8557c478bd9Sstevel@tonic-gate 	kmod.km_list.ml_next = mdb_list_next(&kt->k_modlist);
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)obj) {
8587c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EXEC:
8597c478bd9Sstevel@tonic-gate 		km = &kmod;
8607c478bd9Sstevel@tonic-gate 		n = 1;
8617c478bd9Sstevel@tonic-gate 		break;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EVERY:
8647c478bd9Sstevel@tonic-gate 		km = &kmod;
8657c478bd9Sstevel@tonic-gate 		n = mdb_nv_size(&kt->k_modules) + 1;
8667c478bd9Sstevel@tonic-gate 		break;
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_RTLD:
869ae115bc7Smrj 		obj = kt->k_rtld_name;
8707c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	default:
8737c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&kt->k_modules, obj)) == NULL)
8747c478bd9Sstevel@tonic-gate 			return (set_errno(EMDB_NOOBJ));
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 		km = mdb_nv_get_cookie(v);
8777c478bd9Sstevel@tonic-gate 		n = 1;
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 		if (km->km_symtab == NULL)
8807c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
8817c478bd9Sstevel@tonic-gate 	}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	for (; n > 0; n--, km = mdb_list_next(km)) {
8847c478bd9Sstevel@tonic-gate 		if (mdb_gelf_symtab_lookup_by_name(km->km_symtab, name,
8857c478bd9Sstevel@tonic-gate 		    symp, &sip->sym_id) == 0) {
8867c478bd9Sstevel@tonic-gate 			sip->sym_table = MDB_TGT_SYMTAB;
8877c478bd9Sstevel@tonic-gate 			return (0);
8887c478bd9Sstevel@tonic-gate 		}
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	return (set_errno(EMDB_NOSYM));
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate int
8957c478bd9Sstevel@tonic-gate kt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags,
8967c478bd9Sstevel@tonic-gate     char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip)
8977c478bd9Sstevel@tonic-gate {
8987c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
8997c478bd9Sstevel@tonic-gate 	kt_module_t kmods[3], *kmods_begin = &kmods[0], *kmods_end;
9007c478bd9Sstevel@tonic-gate 	const char *name;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	kt_module_t *km = &kmods[0];	/* Point km at first fake module */
9037c478bd9Sstevel@tonic-gate 	kt_module_t *sym_km = NULL;	/* Module associated with best sym */
9047c478bd9Sstevel@tonic-gate 	GElf_Sym sym;			/* Best symbol found so far if !exact */
9057c478bd9Sstevel@tonic-gate 	uint_t symid;			/* ID of best symbol found so far */
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	/*
9087c478bd9Sstevel@tonic-gate 	 * To simplify the implementation, we create fake modules on the stack
9097c478bd9Sstevel@tonic-gate 	 * that are "prepended" to k_modlist and whose symtab is set to
9107c478bd9Sstevel@tonic-gate 	 * each of three special symbol tables, in order of precedence.
9117c478bd9Sstevel@tonic-gate 	 */
9127c478bd9Sstevel@tonic-gate 	km->km_symtab = mdb.m_prsym;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	if (kt->k_symtab != NULL) {
9157c478bd9Sstevel@tonic-gate 		km->km_list.ml_next = (mdb_list_t *)(km + 1);
9167c478bd9Sstevel@tonic-gate 		km = mdb_list_next(km);
9177c478bd9Sstevel@tonic-gate 		km->km_symtab = kt->k_symtab;
9187c478bd9Sstevel@tonic-gate 	}
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	if (kt->k_dynsym != NULL) {
9217c478bd9Sstevel@tonic-gate 		km->km_list.ml_next = (mdb_list_t *)(km + 1);
9227c478bd9Sstevel@tonic-gate 		km = mdb_list_next(km);
9237c478bd9Sstevel@tonic-gate 		km->km_symtab = kt->k_dynsym;
9247c478bd9Sstevel@tonic-gate 	}
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	km->km_list.ml_next = mdb_list_next(&kt->k_modlist);
9277c478bd9Sstevel@tonic-gate 	kmods_end = km;
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	/*
9307c478bd9Sstevel@tonic-gate 	 * Now iterate over the list of fake and real modules.  If the module
9317c478bd9Sstevel@tonic-gate 	 * has no symbol table and the address is in the text section,
9327c478bd9Sstevel@tonic-gate 	 * instantiate the module's symbol table.  In exact mode, we can
9337c478bd9Sstevel@tonic-gate 	 * jump to 'found' immediately if we match.  Otherwise we continue
9347c478bd9Sstevel@tonic-gate 	 * looking and improve our choice if we find a closer symbol.
9357c478bd9Sstevel@tonic-gate 	 */
9367c478bd9Sstevel@tonic-gate 	for (km = &kmods[0]; km != NULL; km = mdb_list_next(km)) {
9377c478bd9Sstevel@tonic-gate 		if (km->km_symtab == NULL && addr >= km->km_text_va &&
9387c478bd9Sstevel@tonic-gate 		    addr < km->km_text_va + km->km_text_size)
9397c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 		if (mdb_gelf_symtab_lookup_by_addr(km->km_symtab, addr,
9427c478bd9Sstevel@tonic-gate 		    flags, buf, nbytes, symp, &sip->sym_id) != 0 ||
9437c478bd9Sstevel@tonic-gate 		    symp->st_value == 0)
9447c478bd9Sstevel@tonic-gate 			continue;
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 		if (flags & MDB_TGT_SYM_EXACT) {
9477c478bd9Sstevel@tonic-gate 			sym_km = km;
9487c478bd9Sstevel@tonic-gate 			goto found;
9497c478bd9Sstevel@tonic-gate 		}
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 		if (sym_km == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) {
9527c478bd9Sstevel@tonic-gate 			sym_km = km;
9537c478bd9Sstevel@tonic-gate 			sym = *symp;
9547c478bd9Sstevel@tonic-gate 			symid = sip->sym_id;
9557c478bd9Sstevel@tonic-gate 		}
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	if (sym_km == NULL)
9597c478bd9Sstevel@tonic-gate 		return (set_errno(EMDB_NOSYMADDR));
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	*symp = sym; /* Copy our best symbol into the caller's symbol */
9627c478bd9Sstevel@tonic-gate 	sip->sym_id = symid;
9637c478bd9Sstevel@tonic-gate found:
9647c478bd9Sstevel@tonic-gate 	/*
9657c478bd9Sstevel@tonic-gate 	 * Once we've found something, copy the final name into the caller's
9667c478bd9Sstevel@tonic-gate 	 * buffer and prefix it with the load object name if appropriate.
9677c478bd9Sstevel@tonic-gate 	 */
968843e1988Sjohnlev 	if (sym_km != NULL) {
969843e1988Sjohnlev 		name = mdb_gelf_sym_name(sym_km->km_symtab, symp);
970843e1988Sjohnlev 
971843e1988Sjohnlev 		if (sym_km < kmods_begin || sym_km > kmods_end) {
972843e1988Sjohnlev 			(void) mdb_snprintf(buf, nbytes, "%s`%s",
973843e1988Sjohnlev 			    sym_km->km_name, name);
974843e1988Sjohnlev 		} else if (nbytes > 0) {
975843e1988Sjohnlev 			(void) strncpy(buf, name, nbytes);
976843e1988Sjohnlev 			buf[nbytes - 1] = '\0';
977843e1988Sjohnlev 		}
9787c478bd9Sstevel@tonic-gate 
979843e1988Sjohnlev 		if (sym_km->km_symtab == mdb.m_prsym)
980843e1988Sjohnlev 			sip->sym_table = MDB_TGT_PRVSYM;
981843e1988Sjohnlev 		else
982843e1988Sjohnlev 			sip->sym_table = MDB_TGT_SYMTAB;
983843e1988Sjohnlev 	} else {
9847c478bd9Sstevel@tonic-gate 		sip->sym_table = MDB_TGT_SYMTAB;
985843e1988Sjohnlev 	}
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	return (0);
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate static int
9917c478bd9Sstevel@tonic-gate kt_symtab_func(void *data, const GElf_Sym *sym, const char *name, uint_t id)
9927c478bd9Sstevel@tonic-gate {
9937c478bd9Sstevel@tonic-gate 	kt_symarg_t *argp = data;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	if (mdb_tgt_sym_match(sym, argp->sym_type)) {
9967c478bd9Sstevel@tonic-gate 		argp->sym_info.sym_id = id;
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 		return (argp->sym_cb(argp->sym_data, sym, name,
9997c478bd9Sstevel@tonic-gate 		    &argp->sym_info, argp->sym_obj));
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	return (0);
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate static void
10067c478bd9Sstevel@tonic-gate kt_symtab_iter(mdb_gelf_symtab_t *gst, uint_t type, const char *obj,
10077c478bd9Sstevel@tonic-gate     mdb_tgt_sym_f *cb, void *p)
10087c478bd9Sstevel@tonic-gate {
10097c478bd9Sstevel@tonic-gate 	kt_symarg_t arg;
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 	arg.sym_cb = cb;
10127c478bd9Sstevel@tonic-gate 	arg.sym_data = p;
10137c478bd9Sstevel@tonic-gate 	arg.sym_type = type;
10147c478bd9Sstevel@tonic-gate 	arg.sym_info.sym_table = gst->gst_tabid;
10157c478bd9Sstevel@tonic-gate 	arg.sym_obj = obj;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	mdb_gelf_symtab_iter(gst, kt_symtab_func, &arg);
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate int
10217c478bd9Sstevel@tonic-gate kt_symbol_iter(mdb_tgt_t *t, const char *obj, uint_t which, uint_t type,
10227c478bd9Sstevel@tonic-gate     mdb_tgt_sym_f *cb, void *data)
10237c478bd9Sstevel@tonic-gate {
10247c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
10257c478bd9Sstevel@tonic-gate 	kt_module_t *km;
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	mdb_gelf_symtab_t *symtab = NULL;
10287c478bd9Sstevel@tonic-gate 	mdb_var_t *v;
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	switch ((uintptr_t)obj) {
10317c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EXEC:
10327c478bd9Sstevel@tonic-gate 		if (which == MDB_TGT_SYMTAB)
10337c478bd9Sstevel@tonic-gate 			symtab = kt->k_symtab;
10347c478bd9Sstevel@tonic-gate 		else
10357c478bd9Sstevel@tonic-gate 			symtab = kt->k_dynsym;
10367c478bd9Sstevel@tonic-gate 		break;
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_EVERY:
10397c478bd9Sstevel@tonic-gate 		if (which == MDB_TGT_DYNSYM) {
10407c478bd9Sstevel@tonic-gate 			symtab = kt->k_dynsym;
10417c478bd9Sstevel@tonic-gate 			obj = MDB_TGT_OBJ_EXEC;
10427c478bd9Sstevel@tonic-gate 			break;
10437c478bd9Sstevel@tonic-gate 		}
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 		mdb_nv_rewind(&kt->k_modules);
10467c478bd9Sstevel@tonic-gate 		while ((v = mdb_nv_advance(&kt->k_modules)) != NULL) {
10477c478bd9Sstevel@tonic-gate 			km = mdb_nv_get_cookie(v);
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 			if (km->km_symtab == NULL)
10507c478bd9Sstevel@tonic-gate 				kt_load_module(kt, t, km);
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 			if (km->km_symtab != NULL)
10537c478bd9Sstevel@tonic-gate 				kt_symtab_iter(km->km_symtab, type,
10547c478bd9Sstevel@tonic-gate 				    km->km_name, cb, data);
10557c478bd9Sstevel@tonic-gate 		}
10567c478bd9Sstevel@tonic-gate 		break;
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	case (uintptr_t)MDB_TGT_OBJ_RTLD:
1059ae115bc7Smrj 		obj = kt->k_rtld_name;
10607c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	default:
10637c478bd9Sstevel@tonic-gate 		v = mdb_nv_lookup(&kt->k_modules, obj);
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 		if (v == NULL)
10667c478bd9Sstevel@tonic-gate 			return (set_errno(EMDB_NOOBJ));
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 		km = mdb_nv_get_cookie(v);
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 		if (km->km_symtab == NULL)
10717c478bd9Sstevel@tonic-gate 			kt_load_module(kt, t, km);
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 		symtab = km->km_symtab;
10747c478bd9Sstevel@tonic-gate 	}
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	if (symtab)
10777c478bd9Sstevel@tonic-gate 		kt_symtab_iter(symtab, type, obj, cb, data);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	return (0);
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate static int
10837c478bd9Sstevel@tonic-gate kt_mapping_walk(uintptr_t addr, const void *data, kt_maparg_t *marg)
10847c478bd9Sstevel@tonic-gate {
10857c478bd9Sstevel@tonic-gate 	/*
10867c478bd9Sstevel@tonic-gate 	 * This is a bit sketchy but avoids problematic compilation of this
10877c478bd9Sstevel@tonic-gate 	 * target against the current VM implementation.  Now that we have
10887c478bd9Sstevel@tonic-gate 	 * vmem, we can make this less broken and more informative by changing
10897c478bd9Sstevel@tonic-gate 	 * this code to invoke the vmem walker in the near future.
10907c478bd9Sstevel@tonic-gate 	 */
10917c478bd9Sstevel@tonic-gate 	const struct kt_seg {
10927c478bd9Sstevel@tonic-gate 		caddr_t s_base;
10937c478bd9Sstevel@tonic-gate 		size_t s_size;
10947c478bd9Sstevel@tonic-gate 	} *segp = (const struct kt_seg *)data;
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	mdb_map_t map;
10977c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
10987c478bd9Sstevel@tonic-gate 	mdb_syminfo_t info;
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	map.map_base = (uintptr_t)segp->s_base;
11017c478bd9Sstevel@tonic-gate 	map.map_size = segp->s_size;
11027c478bd9Sstevel@tonic-gate 	map.map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_W | MDB_TGT_MAP_X;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	if (kt_lookup_by_addr(marg->map_target, addr, MDB_TGT_SYM_EXACT,
11057c478bd9Sstevel@tonic-gate 	    map.map_name, MDB_TGT_MAPSZ, &sym, &info) == -1) {
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 		(void) mdb_iob_snprintf(map.map_name, MDB_TGT_MAPSZ,
11087c478bd9Sstevel@tonic-gate 		    "%lr", addr);
11097c478bd9Sstevel@tonic-gate 	}
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	return (marg->map_cb(marg->map_data, &map, map.map_name));
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate int
11157c478bd9Sstevel@tonic-gate kt_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
11167c478bd9Sstevel@tonic-gate {
11177c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
11187c478bd9Sstevel@tonic-gate 	kt_maparg_t m;
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	m.map_target = t;
11217c478bd9Sstevel@tonic-gate 	m.map_cb = func;
11227c478bd9Sstevel@tonic-gate 	m.map_data = private;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	return (mdb_pwalk("seg", (mdb_walk_cb_t)kt_mapping_walk, &m,
11257c478bd9Sstevel@tonic-gate 	    (uintptr_t)kt->k_as));
11267c478bd9Sstevel@tonic-gate }
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate static const mdb_map_t *
11297c478bd9Sstevel@tonic-gate kt_module_to_map(kt_module_t *km, mdb_map_t *map)
11307c478bd9Sstevel@tonic-gate {
11317c478bd9Sstevel@tonic-gate 	(void) strncpy(map->map_name, km->km_name, MDB_TGT_MAPSZ);
11327c478bd9Sstevel@tonic-gate 	map->map_name[MDB_TGT_MAPSZ - 1] = '\0';
11337c478bd9Sstevel@tonic-gate 	map->map_base = km->km_text_va;
11347c478bd9Sstevel@tonic-gate 	map->map_size = km->km_text_size;
11357c478bd9Sstevel@tonic-gate 	map->map_flags = MDB_TGT_MAP_R | MDB_TGT_MAP_W | MDB_TGT_MAP_X;
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	return (map);
11387c478bd9Sstevel@tonic-gate }
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate int
11417c478bd9Sstevel@tonic-gate kt_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
11427c478bd9Sstevel@tonic-gate {
11437c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
11447c478bd9Sstevel@tonic-gate 	kt_module_t *km;
11457c478bd9Sstevel@tonic-gate 	mdb_map_t m;
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
11487c478bd9Sstevel@tonic-gate 		if (func(private, kt_module_to_map(km, &m), km->km_name) == -1)
11497c478bd9Sstevel@tonic-gate 			break;
11507c478bd9Sstevel@tonic-gate 	}
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 	return (0);
11537c478bd9Sstevel@tonic-gate }
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate const mdb_map_t *
11567c478bd9Sstevel@tonic-gate kt_addr_to_map(mdb_tgt_t *t, uintptr_t addr)
11577c478bd9Sstevel@tonic-gate {
11587c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
11597c478bd9Sstevel@tonic-gate 	kt_module_t *km;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
11627c478bd9Sstevel@tonic-gate 		if (addr - km->km_text_va < km->km_text_size ||
11637c478bd9Sstevel@tonic-gate 		    addr - km->km_data_va < km->km_data_size ||
11647c478bd9Sstevel@tonic-gate 		    addr - km->km_bss_va < km->km_bss_size)
11657c478bd9Sstevel@tonic-gate 			return (kt_module_to_map(km, &kt->k_map));
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOMAP);
11697c478bd9Sstevel@tonic-gate 	return (NULL);
11707c478bd9Sstevel@tonic-gate }
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate const mdb_map_t *
11737c478bd9Sstevel@tonic-gate kt_name_to_map(mdb_tgt_t *t, const char *name)
11747c478bd9Sstevel@tonic-gate {
11757c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
11767c478bd9Sstevel@tonic-gate 	kt_module_t *km;
11777c478bd9Sstevel@tonic-gate 	mdb_map_t m;
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	/*
11807c478bd9Sstevel@tonic-gate 	 * If name is MDB_TGT_OBJ_EXEC, return the first module on the list,
11817c478bd9Sstevel@tonic-gate 	 * which will be unix since we keep k_modlist in load order.
11827c478bd9Sstevel@tonic-gate 	 */
11837c478bd9Sstevel@tonic-gate 	if (name == MDB_TGT_OBJ_EXEC)
11847c478bd9Sstevel@tonic-gate 		return (kt_module_to_map(mdb_list_next(&kt->k_modlist), &m));
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 	if (name == MDB_TGT_OBJ_RTLD)
1187ae115bc7Smrj 		name = kt->k_rtld_name;
11887c478bd9Sstevel@tonic-gate 
1189ae115bc7Smrj 	if ((km = kt_module_by_name(kt, name)) != NULL)
1190ae115bc7Smrj 		return (kt_module_to_map(km, &m));
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOOBJ);
11937c478bd9Sstevel@tonic-gate 	return (NULL);
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate static ctf_file_t *
11977c478bd9Sstevel@tonic-gate kt_load_ctfdata(mdb_tgt_t *t, kt_module_t *km)
11987c478bd9Sstevel@tonic-gate {
11997c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
12007c478bd9Sstevel@tonic-gate 	int err;
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 	if (km->km_ctfp != NULL)
12037c478bd9Sstevel@tonic-gate 		return (km->km_ctfp);
12047c478bd9Sstevel@tonic-gate 
1205892ad162SToomas Soome 	if (km->km_ctf_va == 0) {
12067c478bd9Sstevel@tonic-gate 		(void) set_errno(EMDB_NOCTF);
12077c478bd9Sstevel@tonic-gate 		return (NULL);
12087c478bd9Sstevel@tonic-gate 	}
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 	if (km->km_symtab == NULL)
12117c478bd9Sstevel@tonic-gate 		kt_load_module(t->t_data, t, km);
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 	if ((km->km_ctf_buf = mdb_alloc(km->km_ctf_size, UM_NOSLEEP)) == NULL) {
12147c478bd9Sstevel@tonic-gate 		warn("failed to allocate memory to load %s debugging "
12157c478bd9Sstevel@tonic-gate 		    "information", km->km_name);
12167c478bd9Sstevel@tonic-gate 		return (NULL);
12177c478bd9Sstevel@tonic-gate 	}
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate 	if (mdb_tgt_vread(t, km->km_ctf_buf, km->km_ctf_size,
12207c478bd9Sstevel@tonic-gate 	    km->km_ctf_va) != km->km_ctf_size) {
12217c478bd9Sstevel@tonic-gate 		warn("failed to read %lu bytes of debug data for %s at %p",
12227c478bd9Sstevel@tonic-gate 		    (ulong_t)km->km_ctf_size, km->km_name,
12237c478bd9Sstevel@tonic-gate 		    (void *)km->km_ctf_va);
12247c478bd9Sstevel@tonic-gate 		mdb_free(km->km_ctf_buf, km->km_ctf_size);
12257c478bd9Sstevel@tonic-gate 		km->km_ctf_buf = NULL;
12267c478bd9Sstevel@tonic-gate 		return (NULL);
12277c478bd9Sstevel@tonic-gate 	}
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	if ((km->km_ctfp = mdb_ctf_bufopen((const void *)km->km_ctf_buf,
12307c478bd9Sstevel@tonic-gate 	    km->km_ctf_size, km->km_symbuf, &km->km_symtab_hdr,
12317c478bd9Sstevel@tonic-gate 	    km->km_strtab, &km->km_strtab_hdr, &err)) == NULL) {
12327c478bd9Sstevel@tonic-gate 		mdb_free(km->km_ctf_buf, km->km_ctf_size);
12337c478bd9Sstevel@tonic-gate 		km->km_ctf_buf = NULL;
12347c478bd9Sstevel@tonic-gate 		(void) set_errno(ctf_to_errno(err));
12357c478bd9Sstevel@tonic-gate 		return (NULL);
12367c478bd9Sstevel@tonic-gate 	}
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 	mdb_dprintf(MDB_DBG_KMOD, "loaded %lu bytes of CTF data for %s\n",
12397c478bd9Sstevel@tonic-gate 	    (ulong_t)km->km_ctf_size, km->km_name);
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 	if (ctf_parent_name(km->km_ctfp) != NULL) {
12427c478bd9Sstevel@tonic-gate 		mdb_var_t *v;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 		if ((v = mdb_nv_lookup(&kt->k_modules,
12457c478bd9Sstevel@tonic-gate 		    ctf_parent_name(km->km_ctfp))) == NULL) {
12467c478bd9Sstevel@tonic-gate 			warn("failed to load CTF data for %s - parent %s not "
12477c478bd9Sstevel@tonic-gate 			    "loaded\n", km->km_name,
12487c478bd9Sstevel@tonic-gate 			    ctf_parent_name(km->km_ctfp));
12497c478bd9Sstevel@tonic-gate 		}
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 		if (v != NULL) {
12527c478bd9Sstevel@tonic-gate 			kt_module_t *pm = mdb_nv_get_cookie(v);
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 			if (pm->km_ctfp == NULL)
12557c478bd9Sstevel@tonic-gate 				(void) kt_load_ctfdata(t, pm);
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 			if (pm->km_ctfp != NULL && ctf_import(km->km_ctfp,
12587c478bd9Sstevel@tonic-gate 			    pm->km_ctfp) == CTF_ERR) {
12597c478bd9Sstevel@tonic-gate 				warn("failed to import parent types into "
12607c478bd9Sstevel@tonic-gate 				    "%s: %s\n", km->km_name,
12617c478bd9Sstevel@tonic-gate 				    ctf_errmsg(ctf_errno(km->km_ctfp)));
12627c478bd9Sstevel@tonic-gate 			}
12637c478bd9Sstevel@tonic-gate 		}
12647c478bd9Sstevel@tonic-gate 	}
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 	return (km->km_ctfp);
12677c478bd9Sstevel@tonic-gate }
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate ctf_file_t *
12707c478bd9Sstevel@tonic-gate kt_addr_to_ctf(mdb_tgt_t *t, uintptr_t addr)
12717c478bd9Sstevel@tonic-gate {
12727c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
12737c478bd9Sstevel@tonic-gate 	kt_module_t *km;
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) {
12767c478bd9Sstevel@tonic-gate 		if (addr - km->km_text_va < km->km_text_size ||
12777c478bd9Sstevel@tonic-gate 		    addr - km->km_data_va < km->km_data_size ||
12787c478bd9Sstevel@tonic-gate 		    addr - km->km_bss_va < km->km_bss_size)
12797c478bd9Sstevel@tonic-gate 			return (kt_load_ctfdata(t, km));
12807c478bd9Sstevel@tonic-gate 	}
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOMAP);
12837c478bd9Sstevel@tonic-gate 	return (NULL);
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate ctf_file_t *
12877c478bd9Sstevel@tonic-gate kt_name_to_ctf(mdb_tgt_t *t, const char *name)
12887c478bd9Sstevel@tonic-gate {
12897c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
12907c478bd9Sstevel@tonic-gate 	kt_module_t *km;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	if (name == MDB_TGT_OBJ_EXEC)
1293ae115bc7Smrj 		name = KT_CTFPARENT;
12947c478bd9Sstevel@tonic-gate 	else if (name == MDB_TGT_OBJ_RTLD)
1295ae115bc7Smrj 		name = kt->k_rtld_name;
12967c478bd9Sstevel@tonic-gate 
1297ae115bc7Smrj 	if ((km = kt_module_by_name(kt, name)) != NULL)
1298ae115bc7Smrj 		return (kt_load_ctfdata(t, km));
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 	(void) set_errno(EMDB_NOOBJ);
13017c478bd9Sstevel@tonic-gate 	return (NULL);
13027c478bd9Sstevel@tonic-gate }
13037c478bd9Sstevel@tonic-gate 
1304843e1988Sjohnlev /*ARGSUSED*/
13057c478bd9Sstevel@tonic-gate int
13067c478bd9Sstevel@tonic-gate kt_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
13077c478bd9Sstevel@tonic-gate {
13087c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
13097c478bd9Sstevel@tonic-gate 	bzero(tsp, sizeof (mdb_tgt_status_t));
1310843e1988Sjohnlev 	tsp->st_state = (kt->k_xpv_domu || (kt->k_dumphdr != NULL)) ?
1311843e1988Sjohnlev 	    MDB_TGT_DEAD : MDB_TGT_RUNNING;
13127c478bd9Sstevel@tonic-gate 	return (0);
13137c478bd9Sstevel@tonic-gate }
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate static ssize_t
13167c478bd9Sstevel@tonic-gate kt_xd_dumphdr(mdb_tgt_t *t, void *buf, size_t nbytes)
13177c478bd9Sstevel@tonic-gate {
13187c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 	if (buf == NULL && nbytes == 0)
13217c478bd9Sstevel@tonic-gate 		return (sizeof (dumphdr_t));
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr == NULL)
13247c478bd9Sstevel@tonic-gate 		return (set_errno(ENODATA));
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 	nbytes = MIN(nbytes, sizeof (dumphdr_t));
13277c478bd9Sstevel@tonic-gate 	bcopy(kt->k_dumphdr, buf, nbytes);
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 	return (nbytes);
13307c478bd9Sstevel@tonic-gate }
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate void
13337c478bd9Sstevel@tonic-gate kt_destroy(mdb_tgt_t *t)
13347c478bd9Sstevel@tonic-gate {
13357c478bd9Sstevel@tonic-gate 	kt_data_t *kt = t->t_data;
13367c478bd9Sstevel@tonic-gate 	kt_module_t *km, *nkm;
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	(void) mdb_module_unload(KT_MODULE, 0);
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate 	if (kt->k_regs != NULL)
13417c478bd9Sstevel@tonic-gate 		mdb_free(kt->k_regs, kt->k_regsize);
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 	if (kt->k_symtab != NULL)
13447c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_symtab);
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 	if (kt->k_dynsym != NULL)
13477c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_dynsym);
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr != NULL)
13507c478bd9Sstevel@tonic-gate 		mdb_free(kt->k_dumphdr, sizeof (dumphdr_t));
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	mdb_gelf_destroy(kt->k_file);
1353843e1988Sjohnlev 
1354843e1988Sjohnlev 	(void) kt->k_kb_ops->kb_close(kt->k_cookie);
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	for (km = mdb_list_next(&kt->k_modlist); km; km = nkm) {
13577c478bd9Sstevel@tonic-gate 		if (km->km_symtab)
13587c478bd9Sstevel@tonic-gate 			mdb_gelf_symtab_destroy(km->km_symtab);
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 		if (km->km_data)
13617c478bd9Sstevel@tonic-gate 			mdb_free(km->km_data, km->km_datasz);
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 		if (km->km_ctfp)
13647c478bd9Sstevel@tonic-gate 			ctf_close(km->km_ctfp);
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 		if (km->km_ctf_buf != NULL)
13677c478bd9Sstevel@tonic-gate 			mdb_free(km->km_ctf_buf, km->km_ctf_size);
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 		nkm = mdb_list_next(km);
13707c478bd9Sstevel@tonic-gate 		strfree(km->km_name);
13717c478bd9Sstevel@tonic-gate 		mdb_free(km, sizeof (kt_module_t));
13727c478bd9Sstevel@tonic-gate 	}
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	mdb_nv_destroy(&kt->k_modules);
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 	strfree(kt->k_kvmfile);
1377843e1988Sjohnlev 	if (kt->k_symfile != NULL)
1378843e1988Sjohnlev 		strfree(kt->k_symfile);
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 	mdb_free(kt, sizeof (kt_data_t));
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate static int
13847c478bd9Sstevel@tonic-gate kt_data_stub(void)
13857c478bd9Sstevel@tonic-gate {
13867c478bd9Sstevel@tonic-gate 	return (-1);
13877c478bd9Sstevel@tonic-gate }
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate int
13907c478bd9Sstevel@tonic-gate mdb_kvm_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
13917c478bd9Sstevel@tonic-gate {
13927c478bd9Sstevel@tonic-gate 	kt_data_t *kt = mdb_zalloc(sizeof (kt_data_t), UM_SLEEP);
1393843e1988Sjohnlev 	mdb_kb_ops_t *kvm_kb_ops = libkvm_kb_ops();
13947c478bd9Sstevel@tonic-gate 	int oflag = (t->t_flags & MDB_TGT_F_RDWR) ? O_RDWR : O_RDONLY;
13957c478bd9Sstevel@tonic-gate 	struct utsname uts;
13967c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
13977c478bd9Sstevel@tonic-gate 	pgcnt_t pmem;
13987c478bd9Sstevel@tonic-gate 
1399843e1988Sjohnlev 
1400843e1988Sjohnlev 	if (argc == 2) {
1401843e1988Sjohnlev 		kt->k_symfile = strdup(argv[0]);
1402843e1988Sjohnlev 		kt->k_kvmfile = strdup(argv[1]);
1403843e1988Sjohnlev 
1404843e1988Sjohnlev 		kt->k_cookie = kvm_kb_ops->kb_open(kt->k_symfile,
1405843e1988Sjohnlev 		    kt->k_kvmfile, NULL, oflag, (char *)mdb.m_pname);
1406843e1988Sjohnlev 
1407843e1988Sjohnlev 		if (kt->k_cookie == NULL)
1408843e1988Sjohnlev 			goto err;
1409843e1988Sjohnlev 
1410843e1988Sjohnlev 		kt->k_xpv_domu = 0;
1411843e1988Sjohnlev 		kt->k_kb_ops = kvm_kb_ops;
1412843e1988Sjohnlev 	} else {
1413843e1988Sjohnlev #ifndef __x86
14147c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
1415843e1988Sjohnlev #else
1416843e1988Sjohnlev 		mdb_kb_ops_t *(*getops)(void);
14177c478bd9Sstevel@tonic-gate 
1418843e1988Sjohnlev 		kt->k_symfile = NULL;
1419843e1988Sjohnlev 		kt->k_kvmfile = strdup(argv[0]);
14207c478bd9Sstevel@tonic-gate 
1421843e1988Sjohnlev 		getops = (mdb_kb_ops_t *(*)())dlsym(RTLD_NEXT, "mdb_kb_ops");
14227c478bd9Sstevel@tonic-gate 
1423a576ab5bSrab 		/*
1424a576ab5bSrab 		 * Load mdb_kb if it's not already loaded during
1425a576ab5bSrab 		 * identification.
1426a576ab5bSrab 		 */
1427a576ab5bSrab 		if (getops == NULL) {
1428a576ab5bSrab 			(void) mdb_module_load("mdb_kb",
1429a576ab5bSrab 			    MDB_MOD_GLOBAL | MDB_MOD_SILENT);
1430a576ab5bSrab 			getops = (mdb_kb_ops_t *(*)())
1431a576ab5bSrab 			    dlsym(RTLD_NEXT, "mdb_kb_ops");
1432a576ab5bSrab 		}
1433a576ab5bSrab 
1434843e1988Sjohnlev 		if (getops == NULL || (kt->k_kb_ops = getops()) == NULL) {
1435843e1988Sjohnlev 			warn("failed to load KVM backend ops\n");
1436843e1988Sjohnlev 			goto err;
1437843e1988Sjohnlev 		}
1438843e1988Sjohnlev 
1439843e1988Sjohnlev 		kt->k_cookie = kt->k_kb_ops->kb_open(NULL, kt->k_kvmfile, NULL,
1440843e1988Sjohnlev 		    oflag, (char *)mdb.m_pname);
1441843e1988Sjohnlev 
1442843e1988Sjohnlev 		if (kt->k_cookie == NULL)
1443843e1988Sjohnlev 			goto err;
1444843e1988Sjohnlev 
1445843e1988Sjohnlev 		kt->k_xpv_domu = 1;
1446843e1988Sjohnlev #endif
14477c478bd9Sstevel@tonic-gate 	}
14487c478bd9Sstevel@tonic-gate 
1449843e1988Sjohnlev 	if ((kt->k_fio = kt->k_kb_ops->kb_sym_io(kt->k_cookie,
1450843e1988Sjohnlev 	    kt->k_symfile)) == NULL)
1451843e1988Sjohnlev 		goto err;
1452843e1988Sjohnlev 
14537c478bd9Sstevel@tonic-gate 	if ((kt->k_file = mdb_gelf_create(kt->k_fio,
14547c478bd9Sstevel@tonic-gate 	    ET_EXEC, GF_FILE)) == NULL) {
14557c478bd9Sstevel@tonic-gate 		mdb_io_destroy(kt->k_fio);
14567c478bd9Sstevel@tonic-gate 		goto err;
14577c478bd9Sstevel@tonic-gate 	}
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 	kt->k_symtab =
14607c478bd9Sstevel@tonic-gate 	    mdb_gelf_symtab_create_file(kt->k_file, SHT_SYMTAB, MDB_TGT_SYMTAB);
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 	kt->k_dynsym =
14637c478bd9Sstevel@tonic-gate 	    mdb_gelf_symtab_create_file(kt->k_file, SHT_DYNSYM, MDB_TGT_DYNSYM);
14647c478bd9Sstevel@tonic-gate 
14657c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "kas",
14667c478bd9Sstevel@tonic-gate 	    &sym, NULL) == -1) {
14677c478bd9Sstevel@tonic-gate 		warn("'kas' symbol is missing from kernel\n");
14687c478bd9Sstevel@tonic-gate 		goto err;
14697c478bd9Sstevel@tonic-gate 	}
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate 	kt->k_as = (struct as *)(uintptr_t)sym.st_value;
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "platform",
14747c478bd9Sstevel@tonic-gate 	    &sym, NULL) == -1) {
14757c478bd9Sstevel@tonic-gate 		warn("'platform' symbol is missing from kernel\n");
14767c478bd9Sstevel@tonic-gate 		goto err;
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate 
1479843e1988Sjohnlev 	if (kt->k_kb_ops->kb_kread(kt->k_cookie, sym.st_value,
14807c478bd9Sstevel@tonic-gate 	    kt->k_platform, MAXNAMELEN) <= 0) {
14817c478bd9Sstevel@tonic-gate 		warn("failed to read 'platform' string from kernel");
14827c478bd9Sstevel@tonic-gate 		goto err;
14837c478bd9Sstevel@tonic-gate 	}
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "utsname",
14867c478bd9Sstevel@tonic-gate 	    &sym, NULL) == -1) {
14877c478bd9Sstevel@tonic-gate 		warn("'utsname' symbol is missing from kernel\n");
14887c478bd9Sstevel@tonic-gate 		goto err;
14897c478bd9Sstevel@tonic-gate 	}
14907c478bd9Sstevel@tonic-gate 
1491843e1988Sjohnlev 	if (kt->k_kb_ops->kb_kread(kt->k_cookie, sym.st_value, &uts,
1492843e1988Sjohnlev 	    sizeof (uts)) <= 0) {
14937c478bd9Sstevel@tonic-gate 		warn("failed to read 'utsname' struct from kernel");
14947c478bd9Sstevel@tonic-gate 		goto err;
14957c478bd9Sstevel@tonic-gate 	}
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 	kt->k_dump_print_content = (void (*)())kt_data_stub;
14987c478bd9Sstevel@tonic-gate 	kt->k_dump_find_curproc = kt_data_stub;
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 	/*
15017c478bd9Sstevel@tonic-gate 	 * We set k_ctfvalid based on the presence of the CTF vmem arena
15027c478bd9Sstevel@tonic-gate 	 * symbol.  The CTF members were added to the end of struct module at
15037c478bd9Sstevel@tonic-gate 	 * the same time, so this allows us to know whether we can use them.
15047c478bd9Sstevel@tonic-gate 	 */
15057c478bd9Sstevel@tonic-gate 	if (mdb_gelf_symtab_lookup_by_name(kt->k_symtab, "ctf_arena", &sym,
15067c478bd9Sstevel@tonic-gate 	    NULL) == 0 && !(mdb.m_flags & MDB_FL_NOCTF))
15077c478bd9Sstevel@tonic-gate 		kt->k_ctfvalid = 1;
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 	(void) mdb_nv_create(&kt->k_modules, UM_SLEEP);
15107c478bd9Sstevel@tonic-gate 	t->t_pshandle = kt->k_cookie;
15117c478bd9Sstevel@tonic-gate 	t->t_data = kt;
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate #if defined(__sparc)
15147c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
15157c478bd9Sstevel@tonic-gate 	kt_sparcv9_init(t);
15167c478bd9Sstevel@tonic-gate #else
15177c478bd9Sstevel@tonic-gate 	kt_sparcv7_init(t);
15187c478bd9Sstevel@tonic-gate #endif
15197c478bd9Sstevel@tonic-gate #elif defined(__amd64)
15207c478bd9Sstevel@tonic-gate 	kt_amd64_init(t);
15217c478bd9Sstevel@tonic-gate #elif defined(__i386)
15227c478bd9Sstevel@tonic-gate 	kt_ia32_init(t);
15237c478bd9Sstevel@tonic-gate #else
15247c478bd9Sstevel@tonic-gate #error	"unknown ISA"
15257c478bd9Sstevel@tonic-gate #endif
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	/*
15287c478bd9Sstevel@tonic-gate 	 * We read our representative thread ID (address) from the kernel's
15297c478bd9Sstevel@tonic-gate 	 * global panic_thread.  It will remain 0 if this is a live kernel.
15307c478bd9Sstevel@tonic-gate 	 */
15317c478bd9Sstevel@tonic-gate 	(void) mdb_tgt_readsym(t, MDB_TGT_AS_VIRT, &kt->k_tid, sizeof (void *),
15327c478bd9Sstevel@tonic-gate 	    MDB_TGT_OBJ_EXEC, "panic_thread");
15337c478bd9Sstevel@tonic-gate 
15347c478bd9Sstevel@tonic-gate 	if ((mdb.m_flags & MDB_FL_ADB) && mdb_tgt_readsym(t, MDB_TGT_AS_VIRT,
15357c478bd9Sstevel@tonic-gate 	    &pmem, sizeof (pmem), MDB_TGT_OBJ_EXEC, "physmem") == sizeof (pmem))
15367c478bd9Sstevel@tonic-gate 		mdb_printf("physmem %lx\n", (ulong_t)pmem);
15377c478bd9Sstevel@tonic-gate 
15387c478bd9Sstevel@tonic-gate 	/*
1539843e1988Sjohnlev 	 * If this is not a live kernel or a hypervisor dump, read the dump
1540843e1988Sjohnlev 	 * header.  We don't have to sanity-check the header, as the open would
1541843e1988Sjohnlev 	 * not have succeeded otherwise.
15427c478bd9Sstevel@tonic-gate 	 */
1543843e1988Sjohnlev 	if (!kt->k_xpv_domu && strcmp(kt->k_symfile, "/dev/ksyms") != 0) {
15447c478bd9Sstevel@tonic-gate 		mdb_io_t *vmcore;
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 		kt->k_dumphdr = mdb_alloc(sizeof (dumphdr_t), UM_SLEEP);
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate 		if ((vmcore = mdb_fdio_create_path(NULL, kt->k_kvmfile,
15497c478bd9Sstevel@tonic-gate 		    O_RDONLY, 0)) == NULL) {
15507c478bd9Sstevel@tonic-gate 			mdb_warn("failed to open %s", kt->k_kvmfile);
15517c478bd9Sstevel@tonic-gate 			goto err;
15527c478bd9Sstevel@tonic-gate 		}
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 		if (IOP_READ(vmcore, kt->k_dumphdr, sizeof (dumphdr_t)) !=
15557c478bd9Sstevel@tonic-gate 		    sizeof (dumphdr_t)) {
15567c478bd9Sstevel@tonic-gate 			mdb_warn("failed to read dump header");
15577c478bd9Sstevel@tonic-gate 			mdb_io_destroy(vmcore);
15587c478bd9Sstevel@tonic-gate 			goto err;
15597c478bd9Sstevel@tonic-gate 		}
15607c478bd9Sstevel@tonic-gate 
15617c478bd9Sstevel@tonic-gate 		mdb_io_destroy(vmcore);
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 		(void) mdb_tgt_xdata_insert(t, "dumphdr",
15647c478bd9Sstevel@tonic-gate 		    "dump header structure", kt_xd_dumphdr);
15657c478bd9Sstevel@tonic-gate 	}
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate 	return (0);
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate err:
15707c478bd9Sstevel@tonic-gate 	if (kt->k_dumphdr != NULL)
15717c478bd9Sstevel@tonic-gate 		mdb_free(kt->k_dumphdr, sizeof (dumphdr_t));
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate 	if (kt->k_symtab != NULL)
15747c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_symtab);
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 	if (kt->k_dynsym != NULL)
15777c478bd9Sstevel@tonic-gate 		mdb_gelf_symtab_destroy(kt->k_dynsym);
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 	if (kt->k_file != NULL)
15807c478bd9Sstevel@tonic-gate 		mdb_gelf_destroy(kt->k_file);
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate 	if (kt->k_cookie != NULL)
1583843e1988Sjohnlev 		(void) kt->k_kb_ops->kb_close(kt->k_cookie);
15847c478bd9Sstevel@tonic-gate 
15857c478bd9Sstevel@tonic-gate 	mdb_free(kt, sizeof (kt_data_t));
15867c478bd9Sstevel@tonic-gate 	return (-1);
15877c478bd9Sstevel@tonic-gate }
1588ca3e8d88SDave Plauger 
15891320caf7SBryan Cantrill int
15901320caf7SBryan Cantrill mdb_kvm_is_dump(mdb_io_t *io)
15911320caf7SBryan Cantrill {
15921320caf7SBryan Cantrill 	dumphdr_t h;
15931320caf7SBryan Cantrill 
15941320caf7SBryan Cantrill 	(void) IOP_SEEK(io, (off64_t)0L, SEEK_SET);
15951320caf7SBryan Cantrill 
15961320caf7SBryan Cantrill 	return (IOP_READ(io, &h, sizeof (dumphdr_t)) == sizeof (dumphdr_t) &&
15971320caf7SBryan Cantrill 	    h.dump_magic == DUMP_MAGIC);
15981320caf7SBryan Cantrill }
15991320caf7SBryan Cantrill 
1600ca3e8d88SDave Plauger int
1601ca3e8d88SDave Plauger mdb_kvm_is_compressed_dump(mdb_io_t *io)
1602ca3e8d88SDave Plauger {
1603ca3e8d88SDave Plauger 	dumphdr_t h;
1604ca3e8d88SDave Plauger 
16051320caf7SBryan Cantrill 	(void) IOP_SEEK(io, (off64_t)0L, SEEK_SET);
16061320caf7SBryan Cantrill 
1607ca3e8d88SDave Plauger 	return (IOP_READ(io, &h, sizeof (dumphdr_t)) == sizeof (dumphdr_t) &&
1608ca3e8d88SDave Plauger 	    h.dump_magic == DUMP_MAGIC &&
1609ca3e8d88SDave Plauger 	    (h.dump_flags & DF_COMPRESSED) != 0);
1610ca3e8d88SDave Plauger }
1611