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