/* * Print the core fields in an NCA nca_conn_t. With the "-t" argument, skip * all nca_conn_t's that are in the TIME_WAIT state. With the "-x" argument, * show the xmit data. */ static int nca_conn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { unsigned int i; nca_conn_t conn; unsigned int show_timewait = TRUE; unsigned int show_xmit = FALSE; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'x', MDB_OPT_SETBITS, TRUE, &show_xmit, 't', MDB_OPT_CLRBITS, TRUE, &show_timewait, NULL) != argc) return (DCMD_USAGE); if (DCMD_HDRSPEC(flags)) { mdb_printf("%<u>%-*s %3s %8s %15s %15s %-*s %-10s%</u>\n", NCA_ADDR_WIDTH, "ADDR", "REF", "CREATE", "LOCAL_ADDR", "REMOTE_ADDR", NCA_ADDR_WIDTH, "NODE", "STATE"); } if (mdb_vread(&conn, sizeof (nca_conn_t), addr) == -1) { mdb_warn("cannot read nca_conn_t at %p", addr); return (DCMD_ERR); } if (!show_timewait && conn.tcp_state == TCPS_TIME_WAIT) return (DCMD_OK); mdb_printf("%0*p %3d %8lx %15I %15I %0*p %s\n", NCA_ADDR_WIDTH, addr, conn.ref, conn.create, conn.laddr, conn.faddr, NCA_ADDR_WIDTH, conn.req_np, state2name(conn.tcp_state)); if (show_xmit) { mdb_inc_indent(4); for (i = 0; i < TCP_XMIT_MAX_IX; i++) { mdb_printf("xmit[%d]\n", i); mdb_printf("\tref pointer\t\t%p\n", conn.xmit[i].np); mdb_printf("\tdata pointer\t\t%p\n", conn.xmit[i].dp); mdb_printf("\tcksum array\t\t%p\n", conn.xmit[i].cp); mdb_printf("\tremaining xmit data\t%d\n", conn.xmit[i].sz); mdb_printf("\tref to node_t\t\t%p\n", conn.xmit[i].refed); mdb_printf("\tremaining segment data\t%d\n", conn.xmit[i].dsz); mdb_printf("\tvirtual pointer\t\t%p\n", conn.xmit[i].dvp); } mdb_dec_indent(4); } return (DCMD_OK); }
int va2pfn_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uintptr_t addrspace; char *addrspace_str = NULL; int piped = flags & DCMD_PIPE_OUT; pfn_t pfn; pfn_t mfn; int rc; init_mmu(); if (mmu.num_level == 0) return (DCMD_ERR); if (mdb_getopts(argc, argv, 'a', MDB_OPT_STR, &addrspace_str) != argc) return (DCMD_USAGE); if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_USAGE); /* * parse the address space */ if (addrspace_str != NULL) addrspace = mdb_strtoull(addrspace_str); else addrspace = 0; rc = do_va2pa(addr, (struct as *)addrspace, !piped, NULL, &mfn); if (rc != DCMD_OK) return (rc); if ((pfn = mdb_mfn_to_pfn(mfn)) == -(pfn_t)1) { mdb_warn("Invalid mfn %lr\n", mfn); return (DCMD_ERR); } if (piped) { mdb_printf("0x%lr\n", pfn); return (DCMD_OK); } mdb_printf("Virtual address 0x%p maps pfn 0x%lr", addr, pfn); if (is_xpv) mdb_printf(" (mfn 0x%lr)", mfn); mdb_printf("\n"); return (DCMD_OK); }
int cmd_nmadd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uintptr_t opt_e = 0, opt_s = 0; uint_t opt_f = FALSE, opt_o = FALSE; GElf_Sym sym; int i; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); i = mdb_getopts(argc, argv, 'f', MDB_OPT_SETBITS, TRUE, &opt_f, 'o', MDB_OPT_SETBITS, TRUE, &opt_o, 'e', MDB_OPT_UINTPTR, &opt_e, 's', MDB_OPT_UINTPTR, &opt_s, NULL); if (i != (argc - 1) || argv[i].a_type != MDB_TYPE_STRING || argv[i].a_un.a_str[0] == '-' || argv[i].a_un.a_str[0] == '+') return (DCMD_USAGE); if (opt_e && opt_e < addr) { mdb_warn("end (%p) is less than start address (%p)\n", (void *)opt_e, (void *)addr); return (DCMD_USAGE); } if (mdb_gelf_symtab_lookup_by_name(mdb.m_prsym, argv[i].a_un.a_str, &sym, NULL) == -1) { bzero(&sym, sizeof (sym)); sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); } if (opt_f) sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC); if (opt_o) sym.st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT); if (opt_e) sym.st_size = (GElf_Xword)(opt_e - addr); if (opt_s) sym.st_size = (GElf_Xword)(opt_s); sym.st_value = (GElf_Addr)addr; mdb_gelf_symtab_insert(mdb.m_prsym, argv[i].a_un.a_str, &sym); mdb_iob_printf(mdb.m_out, "added %s, value=%llr size=%llr\n", argv[i].a_un.a_str, sym.st_value, sym.st_size); return (DCMD_OK); }
int pagelookup(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uintptr_t vp = -(uintptr_t)1; uint64_t offset = -(uint64_t)1; uintptr_t pageaddr; int hasaddr = (flags & DCMD_ADDRSPEC); int usedaddr = 0; if (mdb_getopts(argc, argv, 'v', MDB_OPT_UINTPTR, &vp, 'o', MDB_OPT_UINT64, &offset, 0) != argc) { return (DCMD_USAGE); } if (vp == -(uintptr_t)1) { if (offset == -(uint64_t)1) { mdb_warn( "pagelookup: at least one of -v vp or -o offset " "required.\n"); return (DCMD_USAGE); } vp = addr; usedaddr = 1; } else if (offset == -(uint64_t)1) { offset = mdb_get_dot(); usedaddr = 1; } if (usedaddr && !hasaddr) { mdb_warn("pagelookup: address required\n"); return (DCMD_USAGE); } if (!usedaddr && hasaddr) { mdb_warn( "pagelookup: address specified when both -v and -o were " "passed"); return (DCMD_USAGE); } pageaddr = mdb_page_lookup(vp, offset); if (pageaddr == 0) { mdb_warn("pagelookup: no page for {vp = %p, offset = %llp)\n", vp, offset); return (DCMD_OK); } mdb_printf("%#lr\n", pageaddr); /* this is PIPE_OUT friendly */ return (DCMD_OK); }
static int xhci_mdb_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uintptr_t ep, slot; boolean_t ep_set, slot_set; xhci_mdb_find_t xmf; if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_USAGE); ep_set = slot_set = B_FALSE; if (mdb_getopts(argc, argv, 'e', MDB_OPT_UINTPTR_SET, &ep_set, &ep, 's', MDB_OPT_UINTPTR_SET, &slot_set, &slot) != argc) return (DCMD_USAGE); if (!slot_set) { mdb_warn("-s is required\n"); return (DCMD_USAGE); } xmf.xmf_slot = (int)slot; if (ep_set) xmf.xmf_ep = (int)ep; else xmf.xmf_ep = -1; xmf.xmf_addr = 0; if (mdb_pwalk("xhci`xhci_device", xhci_mdb_find_device_cb, &xmf, addr) == -1) { mdb_warn("failed to walk xhci_device at %p", addr); return (DCMD_ERR); } if (xmf.xmf_addr == 0) { if (ep_set) { mdb_warn("failed to find xhci_endpoint_t for slot %d " "and endpoint %d\n", slot, ep); } else { mdb_warn("failed to find xhci_device_t for slot %d\n", slot); } return (DCMD_ERR); } mdb_printf("%p\n", xmf.xmf_addr); return (DCMD_OK); }
/* * Map from thread pointer to tsd for given key */ static int d_tsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { mdb_libc_ulwp_t u; uintptr_t ulwp_addr; uintptr_t key = NULL; void *element = NULL; if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC) || key == NULL) return (DCMD_USAGE); if (tid2ulwp_impl(addr, &ulwp_addr) != DCMD_OK) return (DCMD_ERR); if (mdb_ctf_vread(&u, "ulwp_t", "mdb_libc_ulwp_t", ulwp_addr, 0) == -1) return (DCMD_ERR); if (key < TSD_NFAST) { element = u.ul_ftsd[key]; } else if (u.ul_stsd != NULL) { uint_t nalloc; /* tsd_t is a union, so we can't use ctf_vread() on it. */ if (mdb_vread(&nalloc, sizeof (nalloc), (uintptr_t)&u.ul_stsd->tsd_nalloc) == -1) { mdb_warn("failed to read tsd_t at %p", u.ul_stsd); return (DCMD_ERR); } if (key < nalloc) { if (mdb_vread(&element, sizeof (element), (uintptr_t)&u.ul_stsd->tsd_data[key]) == -1) { mdb_warn("failed to read tsd_t at %p", u.ul_stsd); return (DCMD_ERR); } } } if (element == NULL && (flags & DCMD_PIPE)) return (DCMD_OK); mdb_printf("%p\n", element); return (DCMD_OK); }
/*ARGSUSED*/ int snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { snode_cbdata_t sd; struct snode snode; uintptr_t major = 0, dev = 0; sd.sd_major = -1; sd.sd_minor = -1; sd.sd_verbose = !(flags & DCMD_PIPE_OUT); if (mdb_getopts(argc, argv, 'm', MDB_OPT_UINTPTR, &major, 'd', MDB_OPT_UINTPTR, &dev, NULL) != argc) return (DCMD_USAGE); if (dev != 0) { sd.sd_major = getmajor(dev); sd.sd_minor = getminor(dev); } if (major != 0) sd.sd_major = major; if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) { mdb_printf("%<u>%?s %?s %6s %16s %-15s%</u>\n", "ADDR", "VNODE", "COUNT", "DEV", "FLAG"); } if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk("snode", (mdb_walk_cb_t)snode_cb, &sd) == -1) { mdb_warn("can't walk snodes"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_vread(&snode, sizeof (snode), addr) == -1) { mdb_warn("failed to read snode structure at %p", addr); return (DCMD_ERR); } snode_cb(addr, &snode, &sd); return (DCMD_OK); }
/* * dcmd ::credsid - display a credsid_t */ int cmd_credsid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { credsid_t kr; uint_t opts = FALSE; int rv = DCMD_OK; if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC)) { return (DCMD_USAGE); } if (mdb_vread(&kr, sizeof (kr), addr) == -1) { mdb_warn("error reading credsid_t at %p", addr); return (DCMD_ERR); } if (opts & OPT_VERBOSE) mdb_printf("kr_ref = 0x%x\n", kr.kr_ref); mdb_printf("kr_sidx[USER] = "); print_ksid(&kr.kr_sidx[KSID_USER]); mdb_printf("kr_sidx[GROUP] = "); print_ksid(&kr.kr_sidx[KSID_GROUP]); mdb_printf("kr_sidx[OWNER] = "); print_ksid(&kr.kr_sidx[KSID_OWNER]); mdb_printf("kr_sidlist = %p\n", kr.kr_sidlist); if (kr.kr_sidlist != NULL && (opts & OPT_VERBOSE) != 0) { mdb_printf("*kr_sidlist = {\n"); mdb_inc_indent(4); rv = mdb_call_dcmd("ksidlist", (uintptr_t)kr.kr_sidlist, flags, argc, argv); mdb_dec_indent(4); mdb_printf("}\n"); } return (rv); }
int pfiles(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int opt_f = 0; struct pfiles_cbdata cb; bzero(&cb, sizeof (cb)); if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'p', MDB_OPT_SETBITS, TRUE, &cb.opt_p, 'f', MDB_OPT_SETBITS, TRUE, &opt_f, NULL) != argc) return (DCMD_USAGE); if (opt_f) { mdb_printf("%<u>%?s %4s %8s %?s %10s %?s %4s%</u>\n", "FILE", "FD", "FLAG", "VNODE", "OFFSET", "CRED", "CNT"); if (mdb_pwalk("allfile", (mdb_walk_cb_t)file_t_callback, &cb, addr) == -1) { mdb_warn("failed to walk 'allfile'"); return (DCMD_ERR); } } else { mdb_printf("%<u>%-4s %4s %?s ", "FD", "TYPE", "VNODE"); if (cb.opt_p) mdb_printf("PATH"); else mdb_printf("INFO"); mdb_printf("%</u>\n"); if (mdb_pwalk("allfile", (mdb_walk_cb_t)pfile_callback, &cb, addr) == -1) { mdb_warn("failed to walk 'allfile'"); return (DCMD_ERR); } } return (DCMD_OK); }
/* * dcmd ::ksidlist - display a ksidlist_t */ int cmd_ksidlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { ksidlist_t ksl; ksid_t ks; uint_t i, opts = FALSE; int rv = DCMD_OK; if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC)) { return (DCMD_USAGE); } if (mdb_vread(&ksl, sizeof (ksl), addr) == -1) { mdb_warn("error reading ksidlist_t at %p", addr); return (DCMD_ERR); } if (opts & OPT_VERBOSE) { mdb_printf("ksl_ref = 0x%x\n", ksl.ksl_ref); mdb_printf("ksl_nsid = 0x%x\n", ksl.ksl_nsid); mdb_printf("ksl_neid = 0x%x\n", ksl.ksl_neid); } mdb_printf("ksl_sids = [\n"); addr += OFFSETOF(ksidlist_t, ksl_sids); mdb_inc_indent(4); for (i = 0; i < ksl.ksl_nsid; i++, addr += sizeof (ksid_t)) { if (mdb_vread(&ks, sizeof (ks), addr) == -1) { mdb_warn("error reading ksid_t at %p", addr); rv = DCMD_ERR; break; } print_ksid(&ks); } mdb_dec_indent(4); mdb_printf("]\n"); return (rv); }
int memlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { struct memlist ml; if (!(flags & DCMD_ADDRSPEC)) { uintptr_t ptr; uint_t list = 0; int i; static const char *lists[] = { "phys_install", "phys_avail", "virt_avail" }; if (mdb_getopts(argc, argv, 'i', MDB_OPT_SETBITS, (1 << 0), &list, 'a', MDB_OPT_SETBITS, (1 << 1), &list, 'v', MDB_OPT_SETBITS, (1 << 2), &list, NULL) != argc) return (DCMD_USAGE); if (!list) list = 1; for (i = 0; list; i++, list >>= 1) { if (!(list & 1)) continue; if ((mdb_readvar(&ptr, lists[i]) == -1) || (ptr == NULL)) { mdb_warn("%s not found or invalid", lists[i]); return (DCMD_ERR); } mdb_printf("%s:\n", lists[i]); if (mdb_pwalk_dcmd("memlist", "memlist", 0, NULL, ptr) == -1) { mdb_warn("can't walk memlist"); return (DCMD_ERR); } } return (DCMD_OK); }
/* * dcmd ::credgrp - display cred_t groups */ int cmd_credgrp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { credgrp_t grps; gid_t gid; uint_t i, opts = FALSE; int rv = DCMD_OK; if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, OPT_VERBOSE, &opts, NULL) != argc) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC)) { return (DCMD_USAGE); } if (mdb_vread(&grps, sizeof (grps), addr) == -1) { mdb_warn("error reading credgrp_t at %p", addr); return (DCMD_ERR); } if (opts & OPT_VERBOSE) { mdb_printf("crg_ref = 0x%x\n", grps.crg_ref); mdb_printf("crg_ngroups = 0x%x\n", grps.crg_ngroups); } mdb_printf("crg_groups = [\n"); addr += OFFSETOF(credgrp_t, crg_groups); mdb_inc_indent(4); for (i = 0; i < grps.crg_ngroups; i++, addr += sizeof (gid_t)) { if (mdb_vread(&gid, sizeof (gid), addr) == -1) { mdb_warn("error reading gid_t at %p", addr); rv = DCMD_ERR; break; } mdb_printf("\t%u,", gid); } mdb_dec_indent(4); mdb_printf("\n]\n"); return (rv); }
/*ARGSUSED*/ int pte_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int level = 0; uint64_t pte = 0; char *level_str = NULL; char *pte_str = NULL; init_mmu(); if (mmu.num_level == 0) return (DCMD_ERR); if (mdb_getopts(argc, argv, 'p', MDB_OPT_STR, &pte_str, 'l', MDB_OPT_STR, &level_str) != argc) return (DCMD_USAGE); /* * parse the PTE to decode, if it's 0, we don't do anything */ if (pte_str != NULL) { pte = mdb_strtoull(pte_str); } else { if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_USAGE); pte = addr; } if (pte == 0) return (DCMD_OK); /* * parse the level if supplied */ if (level_str != NULL) { level = mdb_strtoull(level_str); if (level < 0 || level > mmu.max_level) return (DCMD_ERR); } return (do_pte_dcmd(level, pte)); }
/* ARGSUSED */ int group(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { group_t group; int opt_q = 0; /* display only address. */ /* Should provide an address */ if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'q', MDB_OPT_SETBITS, TRUE, &opt_q, NULL) != argc) return (DCMD_USAGE); if (flags & DCMD_PIPE_OUT) opt_q = B_TRUE; if (DCMD_HDRSPEC(flags) && !opt_q) { mdb_printf("%?s %6s %9s %?s\n", "ADDR", "SIZE", "CAPACITY", "SET"); } if (mdb_vread(&group, sizeof (struct group), addr) == -1) { mdb_warn("unable to read 'group' at %p", addr); return (DCMD_ERR); } if (opt_q) { mdb_printf("%0?p\n", addr); return (DCMD_OK); } mdb_printf("%?p %6d %9d %?p\n", addr, group.grp_size, group.grp_capacity, group.grp_set); return (DCMD_OK); }
static int stmf_sbd_it(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t verbose = FALSE; sbd_lu_t slu; stmf_sbd_cb_t cb_st = {0}; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) return (DCMD_USAGE); if (verbose) { cb_st.flag |= STMF_SBD_VERBOSE; mdb_printf("\nLU:- %p\n", addr); } /* If address of pgr_key is given, just print that key and return */ if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) { mdb_warn("failed to read sbd_lu at %p\n", addr); return (DCMD_ERR); } /* Just a sanity check, not necessarily needed */ if (slu.sl_it_list == NULL) { if (verbose) mdb_printf("sbd_it_list is empty\n", addr); return (DCMD_OK); } if (mdb_pwalk("stmf_sbd_it", (mdb_walk_cb_t)stmf_sbd_it_cb, &cb_st, (uintptr_t)slu.sl_it_list) == -1) { mdb_warn("failed to walk sbd_lu_it_list\n"); return (DCMD_ERR); } return (DCMD_OK); }
/*ARGSUSED*/ int print_nvlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int verbose = B_FALSE; mdb_arg_t v; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) return (DCMD_USAGE); v.a_type = MDB_TYPE_STRING; if (verbose) v.a_un.a_str = "-r"; else v.a_un.a_str = "-rq"; return (mdb_pwalk_dcmd("nvpair", "nvpair", 1, &v, addr)); }
/*ARGSUSED*/ static int mod( uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int status; int rc = DCMD_OK; mfdata_t *mfp; mfp = mdb_zalloc(sizeof (mfdata_t), UM_SLEEP); if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, MF_VERBOSE, &mfp->mf_flags, NULL) != argc) return (DCMD_USAGE); if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) mfp->mf_banner = B_TRUE; if (flags & DCMD_ADDRSPEC) { status = mod_format(addr, NULL, mfp); rc = (status == WALK_NEXT) ? DCMD_OK : DCMD_ERR; goto cleanup; } if (mdb_pwalk("ipp_byid", mod_format, mfp, ipp_mod_byid) == -1) { mdb_warn("failed to execute ipp_byid walk"); rc = DCMD_ERR; } cleanup: mdb_free(mfp, sizeof (mfdata_t)); return (rc); }
/*ARGSUSED*/ static int py_stack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t verbose = FALSE; if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) return (DCMD_USAGE); if (flags & DCMD_PIPE_OUT) { mdb_warn("py_stack cannot output into a pipe\n"); return (DCMD_ERR); } if (flags & DCMD_ADDRSPEC) { mdb_arg_t nargv; uint_t nargc = verbose ? 1 : 0; nargv.a_type = MDB_TYPE_STRING; nargv.a_un.a_str = "-v"; if (mdb_pwalk_dcmd("pyframe", "pyframe", nargc, &nargv, addr) == -1) { mdb_warn("can't walk 'pyframe'"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_walk("pyinterp", (mdb_walk_cb_t)python_thread, &verbose) == -1) { mdb_warn("can't walk 'pyinterp'"); return (DCMD_ERR); } return (DCMD_OK); }
/* * Print the core TCP-related fields in an NCA nca_conn_t. With the "-t" * argument, skips all nca_conn_t's that are in the TIME_WAIT state. */ static int nca_tcpconn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { nca_conn_t conn; unsigned int show_timewait = TRUE; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 't', MDB_OPT_CLRBITS, TRUE, &show_timewait, NULL) != argc) return (DCMD_USAGE); if (DCMD_HDRSPEC(flags)) { mdb_printf("%<u>%-*s %21s %5s %8s %5s %8s %5s %-9s%</u>\n", NCA_ADDR_WIDTH, "ADDR", "REMOTE_ADDR", "SWIND", "SUNASEQ", "SNSEQ", "RACKSEQ", "RNSEQ", "STATE"); } if (mdb_vread(&conn, sizeof (nca_conn_t), addr) == -1) { mdb_warn("cannot read nca_conn_t at %p", addr); return (DCMD_ERR); } if (!show_timewait && conn.tcp_state == TCPS_TIME_WAIT) return (DCMD_OK); mdb_nhconvert(&conn.conn_fport, &conn.conn_fport, sizeof (in_port_t)); mdb_printf("%0*p %15I:%05hu %5u %08x %+5d %08x %+5d %-9s\n", NCA_ADDR_WIDTH, addr, conn.faddr, conn.conn_fport, conn.tcp_swnd, conn.tcp_suna, conn.tcp_snxt - conn.tcp_suna, conn.tcp_rack, conn.tcp_rnxt - conn.tcp_rack, state2name(conn.tcp_state)); return (DCMD_OK); }
/*ARGSUSED*/ int ptable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { pfn_t pfn; uint_t mflag = 0; init_mmu(); if (mmu.num_level == 0) return (DCMD_ERR); if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'm', MDB_OPT_SETBITS, TRUE, &mflag, NULL) != argc) return (DCMD_USAGE); pfn = (pfn_t)addr; if (mflag) pfn = mdb_mfn_to_pfn(pfn); return (do_ptable_dcmd(pfn)); }
/*ARGSUSED*/ int stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { size_t idx; char *seen = NULL; const char *caller_str = NULL; const char *excl_caller_str = NULL; uintptr_t caller = 0, excl_caller = 0; const char *module_str = NULL; const char *excl_module_str = NULL; stacks_module_t module, excl_module; const char *sobj = NULL; const char *excl_sobj = NULL; uintptr_t sobj_ops = 0, excl_sobj_ops = 0; const char *tstate_str = NULL; const char *excl_tstate_str = NULL; uint_t tstate = -1U; uint_t excl_tstate = -1U; uint_t printed = 0; uint_t all = 0; uint_t force = 0; uint_t interesting = 0; uint_t verbose = 0; /* * We have a slight behavior difference between having piped * input and 'addr::stacks'. Without a pipe, we assume the * thread pointer given is a representative thread, and so * we include all similar threads in the system in our output. * * With a pipe, we filter down to just the threads in our * input. */ uint_t addrspec = (flags & DCMD_ADDRSPEC); uint_t only_matching = addrspec && (flags & DCMD_PIPE); mdb_pipe_t p; bzero(&module, sizeof (module)); bzero(&excl_module, sizeof (excl_module)); if (mdb_getopts(argc, argv, 'a', MDB_OPT_SETBITS, TRUE, &all, 'f', MDB_OPT_SETBITS, TRUE, &force, 'i', MDB_OPT_SETBITS, TRUE, &interesting, 'v', MDB_OPT_SETBITS, TRUE, &verbose, 'c', MDB_OPT_STR, &caller_str, 'C', MDB_OPT_STR, &excl_caller_str, 'm', MDB_OPT_STR, &module_str, 'M', MDB_OPT_STR, &excl_module_str, 's', MDB_OPT_STR, &sobj, 'S', MDB_OPT_STR, &excl_sobj, 't', MDB_OPT_STR, &tstate_str, 'T', MDB_OPT_STR, &excl_tstate_str, NULL) != argc) return (DCMD_USAGE); if (interesting) { if (sobj != NULL || excl_sobj != NULL || tstate_str != NULL || excl_tstate_str != NULL) { mdb_warn( "stacks: -i is incompatible with -[sStT]\n"); return (DCMD_USAGE); } excl_sobj = "CV"; excl_tstate_str = "FREE"; } if (caller_str != NULL) { mdb_set_dot(0); if (mdb_eval(caller_str) != 0) { mdb_warn("stacks: evaluation of \"%s\" failed", caller_str); return (DCMD_ABORT); } caller = mdb_get_dot(); } if (excl_caller_str != NULL) { mdb_set_dot(0); if (mdb_eval(excl_caller_str) != 0) { mdb_warn("stacks: evaluation of \"%s\" failed", excl_caller_str); return (DCMD_ABORT); } excl_caller = mdb_get_dot(); } mdb_set_dot(addr); if (module_str != NULL && stacks_module_find(module_str, &module) != 0) return (DCMD_ABORT); if (excl_module_str != NULL && stacks_module_find(excl_module_str, &excl_module) != 0) return (DCMD_ABORT); if (sobj != NULL && text_to_sobj(sobj, &sobj_ops) != 0) return (DCMD_USAGE); if (excl_sobj != NULL && text_to_sobj(excl_sobj, &excl_sobj_ops) != 0) return (DCMD_USAGE); if (sobj_ops != 0 && excl_sobj_ops != 0) { mdb_warn("stacks: only one of -s and -S can be specified\n"); return (DCMD_USAGE); } if (tstate_str != NULL && text_to_tstate(tstate_str, &tstate) != 0) return (DCMD_USAGE); if (excl_tstate_str != NULL && text_to_tstate(excl_tstate_str, &excl_tstate) != 0) return (DCMD_USAGE); if (tstate != -1U && excl_tstate != -1U) { mdb_warn("stacks: only one of -t and -T can be specified\n"); return (DCMD_USAGE); } /* * If there's an address specified, we're going to further filter * to only entries which have an address in the input. To reduce * overhead (and make the sorted output come out right), we * use mdb_get_pipe() to grab the entire pipeline of input, then * use qsort() and bsearch() to speed up the search. */ if (addrspec) { mdb_get_pipe(&p); if (p.pipe_data == NULL || p.pipe_len == 0) { p.pipe_data = &addr; p.pipe_len = 1; } qsort(p.pipe_data, p.pipe_len, sizeof (uintptr_t), uintptrcomp); /* remove any duplicates in the data */ idx = 0; while (idx < p.pipe_len - 1) { uintptr_t *data = &p.pipe_data[idx]; size_t len = p.pipe_len - idx; if (data[0] == data[1]) { memmove(data, data + 1, (len - 1) * sizeof (*data)); p.pipe_len--; continue; /* repeat without incrementing idx */ } idx++; } seen = mdb_zalloc(p.pipe_len, UM_SLEEP | UM_GC); } /* * Force a cleanup if we're connected to a live system. Never * do a cleanup after the first invocation around the loop. */ force |= (mdb_get_state() == MDB_STATE_RUNNING); if (force && (flags & (DCMD_LOOPFIRST|DCMD_LOOP)) == DCMD_LOOP) force = 0; stacks_cleanup(force); if (stacks_state == STACKS_STATE_CLEAN) { int res = stacks_run(verbose, addrspec ? &p : NULL); if (res != DCMD_OK) return (res); } for (idx = 0; idx < stacks_array_size; idx++) { stacks_entry_t *sep = stacks_array[idx]; stacks_entry_t *cur = sep; int frame; size_t count = sep->se_count; if (addrspec) { stacks_entry_t *head = NULL, *tail = NULL, *sp; size_t foundcount = 0; /* * We use the now-unused hash chain field se_next to * link together the dups which match our list. */ for (sp = sep; sp != NULL; sp = sp->se_dup) { uintptr_t *entry = bsearch(&sp->se_thread, p.pipe_data, p.pipe_len, sizeof (uintptr_t), uintptrcomp); if (entry != NULL) { foundcount++; seen[entry - p.pipe_data]++; if (head == NULL) head = sp; else tail->se_next = sp; tail = sp; sp->se_next = NULL; } } if (head == NULL) continue; /* no match, skip entry */ if (only_matching) { cur = sep = head; count = foundcount; } } if (caller != 0 && !stacks_has_caller(sep, caller)) continue; if (excl_caller != 0 && stacks_has_caller(sep, excl_caller)) continue; if (module.sm_size != 0 && !stacks_has_module(sep, &module)) continue; if (excl_module.sm_size != 0 && stacks_has_module(sep, &excl_module)) continue; if (tstate != -1U) { if (tstate == TSTATE_PANIC) { if (!sep->se_panic) continue; } else if (sep->se_panic || sep->se_tstate != tstate) continue; } if (excl_tstate != -1U) { if (excl_tstate == TSTATE_PANIC) { if (sep->se_panic) continue; } else if (!sep->se_panic && sep->se_tstate == excl_tstate) continue; } if (sobj_ops == SOBJ_ALL) { if (sep->se_sobj_ops == 0) continue; } else if (sobj_ops != 0) { if (sobj_ops != sep->se_sobj_ops) continue; } if (!(interesting && sep->se_panic)) { if (excl_sobj_ops == SOBJ_ALL) { if (sep->se_sobj_ops != 0) continue; } else if (excl_sobj_ops != 0) { if (excl_sobj_ops == sep->se_sobj_ops) continue; } } if (flags & DCMD_PIPE_OUT) { while (sep != NULL) { mdb_printf("%lr\n", sep->se_thread); sep = only_matching ? sep->se_next : sep->se_dup; } continue; } if (all || !printed) { mdb_printf("%<u>%-?s %-8s %-?s %8s%</u>\n", "THREAD", "STATE", "SOBJ", "COUNT"); printed = 1; } do { char state[20]; char sobj[100]; tstate_to_text(cur->se_tstate, cur->se_panic, state, sizeof (state)); sobj_to_text(cur->se_sobj_ops, sobj, sizeof (sobj)); if (cur == sep) mdb_printf("%-?p %-8s %-?s %8d\n", cur->se_thread, state, sobj, count); else mdb_printf("%-?p %-8s %-?s %8s\n", cur->se_thread, state, sobj, "-"); cur = only_matching ? cur->se_next : cur->se_dup; } while (all && cur != NULL); if (sep->se_failed != 0) { char *reason; switch (sep->se_failed) { case FSI_FAIL_NOTINMEMORY: reason = "thread not in memory"; break; case FSI_FAIL_THREADCORRUPT: reason = "thread structure stack info corrupt"; break; case FSI_FAIL_STACKNOTFOUND: reason = "no consistent stack found"; break; default: reason = "unknown failure"; break; } mdb_printf("%?s <%s>\n", "", reason); } for (frame = 0; frame < sep->se_depth; frame++) mdb_printf("%?s %a\n", "", sep->se_stack[frame]); if (sep->se_overflow) mdb_printf("%?s ... truncated ...\n", ""); mdb_printf("\n"); } if (flags & DCMD_ADDRSPEC) { for (idx = 0; idx < p.pipe_len; idx++) if (seen[idx] == 0) mdb_warn("stacks: %p not in thread list\n", p.pipe_data[idx]); } return (DCMD_OK); }
/*ARGSUSED*/ int fsinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { vfs_t vfs; int len; int opt_v = 0; char buf[MAXPATHLEN]; char fsname[_ST_FSTYPSZ]; mntopt_t *mntopts; size_t size; int i; int first = 1; char opt[MAX_MNTOPT_STR]; uintptr_t global_zone; if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk_dcmd("vfs", "fsinfo", argc, argv) == -1) { mdb_warn("failed to walk file system list"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) return (DCMD_USAGE); if (DCMD_HDRSPEC(flags)) mdb_printf("%<u>%?s %-15s %s%</u>\n", "VFSP", "FS", "MOUNT"); if (mdb_vread(&vfs, sizeof (vfs), addr) == -1) { mdb_warn("failed to read vfs_t %p", addr); return (DCMD_ERR); } if ((len = mdb_read_refstr((uintptr_t)vfs.vfs_mntpt, buf, sizeof (buf))) <= 0) strcpy(buf, "??"); else if (!opt_v && (len >= FSINFO_MNTLEN)) /* * In normal mode, we truncate the path to keep the output * clean. In -v mode, we just print the full path. */ strcpy(&buf[FSINFO_MNTLEN - 4], "..."); if (read_fsname(addr, fsname) == -1) return (DCMD_ERR); mdb_printf("%0?p %-15s %s\n", addr, fsname, buf); if (!opt_v) return (DCMD_OK); /* * Print 'resource' string; this shows what we're mounted upon. */ if (mdb_read_refstr((uintptr_t)vfs.vfs_resource, buf, MAXPATHLEN) <= 0) strcpy(buf, "??"); mdb_printf("%?s %s\n", "R:", buf); /* * Print mount options array; it sucks to be a mimic, but we copy * the same logic as in mntvnops.c for adding zone= tags, and we * don't bother with the obsolete dev= option. */ size = vfs.vfs_mntopts.mo_count * sizeof (mntopt_t); mntopts = mdb_alloc(size, UM_SLEEP | UM_GC); if (mdb_vread(mntopts, size, (uintptr_t)vfs.vfs_mntopts.mo_list) == -1) { mdb_warn("failed to read mntopts %p", vfs.vfs_mntopts.mo_list); return (DCMD_ERR); } for (i = 0; i < vfs.vfs_mntopts.mo_count; i++) { if (mntopts[i].mo_flags & MO_SET) { if (mdb_readstr(opt, sizeof (opt), (uintptr_t)mntopts[i].mo_name) == -1) { mdb_warn("failed to read mntopt name %p", mntopts[i].mo_name); return (DCMD_ERR); } if (first) { mdb_printf("%?s ", "O:"); first = 0; } else { mdb_printf(","); } mdb_printf("%s", opt); if (mntopts[i].mo_flags & MO_HASVALUE) { if (mdb_readstr(opt, sizeof (opt), (uintptr_t)mntopts[i].mo_arg) == -1) { mdb_warn("failed to read mntopt " "value %p", mntopts[i].mo_arg); return (DCMD_ERR); } mdb_printf("=%s", opt); } } } if (mdb_readvar(&global_zone, "global_zone") == -1) { mdb_warn("failed to locate global_zone"); return (DCMD_ERR); } if ((vfs.vfs_zone != NULL) && ((uintptr_t)vfs.vfs_zone != global_zone)) { zone_t z; if (mdb_vread(&z, sizeof (z), (uintptr_t)vfs.vfs_zone) == -1) { mdb_warn("failed to read zone"); return (DCMD_ERR); } /* * zone names are much shorter than MAX_MNTOPT_STR */ if (mdb_readstr(opt, sizeof (opt), (uintptr_t)z.zone_name) == -1) { mdb_warn("failed to read zone name"); return (DCMD_ERR); } if (first) { mdb_printf("%?s ", "O:"); } else { mdb_printf(","); } mdb_printf("zone=%s", opt); } return (DCMD_OK); }
int mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t opts = 0; MI_O mio; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (mdb_getopts(argc, argv, 'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts, 'd', MDB_OPT_SETBITS, MI_DEVICE, &opts, 'm', MDB_OPT_SETBITS, MI_MODULE, &opts, NULL) != argc) return (DCMD_USAGE); if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) { mdb_warn("at most one filter, d for devices or m " "for modules, may be specified\n"); return (DCMD_USAGE); } if ((opts == 0) && (DCMD_HDRSPEC(flags))) { mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n", "MI_O", "Next", "Prev"); } if (mdb_vread(&mio, sizeof (mio), addr) == -1) { mdb_warn("failed to read mi object MI_O at %p", addr); return (DCMD_ERR); } if (opts != 0) { if (mio.mi_o_isdev == B_FALSE) { /* mio is a module */ if (!(opts & MI_MODULE) && (opts & MI_DEVICE)) return (DCMD_OK); } else { /* mio is a device */ if (!(opts & MI_DEVICE) && (opts & MI_MODULE)) return (DCMD_OK); } if (opts & MI_PAYLOAD) mdb_printf("%p\n", addr + sizeof (MI_O)); else mdb_printf("%p\n", addr); return (DCMD_OK); } mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev); if (mio.mi_o_isdev == B_FALSE) mdb_printf("FALSE"); else mdb_printf("TRUE "); mdb_printf(" %0?p\n", mio.mi_o_dev); return (DCMD_OK); }
int sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { const char *optf = NULL; const char *optt = NULL; const char *optp = NULL; int family, type, proto; int filter = 0; struct sonode so; if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc, argv) == -1) { mdb_warn("failed to walk sonode"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_getopts(argc, argv, 'f', MDB_OPT_STR, &optf, 't', MDB_OPT_STR, &optt, 'p', MDB_OPT_STR, &optp, NULL) != argc) return (DCMD_USAGE); if (optf != NULL) { if (strcmp("inet", optf) == 0) family = AF_INET; else if (strcmp("inet6", optf) == 0) family = AF_INET6; else if (strcmp("unix", optf) == 0) family = AF_UNIX; else family = mdb_strtoull(optf); filter = 1; } if (optt != NULL) { if (strcmp("stream", optt) == 0) type = SOCK_STREAM; else if (strcmp("dgram", optt) == 0) type = SOCK_DGRAM; else if (strcmp("raw", optt) == 0) type = SOCK_RAW; else type = mdb_strtoull(optt); filter = 1; } if (optp != NULL) { proto = mdb_strtoull(optp); filter = 1; } if (DCMD_HDRSPEC(flags) && !filter) { mdb_printf("%<u>%-?s Family Type Proto State Mode Flag " "AccessVP%</u>\n", "Sonode:"); } if (mdb_vread(&so, sizeof (so), addr) == -1) { mdb_warn("failed to read sonode at %p", addr); return (DCMD_ERR); } if ((optf != NULL) && (so.so_family != family)) return (DCMD_OK); if ((optt != NULL) && (so.so_type != type)) return (DCMD_OK); if ((optp != NULL) && (so.so_protocol != proto)) return (DCMD_OK); if (filter) { mdb_printf("%0?p\n", addr); return (DCMD_OK); } mdb_printf("%0?p ", addr); switch (so.so_family) { case AF_UNIX: mdb_printf("unix "); break; case AF_INET: mdb_printf("inet "); break; case AF_INET6: mdb_printf("inet6 "); break; default: mdb_printf("%6hi", so.so_family); } switch (so.so_type) { case SOCK_STREAM: mdb_printf(" strm"); break; case SOCK_DGRAM: mdb_printf(" dgrm"); break; case SOCK_RAW: mdb_printf(" raw "); break; default: mdb_printf(" %4hi", so.so_type); } mdb_printf(" %5hi %05x %04x %04hx\n", so.so_protocol, so.so_state, so.so_mode, so.so_flag); return (DCMD_OK); }
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); }
/* * Dump a UHCI QH (queue head). * -b walk/dump the chian of QHs starting with the one specified. * -d also dump the chain of TDs starting with the one specified. */ int uhci_qh(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t breadth_flag = FALSE, depth_flag = FALSE; uhci_state_t uhci_state, *uhcip = &uhci_state; queue_head_t qh; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (addr & ~QH_LINK_PTR_MASK) { mdb_warn("address must be on a 16-byte boundary.\n"); return (DCMD_ERR); } if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &breadth_flag, 'd', MDB_OPT_SETBITS, TRUE, &depth_flag, NULL) != argc) { return (DCMD_USAGE); } if (breadth_flag) { uint_t new_argc = 0; mdb_arg_t new_argv[1]; if (depth_flag) { new_argc = 1; new_argv[0].a_type = MDB_TYPE_STRING; new_argv[0].a_un.a_str = "-d"; } if ((mdb_pwalk_dcmd("uhci_qh", "uhci_qh", new_argc, new_argv, addr)) != 0) { mdb_warn("failed to walk 'uhci_qh'"); return (DCMD_ERR); } return (DCMD_OK); } if (find_uhci_statep((void *)addr, UHCI_QH, uhcip) != 1) { mdb_warn("failed to find uhci_statep"); return (DCMD_ERR); } if (mdb_vread(&qh, sizeof (qh), addr) != sizeof (qh)) { mdb_warn("failed to read qh at vaddr %p", addr); return (DCMD_ERR); } mdb_printf("\n UHCI qh struct at (vaddr) %08x:\n", addr); if (!(qh.link_ptr & HC_END_OF_LIST) && qh.link_ptr != NULL) { mdb_printf(" link_ptr (paddr) : %08x " "(vaddr) : %p\n", qh.link_ptr, /* Note: uhcip needed by QH_VADDR macro */ QH_VADDR(qh.link_ptr & QH_LINK_PTR_MASK)); } else { mdb_printf( " link_ptr (paddr) : %08x\n", qh.link_ptr); } if (!(qh.element_ptr & HC_END_OF_LIST) && qh.element_ptr != NULL) { mdb_printf(" element_ptr (paddr) : %08x " "(vaddr) : %p\n", qh.element_ptr, /* Note: uhcip needed by TD_VADDR macro */ TD_VADDR(qh.element_ptr & QH_LINK_PTR_MASK)); } else { mdb_printf( " element_ptr (paddr) : %08x\n", qh.element_ptr); } mdb_printf(" node : %04x " "flag : %04x\n", qh.node, qh.qh_flag); mdb_printf(" prev_qh : %?p " "td_tailp : %?p\n", qh.prev_qh, qh.td_tailp); mdb_printf(" bulk_xfer_isoc_info : %?p\n", qh.bulk_xfer_info); if (qh.link_ptr == NULL) { mdb_printf(" --> Link pointer = NULL\n"); return (DCMD_ERR); } else { /* Inform user if next link is a TD or QH. */ if (qh.link_ptr & HC_END_OF_LIST) { mdb_printf(" " "--> Link pointer invalid (terminate bit set).\n"); } else { if ((qh.link_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD) { mdb_printf(" " "--> Link pointer points to a QH.\n"); } else { /* Should never happen. */ mdb_warn(" " "--> Link pointer points to a TD.\n"); return (DCMD_ERR); } } } if (qh.element_ptr == NULL) { mdb_printf(" element_ptr = NULL\n"); return (DCMD_ERR); } else { /* Inform user if next element is a TD or QH. */ if (qh.element_ptr & HC_END_OF_LIST) { mdb_printf(" " "-->Element pointer invalid (terminate bit set)." "\n"); return (DCMD_OK); } else { if ((qh.element_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD) { mdb_printf(" " "--> Element pointer points to a QH.\n"); /* Should never happen in UHCI implementation */ return (DCMD_ERR); } else { mdb_printf(" " "--> Element pointer points to a TD.\n"); } } } /* * If the user specified the -d (depth) option, * dump all TDs linked to this TD via the element_ptr. */ if (depth_flag) { /* Traverse and display all the TDs in the chain */ if (mdb_pwalk_dcmd("uhci_td", "uhci_td", argc, argv, (uintptr_t)(TD_VADDR(qh.element_ptr & QH_LINK_PTR_MASK))) == -1) { mdb_warn("failed to walk 'uhci_td'"); return (DCMD_ERR); } } return (DCMD_OK); }
/* * Dump a UHCI TD (transaction descriptor); * or (-d) the chain of TDs starting with the one specified. */ int uhci_td(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t depth_flag = FALSE; uhci_state_t uhci_state, *uhcip = &uhci_state; uhci_td_t td; if (!(flags & DCMD_ADDRSPEC)) return (DCMD_USAGE); if (addr & ~QH_LINK_PTR_MASK) { mdb_warn("address must be on a 16-byte boundary.\n"); return (DCMD_ERR); } if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, TRUE, &depth_flag, NULL) != argc) { return (DCMD_USAGE); } if (depth_flag) { if (mdb_pwalk_dcmd("uhci_td", "uhci_td", 0, NULL, addr) == -1) { mdb_warn("failed to walk 'uhci_td'"); return (DCMD_ERR); } return (DCMD_OK); } if (find_uhci_statep((void *)addr, UHCI_TD, uhcip) != 1) { mdb_warn("failed to find uhci_statep"); return (DCMD_ERR); } if (mdb_vread(&td, sizeof (td), addr) != sizeof (td)) { mdb_warn("failed to read td at vaddr %p", addr); return (DCMD_ERR); } mdb_printf("\n UHCI td struct at (vaddr) %08x:\n", addr); if (!(td.link_ptr & HC_END_OF_LIST) && td.link_ptr != NULL) { mdb_printf(" link_ptr (paddr) : %-8x " "(vaddr) : %p\n", td.link_ptr, /* Note: uhcip needed by TD_VADDR macro */ TD_VADDR(td.link_ptr & QH_LINK_PTR_MASK)); } else { mdb_printf(" link_ptr (paddr) : %-8x\n", td.link_ptr); } mdb_printf(" td_dword2 : %08x\n", td.dw2); mdb_printf(" td_dword3 : %08x\n", td.dw3); mdb_printf(" buffer_address : %08x\n", td.buffer_address); mdb_printf(" qh_td_prev : %?p " "tw_td_next : %?p\n", td.qh_td_prev, td.tw_td_next); mdb_printf(" outst_td_prev : %?p " "outst_td_next : %?p\n", td.outst_td_prev, td.outst_td_next); mdb_printf(" tw : %?p " "flag : %02x\n", td.tw, td.flag); mdb_printf(" isoc_next : %?p " "isoc_prev : %0x\n", td.isoc_next, td.isoc_prev); mdb_printf(" isoc_pkt_index : %0x " "startingframe: %0x\n", td.isoc_pkt_index, td.starting_frame); if (td.link_ptr == NULL) { mdb_printf(" --> Link pointer = NULL\n"); return (DCMD_ERR); } else { /* Inform user if link is to a TD or QH. */ if (td.link_ptr & HC_END_OF_LIST) { mdb_printf(" " "--> Link pointer invalid (terminate bit set).\n"); } else { if ((td.link_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD) { mdb_printf(" " "--> Link pointer points to a QH.\n"); } else { mdb_printf(" " "--> Link pointer points to a TD.\n"); } } } return (DCMD_OK); }
static int fmd_xprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t opt_s = FALSE, opt_l = FALSE, opt_r = FALSE, opt_u = FALSE; fmd_xprt_impl_t xi; if (mdb_getopts(argc, argv, 'l', MDB_OPT_SETBITS, TRUE, &opt_l, 'r', MDB_OPT_SETBITS, TRUE, &opt_r, 's', MDB_OPT_SETBITS, TRUE, &opt_s, 'u', MDB_OPT_SETBITS, TRUE, &opt_u, NULL) != argc) return (DCMD_USAGE); if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk_dcmd("fmd_xprt", "fmd_xprt", argc, argv) != 0) { mdb_warn("failed to walk fmd_xprt"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_vread(&xi, sizeof (xi), addr) != sizeof (xi)) { mdb_warn("failed to read fmd_xprt at %p", addr); return (DCMD_ERR); } if (DCMD_HDRSPEC(flags)) { mdb_printf("%<u>%-8s %-4s %-4s %-5s %s%</u>\n", "ADDR", "ID", "VERS", "FLAGS", "STATE"); } mdb_printf("%-8p %-4d %-4u %-5x %a\n", addr, xi.xi_id, xi.xi_version, xi.xi_flags, xi.xi_state); if (opt_l | opt_s) { (void) mdb_inc_indent(4); mdb_printf("Local subscriptions requested by peer:\n"); mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, addr + OFFSETOF(fmd_xprt_impl_t, xi_lsub)); (void) mdb_dec_indent(4); } if (opt_r | opt_s) { (void) mdb_inc_indent(4); mdb_printf("Remote subscriptions requested of peer:\n"); mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, addr + OFFSETOF(fmd_xprt_impl_t, xi_rsub)); (void) mdb_dec_indent(4); } if (opt_u | opt_s) { (void) mdb_inc_indent(4); mdb_printf("Pending unsubscription acknowledgements:\n"); mdb_printf("%<u>%-8s %-4s %s%</u>\n", "ADDR", "REFS", "CLASS"); (void) mdb_pwalk("fmd_xprt_class", fmd_xprt_class, &xi, addr + OFFSETOF(fmd_xprt_impl_t, xi_usub)); (void) mdb_dec_indent(4); } return (DCMD_OK); }
static int request_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { request_log_entry_t cur; hrtime_t dur; hrtime_t dursec; hrtime_t durnsec; char durstr[20]; char stampstr[20]; char requstr[30]; char respstr[30]; char typestr[30]; uintptr_t node = 0; uintptr_t client = 0; uint64_t clientid = 0; int idx; int opt_v = FALSE; /* verbose */ if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk_dcmd("configd_log", "configd_log", argc, argv) == -1) { mdb_warn("can't walk 'configd_log'"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_getopts(argc, argv, 'c', MDB_OPT_UINTPTR, &client, 'i', MDB_OPT_UINT64, &clientid, 'n', MDB_OPT_UINTPTR, &node, 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) return (DCMD_USAGE); if (DCMD_HDRSPEC(flags)) { mdb_printf("%<u>%-?s %-4s %-14s %9s %-22s %-17s\n%</u>", "ADDR", "THRD", "START", "DURATION", "REQUEST", "RESPONSE"); } if (mdb_vread(&cur, sizeof (cur), addr) == -1) { mdb_warn("couldn't read log entry at %p", addr); return (DCMD_ERR); } /* * apply filters, if any. */ if (clientid != 0 && clientid != cur.rl_clientid) return (DCMD_OK); if (client != 0 && client != (uintptr_t)cur.rl_client) return (DCMD_OK); if (node != 0) { for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) { if ((uintptr_t)cur.rl_ptrs[idx].rlp_data == node) { node = 0; /* found it */ break; } } if (node != 0) return (DCMD_OK); } enum_lookup(requstr, sizeof (requstr), request_enum, cur.rl_request, "REP_PROTOCOL_", ""); if (cur.rl_end != 0) { enum_lookup(respstr, sizeof (respstr), response_enum, cur.rl_response, "REP_PROTOCOL_", "FAIL_"); dur = cur.rl_end - cur.rl_start; dursec = dur / NANOSEC; durnsec = dur % NANOSEC; if (dursec <= 9) mdb_snprintf(durstr, sizeof (durstr), "%lld.%06lld", dursec, durnsec / (NANOSEC / MICROSEC)); else if (dursec <= 9999) mdb_snprintf(durstr, sizeof (durstr), "%lld.%03lld", dursec, NSEC2MSEC(durnsec)); else mdb_snprintf(durstr, sizeof (durstr), "%lld", dursec); } else { (void) strcpy(durstr, "-"); (void) strcpy(respstr, "-"); } if (max_time_seen != 0 && max_time_seen >= cur.rl_start) { dur = max_time_seen - cur.rl_start; dursec = dur / NANOSEC; durnsec = dur % NANOSEC; if (dursec <= 99ULL) mdb_snprintf(stampstr, sizeof (stampstr), "-%lld.%09lld", dursec, durnsec); else if (dursec <= 99999ULL) mdb_snprintf(stampstr, sizeof (stampstr), "-%lld.%06lld", dursec, durnsec / (NANOSEC / MICROSEC)); else if (dursec <= 99999999ULL) mdb_snprintf(stampstr, sizeof (stampstr), "-%lld.%03lld", dursec, NSEC2MSEC(durnsec)); else mdb_snprintf(stampstr, sizeof (stampstr), "-%lld", dursec); } else { (void) strcpy(stampstr, "-"); } mdb_printf("%0?x %4d T%13s %9s %-22s %-17s\n", addr, cur.rl_tid, stampstr, durstr, requstr, respstr); if (opt_v) { mdb_printf("\tclient: %?p (%d)\tptrs: %d\tstamp: %llx\n", cur.rl_client, cur.rl_clientid, cur.rl_num_ptrs, cur.rl_start); for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) { enum_lookup(typestr, sizeof (typestr), ptr_type_enum, cur.rl_ptrs[idx].rlp_type, "RC_PTR_TYPE_", ""); mdb_printf("\t\t%-7s %5d %?p %?p\n", typestr, cur.rl_ptrs[idx].rlp_id, cur.rl_ptrs[idx].rlp_ptr, cur.rl_ptrs[idx].rlp_data); } mdb_printf("\n"); } return (DCMD_OK); }
/*ARGSUSED*/ int netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t opts = 0; const char *optf = NULL; const char *optP = NULL; netstat_cb_data_t *cbdata; int status; int af = 0; if (mdb_getopts(argc, argv, 'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts, 'f', MDB_OPT_STR, &optf, 'P', MDB_OPT_STR, &optP, 'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts, 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts, NULL) != argc) return (DCMD_USAGE); if (optP != NULL) { if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0) && (strcmp("icmp", optP) != 0)) return (DCMD_USAGE); if (opts & NETSTAT_ROUTE) return (DCMD_USAGE); } if (optf == NULL) opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX; else if (strcmp("inet", optf) == 0) opts |= NETSTAT_V4; else if (strcmp("inet6", optf) == 0) opts |= NETSTAT_V6; else if (strcmp("unix", optf) == 0) opts |= NETSTAT_UNIX; else return (DCMD_USAGE); if (opts & NETSTAT_ROUTE) { if (!(opts & (NETSTAT_V4|NETSTAT_V6))) return (DCMD_USAGE); if (opts & NETSTAT_V4) { opts |= NETSTAT_FIRST; if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) { mdb_warn("failed to walk ip`ire"); return (DCMD_ERR); } } if (opts & NETSTAT_V6) { opts |= NETSTAT_FIRST; if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) { mdb_warn("failed to walk ip`ire"); return (DCMD_ERR); } } return (DCMD_OK); } if ((opts & NETSTAT_UNIX) && (optP == NULL)) { /* Print Unix Domain Sockets */ mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n", "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr", "Remote Addr", "Zone"); if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) { mdb_warn("failed to walk genunix`sonode"); return (DCMD_ERR); } if (!(opts & (NETSTAT_V4 | NETSTAT_V6))) return (DCMD_OK); } cbdata = mdb_alloc(sizeof (netstat_cb_data_t), UM_SLEEP); cbdata->opts = opts; if ((optf != NULL) && (opts & NETSTAT_V4)) af = AF_INET; else if ((optf != NULL) && (opts & NETSTAT_V6)) af = AF_INET6; cbdata->af = af; if ((optP == NULL) || (strcmp("tcp", optP) == 0)) { status = netstat_print_common("tcp_conn_cache", IPPROTO_TCP, netstat_tcp_cb, cbdata); if (status != DCMD_OK) goto out; } if ((optP == NULL) || (strcmp("udp", optP) == 0)) { status = netstat_print_common("udp_conn_cache", IPPROTO_UDP, netstat_udp_cb, cbdata); if (status != DCMD_OK) goto out; } if ((optP == NULL) || (strcmp("icmp", optP) == 0)) { status = netstat_print_common("rawip_conn_cache", IPPROTO_ICMP, netstat_icmp_cb, cbdata); if (status != DCMD_OK) goto out; } out: mdb_free(cbdata, sizeof (netstat_cb_data_t)); return (status); }