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