1 1.29 riastrad /* $NetBSD: fbt.c,v 1.29 2022/09/02 11:03:50 riastradh Exp $ */ 2 1.2 darran 3 1.1 darran /* 4 1.1 darran * CDDL HEADER START 5 1.1 darran * 6 1.1 darran * The contents of this file are subject to the terms of the 7 1.1 darran * Common Development and Distribution License (the "License"). 8 1.1 darran * You may not use this file except in compliance with the License. 9 1.1 darran * 10 1.1 darran * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 1.1 darran * or http://www.opensolaris.org/os/licensing. 12 1.1 darran * See the License for the specific language governing permissions 13 1.1 darran * and limitations under the License. 14 1.1 darran * 15 1.1 darran * When distributing Covered Code, include this CDDL HEADER in each 16 1.1 darran * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 1.1 darran * If applicable, add the following below this CDDL HEADER, with the 18 1.1 darran * fields enclosed by brackets "[]" replaced with your own identifying 19 1.1 darran * information: Portions Copyright [yyyy] [name of copyright owner] 20 1.1 darran * 21 1.1 darran * CDDL HEADER END 22 1.1 darran * 23 1.1 darran * Portions Copyright 2006-2008 John Birrell jb (at) freebsd.org 24 1.3 darran * Portions Copyright 2010 Darran Hunt darran (at) NetBSD.org 25 1.1 darran * 26 1.24 chs * $FreeBSD: head/sys/cddl/dev/fbt/fbt.c 309786 2016-12-10 03:13:11Z markj $ 27 1.1 darran * 28 1.1 darran */ 29 1.1 darran 30 1.1 darran /* 31 1.1 darran * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 32 1.1 darran * Use is subject to license terms. 33 1.1 darran */ 34 1.1 darran 35 1.1 darran #include <sys/cdefs.h> 36 1.24 chs #include <sys/proc.h> 37 1.1 darran #include <sys/param.h> 38 1.1 darran #include <sys/systm.h> 39 1.1 darran #include <sys/conf.h> 40 1.1 darran #include <sys/cpuvar.h> 41 1.1 darran #include <sys/fcntl.h> 42 1.1 darran #include <sys/filio.h> 43 1.1 darran #include <sys/kernel.h> 44 1.1 darran #include <sys/kmem.h> 45 1.5 christos #include <sys/ksyms.h> 46 1.3 darran #include <sys/cpu.h> 47 1.1 darran #include <sys/kthread.h> 48 1.21 christos #include <sys/syslimits.h> 49 1.1 darran #include <sys/linker.h> 50 1.1 darran #include <sys/lock.h> 51 1.1 darran #include <sys/malloc.h> 52 1.1 darran #include <sys/module.h> 53 1.1 darran #include <sys/mutex.h> 54 1.1 darran #include <sys/poll.h> 55 1.1 darran #include <sys/proc.h> 56 1.1 darran #include <sys/selinfo.h> 57 1.1 darran #include <sys/syscall.h> 58 1.1 darran #include <sys/uio.h> 59 1.1 darran #include <sys/unistd.h> 60 1.3 darran #include <sys/exec_elf.h> 61 1.3 darran 62 1.1 darran #include <sys/dtrace.h> 63 1.1 darran #include <sys/dtrace_bsd.h> 64 1.3 darran #include <sys/kern_ctf.h> 65 1.7 tron #include <sys/dtrace_impl.h> 66 1.3 darran 67 1.24 chs #include "fbt.h" 68 1.24 chs 69 1.3 darran mod_ctf_t *modptr; 70 1.1 darran 71 1.24 chs dtrace_provider_id_t fbt_id; 72 1.24 chs fbt_probe_t **fbt_probetab; 73 1.24 chs int fbt_probetab_mask; 74 1.24 chs static int fbt_probetab_size; 75 1.1 darran 76 1.3 darran static dev_type_open(fbt_open); 77 1.1 darran static int fbt_unload(void); 78 1.1 darran static void fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *); 79 1.24 chs static void fbt_provide_module(void *, modctl_t *); 80 1.1 darran static void fbt_destroy(void *, dtrace_id_t, void *); 81 1.3 darran static int fbt_enable(void *, dtrace_id_t, void *); 82 1.1 darran static void fbt_disable(void *, dtrace_id_t, void *); 83 1.3 darran static void fbt_load(void); 84 1.1 darran static void fbt_suspend(void *, dtrace_id_t, void *); 85 1.1 darran static void fbt_resume(void *, dtrace_id_t, void *); 86 1.1 darran 87 1.3 darran static const struct cdevsw fbt_cdevsw = { 88 1.19 pgoyette .d_open = fbt_open, 89 1.19 pgoyette .d_close = noclose, 90 1.19 pgoyette .d_read = noread, 91 1.19 pgoyette .d_write = nowrite, 92 1.19 pgoyette .d_ioctl = noioctl, 93 1.19 pgoyette .d_stop = nostop, 94 1.19 pgoyette .d_tty = notty, 95 1.19 pgoyette .d_poll = nopoll, 96 1.19 pgoyette .d_mmap = nommap, 97 1.19 pgoyette .d_kqfilter = nokqfilter, 98 1.19 pgoyette .d_discard = nodiscard, 99 1.19 pgoyette .d_flag = D_OTHER 100 1.1 darran }; 101 1.1 darran 102 1.1 darran static dtrace_pattr_t fbt_attr = { 103 1.1 darran { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, 104 1.1 darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 105 1.1 darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, 106 1.1 darran { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, 107 1.1 darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, 108 1.1 darran }; 109 1.1 darran 110 1.1 darran static dtrace_pops_t fbt_pops = { 111 1.1 darran NULL, 112 1.1 darran fbt_provide_module, 113 1.1 darran fbt_enable, 114 1.1 darran fbt_disable, 115 1.1 darran fbt_suspend, 116 1.1 darran fbt_resume, 117 1.1 darran fbt_getargdesc, 118 1.1 darran NULL, 119 1.1 darran NULL, 120 1.1 darran fbt_destroy 121 1.1 darran }; 122 1.1 darran 123 1.24 chs #ifdef __FreeBSD__ 124 1.24 chs static int fbt_verbose = 0; 125 1.1 darran 126 1.1 darran static struct cdev *fbt_cdev; 127 1.24 chs #endif /* __FreeBSD__ */ 128 1.1 darran 129 1.24 chs #ifdef __NetBSD__ 130 1.24 chs specificdata_key_t fbt_module_key; 131 1.14 ozaki 132 1.24 chs #define version xversion 133 1.24 chs #endif /* __NetBSD__ */ 134 1.14 ozaki 135 1.24 chs int 136 1.24 chs fbt_excluded(const char *name) 137 1.14 ozaki { 138 1.14 ozaki 139 1.24 chs if (strncmp(name, "dtrace_", 7) == 0 && 140 1.24 chs strncmp(name, "dtrace_safe_", 12) != 0) { 141 1.14 ozaki /* 142 1.24 chs * Anything beginning with "dtrace_" may be called 143 1.24 chs * from probe context unless it explicitly indicates 144 1.24 chs * that it won't be called from probe context by 145 1.24 chs * using the prefix "dtrace_safe_". 146 1.14 ozaki */ 147 1.24 chs return (1); 148 1.14 ozaki } 149 1.14 ozaki 150 1.24 chs #ifdef __FreeBSD__ 151 1.24 chs /* 152 1.24 chs * Lock owner methods may be called from probe context. 153 1.24 chs */ 154 1.24 chs if (strcmp(name, "owner_mtx") == 0 || 155 1.24 chs strcmp(name, "owner_rm") == 0 || 156 1.24 chs strcmp(name, "owner_rw") == 0 || 157 1.24 chs strcmp(name, "owner_sx") == 0) 158 1.24 chs return (1); 159 1.14 ozaki 160 1.24 chs /* 161 1.24 chs * When DTrace is built into the kernel we need to exclude 162 1.24 chs * the FBT functions from instrumentation. 163 1.24 chs */ 164 1.24 chs #ifndef _KLD_MODULE 165 1.24 chs if (strncmp(name, "fbt_", 4) == 0) 166 1.24 chs return (1); 167 1.24 chs #endif 168 1.24 chs #endif 169 1.14 ozaki 170 1.24 chs #ifdef __NetBSD__ 171 1.24 chs if (strcmp(name, "cpu_index") == 0 || 172 1.24 chs strncmp(name, "db_", 3) == 0 || 173 1.24 chs strncmp(name, "ddb_", 4) == 0 || 174 1.24 chs strncmp(name, "kdb_", 4) == 0 || 175 1.24 chs strncmp(name, "lockdebug_", 10) == 0 || 176 1.24 chs strncmp(name, "kauth_", 5) == 0 || 177 1.27 hannken strncmp(name, "ktext_write", 11) == 0 || 178 1.27 hannken strncmp(name, "fbt_", 4) == 0) { 179 1.24 chs return (1); 180 1.14 ozaki } 181 1.24 chs #endif 182 1.24 chs 183 1.24 chs return (0); 184 1.14 ozaki } 185 1.14 ozaki 186 1.1 darran static void 187 1.1 darran fbt_doubletrap(void) 188 1.1 darran { 189 1.1 darran fbt_probe_t *fbt; 190 1.1 darran int i; 191 1.1 darran 192 1.1 darran for (i = 0; i < fbt_probetab_size; i++) { 193 1.1 darran fbt = fbt_probetab[i]; 194 1.1 darran 195 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next) 196 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_savedval); 197 1.1 darran } 198 1.1 darran } 199 1.1 darran 200 1.24 chs #ifdef __FreeBSD__ 201 1.24 chs static void 202 1.24 chs fbt_provide_module(void *arg, modctl_t *lf) 203 1.1 darran { 204 1.24 chs char modname[MAXPATHLEN]; 205 1.24 chs int i; 206 1.24 chs size_t len; 207 1.22 chs 208 1.24 chs strlcpy(modname, lf->filename, sizeof(modname)); 209 1.24 chs len = strlen(modname); 210 1.24 chs if (len > 3 && strcmp(modname + len - 3, ".ko") == 0) 211 1.24 chs modname[len - 3] = '\0'; 212 1.1 darran 213 1.24 chs /* 214 1.24 chs * Employees of dtrace and their families are ineligible. Void 215 1.24 chs * where prohibited. 216 1.24 chs */ 217 1.24 chs if (strcmp(modname, "dtrace") == 0) 218 1.24 chs return; 219 1.1 darran 220 1.10 yamt /* 221 1.24 chs * To register with DTrace, a module must list 'dtrace' as a 222 1.24 chs * dependency in order for the kernel linker to resolve 223 1.24 chs * symbols like dtrace_register(). All modules with such a 224 1.24 chs * dependency are ineligible for FBT tracing. 225 1.10 yamt */ 226 1.24 chs for (i = 0; i < lf->ndeps; i++) 227 1.24 chs if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0) 228 1.24 chs return; 229 1.10 yamt 230 1.24 chs if (lf->fbt_nentries) { 231 1.1 darran /* 232 1.24 chs * This module has some FBT entries allocated; we're afraid 233 1.24 chs * to screw with it. 234 1.1 darran */ 235 1.24 chs return; 236 1.14 ozaki } 237 1.14 ozaki 238 1.14 ozaki /* 239 1.24 chs * List the functions in the module and the symbol values. 240 1.14 ozaki */ 241 1.24 chs (void) linker_file_function_listall(lf, fbt_provide_module_function, modname); 242 1.14 ozaki } 243 1.14 ozaki #endif 244 1.24 chs #ifdef __NetBSD__ 245 1.1 darran static void 246 1.24 chs fbt_provide_module(void *arg, modctl_t *mod) 247 1.1 darran { 248 1.24 chs struct fbt_ksyms_arg fka; 249 1.24 chs struct mod_ctf *mc; 250 1.1 darran char modname[MAXPATHLEN]; 251 1.1 darran int i; 252 1.1 darran size_t len; 253 1.1 darran 254 1.24 chs if (mod_ctf_get(mod, &mc)) { 255 1.24 chs printf("fbt: no CTF data for module %s\n", module_name(mod)); 256 1.24 chs return; 257 1.24 chs } 258 1.24 chs 259 1.24 chs strlcpy(modname, module_name(mod), sizeof(modname)); 260 1.1 darran len = strlen(modname); 261 1.3 darran if (len > 5 && strcmp(modname + len - 3, ".kmod") == 0) 262 1.3 darran modname[len - 4] = '\0'; 263 1.1 darran 264 1.1 darran /* 265 1.1 darran * Employees of dtrace and their families are ineligible. Void 266 1.1 darran * where prohibited. 267 1.1 darran */ 268 1.1 darran if (strcmp(modname, "dtrace") == 0) 269 1.1 darran return; 270 1.1 darran 271 1.1 darran /* 272 1.1 darran * The cyclic timer subsystem can be built as a module and DTrace 273 1.1 darran * depends on that, so it is ineligible too. 274 1.1 darran */ 275 1.1 darran if (strcmp(modname, "cyclic") == 0) 276 1.1 darran return; 277 1.1 darran 278 1.1 darran /* 279 1.1 darran * To register with DTrace, a module must list 'dtrace' as a 280 1.1 darran * dependency in order for the kernel linker to resolve 281 1.1 darran * symbols like dtrace_register(). All modules with such a 282 1.1 darran * dependency are ineligible for FBT tracing. 283 1.1 darran */ 284 1.3 darran for (i = 0; i < mod->mod_nrequired; i++) { 285 1.25 pgoyette if (strncmp(module_name((*mod->mod_required)[i]), 286 1.3 darran "dtrace", 6) == 0) 287 1.1 darran return; 288 1.3 darran } 289 1.24 chs if (mc->fbt_provided) { 290 1.1 darran return; 291 1.1 darran } 292 1.1 darran 293 1.1 darran /* 294 1.1 darran * List the functions in the module and the symbol values. 295 1.1 darran */ 296 1.24 chs memset(&fka, 0, sizeof(fka)); 297 1.24 chs fka.fka_mod = mod; 298 1.24 chs fka.fka_mc = mc; 299 1.24 chs ksyms_mod_foreach(modname, fbt_provide_module_cb, &fka); 300 1.24 chs mc->fbt_provided = true; 301 1.1 darran } 302 1.1 darran 303 1.1 darran static void 304 1.24 chs fbt_module_dtor(void *arg) 305 1.24 chs { 306 1.24 chs mod_ctf_t *mc = arg; 307 1.24 chs 308 1.24 chs if (mc->ctfalloc) 309 1.24 chs free(mc->ctftab, M_TEMP); 310 1.24 chs kmem_free(mc, sizeof(*mc)); 311 1.24 chs } 312 1.24 chs #endif 313 1.24 chs 314 1.24 chs static void 315 1.1 darran fbt_destroy(void *arg, dtrace_id_t id, void *parg) 316 1.1 darran { 317 1.1 darran fbt_probe_t *fbt = parg, *next, *hash, *last; 318 1.24 chs modctl_t *ctl; 319 1.1 darran int ndx; 320 1.1 darran 321 1.1 darran do { 322 1.1 darran ctl = fbt->fbtp_ctl; 323 1.1 darran 324 1.24 chs #ifdef __FreeBSD__ 325 1.3 darran ctl->mod_fbtentries--; 326 1.24 chs #endif 327 1.24 chs #ifdef __NetBSD__ 328 1.24 chs mod_ctf_t *mc = module_getspecific(ctl, fbt_module_key); 329 1.24 chs mc->fbt_provided = false; 330 1.24 chs #endif 331 1.1 darran 332 1.1 darran /* 333 1.1 darran * Now we need to remove this probe from the fbt_probetab. 334 1.1 darran */ 335 1.1 darran ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint); 336 1.1 darran last = NULL; 337 1.1 darran hash = fbt_probetab[ndx]; 338 1.1 darran 339 1.1 darran while (hash != fbt) { 340 1.1 darran ASSERT(hash != NULL); 341 1.1 darran last = hash; 342 1.1 darran hash = hash->fbtp_hashnext; 343 1.1 darran } 344 1.1 darran 345 1.1 darran if (last != NULL) { 346 1.1 darran last->fbtp_hashnext = fbt->fbtp_hashnext; 347 1.1 darran } else { 348 1.1 darran fbt_probetab[ndx] = fbt->fbtp_hashnext; 349 1.1 darran } 350 1.1 darran 351 1.1 darran next = fbt->fbtp_next; 352 1.24 chs kmem_free(fbt, sizeof(*fbt)); 353 1.1 darran 354 1.1 darran fbt = next; 355 1.1 darran } while (fbt != NULL); 356 1.1 darran } 357 1.1 darran 358 1.3 darran static int 359 1.1 darran fbt_enable(void *arg, dtrace_id_t id, void *parg) 360 1.1 darran { 361 1.1 darran fbt_probe_t *fbt = parg; 362 1.24 chs modctl_t *ctl = fbt->fbtp_ctl; 363 1.3 darran 364 1.24 chs #ifdef __NetBSD__ 365 1.24 chs module_hold(ctl); 366 1.24 chs #else 367 1.1 darran ctl->nenabled++; 368 1.1 darran 369 1.1 darran /* 370 1.1 darran * Now check that our modctl has the expected load count. If it 371 1.1 darran * doesn't, this module must have been unloaded and reloaded -- and 372 1.1 darran * we're not going to touch it. 373 1.1 darran */ 374 1.1 darran if (ctl->loadcnt != fbt->fbtp_loadcnt) { 375 1.1 darran if (fbt_verbose) { 376 1.1 darran printf("fbt is failing for probe %s " 377 1.1 darran "(module %s reloaded)", 378 1.24 chs fbt->fbtp_name, module_name(ctl)); 379 1.1 darran } 380 1.1 darran 381 1.24 chs return 0; 382 1.1 darran } 383 1.3 darran #endif 384 1.3 darran 385 1.24 chs for (; fbt != NULL; fbt = fbt->fbtp_next) 386 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_patchval); 387 1.3 darran return 0; 388 1.1 darran } 389 1.1 darran 390 1.1 darran static void 391 1.1 darran fbt_disable(void *arg, dtrace_id_t id, void *parg) 392 1.1 darran { 393 1.1 darran fbt_probe_t *fbt = parg; 394 1.24 chs modctl_t *ctl = fbt->fbtp_ctl; 395 1.1 darran 396 1.24 chs #ifndef __NetBSD__ 397 1.1 darran ASSERT(ctl->nenabled > 0); 398 1.1 darran ctl->nenabled--; 399 1.1 darran 400 1.1 darran if ((ctl->loadcnt != fbt->fbtp_loadcnt)) 401 1.1 darran return; 402 1.3 darran #endif 403 1.1 darran 404 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next) 405 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_savedval); 406 1.3 darran 407 1.24 chs #ifdef __NetBSD__ 408 1.24 chs module_rele(ctl); 409 1.24 chs #endif 410 1.1 darran } 411 1.1 darran 412 1.1 darran static void 413 1.1 darran fbt_suspend(void *arg, dtrace_id_t id, void *parg) 414 1.1 darran { 415 1.1 darran fbt_probe_t *fbt = parg; 416 1.24 chs #ifndef __NetBSD__ 417 1.24 chs modctl_t *ctl = fbt->fbtp_ctl; 418 1.1 darran 419 1.1 darran ASSERT(ctl->nenabled > 0); 420 1.1 darran 421 1.1 darran if ((ctl->loadcnt != fbt->fbtp_loadcnt)) 422 1.1 darran return; 423 1.3 darran #endif 424 1.3 darran 425 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next) 426 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_savedval); 427 1.1 darran } 428 1.1 darran 429 1.1 darran static void 430 1.1 darran fbt_resume(void *arg, dtrace_id_t id, void *parg) 431 1.1 darran { 432 1.1 darran fbt_probe_t *fbt = parg; 433 1.24 chs #ifndef __NetBSD__ 434 1.24 chs modctl_t *ctl = fbt->fbtp_ctl; 435 1.1 darran 436 1.1 darran ASSERT(ctl->nenabled > 0); 437 1.1 darran 438 1.1 darran if ((ctl->loadcnt != fbt->fbtp_loadcnt)) 439 1.1 darran return; 440 1.3 darran #endif 441 1.1 darran 442 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next) 443 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_patchval); 444 1.14 ozaki } 445 1.14 ozaki 446 1.1 darran static int 447 1.24 chs fbt_ctfoff_init(modctl_t *mod, mod_ctf_t *mc) 448 1.1 darran { 449 1.3 darran const Elf_Sym *symp = mc->symtab; 450 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab; 451 1.3 darran const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t); 452 1.1 darran int i; 453 1.1 darran uint32_t *ctfoff; 454 1.1 darran uint32_t objtoff = hp->cth_objtoff; 455 1.1 darran uint32_t funcoff = hp->cth_funcoff; 456 1.1 darran ushort_t info; 457 1.1 darran ushort_t vlen; 458 1.3 darran int nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym; 459 1.1 darran 460 1.1 darran /* Sanity check. */ 461 1.1 darran if (hp->cth_magic != CTF_MAGIC) { 462 1.3 darran printf("Bad magic value in CTF data of '%s'\n", 463 1.24 chs module_name(mod)); 464 1.1 darran return (EINVAL); 465 1.1 darran } 466 1.1 darran 467 1.3 darran if (mc->symtab == NULL) { 468 1.24 chs printf("No symbol table in '%s'\n", module_name(mod)); 469 1.1 darran return (EINVAL); 470 1.1 darran } 471 1.1 darran 472 1.24 chs ctfoff = malloc(sizeof(uint32_t) * nsyms, M_FBT, M_WAITOK); 473 1.3 darran mc->ctfoffp = ctfoff; 474 1.3 darran 475 1.3 darran for (i = 0; i < nsyms; i++, ctfoff++, symp++) { 476 1.3 darran if (mc->nmap != NULL) { 477 1.3 darran if (mc->nmap[i] == 0) { 478 1.3 darran printf("%s.%d: Error! Got zero nmap!\n", 479 1.3 darran __func__, __LINE__); 480 1.3 darran continue; 481 1.3 darran } 482 1.3 darran 483 1.24 chs /* 484 1.24 chs * CTF expects the unsorted symbol ordering, 485 1.3 darran * so map it from that to the current sorted 486 1.24 chs * symbol table. 487 1.3 darran * ctfoff[new-ind] = oldind symbol info. 488 1.3 darran */ 489 1.3 darran 490 1.3 darran /* map old index to new symbol table */ 491 1.3 darran symp = &mc->symtab[mc->nmap[i] - 1]; 492 1.3 darran 493 1.3 darran /* map old index to new ctfoff index */ 494 1.3 darran ctfoff = &mc->ctfoffp[mc->nmap[i]-1]; 495 1.3 darran } 496 1.1 darran 497 1.24 chs /* 498 1.24 chs * Note that due to how kern_ksyms.c adjusts st_name 499 1.24 chs * to be the offset into a virtual combined strtab, 500 1.24 chs * st_name will never be 0 for loaded modules. 501 1.24 chs */ 502 1.24 chs 503 1.1 darran if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) { 504 1.1 darran *ctfoff = 0xffffffff; 505 1.1 darran continue; 506 1.1 darran } 507 1.1 darran 508 1.1 darran switch (ELF_ST_TYPE(symp->st_info)) { 509 1.1 darran case STT_OBJECT: 510 1.1 darran if (objtoff >= hp->cth_funcoff || 511 1.1 darran (symp->st_shndx == SHN_ABS && symp->st_value == 0)) { 512 1.1 darran *ctfoff = 0xffffffff; 513 1.1 darran break; 514 1.1 darran } 515 1.1 darran 516 1.1 darran *ctfoff = objtoff; 517 1.1 darran objtoff += sizeof (ushort_t); 518 1.1 darran break; 519 1.1 darran 520 1.1 darran case STT_FUNC: 521 1.1 darran if (funcoff >= hp->cth_typeoff) { 522 1.1 darran *ctfoff = 0xffffffff; 523 1.1 darran break; 524 1.1 darran } 525 1.1 darran 526 1.1 darran *ctfoff = funcoff; 527 1.1 darran 528 1.1 darran info = *((const ushort_t *)(ctfdata + funcoff)); 529 1.1 darran vlen = CTF_INFO_VLEN(info); 530 1.1 darran 531 1.1 darran /* 532 1.1 darran * If we encounter a zero pad at the end, just skip it. 533 1.1 darran * Otherwise skip over the function and its return type 534 1.1 darran * (+2) and the argument list (vlen). 535 1.1 darran */ 536 1.1 darran if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0) 537 1.1 darran funcoff += sizeof (ushort_t); /* skip pad */ 538 1.1 darran else 539 1.1 darran funcoff += sizeof (ushort_t) * (vlen + 2); 540 1.1 darran break; 541 1.1 darran 542 1.1 darran default: 543 1.1 darran *ctfoff = 0xffffffff; 544 1.1 darran break; 545 1.1 darran } 546 1.1 darran } 547 1.1 darran 548 1.1 darran return (0); 549 1.1 darran } 550 1.1 darran 551 1.1 darran static ssize_t 552 1.24 chs fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep, 553 1.1 darran ssize_t *incrementp) 554 1.1 darran { 555 1.1 darran ssize_t size, increment; 556 1.1 darran 557 1.24 chs if (version > CTF_VERSION_1 && 558 1.1 darran tp->ctt_size == CTF_LSIZE_SENT) { 559 1.1 darran size = CTF_TYPE_LSIZE(tp); 560 1.1 darran increment = sizeof (ctf_type_t); 561 1.1 darran } else { 562 1.1 darran size = tp->ctt_size; 563 1.1 darran increment = sizeof (ctf_stype_t); 564 1.1 darran } 565 1.1 darran 566 1.1 darran if (sizep) 567 1.1 darran *sizep = size; 568 1.1 darran if (incrementp) 569 1.1 darran *incrementp = increment; 570 1.1 darran 571 1.1 darran return (size); 572 1.1 darran } 573 1.1 darran 574 1.1 darran static int 575 1.3 darran fbt_typoff_init(mod_ctf_t *mc) 576 1.1 darran { 577 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab; 578 1.1 darran const ctf_type_t *tbuf; 579 1.1 darran const ctf_type_t *tend; 580 1.1 darran const ctf_type_t *tp; 581 1.3 darran const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t); 582 1.1 darran int ctf_typemax = 0; 583 1.1 darran uint32_t *xp; 584 1.1 darran ulong_t pop[CTF_K_MAX + 1] = { 0 }; 585 1.1 darran 586 1.24 chs 587 1.1 darran /* Sanity check. */ 588 1.1 darran if (hp->cth_magic != CTF_MAGIC) 589 1.1 darran return (EINVAL); 590 1.1 darran 591 1.1 darran tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff); 592 1.1 darran tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff); 593 1.1 darran 594 1.1 darran int child = hp->cth_parname != 0; 595 1.1 darran 596 1.1 darran /* 597 1.1 darran * We make two passes through the entire type section. In this first 598 1.1 darran * pass, we count the number of each type and the total number of types. 599 1.1 darran */ 600 1.1 darran for (tp = tbuf; tp < tend; ctf_typemax++) { 601 1.1 darran ushort_t kind = CTF_INFO_KIND(tp->ctt_info); 602 1.1 darran ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info); 603 1.1 darran ssize_t size, increment; 604 1.1 darran 605 1.1 darran size_t vbytes; 606 1.1 darran uint_t n; 607 1.1 darran 608 1.1 darran (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment); 609 1.1 darran 610 1.1 darran switch (kind) { 611 1.1 darran case CTF_K_INTEGER: 612 1.1 darran case CTF_K_FLOAT: 613 1.1 darran vbytes = sizeof (uint_t); 614 1.1 darran break; 615 1.1 darran case CTF_K_ARRAY: 616 1.1 darran vbytes = sizeof (ctf_array_t); 617 1.1 darran break; 618 1.1 darran case CTF_K_FUNCTION: 619 1.1 darran vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 620 1.1 darran break; 621 1.1 darran case CTF_K_STRUCT: 622 1.1 darran case CTF_K_UNION: 623 1.1 darran if (size < CTF_LSTRUCT_THRESH) { 624 1.1 darran ctf_member_t *mp = (ctf_member_t *) 625 1.1 darran ((uintptr_t)tp + increment); 626 1.1 darran 627 1.1 darran vbytes = sizeof (ctf_member_t) * vlen; 628 1.1 darran for (n = vlen; n != 0; n--, mp++) 629 1.1 darran child |= CTF_TYPE_ISCHILD(mp->ctm_type); 630 1.1 darran } else { 631 1.1 darran ctf_lmember_t *lmp = (ctf_lmember_t *) 632 1.1 darran ((uintptr_t)tp + increment); 633 1.1 darran 634 1.1 darran vbytes = sizeof (ctf_lmember_t) * vlen; 635 1.1 darran for (n = vlen; n != 0; n--, lmp++) 636 1.1 darran child |= 637 1.1 darran CTF_TYPE_ISCHILD(lmp->ctlm_type); 638 1.1 darran } 639 1.1 darran break; 640 1.1 darran case CTF_K_ENUM: 641 1.1 darran vbytes = sizeof (ctf_enum_t) * vlen; 642 1.1 darran break; 643 1.1 darran case CTF_K_FORWARD: 644 1.1 darran /* 645 1.1 darran * For forward declarations, ctt_type is the CTF_K_* 646 1.1 darran * kind for the tag, so bump that population count too. 647 1.1 darran * If ctt_type is unknown, treat the tag as a struct. 648 1.1 darran */ 649 1.1 darran if (tp->ctt_type == CTF_K_UNKNOWN || 650 1.1 darran tp->ctt_type >= CTF_K_MAX) 651 1.1 darran pop[CTF_K_STRUCT]++; 652 1.1 darran else 653 1.1 darran pop[tp->ctt_type]++; 654 1.1 darran /*FALLTHRU*/ 655 1.1 darran case CTF_K_UNKNOWN: 656 1.1 darran vbytes = 0; 657 1.1 darran break; 658 1.1 darran case CTF_K_POINTER: 659 1.1 darran case CTF_K_TYPEDEF: 660 1.1 darran case CTF_K_VOLATILE: 661 1.1 darran case CTF_K_CONST: 662 1.1 darran case CTF_K_RESTRICT: 663 1.1 darran child |= CTF_TYPE_ISCHILD(tp->ctt_type); 664 1.1 darran vbytes = 0; 665 1.1 darran break; 666 1.1 darran default: 667 1.24 chs printf("%s(%d): detected invalid CTF kind -- %u\n", 668 1.24 chs __func__, __LINE__, kind); 669 1.1 darran return (EIO); 670 1.1 darran } 671 1.1 darran tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 672 1.1 darran pop[kind]++; 673 1.1 darran } 674 1.1 darran 675 1.24 chs /* account for a sentinel value below */ 676 1.24 chs ctf_typemax++; 677 1.3 darran mc->typlen = ctf_typemax; 678 1.1 darran 679 1.24 chs xp = malloc(sizeof(uint32_t) * ctf_typemax, M_FBT, M_ZERO | M_WAITOK); 680 1.1 darran 681 1.3 darran mc->typoffp = xp; 682 1.1 darran 683 1.1 darran /* type id 0 is used as a sentinel value */ 684 1.1 darran *xp++ = 0; 685 1.1 darran 686 1.1 darran /* 687 1.1 darran * In the second pass, fill in the type offset. 688 1.1 darran */ 689 1.1 darran for (tp = tbuf; tp < tend; xp++) { 690 1.1 darran ushort_t kind = CTF_INFO_KIND(tp->ctt_info); 691 1.1 darran ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info); 692 1.1 darran ssize_t size, increment; 693 1.1 darran 694 1.1 darran size_t vbytes; 695 1.1 darran uint_t n; 696 1.1 darran 697 1.1 darran (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment); 698 1.1 darran 699 1.1 darran switch (kind) { 700 1.1 darran case CTF_K_INTEGER: 701 1.1 darran case CTF_K_FLOAT: 702 1.1 darran vbytes = sizeof (uint_t); 703 1.1 darran break; 704 1.1 darran case CTF_K_ARRAY: 705 1.1 darran vbytes = sizeof (ctf_array_t); 706 1.1 darran break; 707 1.1 darran case CTF_K_FUNCTION: 708 1.1 darran vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 709 1.1 darran break; 710 1.1 darran case CTF_K_STRUCT: 711 1.1 darran case CTF_K_UNION: 712 1.1 darran if (size < CTF_LSTRUCT_THRESH) { 713 1.1 darran ctf_member_t *mp = (ctf_member_t *) 714 1.1 darran ((uintptr_t)tp + increment); 715 1.1 darran 716 1.1 darran vbytes = sizeof (ctf_member_t) * vlen; 717 1.1 darran for (n = vlen; n != 0; n--, mp++) 718 1.1 darran child |= CTF_TYPE_ISCHILD(mp->ctm_type); 719 1.1 darran } else { 720 1.1 darran ctf_lmember_t *lmp = (ctf_lmember_t *) 721 1.1 darran ((uintptr_t)tp + increment); 722 1.1 darran 723 1.1 darran vbytes = sizeof (ctf_lmember_t) * vlen; 724 1.1 darran for (n = vlen; n != 0; n--, lmp++) 725 1.1 darran child |= 726 1.1 darran CTF_TYPE_ISCHILD(lmp->ctlm_type); 727 1.1 darran } 728 1.1 darran break; 729 1.1 darran case CTF_K_ENUM: 730 1.1 darran vbytes = sizeof (ctf_enum_t) * vlen; 731 1.1 darran break; 732 1.1 darran case CTF_K_FORWARD: 733 1.1 darran case CTF_K_UNKNOWN: 734 1.1 darran vbytes = 0; 735 1.1 darran break; 736 1.1 darran case CTF_K_POINTER: 737 1.1 darran case CTF_K_TYPEDEF: 738 1.1 darran case CTF_K_VOLATILE: 739 1.1 darran case CTF_K_CONST: 740 1.1 darran case CTF_K_RESTRICT: 741 1.1 darran vbytes = 0; 742 1.1 darran break; 743 1.1 darran default: 744 1.1 darran printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind); 745 1.1 darran return (EIO); 746 1.1 darran } 747 1.1 darran *xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata); 748 1.1 darran tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 749 1.1 darran } 750 1.1 darran 751 1.1 darran return (0); 752 1.1 darran } 753 1.1 darran 754 1.1 darran /* 755 1.1 darran * CTF Declaration Stack 756 1.1 darran * 757 1.1 darran * In order to implement ctf_type_name(), we must convert a type graph back 758 1.1 darran * into a C type declaration. Unfortunately, a type graph represents a storage 759 1.1 darran * class ordering of the type whereas a type declaration must obey the C rules 760 1.1 darran * for operator precedence, and the two orderings are frequently in conflict. 761 1.1 darran * For example, consider these CTF type graphs and their C declarations: 762 1.1 darran * 763 1.1 darran * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER : int (*)() 764 1.1 darran * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER : int (*)[] 765 1.1 darran * 766 1.1 darran * In each case, parentheses are used to raise operator * to higher lexical 767 1.1 darran * precedence, so the string form of the C declaration cannot be constructed by 768 1.1 darran * walking the type graph links and forming the string from left to right. 769 1.1 darran * 770 1.1 darran * The functions in this file build a set of stacks from the type graph nodes 771 1.1 darran * corresponding to the C operator precedence levels in the appropriate order. 772 1.1 darran * The code in ctf_type_name() can then iterate over the levels and nodes in 773 1.1 darran * lexical precedence order and construct the final C declaration string. 774 1.1 darran */ 775 1.1 darran typedef struct ctf_list { 776 1.1 darran struct ctf_list *l_prev; /* previous pointer or tail pointer */ 777 1.1 darran struct ctf_list *l_next; /* next pointer or head pointer */ 778 1.1 darran } ctf_list_t; 779 1.1 darran 780 1.1 darran #define ctf_list_prev(elem) ((void *)(((ctf_list_t *)(elem))->l_prev)) 781 1.1 darran #define ctf_list_next(elem) ((void *)(((ctf_list_t *)(elem))->l_next)) 782 1.1 darran 783 1.1 darran typedef enum { 784 1.1 darran CTF_PREC_BASE, 785 1.1 darran CTF_PREC_POINTER, 786 1.1 darran CTF_PREC_ARRAY, 787 1.1 darran CTF_PREC_FUNCTION, 788 1.1 darran CTF_PREC_MAX 789 1.1 darran } ctf_decl_prec_t; 790 1.1 darran 791 1.1 darran typedef struct ctf_decl_node { 792 1.1 darran ctf_list_t cd_list; /* linked list pointers */ 793 1.1 darran ctf_id_t cd_type; /* type identifier */ 794 1.1 darran uint_t cd_kind; /* type kind */ 795 1.1 darran uint_t cd_n; /* type dimension if array */ 796 1.1 darran } ctf_decl_node_t; 797 1.1 darran 798 1.1 darran typedef struct ctf_decl { 799 1.1 darran ctf_list_t cd_nodes[CTF_PREC_MAX]; /* declaration node stacks */ 800 1.1 darran int cd_order[CTF_PREC_MAX]; /* storage order of decls */ 801 1.1 darran ctf_decl_prec_t cd_qualp; /* qualifier precision */ 802 1.1 darran ctf_decl_prec_t cd_ordp; /* ordered precision */ 803 1.1 darran char *cd_buf; /* buffer for output */ 804 1.1 darran char *cd_ptr; /* buffer location */ 805 1.1 darran char *cd_end; /* buffer limit */ 806 1.1 darran size_t cd_len; /* buffer space required */ 807 1.1 darran int cd_err; /* saved error value */ 808 1.1 darran } ctf_decl_t; 809 1.1 darran 810 1.1 darran /* 811 1.1 darran * Simple doubly-linked list append routine. This implementation assumes that 812 1.1 darran * each list element contains an embedded ctf_list_t as the first member. 813 1.1 darran * An additional ctf_list_t is used to store the head (l_next) and tail 814 1.1 darran * (l_prev) pointers. The current head and tail list elements have their 815 1.1 darran * previous and next pointers set to NULL, respectively. 816 1.1 darran */ 817 1.1 darran static void 818 1.1 darran ctf_list_append(ctf_list_t *lp, void *new) 819 1.1 darran { 820 1.1 darran ctf_list_t *p = lp->l_prev; /* p = tail list element */ 821 1.1 darran ctf_list_t *q = new; /* q = new list element */ 822 1.1 darran 823 1.1 darran lp->l_prev = q; 824 1.1 darran q->l_prev = p; 825 1.1 darran q->l_next = NULL; 826 1.1 darran 827 1.1 darran if (p != NULL) 828 1.1 darran p->l_next = q; 829 1.1 darran else 830 1.1 darran lp->l_next = q; 831 1.1 darran } 832 1.1 darran 833 1.1 darran /* 834 1.1 darran * Prepend the specified existing element to the given ctf_list_t. The 835 1.1 darran * existing pointer should be pointing at a struct with embedded ctf_list_t. 836 1.1 darran */ 837 1.1 darran static void 838 1.1 darran ctf_list_prepend(ctf_list_t *lp, void *new) 839 1.1 darran { 840 1.1 darran ctf_list_t *p = new; /* p = new list element */ 841 1.1 darran ctf_list_t *q = lp->l_next; /* q = head list element */ 842 1.1 darran 843 1.1 darran lp->l_next = p; 844 1.1 darran p->l_prev = NULL; 845 1.1 darran p->l_next = q; 846 1.1 darran 847 1.1 darran if (q != NULL) 848 1.1 darran q->l_prev = p; 849 1.1 darran else 850 1.1 darran lp->l_prev = p; 851 1.1 darran } 852 1.1 darran 853 1.1 darran static void 854 1.1 darran ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len) 855 1.1 darran { 856 1.1 darran int i; 857 1.1 darran 858 1.1 darran bzero(cd, sizeof (ctf_decl_t)); 859 1.1 darran 860 1.1 darran for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) 861 1.1 darran cd->cd_order[i] = CTF_PREC_BASE - 1; 862 1.1 darran 863 1.1 darran cd->cd_qualp = CTF_PREC_BASE; 864 1.1 darran cd->cd_ordp = CTF_PREC_BASE; 865 1.1 darran 866 1.1 darran cd->cd_buf = buf; 867 1.1 darran cd->cd_ptr = buf; 868 1.1 darran cd->cd_end = buf + len; 869 1.1 darran } 870 1.1 darran 871 1.1 darran static void 872 1.1 darran ctf_decl_fini(ctf_decl_t *cd) 873 1.1 darran { 874 1.1 darran ctf_decl_node_t *cdp, *ndp; 875 1.1 darran int i; 876 1.1 darran 877 1.1 darran for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) { 878 1.1 darran for (cdp = ctf_list_next(&cd->cd_nodes[i]); 879 1.1 darran cdp != NULL; cdp = ndp) { 880 1.1 darran ndp = ctf_list_next(cdp); 881 1.1 darran free(cdp, M_FBT); 882 1.1 darran } 883 1.1 darran } 884 1.1 darran } 885 1.1 darran 886 1.1 darran static const ctf_type_t * 887 1.3 darran ctf_lookup_by_id(mod_ctf_t *mc, ctf_id_t type) 888 1.1 darran { 889 1.1 darran const ctf_type_t *tp; 890 1.1 darran uint32_t offset; 891 1.3 darran uint32_t *typoff = mc->typoffp; 892 1.1 darran 893 1.3 darran if (type >= mc->typlen) { 894 1.3 darran printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,mc->typlen); 895 1.1 darran return(NULL); 896 1.1 darran } 897 1.1 darran 898 1.1 darran /* Check if the type isn't cross-referenced. */ 899 1.1 darran if ((offset = typoff[type]) == 0) { 900 1.1 darran printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type); 901 1.1 darran return(NULL); 902 1.1 darran } 903 1.1 darran 904 1.3 darran tp = (const ctf_type_t *)(mc->ctftab + offset + sizeof(ctf_header_t)); 905 1.1 darran 906 1.1 darran return (tp); 907 1.1 darran } 908 1.1 darran 909 1.1 darran static void 910 1.3 darran fbt_array_info(mod_ctf_t *mc, ctf_id_t type, ctf_arinfo_t *arp) 911 1.1 darran { 912 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab; 913 1.1 darran const ctf_type_t *tp; 914 1.1 darran const ctf_array_t *ap; 915 1.1 darran ssize_t increment; 916 1.1 darran 917 1.1 darran bzero(arp, sizeof(*arp)); 918 1.1 darran 919 1.3 darran if ((tp = ctf_lookup_by_id(mc, type)) == NULL) 920 1.1 darran return; 921 1.1 darran 922 1.1 darran if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY) 923 1.1 darran return; 924 1.1 darran 925 1.1 darran (void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment); 926 1.1 darran 927 1.1 darran ap = (const ctf_array_t *)((uintptr_t)tp + increment); 928 1.1 darran arp->ctr_contents = ap->cta_contents; 929 1.1 darran arp->ctr_index = ap->cta_index; 930 1.1 darran arp->ctr_nelems = ap->cta_nelems; 931 1.1 darran } 932 1.1 darran 933 1.1 darran static const char * 934 1.3 darran ctf_strptr(mod_ctf_t *mc, int name) 935 1.1 darran { 936 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;; 937 1.1 darran const char *strp = ""; 938 1.1 darran 939 1.1 darran if (name < 0 || name >= hp->cth_strlen) 940 1.1 darran return(strp); 941 1.1 darran 942 1.3 darran strp = (const char *)(mc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t)); 943 1.1 darran 944 1.1 darran return (strp); 945 1.1 darran } 946 1.1 darran 947 1.1 darran static void 948 1.3 darran ctf_decl_push(ctf_decl_t *cd, mod_ctf_t *mc, ctf_id_t type) 949 1.1 darran { 950 1.1 darran ctf_decl_node_t *cdp; 951 1.1 darran ctf_decl_prec_t prec; 952 1.1 darran uint_t kind, n = 1; 953 1.1 darran int is_qual = 0; 954 1.1 darran 955 1.1 darran const ctf_type_t *tp; 956 1.1 darran ctf_arinfo_t ar; 957 1.1 darran 958 1.3 darran if ((tp = ctf_lookup_by_id(mc, type)) == NULL) { 959 1.1 darran cd->cd_err = ENOENT; 960 1.1 darran return; 961 1.1 darran } 962 1.1 darran 963 1.1 darran switch (kind = CTF_INFO_KIND(tp->ctt_info)) { 964 1.1 darran case CTF_K_ARRAY: 965 1.3 darran fbt_array_info(mc, type, &ar); 966 1.3 darran ctf_decl_push(cd, mc, ar.ctr_contents); 967 1.1 darran n = ar.ctr_nelems; 968 1.1 darran prec = CTF_PREC_ARRAY; 969 1.1 darran break; 970 1.1 darran 971 1.1 darran case CTF_K_TYPEDEF: 972 1.3 darran if (ctf_strptr(mc, tp->ctt_name)[0] == '\0') { 973 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type); 974 1.1 darran return; 975 1.1 darran } 976 1.1 darran prec = CTF_PREC_BASE; 977 1.1 darran break; 978 1.1 darran 979 1.1 darran case CTF_K_FUNCTION: 980 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type); 981 1.1 darran prec = CTF_PREC_FUNCTION; 982 1.1 darran break; 983 1.1 darran 984 1.1 darran case CTF_K_POINTER: 985 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type); 986 1.1 darran prec = CTF_PREC_POINTER; 987 1.1 darran break; 988 1.1 darran 989 1.1 darran case CTF_K_VOLATILE: 990 1.1 darran case CTF_K_CONST: 991 1.1 darran case CTF_K_RESTRICT: 992 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type); 993 1.1 darran prec = cd->cd_qualp; 994 1.1 darran is_qual++; 995 1.1 darran break; 996 1.1 darran 997 1.1 darran default: 998 1.1 darran prec = CTF_PREC_BASE; 999 1.1 darran } 1000 1.1 darran 1001 1.24 chs cdp = malloc(sizeof(*cdp), M_FBT, M_WAITOK); 1002 1.1 darran cdp->cd_type = type; 1003 1.1 darran cdp->cd_kind = kind; 1004 1.1 darran cdp->cd_n = n; 1005 1.1 darran 1006 1.1 darran if (ctf_list_next(&cd->cd_nodes[prec]) == NULL) 1007 1.1 darran cd->cd_order[prec] = cd->cd_ordp++; 1008 1.1 darran 1009 1.1 darran /* 1010 1.1 darran * Reset cd_qualp to the highest precedence level that we've seen so 1011 1.1 darran * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER). 1012 1.1 darran */ 1013 1.1 darran if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY) 1014 1.1 darran cd->cd_qualp = prec; 1015 1.1 darran 1016 1.1 darran /* 1017 1.1 darran * C array declarators are ordered inside out so prepend them. Also by 1018 1.1 darran * convention qualifiers of base types precede the type specifier (e.g. 1019 1.1 darran * const int vs. int const) even though the two forms are equivalent. 1020 1.1 darran */ 1021 1.1 darran if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE)) 1022 1.1 darran ctf_list_prepend(&cd->cd_nodes[prec], cdp); 1023 1.1 darran else 1024 1.1 darran ctf_list_append(&cd->cd_nodes[prec], cdp); 1025 1.1 darran } 1026 1.1 darran 1027 1.1 darran static void 1028 1.1 darran ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...) 1029 1.1 darran { 1030 1.1 darran size_t len = (size_t)(cd->cd_end - cd->cd_ptr); 1031 1.1 darran va_list ap; 1032 1.1 darran size_t n; 1033 1.1 darran 1034 1.1 darran va_start(ap, format); 1035 1.1 darran n = vsnprintf(cd->cd_ptr, len, format, ap); 1036 1.1 darran va_end(ap); 1037 1.1 darran 1038 1.1 darran cd->cd_ptr += MIN(n, len); 1039 1.1 darran cd->cd_len += n; 1040 1.1 darran } 1041 1.1 darran 1042 1.1 darran static ssize_t 1043 1.3 darran fbt_type_name(mod_ctf_t *mc, ctf_id_t type, char *buf, size_t len) 1044 1.1 darran { 1045 1.1 darran ctf_decl_t cd; 1046 1.1 darran ctf_decl_node_t *cdp; 1047 1.1 darran ctf_decl_prec_t prec, lp, rp; 1048 1.1 darran int ptr, arr; 1049 1.1 darran uint_t k; 1050 1.1 darran 1051 1.3 darran if (mc == NULL && type == CTF_ERR) 1052 1.1 darran return (-1); /* simplify caller code by permitting CTF_ERR */ 1053 1.1 darran 1054 1.1 darran ctf_decl_init(&cd, buf, len); 1055 1.3 darran ctf_decl_push(&cd, mc, type); 1056 1.1 darran 1057 1.1 darran if (cd.cd_err != 0) { 1058 1.1 darran ctf_decl_fini(&cd); 1059 1.1 darran return (-1); 1060 1.1 darran } 1061 1.1 darran 1062 1.1 darran /* 1063 1.1 darran * If the type graph's order conflicts with lexical precedence order 1064 1.1 darran * for pointers or arrays, then we need to surround the declarations at 1065 1.1 darran * the corresponding lexical precedence with parentheses. This can 1066 1.1 darran * result in either a parenthesized pointer (*) as in int (*)() or 1067 1.1 darran * int (*)[], or in a parenthesized pointer and array as in int (*[])(). 1068 1.1 darran */ 1069 1.1 darran ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER; 1070 1.1 darran arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY; 1071 1.1 darran 1072 1.1 darran rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1; 1073 1.1 darran lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1; 1074 1.1 darran 1075 1.1 darran k = CTF_K_POINTER; /* avoid leading whitespace (see below) */ 1076 1.1 darran 1077 1.1 darran for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) { 1078 1.1 darran for (cdp = ctf_list_next(&cd.cd_nodes[prec]); 1079 1.1 darran cdp != NULL; cdp = ctf_list_next(cdp)) { 1080 1.1 darran 1081 1.1 darran const ctf_type_t *tp = 1082 1.3 darran ctf_lookup_by_id(mc, cdp->cd_type); 1083 1.3 darran const char *name = ctf_strptr(mc, tp->ctt_name); 1084 1.1 darran 1085 1.1 darran if (k != CTF_K_POINTER && k != CTF_K_ARRAY) 1086 1.1 darran ctf_decl_sprintf(&cd, " "); 1087 1.1 darran 1088 1.1 darran if (lp == prec) { 1089 1.1 darran ctf_decl_sprintf(&cd, "("); 1090 1.1 darran lp = -1; 1091 1.1 darran } 1092 1.1 darran 1093 1.1 darran switch (cdp->cd_kind) { 1094 1.1 darran case CTF_K_INTEGER: 1095 1.1 darran case CTF_K_FLOAT: 1096 1.1 darran case CTF_K_TYPEDEF: 1097 1.1 darran ctf_decl_sprintf(&cd, "%s", name); 1098 1.1 darran break; 1099 1.1 darran case CTF_K_POINTER: 1100 1.1 darran ctf_decl_sprintf(&cd, "*"); 1101 1.1 darran break; 1102 1.1 darran case CTF_K_ARRAY: 1103 1.1 darran ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n); 1104 1.1 darran break; 1105 1.1 darran case CTF_K_FUNCTION: 1106 1.1 darran ctf_decl_sprintf(&cd, "()"); 1107 1.1 darran break; 1108 1.1 darran case CTF_K_STRUCT: 1109 1.1 darran case CTF_K_FORWARD: 1110 1.1 darran ctf_decl_sprintf(&cd, "struct %s", name); 1111 1.1 darran break; 1112 1.1 darran case CTF_K_UNION: 1113 1.1 darran ctf_decl_sprintf(&cd, "union %s", name); 1114 1.1 darran break; 1115 1.1 darran case CTF_K_ENUM: 1116 1.1 darran ctf_decl_sprintf(&cd, "enum %s", name); 1117 1.1 darran break; 1118 1.1 darran case CTF_K_VOLATILE: 1119 1.1 darran ctf_decl_sprintf(&cd, "volatile"); 1120 1.1 darran break; 1121 1.1 darran case CTF_K_CONST: 1122 1.1 darran ctf_decl_sprintf(&cd, "const"); 1123 1.1 darran break; 1124 1.1 darran case CTF_K_RESTRICT: 1125 1.1 darran ctf_decl_sprintf(&cd, "restrict"); 1126 1.1 darran break; 1127 1.1 darran } 1128 1.1 darran 1129 1.1 darran k = cdp->cd_kind; 1130 1.1 darran } 1131 1.1 darran 1132 1.1 darran if (rp == prec) 1133 1.1 darran ctf_decl_sprintf(&cd, ")"); 1134 1.1 darran } 1135 1.1 darran 1136 1.1 darran ctf_decl_fini(&cd); 1137 1.1 darran return (cd.cd_len); 1138 1.1 darran } 1139 1.1 darran 1140 1.1 darran static void 1141 1.1 darran fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc) 1142 1.1 darran { 1143 1.1 darran const ushort_t *dp; 1144 1.1 darran fbt_probe_t *fbt = parg; 1145 1.24 chs mod_ctf_t *mc; 1146 1.24 chs modctl_t *ctl = fbt->fbtp_ctl; 1147 1.1 darran int ndx = desc->dtargd_ndx; 1148 1.1 darran int symindx = fbt->fbtp_symindx; 1149 1.1 darran uint32_t *ctfoff; 1150 1.1 darran uint32_t offset; 1151 1.1 darran ushort_t info, kind, n; 1152 1.3 darran int nsyms; 1153 1.1 darran 1154 1.24 chs if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) { 1155 1.24 chs (void) strcpy(desc->dtargd_native, "int"); 1156 1.24 chs return; 1157 1.24 chs } 1158 1.24 chs 1159 1.1 darran desc->dtargd_ndx = DTRACE_ARGNONE; 1160 1.1 darran 1161 1.24 chs /* Get a pointer to the CTF data and its length. */ 1162 1.3 darran if (mod_ctf_get(ctl, &mc) != 0) { 1163 1.24 chs static int report = 0; 1164 1.6 darran if (report < 1) { 1165 1.24 chs report++; 1166 1.24 chs printf("FBT: Error no CTF section found in module \"%s\"\n", 1167 1.24 chs module_name(ctl)); 1168 1.6 darran } 1169 1.1 darran /* No CTF data? Something wrong? *shrug* */ 1170 1.1 darran return; 1171 1.3 darran } 1172 1.3 darran 1173 1.24 chs nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym; 1174 1.1 darran 1175 1.1 darran /* Check if this module hasn't been initialised yet. */ 1176 1.24 chs if (mc->ctfoffp == NULL) { 1177 1.1 darran /* 1178 1.1 darran * Initialise the CTF object and function symindx to 1179 1.1 darran * byte offset array. 1180 1.1 darran */ 1181 1.24 chs if (fbt_ctfoff_init(ctl, mc) != 0) 1182 1.1 darran return; 1183 1.1 darran 1184 1.1 darran /* Initialise the CTF type to byte offset array. */ 1185 1.24 chs if (fbt_typoff_init(mc) != 0) 1186 1.1 darran return; 1187 1.1 darran } 1188 1.1 darran 1189 1.24 chs ctfoff = mc->ctfoffp; 1190 1.1 darran 1191 1.24 chs if (ctfoff == NULL || mc->typoffp == NULL) { 1192 1.1 darran return; 1193 1.3 darran } 1194 1.1 darran 1195 1.1 darran /* Check if the symbol index is out of range. */ 1196 1.3 darran if (symindx >= nsyms) 1197 1.1 darran return; 1198 1.1 darran 1199 1.1 darran /* Check if the symbol isn't cross-referenced. */ 1200 1.1 darran if ((offset = ctfoff[symindx]) == 0xffffffff) 1201 1.1 darran return; 1202 1.1 darran 1203 1.24 chs dp = (const ushort_t *)(mc->ctftab + offset + sizeof(ctf_header_t)); 1204 1.1 darran 1205 1.1 darran info = *dp++; 1206 1.1 darran kind = CTF_INFO_KIND(info); 1207 1.1 darran n = CTF_INFO_VLEN(info); 1208 1.1 darran 1209 1.1 darran if (kind == CTF_K_UNKNOWN && n == 0) { 1210 1.12 christos printf("%s(%d): Unknown function %s!\n",__func__,__LINE__, 1211 1.12 christos fbt->fbtp_name); 1212 1.1 darran return; 1213 1.1 darran } 1214 1.1 darran 1215 1.1 darran if (kind != CTF_K_FUNCTION) { 1216 1.12 christos printf("%s(%d): Expected a function %s!\n",__func__,__LINE__, 1217 1.12 christos fbt->fbtp_name); 1218 1.1 darran return; 1219 1.1 darran } 1220 1.1 darran 1221 1.24 chs if (fbt->fbtp_roffset != 0) { 1222 1.24 chs /* Only return type is available for args[1] in return probe. */ 1223 1.24 chs if (ndx > 1) 1224 1.24 chs return; 1225 1.24 chs ASSERT(ndx == 1); 1226 1.24 chs } else { 1227 1.24 chs /* Check if the requested argument doesn't exist. */ 1228 1.24 chs if (ndx >= n) 1229 1.24 chs return; 1230 1.1 darran 1231 1.24 chs /* Skip the return type and arguments up to the one requested. */ 1232 1.24 chs dp += ndx + 1; 1233 1.24 chs } 1234 1.1 darran 1235 1.24 chs if (fbt_type_name(mc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0) 1236 1.1 darran desc->dtargd_ndx = ndx; 1237 1.1 darran 1238 1.1 darran return; 1239 1.1 darran } 1240 1.1 darran 1241 1.24 chs #ifdef __FreeBSD__ 1242 1.24 chs static int 1243 1.24 chs fbt_linker_file_cb(linker_file_t lf, void *arg) 1244 1.24 chs { 1245 1.24 chs 1246 1.24 chs fbt_provide_module(arg, lf); 1247 1.24 chs 1248 1.24 chs return (0); 1249 1.24 chs } 1250 1.24 chs #endif 1251 1.24 chs 1252 1.1 darran static void 1253 1.3 darran fbt_load(void) 1254 1.1 darran { 1255 1.24 chs 1256 1.24 chs #ifdef __FreeBSD__ 1257 1.24 chs /* Create the /dev/dtrace/fbt entry. */ 1258 1.24 chs fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 1259 1.24 chs "dtrace/fbt"); 1260 1.24 chs #endif 1261 1.24 chs #ifdef __NetBSD__ 1262 1.24 chs (void) module_specific_key_create(&fbt_module_key, fbt_module_dtor); 1263 1.24 chs #endif 1264 1.24 chs 1265 1.1 darran /* Default the probe table size if not specified. */ 1266 1.1 darran if (fbt_probetab_size == 0) 1267 1.1 darran fbt_probetab_size = FBT_PROBETAB_SIZE; 1268 1.1 darran 1269 1.1 darran /* Choose the hash mask for the probe table. */ 1270 1.1 darran fbt_probetab_mask = fbt_probetab_size - 1; 1271 1.1 darran 1272 1.1 darran /* Allocate memory for the probe table. */ 1273 1.1 darran fbt_probetab = 1274 1.1 darran malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO); 1275 1.1 darran 1276 1.1 darran dtrace_doubletrap_func = fbt_doubletrap; 1277 1.1 darran dtrace_invop_add(fbt_invop); 1278 1.1 darran 1279 1.1 darran if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER, 1280 1.1 darran NULL, &fbt_pops, NULL, &fbt_id) != 0) 1281 1.1 darran return; 1282 1.1 darran } 1283 1.1 darran 1284 1.1 darran 1285 1.1 darran static int 1286 1.3 darran fbt_unload(void) 1287 1.1 darran { 1288 1.1 darran int error = 0; 1289 1.1 darran 1290 1.1 darran /* De-register the invalid opcode handler. */ 1291 1.1 darran dtrace_invop_remove(fbt_invop); 1292 1.1 darran 1293 1.1 darran dtrace_doubletrap_func = NULL; 1294 1.1 darran 1295 1.1 darran /* De-register this DTrace provider. */ 1296 1.1 darran if ((error = dtrace_unregister(fbt_id)) != 0) 1297 1.1 darran return (error); 1298 1.1 darran 1299 1.1 darran /* Free the probe table. */ 1300 1.1 darran free(fbt_probetab, M_FBT); 1301 1.1 darran fbt_probetab = NULL; 1302 1.1 darran fbt_probetab_mask = 0; 1303 1.1 darran 1304 1.24 chs #ifdef __FreeBSD__ 1305 1.24 chs destroy_dev(fbt_cdev); 1306 1.24 chs #endif 1307 1.24 chs #ifdef __NetBSD__ 1308 1.24 chs (void) module_specific_key_delete(fbt_module_key); 1309 1.24 chs #endif 1310 1.1 darran return (error); 1311 1.1 darran } 1312 1.1 darran 1313 1.3 darran 1314 1.1 darran static int 1315 1.18 ozaki dtrace_fbt_modcmd(modcmd_t cmd, void *data) 1316 1.1 darran { 1317 1.26 kamil int bmajor = -1, cmajor = 352; 1318 1.17 ozaki int error; 1319 1.1 darran 1320 1.3 darran switch (cmd) { 1321 1.3 darran case MODULE_CMD_INIT: 1322 1.3 darran fbt_load(); 1323 1.3 darran return devsw_attach("fbt", NULL, &bmajor, 1324 1.3 darran &fbt_cdevsw, &cmajor); 1325 1.3 darran case MODULE_CMD_FINI: 1326 1.17 ozaki error = fbt_unload(); 1327 1.17 ozaki if (error != 0) 1328 1.17 ozaki return error; 1329 1.28 riastrad devsw_detach(NULL, &fbt_cdevsw); 1330 1.28 riastrad return 0; 1331 1.17 ozaki case MODULE_CMD_AUTOUNLOAD: 1332 1.17 ozaki return EBUSY; 1333 1.1 darran default: 1334 1.3 darran return ENOTTY; 1335 1.1 darran } 1336 1.1 darran } 1337 1.1 darran 1338 1.1 darran static int 1339 1.3 darran fbt_open(dev_t dev, int flags, int mode, struct lwp *l) 1340 1.1 darran { 1341 1.1 darran return (0); 1342 1.1 darran } 1343 1.1 darran 1344 1.24 chs #ifdef __FreeBSD__ 1345 1.24 chs SYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL); 1346 1.24 chs SYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL); 1347 1.24 chs 1348 1.24 chs DEV_MODULE(fbt, fbt_modevent, NULL); 1349 1.24 chs MODULE_VERSION(fbt, 1); 1350 1.24 chs MODULE_DEPEND(fbt, dtrace, 1, 1, 1); 1351 1.24 chs MODULE_DEPEND(fbt, opensolaris, 1, 1, 1); 1352 1.24 chs #endif 1353 1.24 chs #ifdef __NetBSD__ 1354 1.20 pgoyette MODULE(MODULE_CLASS_MISC, dtrace_fbt, "dtrace,zlib"); 1355 1.24 chs #endif 1356