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