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 * Portions Copyright 2010 The FreeBSD Foundation 22 * 23 * $FreeBSD$ 24 */ 25 26 /* 27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * Copyright (c) 2015, Joyent, Inc. All rights reserved. 33 */ 34 35 #include <sys/atomic.h> 36 #include <sys/errno.h> 37 #include <sys/stat.h> 38 #include <sys/modctl.h> 39 #include <sys/conf.h> 40 #include <sys/systm.h> 41 #ifdef illumos 42 #include <sys/ddi.h> 43 #endif 44 #include <sys/sunddi.h> 45 #include <sys/cpuvar.h> 46 #include <sys/kmem.h> 47 #ifdef illumos 48 #include <sys/strsubr.h> 49 #endif 50 #include <sys/fasttrap.h> 51 #include <sys/fasttrap_impl.h> 52 #include <sys/fasttrap_isa.h> 53 #include <sys/dtrace.h> 54 #include <sys/dtrace_impl.h> 55 #include <sys/sysmacros.h> 56 #include <sys/proc.h> 57 #include <sys/policy.h> 58 #ifdef illumos 59 #include <util/qsort.h> 60 #endif 61 #include <sys/mutex.h> 62 #include <sys/kernel.h> 63 #ifndef illumos 64 #include <sys/dtrace_bsd.h> 65 #include <sys/eventhandler.h> 66 #include <sys/rmlock.h> 67 #include <sys/sysctl.h> 68 #include <sys/u8_textprep.h> 69 #include <sys/user.h> 70 71 #include <vm/vm.h> 72 #include <vm/pmap.h> 73 #include <vm/vm_map.h> 74 #include <vm/vm_param.h> 75 76 #include <cddl/dev/dtrace/dtrace_cddl.h> 77 #endif 78 79 /* 80 * User-Land Trap-Based Tracing 81 * ---------------------------- 82 * 83 * The fasttrap provider allows DTrace consumers to instrument any user-level 84 * instruction to gather data; this includes probes with semantic 85 * signifigance like entry and return as well as simple offsets into the 86 * function. While the specific techniques used are very ISA specific, the 87 * methodology is generalizable to any architecture. 88 * 89 * 90 * The General Methodology 91 * ----------------------- 92 * 93 * With the primary goal of tracing every user-land instruction and the 94 * limitation that we can't trust user space so don't want to rely on much 95 * information there, we begin by replacing the instructions we want to trace 96 * with trap instructions. Each instruction we overwrite is saved into a hash 97 * table keyed by process ID and pc address. When we enter the kernel due to 98 * this trap instruction, we need the effects of the replaced instruction to 99 * appear to have occurred before we proceed with the user thread's 100 * execution. 101 * 102 * Each user level thread is represented by a ulwp_t structure which is 103 * always easily accessible through a register. The most basic way to produce 104 * the effects of the instruction we replaced is to copy that instruction out 105 * to a bit of scratch space reserved in the user thread's ulwp_t structure 106 * (a sort of kernel-private thread local storage), set the PC to that 107 * scratch space and single step. When we reenter the kernel after single 108 * stepping the instruction we must then adjust the PC to point to what would 109 * normally be the next instruction. Of course, special care must be taken 110 * for branches and jumps, but these represent such a small fraction of any 111 * instruction set that writing the code to emulate these in the kernel is 112 * not too difficult. 113 * 114 * Return probes may require several tracepoints to trace every return site, 115 * and, conversely, each tracepoint may activate several probes (the entry 116 * and offset 0 probes, for example). To solve this muliplexing problem, 117 * tracepoints contain lists of probes to activate and probes contain lists 118 * of tracepoints to enable. If a probe is activated, it adds its ID to 119 * existing tracepoints or creates new ones as necessary. 120 * 121 * Most probes are activated _before_ the instruction is executed, but return 122 * probes are activated _after_ the effects of the last instruction of the 123 * function are visible. Return probes must be fired _after_ we have 124 * single-stepped the instruction whereas all other probes are fired 125 * beforehand. 126 * 127 * 128 * Lock Ordering 129 * ------------- 130 * 131 * The lock ordering below -- both internally and with respect to the DTrace 132 * framework -- is a little tricky and bears some explanation. Each provider 133 * has a lock (ftp_mtx) that protects its members including reference counts 134 * for enabled probes (ftp_rcount), consumers actively creating probes 135 * (ftp_ccount) and USDT consumers (ftp_mcount); all three prevent a provider 136 * from being freed. A provider is looked up by taking the bucket lock for the 137 * provider hash table, and is returned with its lock held. The provider lock 138 * may be taken in functions invoked by the DTrace framework, but may not be 139 * held while calling functions in the DTrace framework. 140 * 141 * To ensure consistency over multiple calls to the DTrace framework, the 142 * creation lock (ftp_cmtx) should be held. Naturally, the creation lock may 143 * not be taken when holding the provider lock as that would create a cyclic 144 * lock ordering. In situations where one would naturally take the provider 145 * lock and then the creation lock, we instead up a reference count to prevent 146 * the provider from disappearing, drop the provider lock, and acquire the 147 * creation lock. 148 * 149 * Briefly: 150 * bucket lock before provider lock 151 * DTrace before provider lock 152 * creation lock before DTrace 153 * never hold the provider lock and creation lock simultaneously 154 */ 155 156 static d_open_t fasttrap_open; 157 static d_ioctl_t fasttrap_ioctl; 158 159 static struct cdevsw fasttrap_cdevsw = { 160 .d_version = D_VERSION, 161 .d_open = fasttrap_open, 162 .d_ioctl = fasttrap_ioctl, 163 .d_name = "fasttrap", 164 }; 165 static struct cdev *fasttrap_cdev; 166 static dtrace_meta_provider_id_t fasttrap_meta_id; 167 168 static struct proc *fasttrap_cleanup_proc; 169 static struct mtx fasttrap_cleanup_mtx; 170 static uint_t fasttrap_cleanup_work, fasttrap_cleanup_drain, fasttrap_cleanup_cv; 171 172 /* 173 * Generation count on modifications to the global tracepoint lookup table. 174 */ 175 static volatile uint64_t fasttrap_mod_gen; 176 177 /* 178 * When the fasttrap provider is loaded, fasttrap_max is set to either 179 * FASTTRAP_MAX_DEFAULT, or the value for fasttrap-max-probes in the 180 * fasttrap.conf file (Illumos), or the value provied in the loader.conf (FreeBSD). 181 * Each time a probe is created, fasttrap_total is incremented by the number 182 * of tracepoints that may be associated with that probe; fasttrap_total is capped 183 * at fasttrap_max. 184 */ 185 #define FASTTRAP_MAX_DEFAULT 250000 186 static uint32_t fasttrap_max = FASTTRAP_MAX_DEFAULT; 187 static uint32_t fasttrap_total; 188 189 /* 190 * Copyright (c) 2011, Joyent, Inc. All rights reserved. 191 */ 192 193 #define FASTTRAP_TPOINTS_DEFAULT_SIZE 0x4000 194 #define FASTTRAP_PROVIDERS_DEFAULT_SIZE 0x100 195 #define FASTTRAP_PROCS_DEFAULT_SIZE 0x100 196 197 #define FASTTRAP_PID_NAME "pid" 198 199 fasttrap_hash_t fasttrap_tpoints; 200 static fasttrap_hash_t fasttrap_provs; 201 static fasttrap_hash_t fasttrap_procs; 202 203 static uint64_t fasttrap_pid_count; /* pid ref count */ 204 static kmutex_t fasttrap_count_mtx; /* lock on ref count */ 205 206 #define FASTTRAP_ENABLE_FAIL 1 207 #define FASTTRAP_ENABLE_PARTIAL 2 208 209 static int fasttrap_tracepoint_enable(proc_t *, fasttrap_probe_t *, uint_t); 210 static void fasttrap_tracepoint_disable(proc_t *, fasttrap_probe_t *, uint_t); 211 212 static fasttrap_provider_t *fasttrap_provider_lookup(pid_t, const char *, 213 const dtrace_pattr_t *); 214 static void fasttrap_provider_retire(pid_t, const char *, int); 215 static void fasttrap_provider_free(fasttrap_provider_t *); 216 217 static fasttrap_proc_t *fasttrap_proc_lookup(pid_t); 218 static void fasttrap_proc_release(fasttrap_proc_t *); 219 220 #ifndef illumos 221 static void fasttrap_thread_dtor(void *, struct thread *); 222 #endif 223 224 #define FASTTRAP_PROVS_INDEX(pid, name) \ 225 ((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask) 226 227 #define FASTTRAP_PROCS_INDEX(pid) ((pid) & fasttrap_procs.fth_mask) 228 229 #ifndef illumos 230 struct rmlock fasttrap_tp_lock; 231 static eventhandler_tag fasttrap_thread_dtor_tag; 232 #endif 233 234 static unsigned long tpoints_hash_size = FASTTRAP_TPOINTS_DEFAULT_SIZE; 235 236 #ifdef __FreeBSD__ 237 SYSCTL_DECL(_kern_dtrace); 238 SYSCTL_NODE(_kern_dtrace, OID_AUTO, fasttrap, CTLFLAG_RD, 0, "DTrace fasttrap parameters"); 239 SYSCTL_UINT(_kern_dtrace_fasttrap, OID_AUTO, max_probes, CTLFLAG_RWTUN, &fasttrap_max, 240 FASTTRAP_MAX_DEFAULT, "Maximum number of fasttrap probes"); 241 SYSCTL_ULONG(_kern_dtrace_fasttrap, OID_AUTO, tpoints_hash_size, CTLFLAG_RDTUN, &tpoints_hash_size, 242 FASTTRAP_TPOINTS_DEFAULT_SIZE, "Size of the tracepoint hash table"); 243 #endif 244 245 static int 246 fasttrap_highbit(ulong_t i) 247 { 248 int h = 1; 249 250 if (i == 0) 251 return (0); 252 #ifdef _LP64 253 if (i & 0xffffffff00000000ul) { 254 h += 32; i >>= 32; 255 } 256 #endif 257 if (i & 0xffff0000) { 258 h += 16; i >>= 16; 259 } 260 if (i & 0xff00) { 261 h += 8; i >>= 8; 262 } 263 if (i & 0xf0) { 264 h += 4; i >>= 4; 265 } 266 if (i & 0xc) { 267 h += 2; i >>= 2; 268 } 269 if (i & 0x2) { 270 h += 1; 271 } 272 return (h); 273 } 274 275 static uint_t 276 fasttrap_hash_str(const char *p) 277 { 278 unsigned int g; 279 uint_t hval = 0; 280 281 while (*p) { 282 hval = (hval << 4) + *p++; 283 if ((g = (hval & 0xf0000000)) != 0) 284 hval ^= g >> 24; 285 hval &= ~g; 286 } 287 return (hval); 288 } 289 290 void 291 fasttrap_sigtrap(proc_t *p, kthread_t *t, uintptr_t pc) 292 { 293 #ifdef illumos 294 sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); 295 296 sqp->sq_info.si_signo = SIGTRAP; 297 sqp->sq_info.si_code = TRAP_DTRACE; 298 sqp->sq_info.si_addr = (caddr_t)pc; 299 300 mutex_enter(&p->p_lock); 301 sigaddqa(p, t, sqp); 302 mutex_exit(&p->p_lock); 303 304 if (t != NULL) 305 aston(t); 306 #else 307 ksiginfo_t *ksi = kmem_zalloc(sizeof (ksiginfo_t), KM_SLEEP); 308 309 ksiginfo_init(ksi); 310 ksi->ksi_signo = SIGTRAP; 311 ksi->ksi_code = TRAP_DTRACE; 312 ksi->ksi_addr = (caddr_t)pc; 313 PROC_LOCK(p); 314 (void) tdsendsignal(p, t, SIGTRAP, ksi); 315 PROC_UNLOCK(p); 316 #endif 317 } 318 319 #ifndef illumos 320 /* 321 * Obtain a chunk of scratch space in the address space of the target process. 322 */ 323 fasttrap_scrspace_t * 324 fasttrap_scraddr(struct thread *td, fasttrap_proc_t *fprc) 325 { 326 fasttrap_scrblock_t *scrblk; 327 fasttrap_scrspace_t *scrspc; 328 struct proc *p; 329 vm_offset_t addr; 330 int error, i; 331 332 scrspc = NULL; 333 if (td->t_dtrace_sscr != NULL) { 334 /* If the thread already has scratch space, we're done. */ 335 scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr; 336 return (scrspc); 337 } 338 339 p = td->td_proc; 340 341 mutex_enter(&fprc->ftpc_mtx); 342 if (LIST_EMPTY(&fprc->ftpc_fscr)) { 343 /* 344 * No scratch space is available, so we'll map a new scratch 345 * space block into the traced process' address space. 346 */ 347 addr = 0; 348 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, 349 FASTTRAP_SCRBLOCK_SIZE, 0, VMFS_ANY_SPACE, VM_PROT_ALL, 350 VM_PROT_ALL, 0); 351 if (error != KERN_SUCCESS) 352 goto done; 353 354 scrblk = malloc(sizeof(*scrblk), M_SOLARIS, M_WAITOK); 355 scrblk->ftsb_addr = addr; 356 LIST_INSERT_HEAD(&fprc->ftpc_scrblks, scrblk, ftsb_next); 357 358 /* 359 * Carve the block up into chunks and put them on the free list. 360 */ 361 for (i = 0; 362 i < FASTTRAP_SCRBLOCK_SIZE / FASTTRAP_SCRSPACE_SIZE; i++) { 363 scrspc = malloc(sizeof(*scrspc), M_SOLARIS, M_WAITOK); 364 scrspc->ftss_addr = addr + 365 i * FASTTRAP_SCRSPACE_SIZE; 366 LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, 367 ftss_next); 368 } 369 } 370 371 /* 372 * Take the first scratch chunk off the free list, put it on the 373 * allocated list, and return its address. 374 */ 375 scrspc = LIST_FIRST(&fprc->ftpc_fscr); 376 LIST_REMOVE(scrspc, ftss_next); 377 LIST_INSERT_HEAD(&fprc->ftpc_ascr, scrspc, ftss_next); 378 379 /* 380 * This scratch space is reserved for use by td until the thread exits. 381 */ 382 td->t_dtrace_sscr = scrspc; 383 384 done: 385 mutex_exit(&fprc->ftpc_mtx); 386 387 return (scrspc); 388 } 389 390 /* 391 * Return any allocated per-thread scratch space chunks back to the process' 392 * free list. 393 */ 394 static void 395 fasttrap_thread_dtor(void *arg __unused, struct thread *td) 396 { 397 fasttrap_bucket_t *bucket; 398 fasttrap_proc_t *fprc; 399 fasttrap_scrspace_t *scrspc; 400 pid_t pid; 401 402 if (td->t_dtrace_sscr == NULL) 403 return; 404 405 pid = td->td_proc->p_pid; 406 bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)]; 407 fprc = NULL; 408 409 /* Look up the fasttrap process handle for this process. */ 410 mutex_enter(&bucket->ftb_mtx); 411 for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) { 412 if (fprc->ftpc_pid == pid) { 413 mutex_enter(&fprc->ftpc_mtx); 414 mutex_exit(&bucket->ftb_mtx); 415 break; 416 } 417 } 418 if (fprc == NULL) { 419 mutex_exit(&bucket->ftb_mtx); 420 return; 421 } 422 423 scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr; 424 LIST_REMOVE(scrspc, ftss_next); 425 LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, ftss_next); 426 427 mutex_exit(&fprc->ftpc_mtx); 428 } 429 #endif 430 431 /* 432 * This function ensures that no threads are actively using the memory 433 * associated with probes that were formerly live. 434 */ 435 static void 436 fasttrap_mod_barrier(uint64_t gen) 437 { 438 int i; 439 440 if (gen < fasttrap_mod_gen) 441 return; 442 443 fasttrap_mod_gen++; 444 445 #ifdef illumos 446 CPU_FOREACH(i) { 447 mutex_enter(&fasttrap_cpuc_pid_lock[i]); 448 mutex_exit(&fasttrap_cpuc_pid_lock[i]); 449 } 450 #else 451 rm_wlock(&fasttrap_tp_lock); 452 rm_wunlock(&fasttrap_tp_lock); 453 #endif 454 } 455 456 /* 457 * This function performs asynchronous cleanup of fasttrap providers. The 458 * Solaris implementation of this mechanism use a timeout that's activated in 459 * fasttrap_pid_cleanup(), but this doesn't work in FreeBSD: one may sleep while 460 * holding the DTrace mutexes, but it is unsafe to sleep in a callout handler. 461 * Thus we use a dedicated process to perform the cleanup when requested. 462 */ 463 /*ARGSUSED*/ 464 static void 465 fasttrap_pid_cleanup_cb(void *data) 466 { 467 fasttrap_provider_t **fpp, *fp; 468 fasttrap_bucket_t *bucket; 469 dtrace_provider_id_t provid; 470 int i, later = 0, rval; 471 472 mtx_lock(&fasttrap_cleanup_mtx); 473 while (!fasttrap_cleanup_drain || later > 0) { 474 fasttrap_cleanup_work = 0; 475 mtx_unlock(&fasttrap_cleanup_mtx); 476 477 later = 0; 478 479 /* 480 * Iterate over all the providers trying to remove the marked 481 * ones. If a provider is marked but not retired, we just 482 * have to take a crack at removing it -- it's no big deal if 483 * we can't. 484 */ 485 for (i = 0; i < fasttrap_provs.fth_nent; i++) { 486 bucket = &fasttrap_provs.fth_table[i]; 487 mutex_enter(&bucket->ftb_mtx); 488 fpp = (fasttrap_provider_t **)&bucket->ftb_data; 489 490 while ((fp = *fpp) != NULL) { 491 if (!fp->ftp_marked) { 492 fpp = &fp->ftp_next; 493 continue; 494 } 495 496 mutex_enter(&fp->ftp_mtx); 497 498 /* 499 * If this provider has consumers actively 500 * creating probes (ftp_ccount) or is a USDT 501 * provider (ftp_mcount), we can't unregister 502 * or even condense. 503 */ 504 if (fp->ftp_ccount != 0 || 505 fp->ftp_mcount != 0) { 506 mutex_exit(&fp->ftp_mtx); 507 fp->ftp_marked = 0; 508 continue; 509 } 510 511 if (!fp->ftp_retired || fp->ftp_rcount != 0) 512 fp->ftp_marked = 0; 513 514 mutex_exit(&fp->ftp_mtx); 515 516 /* 517 * If we successfully unregister this 518 * provider we can remove it from the hash 519 * chain and free the memory. If our attempt 520 * to unregister fails and this is a retired 521 * provider, increment our flag to try again 522 * pretty soon. If we've consumed more than 523 * half of our total permitted number of 524 * probes call dtrace_condense() to try to 525 * clean out the unenabled probes. 526 */ 527 provid = fp->ftp_provid; 528 if ((rval = dtrace_unregister(provid)) != 0) { 529 if (fasttrap_total > fasttrap_max / 2) 530 (void) dtrace_condense(provid); 531 532 if (rval == EAGAIN) 533 fp->ftp_marked = 1; 534 535 later += fp->ftp_marked; 536 fpp = &fp->ftp_next; 537 } else { 538 *fpp = fp->ftp_next; 539 fasttrap_provider_free(fp); 540 } 541 } 542 mutex_exit(&bucket->ftb_mtx); 543 } 544 mtx_lock(&fasttrap_cleanup_mtx); 545 546 /* 547 * If we were unable to retire a provider, try again after a 548 * second. This situation can occur in certain circumstances 549 * where providers cannot be unregistered even though they have 550 * no probes enabled because of an execution of dtrace -l or 551 * something similar. 552 */ 553 if (later > 0 || fasttrap_cleanup_work || 554 fasttrap_cleanup_drain) { 555 mtx_unlock(&fasttrap_cleanup_mtx); 556 pause("ftclean", hz); 557 mtx_lock(&fasttrap_cleanup_mtx); 558 } else 559 mtx_sleep(&fasttrap_cleanup_cv, &fasttrap_cleanup_mtx, 560 0, "ftcl", 0); 561 } 562 563 /* 564 * Wake up the thread in fasttrap_unload() now that we're done. 565 */ 566 wakeup(&fasttrap_cleanup_drain); 567 mtx_unlock(&fasttrap_cleanup_mtx); 568 569 kthread_exit(); 570 } 571 572 /* 573 * Activates the asynchronous cleanup mechanism. 574 */ 575 static void 576 fasttrap_pid_cleanup(void) 577 { 578 579 mtx_lock(&fasttrap_cleanup_mtx); 580 if (!fasttrap_cleanup_work) { 581 fasttrap_cleanup_work = 1; 582 wakeup(&fasttrap_cleanup_cv); 583 } 584 mtx_unlock(&fasttrap_cleanup_mtx); 585 } 586 587 /* 588 * This is called from cfork() via dtrace_fasttrap_fork(). The child 589 * process's address space is (roughly) a copy of the parent process's so 590 * we have to remove all the instrumentation we had previously enabled in the 591 * parent. 592 */ 593 static void 594 fasttrap_fork(proc_t *p, proc_t *cp) 595 { 596 #ifndef illumos 597 fasttrap_scrblock_t *scrblk; 598 fasttrap_proc_t *fprc = NULL; 599 #endif 600 pid_t ppid = p->p_pid; 601 int i; 602 603 #ifdef illumos 604 ASSERT(curproc == p); 605 ASSERT(p->p_proc_flag & P_PR_LOCK); 606 #else 607 PROC_LOCK_ASSERT(p, MA_OWNED); 608 #endif 609 #ifdef illumos 610 ASSERT(p->p_dtrace_count > 0); 611 #else 612 if (p->p_dtrace_helpers) { 613 /* 614 * dtrace_helpers_duplicate() allocates memory. 615 */ 616 _PHOLD(cp); 617 PROC_UNLOCK(p); 618 PROC_UNLOCK(cp); 619 dtrace_helpers_duplicate(p, cp); 620 PROC_LOCK(cp); 621 PROC_LOCK(p); 622 _PRELE(cp); 623 } 624 /* 625 * This check is purposely here instead of in kern_fork.c because, 626 * for legal resons, we cannot include the dtrace_cddl.h header 627 * inside kern_fork.c and insert if-clause there. 628 */ 629 if (p->p_dtrace_count == 0) 630 return; 631 #endif 632 ASSERT(cp->p_dtrace_count == 0); 633 634 /* 635 * This would be simpler and faster if we maintained per-process 636 * hash tables of enabled tracepoints. It could, however, potentially 637 * slow down execution of a tracepoint since we'd need to go 638 * through two levels of indirection. In the future, we should 639 * consider either maintaining per-process ancillary lists of 640 * enabled tracepoints or hanging a pointer to a per-process hash 641 * table of enabled tracepoints off the proc structure. 642 */ 643 644 /* 645 * We don't have to worry about the child process disappearing 646 * because we're in fork(). 647 */ 648 #ifdef illumos 649 mtx_lock_spin(&cp->p_slock); 650 sprlock_proc(cp); 651 mtx_unlock_spin(&cp->p_slock); 652 #else 653 /* 654 * fasttrap_tracepoint_remove() expects the child process to be 655 * unlocked and the VM then expects curproc to be unlocked. 656 */ 657 _PHOLD(cp); 658 PROC_UNLOCK(cp); 659 PROC_UNLOCK(p); 660 #endif 661 662 /* 663 * Iterate over every tracepoint looking for ones that belong to the 664 * parent process, and remove each from the child process. 665 */ 666 for (i = 0; i < fasttrap_tpoints.fth_nent; i++) { 667 fasttrap_tracepoint_t *tp; 668 fasttrap_bucket_t *bucket = &fasttrap_tpoints.fth_table[i]; 669 670 mutex_enter(&bucket->ftb_mtx); 671 for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 672 if (tp->ftt_pid == ppid && 673 tp->ftt_proc->ftpc_acount != 0) { 674 int ret = fasttrap_tracepoint_remove(cp, tp); 675 ASSERT(ret == 0); 676 677 /* 678 * The count of active providers can only be 679 * decremented (i.e. to zero) during exec, 680 * exit, and removal of a meta provider so it 681 * should be impossible to drop the count 682 * mid-fork. 683 */ 684 ASSERT(tp->ftt_proc->ftpc_acount != 0); 685 #ifndef illumos 686 fprc = tp->ftt_proc; 687 #endif 688 } 689 } 690 mutex_exit(&bucket->ftb_mtx); 691 692 #ifndef illumos 693 /* 694 * Unmap any scratch space inherited from the parent's address 695 * space. 696 */ 697 if (fprc != NULL) { 698 mutex_enter(&fprc->ftpc_mtx); 699 LIST_FOREACH(scrblk, &fprc->ftpc_scrblks, ftsb_next) { 700 vm_map_remove(&cp->p_vmspace->vm_map, 701 scrblk->ftsb_addr, 702 scrblk->ftsb_addr + FASTTRAP_SCRBLOCK_SIZE); 703 } 704 mutex_exit(&fprc->ftpc_mtx); 705 } 706 #endif 707 } 708 709 #ifdef illumos 710 mutex_enter(&cp->p_lock); 711 sprunlock(cp); 712 #else 713 PROC_LOCK(p); 714 PROC_LOCK(cp); 715 _PRELE(cp); 716 #endif 717 } 718 719 /* 720 * This is called from proc_exit() or from exec_common() if p_dtrace_probes 721 * is set on the proc structure to indicate that there is a pid provider 722 * associated with this process. 723 */ 724 static void 725 fasttrap_exec_exit(proc_t *p) 726 { 727 #ifndef illumos 728 struct thread *td; 729 #endif 730 731 #ifdef illumos 732 ASSERT(p == curproc); 733 #else 734 PROC_LOCK_ASSERT(p, MA_OWNED); 735 _PHOLD(p); 736 /* 737 * Since struct threads may be recycled, we cannot rely on t_dtrace_sscr 738 * fields to be zeroed by kdtrace_thread_ctor. Thus we must zero it 739 * ourselves when a process exits. 740 */ 741 FOREACH_THREAD_IN_PROC(p, td) 742 td->t_dtrace_sscr = NULL; 743 PROC_UNLOCK(p); 744 #endif 745 746 /* 747 * We clean up the pid provider for this process here; user-land 748 * static probes are handled by the meta-provider remove entry point. 749 */ 750 fasttrap_provider_retire(p->p_pid, FASTTRAP_PID_NAME, 0); 751 #ifndef illumos 752 if (p->p_dtrace_helpers) 753 dtrace_helpers_destroy(p); 754 PROC_LOCK(p); 755 _PRELE(p); 756 #endif 757 } 758 759 760 /*ARGSUSED*/ 761 static void 762 fasttrap_pid_provide(void *arg, dtrace_probedesc_t *desc) 763 { 764 /* 765 * There are no "default" pid probes. 766 */ 767 } 768 769 static int 770 fasttrap_tracepoint_enable(proc_t *p, fasttrap_probe_t *probe, uint_t index) 771 { 772 fasttrap_tracepoint_t *tp, *new_tp = NULL; 773 fasttrap_bucket_t *bucket; 774 fasttrap_id_t *id; 775 pid_t pid; 776 uintptr_t pc; 777 778 ASSERT(index < probe->ftp_ntps); 779 780 pid = probe->ftp_pid; 781 pc = probe->ftp_tps[index].fit_tp->ftt_pc; 782 id = &probe->ftp_tps[index].fit_id; 783 784 ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid); 785 786 #ifdef illumos 787 ASSERT(!(p->p_flag & SVFORK)); 788 #endif 789 790 /* 791 * Before we make any modifications, make sure we've imposed a barrier 792 * on the generation in which this probe was last modified. 793 */ 794 fasttrap_mod_barrier(probe->ftp_gen); 795 796 bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 797 798 /* 799 * If the tracepoint has already been enabled, just add our id to the 800 * list of interested probes. This may be our second time through 801 * this path in which case we'll have constructed the tracepoint we'd 802 * like to install. If we can't find a match, and have an allocated 803 * tracepoint ready to go, enable that one now. 804 * 805 * A tracepoint whose process is defunct is also considered defunct. 806 */ 807 again: 808 mutex_enter(&bucket->ftb_mtx); 809 for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 810 /* 811 * Note that it's safe to access the active count on the 812 * associated proc structure because we know that at least one 813 * provider (this one) will still be around throughout this 814 * operation. 815 */ 816 if (tp->ftt_pid != pid || tp->ftt_pc != pc || 817 tp->ftt_proc->ftpc_acount == 0) 818 continue; 819 820 /* 821 * Now that we've found a matching tracepoint, it would be 822 * a decent idea to confirm that the tracepoint is still 823 * enabled and the trap instruction hasn't been overwritten. 824 * Since this is a little hairy, we'll punt for now. 825 */ 826 827 /* 828 * This can't be the first interested probe. We don't have 829 * to worry about another thread being in the midst of 830 * deleting this tracepoint (which would be the only valid 831 * reason for a tracepoint to have no interested probes) 832 * since we're holding P_PR_LOCK for this process. 833 */ 834 ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL); 835 836 switch (id->fti_ptype) { 837 case DTFTP_ENTRY: 838 case DTFTP_OFFSETS: 839 case DTFTP_IS_ENABLED: 840 id->fti_next = tp->ftt_ids; 841 membar_producer(); 842 tp->ftt_ids = id; 843 membar_producer(); 844 break; 845 846 case DTFTP_RETURN: 847 case DTFTP_POST_OFFSETS: 848 id->fti_next = tp->ftt_retids; 849 membar_producer(); 850 tp->ftt_retids = id; 851 membar_producer(); 852 break; 853 854 default: 855 ASSERT(0); 856 } 857 858 mutex_exit(&bucket->ftb_mtx); 859 860 if (new_tp != NULL) { 861 new_tp->ftt_ids = NULL; 862 new_tp->ftt_retids = NULL; 863 } 864 865 return (0); 866 } 867 868 /* 869 * If we have a good tracepoint ready to go, install it now while 870 * we have the lock held and no one can screw with us. 871 */ 872 if (new_tp != NULL) { 873 int rc = 0; 874 875 new_tp->ftt_next = bucket->ftb_data; 876 membar_producer(); 877 bucket->ftb_data = new_tp; 878 membar_producer(); 879 mutex_exit(&bucket->ftb_mtx); 880 881 /* 882 * Activate the tracepoint in the ISA-specific manner. 883 * If this fails, we need to report the failure, but 884 * indicate that this tracepoint must still be disabled 885 * by calling fasttrap_tracepoint_disable(). 886 */ 887 if (fasttrap_tracepoint_install(p, new_tp) != 0) 888 rc = FASTTRAP_ENABLE_PARTIAL; 889 890 /* 891 * Increment the count of the number of tracepoints active in 892 * the victim process. 893 */ 894 #ifdef illumos 895 ASSERT(p->p_proc_flag & P_PR_LOCK); 896 #endif 897 p->p_dtrace_count++; 898 899 return (rc); 900 } 901 902 mutex_exit(&bucket->ftb_mtx); 903 904 /* 905 * Initialize the tracepoint that's been preallocated with the probe. 906 */ 907 new_tp = probe->ftp_tps[index].fit_tp; 908 909 ASSERT(new_tp->ftt_pid == pid); 910 ASSERT(new_tp->ftt_pc == pc); 911 ASSERT(new_tp->ftt_proc == probe->ftp_prov->ftp_proc); 912 ASSERT(new_tp->ftt_ids == NULL); 913 ASSERT(new_tp->ftt_retids == NULL); 914 915 switch (id->fti_ptype) { 916 case DTFTP_ENTRY: 917 case DTFTP_OFFSETS: 918 case DTFTP_IS_ENABLED: 919 id->fti_next = NULL; 920 new_tp->ftt_ids = id; 921 break; 922 923 case DTFTP_RETURN: 924 case DTFTP_POST_OFFSETS: 925 id->fti_next = NULL; 926 new_tp->ftt_retids = id; 927 break; 928 929 default: 930 ASSERT(0); 931 } 932 933 /* 934 * If the ISA-dependent initialization goes to plan, go back to the 935 * beginning and try to install this freshly made tracepoint. 936 */ 937 if (fasttrap_tracepoint_init(p, new_tp, pc, id->fti_ptype) == 0) 938 goto again; 939 940 new_tp->ftt_ids = NULL; 941 new_tp->ftt_retids = NULL; 942 943 return (FASTTRAP_ENABLE_FAIL); 944 } 945 946 static void 947 fasttrap_tracepoint_disable(proc_t *p, fasttrap_probe_t *probe, uint_t index) 948 { 949 fasttrap_bucket_t *bucket; 950 fasttrap_provider_t *provider = probe->ftp_prov; 951 fasttrap_tracepoint_t **pp, *tp; 952 fasttrap_id_t *id, **idp = NULL; 953 pid_t pid; 954 uintptr_t pc; 955 956 ASSERT(index < probe->ftp_ntps); 957 958 pid = probe->ftp_pid; 959 pc = probe->ftp_tps[index].fit_tp->ftt_pc; 960 id = &probe->ftp_tps[index].fit_id; 961 962 ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid); 963 964 /* 965 * Find the tracepoint and make sure that our id is one of the 966 * ones registered with it. 967 */ 968 bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 969 mutex_enter(&bucket->ftb_mtx); 970 for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 971 if (tp->ftt_pid == pid && tp->ftt_pc == pc && 972 tp->ftt_proc == provider->ftp_proc) 973 break; 974 } 975 976 /* 977 * If we somehow lost this tracepoint, we're in a world of hurt. 978 */ 979 ASSERT(tp != NULL); 980 981 switch (id->fti_ptype) { 982 case DTFTP_ENTRY: 983 case DTFTP_OFFSETS: 984 case DTFTP_IS_ENABLED: 985 ASSERT(tp->ftt_ids != NULL); 986 idp = &tp->ftt_ids; 987 break; 988 989 case DTFTP_RETURN: 990 case DTFTP_POST_OFFSETS: 991 ASSERT(tp->ftt_retids != NULL); 992 idp = &tp->ftt_retids; 993 break; 994 995 default: 996 ASSERT(0); 997 } 998 999 while ((*idp)->fti_probe != probe) { 1000 idp = &(*idp)->fti_next; 1001 ASSERT(*idp != NULL); 1002 } 1003 1004 id = *idp; 1005 *idp = id->fti_next; 1006 membar_producer(); 1007 1008 ASSERT(id->fti_probe == probe); 1009 1010 /* 1011 * If there are other registered enablings of this tracepoint, we're 1012 * all done, but if this was the last probe assocated with this 1013 * this tracepoint, we need to remove and free it. 1014 */ 1015 if (tp->ftt_ids != NULL || tp->ftt_retids != NULL) { 1016 1017 /* 1018 * If the current probe's tracepoint is in use, swap it 1019 * for an unused tracepoint. 1020 */ 1021 if (tp == probe->ftp_tps[index].fit_tp) { 1022 fasttrap_probe_t *tmp_probe; 1023 fasttrap_tracepoint_t **tmp_tp; 1024 uint_t tmp_index; 1025 1026 if (tp->ftt_ids != NULL) { 1027 tmp_probe = tp->ftt_ids->fti_probe; 1028 /* LINTED - alignment */ 1029 tmp_index = FASTTRAP_ID_INDEX(tp->ftt_ids); 1030 tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp; 1031 } else { 1032 tmp_probe = tp->ftt_retids->fti_probe; 1033 /* LINTED - alignment */ 1034 tmp_index = FASTTRAP_ID_INDEX(tp->ftt_retids); 1035 tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp; 1036 } 1037 1038 ASSERT(*tmp_tp != NULL); 1039 ASSERT(*tmp_tp != probe->ftp_tps[index].fit_tp); 1040 ASSERT((*tmp_tp)->ftt_ids == NULL); 1041 ASSERT((*tmp_tp)->ftt_retids == NULL); 1042 1043 probe->ftp_tps[index].fit_tp = *tmp_tp; 1044 *tmp_tp = tp; 1045 } 1046 1047 mutex_exit(&bucket->ftb_mtx); 1048 1049 /* 1050 * Tag the modified probe with the generation in which it was 1051 * changed. 1052 */ 1053 probe->ftp_gen = fasttrap_mod_gen; 1054 return; 1055 } 1056 1057 mutex_exit(&bucket->ftb_mtx); 1058 1059 /* 1060 * We can't safely remove the tracepoint from the set of active 1061 * tracepoints until we've actually removed the fasttrap instruction 1062 * from the process's text. We can, however, operate on this 1063 * tracepoint secure in the knowledge that no other thread is going to 1064 * be looking at it since we hold P_PR_LOCK on the process if it's 1065 * live or we hold the provider lock on the process if it's dead and 1066 * gone. 1067 */ 1068 1069 /* 1070 * We only need to remove the actual instruction if we're looking 1071 * at an existing process 1072 */ 1073 if (p != NULL) { 1074 /* 1075 * If we fail to restore the instruction we need to kill 1076 * this process since it's in a completely unrecoverable 1077 * state. 1078 */ 1079 if (fasttrap_tracepoint_remove(p, tp) != 0) 1080 fasttrap_sigtrap(p, NULL, pc); 1081 1082 /* 1083 * Decrement the count of the number of tracepoints active 1084 * in the victim process. 1085 */ 1086 #ifdef illumos 1087 ASSERT(p->p_proc_flag & P_PR_LOCK); 1088 #endif 1089 p->p_dtrace_count--; 1090 } 1091 1092 /* 1093 * Remove the probe from the hash table of active tracepoints. 1094 */ 1095 mutex_enter(&bucket->ftb_mtx); 1096 pp = (fasttrap_tracepoint_t **)&bucket->ftb_data; 1097 ASSERT(*pp != NULL); 1098 while (*pp != tp) { 1099 pp = &(*pp)->ftt_next; 1100 ASSERT(*pp != NULL); 1101 } 1102 1103 *pp = tp->ftt_next; 1104 membar_producer(); 1105 1106 mutex_exit(&bucket->ftb_mtx); 1107 1108 /* 1109 * Tag the modified probe with the generation in which it was changed. 1110 */ 1111 probe->ftp_gen = fasttrap_mod_gen; 1112 } 1113 1114 static void 1115 fasttrap_enable_callbacks(void) 1116 { 1117 /* 1118 * We don't have to play the rw lock game here because we're 1119 * providing something rather than taking something away -- 1120 * we can be sure that no threads have tried to follow this 1121 * function pointer yet. 1122 */ 1123 mutex_enter(&fasttrap_count_mtx); 1124 if (fasttrap_pid_count == 0) { 1125 ASSERT(dtrace_pid_probe_ptr == NULL); 1126 ASSERT(dtrace_return_probe_ptr == NULL); 1127 dtrace_pid_probe_ptr = &fasttrap_pid_probe; 1128 dtrace_return_probe_ptr = &fasttrap_return_probe; 1129 } 1130 ASSERT(dtrace_pid_probe_ptr == &fasttrap_pid_probe); 1131 ASSERT(dtrace_return_probe_ptr == &fasttrap_return_probe); 1132 fasttrap_pid_count++; 1133 mutex_exit(&fasttrap_count_mtx); 1134 } 1135 1136 static void 1137 fasttrap_disable_callbacks(void) 1138 { 1139 #ifdef illumos 1140 ASSERT(MUTEX_HELD(&cpu_lock)); 1141 #endif 1142 1143 1144 mutex_enter(&fasttrap_count_mtx); 1145 ASSERT(fasttrap_pid_count > 0); 1146 fasttrap_pid_count--; 1147 if (fasttrap_pid_count == 0) { 1148 #ifdef illumos 1149 cpu_t *cur, *cpu = CPU; 1150 1151 for (cur = cpu->cpu_next_onln; cur != cpu; 1152 cur = cur->cpu_next_onln) { 1153 rw_enter(&cur->cpu_ft_lock, RW_WRITER); 1154 } 1155 #endif 1156 dtrace_pid_probe_ptr = NULL; 1157 dtrace_return_probe_ptr = NULL; 1158 #ifdef illumos 1159 for (cur = cpu->cpu_next_onln; cur != cpu; 1160 cur = cur->cpu_next_onln) { 1161 rw_exit(&cur->cpu_ft_lock); 1162 } 1163 #endif 1164 } 1165 mutex_exit(&fasttrap_count_mtx); 1166 } 1167 1168 /*ARGSUSED*/ 1169 static void 1170 fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg) 1171 { 1172 fasttrap_probe_t *probe = parg; 1173 proc_t *p = NULL; 1174 int i, rc; 1175 1176 ASSERT(probe != NULL); 1177 ASSERT(!probe->ftp_enabled); 1178 ASSERT(id == probe->ftp_id); 1179 #ifdef illumos 1180 ASSERT(MUTEX_HELD(&cpu_lock)); 1181 #endif 1182 1183 /* 1184 * Increment the count of enabled probes on this probe's provider; 1185 * the provider can't go away while the probe still exists. We 1186 * must increment this even if we aren't able to properly enable 1187 * this probe. 1188 */ 1189 mutex_enter(&probe->ftp_prov->ftp_mtx); 1190 probe->ftp_prov->ftp_rcount++; 1191 mutex_exit(&probe->ftp_prov->ftp_mtx); 1192 1193 /* 1194 * If this probe's provider is retired (meaning it was valid in a 1195 * previously exec'ed incarnation of this address space), bail out. The 1196 * provider can't go away while we're in this code path. 1197 */ 1198 if (probe->ftp_prov->ftp_retired) 1199 return; 1200 1201 /* 1202 * If we can't find the process, it may be that we're in the context of 1203 * a fork in which the traced process is being born and we're copying 1204 * USDT probes. Otherwise, the process is gone so bail. 1205 */ 1206 #ifdef illumos 1207 if ((p = sprlock(probe->ftp_pid)) == NULL) { 1208 if ((curproc->p_flag & SFORKING) == 0) 1209 return; 1210 1211 mutex_enter(&pidlock); 1212 p = prfind(probe->ftp_pid); 1213 1214 if (p == NULL) { 1215 /* 1216 * So it's not that the target process is being born, 1217 * it's that it isn't there at all (and we simply 1218 * happen to be forking). Anyway, we know that the 1219 * target is definitely gone, so bail out. 1220 */ 1221 mutex_exit(&pidlock); 1222 return (0); 1223 } 1224 1225 /* 1226 * Confirm that curproc is indeed forking the process in which 1227 * we're trying to enable probes. 1228 */ 1229 ASSERT(p->p_parent == curproc); 1230 ASSERT(p->p_stat == SIDL); 1231 1232 mutex_enter(&p->p_lock); 1233 mutex_exit(&pidlock); 1234 1235 sprlock_proc(p); 1236 } 1237 1238 ASSERT(!(p->p_flag & SVFORK)); 1239 mutex_exit(&p->p_lock); 1240 #else 1241 if ((p = pfind(probe->ftp_pid)) == NULL) 1242 return; 1243 #endif 1244 1245 /* 1246 * We have to enable the trap entry point before any user threads have 1247 * the chance to execute the trap instruction we're about to place 1248 * in their process's text. 1249 */ 1250 #ifdef __FreeBSD__ 1251 /* 1252 * pfind() returns a locked process. 1253 */ 1254 _PHOLD(p); 1255 PROC_UNLOCK(p); 1256 #endif 1257 fasttrap_enable_callbacks(); 1258 1259 /* 1260 * Enable all the tracepoints and add this probe's id to each 1261 * tracepoint's list of active probes. 1262 */ 1263 for (i = 0; i < probe->ftp_ntps; i++) { 1264 if ((rc = fasttrap_tracepoint_enable(p, probe, i)) != 0) { 1265 /* 1266 * If enabling the tracepoint failed completely, 1267 * we don't have to disable it; if the failure 1268 * was only partial we must disable it. 1269 */ 1270 if (rc == FASTTRAP_ENABLE_FAIL) 1271 i--; 1272 else 1273 ASSERT(rc == FASTTRAP_ENABLE_PARTIAL); 1274 1275 /* 1276 * Back up and pull out all the tracepoints we've 1277 * created so far for this probe. 1278 */ 1279 while (i >= 0) { 1280 fasttrap_tracepoint_disable(p, probe, i); 1281 i--; 1282 } 1283 1284 #ifdef illumos 1285 mutex_enter(&p->p_lock); 1286 sprunlock(p); 1287 #else 1288 PRELE(p); 1289 #endif 1290 1291 /* 1292 * Since we're not actually enabling this probe, 1293 * drop our reference on the trap table entry. 1294 */ 1295 fasttrap_disable_callbacks(); 1296 return; 1297 } 1298 } 1299 #ifdef illumos 1300 mutex_enter(&p->p_lock); 1301 sprunlock(p); 1302 #else 1303 PRELE(p); 1304 #endif 1305 1306 probe->ftp_enabled = 1; 1307 } 1308 1309 /*ARGSUSED*/ 1310 static void 1311 fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg) 1312 { 1313 fasttrap_probe_t *probe = parg; 1314 fasttrap_provider_t *provider = probe->ftp_prov; 1315 proc_t *p; 1316 int i, whack = 0; 1317 1318 ASSERT(id == probe->ftp_id); 1319 1320 mutex_enter(&provider->ftp_mtx); 1321 1322 /* 1323 * We won't be able to acquire a /proc-esque lock on the process 1324 * iff the process is dead and gone. In this case, we rely on the 1325 * provider lock as a point of mutual exclusion to prevent other 1326 * DTrace consumers from disabling this probe. 1327 */ 1328 if ((p = pfind(probe->ftp_pid)) != NULL) { 1329 #ifdef __FreeBSD__ 1330 if (p->p_flag & P_WEXIT) { 1331 PROC_UNLOCK(p); 1332 p = NULL; 1333 } else { 1334 _PHOLD(p); 1335 PROC_UNLOCK(p); 1336 } 1337 #endif 1338 } 1339 1340 /* 1341 * Disable all the associated tracepoints (for fully enabled probes). 1342 */ 1343 if (probe->ftp_enabled) { 1344 for (i = 0; i < probe->ftp_ntps; i++) { 1345 fasttrap_tracepoint_disable(p, probe, i); 1346 } 1347 } 1348 1349 ASSERT(provider->ftp_rcount > 0); 1350 provider->ftp_rcount--; 1351 1352 if (p != NULL) { 1353 /* 1354 * Even though we may not be able to remove it entirely, we 1355 * mark this retired provider to get a chance to remove some 1356 * of the associated probes. 1357 */ 1358 if (provider->ftp_retired && !provider->ftp_marked) 1359 whack = provider->ftp_marked = 1; 1360 mutex_exit(&provider->ftp_mtx); 1361 } else { 1362 /* 1363 * If the process is dead, we're just waiting for the 1364 * last probe to be disabled to be able to free it. 1365 */ 1366 if (provider->ftp_rcount == 0 && !provider->ftp_marked) 1367 whack = provider->ftp_marked = 1; 1368 mutex_exit(&provider->ftp_mtx); 1369 } 1370 1371 if (whack) 1372 fasttrap_pid_cleanup(); 1373 1374 #ifdef __FreeBSD__ 1375 if (p != NULL) 1376 PRELE(p); 1377 #endif 1378 if (!probe->ftp_enabled) 1379 return; 1380 1381 probe->ftp_enabled = 0; 1382 1383 #ifdef illumos 1384 ASSERT(MUTEX_HELD(&cpu_lock)); 1385 #endif 1386 fasttrap_disable_callbacks(); 1387 } 1388 1389 /*ARGSUSED*/ 1390 static void 1391 fasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg, 1392 dtrace_argdesc_t *desc) 1393 { 1394 fasttrap_probe_t *probe = parg; 1395 char *str; 1396 int i, ndx; 1397 1398 desc->dtargd_native[0] = '\0'; 1399 desc->dtargd_xlate[0] = '\0'; 1400 1401 if (probe->ftp_prov->ftp_retired != 0 || 1402 desc->dtargd_ndx >= probe->ftp_nargs) { 1403 desc->dtargd_ndx = DTRACE_ARGNONE; 1404 return; 1405 } 1406 1407 ndx = (probe->ftp_argmap != NULL) ? 1408 probe->ftp_argmap[desc->dtargd_ndx] : desc->dtargd_ndx; 1409 1410 str = probe->ftp_ntypes; 1411 for (i = 0; i < ndx; i++) { 1412 str += strlen(str) + 1; 1413 } 1414 1415 ASSERT(strlen(str + 1) < sizeof (desc->dtargd_native)); 1416 (void) strcpy(desc->dtargd_native, str); 1417 1418 if (probe->ftp_xtypes == NULL) 1419 return; 1420 1421 str = probe->ftp_xtypes; 1422 for (i = 0; i < desc->dtargd_ndx; i++) { 1423 str += strlen(str) + 1; 1424 } 1425 1426 ASSERT(strlen(str + 1) < sizeof (desc->dtargd_xlate)); 1427 (void) strcpy(desc->dtargd_xlate, str); 1428 } 1429 1430 /*ARGSUSED*/ 1431 static void 1432 fasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg) 1433 { 1434 fasttrap_probe_t *probe = parg; 1435 int i; 1436 size_t size; 1437 1438 ASSERT(probe != NULL); 1439 ASSERT(!probe->ftp_enabled); 1440 ASSERT(fasttrap_total >= probe->ftp_ntps); 1441 1442 atomic_add_32(&fasttrap_total, -probe->ftp_ntps); 1443 size = offsetof(fasttrap_probe_t, ftp_tps[probe->ftp_ntps]); 1444 1445 if (probe->ftp_gen + 1 >= fasttrap_mod_gen) 1446 fasttrap_mod_barrier(probe->ftp_gen); 1447 1448 for (i = 0; i < probe->ftp_ntps; i++) { 1449 kmem_free(probe->ftp_tps[i].fit_tp, 1450 sizeof (fasttrap_tracepoint_t)); 1451 } 1452 1453 kmem_free(probe, size); 1454 } 1455 1456 1457 static const dtrace_pattr_t pid_attr = { 1458 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, 1459 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 1460 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 1461 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, 1462 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 1463 }; 1464 1465 static dtrace_pops_t pid_pops = { 1466 fasttrap_pid_provide, 1467 NULL, 1468 fasttrap_pid_enable, 1469 fasttrap_pid_disable, 1470 NULL, 1471 NULL, 1472 fasttrap_pid_getargdesc, 1473 fasttrap_pid_getarg, 1474 NULL, 1475 fasttrap_pid_destroy 1476 }; 1477 1478 static dtrace_pops_t usdt_pops = { 1479 fasttrap_pid_provide, 1480 NULL, 1481 fasttrap_pid_enable, 1482 fasttrap_pid_disable, 1483 NULL, 1484 NULL, 1485 fasttrap_pid_getargdesc, 1486 fasttrap_usdt_getarg, 1487 NULL, 1488 fasttrap_pid_destroy 1489 }; 1490 1491 static fasttrap_proc_t * 1492 fasttrap_proc_lookup(pid_t pid) 1493 { 1494 fasttrap_bucket_t *bucket; 1495 fasttrap_proc_t *fprc, *new_fprc; 1496 1497 1498 bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)]; 1499 mutex_enter(&bucket->ftb_mtx); 1500 1501 for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) { 1502 if (fprc->ftpc_pid == pid && fprc->ftpc_acount != 0) { 1503 mutex_enter(&fprc->ftpc_mtx); 1504 mutex_exit(&bucket->ftb_mtx); 1505 fprc->ftpc_rcount++; 1506 atomic_inc_64(&fprc->ftpc_acount); 1507 ASSERT(fprc->ftpc_acount <= fprc->ftpc_rcount); 1508 mutex_exit(&fprc->ftpc_mtx); 1509 1510 return (fprc); 1511 } 1512 } 1513 1514 /* 1515 * Drop the bucket lock so we don't try to perform a sleeping 1516 * allocation under it. 1517 */ 1518 mutex_exit(&bucket->ftb_mtx); 1519 1520 new_fprc = kmem_zalloc(sizeof (fasttrap_proc_t), KM_SLEEP); 1521 new_fprc->ftpc_pid = pid; 1522 new_fprc->ftpc_rcount = 1; 1523 new_fprc->ftpc_acount = 1; 1524 #ifndef illumos 1525 mutex_init(&new_fprc->ftpc_mtx, "fasttrap proc mtx", MUTEX_DEFAULT, 1526 NULL); 1527 #endif 1528 1529 mutex_enter(&bucket->ftb_mtx); 1530 1531 /* 1532 * Take another lap through the list to make sure a proc hasn't 1533 * been created for this pid while we weren't under the bucket lock. 1534 */ 1535 for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) { 1536 if (fprc->ftpc_pid == pid && fprc->ftpc_acount != 0) { 1537 mutex_enter(&fprc->ftpc_mtx); 1538 mutex_exit(&bucket->ftb_mtx); 1539 fprc->ftpc_rcount++; 1540 atomic_inc_64(&fprc->ftpc_acount); 1541 ASSERT(fprc->ftpc_acount <= fprc->ftpc_rcount); 1542 mutex_exit(&fprc->ftpc_mtx); 1543 1544 kmem_free(new_fprc, sizeof (fasttrap_proc_t)); 1545 1546 return (fprc); 1547 } 1548 } 1549 1550 new_fprc->ftpc_next = bucket->ftb_data; 1551 bucket->ftb_data = new_fprc; 1552 1553 mutex_exit(&bucket->ftb_mtx); 1554 1555 return (new_fprc); 1556 } 1557 1558 static void 1559 fasttrap_proc_release(fasttrap_proc_t *proc) 1560 { 1561 fasttrap_bucket_t *bucket; 1562 fasttrap_proc_t *fprc, **fprcp; 1563 pid_t pid = proc->ftpc_pid; 1564 #ifndef illumos 1565 fasttrap_scrblock_t *scrblk, *scrblktmp; 1566 fasttrap_scrspace_t *scrspc, *scrspctmp; 1567 struct proc *p; 1568 struct thread *td; 1569 #endif 1570 1571 mutex_enter(&proc->ftpc_mtx); 1572 1573 ASSERT(proc->ftpc_rcount != 0); 1574 ASSERT(proc->ftpc_acount <= proc->ftpc_rcount); 1575 1576 if (--proc->ftpc_rcount != 0) { 1577 mutex_exit(&proc->ftpc_mtx); 1578 return; 1579 } 1580 1581 #ifndef illumos 1582 /* 1583 * Free all structures used to manage per-thread scratch space. 1584 */ 1585 LIST_FOREACH_SAFE(scrblk, &proc->ftpc_scrblks, ftsb_next, 1586 scrblktmp) { 1587 LIST_REMOVE(scrblk, ftsb_next); 1588 free(scrblk, M_SOLARIS); 1589 } 1590 LIST_FOREACH_SAFE(scrspc, &proc->ftpc_fscr, ftss_next, scrspctmp) { 1591 LIST_REMOVE(scrspc, ftss_next); 1592 free(scrspc, M_SOLARIS); 1593 } 1594 LIST_FOREACH_SAFE(scrspc, &proc->ftpc_ascr, ftss_next, scrspctmp) { 1595 LIST_REMOVE(scrspc, ftss_next); 1596 free(scrspc, M_SOLARIS); 1597 } 1598 1599 if ((p = pfind(pid)) != NULL) { 1600 FOREACH_THREAD_IN_PROC(p, td) 1601 td->t_dtrace_sscr = NULL; 1602 PROC_UNLOCK(p); 1603 } 1604 #endif 1605 1606 mutex_exit(&proc->ftpc_mtx); 1607 1608 /* 1609 * There should definitely be no live providers associated with this 1610 * process at this point. 1611 */ 1612 ASSERT(proc->ftpc_acount == 0); 1613 1614 bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)]; 1615 mutex_enter(&bucket->ftb_mtx); 1616 1617 fprcp = (fasttrap_proc_t **)&bucket->ftb_data; 1618 while ((fprc = *fprcp) != NULL) { 1619 if (fprc == proc) 1620 break; 1621 1622 fprcp = &fprc->ftpc_next; 1623 } 1624 1625 /* 1626 * Something strange has happened if we can't find the proc. 1627 */ 1628 ASSERT(fprc != NULL); 1629 1630 *fprcp = fprc->ftpc_next; 1631 1632 mutex_exit(&bucket->ftb_mtx); 1633 1634 kmem_free(fprc, sizeof (fasttrap_proc_t)); 1635 } 1636 1637 /* 1638 * Lookup a fasttrap-managed provider based on its name and associated pid. 1639 * If the pattr argument is non-NULL, this function instantiates the provider 1640 * if it doesn't exist otherwise it returns NULL. The provider is returned 1641 * with its lock held. 1642 */ 1643 static fasttrap_provider_t * 1644 fasttrap_provider_lookup(pid_t pid, const char *name, 1645 const dtrace_pattr_t *pattr) 1646 { 1647 fasttrap_provider_t *fp, *new_fp = NULL; 1648 fasttrap_bucket_t *bucket; 1649 char provname[DTRACE_PROVNAMELEN]; 1650 proc_t *p; 1651 cred_t *cred; 1652 1653 ASSERT(strlen(name) < sizeof (fp->ftp_name)); 1654 ASSERT(pattr != NULL); 1655 1656 bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)]; 1657 mutex_enter(&bucket->ftb_mtx); 1658 1659 /* 1660 * Take a lap through the list and return the match if we find it. 1661 */ 1662 for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) { 1663 if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 && 1664 !fp->ftp_retired) { 1665 mutex_enter(&fp->ftp_mtx); 1666 mutex_exit(&bucket->ftb_mtx); 1667 return (fp); 1668 } 1669 } 1670 1671 /* 1672 * Drop the bucket lock so we don't try to perform a sleeping 1673 * allocation under it. 1674 */ 1675 mutex_exit(&bucket->ftb_mtx); 1676 1677 /* 1678 * Make sure the process exists, isn't a child created as the result 1679 * of a vfork(2), and isn't a zombie (but may be in fork). 1680 */ 1681 if ((p = pfind(pid)) == NULL) 1682 return (NULL); 1683 1684 /* 1685 * Increment p_dtrace_probes so that the process knows to inform us 1686 * when it exits or execs. fasttrap_provider_free() decrements this 1687 * when we're done with this provider. 1688 */ 1689 p->p_dtrace_probes++; 1690 1691 /* 1692 * Grab the credentials for this process so we have 1693 * something to pass to dtrace_register(). 1694 */ 1695 PROC_LOCK_ASSERT(p, MA_OWNED); 1696 crhold(p->p_ucred); 1697 cred = p->p_ucred; 1698 PROC_UNLOCK(p); 1699 1700 new_fp = kmem_zalloc(sizeof (fasttrap_provider_t), KM_SLEEP); 1701 new_fp->ftp_pid = pid; 1702 new_fp->ftp_proc = fasttrap_proc_lookup(pid); 1703 #ifndef illumos 1704 mutex_init(&new_fp->ftp_mtx, "provider mtx", MUTEX_DEFAULT, NULL); 1705 mutex_init(&new_fp->ftp_cmtx, "lock on creating", MUTEX_DEFAULT, NULL); 1706 #endif 1707 1708 ASSERT(new_fp->ftp_proc != NULL); 1709 1710 mutex_enter(&bucket->ftb_mtx); 1711 1712 /* 1713 * Take another lap through the list to make sure a provider hasn't 1714 * been created for this pid while we weren't under the bucket lock. 1715 */ 1716 for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) { 1717 if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 && 1718 !fp->ftp_retired) { 1719 mutex_enter(&fp->ftp_mtx); 1720 mutex_exit(&bucket->ftb_mtx); 1721 fasttrap_provider_free(new_fp); 1722 crfree(cred); 1723 return (fp); 1724 } 1725 } 1726 1727 (void) strcpy(new_fp->ftp_name, name); 1728 1729 /* 1730 * Fail and return NULL if either the provider name is too long 1731 * or we fail to register this new provider with the DTrace 1732 * framework. Note that this is the only place we ever construct 1733 * the full provider name -- we keep it in pieces in the provider 1734 * structure. 1735 */ 1736 if (snprintf(provname, sizeof (provname), "%s%u", name, (uint_t)pid) >= 1737 sizeof (provname) || 1738 dtrace_register(provname, pattr, 1739 DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER | DTRACE_PRIV_ZONEOWNER, cred, 1740 pattr == &pid_attr ? &pid_pops : &usdt_pops, new_fp, 1741 &new_fp->ftp_provid) != 0) { 1742 mutex_exit(&bucket->ftb_mtx); 1743 fasttrap_provider_free(new_fp); 1744 crfree(cred); 1745 return (NULL); 1746 } 1747 1748 new_fp->ftp_next = bucket->ftb_data; 1749 bucket->ftb_data = new_fp; 1750 1751 mutex_enter(&new_fp->ftp_mtx); 1752 mutex_exit(&bucket->ftb_mtx); 1753 1754 crfree(cred); 1755 return (new_fp); 1756 } 1757 1758 static void 1759 fasttrap_provider_free(fasttrap_provider_t *provider) 1760 { 1761 pid_t pid = provider->ftp_pid; 1762 proc_t *p; 1763 1764 /* 1765 * There need to be no associated enabled probes, no consumers 1766 * creating probes, and no meta providers referencing this provider. 1767 */ 1768 ASSERT(provider->ftp_rcount == 0); 1769 ASSERT(provider->ftp_ccount == 0); 1770 ASSERT(provider->ftp_mcount == 0); 1771 1772 /* 1773 * If this provider hasn't been retired, we need to explicitly drop the 1774 * count of active providers on the associated process structure. 1775 */ 1776 if (!provider->ftp_retired) { 1777 atomic_dec_64(&provider->ftp_proc->ftpc_acount); 1778 ASSERT(provider->ftp_proc->ftpc_acount < 1779 provider->ftp_proc->ftpc_rcount); 1780 } 1781 1782 fasttrap_proc_release(provider->ftp_proc); 1783 1784 #ifndef illumos 1785 mutex_destroy(&provider->ftp_mtx); 1786 mutex_destroy(&provider->ftp_cmtx); 1787 #endif 1788 kmem_free(provider, sizeof (fasttrap_provider_t)); 1789 1790 /* 1791 * Decrement p_dtrace_probes on the process whose provider we're 1792 * freeing. We don't have to worry about clobbering somone else's 1793 * modifications to it because we have locked the bucket that 1794 * corresponds to this process's hash chain in the provider hash 1795 * table. Don't sweat it if we can't find the process. 1796 */ 1797 if ((p = pfind(pid)) == NULL) { 1798 return; 1799 } 1800 1801 p->p_dtrace_probes--; 1802 #ifndef illumos 1803 PROC_UNLOCK(p); 1804 #endif 1805 } 1806 1807 static void 1808 fasttrap_provider_retire(pid_t pid, const char *name, int mprov) 1809 { 1810 fasttrap_provider_t *fp; 1811 fasttrap_bucket_t *bucket; 1812 dtrace_provider_id_t provid; 1813 1814 ASSERT(strlen(name) < sizeof (fp->ftp_name)); 1815 1816 bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)]; 1817 mutex_enter(&bucket->ftb_mtx); 1818 1819 for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) { 1820 if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 && 1821 !fp->ftp_retired) 1822 break; 1823 } 1824 1825 if (fp == NULL) { 1826 mutex_exit(&bucket->ftb_mtx); 1827 return; 1828 } 1829 1830 mutex_enter(&fp->ftp_mtx); 1831 ASSERT(!mprov || fp->ftp_mcount > 0); 1832 if (mprov && --fp->ftp_mcount != 0) { 1833 mutex_exit(&fp->ftp_mtx); 1834 mutex_exit(&bucket->ftb_mtx); 1835 return; 1836 } 1837 1838 /* 1839 * Mark the provider to be removed in our post-processing step, mark it 1840 * retired, and drop the active count on its proc. Marking it indicates 1841 * that we should try to remove it; setting the retired flag indicates 1842 * that we're done with this provider; dropping the active the proc 1843 * releases our hold, and when this reaches zero (as it will during 1844 * exit or exec) the proc and associated providers become defunct. 1845 * 1846 * We obviously need to take the bucket lock before the provider lock 1847 * to perform the lookup, but we need to drop the provider lock 1848 * before calling into the DTrace framework since we acquire the 1849 * provider lock in callbacks invoked from the DTrace framework. The 1850 * bucket lock therefore protects the integrity of the provider hash 1851 * table. 1852 */ 1853 atomic_dec_64(&fp->ftp_proc->ftpc_acount); 1854 ASSERT(fp->ftp_proc->ftpc_acount < fp->ftp_proc->ftpc_rcount); 1855 1856 fp->ftp_retired = 1; 1857 fp->ftp_marked = 1; 1858 provid = fp->ftp_provid; 1859 mutex_exit(&fp->ftp_mtx); 1860 1861 /* 1862 * We don't have to worry about invalidating the same provider twice 1863 * since fasttrap_provider_lookup() will ignore provider that have 1864 * been marked as retired. 1865 */ 1866 dtrace_invalidate(provid); 1867 1868 mutex_exit(&bucket->ftb_mtx); 1869 1870 fasttrap_pid_cleanup(); 1871 } 1872 1873 static int 1874 fasttrap_uint32_cmp(const void *ap, const void *bp) 1875 { 1876 return (*(const uint32_t *)ap - *(const uint32_t *)bp); 1877 } 1878 1879 static int 1880 fasttrap_uint64_cmp(const void *ap, const void *bp) 1881 { 1882 return (*(const uint64_t *)ap - *(const uint64_t *)bp); 1883 } 1884 1885 static int 1886 fasttrap_add_probe(fasttrap_probe_spec_t *pdata) 1887 { 1888 fasttrap_provider_t *provider; 1889 fasttrap_probe_t *pp; 1890 fasttrap_tracepoint_t *tp; 1891 char *name; 1892 int i, aframes = 0, whack; 1893 1894 /* 1895 * There needs to be at least one desired trace point. 1896 */ 1897 if (pdata->ftps_noffs == 0) 1898 return (EINVAL); 1899 1900 switch (pdata->ftps_type) { 1901 case DTFTP_ENTRY: 1902 name = "entry"; 1903 aframes = FASTTRAP_ENTRY_AFRAMES; 1904 break; 1905 case DTFTP_RETURN: 1906 name = "return"; 1907 aframes = FASTTRAP_RETURN_AFRAMES; 1908 break; 1909 case DTFTP_OFFSETS: 1910 name = NULL; 1911 break; 1912 default: 1913 return (EINVAL); 1914 } 1915 1916 if ((provider = fasttrap_provider_lookup(pdata->ftps_pid, 1917 FASTTRAP_PID_NAME, &pid_attr)) == NULL) 1918 return (ESRCH); 1919 1920 /* 1921 * Increment this reference count to indicate that a consumer is 1922 * actively adding a new probe associated with this provider. This 1923 * prevents the provider from being deleted -- we'll need to check 1924 * for pending deletions when we drop this reference count. 1925 */ 1926 provider->ftp_ccount++; 1927 mutex_exit(&provider->ftp_mtx); 1928 1929 /* 1930 * Grab the creation lock to ensure consistency between calls to 1931 * dtrace_probe_lookup() and dtrace_probe_create() in the face of 1932 * other threads creating probes. We must drop the provider lock 1933 * before taking this lock to avoid a three-way deadlock with the 1934 * DTrace framework. 1935 */ 1936 mutex_enter(&provider->ftp_cmtx); 1937 1938 if (name == NULL) { 1939 for (i = 0; i < pdata->ftps_noffs; i++) { 1940 char name_str[17]; 1941 1942 (void) sprintf(name_str, "%llx", 1943 (unsigned long long)pdata->ftps_offs[i]); 1944 1945 if (dtrace_probe_lookup(provider->ftp_provid, 1946 pdata->ftps_mod, pdata->ftps_func, name_str) != 0) 1947 continue; 1948 1949 atomic_inc_32(&fasttrap_total); 1950 1951 if (fasttrap_total > fasttrap_max) { 1952 atomic_dec_32(&fasttrap_total); 1953 goto no_mem; 1954 } 1955 1956 pp = kmem_zalloc(sizeof (fasttrap_probe_t), KM_SLEEP); 1957 1958 pp->ftp_prov = provider; 1959 pp->ftp_faddr = pdata->ftps_pc; 1960 pp->ftp_fsize = pdata->ftps_size; 1961 pp->ftp_pid = pdata->ftps_pid; 1962 pp->ftp_ntps = 1; 1963 1964 tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), 1965 KM_SLEEP); 1966 1967 tp->ftt_proc = provider->ftp_proc; 1968 tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc; 1969 tp->ftt_pid = pdata->ftps_pid; 1970 1971 pp->ftp_tps[0].fit_tp = tp; 1972 pp->ftp_tps[0].fit_id.fti_probe = pp; 1973 pp->ftp_tps[0].fit_id.fti_ptype = pdata->ftps_type; 1974 1975 pp->ftp_id = dtrace_probe_create(provider->ftp_provid, 1976 pdata->ftps_mod, pdata->ftps_func, name_str, 1977 FASTTRAP_OFFSET_AFRAMES, pp); 1978 } 1979 1980 } else if (dtrace_probe_lookup(provider->ftp_provid, pdata->ftps_mod, 1981 pdata->ftps_func, name) == 0) { 1982 atomic_add_32(&fasttrap_total, pdata->ftps_noffs); 1983 1984 if (fasttrap_total > fasttrap_max) { 1985 atomic_add_32(&fasttrap_total, -pdata->ftps_noffs); 1986 goto no_mem; 1987 } 1988 1989 /* 1990 * Make sure all tracepoint program counter values are unique. 1991 * We later assume that each probe has exactly one tracepoint 1992 * for a given pc. 1993 */ 1994 qsort(pdata->ftps_offs, pdata->ftps_noffs, 1995 sizeof (uint64_t), fasttrap_uint64_cmp); 1996 for (i = 1; i < pdata->ftps_noffs; i++) { 1997 if (pdata->ftps_offs[i] > pdata->ftps_offs[i - 1]) 1998 continue; 1999 2000 atomic_add_32(&fasttrap_total, -pdata->ftps_noffs); 2001 goto no_mem; 2002 } 2003 2004 ASSERT(pdata->ftps_noffs > 0); 2005 pp = kmem_zalloc(offsetof(fasttrap_probe_t, 2006 ftp_tps[pdata->ftps_noffs]), KM_SLEEP); 2007 2008 pp->ftp_prov = provider; 2009 pp->ftp_faddr = pdata->ftps_pc; 2010 pp->ftp_fsize = pdata->ftps_size; 2011 pp->ftp_pid = pdata->ftps_pid; 2012 pp->ftp_ntps = pdata->ftps_noffs; 2013 2014 for (i = 0; i < pdata->ftps_noffs; i++) { 2015 tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), 2016 KM_SLEEP); 2017 2018 tp->ftt_proc = provider->ftp_proc; 2019 tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc; 2020 tp->ftt_pid = pdata->ftps_pid; 2021 2022 pp->ftp_tps[i].fit_tp = tp; 2023 pp->ftp_tps[i].fit_id.fti_probe = pp; 2024 pp->ftp_tps[i].fit_id.fti_ptype = pdata->ftps_type; 2025 } 2026 2027 pp->ftp_id = dtrace_probe_create(provider->ftp_provid, 2028 pdata->ftps_mod, pdata->ftps_func, name, aframes, pp); 2029 } 2030 2031 mutex_exit(&provider->ftp_cmtx); 2032 2033 /* 2034 * We know that the provider is still valid since we incremented the 2035 * creation reference count. If someone tried to clean up this provider 2036 * while we were using it (e.g. because the process called exec(2) or 2037 * exit(2)), take note of that and try to clean it up now. 2038 */ 2039 mutex_enter(&provider->ftp_mtx); 2040 provider->ftp_ccount--; 2041 whack = provider->ftp_retired; 2042 mutex_exit(&provider->ftp_mtx); 2043 2044 if (whack) 2045 fasttrap_pid_cleanup(); 2046 2047 return (0); 2048 2049 no_mem: 2050 /* 2051 * If we've exhausted the allowable resources, we'll try to remove 2052 * this provider to free some up. This is to cover the case where 2053 * the user has accidentally created many more probes than was 2054 * intended (e.g. pid123:::). 2055 */ 2056 mutex_exit(&provider->ftp_cmtx); 2057 mutex_enter(&provider->ftp_mtx); 2058 provider->ftp_ccount--; 2059 provider->ftp_marked = 1; 2060 mutex_exit(&provider->ftp_mtx); 2061 2062 fasttrap_pid_cleanup(); 2063 2064 return (ENOMEM); 2065 } 2066 2067 /*ARGSUSED*/ 2068 static void * 2069 fasttrap_meta_provide(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid) 2070 { 2071 fasttrap_provider_t *provider; 2072 2073 /* 2074 * A 32-bit unsigned integer (like a pid for example) can be 2075 * expressed in 10 or fewer decimal digits. Make sure that we'll 2076 * have enough space for the provider name. 2077 */ 2078 if (strlen(dhpv->dthpv_provname) + 10 >= 2079 sizeof (provider->ftp_name)) { 2080 printf("failed to instantiate provider %s: " 2081 "name too long to accomodate pid", dhpv->dthpv_provname); 2082 return (NULL); 2083 } 2084 2085 /* 2086 * Don't let folks spoof the true pid provider. 2087 */ 2088 if (strcmp(dhpv->dthpv_provname, FASTTRAP_PID_NAME) == 0) { 2089 printf("failed to instantiate provider %s: " 2090 "%s is an invalid name", dhpv->dthpv_provname, 2091 FASTTRAP_PID_NAME); 2092 return (NULL); 2093 } 2094 2095 /* 2096 * The highest stability class that fasttrap supports is ISA; cap 2097 * the stability of the new provider accordingly. 2098 */ 2099 if (dhpv->dthpv_pattr.dtpa_provider.dtat_class > DTRACE_CLASS_ISA) 2100 dhpv->dthpv_pattr.dtpa_provider.dtat_class = DTRACE_CLASS_ISA; 2101 if (dhpv->dthpv_pattr.dtpa_mod.dtat_class > DTRACE_CLASS_ISA) 2102 dhpv->dthpv_pattr.dtpa_mod.dtat_class = DTRACE_CLASS_ISA; 2103 if (dhpv->dthpv_pattr.dtpa_func.dtat_class > DTRACE_CLASS_ISA) 2104 dhpv->dthpv_pattr.dtpa_func.dtat_class = DTRACE_CLASS_ISA; 2105 if (dhpv->dthpv_pattr.dtpa_name.dtat_class > DTRACE_CLASS_ISA) 2106 dhpv->dthpv_pattr.dtpa_name.dtat_class = DTRACE_CLASS_ISA; 2107 if (dhpv->dthpv_pattr.dtpa_args.dtat_class > DTRACE_CLASS_ISA) 2108 dhpv->dthpv_pattr.dtpa_args.dtat_class = DTRACE_CLASS_ISA; 2109 2110 if ((provider = fasttrap_provider_lookup(pid, dhpv->dthpv_provname, 2111 &dhpv->dthpv_pattr)) == NULL) { 2112 printf("failed to instantiate provider %s for " 2113 "process %u", dhpv->dthpv_provname, (uint_t)pid); 2114 return (NULL); 2115 } 2116 2117 /* 2118 * Up the meta provider count so this provider isn't removed until 2119 * the meta provider has been told to remove it. 2120 */ 2121 provider->ftp_mcount++; 2122 2123 mutex_exit(&provider->ftp_mtx); 2124 2125 return (provider); 2126 } 2127 2128 /* 2129 * We know a few things about our context here: we know that the probe being 2130 * created doesn't already exist (DTrace won't load DOF at the same address 2131 * twice, even if explicitly told to do so) and we know that we are 2132 * single-threaded with respect to the meta provider machinery. Knowing that 2133 * this is a new probe and that there is no way for us to race with another 2134 * operation on this provider allows us an important optimization: we need not 2135 * lookup a probe before adding it. Saving this lookup is important because 2136 * this code is in the fork path for processes with USDT probes, and lookups 2137 * here are potentially very expensive because of long hash conflicts on 2138 * module, function and name (DTrace doesn't hash on provider name). 2139 */ 2140 /*ARGSUSED*/ 2141 static void 2142 fasttrap_meta_create_probe(void *arg, void *parg, 2143 dtrace_helper_probedesc_t *dhpb) 2144 { 2145 fasttrap_provider_t *provider = parg; 2146 fasttrap_probe_t *pp; 2147 fasttrap_tracepoint_t *tp; 2148 int i, j; 2149 uint32_t ntps; 2150 2151 /* 2152 * Since the meta provider count is non-zero we don't have to worry 2153 * about this provider disappearing. 2154 */ 2155 ASSERT(provider->ftp_mcount > 0); 2156 2157 /* 2158 * The offsets must be unique. 2159 */ 2160 qsort(dhpb->dthpb_offs, dhpb->dthpb_noffs, sizeof (uint32_t), 2161 fasttrap_uint32_cmp); 2162 for (i = 1; i < dhpb->dthpb_noffs; i++) { 2163 if (dhpb->dthpb_base + dhpb->dthpb_offs[i] <= 2164 dhpb->dthpb_base + dhpb->dthpb_offs[i - 1]) 2165 return; 2166 } 2167 2168 qsort(dhpb->dthpb_enoffs, dhpb->dthpb_nenoffs, sizeof (uint32_t), 2169 fasttrap_uint32_cmp); 2170 for (i = 1; i < dhpb->dthpb_nenoffs; i++) { 2171 if (dhpb->dthpb_base + dhpb->dthpb_enoffs[i] <= 2172 dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1]) 2173 return; 2174 } 2175 2176 ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs; 2177 ASSERT(ntps > 0); 2178 2179 atomic_add_32(&fasttrap_total, ntps); 2180 2181 if (fasttrap_total > fasttrap_max) { 2182 atomic_add_32(&fasttrap_total, -ntps); 2183 return; 2184 } 2185 2186 pp = kmem_zalloc(offsetof(fasttrap_probe_t, ftp_tps[ntps]), KM_SLEEP); 2187 2188 pp->ftp_prov = provider; 2189 pp->ftp_pid = provider->ftp_pid; 2190 pp->ftp_ntps = ntps; 2191 pp->ftp_nargs = dhpb->dthpb_xargc; 2192 pp->ftp_xtypes = dhpb->dthpb_xtypes; 2193 pp->ftp_ntypes = dhpb->dthpb_ntypes; 2194 2195 /* 2196 * First create a tracepoint for each actual point of interest. 2197 */ 2198 for (i = 0; i < dhpb->dthpb_noffs; i++) { 2199 tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP); 2200 2201 tp->ftt_proc = provider->ftp_proc; 2202 tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i]; 2203 tp->ftt_pid = provider->ftp_pid; 2204 2205 pp->ftp_tps[i].fit_tp = tp; 2206 pp->ftp_tps[i].fit_id.fti_probe = pp; 2207 #ifdef __sparc 2208 pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_POST_OFFSETS; 2209 #else 2210 pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_OFFSETS; 2211 #endif 2212 } 2213 2214 /* 2215 * Then create a tracepoint for each is-enabled point. 2216 */ 2217 for (j = 0; i < ntps; i++, j++) { 2218 tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP); 2219 2220 tp->ftt_proc = provider->ftp_proc; 2221 tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j]; 2222 tp->ftt_pid = provider->ftp_pid; 2223 2224 pp->ftp_tps[i].fit_tp = tp; 2225 pp->ftp_tps[i].fit_id.fti_probe = pp; 2226 pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED; 2227 } 2228 2229 /* 2230 * If the arguments are shuffled around we set the argument remapping 2231 * table. Later, when the probe fires, we only remap the arguments 2232 * if the table is non-NULL. 2233 */ 2234 for (i = 0; i < dhpb->dthpb_xargc; i++) { 2235 if (dhpb->dthpb_args[i] != i) { 2236 pp->ftp_argmap = dhpb->dthpb_args; 2237 break; 2238 } 2239 } 2240 2241 /* 2242 * The probe is fully constructed -- register it with DTrace. 2243 */ 2244 pp->ftp_id = dtrace_probe_create(provider->ftp_provid, dhpb->dthpb_mod, 2245 dhpb->dthpb_func, dhpb->dthpb_name, FASTTRAP_OFFSET_AFRAMES, pp); 2246 } 2247 2248 /*ARGSUSED*/ 2249 static void 2250 fasttrap_meta_remove(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid) 2251 { 2252 /* 2253 * Clean up the USDT provider. There may be active consumers of the 2254 * provider busy adding probes, no damage will actually befall the 2255 * provider until that count has dropped to zero. This just puts 2256 * the provider on death row. 2257 */ 2258 fasttrap_provider_retire(pid, dhpv->dthpv_provname, 1); 2259 } 2260 2261 static dtrace_mops_t fasttrap_mops = { 2262 fasttrap_meta_create_probe, 2263 fasttrap_meta_provide, 2264 fasttrap_meta_remove 2265 }; 2266 2267 /*ARGSUSED*/ 2268 static int 2269 fasttrap_open(struct cdev *dev __unused, int oflags __unused, 2270 int devtype __unused, struct thread *td __unused) 2271 { 2272 return (0); 2273 } 2274 2275 /*ARGSUSED*/ 2276 static int 2277 fasttrap_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int fflag, 2278 struct thread *td) 2279 { 2280 #ifdef notyet 2281 struct kinfo_proc kp; 2282 const cred_t *cr = td->td_ucred; 2283 #endif 2284 if (!dtrace_attached()) 2285 return (EAGAIN); 2286 2287 if (cmd == FASTTRAPIOC_MAKEPROBE) { 2288 fasttrap_probe_spec_t *uprobe = *(fasttrap_probe_spec_t **)arg; 2289 fasttrap_probe_spec_t *probe; 2290 uint64_t noffs; 2291 size_t size; 2292 int ret, err; 2293 2294 if (copyin(&uprobe->ftps_noffs, &noffs, 2295 sizeof (uprobe->ftps_noffs))) 2296 return (EFAULT); 2297 2298 /* 2299 * Probes must have at least one tracepoint. 2300 */ 2301 if (noffs == 0) 2302 return (EINVAL); 2303 2304 size = sizeof (fasttrap_probe_spec_t) + 2305 sizeof (probe->ftps_offs[0]) * (noffs - 1); 2306 2307 if (size > 1024 * 1024) 2308 return (ENOMEM); 2309 2310 probe = kmem_alloc(size, KM_SLEEP); 2311 2312 if (copyin(uprobe, probe, size) != 0 || 2313 probe->ftps_noffs != noffs) { 2314 kmem_free(probe, size); 2315 return (EFAULT); 2316 } 2317 2318 /* 2319 * Verify that the function and module strings contain no 2320 * funny characters. 2321 */ 2322 if (u8_validate(probe->ftps_func, strlen(probe->ftps_func), 2323 NULL, U8_VALIDATE_ENTIRE, &err) < 0) { 2324 ret = EINVAL; 2325 goto err; 2326 } 2327 2328 if (u8_validate(probe->ftps_mod, strlen(probe->ftps_mod), 2329 NULL, U8_VALIDATE_ENTIRE, &err) < 0) { 2330 ret = EINVAL; 2331 goto err; 2332 } 2333 2334 #ifdef notyet 2335 if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) { 2336 proc_t *p; 2337 pid_t pid = probe->ftps_pid; 2338 2339 #ifdef illumos 2340 mutex_enter(&pidlock); 2341 #endif 2342 /* 2343 * Report an error if the process doesn't exist 2344 * or is actively being birthed. 2345 */ 2346 sx_slock(&proctree_lock); 2347 p = pfind(pid); 2348 if (p) 2349 fill_kinfo_proc(p, &kp); 2350 sx_sunlock(&proctree_lock); 2351 if (p == NULL || kp.ki_stat == SIDL) { 2352 #ifdef illumos 2353 mutex_exit(&pidlock); 2354 #endif 2355 return (ESRCH); 2356 } 2357 #ifdef illumos 2358 mutex_enter(&p->p_lock); 2359 mutex_exit(&pidlock); 2360 #else 2361 PROC_LOCK_ASSERT(p, MA_OWNED); 2362 #endif 2363 2364 #ifdef notyet 2365 if ((ret = priv_proc_cred_perm(cr, p, NULL, 2366 VREAD | VWRITE)) != 0) { 2367 #ifdef illumos 2368 mutex_exit(&p->p_lock); 2369 #else 2370 PROC_UNLOCK(p); 2371 #endif 2372 return (ret); 2373 } 2374 #endif /* notyet */ 2375 #ifdef illumos 2376 mutex_exit(&p->p_lock); 2377 #else 2378 PROC_UNLOCK(p); 2379 #endif 2380 } 2381 #endif /* notyet */ 2382 2383 ret = fasttrap_add_probe(probe); 2384 err: 2385 kmem_free(probe, size); 2386 2387 return (ret); 2388 2389 } else if (cmd == FASTTRAPIOC_GETINSTR) { 2390 fasttrap_instr_query_t instr; 2391 fasttrap_tracepoint_t *tp; 2392 uint_t index; 2393 #ifdef illumos 2394 int ret; 2395 #endif 2396 2397 #ifdef illumos 2398 if (copyin((void *)arg, &instr, sizeof (instr)) != 0) 2399 return (EFAULT); 2400 #endif 2401 2402 #ifdef notyet 2403 if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) { 2404 proc_t *p; 2405 pid_t pid = instr.ftiq_pid; 2406 2407 #ifdef illumos 2408 mutex_enter(&pidlock); 2409 #endif 2410 /* 2411 * Report an error if the process doesn't exist 2412 * or is actively being birthed. 2413 */ 2414 sx_slock(&proctree_lock); 2415 p = pfind(pid); 2416 if (p) 2417 fill_kinfo_proc(p, &kp); 2418 sx_sunlock(&proctree_lock); 2419 if (p == NULL || kp.ki_stat == SIDL) { 2420 #ifdef illumos 2421 mutex_exit(&pidlock); 2422 #endif 2423 return (ESRCH); 2424 } 2425 #ifdef illumos 2426 mutex_enter(&p->p_lock); 2427 mutex_exit(&pidlock); 2428 #else 2429 PROC_LOCK_ASSERT(p, MA_OWNED); 2430 #endif 2431 2432 #ifdef notyet 2433 if ((ret = priv_proc_cred_perm(cr, p, NULL, 2434 VREAD)) != 0) { 2435 #ifdef illumos 2436 mutex_exit(&p->p_lock); 2437 #else 2438 PROC_UNLOCK(p); 2439 #endif 2440 return (ret); 2441 } 2442 #endif /* notyet */ 2443 2444 #ifdef illumos 2445 mutex_exit(&p->p_lock); 2446 #else 2447 PROC_UNLOCK(p); 2448 #endif 2449 } 2450 #endif /* notyet */ 2451 2452 index = FASTTRAP_TPOINTS_INDEX(instr.ftiq_pid, instr.ftiq_pc); 2453 2454 mutex_enter(&fasttrap_tpoints.fth_table[index].ftb_mtx); 2455 tp = fasttrap_tpoints.fth_table[index].ftb_data; 2456 while (tp != NULL) { 2457 if (instr.ftiq_pid == tp->ftt_pid && 2458 instr.ftiq_pc == tp->ftt_pc && 2459 tp->ftt_proc->ftpc_acount != 0) 2460 break; 2461 2462 tp = tp->ftt_next; 2463 } 2464 2465 if (tp == NULL) { 2466 mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx); 2467 return (ENOENT); 2468 } 2469 2470 bcopy(&tp->ftt_instr, &instr.ftiq_instr, 2471 sizeof (instr.ftiq_instr)); 2472 mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx); 2473 2474 if (copyout(&instr, (void *)arg, sizeof (instr)) != 0) 2475 return (EFAULT); 2476 2477 return (0); 2478 } 2479 2480 return (EINVAL); 2481 } 2482 2483 static int 2484 fasttrap_load(void) 2485 { 2486 ulong_t nent; 2487 int i, ret; 2488 2489 /* Create the /dev/dtrace/fasttrap entry. */ 2490 fasttrap_cdev = make_dev(&fasttrap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 2491 "dtrace/fasttrap"); 2492 2493 mtx_init(&fasttrap_cleanup_mtx, "fasttrap clean", "dtrace", MTX_DEF); 2494 mutex_init(&fasttrap_count_mtx, "fasttrap count mtx", MUTEX_DEFAULT, 2495 NULL); 2496 2497 #ifdef illumos 2498 fasttrap_max = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 2499 "fasttrap-max-probes", FASTTRAP_MAX_DEFAULT); 2500 #endif 2501 fasttrap_total = 0; 2502 2503 /* 2504 * Conjure up the tracepoints hashtable... 2505 */ 2506 #ifdef illumos 2507 nent = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 2508 "fasttrap-hash-size", FASTTRAP_TPOINTS_DEFAULT_SIZE); 2509 #else 2510 nent = tpoints_hash_size; 2511 #endif 2512 2513 if (nent == 0 || nent > 0x1000000) 2514 nent = FASTTRAP_TPOINTS_DEFAULT_SIZE; 2515 2516 tpoints_hash_size = nent; 2517 2518 if (ISP2(nent)) 2519 fasttrap_tpoints.fth_nent = nent; 2520 else 2521 fasttrap_tpoints.fth_nent = 1 << fasttrap_highbit(nent); 2522 ASSERT(fasttrap_tpoints.fth_nent > 0); 2523 fasttrap_tpoints.fth_mask = fasttrap_tpoints.fth_nent - 1; 2524 fasttrap_tpoints.fth_table = kmem_zalloc(fasttrap_tpoints.fth_nent * 2525 sizeof (fasttrap_bucket_t), KM_SLEEP); 2526 #ifndef illumos 2527 for (i = 0; i < fasttrap_tpoints.fth_nent; i++) 2528 mutex_init(&fasttrap_tpoints.fth_table[i].ftb_mtx, 2529 "tracepoints bucket mtx", MUTEX_DEFAULT, NULL); 2530 #endif 2531 2532 /* 2533 * ... and the providers hash table... 2534 */ 2535 nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE; 2536 if (ISP2(nent)) 2537 fasttrap_provs.fth_nent = nent; 2538 else 2539 fasttrap_provs.fth_nent = 1 << fasttrap_highbit(nent); 2540 ASSERT(fasttrap_provs.fth_nent > 0); 2541 fasttrap_provs.fth_mask = fasttrap_provs.fth_nent - 1; 2542 fasttrap_provs.fth_table = kmem_zalloc(fasttrap_provs.fth_nent * 2543 sizeof (fasttrap_bucket_t), KM_SLEEP); 2544 #ifndef illumos 2545 for (i = 0; i < fasttrap_provs.fth_nent; i++) 2546 mutex_init(&fasttrap_provs.fth_table[i].ftb_mtx, 2547 "providers bucket mtx", MUTEX_DEFAULT, NULL); 2548 #endif 2549 2550 ret = kproc_create(fasttrap_pid_cleanup_cb, NULL, 2551 &fasttrap_cleanup_proc, 0, 0, "ftcleanup"); 2552 if (ret != 0) { 2553 destroy_dev(fasttrap_cdev); 2554 #ifndef illumos 2555 for (i = 0; i < fasttrap_provs.fth_nent; i++) 2556 mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx); 2557 for (i = 0; i < fasttrap_tpoints.fth_nent; i++) 2558 mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx); 2559 #endif 2560 kmem_free(fasttrap_provs.fth_table, fasttrap_provs.fth_nent * 2561 sizeof (fasttrap_bucket_t)); 2562 mtx_destroy(&fasttrap_cleanup_mtx); 2563 mutex_destroy(&fasttrap_count_mtx); 2564 return (ret); 2565 } 2566 2567 2568 /* 2569 * ... and the procs hash table. 2570 */ 2571 nent = FASTTRAP_PROCS_DEFAULT_SIZE; 2572 if (ISP2(nent)) 2573 fasttrap_procs.fth_nent = nent; 2574 else 2575 fasttrap_procs.fth_nent = 1 << fasttrap_highbit(nent); 2576 ASSERT(fasttrap_procs.fth_nent > 0); 2577 fasttrap_procs.fth_mask = fasttrap_procs.fth_nent - 1; 2578 fasttrap_procs.fth_table = kmem_zalloc(fasttrap_procs.fth_nent * 2579 sizeof (fasttrap_bucket_t), KM_SLEEP); 2580 #ifndef illumos 2581 for (i = 0; i < fasttrap_procs.fth_nent; i++) 2582 mutex_init(&fasttrap_procs.fth_table[i].ftb_mtx, 2583 "processes bucket mtx", MUTEX_DEFAULT, NULL); 2584 2585 rm_init(&fasttrap_tp_lock, "fasttrap tracepoint"); 2586 2587 /* 2588 * This event handler must run before kdtrace_thread_dtor() since it 2589 * accesses the thread's struct kdtrace_thread. 2590 */ 2591 fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor, 2592 fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST); 2593 #endif 2594 2595 /* 2596 * Install our hooks into fork(2), exec(2), and exit(2). 2597 */ 2598 dtrace_fasttrap_fork = &fasttrap_fork; 2599 dtrace_fasttrap_exit = &fasttrap_exec_exit; 2600 dtrace_fasttrap_exec = &fasttrap_exec_exit; 2601 2602 (void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL, 2603 &fasttrap_meta_id); 2604 2605 return (0); 2606 } 2607 2608 static int 2609 fasttrap_unload(void) 2610 { 2611 int i, fail = 0; 2612 2613 /* 2614 * Unregister the meta-provider to make sure no new fasttrap- 2615 * managed providers come along while we're trying to close up 2616 * shop. If we fail to detach, we'll need to re-register as a 2617 * meta-provider. We can fail to unregister as a meta-provider 2618 * if providers we manage still exist. 2619 */ 2620 if (fasttrap_meta_id != DTRACE_METAPROVNONE && 2621 dtrace_meta_unregister(fasttrap_meta_id) != 0) 2622 return (-1); 2623 2624 /* 2625 * Iterate over all of our providers. If there's still a process 2626 * that corresponds to that pid, fail to detach. 2627 */ 2628 for (i = 0; i < fasttrap_provs.fth_nent; i++) { 2629 fasttrap_provider_t **fpp, *fp; 2630 fasttrap_bucket_t *bucket = &fasttrap_provs.fth_table[i]; 2631 2632 mutex_enter(&bucket->ftb_mtx); 2633 fpp = (fasttrap_provider_t **)&bucket->ftb_data; 2634 while ((fp = *fpp) != NULL) { 2635 /* 2636 * Acquire and release the lock as a simple way of 2637 * waiting for any other consumer to finish with 2638 * this provider. A thread must first acquire the 2639 * bucket lock so there's no chance of another thread 2640 * blocking on the provider's lock. 2641 */ 2642 mutex_enter(&fp->ftp_mtx); 2643 mutex_exit(&fp->ftp_mtx); 2644 2645 if (dtrace_unregister(fp->ftp_provid) != 0) { 2646 fail = 1; 2647 fpp = &fp->ftp_next; 2648 } else { 2649 *fpp = fp->ftp_next; 2650 fasttrap_provider_free(fp); 2651 } 2652 } 2653 2654 mutex_exit(&bucket->ftb_mtx); 2655 } 2656 2657 if (fail) { 2658 (void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL, 2659 &fasttrap_meta_id); 2660 2661 return (-1); 2662 } 2663 2664 /* 2665 * Stop new processes from entering these hooks now, before the 2666 * fasttrap_cleanup thread runs. That way all processes will hopefully 2667 * be out of these hooks before we free fasttrap_provs.fth_table 2668 */ 2669 ASSERT(dtrace_fasttrap_fork == &fasttrap_fork); 2670 dtrace_fasttrap_fork = NULL; 2671 2672 ASSERT(dtrace_fasttrap_exec == &fasttrap_exec_exit); 2673 dtrace_fasttrap_exec = NULL; 2674 2675 ASSERT(dtrace_fasttrap_exit == &fasttrap_exec_exit); 2676 dtrace_fasttrap_exit = NULL; 2677 2678 mtx_lock(&fasttrap_cleanup_mtx); 2679 fasttrap_cleanup_drain = 1; 2680 /* Wait for the cleanup thread to finish up and signal us. */ 2681 wakeup(&fasttrap_cleanup_cv); 2682 mtx_sleep(&fasttrap_cleanup_drain, &fasttrap_cleanup_mtx, 0, "ftcld", 2683 0); 2684 fasttrap_cleanup_proc = NULL; 2685 mtx_destroy(&fasttrap_cleanup_mtx); 2686 2687 #ifdef DEBUG 2688 mutex_enter(&fasttrap_count_mtx); 2689 ASSERT(fasttrap_pid_count == 0); 2690 mutex_exit(&fasttrap_count_mtx); 2691 #endif 2692 2693 #ifndef illumos 2694 EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag); 2695 2696 for (i = 0; i < fasttrap_tpoints.fth_nent; i++) 2697 mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx); 2698 for (i = 0; i < fasttrap_provs.fth_nent; i++) 2699 mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx); 2700 for (i = 0; i < fasttrap_procs.fth_nent; i++) 2701 mutex_destroy(&fasttrap_procs.fth_table[i].ftb_mtx); 2702 #endif 2703 kmem_free(fasttrap_tpoints.fth_table, 2704 fasttrap_tpoints.fth_nent * sizeof (fasttrap_bucket_t)); 2705 fasttrap_tpoints.fth_nent = 0; 2706 2707 kmem_free(fasttrap_provs.fth_table, 2708 fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t)); 2709 fasttrap_provs.fth_nent = 0; 2710 2711 kmem_free(fasttrap_procs.fth_table, 2712 fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t)); 2713 fasttrap_procs.fth_nent = 0; 2714 2715 #ifndef illumos 2716 destroy_dev(fasttrap_cdev); 2717 mutex_destroy(&fasttrap_count_mtx); 2718 rm_destroy(&fasttrap_tp_lock); 2719 #endif 2720 2721 return (0); 2722 } 2723 2724 /* ARGSUSED */ 2725 static int 2726 fasttrap_modevent(module_t mod __unused, int type, void *data __unused) 2727 { 2728 int error = 0; 2729 2730 switch (type) { 2731 case MOD_LOAD: 2732 break; 2733 2734 case MOD_UNLOAD: 2735 break; 2736 2737 case MOD_SHUTDOWN: 2738 break; 2739 2740 default: 2741 error = EOPNOTSUPP; 2742 break; 2743 } 2744 return (error); 2745 } 2746 2747 SYSINIT(fasttrap_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fasttrap_load, 2748 NULL); 2749 SYSUNINIT(fasttrap_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 2750 fasttrap_unload, NULL); 2751 2752 DEV_MODULE(fasttrap, fasttrap_modevent, NULL); 2753 MODULE_VERSION(fasttrap, 1); 2754 MODULE_DEPEND(fasttrap, dtrace, 1, 1, 1); 2755 MODULE_DEPEND(fasttrap, opensolaris, 1, 1, 1); 2756