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