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