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