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