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