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