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