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