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