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