/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include static uintptr_t ipp_mod_byid; static uintptr_t ipp_action_byid; static int byid_walk_init(mdb_walk_state_t *); static int byid_walk_step(mdb_walk_state_t *); static void byid_walk_fini(mdb_walk_state_t *); static int action(uintptr_t, uint_t, int, const mdb_arg_t *); static int action_format(uintptr_t, const void *, void *); static int action_dump(uintptr_t, ipp_action_t *, boolean_t); static int action_summary(uintptr_t, ipp_action_t *, boolean_t); static int cfglock(uintptr_t, uint_t, int, const mdb_arg_t *); static int mod(uintptr_t, uint_t, int, const mdb_arg_t *); static int mod_format(uintptr_t, const void *, void *); static int mod_dump(uintptr_t, ipp_mod_t *, boolean_t); static int mod_summary(uintptr_t, ipp_mod_t *, boolean_t); static int cfglock(uintptr_t, uint_t, int, const mdb_arg_t *); static int ippops(uintptr_t, uint_t, int, const mdb_arg_t *); static int packet(uintptr_t, uint_t, int, const mdb_arg_t *); static void dump_classes(uintptr_t, uint_t); static void dump_log(uintptr_t, uint_t); static void aid2aname(ipp_action_id_t, char *); static int ref_walk_init(mdb_walk_state_t *); static int ref_walk_step(mdb_walk_state_t *); static void ref_walk_fini(mdb_walk_state_t *); typedef struct afdata { boolean_t af_banner; uint_t af_flags; } afdata_t; #define AF_VERBOSE 1 typedef struct mfdata { boolean_t mf_banner; uint_t mf_flags; } mfdata_t; #define MF_VERBOSE 1 /* * walker. Skips entries that are NULL. */ static int byid_walk_init( mdb_walk_state_t *wsp) { uintptr_t start; if (mdb_vread(&start, sizeof (uintptr_t), wsp->walk_addr) == -1) { mdb_warn("failed to read from address %p", wsp->walk_addr); return (WALK_ERR); } wsp->walk_addr = start; return (WALK_NEXT); } static int byid_walk_step( mdb_walk_state_t *wsp) { int status; void *ptr; if (mdb_vread(&ptr, sizeof (void *), wsp->walk_addr) == -1) { mdb_warn("failed to read from address %p", wsp->walk_addr); return (WALK_ERR); } if (ptr == (void *)-1) { status = WALK_DONE; } else if (ptr == NULL) { status = WALK_NEXT; } else { status = wsp->walk_callback((uintptr_t)ptr, NULL, wsp->walk_cbdata); } wsp->walk_addr += sizeof (void *); return (status); } /*ARGSUSED*/ static void byid_walk_fini( mdb_walk_state_t *wsp) { } /*ARGSUSED*/ static int action( uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int status; int rc = DCMD_OK; afdata_t *afp; afp = mdb_zalloc(sizeof (afdata_t), UM_SLEEP); if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, AF_VERBOSE, &afp->af_flags, NULL) != argc) return (DCMD_USAGE); if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) afp->af_banner = B_TRUE; if (flags & DCMD_ADDRSPEC) { status = action_format(addr, NULL, afp); rc = (status == WALK_NEXT) ? DCMD_OK : DCMD_ERR; goto cleanup; } if (mdb_pwalk("ipp_byid", action_format, afp, ipp_action_byid) == -1) { mdb_warn("failed to execute ipp_byid walk"); rc = DCMD_ERR; } cleanup: mdb_free(afp, sizeof (afdata_t)); return (rc); } /*ARGSUSED*/ static int action_format( uintptr_t addr, const void *data, void *arg) { afdata_t *afp = (afdata_t *)arg; ipp_action_t *ap; int rc; ap = mdb_alloc(sizeof (ipp_action_t), UM_SLEEP); if (mdb_vread(ap, sizeof (ipp_action_t), addr) == -1) { mdb_warn("failed to read ipp_action_t at %p", addr); rc = WALK_ERR; goto done; } if (afp->af_flags & AF_VERBOSE) rc = action_dump(addr, ap, afp->af_banner); else rc = action_summary(addr, ap, afp->af_banner); afp->af_banner = B_FALSE; done: mdb_free(ap, sizeof (ipp_action_t)); return (rc); } /*ARGSUSED*/ static int action_dump( uintptr_t addr, ipp_action_t *ap, boolean_t banner) { mdb_printf("%?p: %20s = %d\n", addr, "id", ap->ippa_id); if (!ap->ippa_nameless) { mdb_printf("%?s %20s = %s\n", "", "name", ap->ippa_name); } mdb_printf("%?s %20s = 0x%p\n", "", "mod", ap->ippa_mod); mdb_printf("%?s %20s = 0x%p\n", "", "ref", ap->ippa_ref); mdb_printf("%?s %20s = 0x%p\n", "", "refby", ap->ippa_refby); mdb_printf("%?s %20s = 0x%p\n", "", "ptr", ap->ippa_ptr); mdb_printf("%?s %20s = ", "", "state"); switch (ap->ippa_state) { case IPP_ASTATE_PROTO: mdb_printf("%s\n", "PROTO"); break; case IPP_ASTATE_CONFIG_PENDING: mdb_printf("%s\n", "CONFIG_PENDING"); break; case IPP_ASTATE_AVAILABLE: mdb_printf("%s\n", "AVAILABLE"); break; default: mdb_printf("%s\n", ""); break; } mdb_printf("%?s %20s = %d\n", "", "packets", ap->ippa_packets); mdb_printf("%?s %20s = %d\n", "", "hold_count", ap->ippa_hold_count); mdb_printf("%?s %20s = %s\n", "", "destruct_pending", (ap->ippa_destruct_pending) ? "TRUE" : "FALSE"); mdb_printf("%?s %20s = 0x%p\n", "", "lock", addr + ((uintptr_t)ap->ippa_lock - (uintptr_t)ap)); mdb_printf("%?s %20s = 0x%p\n", "", "config_lock", addr + ((uintptr_t)ap->ippa_config_lock - (uintptr_t)ap)); mdb_printf("\n"); return (WALK_NEXT); } static int action_summary( uintptr_t addr, ipp_action_t *ap, boolean_t banner) { ipp_mod_t *imp; uintptr_t ptr; if (banner) mdb_printf("%?s %%20s %5s %20s%\n", "", "NAME", "ID", "MODNAME"); imp = mdb_alloc(sizeof (ipp_mod_t), UM_SLEEP); ptr = (uintptr_t)ap->ippa_mod; if (mdb_vread(imp, sizeof (ipp_mod_t), ptr) == -1) { mdb_warn("failed to read ipp_mod_t at %p", ptr); mdb_free(imp, sizeof (ipp_mod_t)); return (WALK_ERR); } mdb_printf("%?p:%20s %5d %20s\n", addr, ap->ippa_name, ap->ippa_id, imp->ippm_name); mdb_free(imp, sizeof (ipp_mod_t)); return (WALK_NEXT); } /*ARGSUSED*/ static int cfglock( uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { cfglock_t *clp; if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_ERR); clp = mdb_alloc(sizeof (cfglock_t), UM_SLEEP); if (mdb_vread(clp, sizeof (cfglock_t), addr) == -1) { mdb_warn("failed to read cfglock_t at %p", addr); mdb_free(clp, sizeof (cfglock_t)); return (WALK_ERR); } mdb_printf("%?p: %20s = %p\n", addr, "owner", clp->cl_owner); mdb_printf("%?s %20s = %s\n", "", "reader", clp->cl_reader ? "TRUE" : "FALSE"); mdb_printf("%?s %20s = %d\n", "", "writers", clp->cl_writers); mdb_printf("%?s %20s = 0x%p\n", "", "mutex", addr + ((uintptr_t)clp->cl_mutex - (uintptr_t)clp)); mdb_printf("%?s %20s = 0x%p\n", "", "cv", addr + ((uintptr_t)clp->cl_cv - (uintptr_t)clp)); mdb_printf("\n"); mdb_free(clp, sizeof (cfglock_t)); return (DCMD_OK); } /*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 mod_format( uintptr_t addr, const void *data, void *arg) { mfdata_t *mfp = (mfdata_t *)arg; ipp_mod_t *imp; int rc; imp = mdb_alloc(sizeof (ipp_mod_t), UM_SLEEP); if (mdb_vread(imp, sizeof (ipp_mod_t), addr) == -1) { mdb_warn("failed to read ipp_mod_t at %p", addr); rc = WALK_ERR; goto done; } if (mfp->mf_flags & MF_VERBOSE) rc = mod_dump(addr, imp, mfp->mf_banner); else rc = mod_summary(addr, imp, mfp->mf_banner); mfp->mf_banner = B_FALSE; done: mdb_free(imp, sizeof (ipp_mod_t)); return (rc); } /*ARGSUSED*/ static int mod_dump( uintptr_t addr, ipp_mod_t *imp, boolean_t banner) { mdb_printf("%?p: %20s = %d\n", addr, "id", imp->ippm_id); mdb_printf("%?s %20s = %s\n", "", "name", imp->ippm_name); mdb_printf("%?s %20s = 0x%p\n", "", "ops", imp->ippm_ops); mdb_printf("%?s %20s = 0x%p\n", "", "action", imp->ippm_action); mdb_printf("%?s %20s = ", "", "state"); switch (imp->ippm_state) { case IPP_MODSTATE_PROTO: mdb_printf("%s\n", "PROTO"); break; case IPP_MODSTATE_AVAILABLE: mdb_printf("%s\n", "AVAILABLE"); break; default: mdb_printf("%s\n", ""); break; } mdb_printf("%?s %20s = %d\n", "", "hold_count", imp->ippm_hold_count); mdb_printf("%?s %20s = %s\n", "", "destruct_pending", (imp->ippm_destruct_pending) ? "TRUE" : "FALSE"); mdb_printf("%?s %20s = 0x%p\n", "", "lock", addr + ((uintptr_t)imp->ippm_lock - (uintptr_t)imp)); mdb_printf("\n"); return (WALK_NEXT); } static int mod_summary( uintptr_t addr, ipp_mod_t *imp, boolean_t banner) { if (banner) mdb_printf("%?s %%20s %5s%\n", "", "NAME", "ID"); mdb_printf("%?p:%20s %5d\n", addr, imp->ippm_name, imp->ippm_id); return (WALK_NEXT); } /*ARGSUSED*/ static int ippops( uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { ipp_ops_t *ippo; GElf_Sym sym; char buf[MDB_SYM_NAMLEN]; if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_ERR); ippo = mdb_alloc(sizeof (ipp_ops_t), UM_SLEEP); if (mdb_vread(ippo, sizeof (ipp_ops_t), addr) == -1) { mdb_warn("failed to read ipp_ops_t at %p", addr); mdb_free(ippo, sizeof (ipp_ops_t)); return (DCMD_ERR); } mdb_printf("%?p: %20s = %d\n", addr, "rev", ippo->ippo_rev); if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_create, MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0) mdb_printf("%?s %20s = %s\n", "", "action_create", buf); else mdb_printf("%?s %20s = 0x%p\n", "", "action_create", ippo->ippo_action_create); if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_modify, MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0) mdb_printf("%?s %20s = %s\n", "", "action_modify", buf); else mdb_printf("%?s %20s = 0x%p\n", "", "action_modify", ippo->ippo_action_modify); if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_destroy, MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0) mdb_printf("%?s %20s = %s\n", "", "action_destroy", buf); else mdb_printf("%?s %20s = 0x%p\n", "", "action_destroy", ippo->ippo_action_destroy); if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_info, MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0) mdb_printf("%?s %20s = %s\n", "", "action_info", buf); else mdb_printf("%?s %20s = 0x%p\n", "", "action_info", ippo->ippo_action_info); if (mdb_lookup_by_addr((uintptr_t)ippo->ippo_action_invoke, MDB_SYM_EXACT, buf, MDB_SYM_NAMLEN, &sym) == 0) mdb_printf("%?s %20s = %s\n", "", "action_invoke", buf); else mdb_printf("%?s %20s = 0x%p\n", "", "action_invoke", ippo->ippo_action_invoke); mdb_printf("\n"); mdb_free(ippo, sizeof (ipp_ops_t)); return (DCMD_OK); } static int ref_walk_init( mdb_walk_state_t *wsp) { if (wsp->walk_addr == 0) return (WALK_DONE); return (WALK_NEXT); } static int ref_walk_step( mdb_walk_state_t *wsp) { ipp_ref_t *rp; int status; if (wsp->walk_addr == 0) return (WALK_DONE); rp = mdb_alloc(sizeof (ipp_ref_t), UM_SLEEP); if (mdb_vread(rp, sizeof (ipp_ref_t), wsp->walk_addr) == -1) { mdb_warn("failed to read ipp_ref_t at %p", wsp->walk_addr); mdb_free(rp, sizeof (ipp_ref_t)); return (WALK_ERR); } status = wsp->walk_callback((uintptr_t)rp->ippr_ptr, NULL, wsp->walk_cbdata); wsp->walk_addr = (uintptr_t)(rp->ippr_nextp); mdb_free(rp, sizeof (ipp_ref_t)); return (status); } /*ARGSUSED*/ static void ref_walk_fini( mdb_walk_state_t *wsp) { } /*ARGSUSED*/ static int packet( uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { ipp_packet_t *pp; if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_ERR); pp = mdb_alloc(sizeof (ipp_packet_t), UM_SLEEP); if (mdb_vread(pp, sizeof (ipp_packet_t), addr) == -1) { mdb_warn("failed to read ipp_packet_t at %p", addr); mdb_free(pp, sizeof (ipp_packet_t)); return (DCMD_ERR); } mdb_printf("%?p: %20s = 0x%p\n", addr, "data", pp->ippp_data); mdb_printf("%?s %20s = 0x%p\n", "", "private", pp->ippp_private); dump_classes((uintptr_t)pp->ippp_class_array, pp->ippp_class_windex); dump_log((uintptr_t)pp->ippp_log, pp->ippp_log_windex); mdb_free(pp, sizeof (ipp_packet_t)); return (DCMD_OK); } static void dump_classes( uintptr_t ptr, uint_t nelt) { ipp_class_t *array; ipp_class_t *cp = NULL; uint_t i; boolean_t first_time = B_TRUE; char buf[MAXNAMELEN]; array = mdb_alloc(sizeof (ipp_class_t) * nelt, UM_SLEEP); if (mdb_vread(array, sizeof (ipp_class_t) * nelt, ptr) == -1) { mdb_warn("failed to read ipp_class_t array at %p", ptr); return; } for (i = 0; i < nelt; i++) { if (first_time) { mdb_printf("%20s %?s %%15s %15s%\n", "", "classes", "NAME", "ACTION"); first_time = B_FALSE; } cp = &(array[i]); aid2aname(cp->ippc_aid, buf); mdb_printf("%20s %?p: %15s %15s%\n", "", ptr + (i * sizeof (ipp_class_t)), cp->ippc_name, buf); } mdb_free(cp, sizeof (ipp_class_t) * nelt); } static void dump_log( uintptr_t ptr, uint_t nelt) { ipp_log_t *array; ipp_log_t *lp = NULL; uint_t i; boolean_t first_time = B_TRUE; char buf[MAXNAMELEN]; array = mdb_alloc(sizeof (ipp_log_t) * nelt, UM_SLEEP); if (mdb_vread(array, sizeof (ipp_log_t) * nelt, ptr) == -1) { mdb_warn("failed to read ipp_log_t array at %p", ptr); return; } for (i = 0; i < nelt; i++) { if (first_time) { mdb_printf("%20s %?s %%15s %15s%\n", "", "log", "CLASS NAME", "ACTION"); first_time = B_FALSE; } lp = &(array[i]); aid2aname(lp->ippl_aid, buf); mdb_printf("%20s %?p: %15s %15s\n", "", ptr + (i * sizeof (ipp_class_t)), lp->ippl_name, buf); } mdb_free(lp, sizeof (ipp_log_t) * nelt); } static void aid2aname( ipp_action_id_t aid, char *buf) { uintptr_t addr; uintptr_t ptr; ipp_action_t *ap; switch (aid) { case IPP_ACTION_INVAL: strcpy(buf, "invalid"); break; case IPP_ACTION_CONT: strcpy(buf, "continue"); break; case IPP_ACTION_DEFER: strcpy(buf, "defer"); break; case IPP_ACTION_DROP: strcpy(buf, "drop"); break; default: if (mdb_vread(&addr, sizeof (uintptr_t), ipp_action_byid) == -1) { mdb_warn("failed to read from address %p", ipp_action_byid); strcpy(buf, "???"); break; } addr += ((int32_t)aid * sizeof (void *)); if (mdb_vread(&ptr, sizeof (uintptr_t), addr) == -1) { mdb_warn("failed to read from address %p", addr); strcpy(buf, "???"); break; } ap = mdb_alloc(sizeof (ipp_action_t), UM_SLEEP); if (mdb_vread(ap, sizeof (ipp_action_t), ptr) == -1) { mdb_warn("failed to read ipp_action_t at %p", ptr); mdb_free(ap, sizeof (ipp_action_t)); strcpy(buf, "???"); break; } if (ap->ippa_id != aid) { mdb_warn("corrupt action at %p", ptr); mdb_free(ap, sizeof (ipp_action_t)); strcpy(buf, "???"); break; } strcpy(buf, ap->ippa_name); } } static const mdb_dcmd_t dcmds[] = { { "ipp_action", "?[-v]", "display ipp_action structure", action }, { "ipp_mod", "?[-v]", "display ipp_mod structure", mod }, { "cfglock", ":", "display cfglock structure", cfglock }, { "ippops", ":", "display ipp_ops structure", ippops }, { "ipp_packet", ":", "display ipp_packet structure", packet }, { NULL } }; static const mdb_walker_t walkers[] = { { "ipp_byid", "walk byid array", byid_walk_init, byid_walk_step, byid_walk_fini }, { "ipp_ref", "walk reference list", ref_walk_init, ref_walk_step, ref_walk_fini }, { NULL } }; static const mdb_modinfo_t ipp_modinfo = { MDB_API_VERSION, dcmds, walkers }; 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); }