int rctl_dict_walk_init(mdb_walk_state_t *wsp) { uintptr_t ptr; int nlists; GElf_Sym sym; rctl_dict_entry_t **dicts; dict_walk_data_t *dwd; if (mdb_lookup_by_name("rctl_lists", &sym) == -1) { mdb_warn("failed to find 'rctl_lists'\n"); return (WALK_ERR); } nlists = sym.st_size / sizeof (rctl_dict_entry_t *); ptr = (uintptr_t)sym.st_value; dicts = mdb_alloc(nlists * sizeof (rctl_dict_entry_t *), UM_SLEEP); mdb_vread(dicts, sym.st_size, ptr); dwd = mdb_alloc(sizeof (dict_walk_data_t), UM_SLEEP); dwd->num_dicts = nlists; dwd->num_cur = 0; dwd->curdict = dicts; wsp->walk_addr = 0; wsp->walk_data = dwd; return (WALK_NEXT); }
/* * Initialize a walk for NCA node LRUs; the type of LRU to walk should * be specified through `wsp->walk_arg'. If no starting location for * the walk is given, `wsp->walk_addr' is set to the head of the * appropriate LRU. */ static int nca_node_lru_walk_init(mdb_walk_state_t *wsp) { GElf_Sym sym; lru_t lru; if (wsp->walk_addr != 0) return (WALK_NEXT); /* * We do this instead of mdb_readvar() so that we catch changes * in the size of the lru_t structure. */ if (mdb_lookup_by_name("nca_lru", &sym) == -1) { mdb_warn("cannot lookup symbol nca_lru"); return (WALK_ERR); } if (sym.st_size != sizeof (lru)) { mdb_warn("nca_lru object size mismatch\n"); return (WALK_ERR); } if (mdb_vread(&lru, sym.st_size, (uintptr_t)sym.st_value) == -1) { mdb_warn("cannot read nca_lru at %p", sym.st_value); return (WALK_ERR); } if (wsp->walk_arg == NCA_WALK_PLRU) wsp->walk_addr = (uintptr_t)lru.phead; else wsp->walk_addr = (uintptr_t)lru.vhead; return (WALK_NEXT); }
/*ARGSUSED*/ static int scalehrtime_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint32_t nsec_scale; hrtime_t tsc = addr, hrt; unsigned int *tscp = (unsigned int *)&tsc; uintptr_t scalehrtimef; uint64_t scale; GElf_Sym sym; if (!(flags & DCMD_ADDRSPEC)) { if (argc != 1) return (DCMD_USAGE); switch (argv[0].a_type) { case MDB_TYPE_STRING: tsc = mdb_strtoull(argv[0].a_un.a_str); break; case MDB_TYPE_IMMEDIATE: tsc = argv[0].a_un.a_val; break; default: return (DCMD_USAGE); } } if (mdb_readsym(&scalehrtimef, sizeof (scalehrtimef), "scalehrtimef") == -1) { mdb_warn("couldn't read 'scalehrtimef'"); return (DCMD_ERR); } if (mdb_lookup_by_name("tsc_scalehrtime", &sym) == -1) { mdb_warn("couldn't find 'tsc_scalehrtime'"); return (DCMD_ERR); } if (sym.st_value != scalehrtimef) { mdb_warn("::scalehrtime requires that scalehrtimef " "be set to tsc_scalehrtime\n"); return (DCMD_ERR); } if (mdb_readsym(&nsec_scale, sizeof (nsec_scale), "nsec_scale") == -1) { mdb_warn("couldn't read 'nsec_scale'"); return (DCMD_ERR); } scale = (uint64_t)nsec_scale; hrt = ((uint64_t)tscp[1] * scale) << NSEC_SHIFT; hrt += ((uint64_t)tscp[0] * scale) >> (32 - NSEC_SHIFT); mdb_printf("0x%llx\n", hrt); return (DCMD_OK); }
/*ARGSUSED*/ static int x86_featureset_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { void *fset; GElf_Sym sym; uintptr_t nptr; char name[128]; int ii; size_t sz = sizeof (uchar_t) * BT_SIZEOFMAP(NUM_X86_FEATURES); if (argc != 0) return (DCMD_USAGE); if (mdb_lookup_by_name("x86_feature_names", &sym) == -1) { mdb_warn("couldn't find x86_feature_names"); return (DCMD_ERR); } fset = mdb_zalloc(sz, UM_NOSLEEP); if (fset == NULL) { mdb_warn("failed to allocate memory for x86_featureset"); return (DCMD_ERR); } if (mdb_readvar(fset, "x86_featureset") != sz) { mdb_warn("failed to read x86_featureset"); mdb_free(fset, sz); return (DCMD_ERR); } for (ii = 0; ii < NUM_X86_FEATURES; ii++) { if (!BT_TEST((ulong_t *)fset, ii)) continue; if (mdb_vread(&nptr, sizeof (char *), sym.st_value + sizeof (void *) * ii) != sizeof (char *)) { mdb_warn("failed to read feature array %d", ii); mdb_free(fset, sz); return (DCMD_ERR); } if (mdb_readstr(name, sizeof (name), nptr) == -1) { mdb_warn("failed to read feature %d", ii); mdb_free(fset, sz); return (DCMD_ERR); } mdb_printf("%s\n", name); } mdb_free(fset, sz); return (DCMD_OK); }
const mdb_modinfo_t * _mdb_init(void) { GElf_Sym sym; if (mdb_lookup_by_name("ipp_action_byid", &sym) == -1) { mdb_warn("failed to lookup 'ipp_action_byid'"); return (NULL); } ipp_action_byid = (uintptr_t)sym.st_value; if (mdb_lookup_by_name("ipp_mod_byid", &sym) == -1) { mdb_warn("failed to lookup 'ipp_mod_byid'"); return (NULL); } ipp_mod_byid = (uintptr_t)sym.st_value; return (&ipp_modinfo); }
static int ttrace_interrupt(trap_trace_rec_t *rec) { GElf_Sym sym; uintptr_t addr; struct av_head hd; struct autovec av; switch (rec->ttr_regs.r_trapno) { case T_SOFTINT: mdb_printf("%-3s %-*s", "-", TT_HDLR_WIDTH, "(fakesoftint)"); return (0); default: break; } mdb_printf("%-3x ", rec->ttr_vector); if (mdb_lookup_by_name("autovect", &sym) == -1) { mdb_warn("\ncouldn't find 'autovect'"); return (-1); } addr = (uintptr_t)sym.st_value + rec->ttr_vector * sizeof (struct av_head); if (addr >= (uintptr_t)sym.st_value + sym.st_size) { mdb_warn("\nav_head for vec %x is corrupt\n", rec->ttr_vector); return (-1); } if (mdb_vread(&hd, sizeof (hd), addr) == -1) { mdb_warn("\ncouldn't read av_head for vec %x", rec->ttr_vector); return (-1); } if (hd.avh_link == NULL) { if (rec->ttr_ipl == XC_CPUPOKE_PIL) mdb_printf("%-*s", TT_HDLR_WIDTH, "(cpupoke)"); else mdb_printf("%-*s", TT_HDLR_WIDTH, "(spurious)"); } else { if (mdb_vread(&av, sizeof (av), (uintptr_t)hd.avh_link) == -1) { mdb_warn("couldn't read autovec at %p", (uintptr_t)hd.avh_link); } mdb_printf("%-*a", TT_HDLR_WIDTH, av.av_vector); } return (0); }
const mdb_modinfo_t * _mdb_init(void) { GElf_Sym sym; if (mdb_lookup_by_name("gld_intr", &sym) != -1) if (GELF_ST_TYPE(sym.st_info) == STT_FUNC) gld_intr_addr = (uintptr_t)sym.st_value; if (mdb_readvar(&apic_pir_vect, "apic_pir_vect") == -1) { apic_pir_vect = -1; } return (&modinfo); }
int cyctrace_walk_init(mdb_walk_state_t *wsp) { cyc_cpu_t *cpu; int i; cpu = mdb_zalloc(sizeof (cyc_cpu_t), UM_SLEEP); if (wsp->walk_addr == NULL) { /* * If an address isn't provided, we'll use the passive buffer. */ GElf_Sym sym; cyc_tracebuf_t *tr = &cpu->cyp_trace[0]; uintptr_t addr; if (mdb_lookup_by_name("cyc_ptrace", &sym) == -1) { mdb_warn("couldn't find passive buffer"); return (-1); } addr = (uintptr_t)sym.st_value; if (mdb_vread(tr, sizeof (cyc_tracebuf_t), addr) == -1) { mdb_warn("couldn't read passive buffer"); return (-1); } wsp->walk_addr = addr - offsetof(cyc_cpu_t, cyp_trace[0]); } else { if (mdb_vread(cpu, sizeof (cyc_cpu_t), wsp->walk_addr) == -1) { mdb_warn("couldn't read cyc_cpu at %p", wsp->walk_addr); mdb_free(cpu, sizeof (cyc_cpu_t)); return (-1); } } for (i = 0; i < CY_LEVELS; i++) { if (cpu->cyp_trace[i].cyt_ndx-- == 0) cpu->cyp_trace[i].cyt_ndx = CY_NTRACEREC - 1; } wsp->walk_data = cpu; return (0); }
int zone_walk_init(mdb_walk_state_t *wsp) { GElf_Sym sym; if (wsp->walk_addr == 0) { if (mdb_lookup_by_name("zone_active", &sym) == -1) { mdb_warn("failed to find 'zone_active'"); return (WALK_ERR); } wsp->walk_addr = (uintptr_t)sym.st_value; } if (mdb_layered_walk("list", wsp) == -1) { mdb_warn("couldn't walk 'list'"); return (WALK_ERR); } return (WALK_NEXT); }
/* * Look up the symbol name for the given sockparams list and walk * all the entries. */ static boolean_t sockparams_walk_list(const char *symname, int argc, const mdb_arg_t *argv) { GElf_Sym sym; if (mdb_lookup_by_name(symname, &sym)) { mdb_warn("can't find symbol %s", symname); return (B_FALSE); } if (mdb_pwalk_dcmd("list", "sockfs`sockparams", argc, argv, sym.st_value) != 0) { mdb_warn("can't walk %s", symname); return (B_FALSE); } return (B_TRUE); }
/*ARGSUSED*/ int cyccover(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { cyc_coverage_t cv[CY_NCOVERAGE]; char c[WHYLEN]; GElf_Sym sym; int i; if ((flags & DCMD_ADDRSPEC) || argc != 0) return (DCMD_USAGE); if (mdb_lookup_by_name("cyc_coverage", &sym) == -1) { mdb_warn("couldn't find coverage information"); return (DCMD_ABORT); } addr = (uintptr_t)sym.st_value; if (mdb_vread(cv, sizeof (cyc_coverage_t) * CY_NCOVERAGE, addr) == -1) { mdb_warn("couldn't read coverage array at %p", addr); return (DCMD_ABORT); } mdb_printf("%-*s %8s %8s %8s %15s %15s\n", WHYLEN, "POINT", "HIGH", "LOCK", "LOW/PASV", "ARG0", "ARG1"); qsort(cv, CY_NCOVERAGE, sizeof (cyc_coverage_t), cyccover_comp); for (i = 0; i < CY_NCOVERAGE; i++) { if (cv[i].cyv_why != NULL) { (void) mdb_readstr(c, WHYLEN, (uintptr_t)cv[i].cyv_why); mdb_printf("%-*s %8d %8d %8d %15llx %15llx\n", WHYLEN, c, cv[i].cyv_count[CY_HIGH_LEVEL], cv[i].cyv_count[CY_LOCK_LEVEL], cv[i].cyv_passive_count != 0 ? cv[i].cyv_passive_count : cv[i].cyv_count[CY_LOW_LEVEL], cv[i].cyv_arg0, cv[i].cyv_arg1); } } return (DCMD_OK); }
/*ARGSUSED*/ static int idt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int i; if (!(flags & DCMD_ADDRSPEC)) { GElf_Sym idt0_va; gate_desc_t *idt0; if (mdb_lookup_by_name("idt0", &idt0_va) < 0) { mdb_warn("failed to find VA of idt0"); return (DCMD_ERR); } addr = idt0_va.st_value; if (mdb_vread(&idt0, sizeof (idt0), addr) != sizeof (idt0)) { mdb_warn("failed to read idt0 at %p\n", addr); return (DCMD_ERR); } addr = (uintptr_t)idt0; } for (i = 0; i < NIDT; i++, addr += sizeof (gate_desc_t)) { gate_desc_t gate; char label[6]; if (mdb_vread(&gate, sizeof (gate_desc_t), addr) != sizeof (gate_desc_t)) { mdb_warn("failed to read gate descriptor at %p\n", addr); return (DCMD_ERR); } (void) mdb_snprintf(label, sizeof (label), "%3d: ", i); gate_desc_dump(&gate, label, i == 0); } return (DCMD_OK); }
int snode_walk_init(mdb_walk_state_t *wsp) { int stablesz; GElf_Sym sym; uintptr_t stable; uintptr_t sp; snode_walk_data_t *sw; if (mdb_readvar(&stablesz, "stablesz") == -1) { mdb_warn("failed to read 'stablesz'"); return (WALK_ERR); } if (stablesz == 0) return (WALK_DONE); if (mdb_lookup_by_name("stable", &sym) == -1) { mdb_warn("failed to read 'stable'"); return (WALK_ERR); } stable = (uintptr_t)sym.st_value; if (mdb_vread(&sp, sizeof (sp), stable) == -1) { mdb_warn("failed to read stable entry at %p", stable); return (WALK_DONE); } sw = mdb_alloc(sizeof (snode_walk_data_t), UM_SLEEP); sw->sw_stablesz = stablesz; sw->sw_stable = stable; wsp->walk_addr = sp; wsp->walk_data = sw; return (WALK_NEXT); }
static int ttrace_syscall(trap_trace_rec_t *rec) { GElf_Sym sym; int sysnum = rec->ttr_sysnum; uintptr_t addr; struct sysent sys; mdb_printf("%-3x", sysnum); if (rec->ttr_sysnum > NSYSCALL) { mdb_printf(" %-*d", TT_HDLR_WIDTH, rec->ttr_sysnum); return (0); } if (mdb_lookup_by_name("sysent", &sym) == -1) { mdb_warn("\ncouldn't find 'sysent'"); return (-1); } addr = (uintptr_t)sym.st_value + sysnum * sizeof (struct sysent); if (addr >= (uintptr_t)sym.st_value + sym.st_size) { mdb_warn("\nsysnum %d out-of-range\n", sysnum); return (-1); } if (mdb_vread(&sys, sizeof (sys), addr) == -1) { mdb_warn("\nfailed to read sysent at %p", addr); return (-1); } mdb_printf(" %-*a", TT_HDLR_WIDTH, sys.sy_callc); return (0); }
int zoneprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { zone_t zn; char name[ZONE_NAMELEN]; char path[ZONE_PATHLEN]; int len; uint_t vopt_given; uint_t ropt_given; if (argc > 2) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk_dcmd("zone", "zone", argc, argv) == -1) { mdb_warn("can't walk zones"); return (DCMD_ERR); } return (DCMD_OK); } /* * Get the optional -r (reference counts) and -v (verbose output) * arguments. */ vopt_given = FALSE; ropt_given = FALSE; if (argc > 0 && mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &vopt_given, 'r', MDB_OPT_SETBITS, TRUE, &ropt_given, NULL) != argc) return (DCMD_USAGE); /* * -v can only be specified with -r. */ if (vopt_given == TRUE && ropt_given == FALSE) return (DCMD_USAGE); /* * Print a table header, if necessary. */ if (DCMD_HDRSPEC(flags)) { if (ropt_given == FALSE) mdb_printf("%<u>%?s %6s %-13s %-20s %-s%</u>\n", "ADDR", "ID", "STATUS", "NAME", "PATH"); else mdb_printf("%<u>%?s %6s %10s %10s %-20s%</u>\n", "ADDR", "ID", "REFS", "CREFS", "NAME"); } /* * Read the zone_t structure at the given address and read its name. */ if (mdb_vread(&zn, sizeof (zone_t), addr) == -1) { mdb_warn("can't read zone_t structure at %p", addr); return (DCMD_ERR); } len = mdb_readstr(name, ZONE_NAMELEN, (uintptr_t)zn.zone_name); if (len > 0) { if (len == ZONE_NAMELEN) (void) strcpy(&name[len - 4], "..."); } else { (void) strcpy(name, "??"); } if (ropt_given == FALSE) { char *statusp; /* * Default display * Fetch the zone's path and print the results. */ len = mdb_readstr(path, ZONE_PATHLEN, (uintptr_t)zn.zone_rootpath); if (len > 0) { if (len == ZONE_PATHLEN) (void) strcpy(&path[len - 4], "..."); } else { (void) strcpy(path, "??"); } if (zn.zone_status >= ZONE_IS_UNINITIALIZED && zn.zone_status <= ZONE_IS_DEAD) statusp = zone_status_names[zn.zone_status]; else statusp = "???"; mdb_printf("%0?p %6d %-13s %-20s %s\n", addr, zn.zone_id, statusp, name, path); } else { /* * Display the zone's reference counts. * Display the zone's subsystem-specific reference counts if * the user specified the '-v' option. */ mdb_printf("%0?p %6d %10u %10u %-20s\n", addr, zn.zone_id, zn.zone_ref, zn.zone_cred_ref, name); if (vopt_given == TRUE) { GElf_Sym subsys_names_sym; uintptr_t **zone_ref_subsys_names; uint_t num_subsys; uint_t n; /* * Read zone_ref_subsys_names from the kernel image. */ if (mdb_lookup_by_name("zone_ref_subsys_names", &subsys_names_sym) != 0) { mdb_warn("can't find zone_ref_subsys_names"); return (DCMD_ERR); } if (subsys_names_sym.st_size != ZONE_REF_NUM_SUBSYS * sizeof (char *)) { mdb_warn("number of subsystems in target " "differs from what mdb expects (mismatched" " kernel versions?)"); if (subsys_names_sym.st_size < ZONE_REF_NUM_SUBSYS * sizeof (char *)) num_subsys = subsys_names_sym.st_size / sizeof (char *); else num_subsys = ZONE_REF_NUM_SUBSYS; } else { num_subsys = ZONE_REF_NUM_SUBSYS; } if ((zone_ref_subsys_names = mdb_alloc( subsys_names_sym.st_size, UM_GC)) == NULL) { mdb_warn("out of memory"); return (DCMD_ERR); } if (mdb_readvar(zone_ref_subsys_names, "zone_ref_subsys_names") == -1) { mdb_warn("can't find zone_ref_subsys_names"); return (DCMD_ERR); } /* * Display each subsystem's reference count if it's * nonzero. */ mdb_inc_indent(7); for (n = 0; n < num_subsys; ++n) { char subsys_name[16]; /* * Skip subsystems lacking outstanding * references. */ if (zn.zone_subsys_ref[n] == 0) continue; /* * Each subsystem's name must be read from * the target's image. */ if (mdb_readstr(subsys_name, sizeof (subsys_name), (uintptr_t)zone_ref_subsys_names[n]) == -1) { mdb_warn("unable to read subsystem name" " from zone_ref_subsys_names[%u]", n); return (DCMD_ERR); } mdb_printf("%15s: %10u\n", subsys_name, zn.zone_subsys_ref[n]); } mdb_dec_indent(7); } } return (DCMD_OK); }
/* * Utility routine to read in a filesystem name given a vfs pointer. If * no vfssw entry for the vfs is available (as is the case with some pseudo- * filesystems), we check against some known problem fs's: doorfs and * portfs. If that fails, we try to guess the filesystem name using * symbol names. fsname should be a buffer of size _ST_FSTYPSZ. */ static int read_fsname(uintptr_t vfsp, char *fsname) { vfs_t vfs; struct vfssw vfssw_entry; GElf_Sym vfssw_sym, test_sym; char testname[MDB_SYM_NAMLEN]; if (mdb_vread(&vfs, sizeof (vfs), vfsp) == -1) { mdb_warn("failed to read vfs %p", vfsp); return (-1); } if (mdb_lookup_by_name("vfssw", &vfssw_sym) == -1) { mdb_warn("failed to find vfssw"); return (-1); } /* * vfssw is an array; we need vfssw[vfs.vfs_fstype]. */ if (mdb_vread(&vfssw_entry, sizeof (vfssw_entry), vfssw_sym.st_value + (sizeof (struct vfssw) * vfs.vfs_fstype)) == -1) { mdb_warn("failed to read vfssw index %d", vfs.vfs_fstype); return (-1); } if (vfs.vfs_fstype != 0) { if (mdb_readstr(fsname, _ST_FSTYPSZ, (uintptr_t)vfssw_entry.vsw_name) == -1) { mdb_warn("failed to find fs name %p", vfssw_entry.vsw_name); return (-1); } return (0); } /* * Do precise detection for certain filesystem types that we * know do not appear in vfssw[], and that we depend upon in other * parts of the code: doorfs and portfs. */ if (mdb_lookup_by_name("door_vfs", &test_sym) != -1) { if (test_sym.st_value == vfsp) { strcpy(fsname, "doorfs"); return (0); } } if (mdb_lookup_by_name("port_vfs", &test_sym) != -1) { if (test_sym.st_value == vfsp) { strcpy(fsname, "portfs"); return (0); } } /* * Heuristic detection for other filesystems that don't have a * vfssw[] entry. These tend to be named <fsname>_vfs, so we do a * lookup_by_addr and see if we find a symbol of that name. */ if (mdb_lookup_by_addr(vfsp, MDB_SYM_EXACT, testname, sizeof (testname), &test_sym) != -1) { if ((strlen(testname) > 4) && (strcmp(testname + strlen(testname) - 4, "_vfs") == 0)) { testname[strlen(testname) - 4] = '\0'; strncpy(fsname, testname, _ST_FSTYPSZ); return (0); } } mdb_warn("unknown filesystem type for vfs %p", vfsp); return (-1); }
/* ARGSUSED */ int set_io(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { GElf_Sym setiosym; uint64_t i; size_t offset = 0; uint64_t opt_a = 0; /* up to active_sets */ char *opt_s = (char *)NULL; /* a named set */ uint64_t opt_m = 0; /* array element */ int setno = 0; int argnum = 0; argnum = mdb_getopts(argc, argv, 'a', MDB_OPT_UINT64, &opt_a, 's', MDB_OPT_STR, &opt_s, 'm', MDB_OPT_UINT64, &opt_m, NULL); if (argnum != argc) { mdb_printf("invalid arguments\n"); return (DCMD_USAGE); } if ((opt_s != 0) && (opt_m != 0)) { mdb_printf("-s and -m cannot both be specified\n"); return (DCMD_USAGE); } snarf_sets(); if (opt_a == 0) opt_a = active_sets; /* find the array */ if (mdb_lookup_by_name("md_set_io", &setiosym) == -1) { mdb_warn("SVM - no set io counts set\n"); return (DCMD_ERR); } if (md_verbose) { mdb_printf("Base address for the md_set_io array: %p\n", setiosym.st_value); } if (opt_s != NULL) { setno = findset(opt_s); if (setno == -1) { mdb_warn("no such set: %s\n", opt_s); return (DCMD_ERR); } opt_m = setno; } if (opt_m > 0) { mdb_printf("%lld]\t%ld\t%ld", opt_m, md_setio[opt_m].io_cnt, md_setio[opt_m].io_state); mdb_printf("\t%hb\n", io_state_bits); return (DCMD_OK); } if (opt_a == 0) { mdb_warn("No active set!\n"); return (DCMD_ERR); } for (i = 0; i < opt_a; i++) { if (mdb_vread(&md_setio[i], sizeof (md_set_io_t), setiosym.st_value + offset) == -1) { mdb_warn("failed to read md_set_io_t at 0x%x\n", setiosym.st_value + offset); } mdb_printf("%lld]\t%ld\t%ld", i, md_setio[i].io_cnt, md_setio[i].io_state); mdb_printf("\t%hb", io_state_bits); if (md_verbose) { mdb_printf(" - io_cnt: %p", setiosym.st_value + offset + sizeof (kmutex_t) + sizeof (kcondvar_t)); mdb_printf(" %d", sizeof (md_set_io_t)); } mdb_printf("\n"); offset += sizeof (md_set_io_t); } return (DCMD_OK); }