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