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 /* 28 * Active walks are tracked using a WCB (Walk Control Block), which is a simple 29 * data structure that contains the mdb_walk_state_t passed to the various 30 * walker functions for this particular walk, as well as links to other walk 31 * layers if this is a layered walk. The control block is kept in a list 32 * associated with the MDB frame, so that we can clean up all the walks and 33 * call their respective fini routines at the end of command processing. 34 */ 35 36 #include <mdb/mdb_module.h> 37 #include <mdb/mdb_modapi.h> 38 #include <mdb/mdb_debug.h> 39 #include <mdb/mdb_frame.h> 40 #include <mdb/mdb_err.h> 41 #include <mdb/mdb_wcb.h> 42 #include <mdb/mdb.h> 43 44 mdb_wcb_t * 45 mdb_wcb_from_state(mdb_walk_state_t *wsp) 46 { 47 /* 48 * The walk state passed to a walker sits at the start of the 49 * walk control block, so we can ask the walker to pass this 50 * back to us and quickly obtain the control block: 51 */ 52 mdb_wcb_t *wcb = (mdb_wcb_t *)wsp; 53 54 if (wcb->w_buftag != WCB_TAG_ACTIVE && wcb->w_buftag != WCB_TAG_INITIAL) 55 fail("walk state %p is corrupt or not active\n", (void *)wcb); 56 57 return (wcb); 58 } 59 60 mdb_wcb_t * 61 mdb_wcb_create(mdb_iwalker_t *iwp, mdb_walk_cb_t cb, void *data, uintptr_t addr) 62 { 63 mdb_wcb_t *wcb = mdb_zalloc(sizeof (mdb_wcb_t), UM_SLEEP); 64 65 wcb->w_buftag = WCB_TAG_INITIAL; 66 wcb->w_walker = iwp; 67 68 wcb->w_state.walk_callback = cb; 69 wcb->w_state.walk_cbdata = data; 70 wcb->w_state.walk_addr = addr; 71 wcb->w_state.walk_arg = iwp->iwlk_init_arg; 72 73 return (wcb); 74 } 75 76 void 77 mdb_wcb_destroy(mdb_wcb_t *wcb) 78 { 79 mdb_wcb_t *p, *q; 80 81 for (p = wcb->w_lyr_head; p != NULL; p = q) { 82 q = wcb->w_lyr_link; 83 mdb_wcb_destroy(p); 84 } 85 86 if (wcb->w_inited) 87 wcb->w_walker->iwlk_fini(&wcb->w_state); 88 89 mdb_free(wcb, sizeof (mdb_wcb_t)); 90 } 91 92 void 93 mdb_wcb_insert(mdb_wcb_t *wcb, mdb_frame_t *fp) 94 { 95 mdb_dprintf(MDB_DBG_WALK, "activate walk %s`%s wcb %p\n", 96 wcb->w_walker->iwlk_modp->mod_name, 97 wcb->w_walker->iwlk_name, (void *)wcb); 98 99 wcb->w_buftag = WCB_TAG_ACTIVE; 100 wcb->w_link = fp->f_wcbs; 101 fp->f_wcbs = wcb; 102 } 103 104 void 105 mdb_wcb_delete(mdb_wcb_t *wcb, mdb_frame_t *fp) 106 { 107 mdb_wcb_t **pp = &fp->f_wcbs; 108 mdb_wcb_t *w; 109 110 mdb_dprintf(MDB_DBG_WALK, "deactivate walk %s`%s wcb %p\n", 111 wcb->w_walker->iwlk_modp->mod_name, 112 wcb->w_walker->iwlk_name, (void *)wcb); 113 114 for (w = fp->f_wcbs; w != NULL; pp = &w->w_link, w = w->w_link) { 115 if (w == wcb) { 116 w->w_buftag = WCB_TAG_PASSIVE; 117 *pp = w->w_link; 118 return; 119 } 120 } 121 122 fail("attempted to remove wcb not on list: %p\n", (void *)wcb); 123 } 124 125 void 126 mdb_wcb_purge(mdb_wcb_t **wcbpp) 127 { 128 mdb_wcb_t *n, *wcb = *wcbpp; 129 130 while (wcb != NULL) { 131 mdb_dprintf(MDB_DBG_WALK, "purge walk %s`%s wcb %p\n", 132 wcb->w_walker->iwlk_modp->mod_name, 133 wcb->w_walker->iwlk_name, (void *)wcb); 134 135 n = wcb->w_link; 136 mdb_wcb_destroy(wcb); 137 wcb = n; 138 } 139 140 *wcbpp = NULL; 141 } 142