void _mdb_fini(void) { GElf_Sym sym; if (mdb_lookup_by_obj("ptm", "ptmwint", &sym) == 0) mdb_qops_remove(&ptm_qops, (uintptr_t)sym.st_value); if (mdb_lookup_by_obj("pts", "ptswint", &sym) == 0) mdb_qops_remove(&pts_qops, (uintptr_t)sym.st_value); }
const mdb_modinfo_t * _mdb_init(void) { GElf_Sym sym; if (mdb_lookup_by_obj("ptm", "ptmwint", &sym) == 0) mdb_qops_install(&ptm_qops, (uintptr_t)sym.st_value); if (mdb_lookup_by_obj("pts", "ptswint", &sym) == 0) mdb_qops_install(&pts_qops, (uintptr_t)sym.st_value); return (&modinfo); }
int sonode_walk_init(mdb_walk_state_t *wsp) { if (wsp->walk_addr == 0) { GElf_Sym sym; struct socklist *slp; if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) { mdb_warn("failed to lookup sockfs`socklist"); return (WALK_ERR); } slp = (struct socklist *)(uintptr_t)sym.st_value; if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), (uintptr_t)&slp->sl_list) == -1) { mdb_warn("failed to read address of initial sonode " "at %p", &slp->sl_list); return (WALK_ERR); } } wsp->walk_data = mdb_alloc(sizeof (struct sotpi_sonode), UM_SLEEP); return (WALK_NEXT); }
int uutil_listpool_walk_init(mdb_walk_state_t *wsp) { uu_list_pool_t null_lpool; uutil_listpool_walk_t *ulpw; GElf_Sym sym; bzero(&null_lpool, sizeof (uu_list_pool_t)); if (mdb_lookup_by_obj("libuutil.so.1", "uu_null_lpool", &sym) == -1) { mdb_warn("failed to find 'uu_null_lpool'\n"); return (WALK_ERR); } if (mdb_vread(&null_lpool, sym.st_size, (uintptr_t)sym.st_value) == -1) { mdb_warn("failed to read data from 'uu_null_lpool' address\n"); return (WALK_ERR); } ulpw = mdb_alloc(sizeof (uutil_listpool_walk_t), UM_SLEEP); ulpw->ulpw_final = (uintptr_t)null_lpool.ulp_prev; ulpw->ulpw_current = (uintptr_t)null_lpool.ulp_next; wsp->walk_data = ulpw; return (WALK_NEXT); }
static int xhci_mdb_walk_xhci_init(mdb_walk_state_t *wsp) { GElf_Sym sym; uintptr_t addr; if (wsp->walk_addr != 0) { mdb_warn("::walk xhci only supports global walks\n"); return (WALK_ERR); } if (mdb_lookup_by_obj("xhci", "xhci_soft_state", &sym) != 0) { mdb_warn("failed to find xhci_soft_state symbol"); return (WALK_ERR); } if (mdb_vread(&addr, sizeof (addr), sym.st_value) != sizeof (addr)) { mdb_warn("failed to read xhci_soft_state at %p", addr); return (WALK_ERR); } wsp->walk_addr = addr; if (mdb_layered_walk("softstate", wsp) != 0) { mdb_warn("failed to walk softstate"); return (WALK_ERR); } return (WALK_NEXT); }
/* * To further confuse the issue, this dmod can run against either * libumem.so.1 *or* the libstandumem.so linked into kmdb(1M). To figure * out which one we are working against, we look up "umem_alloc" in both * libumem.so and the executable. * * A further wrinkle is that libumem.so may not yet be loaded into the * process' address space. That can lead to either the lookup failing, or * being unable to read from the data segment. We treat either case as * an error. */ int umem_set_standalone(void) { GElf_Sym sym; int ready; if (mdb_lookup_by_obj(UMEM_OBJNAME, "umem_alloc", &sym) == 0) umem_is_standalone = 0; else if (mdb_lookup_by_obj(MDB_OBJ_EXEC, "umem_alloc", &sym) == 0) umem_is_standalone = 1; else return (-1); /* * now that we know where things should be, make sure we can actually * read things out. */ if (umem_readvar(&ready, "umem_ready") == -1) return (-1); return (0); }
/* * Get the address of the unique uberdata_t structure. */ static uintptr_t uberdata_addr(void) { uintptr_t uaddr; uintptr_t addr; GElf_Sym sym; if (mdb_lookup_by_obj("libc.so.1", "_tdb_bootstrap", &sym) != 0) { mdb_warn("cannot find libc.so.1`_tdb_bootstrap"); return (NULL); } if (mdb_vread(&addr, sizeof (addr), sym.st_value) == sizeof (addr) && addr != NULL && mdb_vread(&uaddr, sizeof (uaddr), addr) == sizeof (uaddr) && uaddr != NULL) { return (uaddr); } if (mdb_lookup_by_obj("libc.so.1", "_uberdata", &sym) != 0) { mdb_warn("cannot find libc.so.1`_uberdata"); return (NULL); } return ((uintptr_t)sym.st_value); }
int mdb_lookup_by_name(const char *name, GElf_Sym *sym) { return (mdb_lookup_by_obj(MDB_TGT_OBJ_EXEC, name, sym)); }
static int dladm_show_bridge(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { show_bridge_args_t *args; GElf_Sym sym; int i; args = mdb_zalloc(sizeof (*args), UM_SLEEP); i = mdb_getopts(argc, argv, 'l', MDB_OPT_SETBITS, 1, &args->opt_l, 'f', MDB_OPT_SETBITS, 1, &args->opt_f, 't', MDB_OPT_SETBITS, 1, &args->opt_t, NULL); argc -= i; argv += i; if (argc > 1 || (argc == 1 && argv[0].a_type != MDB_TYPE_STRING)) { mdb_free(args, sizeof (*args)); return (DCMD_USAGE); } if (argc == 1) args->name = argv[0].a_un.a_str; if ((args->lbolt = mdb_get_lbolt()) == -1) { mdb_warn("failed to read lbolt"); goto err; } if (flags & DCMD_ADDRSPEC) { if (args->name != NULL) { mdb_printf("bridge name and address are mutually " "exclusive\n"); goto err; } if (!args->opt_l && !args->opt_f && !args->opt_t) mdb_printf("%-?s %-7s %-16s %-7s %-7s\n", "ADDR", "PROTECT", "NAME", "NLINKS", "NFWD"); if (do_show_bridge(addr, NULL, args) != WALK_NEXT) goto err; mdb_free(args, sizeof (*args)); return (DCMD_OK); } else { if ((args->opt_l || args->opt_f || args->opt_t) && args->name == NULL) { mdb_printf("need bridge name or address with -[lft]\n"); goto err; } if (mdb_lookup_by_obj("bridge", "inst_list", &sym) == -1) { mdb_warn("failed to find 'bridge`inst_list'"); goto err; } if (!args->opt_l && !args->opt_f && !args->opt_t) mdb_printf("%-?s %-7s %-16s %-7s %-7s %-7s %s\n", "ADDR", "PROTECT", "NAME", "NLINKS", "NFWD", "NNICKS", "NICK"); if (mdb_pwalk("list", do_show_bridge, args, (uintptr_t)sym.st_value) != DCMD_OK) goto err; if (!args->found && args->name != NULL) { mdb_printf("bridge instance %s not found\n", args->name); goto err; } mdb_free(args, sizeof (*args)); return (DCMD_OK); } err: mdb_free(args, sizeof (*args)); return (DCMD_ERR); }
/* ARGSUSED */ int memstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { pgcnt_t total_pages, physmem; ulong_t freemem; memstat_t stats; GElf_Sym sym; vn_htable_t ht; struct vnode *kvps; uintptr_t vn_size = 0; #if defined(__i386) || defined(__amd64) bln_stats_t bln_stats; ssize_t bln_size; #endif bzero(&stats, sizeof (memstat_t)); /* * -s size, is an internal option. It specifies the size of vn_htable. * Hash table size is set in the following order: * If user has specified the size that is larger than VN_LARGE: try it, * but if malloc failed default to VN_SMALL. Otherwise try VN_LARGE, if * failed to allocate default to VN_SMALL. * For a better efficiency of hash table it is highly recommended to * set size to a prime number. */ if ((flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv, 's', MDB_OPT_UINTPTR, &vn_size, NULL) != argc) return (DCMD_USAGE); /* Initialize vnode hash list and queue */ vn_htable_init(&ht, vn_size); stats.ms_vn_htable = &ht; /* Total physical memory */ if (mdb_readvar(&total_pages, "total_pages") == -1) { mdb_warn("unable to read total_pages"); return (DCMD_ERR); } /* Artificially limited memory */ if (mdb_readvar(&physmem, "physmem") == -1) { mdb_warn("unable to read physmem"); return (DCMD_ERR); } /* read kernel vnode array pointer */ if (mdb_lookup_by_obj(MDB_OBJ_EXEC, "kvps", (GElf_Sym *)&sym) == -1) { mdb_warn("unable to read kvps"); return (DCMD_ERR); } kvps = (struct vnode *)(uintptr_t)sym.st_value; stats.ms_kvp = &kvps[KV_KVP]; /* * Read the zio vnode pointer. */ stats.ms_zvp = &kvps[KV_ZVP]; /* * If physmem != total_pages, then the administrator has limited the * number of pages available in the system. Excluded pages are * associated with the unused pages vnode. Read this vnode so the * pages can be excluded in the page accounting. */ if (mdb_lookup_by_obj(MDB_OBJ_EXEC, "unused_pages_vp", (GElf_Sym *)&sym) == -1) { mdb_warn("unable to read unused_pages_vp"); return (DCMD_ERR); } stats.ms_unused_vp = (struct vnode *)(uintptr_t)sym.st_value; /* walk all pages, collect statistics */ if (mdb_walk("allpages", (mdb_walk_cb_t)memstat_callback, &stats) == -1) { mdb_warn("can't walk memseg"); return (DCMD_ERR); } #define MS_PCT_TOTAL(x) ((ulong_t)((((5 * total_pages) + ((x) * 1000ull))) / \ ((physmem) * 10))) mdb_printf("Page Summary Pages MB" " %%Tot\n"); mdb_printf("------------ ---------------- ----------------" " ----\n"); mdb_printf("Kernel %16llu %16llu %3lu%%\n", stats.ms_kmem, (uint64_t)stats.ms_kmem * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(stats.ms_kmem)); if (stats.ms_zfs_data != 0) mdb_printf("ZFS File Data %16llu %16llu %3lu%%\n", stats.ms_zfs_data, (uint64_t)stats.ms_zfs_data * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(stats.ms_zfs_data)); mdb_printf("Anon %16llu %16llu %3lu%%\n", stats.ms_anon, (uint64_t)stats.ms_anon * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(stats.ms_anon)); mdb_printf("Exec and libs %16llu %16llu %3lu%%\n", stats.ms_exec, (uint64_t)stats.ms_exec * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(stats.ms_exec)); mdb_printf("Page cache %16llu %16llu %3lu%%\n", stats.ms_vnode, (uint64_t)stats.ms_vnode * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(stats.ms_vnode)); mdb_printf("Free (cachelist) %16llu %16llu %3lu%%\n", stats.ms_cachelist, (uint64_t)stats.ms_cachelist * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(stats.ms_cachelist)); /* * occasionally, we double count pages above. To avoid printing * absurdly large values for freemem, we clamp it at zero. */ if (physmem > stats.ms_total) freemem = physmem - stats.ms_total; else freemem = 0; #if defined(__i386) || defined(__amd64) /* Are we running under Xen? If so, get balloon memory usage. */ if ((bln_size = mdb_readvar(&bln_stats, "bln_stats")) != -1) { if (freemem > bln_stats.bln_hv_pages) freemem -= bln_stats.bln_hv_pages; else freemem = 0; } #endif mdb_printf("Free (freelist) %16lu %16llu %3lu%%\n", freemem, (uint64_t)freemem * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(freemem)); #if defined(__i386) || defined(__amd64) if (bln_size != -1) { mdb_printf("Balloon %16lu %16llu %3lu%%\n", bln_stats.bln_hv_pages, (uint64_t)bln_stats.bln_hv_pages * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(bln_stats.bln_hv_pages)); } #endif mdb_printf("\nTotal %16lu %16lu\n", physmem, (uint64_t)physmem * PAGESIZE / (1024 * 1024)); if (physmem != total_pages) { mdb_printf("Physical %16lu %16lu\n", total_pages, (uint64_t)total_pages * PAGESIZE / (1024 * 1024)); } #undef MS_PCT_TOTAL return (DCMD_OK); }
ssize_t umem_lookup_by_name(const char *name, GElf_Sym *sym) { return (mdb_lookup_by_obj((umem_is_standalone ? MDB_OBJ_EXEC : UMEM_OBJNAME), name, sym)); }