xref: /illumos-gate/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c (revision 5d460eafffba936e81c4dd5ebe0f59b238f09121)
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