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