1248457Sjhibbits/*
2248457Sjhibbits * CDDL HEADER START
3248457Sjhibbits *
4248457Sjhibbits * The contents of this file are subject to the terms of the
5248457Sjhibbits * Common Development and Distribution License (the "License").
6248457Sjhibbits * You may not use this file except in compliance with the License.
7248457Sjhibbits *
8248457Sjhibbits * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9248457Sjhibbits * or http://www.opensolaris.org/os/licensing.
10248457Sjhibbits * See the License for the specific language governing permissions
11248457Sjhibbits * and limitations under the License.
12248457Sjhibbits *
13248457Sjhibbits * When distributing Covered Code, include this CDDL HEADER in each
14248457Sjhibbits * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15248457Sjhibbits * If applicable, add the following below this CDDL HEADER, with the
16248457Sjhibbits * fields enclosed by brackets "[]" replaced with your own identifying
17248457Sjhibbits * information: Portions Copyright [yyyy] [name of copyright owner]
18248457Sjhibbits *
19248457Sjhibbits * CDDL HEADER END
20248457Sjhibbits *
21248457Sjhibbits * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
22248457Sjhibbits * Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org
23248457Sjhibbits *
24248457Sjhibbits * $FreeBSD$
25248457Sjhibbits *
26248457Sjhibbits */
27248457Sjhibbits
28248457Sjhibbits/*
29248457Sjhibbits * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
30248457Sjhibbits * Use is subject to license terms.
31248457Sjhibbits */
32248457Sjhibbits
33248457Sjhibbits#include <sys/cdefs.h>
34248457Sjhibbits#include <sys/param.h>
35248457Sjhibbits#include <sys/systm.h>
36248457Sjhibbits#include <sys/conf.h>
37248457Sjhibbits#include <sys/cpuvar.h>
38248457Sjhibbits#include <sys/fcntl.h>
39248457Sjhibbits#include <sys/filio.h>
40248457Sjhibbits#include <sys/kdb.h>
41248457Sjhibbits#include <sys/kernel.h>
42248457Sjhibbits#include <sys/kmem.h>
43248457Sjhibbits#include <sys/kthread.h>
44248457Sjhibbits#include <sys/limits.h>
45248457Sjhibbits#include <sys/linker.h>
46248457Sjhibbits#include <sys/lock.h>
47248457Sjhibbits#include <sys/malloc.h>
48248457Sjhibbits#include <sys/module.h>
49248457Sjhibbits#include <sys/mutex.h>
50248457Sjhibbits#include <sys/pcpu.h>
51248457Sjhibbits#include <sys/poll.h>
52248457Sjhibbits#include <sys/proc.h>
53248457Sjhibbits#include <sys/selinfo.h>
54248457Sjhibbits#include <sys/smp.h>
55248457Sjhibbits#include <sys/syscall.h>
56248457Sjhibbits#include <sys/sysent.h>
57248457Sjhibbits#include <sys/sysproto.h>
58248457Sjhibbits#include <sys/uio.h>
59248457Sjhibbits#include <sys/unistd.h>
60255099Sjhibbits#include <machine/md_var.h>
61248457Sjhibbits#include <machine/stdarg.h>
62248457Sjhibbits
63248457Sjhibbits#include <sys/dtrace.h>
64248457Sjhibbits#include <sys/dtrace_bsd.h>
65248457Sjhibbits
66248457Sjhibbitsstatic MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
67248457Sjhibbits
68248457Sjhibbits#define FBT_PATCHVAL		0x7c810808
69248457Sjhibbits#define FBT_MFLR_R0		0x7c0802a6
70248457Sjhibbits#define FBT_MTLR_R0		0x7c0803a6
71248457Sjhibbits#define FBT_BLR			0x4e800020
72248457Sjhibbits#define FBT_BCTR		0x4e800030
73248457Sjhibbits#define FBT_BRANCH		0x48000000
74248457Sjhibbits#define FBT_BR_MASK		0x03fffffc
75248457Sjhibbits#define FBT_IS_JUMP(instr)	((instr & ~FBT_BR_MASK) == FBT_BRANCH)
76248457Sjhibbits
77248457Sjhibbitsstatic d_open_t	fbt_open;
78248457Sjhibbitsstatic int	fbt_unload(void);
79248457Sjhibbitsstatic void	fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
80248457Sjhibbitsstatic void	fbt_provide_module(void *, modctl_t *);
81248457Sjhibbitsstatic void	fbt_destroy(void *, dtrace_id_t, void *);
82248457Sjhibbitsstatic void	fbt_enable(void *, dtrace_id_t, void *);
83248457Sjhibbitsstatic void	fbt_disable(void *, dtrace_id_t, void *);
84248457Sjhibbitsstatic void	fbt_load(void *);
85248457Sjhibbitsstatic void	fbt_suspend(void *, dtrace_id_t, void *);
86248457Sjhibbitsstatic void	fbt_resume(void *, dtrace_id_t, void *);
87248457Sjhibbits
88248457Sjhibbits#define	FBT_ENTRY	"entry"
89248457Sjhibbits#define	FBT_RETURN	"return"
90248457Sjhibbits#define	FBT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
91248457Sjhibbits#define	FBT_PROBETAB_SIZE	0x8000		/* 32k entries -- 128K total */
92248457Sjhibbits
93248457Sjhibbitsstatic struct cdevsw fbt_cdevsw = {
94248457Sjhibbits	.d_version	= D_VERSION,
95248457Sjhibbits	.d_open		= fbt_open,
96248457Sjhibbits	.d_name		= "fbt",
97248457Sjhibbits};
98248457Sjhibbits
99248457Sjhibbitsstatic dtrace_pattr_t fbt_attr = {
100248457Sjhibbits{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
101248457Sjhibbits{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
102248457Sjhibbits{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
103248457Sjhibbits{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
104248457Sjhibbits{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
105248457Sjhibbits};
106248457Sjhibbits
107248457Sjhibbitsstatic dtrace_pops_t fbt_pops = {
108248457Sjhibbits	NULL,
109248457Sjhibbits	fbt_provide_module,
110248457Sjhibbits	fbt_enable,
111248457Sjhibbits	fbt_disable,
112248457Sjhibbits	fbt_suspend,
113248457Sjhibbits	fbt_resume,
114248457Sjhibbits	fbt_getargdesc,
115248457Sjhibbits	NULL,
116248457Sjhibbits	NULL,
117248457Sjhibbits	fbt_destroy
118248457Sjhibbits};
119248457Sjhibbits
120248457Sjhibbitstypedef struct fbt_probe {
121248457Sjhibbits	struct fbt_probe *fbtp_hashnext;
122248457Sjhibbits	uint32_t	*fbtp_patchpoint;
123248457Sjhibbits	int8_t		fbtp_rval;
124248457Sjhibbits	uint32_t	fbtp_patchval;
125248457Sjhibbits	uint32_t	fbtp_savedval;
126248457Sjhibbits	uintptr_t	fbtp_roffset;
127248457Sjhibbits	dtrace_id_t	fbtp_id;
128248457Sjhibbits	const char	*fbtp_name;
129248457Sjhibbits	modctl_t	*fbtp_ctl;
130248457Sjhibbits	int		fbtp_loadcnt;
131248457Sjhibbits	int		fbtp_primary;
132248457Sjhibbits	int		fbtp_invop_cnt;
133248457Sjhibbits	int		fbtp_symindx;
134248457Sjhibbits	struct fbt_probe *fbtp_next;
135248457Sjhibbits} fbt_probe_t;
136248457Sjhibbits
137248457Sjhibbitsstatic struct cdev		*fbt_cdev;
138248457Sjhibbitsstatic dtrace_provider_id_t	fbt_id;
139248457Sjhibbitsstatic fbt_probe_t		**fbt_probetab;
140248457Sjhibbitsstatic int			fbt_probetab_size;
141248457Sjhibbitsstatic int			fbt_probetab_mask;
142248457Sjhibbitsstatic int			fbt_verbose = 0;
143248457Sjhibbits
144248457Sjhibbitsstatic int
145248457Sjhibbitsfbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
146248457Sjhibbits{
147248457Sjhibbits	struct trapframe *frame = (struct trapframe *)stack;
148248457Sjhibbits	solaris_cpu_t *cpu = &solaris_cpu[curcpu];
149248457Sjhibbits	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
150248457Sjhibbits	uintptr_t tmp;
151248457Sjhibbits
152248457Sjhibbits	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
153248457Sjhibbits		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
154248457Sjhibbits			fbt->fbtp_invop_cnt++;
155248457Sjhibbits			if (fbt->fbtp_roffset == 0) {
156248457Sjhibbits				cpu->cpu_dtrace_caller = addr;
157248457Sjhibbits
158248457Sjhibbits				dtrace_probe(fbt->fbtp_id, frame->fixreg[3],
159248457Sjhibbits				    frame->fixreg[4], frame->fixreg[5],
160248457Sjhibbits				    frame->fixreg[6], frame->fixreg[7]);
161248457Sjhibbits
162248457Sjhibbits				cpu->cpu_dtrace_caller = 0;
163248457Sjhibbits			} else {
164248457Sjhibbits
165248457Sjhibbits				dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
166248457Sjhibbits				    rval, 0, 0, 0);
167248457Sjhibbits				/*
168248457Sjhibbits				 * The caller doesn't have the fbt item, so
169248457Sjhibbits				 * fixup tail calls here.
170248457Sjhibbits				 */
171248457Sjhibbits				if (fbt->fbtp_rval == DTRACE_INVOP_JUMP) {
172248457Sjhibbits					frame->srr0 = (uintptr_t)fbt->fbtp_patchpoint;
173248457Sjhibbits					tmp = fbt->fbtp_savedval & FBT_BR_MASK;
174248457Sjhibbits					/* Sign extend. */
175248457Sjhibbits					if (tmp & 0x02000000)
176255099Sjhibbits#ifdef __powerpc64__
177255099Sjhibbits						tmp |= 0xfffffffffc000000ULL;
178255099Sjhibbits#else
179255099Sjhibbits						tmp |= 0xfc000000UL;
180255099Sjhibbits#endif
181248457Sjhibbits					frame->srr0 += tmp;
182248457Sjhibbits				}
183248457Sjhibbits				cpu->cpu_dtrace_caller = 0;
184248457Sjhibbits			}
185248457Sjhibbits
186248457Sjhibbits			return (fbt->fbtp_rval);
187248457Sjhibbits		}
188248457Sjhibbits	}
189248457Sjhibbits
190248457Sjhibbits	return (0);
191248457Sjhibbits}
192248457Sjhibbits
193248457Sjhibbitsstatic int
194248457Sjhibbitsfbt_provide_module_function(linker_file_t lf, int symindx,
195248457Sjhibbits    linker_symval_t *symval, void *opaque)
196248457Sjhibbits{
197248457Sjhibbits	char *modname = opaque;
198248457Sjhibbits	const char *name = symval->name;
199248457Sjhibbits	fbt_probe_t *fbt, *retfbt;
200248457Sjhibbits	int j;
201248457Sjhibbits	u_int32_t *instr, *limit;
202248457Sjhibbits
203255099Sjhibbits	/* PowerPC64 uses '.' prefixes on symbol names, ignore it. */
204255099Sjhibbits	if (name[0] == '.')
205255099Sjhibbits		name++;
206255099Sjhibbits
207248457Sjhibbits	if (strncmp(name, "dtrace_", 7) == 0 &&
208248457Sjhibbits	    strncmp(name, "dtrace_safe_", 12) != 0) {
209248457Sjhibbits		/*
210248457Sjhibbits		 * Anything beginning with "dtrace_" may be called
211248457Sjhibbits		 * from probe context unless it explicitly indicates
212248457Sjhibbits		 * that it won't be called from probe context by
213248457Sjhibbits		 * using the prefix "dtrace_safe_".
214248457Sjhibbits		 */
215248457Sjhibbits		return (0);
216248457Sjhibbits	}
217248457Sjhibbits
218248457Sjhibbits	if (name[0] == '_' && name[1] == '_')
219248457Sjhibbits		return (0);
220248457Sjhibbits
221248457Sjhibbits	instr = (u_int32_t *) symval->value;
222260670Sjhibbits	limit = (u_int32_t *) (symval->value + symval->size);
223248457Sjhibbits
224248457Sjhibbits	for (; instr < limit; instr++)
225248457Sjhibbits		if (*instr == FBT_MFLR_R0)
226248457Sjhibbits			break;
227248457Sjhibbits
228255099Sjhibbits	if (*instr != FBT_MFLR_R0)
229248457Sjhibbits		return (0);
230248457Sjhibbits
231248457Sjhibbits	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
232248457Sjhibbits	fbt->fbtp_name = name;
233248457Sjhibbits	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
234248457Sjhibbits	    name, FBT_ENTRY, 3, fbt);
235248457Sjhibbits	fbt->fbtp_patchpoint = instr;
236248457Sjhibbits	fbt->fbtp_ctl = lf;
237248457Sjhibbits	fbt->fbtp_loadcnt = lf->loadcnt;
238248457Sjhibbits	fbt->fbtp_savedval = *instr;
239248457Sjhibbits	fbt->fbtp_patchval = FBT_PATCHVAL;
240248457Sjhibbits	fbt->fbtp_rval = DTRACE_INVOP_MFLR_R0;
241248457Sjhibbits	fbt->fbtp_symindx = symindx;
242248457Sjhibbits
243248457Sjhibbits	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
244248457Sjhibbits	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
245248457Sjhibbits
246248457Sjhibbits	lf->fbt_nentries++;
247248457Sjhibbits
248248457Sjhibbits	retfbt = NULL;
249248457Sjhibbitsagain:
250248457Sjhibbits	if (instr >= limit)
251248457Sjhibbits		return (0);
252248457Sjhibbits
253248457Sjhibbits	/*
254248457Sjhibbits	 * We (desperately) want to avoid erroneously instrumenting a
255248457Sjhibbits	 * jump table To determine if we're looking at a true instruction
256248457Sjhibbits	 * sequence or an inline jump table that happens to contain the same
257248457Sjhibbits	 * byte sequences, we resort to some heuristic sleeze:  we treat this
258248457Sjhibbits	 * instruction as being contained within a pointer, and see if that
259248457Sjhibbits	 * pointer points to within the body of the function.  If it does, we
260248457Sjhibbits	 * refuse to instrument it.
261248457Sjhibbits	 */
262248457Sjhibbits	{
263248457Sjhibbits		uint32_t *ptr;
264248457Sjhibbits
265248457Sjhibbits		ptr = *(uint32_t **)instr;
266248457Sjhibbits
267248457Sjhibbits		if (ptr >= (uint32_t *) symval->value && ptr < limit) {
268248457Sjhibbits			instr++;
269248457Sjhibbits			goto again;
270248457Sjhibbits		}
271248457Sjhibbits	}
272248457Sjhibbits
273248457Sjhibbits	if (*instr != FBT_MTLR_R0) {
274248457Sjhibbits		instr++;
275248457Sjhibbits		goto again;
276248457Sjhibbits	}
277248457Sjhibbits
278248457Sjhibbits	instr++;
279248457Sjhibbits
280248457Sjhibbits	for (j = 0; j < 12 && instr < limit; j++, instr++) {
281260670Sjhibbits		if ((*instr == FBT_BCTR) || (*instr == FBT_BLR) ||
282248457Sjhibbits		    FBT_IS_JUMP(*instr))
283248457Sjhibbits			break;
284248457Sjhibbits	}
285248457Sjhibbits
286248457Sjhibbits	if (!(*instr == FBT_BCTR || *instr == FBT_BLR || FBT_IS_JUMP(*instr)))
287248457Sjhibbits		goto again;
288248457Sjhibbits
289248457Sjhibbits	/*
290248457Sjhibbits	 * We have a winner!
291248457Sjhibbits	 */
292248457Sjhibbits	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
293248457Sjhibbits	fbt->fbtp_name = name;
294248457Sjhibbits
295248457Sjhibbits	if (retfbt == NULL) {
296248457Sjhibbits		fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
297255099Sjhibbits		    name, FBT_RETURN, 5, fbt);
298248457Sjhibbits	} else {
299248457Sjhibbits		retfbt->fbtp_next = fbt;
300248457Sjhibbits		fbt->fbtp_id = retfbt->fbtp_id;
301248457Sjhibbits	}
302248457Sjhibbits
303248457Sjhibbits	retfbt = fbt;
304248457Sjhibbits	fbt->fbtp_patchpoint = instr;
305248457Sjhibbits	fbt->fbtp_ctl = lf;
306248457Sjhibbits	fbt->fbtp_loadcnt = lf->loadcnt;
307248457Sjhibbits	fbt->fbtp_symindx = symindx;
308248457Sjhibbits
309248457Sjhibbits	if (*instr == FBT_BCTR)
310248457Sjhibbits		fbt->fbtp_rval = DTRACE_INVOP_BCTR;
311248457Sjhibbits	else if (*instr == FBT_BLR)
312248457Sjhibbits		fbt->fbtp_rval = DTRACE_INVOP_RET;
313248457Sjhibbits	else
314248457Sjhibbits		fbt->fbtp_rval = DTRACE_INVOP_JUMP;
315248457Sjhibbits
316248457Sjhibbits	fbt->fbtp_savedval = *instr;
317248457Sjhibbits	fbt->fbtp_patchval = FBT_PATCHVAL;
318248457Sjhibbits	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
319248457Sjhibbits	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
320248457Sjhibbits
321248457Sjhibbits	lf->fbt_nentries++;
322248457Sjhibbits
323255099Sjhibbits	instr += 4;
324248457Sjhibbits	goto again;
325248457Sjhibbits}
326248457Sjhibbits
327248457Sjhibbitsstatic void
328248457Sjhibbitsfbt_provide_module(void *arg, modctl_t *lf)
329248457Sjhibbits{
330248457Sjhibbits	char modname[MAXPATHLEN];
331248457Sjhibbits	int i;
332248457Sjhibbits	size_t len;
333248457Sjhibbits
334248457Sjhibbits	strlcpy(modname, lf->filename, sizeof(modname));
335248457Sjhibbits	len = strlen(modname);
336248457Sjhibbits	if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
337248457Sjhibbits		modname[len - 3] = '\0';
338248457Sjhibbits
339248457Sjhibbits	/*
340248457Sjhibbits	 * Employees of dtrace and their families are ineligible.  Void
341248457Sjhibbits	 * where prohibited.
342248457Sjhibbits	 */
343248457Sjhibbits	if (strcmp(modname, "dtrace") == 0)
344248457Sjhibbits		return;
345248457Sjhibbits
346248457Sjhibbits	/*
347248457Sjhibbits	 * The cyclic timer subsystem can be built as a module and DTrace
348248457Sjhibbits	 * depends on that, so it is ineligible too.
349248457Sjhibbits	 */
350248457Sjhibbits	if (strcmp(modname, "cyclic") == 0)
351248457Sjhibbits		return;
352248457Sjhibbits
353248457Sjhibbits	/*
354248457Sjhibbits	 * To register with DTrace, a module must list 'dtrace' as a
355248457Sjhibbits	 * dependency in order for the kernel linker to resolve
356248457Sjhibbits	 * symbols like dtrace_register(). All modules with such a
357248457Sjhibbits	 * dependency are ineligible for FBT tracing.
358248457Sjhibbits	 */
359248457Sjhibbits	for (i = 0; i < lf->ndeps; i++)
360248457Sjhibbits		if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
361248457Sjhibbits			return;
362248457Sjhibbits
363248457Sjhibbits	if (lf->fbt_nentries) {
364248457Sjhibbits		/*
365248457Sjhibbits		 * This module has some FBT entries allocated; we're afraid
366248457Sjhibbits		 * to screw with it.
367248457Sjhibbits		 */
368248457Sjhibbits		return;
369248457Sjhibbits	}
370248457Sjhibbits
371248457Sjhibbits	/*
372248457Sjhibbits	 * List the functions in the module and the symbol values.
373248457Sjhibbits	 */
374248457Sjhibbits	(void) linker_file_function_listall(lf, fbt_provide_module_function, modname);
375248457Sjhibbits}
376248457Sjhibbits
377248457Sjhibbitsstatic void
378248457Sjhibbitsfbt_destroy(void *arg, dtrace_id_t id, void *parg)
379248457Sjhibbits{
380248457Sjhibbits	fbt_probe_t *fbt = parg, *next, *hash, *last;
381248457Sjhibbits	modctl_t *ctl;
382248457Sjhibbits	int ndx;
383248457Sjhibbits
384248457Sjhibbits	do {
385248457Sjhibbits		ctl = fbt->fbtp_ctl;
386248457Sjhibbits
387248457Sjhibbits		ctl->fbt_nentries--;
388248457Sjhibbits
389248457Sjhibbits		/*
390248457Sjhibbits		 * Now we need to remove this probe from the fbt_probetab.
391248457Sjhibbits		 */
392248457Sjhibbits		ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
393248457Sjhibbits		last = NULL;
394248457Sjhibbits		hash = fbt_probetab[ndx];
395248457Sjhibbits
396248457Sjhibbits		while (hash != fbt) {
397248457Sjhibbits			ASSERT(hash != NULL);
398248457Sjhibbits			last = hash;
399248457Sjhibbits			hash = hash->fbtp_hashnext;
400248457Sjhibbits		}
401248457Sjhibbits
402248457Sjhibbits		if (last != NULL) {
403248457Sjhibbits			last->fbtp_hashnext = fbt->fbtp_hashnext;
404248457Sjhibbits		} else {
405248457Sjhibbits			fbt_probetab[ndx] = fbt->fbtp_hashnext;
406248457Sjhibbits		}
407248457Sjhibbits
408248457Sjhibbits		next = fbt->fbtp_next;
409248457Sjhibbits		free(fbt, M_FBT);
410248457Sjhibbits
411248457Sjhibbits		fbt = next;
412248457Sjhibbits	} while (fbt != NULL);
413248457Sjhibbits}
414248457Sjhibbits
415248457Sjhibbitsstatic void
416248457Sjhibbitsfbt_enable(void *arg, dtrace_id_t id, void *parg)
417248457Sjhibbits{
418248457Sjhibbits	fbt_probe_t *fbt = parg;
419248457Sjhibbits	modctl_t *ctl = fbt->fbtp_ctl;
420248457Sjhibbits
421248457Sjhibbits	ctl->nenabled++;
422248457Sjhibbits
423248457Sjhibbits	/*
424248457Sjhibbits	 * Now check that our modctl has the expected load count.  If it
425248457Sjhibbits	 * doesn't, this module must have been unloaded and reloaded -- and
426248457Sjhibbits	 * we're not going to touch it.
427248457Sjhibbits	 */
428248457Sjhibbits	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
429248457Sjhibbits		if (fbt_verbose) {
430248457Sjhibbits			printf("fbt is failing for probe %s "
431248457Sjhibbits			    "(module %s reloaded)",
432248457Sjhibbits			    fbt->fbtp_name, ctl->filename);
433248457Sjhibbits		}
434248457Sjhibbits
435248457Sjhibbits		return;
436248457Sjhibbits	}
437248457Sjhibbits
438248457Sjhibbits	for (; fbt != NULL; fbt = fbt->fbtp_next) {
439248457Sjhibbits		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
440255099Sjhibbits		__syncicache(fbt->fbtp_patchpoint, 4);
441248457Sjhibbits	}
442248457Sjhibbits}
443248457Sjhibbits
444248457Sjhibbitsstatic void
445248457Sjhibbitsfbt_disable(void *arg, dtrace_id_t id, void *parg)
446248457Sjhibbits{
447248457Sjhibbits	fbt_probe_t *fbt = parg;
448248457Sjhibbits	modctl_t *ctl = fbt->fbtp_ctl;
449248457Sjhibbits
450248457Sjhibbits	ASSERT(ctl->nenabled > 0);
451248457Sjhibbits	ctl->nenabled--;
452248457Sjhibbits
453248457Sjhibbits	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
454248457Sjhibbits		return;
455248457Sjhibbits
456255099Sjhibbits	for (; fbt != NULL; fbt = fbt->fbtp_next) {
457248457Sjhibbits		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
458255099Sjhibbits		__syncicache(fbt->fbtp_patchpoint, 4);
459255099Sjhibbits	}
460248457Sjhibbits}
461248457Sjhibbits
462248457Sjhibbitsstatic void
463248457Sjhibbitsfbt_suspend(void *arg, dtrace_id_t id, void *parg)
464248457Sjhibbits{
465248457Sjhibbits	fbt_probe_t *fbt = parg;
466248457Sjhibbits	modctl_t *ctl = fbt->fbtp_ctl;
467248457Sjhibbits
468248457Sjhibbits	ASSERT(ctl->nenabled > 0);
469248457Sjhibbits
470248457Sjhibbits	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
471248457Sjhibbits		return;
472248457Sjhibbits
473255099Sjhibbits	for (; fbt != NULL; fbt = fbt->fbtp_next) {
474248457Sjhibbits		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
475255099Sjhibbits		__syncicache(fbt->fbtp_patchpoint, 4);
476255099Sjhibbits	}
477248457Sjhibbits}
478248457Sjhibbits
479248457Sjhibbitsstatic void
480248457Sjhibbitsfbt_resume(void *arg, dtrace_id_t id, void *parg)
481248457Sjhibbits{
482248457Sjhibbits	fbt_probe_t *fbt = parg;
483248457Sjhibbits	modctl_t *ctl = fbt->fbtp_ctl;
484248457Sjhibbits
485248457Sjhibbits	ASSERT(ctl->nenabled > 0);
486248457Sjhibbits
487248457Sjhibbits	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
488248457Sjhibbits		return;
489248457Sjhibbits
490255099Sjhibbits	for (; fbt != NULL; fbt = fbt->fbtp_next) {
491248457Sjhibbits		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
492255099Sjhibbits		__syncicache(fbt->fbtp_patchpoint, 4);
493255099Sjhibbits	}
494248457Sjhibbits}
495248457Sjhibbits
496248457Sjhibbitsstatic int
497248457Sjhibbitsfbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
498248457Sjhibbits{
499248457Sjhibbits	const Elf_Sym *symp = lc->symtab;;
500248457Sjhibbits	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
501248457Sjhibbits	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
502248457Sjhibbits	int i;
503248457Sjhibbits	uint32_t *ctfoff;
504248457Sjhibbits	uint32_t objtoff = hp->cth_objtoff;
505248457Sjhibbits	uint32_t funcoff = hp->cth_funcoff;
506248457Sjhibbits	ushort_t info;
507248457Sjhibbits	ushort_t vlen;
508248457Sjhibbits
509248457Sjhibbits	/* Sanity check. */
510248457Sjhibbits	if (hp->cth_magic != CTF_MAGIC) {
511248457Sjhibbits		printf("Bad magic value in CTF data of '%s'\n",lf->pathname);
512248457Sjhibbits		return (EINVAL);
513248457Sjhibbits	}
514248457Sjhibbits
515248457Sjhibbits	if (lc->symtab == NULL) {
516248457Sjhibbits		printf("No symbol table in '%s'\n",lf->pathname);
517248457Sjhibbits		return (EINVAL);
518248457Sjhibbits	}
519248457Sjhibbits
520248457Sjhibbits	if ((ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK)) == NULL)
521248457Sjhibbits		return (ENOMEM);
522248457Sjhibbits
523248457Sjhibbits	*lc->ctfoffp = ctfoff;
524248457Sjhibbits
525248457Sjhibbits	for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) {
526248457Sjhibbits		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
527248457Sjhibbits			*ctfoff = 0xffffffff;
528248457Sjhibbits			continue;
529248457Sjhibbits		}
530248457Sjhibbits
531248457Sjhibbits		switch (ELF_ST_TYPE(symp->st_info)) {
532248457Sjhibbits		case STT_OBJECT:
533248457Sjhibbits			if (objtoff >= hp->cth_funcoff ||
534248457Sjhibbits                            (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
535248457Sjhibbits				*ctfoff = 0xffffffff;
536248457Sjhibbits                                break;
537248457Sjhibbits                        }
538248457Sjhibbits
539248457Sjhibbits                        *ctfoff = objtoff;
540248457Sjhibbits                        objtoff += sizeof (ushort_t);
541248457Sjhibbits			break;
542248457Sjhibbits
543248457Sjhibbits		case STT_FUNC:
544248457Sjhibbits			if (funcoff >= hp->cth_typeoff) {
545248457Sjhibbits				*ctfoff = 0xffffffff;
546248457Sjhibbits				break;
547248457Sjhibbits			}
548248457Sjhibbits
549248457Sjhibbits			*ctfoff = funcoff;
550248457Sjhibbits
551248457Sjhibbits			info = *((const ushort_t *)(ctfdata + funcoff));
552248457Sjhibbits			vlen = CTF_INFO_VLEN(info);
553248457Sjhibbits
554248457Sjhibbits			/*
555248457Sjhibbits			 * If we encounter a zero pad at the end, just skip it.
556248457Sjhibbits			 * Otherwise skip over the function and its return type
557248457Sjhibbits			 * (+2) and the argument list (vlen).
558248457Sjhibbits			 */
559248457Sjhibbits			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
560248457Sjhibbits				funcoff += sizeof (ushort_t); /* skip pad */
561248457Sjhibbits			else
562248457Sjhibbits				funcoff += sizeof (ushort_t) * (vlen + 2);
563248457Sjhibbits			break;
564248457Sjhibbits
565248457Sjhibbits		default:
566248457Sjhibbits			*ctfoff = 0xffffffff;
567248457Sjhibbits			break;
568248457Sjhibbits		}
569248457Sjhibbits	}
570248457Sjhibbits
571248457Sjhibbits	return (0);
572248457Sjhibbits}
573248457Sjhibbits
574248457Sjhibbitsstatic ssize_t
575248457Sjhibbitsfbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
576248457Sjhibbits    ssize_t *incrementp)
577248457Sjhibbits{
578248457Sjhibbits	ssize_t size, increment;
579248457Sjhibbits
580248457Sjhibbits	if (version > CTF_VERSION_1 &&
581248457Sjhibbits	    tp->ctt_size == CTF_LSIZE_SENT) {
582248457Sjhibbits		size = CTF_TYPE_LSIZE(tp);
583248457Sjhibbits		increment = sizeof (ctf_type_t);
584248457Sjhibbits	} else {
585248457Sjhibbits		size = tp->ctt_size;
586248457Sjhibbits		increment = sizeof (ctf_stype_t);
587248457Sjhibbits	}
588248457Sjhibbits
589248457Sjhibbits	if (sizep)
590248457Sjhibbits		*sizep = size;
591248457Sjhibbits	if (incrementp)
592248457Sjhibbits		*incrementp = increment;
593248457Sjhibbits
594248457Sjhibbits	return (size);
595248457Sjhibbits}
596248457Sjhibbits
597248457Sjhibbitsstatic int
598248457Sjhibbitsfbt_typoff_init(linker_ctf_t *lc)
599248457Sjhibbits{
600248457Sjhibbits	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
601248457Sjhibbits	const ctf_type_t *tbuf;
602248457Sjhibbits	const ctf_type_t *tend;
603248457Sjhibbits	const ctf_type_t *tp;
604248457Sjhibbits	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
605248457Sjhibbits	int ctf_typemax = 0;
606248457Sjhibbits	uint32_t *xp;
607248457Sjhibbits	ulong_t pop[CTF_K_MAX + 1] = { 0 };
608248457Sjhibbits
609248457Sjhibbits
610248457Sjhibbits	/* Sanity check. */
611248457Sjhibbits	if (hp->cth_magic != CTF_MAGIC)
612248457Sjhibbits		return (EINVAL);
613248457Sjhibbits
614248457Sjhibbits	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
615248457Sjhibbits	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
616248457Sjhibbits
617248457Sjhibbits	int child = hp->cth_parname != 0;
618248457Sjhibbits
619248457Sjhibbits	/*
620248457Sjhibbits	 * We make two passes through the entire type section.  In this first
621248457Sjhibbits	 * pass, we count the number of each type and the total number of types.
622248457Sjhibbits	 */
623248457Sjhibbits	for (tp = tbuf; tp < tend; ctf_typemax++) {
624248457Sjhibbits		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
625248457Sjhibbits		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
626248457Sjhibbits		ssize_t size, increment;
627248457Sjhibbits
628248457Sjhibbits		size_t vbytes;
629248457Sjhibbits		uint_t n;
630248457Sjhibbits
631248457Sjhibbits		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
632248457Sjhibbits
633248457Sjhibbits		switch (kind) {
634248457Sjhibbits		case CTF_K_INTEGER:
635248457Sjhibbits		case CTF_K_FLOAT:
636248457Sjhibbits			vbytes = sizeof (uint_t);
637248457Sjhibbits			break;
638248457Sjhibbits		case CTF_K_ARRAY:
639248457Sjhibbits			vbytes = sizeof (ctf_array_t);
640248457Sjhibbits			break;
641248457Sjhibbits		case CTF_K_FUNCTION:
642248457Sjhibbits			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
643248457Sjhibbits			break;
644248457Sjhibbits		case CTF_K_STRUCT:
645248457Sjhibbits		case CTF_K_UNION:
646248457Sjhibbits			if (size < CTF_LSTRUCT_THRESH) {
647248457Sjhibbits				ctf_member_t *mp = (ctf_member_t *)
648248457Sjhibbits				    ((uintptr_t)tp + increment);
649248457Sjhibbits
650248457Sjhibbits				vbytes = sizeof (ctf_member_t) * vlen;
651248457Sjhibbits				for (n = vlen; n != 0; n--, mp++)
652248457Sjhibbits					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
653248457Sjhibbits			} else {
654248457Sjhibbits				ctf_lmember_t *lmp = (ctf_lmember_t *)
655248457Sjhibbits				    ((uintptr_t)tp + increment);
656248457Sjhibbits
657248457Sjhibbits				vbytes = sizeof (ctf_lmember_t) * vlen;
658248457Sjhibbits				for (n = vlen; n != 0; n--, lmp++)
659248457Sjhibbits					child |=
660248457Sjhibbits					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
661248457Sjhibbits			}
662248457Sjhibbits			break;
663248457Sjhibbits		case CTF_K_ENUM:
664248457Sjhibbits			vbytes = sizeof (ctf_enum_t) * vlen;
665248457Sjhibbits			break;
666248457Sjhibbits		case CTF_K_FORWARD:
667248457Sjhibbits			/*
668248457Sjhibbits			 * For forward declarations, ctt_type is the CTF_K_*
669248457Sjhibbits			 * kind for the tag, so bump that population count too.
670248457Sjhibbits			 * If ctt_type is unknown, treat the tag as a struct.
671248457Sjhibbits			 */
672248457Sjhibbits			if (tp->ctt_type == CTF_K_UNKNOWN ||
673248457Sjhibbits			    tp->ctt_type >= CTF_K_MAX)
674248457Sjhibbits				pop[CTF_K_STRUCT]++;
675248457Sjhibbits			else
676248457Sjhibbits				pop[tp->ctt_type]++;
677248457Sjhibbits			/*FALLTHRU*/
678248457Sjhibbits		case CTF_K_UNKNOWN:
679248457Sjhibbits			vbytes = 0;
680248457Sjhibbits			break;
681248457Sjhibbits		case CTF_K_POINTER:
682248457Sjhibbits		case CTF_K_TYPEDEF:
683248457Sjhibbits		case CTF_K_VOLATILE:
684248457Sjhibbits		case CTF_K_CONST:
685248457Sjhibbits		case CTF_K_RESTRICT:
686248457Sjhibbits			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
687248457Sjhibbits			vbytes = 0;
688248457Sjhibbits			break;
689248457Sjhibbits		default:
690248457Sjhibbits			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
691248457Sjhibbits			return (EIO);
692248457Sjhibbits		}
693248457Sjhibbits		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
694248457Sjhibbits		pop[kind]++;
695248457Sjhibbits	}
696248457Sjhibbits
697255099Sjhibbits	/* account for a sentinel value below */
698255099Sjhibbits	ctf_typemax++;
699248457Sjhibbits	*lc->typlenp = ctf_typemax;
700248457Sjhibbits
701248457Sjhibbits	if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_LINKER, M_ZERO | M_WAITOK)) == NULL)
702248457Sjhibbits		return (ENOMEM);
703248457Sjhibbits
704248457Sjhibbits	*lc->typoffp = xp;
705248457Sjhibbits
706248457Sjhibbits	/* type id 0 is used as a sentinel value */
707248457Sjhibbits	*xp++ = 0;
708248457Sjhibbits
709248457Sjhibbits	/*
710248457Sjhibbits	 * In the second pass, fill in the type offset.
711248457Sjhibbits	 */
712248457Sjhibbits	for (tp = tbuf; tp < tend; xp++) {
713248457Sjhibbits		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
714248457Sjhibbits		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
715248457Sjhibbits		ssize_t size, increment;
716248457Sjhibbits
717248457Sjhibbits		size_t vbytes;
718248457Sjhibbits		uint_t n;
719248457Sjhibbits
720248457Sjhibbits		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
721248457Sjhibbits
722248457Sjhibbits		switch (kind) {
723248457Sjhibbits		case CTF_K_INTEGER:
724248457Sjhibbits		case CTF_K_FLOAT:
725248457Sjhibbits			vbytes = sizeof (uint_t);
726248457Sjhibbits			break;
727248457Sjhibbits		case CTF_K_ARRAY:
728248457Sjhibbits			vbytes = sizeof (ctf_array_t);
729248457Sjhibbits			break;
730248457Sjhibbits		case CTF_K_FUNCTION:
731248457Sjhibbits			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
732248457Sjhibbits			break;
733248457Sjhibbits		case CTF_K_STRUCT:
734248457Sjhibbits		case CTF_K_UNION:
735248457Sjhibbits			if (size < CTF_LSTRUCT_THRESH) {
736248457Sjhibbits				ctf_member_t *mp = (ctf_member_t *)
737248457Sjhibbits				    ((uintptr_t)tp + increment);
738248457Sjhibbits
739248457Sjhibbits				vbytes = sizeof (ctf_member_t) * vlen;
740248457Sjhibbits				for (n = vlen; n != 0; n--, mp++)
741248457Sjhibbits					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
742248457Sjhibbits			} else {
743248457Sjhibbits				ctf_lmember_t *lmp = (ctf_lmember_t *)
744248457Sjhibbits				    ((uintptr_t)tp + increment);
745248457Sjhibbits
746248457Sjhibbits				vbytes = sizeof (ctf_lmember_t) * vlen;
747248457Sjhibbits				for (n = vlen; n != 0; n--, lmp++)
748248457Sjhibbits					child |=
749248457Sjhibbits					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
750248457Sjhibbits			}
751248457Sjhibbits			break;
752248457Sjhibbits		case CTF_K_ENUM:
753248457Sjhibbits			vbytes = sizeof (ctf_enum_t) * vlen;
754248457Sjhibbits			break;
755248457Sjhibbits		case CTF_K_FORWARD:
756248457Sjhibbits		case CTF_K_UNKNOWN:
757248457Sjhibbits			vbytes = 0;
758248457Sjhibbits			break;
759248457Sjhibbits		case CTF_K_POINTER:
760248457Sjhibbits		case CTF_K_TYPEDEF:
761248457Sjhibbits		case CTF_K_VOLATILE:
762248457Sjhibbits		case CTF_K_CONST:
763248457Sjhibbits		case CTF_K_RESTRICT:
764248457Sjhibbits			vbytes = 0;
765248457Sjhibbits			break;
766248457Sjhibbits		default:
767248457Sjhibbits			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
768248457Sjhibbits			return (EIO);
769248457Sjhibbits		}
770248457Sjhibbits		*xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
771248457Sjhibbits		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
772248457Sjhibbits	}
773248457Sjhibbits
774248457Sjhibbits	return (0);
775248457Sjhibbits}
776248457Sjhibbits
777248457Sjhibbits/*
778248457Sjhibbits * CTF Declaration Stack
779248457Sjhibbits *
780248457Sjhibbits * In order to implement ctf_type_name(), we must convert a type graph back
781248457Sjhibbits * into a C type declaration.  Unfortunately, a type graph represents a storage
782248457Sjhibbits * class ordering of the type whereas a type declaration must obey the C rules
783248457Sjhibbits * for operator precedence, and the two orderings are frequently in conflict.
784248457Sjhibbits * For example, consider these CTF type graphs and their C declarations:
785248457Sjhibbits *
786248457Sjhibbits * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
787248457Sjhibbits * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
788248457Sjhibbits *
789248457Sjhibbits * In each case, parentheses are used to raise operator * to higher lexical
790248457Sjhibbits * precedence, so the string form of the C declaration cannot be constructed by
791248457Sjhibbits * walking the type graph links and forming the string from left to right.
792248457Sjhibbits *
793248457Sjhibbits * The functions in this file build a set of stacks from the type graph nodes
794248457Sjhibbits * corresponding to the C operator precedence levels in the appropriate order.
795248457Sjhibbits * The code in ctf_type_name() can then iterate over the levels and nodes in
796248457Sjhibbits * lexical precedence order and construct the final C declaration string.
797248457Sjhibbits */
798248457Sjhibbitstypedef struct ctf_list {
799248457Sjhibbits	struct ctf_list *l_prev; /* previous pointer or tail pointer */
800248457Sjhibbits	struct ctf_list *l_next; /* next pointer or head pointer */
801248457Sjhibbits} ctf_list_t;
802248457Sjhibbits
803248457Sjhibbits#define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
804248457Sjhibbits#define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
805248457Sjhibbits
806248457Sjhibbitstypedef enum {
807248457Sjhibbits	CTF_PREC_BASE,
808248457Sjhibbits	CTF_PREC_POINTER,
809248457Sjhibbits	CTF_PREC_ARRAY,
810248457Sjhibbits	CTF_PREC_FUNCTION,
811248457Sjhibbits	CTF_PREC_MAX
812248457Sjhibbits} ctf_decl_prec_t;
813248457Sjhibbits
814248457Sjhibbitstypedef struct ctf_decl_node {
815248457Sjhibbits	ctf_list_t cd_list;			/* linked list pointers */
816248457Sjhibbits	ctf_id_t cd_type;			/* type identifier */
817248457Sjhibbits	uint_t cd_kind;				/* type kind */
818248457Sjhibbits	uint_t cd_n;				/* type dimension if array */
819248457Sjhibbits} ctf_decl_node_t;
820248457Sjhibbits
821248457Sjhibbitstypedef struct ctf_decl {
822248457Sjhibbits	ctf_list_t cd_nodes[CTF_PREC_MAX];	/* declaration node stacks */
823248457Sjhibbits	int cd_order[CTF_PREC_MAX];		/* storage order of decls */
824248457Sjhibbits	ctf_decl_prec_t cd_qualp;		/* qualifier precision */
825248457Sjhibbits	ctf_decl_prec_t cd_ordp;		/* ordered precision */
826248457Sjhibbits	char *cd_buf;				/* buffer for output */
827248457Sjhibbits	char *cd_ptr;				/* buffer location */
828248457Sjhibbits	char *cd_end;				/* buffer limit */
829248457Sjhibbits	size_t cd_len;				/* buffer space required */
830248457Sjhibbits	int cd_err;				/* saved error value */
831248457Sjhibbits} ctf_decl_t;
832248457Sjhibbits
833248457Sjhibbits/*
834248457Sjhibbits * Simple doubly-linked list append routine.  This implementation assumes that
835248457Sjhibbits * each list element contains an embedded ctf_list_t as the first member.
836248457Sjhibbits * An additional ctf_list_t is used to store the head (l_next) and tail
837248457Sjhibbits * (l_prev) pointers.  The current head and tail list elements have their
838248457Sjhibbits * previous and next pointers set to NULL, respectively.
839248457Sjhibbits */
840248457Sjhibbitsstatic void
841248457Sjhibbitsctf_list_append(ctf_list_t *lp, void *new)
842248457Sjhibbits{
843248457Sjhibbits	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
844248457Sjhibbits	ctf_list_t *q = new;		/* q = new list element */
845248457Sjhibbits
846248457Sjhibbits	lp->l_prev = q;
847248457Sjhibbits	q->l_prev = p;
848248457Sjhibbits	q->l_next = NULL;
849248457Sjhibbits
850248457Sjhibbits	if (p != NULL)
851248457Sjhibbits		p->l_next = q;
852248457Sjhibbits	else
853248457Sjhibbits		lp->l_next = q;
854248457Sjhibbits}
855248457Sjhibbits
856248457Sjhibbits/*
857248457Sjhibbits * Prepend the specified existing element to the given ctf_list_t.  The
858248457Sjhibbits * existing pointer should be pointing at a struct with embedded ctf_list_t.
859248457Sjhibbits */
860248457Sjhibbitsstatic void
861248457Sjhibbitsctf_list_prepend(ctf_list_t *lp, void *new)
862248457Sjhibbits{
863248457Sjhibbits	ctf_list_t *p = new;		/* p = new list element */
864248457Sjhibbits	ctf_list_t *q = lp->l_next;	/* q = head list element */
865248457Sjhibbits
866248457Sjhibbits	lp->l_next = p;
867248457Sjhibbits	p->l_prev = NULL;
868248457Sjhibbits	p->l_next = q;
869248457Sjhibbits
870248457Sjhibbits	if (q != NULL)
871248457Sjhibbits		q->l_prev = p;
872248457Sjhibbits	else
873248457Sjhibbits		lp->l_prev = p;
874248457Sjhibbits}
875248457Sjhibbits
876248457Sjhibbitsstatic void
877248457Sjhibbitsctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
878248457Sjhibbits{
879248457Sjhibbits	int i;
880248457Sjhibbits
881248457Sjhibbits	bzero(cd, sizeof (ctf_decl_t));
882248457Sjhibbits
883248457Sjhibbits	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
884248457Sjhibbits		cd->cd_order[i] = CTF_PREC_BASE - 1;
885248457Sjhibbits
886248457Sjhibbits	cd->cd_qualp = CTF_PREC_BASE;
887248457Sjhibbits	cd->cd_ordp = CTF_PREC_BASE;
888248457Sjhibbits
889248457Sjhibbits	cd->cd_buf = buf;
890248457Sjhibbits	cd->cd_ptr = buf;
891248457Sjhibbits	cd->cd_end = buf + len;
892248457Sjhibbits}
893248457Sjhibbits
894248457Sjhibbitsstatic void
895248457Sjhibbitsctf_decl_fini(ctf_decl_t *cd)
896248457Sjhibbits{
897248457Sjhibbits	ctf_decl_node_t *cdp, *ndp;
898248457Sjhibbits	int i;
899248457Sjhibbits
900248457Sjhibbits	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
901248457Sjhibbits		for (cdp = ctf_list_next(&cd->cd_nodes[i]);
902248457Sjhibbits		    cdp != NULL; cdp = ndp) {
903248457Sjhibbits			ndp = ctf_list_next(cdp);
904248457Sjhibbits			free(cdp, M_FBT);
905248457Sjhibbits		}
906248457Sjhibbits	}
907248457Sjhibbits}
908248457Sjhibbits
909248457Sjhibbitsstatic const ctf_type_t *
910248457Sjhibbitsctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type)
911248457Sjhibbits{
912248457Sjhibbits	const ctf_type_t *tp;
913248457Sjhibbits	uint32_t offset;
914248457Sjhibbits	uint32_t *typoff = *lc->typoffp;
915248457Sjhibbits
916248457Sjhibbits	if (type >= *lc->typlenp) {
917248457Sjhibbits		printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,*lc->typlenp);
918248457Sjhibbits		return(NULL);
919248457Sjhibbits	}
920248457Sjhibbits
921248457Sjhibbits	/* Check if the type isn't cross-referenced. */
922248457Sjhibbits	if ((offset = typoff[type]) == 0) {
923248457Sjhibbits		printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
924248457Sjhibbits		return(NULL);
925248457Sjhibbits	}
926248457Sjhibbits
927248457Sjhibbits	tp = (const ctf_type_t *)(lc->ctftab + offset + sizeof(ctf_header_t));
928248457Sjhibbits
929248457Sjhibbits	return (tp);
930248457Sjhibbits}
931248457Sjhibbits
932248457Sjhibbitsstatic void
933248457Sjhibbitsfbt_array_info(linker_ctf_t *lc, ctf_id_t type, ctf_arinfo_t *arp)
934248457Sjhibbits{
935248457Sjhibbits	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
936248457Sjhibbits	const ctf_type_t *tp;
937248457Sjhibbits	const ctf_array_t *ap;
938248457Sjhibbits	ssize_t increment;
939248457Sjhibbits
940248457Sjhibbits	bzero(arp, sizeof(*arp));
941248457Sjhibbits
942248457Sjhibbits	if ((tp = ctf_lookup_by_id(lc, type)) == NULL)
943248457Sjhibbits		return;
944248457Sjhibbits
945248457Sjhibbits	if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
946248457Sjhibbits		return;
947248457Sjhibbits
948248457Sjhibbits	(void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
949248457Sjhibbits
950248457Sjhibbits	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
951248457Sjhibbits	arp->ctr_contents = ap->cta_contents;
952248457Sjhibbits	arp->ctr_index = ap->cta_index;
953248457Sjhibbits	arp->ctr_nelems = ap->cta_nelems;
954248457Sjhibbits}
955248457Sjhibbits
956248457Sjhibbitsstatic const char *
957248457Sjhibbitsctf_strptr(linker_ctf_t *lc, int name)
958248457Sjhibbits{
959248457Sjhibbits	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;;
960248457Sjhibbits	const char *strp = "";
961248457Sjhibbits
962248457Sjhibbits	if (name < 0 || name >= hp->cth_strlen)
963248457Sjhibbits		return(strp);
964248457Sjhibbits
965248457Sjhibbits	strp = (const char *)(lc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
966248457Sjhibbits
967248457Sjhibbits	return (strp);
968248457Sjhibbits}
969248457Sjhibbits
970248457Sjhibbitsstatic void
971248457Sjhibbitsctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
972248457Sjhibbits{
973248457Sjhibbits	ctf_decl_node_t *cdp;
974248457Sjhibbits	ctf_decl_prec_t prec;
975248457Sjhibbits	uint_t kind, n = 1;
976248457Sjhibbits	int is_qual = 0;
977248457Sjhibbits
978248457Sjhibbits	const ctf_type_t *tp;
979248457Sjhibbits	ctf_arinfo_t ar;
980248457Sjhibbits
981248457Sjhibbits	if ((tp = ctf_lookup_by_id(lc, type)) == NULL) {
982248457Sjhibbits		cd->cd_err = ENOENT;
983248457Sjhibbits		return;
984248457Sjhibbits	}
985248457Sjhibbits
986248457Sjhibbits	switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
987248457Sjhibbits	case CTF_K_ARRAY:
988248457Sjhibbits		fbt_array_info(lc, type, &ar);
989248457Sjhibbits		ctf_decl_push(cd, lc, ar.ctr_contents);
990248457Sjhibbits		n = ar.ctr_nelems;
991248457Sjhibbits		prec = CTF_PREC_ARRAY;
992248457Sjhibbits		break;
993248457Sjhibbits
994248457Sjhibbits	case CTF_K_TYPEDEF:
995248457Sjhibbits		if (ctf_strptr(lc, tp->ctt_name)[0] == '\0') {
996248457Sjhibbits			ctf_decl_push(cd, lc, tp->ctt_type);
997248457Sjhibbits			return;
998248457Sjhibbits		}
999248457Sjhibbits		prec = CTF_PREC_BASE;
1000248457Sjhibbits		break;
1001248457Sjhibbits
1002248457Sjhibbits	case CTF_K_FUNCTION:
1003248457Sjhibbits		ctf_decl_push(cd, lc, tp->ctt_type);
1004248457Sjhibbits		prec = CTF_PREC_FUNCTION;
1005248457Sjhibbits		break;
1006248457Sjhibbits
1007248457Sjhibbits	case CTF_K_POINTER:
1008248457Sjhibbits		ctf_decl_push(cd, lc, tp->ctt_type);
1009248457Sjhibbits		prec = CTF_PREC_POINTER;
1010248457Sjhibbits		break;
1011248457Sjhibbits
1012248457Sjhibbits	case CTF_K_VOLATILE:
1013248457Sjhibbits	case CTF_K_CONST:
1014248457Sjhibbits	case CTF_K_RESTRICT:
1015248457Sjhibbits		ctf_decl_push(cd, lc, tp->ctt_type);
1016248457Sjhibbits		prec = cd->cd_qualp;
1017248457Sjhibbits		is_qual++;
1018248457Sjhibbits		break;
1019248457Sjhibbits
1020248457Sjhibbits	default:
1021248457Sjhibbits		prec = CTF_PREC_BASE;
1022248457Sjhibbits	}
1023248457Sjhibbits
1024248457Sjhibbits	if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) {
1025248457Sjhibbits		cd->cd_err = EAGAIN;
1026248457Sjhibbits		return;
1027248457Sjhibbits	}
1028248457Sjhibbits
1029248457Sjhibbits	cdp->cd_type = type;
1030248457Sjhibbits	cdp->cd_kind = kind;
1031248457Sjhibbits	cdp->cd_n = n;
1032248457Sjhibbits
1033248457Sjhibbits	if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
1034248457Sjhibbits		cd->cd_order[prec] = cd->cd_ordp++;
1035248457Sjhibbits
1036248457Sjhibbits	/*
1037248457Sjhibbits	 * Reset cd_qualp to the highest precedence level that we've seen so
1038248457Sjhibbits	 * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
1039248457Sjhibbits	 */
1040248457Sjhibbits	if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
1041248457Sjhibbits		cd->cd_qualp = prec;
1042248457Sjhibbits
1043248457Sjhibbits	/*
1044248457Sjhibbits	 * C array declarators are ordered inside out so prepend them.  Also by
1045248457Sjhibbits	 * convention qualifiers of base types precede the type specifier (e.g.
1046248457Sjhibbits	 * const int vs. int const) even though the two forms are equivalent.
1047248457Sjhibbits	 */
1048248457Sjhibbits	if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
1049248457Sjhibbits		ctf_list_prepend(&cd->cd_nodes[prec], cdp);
1050248457Sjhibbits	else
1051248457Sjhibbits		ctf_list_append(&cd->cd_nodes[prec], cdp);
1052248457Sjhibbits}
1053248457Sjhibbits
1054248457Sjhibbitsstatic void
1055248457Sjhibbitsctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
1056248457Sjhibbits{
1057248457Sjhibbits	size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
1058248457Sjhibbits	va_list ap;
1059248457Sjhibbits	size_t n;
1060248457Sjhibbits
1061248457Sjhibbits	va_start(ap, format);
1062248457Sjhibbits	n = vsnprintf(cd->cd_ptr, len, format, ap);
1063248457Sjhibbits	va_end(ap);
1064248457Sjhibbits
1065248457Sjhibbits	cd->cd_ptr += MIN(n, len);
1066248457Sjhibbits	cd->cd_len += n;
1067248457Sjhibbits}
1068248457Sjhibbits
1069248457Sjhibbitsstatic ssize_t
1070248457Sjhibbitsfbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len)
1071248457Sjhibbits{
1072248457Sjhibbits	ctf_decl_t cd;
1073248457Sjhibbits	ctf_decl_node_t *cdp;
1074248457Sjhibbits	ctf_decl_prec_t prec, lp, rp;
1075248457Sjhibbits	int ptr, arr;
1076248457Sjhibbits	uint_t k;
1077248457Sjhibbits
1078248457Sjhibbits	if (lc == NULL && type == CTF_ERR)
1079248457Sjhibbits		return (-1); /* simplify caller code by permitting CTF_ERR */
1080248457Sjhibbits
1081248457Sjhibbits	ctf_decl_init(&cd, buf, len);
1082248457Sjhibbits	ctf_decl_push(&cd, lc, type);
1083248457Sjhibbits
1084248457Sjhibbits	if (cd.cd_err != 0) {
1085248457Sjhibbits		ctf_decl_fini(&cd);
1086248457Sjhibbits		return (-1);
1087248457Sjhibbits	}
1088248457Sjhibbits
1089248457Sjhibbits	/*
1090248457Sjhibbits	 * If the type graph's order conflicts with lexical precedence order
1091248457Sjhibbits	 * for pointers or arrays, then we need to surround the declarations at
1092248457Sjhibbits	 * the corresponding lexical precedence with parentheses.  This can
1093248457Sjhibbits	 * result in either a parenthesized pointer (*) as in int (*)() or
1094248457Sjhibbits	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
1095248457Sjhibbits	 */
1096248457Sjhibbits	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
1097248457Sjhibbits	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
1098248457Sjhibbits
1099248457Sjhibbits	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
1100248457Sjhibbits	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
1101248457Sjhibbits
1102248457Sjhibbits	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
1103248457Sjhibbits
1104248457Sjhibbits	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
1105248457Sjhibbits		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
1106248457Sjhibbits		    cdp != NULL; cdp = ctf_list_next(cdp)) {
1107248457Sjhibbits
1108248457Sjhibbits			const ctf_type_t *tp =
1109248457Sjhibbits			    ctf_lookup_by_id(lc, cdp->cd_type);
1110248457Sjhibbits			const char *name = ctf_strptr(lc, tp->ctt_name);
1111248457Sjhibbits
1112248457Sjhibbits			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
1113248457Sjhibbits				ctf_decl_sprintf(&cd, " ");
1114248457Sjhibbits
1115248457Sjhibbits			if (lp == prec) {
1116248457Sjhibbits				ctf_decl_sprintf(&cd, "(");
1117248457Sjhibbits				lp = -1;
1118248457Sjhibbits			}
1119248457Sjhibbits
1120248457Sjhibbits			switch (cdp->cd_kind) {
1121248457Sjhibbits			case CTF_K_INTEGER:
1122248457Sjhibbits			case CTF_K_FLOAT:
1123248457Sjhibbits			case CTF_K_TYPEDEF:
1124248457Sjhibbits				ctf_decl_sprintf(&cd, "%s", name);
1125248457Sjhibbits				break;
1126248457Sjhibbits			case CTF_K_POINTER:
1127248457Sjhibbits				ctf_decl_sprintf(&cd, "*");
1128248457Sjhibbits				break;
1129248457Sjhibbits			case CTF_K_ARRAY:
1130248457Sjhibbits				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
1131248457Sjhibbits				break;
1132248457Sjhibbits			case CTF_K_FUNCTION:
1133248457Sjhibbits				ctf_decl_sprintf(&cd, "()");
1134248457Sjhibbits				break;
1135248457Sjhibbits			case CTF_K_STRUCT:
1136248457Sjhibbits			case CTF_K_FORWARD:
1137248457Sjhibbits				ctf_decl_sprintf(&cd, "struct %s", name);
1138248457Sjhibbits				break;
1139248457Sjhibbits			case CTF_K_UNION:
1140248457Sjhibbits				ctf_decl_sprintf(&cd, "union %s", name);
1141248457Sjhibbits				break;
1142248457Sjhibbits			case CTF_K_ENUM:
1143248457Sjhibbits				ctf_decl_sprintf(&cd, "enum %s", name);
1144248457Sjhibbits				break;
1145248457Sjhibbits			case CTF_K_VOLATILE:
1146248457Sjhibbits				ctf_decl_sprintf(&cd, "volatile");
1147248457Sjhibbits				break;
1148248457Sjhibbits			case CTF_K_CONST:
1149248457Sjhibbits				ctf_decl_sprintf(&cd, "const");
1150248457Sjhibbits				break;
1151248457Sjhibbits			case CTF_K_RESTRICT:
1152248457Sjhibbits				ctf_decl_sprintf(&cd, "restrict");
1153248457Sjhibbits				break;
1154248457Sjhibbits			}
1155248457Sjhibbits
1156248457Sjhibbits			k = cdp->cd_kind;
1157248457Sjhibbits		}
1158248457Sjhibbits
1159248457Sjhibbits		if (rp == prec)
1160248457Sjhibbits			ctf_decl_sprintf(&cd, ")");
1161248457Sjhibbits	}
1162248457Sjhibbits
1163248457Sjhibbits	ctf_decl_fini(&cd);
1164248457Sjhibbits	return (cd.cd_len);
1165248457Sjhibbits}
1166248457Sjhibbits
1167248457Sjhibbitsstatic void
1168248457Sjhibbitsfbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
1169248457Sjhibbits{
1170248457Sjhibbits	const ushort_t *dp;
1171248457Sjhibbits	fbt_probe_t *fbt = parg;
1172248457Sjhibbits	linker_ctf_t lc;
1173248457Sjhibbits	modctl_t *ctl = fbt->fbtp_ctl;
1174248457Sjhibbits	int ndx = desc->dtargd_ndx;
1175248457Sjhibbits	int symindx = fbt->fbtp_symindx;
1176248457Sjhibbits	uint32_t *ctfoff;
1177248457Sjhibbits	uint32_t offset;
1178248457Sjhibbits	ushort_t info, kind, n;
1179248457Sjhibbits
1180255099Sjhibbits	if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
1181255099Sjhibbits		(void) strcpy(desc->dtargd_native, "int");
1182255099Sjhibbits		return;
1183255099Sjhibbits	}
1184255099Sjhibbits
1185248457Sjhibbits	desc->dtargd_ndx = DTRACE_ARGNONE;
1186248457Sjhibbits
1187248457Sjhibbits	/* Get a pointer to the CTF data and it's length. */
1188248457Sjhibbits	if (linker_ctf_get(ctl, &lc) != 0)
1189248457Sjhibbits		/* No CTF data? Something wrong? *shrug* */
1190248457Sjhibbits		return;
1191248457Sjhibbits
1192248457Sjhibbits	/* Check if this module hasn't been initialised yet. */
1193248457Sjhibbits	if (*lc.ctfoffp == NULL) {
1194248457Sjhibbits		/*
1195248457Sjhibbits		 * Initialise the CTF object and function symindx to
1196248457Sjhibbits		 * byte offset array.
1197248457Sjhibbits		 */
1198248457Sjhibbits		if (fbt_ctfoff_init(ctl, &lc) != 0)
1199248457Sjhibbits			return;
1200248457Sjhibbits
1201248457Sjhibbits		/* Initialise the CTF type to byte offset array. */
1202248457Sjhibbits		if (fbt_typoff_init(&lc) != 0)
1203248457Sjhibbits			return;
1204248457Sjhibbits	}
1205248457Sjhibbits
1206248457Sjhibbits	ctfoff = *lc.ctfoffp;
1207248457Sjhibbits
1208248457Sjhibbits	if (ctfoff == NULL || *lc.typoffp == NULL)
1209248457Sjhibbits		return;
1210248457Sjhibbits
1211248457Sjhibbits	/* Check if the symbol index is out of range. */
1212248457Sjhibbits	if (symindx >= lc.nsym)
1213248457Sjhibbits		return;
1214248457Sjhibbits
1215248457Sjhibbits	/* Check if the symbol isn't cross-referenced. */
1216248457Sjhibbits	if ((offset = ctfoff[symindx]) == 0xffffffff)
1217248457Sjhibbits		return;
1218248457Sjhibbits
1219248457Sjhibbits	dp = (const ushort_t *)(lc.ctftab + offset + sizeof(ctf_header_t));
1220248457Sjhibbits
1221248457Sjhibbits	info = *dp++;
1222248457Sjhibbits	kind = CTF_INFO_KIND(info);
1223248457Sjhibbits	n = CTF_INFO_VLEN(info);
1224248457Sjhibbits
1225248457Sjhibbits	if (kind == CTF_K_UNKNOWN && n == 0) {
1226248457Sjhibbits		printf("%s(%d): Unknown function!\n",__func__,__LINE__);
1227248457Sjhibbits		return;
1228248457Sjhibbits	}
1229248457Sjhibbits
1230248457Sjhibbits	if (kind != CTF_K_FUNCTION) {
1231248457Sjhibbits		printf("%s(%d): Expected a function!\n",__func__,__LINE__);
1232248457Sjhibbits		return;
1233248457Sjhibbits	}
1234248457Sjhibbits
1235255099Sjhibbits	if (fbt->fbtp_roffset != 0) {
1236255099Sjhibbits		/* Only return type is available for args[1] in return probe. */
1237255099Sjhibbits		if (ndx > 1)
1238255099Sjhibbits			return;
1239255099Sjhibbits		ASSERT(ndx == 1);
1240255099Sjhibbits	} else {
1241255099Sjhibbits		/* Check if the requested argument doesn't exist. */
1242255099Sjhibbits		if (ndx >= n)
1243255099Sjhibbits			return;
1244248457Sjhibbits
1245255099Sjhibbits		/* Skip the return type and arguments up to the one requested. */
1246255099Sjhibbits		dp += ndx + 1;
1247255099Sjhibbits	}
1248248457Sjhibbits
1249248457Sjhibbits	if (fbt_type_name(&lc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
1250248457Sjhibbits		desc->dtargd_ndx = ndx;
1251248457Sjhibbits
1252248457Sjhibbits	return;
1253248457Sjhibbits}
1254248457Sjhibbits
1255255099Sjhibbitsstatic int
1256255099Sjhibbitsfbt_linker_file_cb(linker_file_t lf, void *arg)
1257255099Sjhibbits{
1258255099Sjhibbits
1259255099Sjhibbits	fbt_provide_module(arg, lf);
1260255099Sjhibbits
1261255099Sjhibbits	return (0);
1262255099Sjhibbits}
1263255099Sjhibbits
1264248457Sjhibbitsstatic void
1265248457Sjhibbitsfbt_load(void *dummy)
1266248457Sjhibbits{
1267248457Sjhibbits	/* Create the /dev/dtrace/fbt entry. */
1268248457Sjhibbits	fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
1269248457Sjhibbits	    "dtrace/fbt");
1270248457Sjhibbits
1271248457Sjhibbits	/* Default the probe table size if not specified. */
1272248457Sjhibbits	if (fbt_probetab_size == 0)
1273248457Sjhibbits		fbt_probetab_size = FBT_PROBETAB_SIZE;
1274248457Sjhibbits
1275248457Sjhibbits	/* Choose the hash mask for the probe table. */
1276248457Sjhibbits	fbt_probetab_mask = fbt_probetab_size - 1;
1277248457Sjhibbits
1278248457Sjhibbits	/* Allocate memory for the probe table. */
1279248457Sjhibbits	fbt_probetab =
1280248457Sjhibbits	    malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
1281248457Sjhibbits
1282248457Sjhibbits	dtrace_invop_add(fbt_invop);
1283248457Sjhibbits
1284248457Sjhibbits	if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
1285248457Sjhibbits	    NULL, &fbt_pops, NULL, &fbt_id) != 0)
1286248457Sjhibbits		return;
1287255099Sjhibbits
1288255099Sjhibbits	/* Create probes for the kernel and already-loaded modules. */
1289255099Sjhibbits	linker_file_foreach(fbt_linker_file_cb, NULL);
1290248457Sjhibbits}
1291248457Sjhibbits
1292248457Sjhibbits
1293248457Sjhibbitsstatic int
1294248457Sjhibbitsfbt_unload()
1295248457Sjhibbits{
1296248457Sjhibbits	int error = 0;
1297248457Sjhibbits
1298248457Sjhibbits	/* De-register the invalid opcode handler. */
1299248457Sjhibbits	dtrace_invop_remove(fbt_invop);
1300248457Sjhibbits
1301248457Sjhibbits	/* De-register this DTrace provider. */
1302248457Sjhibbits	if ((error = dtrace_unregister(fbt_id)) != 0)
1303248457Sjhibbits		return (error);
1304248457Sjhibbits
1305248457Sjhibbits	/* Free the probe table. */
1306248457Sjhibbits	free(fbt_probetab, M_FBT);
1307248457Sjhibbits	fbt_probetab = NULL;
1308248457Sjhibbits	fbt_probetab_mask = 0;
1309248457Sjhibbits
1310248457Sjhibbits	destroy_dev(fbt_cdev);
1311248457Sjhibbits
1312248457Sjhibbits	return (error);
1313248457Sjhibbits}
1314248457Sjhibbits
1315248457Sjhibbitsstatic int
1316248457Sjhibbitsfbt_modevent(module_t mod __unused, int type, void *data __unused)
1317248457Sjhibbits{
1318248457Sjhibbits	int error = 0;
1319248457Sjhibbits
1320248457Sjhibbits	switch (type) {
1321248457Sjhibbits	case MOD_LOAD:
1322248457Sjhibbits		break;
1323248457Sjhibbits
1324248457Sjhibbits	case MOD_UNLOAD:
1325248457Sjhibbits		break;
1326248457Sjhibbits
1327248457Sjhibbits	case MOD_SHUTDOWN:
1328248457Sjhibbits		break;
1329248457Sjhibbits
1330248457Sjhibbits	default:
1331248457Sjhibbits		error = EOPNOTSUPP;
1332248457Sjhibbits		break;
1333248457Sjhibbits
1334248457Sjhibbits	}
1335248457Sjhibbits
1336248457Sjhibbits	return (error);
1337248457Sjhibbits}
1338248457Sjhibbits
1339248457Sjhibbitsstatic int
1340248457Sjhibbitsfbt_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
1341248457Sjhibbits{
1342248457Sjhibbits	return (0);
1343248457Sjhibbits}
1344248457Sjhibbits
1345248457SjhibbitsSYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL);
1346248457SjhibbitsSYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL);
1347248457Sjhibbits
1348248457SjhibbitsDEV_MODULE(fbt, fbt_modevent, NULL);
1349248457SjhibbitsMODULE_VERSION(fbt, 1);
1350248457SjhibbitsMODULE_DEPEND(fbt, dtrace, 1, 1, 1);
1351248457SjhibbitsMODULE_DEPEND(fbt, opensolaris, 1, 1, 1);
1352