Home | History | Annotate | Line # | Download | only in fbt
fbt.c revision 1.29
      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 (at) freebsd.org
     24  * Portions Copyright 2010 Darran Hunt darran (at) 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 (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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 *
    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
    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 *
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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