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