/* * 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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * In order to implement walk iteration variables (that is, ::walk walk varname) * we need to keep track of the active walk variables as the pipeline is * processed. Each variable is tracked using a VCB (Variable Control Block) * that keeps a pointer to the variable in the MDB variable hash table, as * well as an addrvec (array of values) and parent pointer. Each command in * the pipeline keeps its own list of VCBs, and these are inherited from left * to right in the pipeline. The diagram shows an example pipeline and the * contents of c_addrv and VCBs at each stage: * * > ::walk proc p | ::map .+1 | ::eval ' ::walk proc p | ::walk proc v | ::eval " #include #include #include #include mdb_vcb_t * mdb_vcb_create(mdb_var_t *v) { mdb_vcb_t *vcb = mdb_zalloc(sizeof (mdb_vcb_t), UM_SLEEP); vcb->vc_var = v; return (vcb); } void mdb_vcb_destroy(mdb_vcb_t *vcb) { mdb_dprintf(MDB_DBG_DSTK, "delete vcb %p (%s)\n", (void *)vcb, mdb_nv_get_name(vcb->vc_var)); mdb_addrvec_destroy(&vcb->vc_addrv); mdb_free(vcb, sizeof (mdb_vcb_t)); } void mdb_vcb_propagate(mdb_vcb_t *vcb) { while (vcb != NULL) { mdb_addrvec_t *adp = &vcb->vc_addrv; ASSERT(vcb->vc_adnext < adp->ad_nelems); mdb_nv_set_value(vcb->vc_var, adp->ad_data[vcb->vc_adnext++]); vcb = vcb->vc_link; } } void mdb_vcb_purge(mdb_vcb_t *vcb) { while (vcb != NULL) { mdb_vcb_t *n = vcb->vc_link; mdb_vcb_destroy(vcb); vcb = n; } } void mdb_vcb_inherit(mdb_cmd_t *src, mdb_cmd_t *dst) { mdb_vcb_t *vc1, *vc2; for (vc1 = src->c_vcbs; vc1 != NULL; vc1 = vc1->vc_link) { vc2 = mdb_vcb_create(vc1->vc_var); vc2->vc_parent = vc1; vc2->vc_link = dst->c_vcbs; dst->c_vcbs = vc2; } } void mdb_vcb_insert(mdb_vcb_t *vcb, mdb_frame_t *fp) { if (fp->f_pcmd != NULL) { mdb_cmd_t *cp = fp->f_pcmd; mdb_dprintf(MDB_DBG_DSTK, "insert vcb %p (%s)\n", (void *)vcb, mdb_nv_get_name(vcb->vc_var)); ASSERT(vcb->vc_link == NULL); vcb->vc_link = cp->c_vcbs; cp->c_vcbs = vcb; } } void mdb_vcb_update(struct mdb_frame *fp, uintptr_t value) { mdb_vcb_t *vcb; for (vcb = fp->f_pcmd->c_vcbs; vcb != NULL; vcb = vcb->vc_link) { if (vcb->vc_parent != NULL) { mdb_addrvec_t *adp = &vcb->vc_parent->vc_addrv; adp->ad_ndx = vcb->vc_parent->vc_adnext - 1; ASSERT(adp->ad_ndx < adp->ad_nelems); value = adp->ad_data[adp->ad_ndx++]; } mdb_addrvec_unshift(&vcb->vc_addrv, value); } } mdb_vcb_t * mdb_vcb_find(mdb_var_t *var, mdb_frame_t *fp) { mdb_vcb_t *vcb; if (fp->f_pcmd != NULL) { vcb = fp->f_pcmd->c_vcbs; while (vcb != NULL) { if (vcb->vc_var == var) return (vcb); vcb = vcb->vc_link; } } return (NULL); }