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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/tsol/tndb.h> 30 #include <sys/modhash_impl.h> 31 32 #include <mdb/mdb_modapi.h> 33 #include <mdb/mdb_ks.h> 34 35 #include "tsol.h" 36 #include "modhash.h" 37 38 /* ****************** tnrh ****************** */ 39 40 typedef struct tnrh_walk_s { 41 tnrhc_hash_t **hptr; 42 int idx; 43 tnrhc_hash_t *tnrhc_table[TSOL_MASK_TABLE_SIZE]; 44 tnrhc_hash_t *tnrhc_table_v6[TSOL_MASK_TABLE_SIZE_V6]; 45 } tnrh_walk_t; 46 47 /* 48 * Free the mdb storage pointed to by the given per-prefix table. 49 */ 50 static void 51 free_table(tnrhc_hash_t **table, int ntable) 52 { 53 while (--ntable >= 0) { 54 if (*table != NULL) 55 mdb_free(*table, TNRHC_SIZE * sizeof (**table)); 56 table++; 57 } 58 } 59 60 /* 61 * Read in a list of per-prefix-length hash tables. Allocate storage for the 62 * hashes that are present. On successful return, the table will contain 63 * pointers to mdb-resident storage, not kernel addresses. On failure, the 64 * contents will not point to any mdb storage. 65 */ 66 static int 67 read_table(const char *symname, tnrhc_hash_t **table, int ntable) 68 { 69 GElf_Sym tnrhc_hash; 70 tnrhc_hash_t **hp; 71 uintptr_t addr; 72 73 if (mdb_lookup_by_name(symname, &tnrhc_hash) == -1) { 74 mdb_warn("failed to read %s", symname); 75 return (-1); 76 } 77 if (mdb_vread(table, ntable * sizeof (*table), 78 tnrhc_hash.st_value) == -1) { 79 mdb_warn("can't read %s at %p", symname, tnrhc_hash.st_value); 80 return (-1); 81 } 82 for (hp = table; hp < table + ntable; hp++) { 83 if ((addr = (uintptr_t)*hp) != 0) { 84 *hp = mdb_alloc(TNRHC_SIZE * sizeof (**hp), UM_SLEEP); 85 if (mdb_vread(*hp, TNRHC_SIZE * sizeof (**hp), 86 addr) == -1) { 87 mdb_warn("can't read %s[%d] at %p", symname, 88 hp - table, addr); 89 free_table(table, (hp - table) + 1); 90 return (-1); 91 } 92 } 93 } 94 return (0); 95 } 96 97 int 98 tnrh_walk_init(mdb_walk_state_t *wsp) 99 { 100 tnrh_walk_t *twp; 101 102 twp = mdb_alloc(sizeof (*twp), UM_SLEEP); 103 104 if (read_table("tnrhc_table", twp->tnrhc_table, 105 TSOL_MASK_TABLE_SIZE) == -1) { 106 mdb_free(twp, sizeof (*twp)); 107 return (WALK_ERR); 108 } 109 if (read_table("tnrhc_table_v6", twp->tnrhc_table_v6, 110 TSOL_MASK_TABLE_SIZE_V6) == -1) { 111 free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE); 112 mdb_free(twp, sizeof (*twp)); 113 return (WALK_ERR); 114 } 115 116 twp->hptr = twp->tnrhc_table; 117 twp->idx = 0; 118 wsp->walk_addr = 0; 119 wsp->walk_data = twp; 120 121 return (WALK_NEXT); 122 } 123 124 int 125 tnrh_walk_step(mdb_walk_state_t *wsp) 126 { 127 tnrh_walk_t *twp = wsp->walk_data; 128 tsol_tnrhc_t tnrhc; 129 int status; 130 131 while (wsp->walk_addr == NULL) { 132 if (*twp->hptr == NULL || twp->idx >= TNRHC_SIZE) { 133 twp->hptr++; 134 if (twp->hptr == twp->tnrhc_table + 135 TSOL_MASK_TABLE_SIZE) 136 twp->hptr = twp->tnrhc_table_v6; 137 else if (twp->hptr == twp->tnrhc_table_v6 + 138 TSOL_MASK_TABLE_SIZE_V6) 139 return (WALK_DONE); 140 twp->idx = 0; 141 } else { 142 wsp->walk_addr = (uintptr_t)(*twp->hptr)[twp->idx++]. 143 tnrh_list; 144 } 145 } 146 147 if (mdb_vread(&tnrhc, sizeof (tnrhc), wsp->walk_addr) == -1) { 148 mdb_warn("can't read tsol_tnrhc_t at %p", wsp->walk_addr); 149 return (WALK_ERR); 150 } 151 152 status = wsp->walk_callback(wsp->walk_addr, &tnrhc, 153 wsp->walk_cbdata); 154 155 wsp->walk_addr = (uintptr_t)tnrhc.rhc_next; 156 return (status); 157 } 158 159 void 160 tnrh_walk_fini(mdb_walk_state_t *wsp) 161 { 162 tnrh_walk_t *twp = wsp->walk_data; 163 164 free_table(twp->tnrhc_table, TSOL_MASK_TABLE_SIZE); 165 free_table(twp->tnrhc_table_v6, TSOL_MASK_TABLE_SIZE_V6); 166 mdb_free(twp, sizeof (*twp)); 167 } 168 169 /* ****************** tnrhtp ****************** */ 170 171 typedef struct tnrhtp_walk_data_s { 172 int (*old_callback)(uintptr_t, const void *, void *); 173 void *old_cbdata; 174 } tnrhtp_walk_data_t; 175 176 /* ARGSUSED */ 177 static int 178 tnrhtp_walk_callback(uintptr_t addr, const void *data, void *private) 179 { 180 const struct mod_hash_entry *mhe = data; 181 tnrhtp_walk_data_t *twd = private; 182 tsol_tpc_t tpc; 183 184 if (mdb_vread(&tpc, sizeof (tpc), (uintptr_t)mhe->mhe_val) == -1) { 185 mdb_warn("failed to read tsol_tpc_t at %p", mhe->mhe_val); 186 return (WALK_ERR); 187 } else { 188 return (twd->old_callback((uintptr_t)mhe->mhe_val, &tpc, 189 twd->old_cbdata)); 190 } 191 } 192 193 int 194 tnrhtp_walk_init(mdb_walk_state_t *wsp) 195 { 196 mod_hash_t *tpc_name_hash; 197 198 if (mdb_readvar(&tpc_name_hash, "tpc_name_hash") == -1) { 199 mdb_warn("failed to read tpc_name_hash"); 200 return (WALK_ERR); 201 } 202 203 wsp->walk_addr = (uintptr_t)tpc_name_hash; 204 205 return (modent_walk_init(wsp)); 206 } 207 208 int 209 tnrhtp_walk_step(mdb_walk_state_t *wsp) 210 { 211 tnrhtp_walk_data_t twd; 212 int retv; 213 214 twd.old_callback = wsp->walk_callback; 215 twd.old_cbdata = wsp->walk_cbdata; 216 wsp->walk_callback = tnrhtp_walk_callback; 217 wsp->walk_cbdata = &twd; 218 219 retv = modent_walk_step(wsp); 220 221 wsp->walk_callback = twd.old_callback; 222 wsp->walk_cbdata = twd.old_cbdata; 223 224 return (retv); 225 } 226 227 void 228 tnrhtp_walk_fini(mdb_walk_state_t *wsp) 229 { 230 modent_walk_fini(wsp); 231 } 232