xref: /illumos-gate/usr/src/cmd/mdb/common/modules/hook/hook.c (revision f4b3ec61df05330d25f55a36b975b4d7519fdeb1)
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 2007 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/rwlock.h>
30 #include <mdb/mdb_modapi.h>
31 #include <sys/queue.h>
32 #include <inet/ip.h>
33 #include <sys/hook.h>
34 #include <sys/hook_impl.h>
35 
36 #define	MAX_LENGTH 64
37 
38 /*
39  * List pfhooks hook list information.
40  */
41 /*ARGSUSED*/
42 int
43 hooklist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
44 {
45 	hook_event_int_t hr;
46 	hook_int_t hl, *hlp;
47 	char hrstr[MAX_LENGTH];
48 	GElf_Sym sym;
49 	char buf[MDB_SYM_NAMLEN + 1];
50 
51 	if (argc)
52 		return (DCMD_USAGE);
53 
54 	if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)addr) == -1) {
55 		mdb_warn("couldn't read hook register at %p", addr);
56 		return (DCMD_ERR);
57 	}
58 
59 	mdb_printf("%<u>%?s %10s %20s %?s%</u>\n",
60 	    "ADDR", "FLAG", "FUNC", "NAME");
61 	hlp = TAILQ_FIRST(&hr.hei_head);
62 	while (hlp) {
63 		if (mdb_vread((void *)&hl, sizeof (hl),
64 		    (uintptr_t)hlp) == -1) {
65 			mdb_warn("couldn't read hook list at %p",
66 			    hlp);
67 			return (DCMD_ERR);
68 		}
69 		if (!hl.hi_hook.h_name) {
70 			mdb_warn("hook list at %p has null role",
71 			    hl.hi_hook);
72 			return (DCMD_ERR);
73 		}
74 		if (mdb_readstr((char *)hrstr, sizeof (hrstr),
75 		    (uintptr_t)hl.hi_hook.h_name) == -1) {
76 			mdb_warn("couldn't read list role at %p",
77 			    hl.hi_hook.h_name);
78 			return (DCMD_ERR);
79 		}
80 		if (mdb_lookup_by_addr((uintptr_t)hl.hi_hook.h_func,
81 		    MDB_SYM_EXACT, buf, sizeof (buf), &sym) == -1)
82 			mdb_printf("%0?p %10x %0?p %10s\n",
83 			    hlp, hl.hi_hook.h_flags, hl.hi_hook.h_func, hrstr);
84 		else
85 			mdb_printf("%0?p %10x %20s %10s\n",
86 			    hlp, hl.hi_hook.h_flags, buf, hrstr);
87 		hlp = TAILQ_NEXT(&hl, hi_entry);
88 	}
89 	return (DCMD_OK);
90 }
91 
92 
93 /*
94  * List pfhooks event information.
95  * List the hooks information in verbose mode as well.
96  */
97 /*ARGSUSED*/
98 int
99 hookeventlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
100 {
101 	hook_family_int_t hf;
102 	hook_event_int_t hr, *hrp;
103 	hook_event_t hp;
104 	char hprstr[MAX_LENGTH];
105 
106 	if (argc)
107 		return (DCMD_USAGE);
108 
109 	if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)addr) == -1) {
110 		mdb_warn("couldn't read hook family at %p", addr);
111 		return (DCMD_ERR);
112 	}
113 
114 	mdb_printf("%<u>%?s %10s %20s%</u>\n", "ADDR", "FLAG", "NAME");
115 	hrp = SLIST_FIRST(&hf.hfi_head);
116 	while (hrp) {
117 		if (mdb_vread((void *)&hr, sizeof (hr), (uintptr_t)hrp) == -1) {
118 			mdb_warn("couldn't read hook register at %p", hrp);
119 			return (DCMD_ERR);
120 		}
121 		if (!hr.hei_event) {
122 			mdb_warn("hook register at %p has no hook provider",
123 			    hrp);
124 			return (DCMD_ERR);
125 		}
126 		if (mdb_vread((void *)&hp, sizeof (hp),
127 		    (uintptr_t)hr.hei_event) == -1) {
128 			mdb_warn("hook provider at %p has null role",
129 			    hr.hei_event);
130 			return (DCMD_ERR);
131 		}
132 		if (!hp.he_name) {
133 			mdb_warn("hook provider at %p has null role",
134 			    hr.hei_event);
135 			return (DCMD_ERR);
136 		}
137 		if (mdb_readstr((char *)hprstr, sizeof (hprstr),
138 		    (uintptr_t)hp.he_name) == -1) {
139 			mdb_warn("couldn't read provider role at %p",
140 			    hp.he_name);
141 			return (DCMD_ERR);
142 		}
143 		mdb_printf("%0?p %10x %20s\n", hrp, hp.he_flags, hprstr);
144 		hrp = SLIST_NEXT(&hr, hei_entry);
145 	}
146 
147 	return (DCMD_OK);
148 }
149 
150 /*
151  * List pfhooks family information.
152  */
153 /*ARGSUSED*/
154 int
155 hookrootlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
156 {
157 	struct hook_stack *hks;
158 	hook_family_int_head_t hfh;
159 	hook_family_int_t hf, *hfp;
160 	char hrrstr[MAX_LENGTH];
161 
162 	if (argc)
163 		return (DCMD_USAGE);
164 
165 	if (mdb_vread((void *)&hks, sizeof (hks),
166 	    (uintptr_t)(addr + OFFSETOF(netstack_t, netstack_hook))) == -1) {
167 		mdb_warn("couldn't read netstack_hook");
168 		return (DCMD_ERR);
169 	}
170 
171 	if (mdb_vread((void *)&hfh, sizeof (hfh), (uintptr_t)((uintptr_t)hks +
172 	    OFFSETOF(hook_stack_t, hks_familylist))) == -1) {
173 		mdb_warn("couldn't read hook family head");
174 		return (DCMD_ERR);
175 	}
176 
177 	mdb_printf("%<u>%?s %10s%</u>\n", "ADDR", "FAMILY");
178 	hfp = SLIST_FIRST(&hfh);
179 	while (hfp) {
180 		if (mdb_vread((void *)&hf, sizeof (hf), (uintptr_t)hfp) == -1) {
181 			mdb_warn("couldn't read hook family at %p", hfp);
182 			return (DCMD_ERR);
183 		}
184 		if (!hf.hfi_family.hf_name) {
185 			mdb_warn("hook root at %p has null role",
186 			    hf.hfi_family);
187 			return (DCMD_ERR);
188 		}
189 		if (mdb_readstr((char *)hrrstr, sizeof (hrrstr),
190 		    (uintptr_t)hf.hfi_family.hf_name) == -1) {
191 			mdb_warn("couldn't read root role at %p",
192 			    hf.hfi_family.hf_name);
193 			return (DCMD_ERR);
194 		}
195 		mdb_printf("%0?p %10s\n", hfp, hrrstr);
196 		hfp = SLIST_NEXT(&hf, hfi_entry);
197 	}
198 
199 	return (DCMD_OK);
200 }
201 
202 
203 static int
204 hookevent_stack_walk_init(mdb_walk_state_t *wsp)
205 {
206 	hook_family_int_t hf;
207 
208 	if (wsp->walk_addr == NULL) {
209 		mdb_warn("global walk not supported\n");
210 		return (WALK_ERR);
211 	}
212 
213 	if (mdb_vread((void *)&hf, sizeof (hf),
214 	    (uintptr_t)wsp->walk_addr) == -1) {
215 		mdb_warn("couldn't read hook family at %p", wsp->walk_addr);
216 		return (DCMD_ERR);
217 	}
218 	wsp->walk_addr = (uintptr_t)SLIST_FIRST(&hf.hfi_head);
219 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
220 		    wsp->walk_cbdata));
221 }
222 
223 static int
224 hookevent_stack_walk_step(mdb_walk_state_t *wsp)
225 {
226 	hook_event_int_t hr;
227 
228 	if (mdb_vread((void *)&hr, sizeof (hr),
229 	    (uintptr_t)wsp->walk_addr) == -1) {
230 		mdb_warn("couldn't read hook event at %p", wsp->walk_addr);
231 		return (DCMD_ERR);
232 	}
233 	wsp->walk_addr = (uintptr_t)SLIST_NEXT(&hr, hei_entry);
234 	if (wsp->walk_addr == NULL)
235 		return (WALK_DONE);
236 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
237 		    wsp->walk_cbdata));
238 }
239 
240 static const mdb_dcmd_t dcmds[] = {
241 	{ "hookrootlist", "", "display hook family information", hookrootlist },
242 	{ "hookeventlist", "", "display hook event information",
243 		hookeventlist, NULL },
244 	{ "hooklist", "", "display hooks", hooklist },
245 	{ NULL }
246 };
247 
248 static const mdb_walker_t walkers[] = {
249 	{ "hookevent_stack", "walk list of hooks",
250 		hookevent_stack_walk_init, hookevent_stack_walk_step, NULL },
251 	{ NULL }
252 };
253 
254 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
255 
256 const mdb_modinfo_t *
257 _mdb_init(void)
258 {
259 	return (&modinfo);
260 }
261