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