1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Active walks are tracked using a WCB (Walk Control Block), which is a simple 31 * data structure that contains the mdb_walk_state_t passed to the various 32 * walker functions for this particular walk, as well as links to other walk 33 * layers if this is a layered walk. The control block is kept in a list 34 * associated with the MDB frame, so that we can clean up all the walks and 35 * call their respective fini routines at the end of command processing. 36 */ 37 38 #include <mdb/mdb_module.h> 39 #include <mdb/mdb_modapi.h> 40 #include <mdb/mdb_debug.h> 41 #include <mdb/mdb_frame.h> 42 #include <mdb/mdb_err.h> 43 #include <mdb/mdb_wcb.h> 44 #include <mdb/mdb.h> 45 46 mdb_wcb_t * 47 mdb_wcb_from_state(mdb_walk_state_t *wsp) 48 { 49 /* 50 * The walk state passed to a walker sits at the start of the 51 * walk control block, so we can ask the walker to pass this 52 * back to us and quickly obtain the control block: 53 */ 54 mdb_wcb_t *wcb = (mdb_wcb_t *)wsp; 55 56 if (wcb->w_buftag != WCB_TAG_ACTIVE && wcb->w_buftag != WCB_TAG_INITIAL) 57 fail("walk state %p is corrupt or not active\n", (void *)wcb); 58 59 return (wcb); 60 } 61 62 mdb_wcb_t * 63 mdb_wcb_create(mdb_iwalker_t *iwp, mdb_walk_cb_t cb, void *data, uintptr_t addr) 64 { 65 mdb_wcb_t *wcb = mdb_zalloc(sizeof (mdb_wcb_t), UM_SLEEP); 66 67 wcb->w_buftag = WCB_TAG_INITIAL; 68 wcb->w_walker = iwp; 69 70 wcb->w_state.walk_callback = cb; 71 wcb->w_state.walk_cbdata = data; 72 wcb->w_state.walk_addr = addr; 73 wcb->w_state.walk_arg = iwp->iwlk_init_arg; 74 75 return (wcb); 76 } 77 78 void 79 mdb_wcb_destroy(mdb_wcb_t *wcb) 80 { 81 mdb_wcb_t *p, *q; 82 83 for (p = wcb->w_lyr_head; p != NULL; p = q) { 84 q = wcb->w_lyr_link; 85 mdb_wcb_destroy(p); 86 } 87 88 if (wcb->w_inited) 89 wcb->w_walker->iwlk_fini(&wcb->w_state); 90 91 mdb_free(wcb, sizeof (mdb_wcb_t)); 92 } 93 94 void 95 mdb_wcb_insert(mdb_wcb_t *wcb, mdb_frame_t *fp) 96 { 97 mdb_dprintf(MDB_DBG_WALK, "activate walk %s`%s wcb %p\n", 98 wcb->w_walker->iwlk_modp->mod_name, 99 wcb->w_walker->iwlk_name, (void *)wcb); 100 101 wcb->w_buftag = WCB_TAG_ACTIVE; 102 wcb->w_link = fp->f_wcbs; 103 fp->f_wcbs = wcb; 104 } 105 106 void 107 mdb_wcb_delete(mdb_wcb_t *wcb, mdb_frame_t *fp) 108 { 109 mdb_wcb_t **pp = &fp->f_wcbs; 110 mdb_wcb_t *w; 111 112 mdb_dprintf(MDB_DBG_WALK, "deactivate walk %s`%s wcb %p\n", 113 wcb->w_walker->iwlk_modp->mod_name, 114 wcb->w_walker->iwlk_name, (void *)wcb); 115 116 for (w = fp->f_wcbs; w != NULL; pp = &w->w_link, w = w->w_link) { 117 if (w == wcb) { 118 w->w_buftag = WCB_TAG_PASSIVE; 119 *pp = w->w_link; 120 return; 121 } 122 } 123 124 fail("attempted to remove wcb not on list: %p\n", (void *)wcb); 125 } 126 127 void 128 mdb_wcb_purge(mdb_wcb_t **wcbpp) 129 { 130 mdb_wcb_t *n, *wcb = *wcbpp; 131 132 while (wcb != NULL) { 133 mdb_dprintf(MDB_DBG_WALK, "purge walk %s`%s wcb %p\n", 134 wcb->w_walker->iwlk_modp->mod_name, 135 wcb->w_walker->iwlk_name, (void *)wcb); 136 137 n = wcb->w_link; 138 mdb_wcb_destroy(wcb); 139 wcb = n; 140 } 141 142 *wcbpp = NULL; 143 } 144