Home | History | Annotate | Download | only in mdb_ks
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * Mdb kernel support module.  This module is loaded automatically when the
     28  * kvm target is initialized.  Any global functions declared here are exported
     29  * for the resolution of symbols in subsequently loaded modules.
     30  *
     31  * WARNING: Do not assume that static variables in mdb_ks will be initialized
     32  * to zero.
     33  */
     34 
     35 
     36 #include <mdb/mdb_target.h>
     37 #include <mdb/mdb_param.h>
     38 #include <mdb/mdb_modapi.h>
     39 #include <mdb/mdb_ks.h>
     40 
     41 #include <sys/types.h>
     42 #include <sys/procfs.h>
     43 #include <sys/proc.h>
     44 #include <sys/dnlc.h>
     45 #include <sys/autoconf.h>
     46 #include <sys/machelf.h>
     47 #include <sys/modctl.h>
     48 #include <sys/hwconf.h>
     49 #include <sys/kobj.h>
     50 #include <sys/fs/autofs.h>
     51 #include <sys/ddi_impldefs.h>
     52 #include <sys/refstr_impl.h>
     53 #include <sys/cpuvar.h>
     54 #include <sys/dlpi.h>
     55 #include <errno.h>
     56 
     57 #include <vm/seg_vn.h>
     58 #include <vm/page.h>
     59 
     60 #define	MDB_PATH_NELEM	256			/* Maximum path components */
     61 
     62 typedef struct mdb_path {
     63 	size_t mdp_nelem;			/* Number of components */
     64 	uint_t mdp_complete;			/* Path completely resolved? */
     65 	uintptr_t mdp_vnode[MDB_PATH_NELEM];	/* Array of vnode_t addresses */
     66 	char *mdp_name[MDB_PATH_NELEM];		/* Array of name components */
     67 } mdb_path_t;
     68 
     69 static int mdb_autonode2path(uintptr_t, mdb_path_t *);
     70 static int mdb_sprintpath(char *, size_t, mdb_path_t *);
     71 
     72 /*
     73  * Kernel parameters from <sys/param.h> which we keep in-core:
     74  */
     75 unsigned long _mdb_ks_pagesize;
     76 unsigned int _mdb_ks_pageshift;
     77 unsigned long _mdb_ks_pageoffset;
     78 unsigned long long _mdb_ks_pagemask;
     79 unsigned long _mdb_ks_mmu_pagesize;
     80 unsigned int _mdb_ks_mmu_pageshift;
     81 unsigned long _mdb_ks_mmu_pageoffset;
     82 unsigned long _mdb_ks_mmu_pagemask;
     83 uintptr_t _mdb_ks_kernelbase;
     84 uintptr_t _mdb_ks_userlimit;
     85 uintptr_t _mdb_ks_userlimit32;
     86 uintptr_t _mdb_ks_argsbase;
     87 unsigned long _mdb_ks_msg_bsize;
     88 unsigned long _mdb_ks_defaultstksz;
     89 int _mdb_ks_ncpu;
     90 
     91 /*
     92  * In-core copy of DNLC information:
     93  */
     94 #define	MDB_DNLC_HSIZE	1024
     95 #define	MDB_DNLC_HASH(vp)	(((uintptr_t)(vp) >> 3) & (MDB_DNLC_HSIZE - 1))
     96 #define	MDB_DNLC_NCACHE_SZ(ncp) (sizeof (ncache_t) + (ncp)->namlen)
     97 #define	MDB_DNLC_MAX_RETRY 4
     98 
     99 
    100 static ncache_t **dnlc_hash;	/* mdbs hash array of dnlc entries */
    101 
    102 /*
    103  * This will be the location of the vnodeops pointer for "autofs_vnodeops"
    104  * The pointer still needs to be read with mdb_vread() to get the location
    105  * of the vnodeops structure for autofs.
    106  */
    107 static struct vnodeops *autofs_vnops_ptr;
    108 
    109 /*
    110  * STREAMS queue registrations:
    111  */
    112 typedef struct mdb_qinfo {
    113 	const mdb_qops_t *qi_ops;	/* Address of ops vector */
    114 	uintptr_t qi_addr;		/* Address of qinit structure (key) */
    115 	struct mdb_qinfo *qi_next;	/* Next qinfo in list */
    116 } mdb_qinfo_t;
    117 
    118 static mdb_qinfo_t *qi_head;		/* Head of qinfo chain */
    119 
    120 /*
    121  * Device naming callback structure:
    122  */
    123 typedef struct nm_query {
    124 	const char *nm_name;		/* Device driver name [in/out] */
    125 	major_t nm_major;		/* Device major number [in/out] */
    126 	ushort_t nm_found;		/* Did we find a match? [out] */
    127 } nm_query_t;
    128 
    129 /*
    130  * Address-to-modctl callback structure:
    131  */
    132 typedef struct a2m_query {
    133 	uintptr_t a2m_addr;		/* Virtual address [in] */
    134 	uintptr_t a2m_where;		/* Modctl address [out] */
    135 } a2m_query_t;
    136 
    137 /*
    138  * Segment-to-mdb_map callback structure:
    139  */
    140 typedef struct {
    141 	struct seg_ops *asm_segvn_ops;	/* Address of segvn ops [in] */
    142 	void (*asm_callback)(const struct mdb_map *, void *); /* Callb [in] */
    143 	void *asm_cbdata;		/* Callback data [in] */
    144 } asmap_arg_t;
    145 
    146 static void
    147 dnlc_free(void)
    148 {
    149 	ncache_t *ncp, *next;
    150 	int i;
    151 
    152 	if (dnlc_hash == NULL) {
    153 		return;
    154 	}
    155 
    156 	/*
    157 	 * Free up current dnlc entries
    158 	 */
    159 	for (i = 0; i < MDB_DNLC_HSIZE; i++) {
    160 		for (ncp = dnlc_hash[i]; ncp; ncp = next) {
    161 			next = ncp->hash_next;
    162 			mdb_free(ncp, MDB_DNLC_NCACHE_SZ(ncp));
    163 		}
    164 	}
    165 	mdb_free(dnlc_hash, MDB_DNLC_HSIZE * sizeof (ncache_t *));
    166 	dnlc_hash = NULL;
    167 }
    168 
    169 char bad_dnlc[] = "inconsistent dnlc chain: %d, ncache va: %p"
    170 	" - continuing with the rest\n";
    171 
    172 static int
    173 dnlc_load(void)
    174 {
    175 	int i; /* hash index */
    176 	int retry_cnt = 0;
    177 	int skip_bad_chains = 0;
    178 	int nc_hashsz; /* kernel hash array size */
    179 	uintptr_t nc_hash_addr; /* kernel va of ncache hash array */
    180 	uintptr_t head; /* kernel va of head of hash chain */
    181 
    182 	/*
    183 	 * If we've already cached the DNLC and we're looking at a dump,
    184 	 * our cache is good forever, so don't bother re-loading.
    185 	 */
    186 	if (dnlc_hash && mdb_prop_postmortem) {
    187 		return (0);
    188 	}
    189 
    190 	/*
    191 	 * For a core dump, retries wont help.
    192 	 * Just print and skip any bad chains.
    193 	 */
    194 	if (mdb_prop_postmortem) {
    195 		skip_bad_chains = 1;
    196 	}
    197 retry:
    198 	if (retry_cnt++ >= MDB_DNLC_MAX_RETRY) {
    199 		/*
    200 		 * Give up retrying the rapidly changing dnlc.
    201 		 * Just print and skip any bad chains
    202 		 */
    203 		skip_bad_chains = 1;
    204 	}
    205 
    206 	dnlc_free(); /* Free up the mdb hashed dnlc - if any */
    207 
    208 	/*
    209 	 * Although nc_hashsz and the location of nc_hash doesn't currently
    210 	 * change, it may do in the future with a more dynamic dnlc.
    211 	 * So always read these values afresh.
    212 	 */
    213 	if (mdb_readvar(&nc_hashsz, "nc_hashsz") == -1) {
    214 		mdb_warn("failed to read nc_hashsz");
    215 		return (-1);
    216 	}
    217 	if (mdb_readvar(&nc_hash_addr, "nc_hash") == -1) {
    218 		mdb_warn("failed to read nc_hash");
    219 		return (-1);
    220 	}
    221 
    222 	/*
    223 	 * Allocate the mdb dnlc hash array
    224 	 */
    225 	dnlc_hash = mdb_zalloc(MDB_DNLC_HSIZE * sizeof (ncache_t *), UM_SLEEP);
    226 
    227 	/* for each kernel hash chain */
    228 	for (i = 0, head = nc_hash_addr; i < nc_hashsz;
    229 	    i++, head += sizeof (nc_hash_t)) {
    230 		nc_hash_t nch; /* kernel hash chain header */
    231 		ncache_t *ncp; /* name cache pointer */
    232 		int hash; /* mdb hash value */
    233 		uintptr_t nc_va; /* kernel va of next ncache */
    234 		uintptr_t ncprev_va; /* kernel va of previous ncache */
    235 		int khash; /* kernel dnlc hash value */
    236 		uchar_t namelen; /* name length */
    237 		ncache_t nc; /* name cache entry */
    238 		int nc_size; /* size of a name cache entry */
    239 
    240 		/*
    241 		 * We read each element of the nc_hash array individually
    242 		 * just before we process the entries in its chain. This is
    243 		 * because the chain can change so rapidly on a running system.
    244 		 */
    245 		if (mdb_vread(&nch, sizeof (nc_hash_t), head) == -1) {
    246 			mdb_warn("failed to read nc_hash chain header %d", i);
    247 			dnlc_free();
    248 			return (-1);
    249 		}
    250 
    251 		ncprev_va = head;
    252 		nc_va = (uintptr_t)(nch.hash_next);
    253 		/* for each entry in the chain */
    254 		while (nc_va != head) {
    255 			/*
    256 			 * The size of the ncache entries varies
    257 			 * because the name is appended to the structure.
    258 			 * So we read in the structure then re-read
    259 			 * for the structure plus name.
    260 			 */
    261 			if (mdb_vread(&nc, sizeof (ncache_t), nc_va) == -1) {
    262 				if (skip_bad_chains) {
    263 					mdb_warn(bad_dnlc, i, nc_va);
    264 					break;
    265 				}
    266 				goto retry;
    267 			}
    268 			nc_size = MDB_DNLC_NCACHE_SZ(&nc);
    269 			ncp = mdb_alloc(nc_size, UM_SLEEP);
    270 			if (mdb_vread(ncp, nc_size - 1, nc_va) == -1) {
    271 				mdb_free(ncp, nc_size);
    272 				if (skip_bad_chains) {
    273 					mdb_warn(bad_dnlc, i, nc_va);
    274 					break;
    275 				}
    276 				goto retry;
    277 			}
    278 
    279 			/*
    280 			 * Check for chain consistency
    281 			 */
    282 			if ((uintptr_t)ncp->hash_prev != ncprev_va) {
    283 				mdb_free(ncp, nc_size);
    284 				if (skip_bad_chains) {
    285 					mdb_warn(bad_dnlc, i, nc_va);
    286 					break;
    287 				}
    288 				goto retry;
    289 			}
    290 			/*
    291 			 * Terminate the new name with a null.
    292 			 * Note, we allowed space for this null when
    293 			 * allocating space for the entry.
    294 			 */
    295 			ncp->name[ncp->namlen] = '\0';
    296 
    297 			/*
    298 			 * Validate new entry by re-hashing using the
    299 			 * kernel dnlc hash function and comparing the hash
    300 			 */
    301 			DNLCHASH(ncp->name, ncp->dp, khash, namelen);
    302 			if ((namelen != ncp->namlen) ||
    303 			    (khash != ncp->hash)) {
    304 				mdb_free(ncp, nc_size);
    305 				if (skip_bad_chains) {
    306 					mdb_warn(bad_dnlc, i, nc_va);
    307 					break;
    308 				}
    309 				goto retry;
    310 			}
    311 
    312 			/*
    313 			 * Finally put the validated entry into the mdb
    314 			 * hash chains. Reuse the kernel next hash field
    315 			 * for the mdb hash chain pointer.
    316 			 */
    317 			hash = MDB_DNLC_HASH(ncp->vp);
    318 			ncprev_va = nc_va;
    319 			nc_va = (uintptr_t)(ncp->hash_next);
    320 			ncp->hash_next = dnlc_hash[hash];
    321 			dnlc_hash[hash] = ncp;
    322 		}
    323 	}
    324 	return (0);
    325 }
    326 
    327 /*ARGSUSED*/
    328 int
    329 dnlcdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
    330 {
    331 	ncache_t *ent;
    332 	int i;
    333 
    334 	if ((flags & DCMD_ADDRSPEC) || argc != 0)
    335 		return (DCMD_USAGE);
    336 
    337 	if (dnlc_load() == -1)
    338 		return (DCMD_ERR);
    339 
    340 	mdb_printf("%<u>%-?s %-?s %-32s%</u>\n", "VP", "DVP", "NAME");
    341 
    342 	for (i = 0; i < MDB_DNLC_HSIZE; i++) {
    343 		for (ent = dnlc_hash[i]; ent != NULL; ent = ent->hash_next) {
    344 			mdb_printf("%0?p %0?p %s\n",
    345 			    ent->vp, ent->dp, ent->name);
    346 		}
    347 	}
    348 
    349 	return (DCMD_OK);
    350 }
    351 
    352 static int
    353 mdb_sprintpath(char *buf, size_t len, mdb_path_t *path)
    354 {
    355 	char *s = buf;
    356 	int i;
    357 
    358 	if (len < sizeof ("/..."))
    359 		return (-1);
    360 
    361 	if (!path->mdp_complete) {
    362 		(void) strcpy(s, "??");
    363 		s += 2;
    364 
    365 		if (path->mdp_nelem == 0)
    366 			return (-1);
    367 	}
    368 
    369 	if (path->mdp_nelem == 0) {
    370 		(void) strcpy(s, "/");
    371 		return (0);
    372 	}
    373 
    374 	for (i = path->mdp_nelem - 1; i >= 0; i--) {
    375 		/*
    376 		 * Number of bytes left is the distance from where we
    377 		 * are to the end, minus 2 for '/' and '\0'
    378 		 */
    379 		ssize_t left = (ssize_t)(&buf[len] - s) - 2;
    380 
    381 		if (left <= 0)
    382 			break;
    383 
    384 		*s++ = '/';
    385 		(void) strncpy(s, path->mdp_name[i], left);
    386 		s[left - 1] = '\0';
    387 		s += strlen(s);
    388 
    389 		if (left < strlen(path->mdp_name[i]))
    390 			break;
    391 	}
    392 
    393 	if (i >= 0)
    394 		(void) strcpy(&buf[len - 4], "...");
    395 
    396 	return (0);
    397 }
    398 
    399 static int
    400 mdb_autonode2path(uintptr_t addr, mdb_path_t *path)
    401 {
    402 	fninfo_t fni;
    403 	fnnode_t fn;
    404 
    405 	vnode_t vn;
    406 	vfs_t vfs;
    407 	struct vnodeops *autofs_vnops = NULL;
    408 
    409 	/*
    410 	 * "autofs_vnops_ptr" is the address of the pointer to the vnodeops
    411 	 * structure for autofs.  We want to read it each time we access
    412 	 * it since autofs could (in theory) be unloaded and reloaded.
    413 	 */
    414 	if (mdb_vread(&autofs_vnops, sizeof (autofs_vnops),
    415 	    (uintptr_t)autofs_vnops_ptr) == -1)
    416 		return (-1);
    417 
    418 	if (mdb_vread(&vn, sizeof (vn), addr) == -1)
    419 		return (-1);
    420 
    421 	if (autofs_vnops == NULL || vn.v_op != autofs_vnops)
    422 		return (-1);
    423 
    424 	addr = (uintptr_t)vn.v_data;
    425 
    426 	if (mdb_vread(&vfs, sizeof (vfs), (uintptr_t)vn.v_vfsp) == -1 ||
    427 	    mdb_vread(&fni, sizeof (fni), (uintptr_t)vfs.vfs_data) == -1 ||
    428 	    mdb_vread(&vn, sizeof (vn), (uintptr_t)fni.fi_rootvp) == -1)
    429 		return (-1);
    430 
    431 	for (;;) {
    432 		size_t elem = path->mdp_nelem++;
    433 		char elemstr[MAXNAMELEN];
    434 		char *c, *p;
    435 
    436 		if (elem == MDB_PATH_NELEM) {
    437 			path->mdp_nelem--;
    438 			return (-1);
    439 		}
    440 
    441 		if (mdb_vread(&fn, sizeof (fn), addr) != sizeof (fn)) {
    442 			path->mdp_nelem--;
    443 			return (-1);
    444 		}
    445 
    446 		if (mdb_readstr(elemstr, sizeof (elemstr),
    447 		    (uintptr_t)fn.fn_name) <= 0) {
    448 			(void) strcpy(elemstr, "?");
    449 		}
    450 
    451 		c = mdb_alloc(strlen(elemstr) + 1, UM_SLEEP | UM_GC);
    452 		(void) strcpy(c, elemstr);
    453 
    454 		path->mdp_vnode[elem] = (uintptr_t)fn.fn_vnode;
    455 
    456 		if (addr == (uintptr_t)fn.fn_parent) {
    457 			path->mdp_name[elem] = &c[1];
    458 			path->mdp_complete = TRUE;
    459 			break;
    460 		}
    461 
    462 		if ((p = strrchr(c, '/')) != NULL)
    463 			path->mdp_name[elem] = p + 1;
    464 		else
    465 			path->mdp_name[elem] = c;
    466 
    467 		addr = (uintptr_t)fn.fn_parent;
    468 	}
    469 
    470 	return (0);
    471 }
    472 
    473 int
    474 mdb_vnode2path(uintptr_t addr, char *buf, size_t buflen)
    475 {
    476 	uintptr_t rootdir;
    477 	ncache_t *ent;
    478 	vnode_t vp;
    479 	mdb_path_t path;
    480 
    481 	/*
    482 	 * Check to see if we have a cached value for this vnode
    483 	 */
    484 	if (mdb_vread(&vp, sizeof (vp), addr) != -1 &&
    485 	    vp.v_path != NULL &&
    486 	    mdb_readstr(buf, buflen, (uintptr_t)vp.v_path) != -1)
    487 		return (0);
    488 
    489 	if (dnlc_load() == -1)
    490 		return (-1);
    491 
    492 	if (mdb_readvar(&rootdir, "rootdir") == -1) {
    493 		mdb_warn("failed to read 'rootdir'");
    494 		return (-1);
    495 	}
    496 
    497 	bzero(&path, sizeof (mdb_path_t));
    498 again:
    499 	if ((addr == NULL) && (path.mdp_nelem == 0)) {
    500 		/*
    501 		 * 0 elems && complete tells sprintpath to just print "/"
    502 		 */
    503 		path.mdp_complete = TRUE;
    504 		goto out;
    505 	}
    506 
    507 	if (addr == rootdir) {
    508 		path.mdp_complete = TRUE;
    509 		goto out;
    510 	}
    511 
    512 	for (ent = dnlc_hash[MDB_DNLC_HASH(addr)]; ent; ent = ent->hash_next) {
    513 		if ((uintptr_t)ent->vp == addr) {
    514 			if (strcmp(ent->name, "..") == 0 ||
    515 			    strcmp(ent->name, ".") == 0)
    516 				continue;
    517 
    518 			path.mdp_vnode[path.mdp_nelem] = (uintptr_t)ent->vp;
    519 			path.mdp_name[path.mdp_nelem] = ent->name;
    520 			path.mdp_nelem++;
    521 
    522 			if (path.mdp_nelem == MDB_PATH_NELEM) {
    523 				path.mdp_nelem--;
    524 				mdb_warn("path exceeded maximum expected "
    525 				    "elements\n");
    526 				return (-1);
    527 			}
    528 
    529 			addr = (uintptr_t)ent->dp;
    530 			goto again;
    531 		}
    532 	}
    533 
    534 	(void) mdb_autonode2path(addr, &path);
    535 
    536 out:
    537 	return (mdb_sprintpath(buf, buflen, &path));
    538 }
    539 
    540 
    541 uintptr_t
    542 mdb_pid2proc(pid_t pid, proc_t *proc)
    543 {
    544 	int pid_hashsz, hash;
    545 	uintptr_t paddr, pidhash, procdir;
    546 	struct pid pidp;
    547 
    548 	if (mdb_readvar(&pidhash, "pidhash") == -1)
    549 		return (NULL);
    550 
    551 	if (mdb_readvar(&pid_hashsz, "pid_hashsz") == -1)
    552 		return (NULL);
    553 
    554 	if (mdb_readvar(&procdir, "procdir") == -1)
    555 		return (NULL);
    556 
    557 	hash = pid & (pid_hashsz - 1);
    558 
    559 	if (mdb_vread(&paddr, sizeof (paddr),
    560 	    pidhash + (hash * sizeof (paddr))) == -1)
    561 		return (NULL);
    562 
    563 	while (paddr != 0) {
    564 		if (mdb_vread(&pidp, sizeof (pidp), paddr) == -1)
    565 			return (NULL);
    566 
    567 		if (pidp.pid_id == pid) {
    568 			uintptr_t procp;
    569 
    570 			if (mdb_vread(&procp, sizeof (procp), procdir +
    571 			    (pidp.pid_prslot * sizeof (procp))) == -1)
    572 				return (NULL);
    573 
    574 			if (proc != NULL)
    575 				(void) mdb_vread(proc, sizeof (proc_t), procp);
    576 
    577 			return (procp);
    578 		}
    579 		paddr = (uintptr_t)pidp.pid_link;
    580 	}
    581 	return (NULL);
    582 }
    583 
    584 int
    585 mdb_cpu2cpuid(uintptr_t cpup)
    586 {
    587 	cpu_t cpu;
    588 
    589 	if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t))
    590 		return (-1);
    591 
    592 	return (cpu.cpu_id);
    593 }
    594 
    595 int
    596 mdb_cpuset_find(uintptr_t cpusetp)
    597 {
    598 	ulong_t	*cpuset;
    599 	size_t nr_words = BT_BITOUL(NCPU);
    600 	size_t sz = nr_words * sizeof (ulong_t);
    601 	size_t	i;
    602 	int cpu = -1;
    603 
    604 	cpuset = mdb_alloc(sz, UM_SLEEP);
    605 
    606 	if (mdb_vread((void *)cpuset, sz, cpusetp) != sz)
    607 		goto out;
    608 
    609 	for (i = 0; i < nr_words; i++) {
    610 		size_t j;
    611 		ulong_t m;
    612 
    613 		for (j = 0, m = 1; j < BT_NBIPUL; j++, m <<= 1) {
    614 			if (cpuset[i] & m) {
    615 				cpu = i * BT_NBIPUL + j;
    616 				goto out;
    617 			}
    618 		}
    619 	}
    620 
    621 out:
    622 	mdb_free(cpuset, sz);
    623 	return (cpu);
    624 }
    625 
    626 uintptr_t
    627 mdb_vnode2page(uintptr_t vp, uintptr_t offset)
    628 {
    629 	long page_hashsz, ndx;
    630 	uintptr_t page_hash, pp;
    631 
    632 	if (mdb_readvar(&page_hashsz, "page_hashsz") == -1 ||
    633 	    mdb_readvar(&page_hash, "page_hash") == -1)
    634 		return (NULL);
    635 
    636 	ndx = PAGE_HASH_FUNC(vp, offset);
    637 	page_hash += ndx * sizeof (uintptr_t);
    638 
    639 	mdb_vread(&pp, sizeof (pp), page_hash);
    640 
    641 	while (pp != NULL) {
    642 		page_t page;
    643 
    644 		mdb_vread(&page, sizeof (page), pp);
    645 
    646 		if ((uintptr_t)page.p_vnode == vp &&
    647 		    (uintptr_t)page.p_offset == offset)
    648 			return (pp);
    649 
    650 		pp = (uintptr_t)page.p_hash;
    651 	}
    652 
    653 	return (NULL);
    654 }
    655 
    656 char
    657 mdb_vtype2chr(vtype_t type, mode_t mode)
    658 {
    659 	static const char vttab[] = {
    660 		' ',	/* VNON */
    661 		' ',	/* VREG */
    662 		'/',	/* VDIR */
    663 		' ',	/* VBLK */
    664 		' ',	/* VCHR */
    665 		'@',	/* VLNK */
    666 		'|',	/* VFIFO */
    667 		'>',	/* VDOOR */
    668 		' ',	/* VPROC */
    669 		'=',	/* VSOCK */
    670 		' ',	/* VBAD */
    671 	};
    672 
    673 	if (type < 0 || type >= sizeof (vttab) / sizeof (vttab[0]))
    674 		return ('?');
    675 
    676 	if (type == VREG && (mode & 0111) != 0)
    677 		return ('*');
    678 
    679 	return (vttab[type]);
    680 }
    681 
    682 static int
    683 a2m_walk_modctl(uintptr_t addr, const struct modctl *m, a2m_query_t *a2m)
    684 {
    685 	struct module mod;
    686 
    687 	if (m->mod_mp == NULL)
    688 		return (0);
    689 
    690 	if (mdb_vread(&mod, sizeof (mod), (uintptr_t)m->mod_mp) == -1) {
    691 		mdb_warn("couldn't read modctl %p's module", addr);
    692 		return (0);
    693 	}
    694 
    695 	if (a2m->a2m_addr >= (uintptr_t)mod.text &&
    696 	    a2m->a2m_addr < (uintptr_t)mod.text + mod.text_size)
    697 		goto found;
    698 
    699 	if (a2m->a2m_addr >= (uintptr_t)mod.data &&
    700 	    a2m->a2m_addr < (uintptr_t)mod.data + mod.data_size)
    701 		goto found;
    702 
    703 	return (0);
    704 
    705 found:
    706 	a2m->a2m_where = addr;
    707 	return (-1);
    708 }
    709 
    710 uintptr_t
    711 mdb_addr2modctl(uintptr_t addr)
    712 {
    713 	a2m_query_t a2m;
    714 
    715 	a2m.a2m_addr = addr;
    716 	a2m.a2m_where = NULL;
    717 
    718 	(void) mdb_walk("modctl", (mdb_walk_cb_t)a2m_walk_modctl, &a2m);
    719 	return (a2m.a2m_where);
    720 }
    721 
    722 static mdb_qinfo_t *
    723 qi_lookup(uintptr_t qinit_addr)
    724 {
    725 	mdb_qinfo_t *qip;
    726 
    727 	for (qip = qi_head; qip != NULL; qip = qip->qi_next) {
    728 		if (qip->qi_addr == qinit_addr)
    729 			return (qip);
    730 	}
    731 
    732 	return (NULL);
    733 }
    734 
    735 void
    736 mdb_qops_install(const mdb_qops_t *qops, uintptr_t qinit_addr)
    737 {
    738 	mdb_qinfo_t *qip = qi_lookup(qinit_addr);
    739 
    740 	if (qip != NULL) {
    741 		qip->qi_ops = qops;
    742 		return;
    743 	}
    744 
    745 	qip = mdb_alloc(sizeof (mdb_qinfo_t), UM_SLEEP);
    746 
    747 	qip->qi_ops = qops;
    748 	qip->qi_addr = qinit_addr;
    749 	qip->qi_next = qi_head;
    750 
    751 	qi_head = qip;
    752 }
    753 
    754 void
    755 mdb_qops_remove(const mdb_qops_t *qops, uintptr_t qinit_addr)
    756 {
    757 	mdb_qinfo_t *qip, *p = NULL;
    758 
    759 	for (qip = qi_head; qip != NULL; p = qip, qip = qip->qi_next) {
    760 		if (qip->qi_addr == qinit_addr && qip->qi_ops == qops) {
    761 			if (qi_head == qip)
    762 				qi_head = qip->qi_next;
    763 			else
    764 				p->qi_next = qip->qi_next;
    765 			mdb_free(qip, sizeof (mdb_qinfo_t));
    766 			return;
    767 		}
    768 	}
    769 }
    770 
    771 char *
    772 mdb_qname(const queue_t *q, char *buf, size_t nbytes)
    773 {
    774 	struct module_info mi;
    775 	struct qinit qi;
    776 
    777 	if (mdb_vread(&qi, sizeof (qi), (uintptr_t)q->q_qinfo) == -1) {
    778 		mdb_warn("failed to read qinit at %p", q->q_qinfo);
    779 		goto err;
    780 	}
    781 
    782 	if (mdb_vread(&mi, sizeof (mi), (uintptr_t)qi.qi_minfo) == -1) {
    783 		mdb_warn("failed to read module_info at %p", qi.qi_minfo);
    784 		goto err;
    785 	}
    786 
    787 	if (mdb_readstr(buf, nbytes, (uintptr_t)mi.mi_idname) <= 0) {
    788 		mdb_warn("failed to read mi_idname at %p", mi.mi_idname);
    789 		goto err;
    790 	}
    791 
    792 	return (buf);
    793 
    794 err:
    795 	(void) mdb_snprintf(buf, nbytes, "???");
    796 	return (buf);
    797 }
    798 
    799 void
    800 mdb_qinfo(const queue_t *q, char *buf, size_t nbytes)
    801 {
    802 	mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
    803 	buf[0] = '\0';
    804 
    805 	if (qip != NULL)
    806 		qip->qi_ops->q_info(q, buf, nbytes);
    807 }
    808 
    809 uintptr_t
    810 mdb_qrnext(const queue_t *q)
    811 {
    812 	mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
    813 
    814 	if (qip != NULL)
    815 		return (qip->qi_ops->q_rnext(q));
    816 
    817 	return (NULL);
    818 }
    819 
    820 uintptr_t
    821 mdb_qwnext(const queue_t *q)
    822 {
    823 	mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
    824 
    825 	if (qip != NULL)
    826 		return (qip->qi_ops->q_wnext(q));
    827 
    828 	return (NULL);
    829 }
    830 
    831 uintptr_t
    832 mdb_qrnext_default(const queue_t *q)
    833 {
    834 	return ((uintptr_t)q->q_next);
    835 }
    836 
    837 uintptr_t
    838 mdb_qwnext_default(const queue_t *q)
    839 {
    840 	return ((uintptr_t)q->q_next);
    841 }
    842 
    843 /*
    844  * The following three routines borrowed from modsubr.c
    845  */
    846 static int
    847 nm_hash(const char *name)
    848 {
    849 	char c;
    850 	int hash = 0;
    851 
    852 	for (c = *name++; c; c = *name++)
    853 		hash ^= c;
    854 
    855 	return (hash & MOD_BIND_HASHMASK);
    856 }
    857 
    858 static uintptr_t
    859 find_mbind(const char *name, uintptr_t *hashtab)
    860 {
    861 	int hashndx;
    862 	uintptr_t mb;
    863 	struct bind mb_local;
    864 	char node_name[MAXPATHLEN + 1];
    865 
    866 	hashndx = nm_hash(name);
    867 	mb = hashtab[hashndx];
    868 	while (mb) {
    869 		if (mdb_vread(&mb_local, sizeof (mb_local), mb) == -1) {
    870 			mdb_warn("failed to read struct bind at %p", mb);
    871 			return (NULL);
    872 		}
    873 		if (mdb_readstr(node_name, sizeof (node_name),
    874 		    (uintptr_t)mb_local.b_name) == -1) {
    875 			mdb_warn("failed to read node name string at %p",
    876 			    mb_local.b_name);
    877 			return (NULL);
    878 		}
    879 
    880 		if (strcmp(name, node_name) == 0)
    881 			break;
    882 
    883 		mb = (uintptr_t)mb_local.b_next;
    884 	}
    885 	return (mb);
    886 }
    887 
    888 int
    889 mdb_name_to_major(const char *name, major_t *major)
    890 {
    891 	uintptr_t	mbind;
    892 	uintptr_t	mb_hashtab[MOD_BIND_HASHSIZE];
    893 	struct bind 	mbind_local;
    894 
    895 
    896 	if (mdb_readsym(mb_hashtab, sizeof (mb_hashtab), "mb_hashtab") == -1) {
    897 		mdb_warn("failed to read symbol 'mb_hashtab'");
    898 		return (-1);
    899 	}
    900 
    901 	if ((mbind = find_mbind(name, mb_hashtab)) != NULL) {
    902 		if (mdb_vread(&mbind_local, sizeof (mbind_local), mbind) ==
    903 		    -1) {
    904 			mdb_warn("failed to read mbind struct at %p", mbind);
    905 			return (-1);
    906 		}
    907 
    908 		*major = (major_t)mbind_local.b_num;
    909 		return (0);
    910 	}
    911 	return (-1);
    912 }
    913 
    914 const char *
    915 mdb_major_to_name(major_t major)
    916 {
    917 	static char name[MODMAXNAMELEN + 1];
    918 
    919 	uintptr_t devnamesp;
    920 	struct devnames dn;
    921 	uint_t devcnt;
    922 
    923 	if (mdb_readvar(&devcnt, "devcnt") == -1 || major >= devcnt ||
    924 	    mdb_readvar(&devnamesp, "devnamesp") == -1)
    925 		return (NULL);
    926 
    927 	if (mdb_vread(&dn, sizeof (struct devnames), devnamesp +
    928 	    major * sizeof (struct devnames)) != sizeof (struct devnames))
    929 		return (NULL);
    930 
    931 	if (mdb_readstr(name, MODMAXNAMELEN + 1, (uintptr_t)dn.dn_name) == -1)
    932 		return (NULL);
    933 
    934 	return ((const char *)name);
    935 }
    936 
    937 /*
    938  * Return the name of the driver attached to the dip in drivername.
    939  */
    940 int
    941 mdb_devinfo2driver(uintptr_t dip_addr, char *drivername, size_t namebufsize)
    942 {
    943 	struct dev_info	devinfo;
    944 	char bind_name[MAXPATHLEN + 1];
    945 	major_t	major;
    946 	const char *namestr;
    947 
    948 
    949 	if (mdb_vread(&devinfo, sizeof (devinfo), dip_addr) == -1) {
    950 		mdb_warn("failed to read devinfo at %p", dip_addr);
    951 		return (-1);
    952 	}
    953 
    954 	if (mdb_readstr(bind_name, sizeof (bind_name),
    955 	    (uintptr_t)devinfo.devi_binding_name) == -1) {
    956 		mdb_warn("failed to read binding name at %p",
    957 		    devinfo.devi_binding_name);
    958 		return (-1);
    959 	}
    960 
    961 	/*
    962 	 * Many->one relation: various names to one major number
    963 	 */
    964 	if (mdb_name_to_major(bind_name, &major) == -1) {
    965 		mdb_warn("failed to translate bind name to major number\n");
    966 		return (-1);
    967 	}
    968 
    969 	/*
    970 	 * One->one relation: one major number corresponds to one driver
    971 	 */
    972 	if ((namestr = mdb_major_to_name(major)) == NULL) {
    973 		(void) strncpy(drivername, "???", namebufsize);
    974 		return (-1);
    975 	}
    976 
    977 	(void) strncpy(drivername, namestr, namebufsize);
    978 	return (0);
    979 }
    980 
    981 /*
    982  * Find the name of the driver attached to this dip (if any), given:
    983  * - the address of a dip (in core)
    984  * - the NAME of the global pointer to the driver's i_ddi_soft_state struct
    985  * - pointer to a pointer to receive the address
    986  */
    987 int
    988 mdb_devinfo2statep(uintptr_t dip_addr, char *soft_statep_name,
    989     uintptr_t *statep)
    990 {
    991 	struct dev_info	dev_info;
    992 
    993 
    994 	if (mdb_vread(&dev_info, sizeof (dev_info), dip_addr) == -1) {
    995 		mdb_warn("failed to read devinfo at %p", dip_addr);
    996 		return (-1);
    997 	}
    998 
    999 	return (mdb_get_soft_state_byname(soft_statep_name,
   1000 	    dev_info.devi_instance, statep, NULL, 0));
   1001 }
   1002 
   1003 /*
   1004  * Returns a pointer to the top of the soft state struct for the instance
   1005  * specified (in state_addr), given the address of the global soft state
   1006  * pointer and size of the struct.  Also fills in the buffer pointed to by
   1007  * state_buf_p (if non-NULL) with the contents of the state struct.
   1008  */
   1009 int
   1010 mdb_get_soft_state_byaddr(uintptr_t ssaddr, uint_t instance,
   1011     uintptr_t *state_addr, void *state_buf_p, size_t sizeof_state)
   1012 {
   1013 	struct i_ddi_soft_state ss;
   1014 	void *statep;
   1015 
   1016 
   1017 	if (mdb_vread(&ss, sizeof (ss), ssaddr) == -1)
   1018 		return (-1);
   1019 
   1020 	if (instance >= ss.n_items)
   1021 		return (-1);
   1022 
   1023 	if (mdb_vread(&statep, sizeof (statep), (uintptr_t)ss.array +
   1024 	    (sizeof (statep) * instance)) == -1)
   1025 		return (-1);
   1026 
   1027 	if (state_addr != NULL)
   1028 		*state_addr = (uintptr_t)statep;
   1029 
   1030 	if (statep == NULL) {
   1031 		errno = ENOENT;
   1032 		return (-1);
   1033 	}
   1034 
   1035 	if (state_buf_p != NULL) {
   1036 
   1037 		/* Read the state struct into the buffer in local space. */
   1038 		if (mdb_vread(state_buf_p, sizeof_state,
   1039 		    (uintptr_t)statep) == -1)
   1040 			return (-1);
   1041 	}
   1042 
   1043 	return (0);
   1044 }
   1045 
   1046 
   1047 /*
   1048  * Returns a pointer to the top of the soft state struct for the instance
   1049  * specified (in state_addr), given the name of the global soft state pointer
   1050  * and size of the struct.  Also fills in the buffer pointed to by
   1051  * state_buf_p (if non-NULL) with the contents of the state struct.
   1052  */
   1053 int
   1054 mdb_get_soft_state_byname(char *softstatep_name, uint_t instance,
   1055     uintptr_t *state_addr, void *state_buf_p, size_t sizeof_state)
   1056 {
   1057 	uintptr_t ssaddr;
   1058 
   1059 	if (mdb_readvar((void *)&ssaddr, softstatep_name) == -1)
   1060 		return (-1);
   1061 
   1062 	return (mdb_get_soft_state_byaddr(ssaddr, instance, state_addr,
   1063 	    state_buf_p, sizeof_state));
   1064 }
   1065 
   1066 static const mdb_dcmd_t dcmds[] = {
   1067 	{ "dnlc", NULL, "print DNLC contents", dnlcdump },
   1068 	{ NULL }
   1069 };
   1070 
   1071 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds };
   1072 
   1073 /*ARGSUSED*/
   1074 static void
   1075 update_vars(void *arg)
   1076 {
   1077 	GElf_Sym sym;
   1078 
   1079 	if (mdb_lookup_by_name("auto_vnodeops", &sym) == 0)
   1080 		autofs_vnops_ptr = (struct vnodeops *)(uintptr_t)sym.st_value;
   1081 	else
   1082 		autofs_vnops_ptr = NULL;
   1083 
   1084 	(void) mdb_readvar(&_mdb_ks_pagesize, "_pagesize");
   1085 	(void) mdb_readvar(&_mdb_ks_pageshift, "_pageshift");
   1086 	(void) mdb_readvar(&_mdb_ks_pageoffset, "_pageoffset");
   1087 	(void) mdb_readvar(&_mdb_ks_pagemask, "_pagemask");
   1088 	(void) mdb_readvar(&_mdb_ks_mmu_pagesize, "_mmu_pagesize");
   1089 	(void) mdb_readvar(&_mdb_ks_mmu_pageshift, "_mmu_pageshift");
   1090 	(void) mdb_readvar(&_mdb_ks_mmu_pageoffset, "_mmu_pageoffset");
   1091 	(void) mdb_readvar(&_mdb_ks_mmu_pagemask, "_mmu_pagemask");
   1092 	(void) mdb_readvar(&_mdb_ks_kernelbase, "_kernelbase");
   1093 
   1094 	(void) mdb_readvar(&_mdb_ks_userlimit, "_userlimit");
   1095 	(void) mdb_readvar(&_mdb_ks_userlimit32, "_userlimit32");
   1096 	(void) mdb_readvar(&_mdb_ks_argsbase, "_argsbase");
   1097 	(void) mdb_readvar(&_mdb_ks_msg_bsize, "_msg_bsize");
   1098 	(void) mdb_readvar(&_mdb_ks_defaultstksz, "_defaultstksz");
   1099 	(void) mdb_readvar(&_mdb_ks_ncpu, "_ncpu");
   1100 }
   1101 
   1102 const mdb_modinfo_t *
   1103 _mdb_init(void)
   1104 {
   1105 	/*
   1106 	 * When used with mdb, mdb_ks is a separate dmod.  With kmdb, however,
   1107 	 * mdb_ks is compiled into the debugger module.  kmdb cannot
   1108 	 * automatically modunload itself when it exits.  If it restarts after
   1109 	 * debugger fault, static variables may not be initialized to zero.
   1110 	 * They must be manually reinitialized here.
   1111 	 */
   1112 	dnlc_hash = NULL;
   1113 	qi_head = NULL;
   1114 
   1115 	mdb_callback_add(MDB_CALLBACK_STCHG, update_vars, NULL);
   1116 
   1117 	update_vars(NULL);
   1118 
   1119 	return (&modinfo);
   1120 }
   1121 
   1122 void
   1123 _mdb_fini(void)
   1124 {
   1125 	dnlc_free();
   1126 	while (qi_head != NULL) {
   1127 		mdb_qinfo_t *qip = qi_head;
   1128 		qi_head = qip->qi_next;
   1129 		mdb_free(qip, sizeof (mdb_qinfo_t));
   1130 	}
   1131 }
   1132 
   1133 /*
   1134  * Interface between MDB kproc target and mdb_ks.  The kproc target relies
   1135  * on looking up and invoking these functions in mdb_ks so that dependencies
   1136  * on the current kernel implementation are isolated in mdb_ks.
   1137  */
   1138 
   1139 /*
   1140  * Given the address of a proc_t, return the p.p_as pointer; return NULL
   1141  * if we were unable to read a proc structure from the given address.
   1142  */
   1143 uintptr_t
   1144 mdb_kproc_as(uintptr_t proc_addr)
   1145 {
   1146 	proc_t p;
   1147 
   1148 	if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p))
   1149 		return ((uintptr_t)p.p_as);
   1150 
   1151 	return (NULL);
   1152 }
   1153 
   1154 /*
   1155  * Given the address of a proc_t, return the p.p_model value; return
   1156  * PR_MODEL_UNKNOWN if we were unable to read a proc structure or if
   1157  * the model value does not match one of the two known values.
   1158  */
   1159 uint_t
   1160 mdb_kproc_model(uintptr_t proc_addr)
   1161 {
   1162 	proc_t p;
   1163 
   1164 	if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p)) {
   1165 		switch (p.p_model) {
   1166 		case DATAMODEL_ILP32:
   1167 			return (PR_MODEL_ILP32);
   1168 		case DATAMODEL_LP64:
   1169 			return (PR_MODEL_LP64);
   1170 		}
   1171 	}
   1172 
   1173 	return (PR_MODEL_UNKNOWN);
   1174 }
   1175 
   1176 /*
   1177  * Callback function for walking process's segment list.  For each segment,
   1178  * we fill in an mdb_map_t describing its properties, and then invoke
   1179  * the callback function provided by the kproc target.
   1180  */
   1181 static int
   1182 asmap_step(uintptr_t addr, const struct seg *seg, asmap_arg_t *asmp)
   1183 {
   1184 	struct segvn_data svd;
   1185 	mdb_map_t map;
   1186 
   1187 	if (seg->s_ops == asmp->asm_segvn_ops && mdb_vread(&svd,
   1188 	    sizeof (svd), (uintptr_t)seg->s_data) == sizeof (svd)) {
   1189 
   1190 		if (svd.vp != NULL) {
   1191 			if (mdb_vnode2path((uintptr_t)svd.vp, map.map_name,
   1192 			    MDB_TGT_MAPSZ) != 0) {
   1193 				(void) mdb_snprintf(map.map_name,
   1194 				    MDB_TGT_MAPSZ, "[ vnode %p ]", svd.vp);
   1195 			}
   1196 		} else
   1197 			(void) strcpy(map.map_name, "[ anon ]");
   1198 
   1199 	} else {
   1200 		(void) mdb_snprintf(map.map_name, MDB_TGT_MAPSZ,
   1201 		    "[ seg %p ]", addr);
   1202 	}
   1203 
   1204 	map.map_base = (uintptr_t)seg->s_base;
   1205 	map.map_size = seg->s_size;
   1206 	map.map_flags = 0;
   1207 
   1208 	asmp->asm_callback((const struct mdb_map *)&map, asmp->asm_cbdata);
   1209 	return (WALK_NEXT);
   1210 }
   1211 
   1212 /*
   1213  * Given a process address space, walk its segment list using the seg walker,
   1214  * convert the segment data to an mdb_map_t, and pass this information
   1215  * back to the kproc target via the given callback function.
   1216  */
   1217 int
   1218 mdb_kproc_asiter(uintptr_t as,
   1219     void (*func)(const struct mdb_map *, void *), void *p)
   1220 {
   1221 	asmap_arg_t arg;
   1222 	GElf_Sym sym;
   1223 
   1224 	arg.asm_segvn_ops = NULL;
   1225 	arg.asm_callback = func;
   1226 	arg.asm_cbdata = p;
   1227 
   1228 	if (mdb_lookup_by_name("segvn_ops", &sym) == 0)
   1229 		arg.asm_segvn_ops = (struct seg_ops *)(uintptr_t)sym.st_value;
   1230 
   1231 	return (mdb_pwalk("seg", (mdb_walk_cb_t)asmap_step, &arg, as));
   1232 }
   1233 
   1234 /*
   1235  * Copy the auxv array from the given process's u-area into the provided
   1236  * buffer.  If the buffer is NULL, only return the size of the auxv array
   1237  * so the caller knows how much space will be required.
   1238  */
   1239 int
   1240 mdb_kproc_auxv(uintptr_t proc, auxv_t *auxv)
   1241 {
   1242 	if (auxv != NULL) {
   1243 		proc_t p;
   1244 
   1245 		if (mdb_vread(&p, sizeof (p), proc) != sizeof (p))
   1246 			return (-1);
   1247 
   1248 		bcopy(p.p_user.u_auxv, auxv,
   1249 		    sizeof (auxv_t) * __KERN_NAUXV_IMPL);
   1250 	}
   1251 
   1252 	return (__KERN_NAUXV_IMPL);
   1253 }
   1254 
   1255 /*
   1256  * Given a process address, return the PID.
   1257  */
   1258 pid_t
   1259 mdb_kproc_pid(uintptr_t proc_addr)
   1260 {
   1261 	struct pid pid;
   1262 	proc_t p;
   1263 
   1264 	if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p) &&
   1265 	    mdb_vread(&pid, sizeof (pid), (uintptr_t)p.p_pidp) == sizeof (pid))
   1266 		return (pid.pid_id);
   1267 
   1268 	return (-1);
   1269 }
   1270 
   1271 /*
   1272  * Interface between the MDB kvm target and mdb_ks.  The kvm target relies
   1273  * on looking up and invoking these functions in mdb_ks so that dependencies
   1274  * on the current kernel implementation are isolated in mdb_ks.
   1275  */
   1276 
   1277 /*
   1278  * Determine whether or not the thread that panicked the given kernel was a
   1279  * kernel thread (panic_thread->t_procp == &p0).
   1280  */
   1281 void
   1282 mdb_dump_print_content(dumphdr_t *dh, pid_t content)
   1283 {
   1284 	GElf_Sym sym;
   1285 	uintptr_t pt;
   1286 	uintptr_t procp;
   1287 	int expcont = 0;
   1288 	int actcont;
   1289 
   1290 	(void) mdb_readvar(&expcont, "dump_conflags");
   1291 	actcont = dh->dump_flags & DF_CONTENT;
   1292 
   1293 	if (actcont == DF_ALL) {
   1294 		mdb_printf("dump content: all kernel and user pages\n");
   1295 		return;
   1296 	} else if (actcont == DF_CURPROC) {
   1297 		mdb_printf("dump content: kernel pages and pages from "
   1298 		    "PID %d", content);
   1299 		return;
   1300 	}
   1301 
   1302 	mdb_printf("dump content: kernel pages only\n");
   1303 	if (!(expcont & DF_CURPROC))
   1304 		return;
   1305 
   1306 	if (mdb_readvar(&pt, "panic_thread") != sizeof (pt) || pt == NULL)
   1307 		goto kthreadpanic_err;
   1308 
   1309 	if (mdb_vread(&procp, sizeof (procp), pt + OFFSETOF(kthread_t,
   1310 	    t_procp)) == -1 || procp == NULL)
   1311 		goto kthreadpanic_err;
   1312 
   1313 	if (mdb_lookup_by_name("p0", &sym) != 0)
   1314 		goto kthreadpanic_err;
   1315 
   1316 	if (procp == (uintptr_t)sym.st_value) {
   1317 		mdb_printf("  (curproc requested, but a kernel thread "
   1318 		    "panicked)\n");
   1319 	} else {
   1320 		mdb_printf("  (curproc requested, but the process that "
   1321 		    "panicked could not be dumped)\n");
   1322 	}
   1323 
   1324 	return;
   1325 
   1326 kthreadpanic_err:
   1327 	mdb_printf("  (curproc requested, but the process that panicked could "
   1328 	    "not be found)\n");
   1329 }
   1330 
   1331 /*
   1332  * Determine the process that was saved in a `curproc' dump.  This process will
   1333  * be recorded as the first element in dump_pids[].
   1334  */
   1335 int
   1336 mdb_dump_find_curproc(void)
   1337 {
   1338 	uintptr_t pidp;
   1339 	pid_t pid = -1;
   1340 
   1341 	if (mdb_readvar(&pidp, "dump_pids") == sizeof (pidp) &&
   1342 	    mdb_vread(&pid, sizeof (pid), pidp) == sizeof (pid) &&
   1343 	    pid > 0)
   1344 		return (pid);
   1345 	else
   1346 		return (-1);
   1347 }
   1348 
   1349 
   1350 /*
   1351  * Following three funcs extracted from sunddi.c
   1352  */
   1353 
   1354 /*
   1355  * Return core address of root node of devinfo tree
   1356  */
   1357 static uintptr_t
   1358 mdb_ddi_root_node(void)
   1359 {
   1360 	uintptr_t	top_devinfo_addr;
   1361 
   1362 	/* return (top_devinfo);   */
   1363 	if (mdb_readvar(&top_devinfo_addr, "top_devinfo") == -1) {
   1364 		mdb_warn("failed to read top_devinfo");
   1365 		return (NULL);
   1366 	}
   1367 	return (top_devinfo_addr);
   1368 }
   1369 
   1370 /*
   1371  * Return the name of the devinfo node pointed at by 'dip_addr' in the buffer
   1372  * pointed at by 'name.'
   1373  *
   1374  * - dip_addr is a pointer to a dev_info struct in core.
   1375  */
   1376 static char *
   1377 mdb_ddi_deviname(uintptr_t dip_addr, char *name, size_t name_size)
   1378 {
   1379 	uintptr_t addrname;
   1380 	ssize_t	length;
   1381 	char *local_namep = name;
   1382 	size_t local_name_size = name_size;
   1383 	struct dev_info	local_dip;
   1384 
   1385 
   1386 	if (dip_addr == mdb_ddi_root_node()) {
   1387 		if (name_size < 1) {
   1388 			mdb_warn("failed to get node name: buf too small\n");
   1389 			return (NULL);
   1390 		}
   1391 
   1392 		*name = '\0';
   1393 		return (name);
   1394 	}
   1395 
   1396 	if (name_size < 2) {
   1397 		mdb_warn("failed to get node name: buf too small\n");
   1398 		return (NULL);
   1399 	}
   1400 
   1401 	local_namep = name;
   1402 	*local_namep++ = '/';
   1403 	*local_namep = '\0';
   1404 	local_name_size--;
   1405 
   1406 	if (mdb_vread(&local_dip, sizeof (struct dev_info), dip_addr) == -1) {
   1407 		mdb_warn("failed to read devinfo struct");
   1408 	}
   1409 
   1410 	length = mdb_readstr(local_namep, local_name_size,
   1411 	    (uintptr_t)local_dip.devi_node_name);
   1412 	if (length == -1) {
   1413 		mdb_warn("failed to read node name");
   1414 		return (NULL);
   1415 	}
   1416 	local_namep += length;
   1417 	local_name_size -= length;
   1418 	addrname = (uintptr_t)local_dip.devi_addr;
   1419 
   1420 	if (addrname != NULL) {
   1421 
   1422 		if (local_name_size < 2) {
   1423 			mdb_warn("not enough room for node address string");
   1424 			return (name);
   1425 		}
   1426 		*local_namep++ = '@';
   1427 		*local_namep = '\0';
   1428 		local_name_size--;
   1429 
   1430 		length = mdb_readstr(local_namep, local_name_size, addrname);
   1431 		if (length == -1) {
   1432 			mdb_warn("failed to read name");
   1433 			return (NULL);
   1434 		}
   1435 	}
   1436 
   1437 	return (name);
   1438 }
   1439 
   1440 /*
   1441  * Generate the full path under the /devices dir to the device entry.
   1442  *
   1443  * dip is a pointer to a devinfo struct in core (not in local memory).
   1444  */
   1445 char *
   1446 mdb_ddi_pathname(uintptr_t dip_addr, char *path, size_t pathlen)
   1447 {
   1448 	struct dev_info local_dip;
   1449 	uintptr_t	parent_dip;
   1450 	char		*bp;
   1451 	size_t		buf_left;
   1452 
   1453 
   1454 	if (dip_addr == mdb_ddi_root_node()) {
   1455 		*path = '\0';
   1456 		return (path);
   1457 	}
   1458 
   1459 
   1460 	if (mdb_vread(&local_dip, sizeof (struct dev_info), dip_addr) == -1) {
   1461 		mdb_warn("failed to read devinfo struct");
   1462 	}
   1463 
   1464 	parent_dip = (uintptr_t)local_dip.devi_parent;
   1465 	(void) mdb_ddi_pathname(parent_dip, path, pathlen);
   1466 
   1467 	bp = path + strlen(path);
   1468 	buf_left = pathlen - strlen(path);
   1469 	(void) mdb_ddi_deviname(dip_addr, bp, buf_left);
   1470 	return (path);
   1471 }
   1472 
   1473 
   1474 /*
   1475  * Read in the string value of a refstr, which is appended to the end of
   1476  * the structure.
   1477  */
   1478 ssize_t
   1479 mdb_read_refstr(uintptr_t refstr_addr, char *str, size_t nbytes)
   1480 {
   1481 	struct refstr *r = (struct refstr *)refstr_addr;
   1482 
   1483 	return (mdb_readstr(str, nbytes, (uintptr_t)r->rs_string));
   1484 }
   1485 
   1486 /*
   1487  * Chase an mblk list by b_next and return the length.
   1488  */
   1489 int
   1490 mdb_mblk_count(const mblk_t *mb)
   1491 {
   1492 	int count;
   1493 	mblk_t mblk;
   1494 
   1495 	if (mb == NULL)
   1496 		return (0);
   1497 
   1498 	count = 1;
   1499 	while (mb->b_next != NULL) {
   1500 		count++;
   1501 		if (mdb_vread(&mblk, sizeof (mblk), (uintptr_t)mb->b_next) ==
   1502 		    -1)
   1503 			break;
   1504 		mb = &mblk;
   1505 	}
   1506 	return (count);
   1507 }
   1508 
   1509 /*
   1510  * Write the given MAC address as a printable string in the usual colon-
   1511  * separated format.  Assumes that buflen is at least 2.
   1512  */
   1513 void
   1514 mdb_mac_addr(const uint8_t *addr, size_t alen, char *buf, size_t buflen)
   1515 {
   1516 	int slen;
   1517 
   1518 	if (alen == 0 || buflen < 4) {
   1519 		(void) strcpy(buf, "?");
   1520 		return;
   1521 	}
   1522 	for (;;) {
   1523 		/*
   1524 		 * If there are more MAC address bytes available, but we won't
   1525 		 * have any room to print them, then add "..." to the string
   1526 		 * instead.  See below for the 'magic number' explanation.
   1527 		 */
   1528 		if ((alen == 2 && buflen < 6) || (alen > 2 && buflen < 7)) {
   1529 			(void) strcpy(buf, "...");
   1530 			break;
   1531 		}
   1532 		slen = mdb_snprintf(buf, buflen, "%02x", *addr++);
   1533 		buf += slen;
   1534 		if (--alen == 0)
   1535 			break;
   1536 		*buf++ = ':';
   1537 		buflen -= slen + 1;
   1538 		/*
   1539 		 * At this point, based on the first 'if' statement above,
   1540 		 * either alen == 1 and buflen >= 3, or alen > 1 and
   1541 		 * buflen >= 4.  The first case leaves room for the final "xx"
   1542 		 * number and trailing NUL byte.  The second leaves room for at
   1543 		 * least "...".  Thus the apparently 'magic' numbers chosen for
   1544 		 * that statement.
   1545 		 */
   1546 	}
   1547 }
   1548 
   1549 /*
   1550  * Produce a string that represents a DLPI primitive, or NULL if no such string
   1551  * is possible.
   1552  */
   1553 const char *
   1554 mdb_dlpi_prim(int prim)
   1555 {
   1556 	switch (prim) {
   1557 	case DL_INFO_REQ:	return ("DL_INFO_REQ");
   1558 	case DL_INFO_ACK:	return ("DL_INFO_ACK");
   1559 	case DL_ATTACH_REQ:	return ("DL_ATTACH_REQ");
   1560 	case DL_DETACH_REQ:	return ("DL_DETACH_REQ");
   1561 	case DL_BIND_REQ:	return ("DL_BIND_REQ");
   1562 	case DL_BIND_ACK:	return ("DL_BIND_ACK");
   1563 	case DL_UNBIND_REQ:	return ("DL_UNBIND_REQ");
   1564 	case DL_OK_ACK:		return ("DL_OK_ACK");
   1565 	case DL_ERROR_ACK:	return ("DL_ERROR_ACK");
   1566 	case DL_ENABMULTI_REQ:	return ("DL_ENABMULTI_REQ");
   1567 	case DL_DISABMULTI_REQ:	return ("DL_DISABMULTI_REQ");
   1568 	case DL_PROMISCON_REQ:	return ("DL_PROMISCON_REQ");
   1569 	case DL_PROMISCOFF_REQ:	return ("DL_PROMISCOFF_REQ");
   1570 	case DL_UNITDATA_REQ:	return ("DL_UNITDATA_REQ");
   1571 	case DL_UNITDATA_IND:	return ("DL_UNITDATA_IND");
   1572 	case DL_UDERROR_IND:	return ("DL_UDERROR_IND");
   1573 	case DL_PHYS_ADDR_REQ:	return ("DL_PHYS_ADDR_REQ");
   1574 	case DL_PHYS_ADDR_ACK:	return ("DL_PHYS_ADDR_ACK");
   1575 	case DL_SET_PHYS_ADDR_REQ:	return ("DL_SET_PHYS_ADDR_REQ");
   1576 	case DL_NOTIFY_REQ:	return ("DL_NOTIFY_REQ");
   1577 	case DL_NOTIFY_ACK:	return ("DL_NOTIFY_ACK");
   1578 	case DL_NOTIFY_IND:	return ("DL_NOTIFY_IND");
   1579 	case DL_NOTIFY_CONF:	return ("DL_NOTIFY_CONF");
   1580 	case DL_CAPABILITY_REQ:	return ("DL_CAPABILITY_REQ");
   1581 	case DL_CAPABILITY_ACK:	return ("DL_CAPABILITY_ACK");
   1582 	case DL_CONTROL_REQ:	return ("DL_CONTROL_REQ");
   1583 	case DL_CONTROL_ACK:	return ("DL_CONTROL_ACK");
   1584 	case DL_PASSIVE_REQ:	return ("DL_PASSIVE_REQ");
   1585 	default:		return (NULL);
   1586 	}
   1587 }
   1588