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