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