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