xref: /onnv-gate/usr/src/cmd/mdb/common/modules/hook/hook.c (revision 2958:98aa41c076f5)
1*2958Sdr146992 /*
2*2958Sdr146992  * CDDL HEADER START
3*2958Sdr146992  *
4*2958Sdr146992  * The contents of this file are subject to the terms of the
5*2958Sdr146992  * Common Development and Distribution License (the "License").
6*2958Sdr146992  * You may not use this file except in compliance with the License.
7*2958Sdr146992  *
8*2958Sdr146992  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2958Sdr146992  * or http://www.opensolaris.org/os/licensing.
10*2958Sdr146992  * See the License for the specific language governing permissions
11*2958Sdr146992  * and limitations under the License.
12*2958Sdr146992  *
13*2958Sdr146992  * When distributing Covered Code, include this CDDL HEADER in each
14*2958Sdr146992  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2958Sdr146992  * If applicable, add the following below this CDDL HEADER, with the
16*2958Sdr146992  * fields enclosed by brackets "[]" replaced with your own identifying
17*2958Sdr146992  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2958Sdr146992  *
19*2958Sdr146992  * CDDL HEADER END
20*2958Sdr146992  */
21*2958Sdr146992 /*
22*2958Sdr146992  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*2958Sdr146992  * Use is subject to license terms.
24*2958Sdr146992  */
25*2958Sdr146992 
26*2958Sdr146992 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*2958Sdr146992 
28*2958Sdr146992 #include <sys/types.h>
29*2958Sdr146992 #include <sys/rwlock.h>
30*2958Sdr146992 #include <mdb/mdb_modapi.h>
31*2958Sdr146992 #include <sys/queue.h>
32*2958Sdr146992 #include <sys/hook.h>
33*2958Sdr146992 #include <sys/hook_impl.h>
34*2958Sdr146992 
35*2958Sdr146992 #define	MAX_LENGTH 64
36*2958Sdr146992 
37*2958Sdr146992 /*
38*2958Sdr146992  * List pfhooks hook list information.
39*2958Sdr146992  */
40*2958Sdr146992 /*ARGSUSED*/
41*2958Sdr146992 int
42*2958Sdr146992 hooklist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
43*2958Sdr146992 {
44*2958Sdr146992 	hook_event_int_t hr;
45*2958Sdr146992 	hook_int_t hl, *hlp;
46*2958Sdr146992 	char hrstr[MAX_LENGTH];
47*2958Sdr146992 	GElf_Sym sym;
48*2958Sdr146992 	char buf[MDB_SYM_NAMLEN + 1];
49*2958Sdr146992 
50*2958Sdr146992 	if (argc)
51*2958Sdr146992 		return (DCMD_USAGE);
52*2958Sdr146992 
53*2958Sdr146992 	if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)addr) == -1) {
54*2958Sdr146992 		mdb_warn("couldn't read hook register at %p", addr);
55*2958Sdr146992 		return (DCMD_ERR);
56*2958Sdr146992 	}
57*2958Sdr146992 
58*2958Sdr146992 	mdb_printf("%<u>%?s %10s %20s %?s%</u>\n",
59*2958Sdr146992 	    "ADDR", "FLAG", "FUNC", "NAME");
60*2958Sdr146992 	hlp = TAILQ_FIRST(&hr.hei_head);
61*2958Sdr146992 	while (hlp) {
62*2958Sdr146992 		if (mdb_vread((void *)&hl, sizeof (hl),
63*2958Sdr146992 		    (uintptr_t)hlp) == -1) {
64*2958Sdr146992 			mdb_warn("couldn't read hook list at %p",
65*2958Sdr146992 			    hlp);
66*2958Sdr146992 			return (DCMD_ERR);
67*2958Sdr146992 		}
68*2958Sdr146992 		if (!hl.hi_hook.h_name) {
69*2958Sdr146992 			mdb_warn("hook list at %p has null role",
70*2958Sdr146992 			    hl.hi_hook);
71*2958Sdr146992 			return (DCMD_ERR);
72*2958Sdr146992 		}
73*2958Sdr146992 		if (mdb_readstr((char *)hrstr, sizeof (hrstr),
74*2958Sdr146992 		    (uintptr_t)hl.hi_hook.h_name) == -1) {
75*2958Sdr146992 			mdb_warn("couldn't read list role at %p",
76*2958Sdr146992 			    hl.hi_hook.h_name);
77*2958Sdr146992 			return (DCMD_ERR);
78*2958Sdr146992 		}
79*2958Sdr146992 		if (mdb_lookup_by_addr((uintptr_t)hl.hi_hook.h_func,
80*2958Sdr146992 		    MDB_SYM_EXACT, buf, sizeof (buf), &sym) == -1)
81*2958Sdr146992 			mdb_printf("%0?p %10x %0?p %10s\n",
82*2958Sdr146992 			    hlp, hl.hi_hook.h_flags, hl.hi_hook.h_func, hrstr);
83*2958Sdr146992 		else
84*2958Sdr146992 			mdb_printf("%0?p %10x %20s %10s\n",
85*2958Sdr146992 			    hlp, hl.hi_hook.h_flags, buf, hrstr);
86*2958Sdr146992 		hlp = TAILQ_NEXT(&hl, hi_entry);
87*2958Sdr146992 	}
88*2958Sdr146992 	return (DCMD_OK);
89*2958Sdr146992 }
90*2958Sdr146992 
91*2958Sdr146992 
92*2958Sdr146992 /*
93*2958Sdr146992  * List pfhooks event information.
94*2958Sdr146992  * List the hooks information in verbose mode as well.
95*2958Sdr146992  */
96*2958Sdr146992 /*ARGSUSED*/
97*2958Sdr146992 int
98*2958Sdr146992 hookeventlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
99*2958Sdr146992 {
100*2958Sdr146992 	hook_family_int_t hf;
101*2958Sdr146992 	hook_event_int_t hr, *hrp;
102*2958Sdr146992 	hook_event_t hp;
103*2958Sdr146992 	char hprstr[MAX_LENGTH];
104*2958Sdr146992 
105*2958Sdr146992 	if (argc)
106*2958Sdr146992 		return (DCMD_USAGE);
107*2958Sdr146992 
108*2958Sdr146992 	if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)addr) == -1) {
109*2958Sdr146992 		mdb_warn("couldn't read hook family at %p", addr);
110*2958Sdr146992 		return (DCMD_ERR);
111*2958Sdr146992 	}
112*2958Sdr146992 
113*2958Sdr146992 	mdb_printf("%<u>%?s %10s %20s%</u>\n", "ADDR", "FLAG", "NAME");
114*2958Sdr146992 	hrp = SLIST_FIRST(&hf.hfi_head);
115*2958Sdr146992 	while (hrp) {
116*2958Sdr146992 		if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)hrp) == -1) {
117*2958Sdr146992 			mdb_warn("couldn't read hook register at %p", hrp);
118*2958Sdr146992 			return (DCMD_ERR);
119*2958Sdr146992 		}
120*2958Sdr146992 		if (!hr.hei_event) {
121*2958Sdr146992 			mdb_warn("hook register at %p has no hook provider",
122*2958Sdr146992 			    hrp);
123*2958Sdr146992 			return (DCMD_ERR);
124*2958Sdr146992 		}
125*2958Sdr146992 		if (mdb_vread((void *)&hp, sizeof (hp),
126*2958Sdr146992 		    (uintptr_t)hr.hei_event) == -1) {
127*2958Sdr146992 			mdb_warn("hook provider at %p has null role",
128*2958Sdr146992 			    hr.hei_event);
129*2958Sdr146992 			return (DCMD_ERR);
130*2958Sdr146992 		}
131*2958Sdr146992 		if (!hp.he_name) {
132*2958Sdr146992 			mdb_warn("hook provider at %p has null role",
133*2958Sdr146992 			    hr.hei_event);
134*2958Sdr146992 			return (DCMD_ERR);
135*2958Sdr146992 		}
136*2958Sdr146992 		if (mdb_readstr((char *)hprstr, sizeof (hprstr),
137*2958Sdr146992 		    (uintptr_t)hp.he_name) == -1) {
138*2958Sdr146992 			mdb_warn("couldn't read provider role at %p",
139*2958Sdr146992 			    hp.he_name);
140*2958Sdr146992 			return (DCMD_ERR);
141*2958Sdr146992 		}
142*2958Sdr146992 		mdb_printf("%0?p %10x %20s\n", hrp, hp.he_flags, hprstr);
143*2958Sdr146992 		hrp = SLIST_NEXT(&hr, hei_entry);
144*2958Sdr146992 	}
145*2958Sdr146992 
146*2958Sdr146992 	return (DCMD_OK);
147*2958Sdr146992 }
148*2958Sdr146992 
149*2958Sdr146992 /*
150*2958Sdr146992  * List pfhooks family information.
151*2958Sdr146992  */
152*2958Sdr146992 /*ARGSUSED*/
153*2958Sdr146992 int
154*2958Sdr146992 hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
155*2958Sdr146992 {
156*2958Sdr146992 	hook_family_int_head_t hfh;
157*2958Sdr146992 	hook_family_int_t hf, *hfp;
158*2958Sdr146992 	char hrrstr[MAX_LENGTH];
159*2958Sdr146992 
160*2958Sdr146992 	if (argc)
161*2958Sdr146992 		return (DCMD_USAGE);
162*2958Sdr146992 
163*2958Sdr146992 	if (mdb_readvar(&hfh, "familylist") == -1) {
164*2958Sdr146992 		mdb_warn("couldn't read symbol 'familylist'");
165*2958Sdr146992 		return (DCMD_ERR);
166*2958Sdr146992 	}
167*2958Sdr146992 
168*2958Sdr146992 	mdb_printf("%<u>%?s %10s%</u>\n", "ADDR", "FAMILY");
169*2958Sdr146992 	hfp = SLIST_FIRST(&hfh);
170*2958Sdr146992 	while (hfp) {
171*2958Sdr146992 		if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)hfp) == -1) {
172*2958Sdr146992 			mdb_warn("couldn't read hook family at %p", hfp);
173*2958Sdr146992 			return (DCMD_ERR);
174*2958Sdr146992 		}
175*2958Sdr146992 		if (!hf.hfi_family.hf_name) {
176*2958Sdr146992 			mdb_warn("hook root at %p has null role",
177*2958Sdr146992 			    hf.hfi_family);
178*2958Sdr146992 			return (DCMD_ERR);
179*2958Sdr146992 		}
180*2958Sdr146992 		if (mdb_readstr((char *)hrrstr, sizeof (hrrstr),
181*2958Sdr146992 		    (uintptr_t)hf.hfi_family.hf_name) == -1) {
182*2958Sdr146992 			mdb_warn("couldn't read root role at %p",
183*2958Sdr146992 			    hf.hfi_family.hf_name);
184*2958Sdr146992 			return (DCMD_ERR);
185*2958Sdr146992 		}
186*2958Sdr146992 		mdb_printf("%0?p %10s\n", hfp, hrrstr);
187*2958Sdr146992 		hfp = SLIST_NEXT(&hf, hfi_entry);
188*2958Sdr146992 	}
189*2958Sdr146992 
190*2958Sdr146992 	return (DCMD_OK);
191*2958Sdr146992 }
192*2958Sdr146992 
193*2958Sdr146992 
194*2958Sdr146992 static int
195*2958Sdr146992 hookevent_walk_init(mdb_walk_state_t *wsp)
196*2958Sdr146992 {
197*2958Sdr146992 	hook_family_int_t hf;
198*2958Sdr146992 
199*2958Sdr146992 	if (wsp->walk_addr == NULL) {
200*2958Sdr146992 		mdb_warn("global walk not supported\n");
201*2958Sdr146992 		return (WALK_ERR);
202*2958Sdr146992 	}
203*2958Sdr146992 
204*2958Sdr146992 	if (mdb_vread((void *)&hf, sizeof (hf),
205*2958Sdr146992 	    (uintptr_t)wsp->walk_addr) == -1) {
206*2958Sdr146992 		mdb_warn("couldn't read hook family at %p", wsp->walk_addr);
207*2958Sdr146992 		return (DCMD_ERR);
208*2958Sdr146992 	}
209*2958Sdr146992 	wsp->walk_addr = (uintptr_t)SLIST_FIRST(&hf.hfi_head);
210*2958Sdr146992 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
211*2958Sdr146992 		    wsp->walk_cbdata));
212*2958Sdr146992 }
213*2958Sdr146992 
214*2958Sdr146992 static int
215*2958Sdr146992 hookevent_walk_step(mdb_walk_state_t *wsp)
216*2958Sdr146992 {
217*2958Sdr146992 	hook_event_int_t hr;
218*2958Sdr146992 
219*2958Sdr146992 	if (mdb_vread((void *)&hr, sizeof (hr),
220*2958Sdr146992 	    (uintptr_t)wsp->walk_addr) == -1) {
221*2958Sdr146992 		mdb_warn("couldn't read hook event at %p", wsp->walk_addr);
222*2958Sdr146992 		return (DCMD_ERR);
223*2958Sdr146992 	}
224*2958Sdr146992 	wsp->walk_addr = (uintptr_t)SLIST_NEXT(&hr, hei_entry);
225*2958Sdr146992 	if (wsp->walk_addr == NULL)
226*2958Sdr146992 		return (WALK_DONE);
227*2958Sdr146992 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
228*2958Sdr146992 		    wsp->walk_cbdata));
229*2958Sdr146992 }
230*2958Sdr146992 
231*2958Sdr146992 
232*2958Sdr146992 static const mdb_dcmd_t dcmds[] = {
233*2958Sdr146992 	{ "hookrootlist", "", "display hook family information", hookrootlist },
234*2958Sdr146992 	{ "hookeventlist", "", "display hook event information",
235*2958Sdr146992 		hookeventlist, NULL },
236*2958Sdr146992 	{ "hooklist", "", "display hooks", hooklist },
237*2958Sdr146992 	{ NULL }
238*2958Sdr146992 };
239*2958Sdr146992 
240*2958Sdr146992 static const mdb_walker_t walkers[] = {
241*2958Sdr146992 	{ "hookevent", "walk a list of hooks",
242*2958Sdr146992 		hookevent_walk_init, hookevent_walk_step, NULL },
243*2958Sdr146992 	{ NULL }
244*2958Sdr146992 };
245*2958Sdr146992 
246*2958Sdr146992 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
247*2958Sdr146992 
248*2958Sdr146992 const mdb_modinfo_t *
249*2958Sdr146992 _mdb_init(void)
250*2958Sdr146992 {
251*2958Sdr146992 	return (&modinfo);
252*2958Sdr146992 }
253