xref: /illumos-gate/usr/src/cmd/mdb/common/modules/genunix/tsol.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
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