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