stevel@tonic-gate | 7c478bd | 2005-06-14 00:00:00 -0700 | [diff] [blame] | 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 | } |