Home | History | Annotate | Line # | Download | only in fbt
fbt.c revision 1.24
      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 (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 (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