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