Home | History | Annotate | Line # | Download | only in fbt
fbt.c revision 1.9
      1  1.9  christos /*	$NetBSD: fbt.c,v 1.9 2011/08/31 21:57:16 christos 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.1    darran  * $FreeBSD: src/sys/cddl/dev/fbt/fbt.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
     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.1    darran #include <sys/param.h>
     37  1.1    darran #include <sys/systm.h>
     38  1.1    darran #include <sys/conf.h>
     39  1.1    darran #include <sys/cpuvar.h>
     40  1.1    darran #include <sys/fcntl.h>
     41  1.1    darran #include <sys/filio.h>
     42  1.1    darran #include <sys/kernel.h>
     43  1.1    darran #include <sys/kmem.h>
     44  1.5  christos #include <sys/ksyms.h>
     45  1.3    darran #include <sys/cpu.h>
     46  1.1    darran #include <sys/kthread.h>
     47  1.1    darran #include <sys/limits.h>
     48  1.1    darran #include <sys/linker.h>
     49  1.1    darran #include <sys/lock.h>
     50  1.1    darran #include <sys/malloc.h>
     51  1.1    darran #include <sys/module.h>
     52  1.1    darran #include <sys/mutex.h>
     53  1.1    darran #include <sys/poll.h>
     54  1.1    darran #include <sys/proc.h>
     55  1.1    darran #include <sys/selinfo.h>
     56  1.1    darran #include <sys/syscall.h>
     57  1.1    darran #include <sys/uio.h>
     58  1.1    darran #include <sys/unistd.h>
     59  1.1    darran 
     60  1.3    darran #include <machine/cpu.h>
     61  1.3    darran #include <machine/cpufunc.h>
     62  1.3    darran #include <machine/specialreg.h>
     63  1.3    darran #if 0
     64  1.3    darran #include <x86/cpuvar.h>
     65  1.3    darran #endif
     66  1.3    darran #include <x86/cputypes.h>
     67  1.3    darran 
     68  1.3    darran #define ELFSIZE ARCH_ELFSIZE
     69  1.3    darran #include <sys/exec_elf.h>
     70  1.3    darran 
     71  1.1    darran #include <sys/dtrace.h>
     72  1.1    darran #include <sys/dtrace_bsd.h>
     73  1.3    darran #include <sys/kern_ctf.h>
     74  1.7      tron #include <sys/dtrace_impl.h>
     75  1.3    darran 
     76  1.3    darran mod_ctf_t *modptr;
     77  1.1    darran 
     78  1.1    darran MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
     79  1.1    darran 
     80  1.1    darran #define	FBT_PUSHL_EBP		0x55
     81  1.1    darran #define	FBT_MOVL_ESP_EBP0_V0	0x8b
     82  1.1    darran #define	FBT_MOVL_ESP_EBP1_V0	0xec
     83  1.1    darran #define	FBT_MOVL_ESP_EBP0_V1	0x89
     84  1.1    darran #define	FBT_MOVL_ESP_EBP1_V1	0xe5
     85  1.1    darran #define	FBT_REX_RSP_RBP		0x48
     86  1.1    darran 
     87  1.1    darran #define	FBT_POPL_EBP		0x5d
     88  1.1    darran #define	FBT_RET			0xc3
     89  1.1    darran #define	FBT_RET_IMM16		0xc2
     90  1.1    darran #define	FBT_LEAVE		0xc9
     91  1.1    darran 
     92  1.1    darran #ifdef __amd64__
     93  1.1    darran #define	FBT_PATCHVAL		0xcc
     94  1.1    darran #else
     95  1.1    darran #define	FBT_PATCHVAL		0xf0
     96  1.1    darran #endif
     97  1.1    darran 
     98  1.3    darran static dev_type_open(fbt_open);
     99  1.1    darran static int	fbt_unload(void);
    100  1.1    darran static void	fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
    101  1.3    darran static void	fbt_provide_module(void *, dtrace_modctl_t *);
    102  1.1    darran static void	fbt_destroy(void *, dtrace_id_t, void *);
    103  1.3    darran static int	fbt_enable(void *, dtrace_id_t, void *);
    104  1.1    darran static void	fbt_disable(void *, dtrace_id_t, void *);
    105  1.3    darran static void	fbt_load(void);
    106  1.1    darran static void	fbt_suspend(void *, dtrace_id_t, void *);
    107  1.1    darran static void	fbt_resume(void *, dtrace_id_t, void *);
    108  1.1    darran 
    109  1.1    darran #define	FBT_ENTRY	"entry"
    110  1.1    darran #define	FBT_RETURN	"return"
    111  1.1    darran #define	FBT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
    112  1.1    darran #define	FBT_PROBETAB_SIZE	0x8000		/* 32k entries -- 128K total */
    113  1.1    darran 
    114  1.3    darran static const struct cdevsw fbt_cdevsw = {
    115  1.3    darran 	fbt_open, noclose, noread, nowrite, noioctl,
    116  1.3    darran 	nostop, notty, nopoll, nommap, nokqfilter,
    117  1.3    darran 	D_OTHER
    118  1.1    darran };
    119  1.1    darran 
    120  1.1    darran static dtrace_pattr_t fbt_attr = {
    121  1.1    darran { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
    122  1.1    darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
    123  1.1    darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
    124  1.1    darran { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
    125  1.1    darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
    126  1.1    darran };
    127  1.1    darran 
    128  1.1    darran static dtrace_pops_t fbt_pops = {
    129  1.1    darran 	NULL,
    130  1.1    darran 	fbt_provide_module,
    131  1.1    darran 	fbt_enable,
    132  1.1    darran 	fbt_disable,
    133  1.1    darran 	fbt_suspend,
    134  1.1    darran 	fbt_resume,
    135  1.1    darran 	fbt_getargdesc,
    136  1.1    darran 	NULL,
    137  1.1    darran 	NULL,
    138  1.1    darran 	fbt_destroy
    139  1.1    darran };
    140  1.1    darran 
    141  1.1    darran typedef struct fbt_probe {
    142  1.1    darran 	struct fbt_probe *fbtp_hashnext;
    143  1.1    darran 	uint8_t		*fbtp_patchpoint;
    144  1.1    darran 	int8_t		fbtp_rval;
    145  1.1    darran 	uint8_t		fbtp_patchval;
    146  1.1    darran 	uint8_t		fbtp_savedval;
    147  1.1    darran 	uintptr_t	fbtp_roffset;
    148  1.1    darran 	dtrace_id_t	fbtp_id;
    149  1.1    darran 	const char	*fbtp_name;
    150  1.3    darran 	dtrace_modctl_t	*fbtp_ctl;
    151  1.1    darran 	int		fbtp_loadcnt;
    152  1.1    darran 	int		fbtp_primary;
    153  1.1    darran 	int		fbtp_invop_cnt;
    154  1.1    darran 	int		fbtp_symindx;
    155  1.1    darran 	struct fbt_probe *fbtp_next;
    156  1.1    darran } fbt_probe_t;
    157  1.1    darran 
    158  1.5  christos #ifdef notyet
    159  1.1    darran static struct cdev		*fbt_cdev;
    160  1.5  christos static int			fbt_verbose = 0;
    161  1.5  christos #endif
    162  1.1    darran static dtrace_provider_id_t	fbt_id;
    163  1.1    darran static fbt_probe_t		**fbt_probetab;
    164  1.1    darran static int			fbt_probetab_size;
    165  1.1    darran static int			fbt_probetab_mask;
    166  1.1    darran 
    167  1.1    darran static void
    168  1.1    darran fbt_doubletrap(void)
    169  1.1    darran {
    170  1.1    darran 	fbt_probe_t *fbt;
    171  1.1    darran 	int i;
    172  1.1    darran 
    173  1.1    darran 	for (i = 0; i < fbt_probetab_size; i++) {
    174  1.1    darran 		fbt = fbt_probetab[i];
    175  1.1    darran 
    176  1.1    darran 		for (; fbt != NULL; fbt = fbt->fbtp_next)
    177  1.1    darran 			*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
    178  1.1    darran 	}
    179  1.1    darran }
    180  1.1    darran 
    181  1.3    darran 
    182  1.1    darran static int
    183  1.1    darran fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
    184  1.1    darran {
    185  1.9  christos 	solaris_cpu_t *xcpu = &solaris_cpu[cpu_number()];
    186  1.1    darran 	uintptr_t stack0, stack1, stack2, stack3, stack4;
    187  1.1    darran 	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
    188  1.1    darran 
    189  1.1    darran 	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
    190  1.1    darran 		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
    191  1.1    darran 			fbt->fbtp_invop_cnt++;
    192  1.1    darran 			if (fbt->fbtp_roffset == 0) {
    193  1.1    darran 				int i = 0;
    194  1.1    darran 				/*
    195  1.1    darran 				 * When accessing the arguments on the stack,
    196  1.1    darran 				 * we must protect against accessing beyond
    197  1.1    darran 				 * the stack.  We can safely set NOFAULT here
    198  1.1    darran 				 * -- we know that interrupts are already
    199  1.1    darran 				 * disabled.
    200  1.1    darran 				 */
    201  1.1    darran 				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
    202  1.9  christos 				xcpu->cpu_dtrace_caller = stack[i++];
    203  1.1    darran 				stack0 = stack[i++];
    204  1.1    darran 				stack1 = stack[i++];
    205  1.1    darran 				stack2 = stack[i++];
    206  1.1    darran 				stack3 = stack[i++];
    207  1.1    darran 				stack4 = stack[i++];
    208  1.1    darran 				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
    209  1.1    darran 				    CPU_DTRACE_BADADDR);
    210  1.1    darran 
    211  1.1    darran 				dtrace_probe(fbt->fbtp_id, stack0, stack1,
    212  1.1    darran 				    stack2, stack3, stack4);
    213  1.1    darran 
    214  1.9  christos 				xcpu->cpu_dtrace_caller = 0;
    215  1.1    darran 			} else {
    216  1.1    darran #ifdef __amd64__
    217  1.1    darran 				/*
    218  1.1    darran 				 * On amd64, we instrument the ret, not the
    219  1.1    darran 				 * leave.  We therefore need to set the caller
    220  1.1    darran 				 * to assure that the top frame of a stack()
    221  1.1    darran 				 * action is correct.
    222  1.1    darran 				 */
    223  1.1    darran 				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
    224  1.9  christos 				xcpu->cpu_dtrace_caller = stack[0];
    225  1.1    darran 				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
    226  1.1    darran 				    CPU_DTRACE_BADADDR);
    227  1.1    darran #endif
    228  1.1    darran 
    229  1.1    darran 				dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
    230  1.1    darran 				    rval, 0, 0, 0);
    231  1.9  christos 				xcpu->cpu_dtrace_caller = 0;
    232  1.1    darran 			}
    233  1.1    darran 
    234  1.1    darran 			return (fbt->fbtp_rval);
    235  1.1    darran 		}
    236  1.1    darran 	}
    237  1.1    darran 
    238  1.1    darran 	return (0);
    239  1.1    darran }
    240  1.1    darran 
    241  1.1    darran static int
    242  1.3    darran fbt_provide_module_cb(const char *name, int symindx, void *value,
    243  1.4    darran 	uint32_t symsize, int type, void *opaque)
    244  1.1    darran {
    245  1.1    darran 	fbt_probe_t *fbt, *retfbt;
    246  1.3    darran 	u_int8_t *instr, *limit;
    247  1.3    darran 	dtrace_modctl_t *mod = opaque;
    248  1.3    darran 	const char *modname = mod->mod_info->mi_name;
    249  1.1    darran 	int j;
    250  1.4    darran 	int size;
    251  1.3    darran 
    252  1.3    darran 	/* got a function? */
    253  1.3    darran 	if (ELF_ST_TYPE(type) != STT_FUNC) {
    254  1.3    darran 	    return 0;
    255  1.3    darran 	}
    256  1.1    darran 
    257  1.1    darran 	if (strncmp(name, "dtrace_", 7) == 0 &&
    258  1.1    darran 	    strncmp(name, "dtrace_safe_", 12) != 0) {
    259  1.1    darran 		/*
    260  1.1    darran 		 * Anything beginning with "dtrace_" may be called
    261  1.1    darran 		 * from probe context unless it explicitly indicates
    262  1.1    darran 		 * that it won't be called from probe context by
    263  1.1    darran 		 * using the prefix "dtrace_safe_".
    264  1.1    darran 		 */
    265  1.1    darran 		return (0);
    266  1.1    darran 	}
    267  1.1    darran 
    268  1.1    darran 	if (name[0] == '_' && name[1] == '_')
    269  1.1    darran 		return (0);
    270  1.1    darran 
    271  1.3    darran 	instr = (u_int8_t *) value;
    272  1.4    darran 	limit = (u_int8_t *) value + symsize;
    273  1.1    darran 
    274  1.1    darran #ifdef __amd64__
    275  1.1    darran 	while (instr < limit) {
    276  1.1    darran 		if (*instr == FBT_PUSHL_EBP)
    277  1.1    darran 			break;
    278  1.1    darran 
    279  1.1    darran 		if ((size = dtrace_instr_size(instr)) <= 0)
    280  1.1    darran 			break;
    281  1.1    darran 
    282  1.1    darran 		instr += size;
    283  1.1    darran 	}
    284  1.1    darran 
    285  1.1    darran 	if (instr >= limit || *instr != FBT_PUSHL_EBP) {
    286  1.1    darran 		/*
    287  1.1    darran 		 * We either don't save the frame pointer in this
    288  1.1    darran 		 * function, or we ran into some disassembly
    289  1.1    darran 		 * screw-up.  Either way, we bail.
    290  1.1    darran 		 */
    291  1.1    darran 		return (0);
    292  1.1    darran 	}
    293  1.1    darran #else
    294  1.3    darran 	if (instr[0] != FBT_PUSHL_EBP) {
    295  1.1    darran 		return (0);
    296  1.3    darran 	}
    297  1.1    darran 
    298  1.1    darran 	if (!(instr[1] == FBT_MOVL_ESP_EBP0_V0 &&
    299  1.1    darran 	    instr[2] == FBT_MOVL_ESP_EBP1_V0) &&
    300  1.1    darran 	    !(instr[1] == FBT_MOVL_ESP_EBP0_V1 &&
    301  1.3    darran 	    instr[2] == FBT_MOVL_ESP_EBP1_V1)) {
    302  1.1    darran 		return (0);
    303  1.3    darran 	}
    304  1.1    darran #endif
    305  1.1    darran 	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
    306  1.1    darran 	fbt->fbtp_name = name;
    307  1.1    darran 	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
    308  1.1    darran 	    name, FBT_ENTRY, 3, fbt);
    309  1.1    darran 	fbt->fbtp_patchpoint = instr;
    310  1.3    darran 	fbt->fbtp_ctl = mod;
    311  1.3    darran 	/* fbt->fbtp_loadcnt = lf->loadcnt; */
    312  1.1    darran 	fbt->fbtp_rval = DTRACE_INVOP_PUSHL_EBP;
    313  1.1    darran 	fbt->fbtp_savedval = *instr;
    314  1.1    darran 	fbt->fbtp_patchval = FBT_PATCHVAL;
    315  1.1    darran 	fbt->fbtp_symindx = symindx;
    316  1.1    darran 
    317  1.1    darran 	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
    318  1.1    darran 	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
    319  1.3    darran 	mod->mod_fbtentries++;
    320  1.1    darran 
    321  1.3    darran 	retfbt = NULL;
    322  1.1    darran 
    323  1.3    darran 	while (instr < limit) {
    324  1.3    darran 		if (instr >= limit)
    325  1.3    darran 			return (0);
    326  1.1    darran 
    327  1.3    darran 		/*
    328  1.3    darran 		 * If this disassembly fails, then we've likely walked off into
    329  1.3    darran 		 * a jump table or some other unsuitable area.  Bail out of the
    330  1.3    darran 		 * disassembly now.
    331  1.3    darran 		 */
    332  1.3    darran 		if ((size = dtrace_instr_size(instr)) <= 0)
    333  1.3    darran 			return (0);
    334  1.1    darran 
    335  1.1    darran #ifdef __amd64__
    336  1.3    darran 		/*
    337  1.3    darran 		 * We only instrument "ret" on amd64 -- we don't yet instrument
    338  1.3    darran 		 * ret imm16, largely because the compiler doesn't seem to
    339  1.3    darran 		 * (yet) emit them in the kernel...
    340  1.3    darran 		 */
    341  1.3    darran 		if (*instr != FBT_RET) {
    342  1.3    darran 			instr += size;
    343  1.3    darran 			continue;
    344  1.3    darran 		}
    345  1.1    darran #else
    346  1.3    darran 		if (!(size == 1 &&
    347  1.3    darran 		    (*instr == FBT_POPL_EBP || *instr == FBT_LEAVE) &&
    348  1.3    darran 		    (*(instr + 1) == FBT_RET ||
    349  1.3    darran 		    *(instr + 1) == FBT_RET_IMM16))) {
    350  1.3    darran 			instr += size;
    351  1.3    darran 			continue;
    352  1.3    darran 		}
    353  1.1    darran #endif
    354  1.1    darran 
    355  1.3    darran 		/*
    356  1.3    darran 		 * We (desperately) want to avoid erroneously instrumenting a
    357  1.3    darran 		 * jump table, especially given that our markers are pretty
    358  1.3    darran 		 * short:  two bytes on x86, and just one byte on amd64.  To
    359  1.3    darran 		 * determine if we're looking at a true instruction sequence
    360  1.3    darran 		 * or an inline jump table that happens to contain the same
    361  1.3    darran 		 * byte sequences, we resort to some heuristic sleeze:  we
    362  1.3    darran 		 * treat this instruction as being contained within a pointer,
    363  1.3    darran 		 * and see if that pointer points to within the body of the
    364  1.3    darran 		 * function.  If it does, we refuse to instrument it.
    365  1.3    darran 		 */
    366  1.3    darran 		for (j = 0; j < sizeof (uintptr_t); j++) {
    367  1.3    darran 			caddr_t check = (caddr_t) instr - j;
    368  1.3    darran 			uint8_t *ptr;
    369  1.1    darran 
    370  1.3    darran 			if (check < (caddr_t)value)
    371  1.3    darran 				break;
    372  1.1    darran 
    373  1.3    darran 			if (check + sizeof (caddr_t) > (caddr_t)limit)
    374  1.3    darran 				continue;
    375  1.1    darran 
    376  1.3    darran 			ptr = *(uint8_t **)check;
    377  1.1    darran 
    378  1.3    darran 			if (ptr >= (uint8_t *) value && ptr < limit) {
    379  1.3    darran 				instr += size;
    380  1.3    darran 				continue;
    381  1.3    darran 			}
    382  1.1    darran 		}
    383  1.1    darran 
    384  1.3    darran 		/*
    385  1.3    darran 		 * We have a winner!
    386  1.3    darran 		 */
    387  1.3    darran 		fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
    388  1.3    darran 		fbt->fbtp_name = name;
    389  1.1    darran 
    390  1.3    darran 		if (retfbt == NULL) {
    391  1.3    darran 			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
    392  1.3    darran 			    name, FBT_RETURN, 3, fbt);
    393  1.3    darran 		} else {
    394  1.3    darran 			retfbt->fbtp_next = fbt;
    395  1.3    darran 			fbt->fbtp_id = retfbt->fbtp_id;
    396  1.3    darran 		}
    397  1.1    darran 
    398  1.3    darran 		retfbt = fbt;
    399  1.3    darran 		fbt->fbtp_patchpoint = instr;
    400  1.3    darran 		fbt->fbtp_ctl = mod;
    401  1.3    darran 		/* fbt->fbtp_loadcnt = lf->loadcnt; */
    402  1.3    darran 		fbt->fbtp_symindx = symindx;
    403  1.1    darran 
    404  1.1    darran #ifndef __amd64__
    405  1.3    darran 		if (*instr == FBT_POPL_EBP) {
    406  1.3    darran 			fbt->fbtp_rval = DTRACE_INVOP_POPL_EBP;
    407  1.3    darran 		} else {
    408  1.3    darran 			ASSERT(*instr == FBT_LEAVE);
    409  1.3    darran 			fbt->fbtp_rval = DTRACE_INVOP_LEAVE;
    410  1.3    darran 		}
    411  1.3    darran 		fbt->fbtp_roffset =
    412  1.3    darran 		    (uintptr_t)(instr - (uint8_t *) value) + 1;
    413  1.1    darran 
    414  1.1    darran #else
    415  1.3    darran 		ASSERT(*instr == FBT_RET);
    416  1.3    darran 		fbt->fbtp_rval = DTRACE_INVOP_RET;
    417  1.3    darran 		fbt->fbtp_roffset =
    418  1.3    darran 		    (uintptr_t)(instr - (uint8_t *) value);
    419  1.1    darran #endif
    420  1.1    darran 
    421  1.3    darran 		fbt->fbtp_savedval = *instr;
    422  1.3    darran 		fbt->fbtp_patchval = FBT_PATCHVAL;
    423  1.3    darran 		fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
    424  1.3    darran 		fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
    425  1.3    darran 
    426  1.3    darran 		mod->mod_fbtentries++;
    427  1.1    darran 
    428  1.3    darran 		instr += size;
    429  1.3    darran 	}
    430  1.1    darran 
    431  1.3    darran 	return 0;
    432  1.1    darran }
    433  1.1    darran 
    434  1.1    darran static void
    435  1.3    darran fbt_provide_module(void *arg, dtrace_modctl_t *mod)
    436  1.1    darran {
    437  1.1    darran 	char modname[MAXPATHLEN];
    438  1.1    darran 	int i;
    439  1.1    darran 	size_t len;
    440  1.1    darran 
    441  1.3    darran 	strlcpy(modname, mod->mod_info->mi_name, sizeof(modname));
    442  1.1    darran 	len = strlen(modname);
    443  1.3    darran 	if (len > 5 && strcmp(modname + len - 3, ".kmod") == 0)
    444  1.3    darran 		modname[len - 4] = '\0';
    445  1.1    darran 
    446  1.1    darran 	/*
    447  1.1    darran 	 * Employees of dtrace and their families are ineligible.  Void
    448  1.1    darran 	 * where prohibited.
    449  1.1    darran 	 */
    450  1.1    darran 	if (strcmp(modname, "dtrace") == 0)
    451  1.1    darran 		return;
    452  1.1    darran 
    453  1.1    darran 	/*
    454  1.1    darran 	 * The cyclic timer subsystem can be built as a module and DTrace
    455  1.1    darran 	 * depends on that, so it is ineligible too.
    456  1.1    darran 	 */
    457  1.1    darran 	if (strcmp(modname, "cyclic") == 0)
    458  1.1    darran 		return;
    459  1.1    darran 
    460  1.1    darran 	/*
    461  1.1    darran 	 * To register with DTrace, a module must list 'dtrace' as a
    462  1.1    darran 	 * dependency in order for the kernel linker to resolve
    463  1.1    darran 	 * symbols like dtrace_register(). All modules with such a
    464  1.1    darran 	 * dependency are ineligible for FBT tracing.
    465  1.1    darran 	 */
    466  1.3    darran 	for (i = 0; i < mod->mod_nrequired; i++) {
    467  1.3    darran 		if (strncmp(mod->mod_required[i]->mod_info->mi_name,
    468  1.3    darran 			    "dtrace", 6) == 0)
    469  1.1    darran 			return;
    470  1.3    darran 	}
    471  1.1    darran 
    472  1.3    darran 	if (mod->mod_fbtentries) {
    473  1.1    darran 		/*
    474  1.1    darran 		 * This module has some FBT entries allocated; we're afraid
    475  1.1    darran 		 * to screw with it.
    476  1.1    darran 		 */
    477  1.1    darran 		return;
    478  1.1    darran 	}
    479  1.1    darran 
    480  1.1    darran 	/*
    481  1.1    darran 	 * List the functions in the module and the symbol values.
    482  1.1    darran 	 */
    483  1.3    darran 	ksyms_mod_foreach(modname, fbt_provide_module_cb, mod);
    484  1.1    darran }
    485  1.1    darran 
    486  1.1    darran static void
    487  1.1    darran fbt_destroy(void *arg, dtrace_id_t id, void *parg)
    488  1.1    darran {
    489  1.1    darran 	fbt_probe_t *fbt = parg, *next, *hash, *last;
    490  1.3    darran 	dtrace_modctl_t *ctl;
    491  1.1    darran 	int ndx;
    492  1.1    darran 
    493  1.1    darran 	do {
    494  1.1    darran 		ctl = fbt->fbtp_ctl;
    495  1.1    darran 
    496  1.3    darran 		ctl->mod_fbtentries--;
    497  1.1    darran 
    498  1.1    darran 		/*
    499  1.1    darran 		 * Now we need to remove this probe from the fbt_probetab.
    500  1.1    darran 		 */
    501  1.1    darran 		ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
    502  1.1    darran 		last = NULL;
    503  1.1    darran 		hash = fbt_probetab[ndx];
    504  1.1    darran 
    505  1.1    darran 		while (hash != fbt) {
    506  1.1    darran 			ASSERT(hash != NULL);
    507  1.1    darran 			last = hash;
    508  1.1    darran 			hash = hash->fbtp_hashnext;
    509  1.1    darran 		}
    510  1.1    darran 
    511  1.1    darran 		if (last != NULL) {
    512  1.1    darran 			last->fbtp_hashnext = fbt->fbtp_hashnext;
    513  1.1    darran 		} else {
    514  1.1    darran 			fbt_probetab[ndx] = fbt->fbtp_hashnext;
    515  1.1    darran 		}
    516  1.1    darran 
    517  1.1    darran 		next = fbt->fbtp_next;
    518  1.1    darran 		free(fbt, M_FBT);
    519  1.1    darran 
    520  1.1    darran 		fbt = next;
    521  1.1    darran 	} while (fbt != NULL);
    522  1.1    darran }
    523  1.1    darran 
    524  1.3    darran static int
    525  1.1    darran fbt_enable(void *arg, dtrace_id_t id, void *parg)
    526  1.1    darran {
    527  1.1    darran 	fbt_probe_t *fbt = parg;
    528  1.5  christos #if 0
    529  1.3    darran 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
    530  1.5  christos #endif
    531  1.3    darran 	u_long psl;
    532  1.3    darran 	u_long cr0;
    533  1.3    darran 
    534  1.1    darran 
    535  1.3    darran #if 0	/* XXX TBD */
    536  1.1    darran 	ctl->nenabled++;
    537  1.1    darran 
    538  1.1    darran 	/*
    539  1.1    darran 	 * Now check that our modctl has the expected load count.  If it
    540  1.1    darran 	 * doesn't, this module must have been unloaded and reloaded -- and
    541  1.1    darran 	 * we're not going to touch it.
    542  1.1    darran 	 */
    543  1.1    darran 	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
    544  1.1    darran 		if (fbt_verbose) {
    545  1.1    darran 			printf("fbt is failing for probe %s "
    546  1.1    darran 			    "(module %s reloaded)",
    547  1.1    darran 			    fbt->fbtp_name, ctl->filename);
    548  1.1    darran 		}
    549  1.1    darran 
    550  1.1    darran 		return;
    551  1.1    darran 	}
    552  1.3    darran #endif
    553  1.3    darran 
    554  1.3    darran 	/* Disable interrupts. */
    555  1.3    darran 	psl = x86_read_psl();
    556  1.3    darran 	x86_disable_intr();
    557  1.3    darran 
    558  1.3    darran 	/* Disable write protection in supervisor mode. */
    559  1.3    darran 	cr0 = rcr0();
    560  1.3    darran 	lcr0(cr0 & ~CR0_WP);
    561  1.1    darran 
    562  1.1    darran 	for (; fbt != NULL; fbt = fbt->fbtp_next) {
    563  1.1    darran 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
    564  1.1    darran 	}
    565  1.3    darran 
    566  1.3    darran 	/* Write back and invalidate cache, flush pipelines. */
    567  1.3    darran 	wbinvd();
    568  1.3    darran 	x86_flush();
    569  1.3    darran 	x86_write_psl(psl);
    570  1.3    darran 
    571  1.3    darran 	/* Re-enable write protection. */
    572  1.3    darran 	lcr0(cr0);
    573  1.3    darran 
    574  1.3    darran 	return 0;
    575  1.1    darran }
    576  1.1    darran 
    577  1.1    darran static void
    578  1.1    darran fbt_disable(void *arg, dtrace_id_t id, void *parg)
    579  1.1    darran {
    580  1.1    darran 	fbt_probe_t *fbt = parg;
    581  1.5  christos #if 0
    582  1.3    darran 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
    583  1.5  christos #endif
    584  1.3    darran 	u_long psl;
    585  1.3    darran 	u_long cr0;
    586  1.1    darran 
    587  1.3    darran #if 0	/* XXX TBD */
    588  1.1    darran 	ASSERT(ctl->nenabled > 0);
    589  1.1    darran 	ctl->nenabled--;
    590  1.1    darran 
    591  1.1    darran 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
    592  1.1    darran 		return;
    593  1.3    darran #endif
    594  1.3    darran 	/* Disable interrupts. */
    595  1.3    darran 	psl = x86_read_psl();
    596  1.3    darran 	x86_disable_intr();
    597  1.3    darran 
    598  1.3    darran 	/* Disable write protection in supervisor mode. */
    599  1.3    darran 	cr0 = rcr0();
    600  1.3    darran 	lcr0(cr0 & ~CR0_WP);
    601  1.1    darran 
    602  1.1    darran 	for (; fbt != NULL; fbt = fbt->fbtp_next)
    603  1.1    darran 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
    604  1.3    darran 
    605  1.3    darran 	/* Write back and invalidate cache, flush pipelines. */
    606  1.3    darran 	wbinvd();
    607  1.3    darran 	x86_flush();
    608  1.3    darran 	x86_write_psl(psl);
    609  1.3    darran 
    610  1.3    darran 	/* Re-enable write protection. */
    611  1.3    darran 	lcr0(cr0);
    612  1.1    darran }
    613  1.1    darran 
    614  1.1    darran static void
    615  1.1    darran fbt_suspend(void *arg, dtrace_id_t id, void *parg)
    616  1.1    darran {
    617  1.1    darran 	fbt_probe_t *fbt = parg;
    618  1.5  christos #if 0
    619  1.3    darran 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
    620  1.5  christos #endif
    621  1.3    darran 	u_long psl;
    622  1.3    darran 	u_long cr0;
    623  1.1    darran 
    624  1.3    darran #if 0	/* XXX TBD */
    625  1.1    darran 	ASSERT(ctl->nenabled > 0);
    626  1.1    darran 
    627  1.1    darran 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
    628  1.1    darran 		return;
    629  1.3    darran #endif
    630  1.3    darran 
    631  1.3    darran 	/* Disable interrupts. */
    632  1.3    darran 	psl = x86_read_psl();
    633  1.3    darran 	x86_disable_intr();
    634  1.3    darran 
    635  1.3    darran 	/* Disable write protection in supervisor mode. */
    636  1.3    darran 	cr0 = rcr0();
    637  1.3    darran 	lcr0(cr0 & ~CR0_WP);
    638  1.1    darran 
    639  1.1    darran 	for (; fbt != NULL; fbt = fbt->fbtp_next)
    640  1.1    darran 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
    641  1.3    darran 
    642  1.3    darran 	/* Write back and invalidate cache, flush pipelines. */
    643  1.3    darran 	wbinvd();
    644  1.3    darran 	x86_flush();
    645  1.3    darran 	x86_write_psl(psl);
    646  1.3    darran 
    647  1.3    darran 	/* Re-enable write protection. */
    648  1.3    darran 	lcr0(cr0);
    649  1.1    darran }
    650  1.1    darran 
    651  1.1    darran static void
    652  1.1    darran fbt_resume(void *arg, dtrace_id_t id, void *parg)
    653  1.1    darran {
    654  1.1    darran 	fbt_probe_t *fbt = parg;
    655  1.5  christos #if 0
    656  1.3    darran 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
    657  1.5  christos #endif
    658  1.3    darran 	u_long psl;
    659  1.3    darran 	u_long cr0;
    660  1.1    darran 
    661  1.3    darran #if 0	/* XXX TBD */
    662  1.1    darran 	ASSERT(ctl->nenabled > 0);
    663  1.1    darran 
    664  1.1    darran 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
    665  1.1    darran 		return;
    666  1.3    darran #endif
    667  1.3    darran 	/* Disable interrupts. */
    668  1.3    darran 	psl = x86_read_psl();
    669  1.3    darran 	x86_disable_intr();
    670  1.3    darran 
    671  1.3    darran 	/* Disable write protection in supervisor mode. */
    672  1.3    darran 	cr0 = rcr0();
    673  1.3    darran 	lcr0(cr0 & ~CR0_WP);
    674  1.1    darran 
    675  1.1    darran 	for (; fbt != NULL; fbt = fbt->fbtp_next)
    676  1.1    darran 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
    677  1.3    darran 
    678  1.3    darran 	/* Write back and invalidate cache, flush pipelines. */
    679  1.3    darran 	wbinvd();
    680  1.3    darran 	x86_flush();
    681  1.3    darran 	x86_write_psl(psl);
    682  1.3    darran 
    683  1.3    darran 	/* Re-enable write protection. */
    684  1.3    darran 	lcr0(cr0);
    685  1.1    darran }
    686  1.1    darran 
    687  1.1    darran static int
    688  1.3    darran fbt_ctfoff_init(dtrace_modctl_t *mod, mod_ctf_t *mc)
    689  1.1    darran {
    690  1.3    darran 	const Elf_Sym *symp = mc->symtab;
    691  1.1    darran 	const char *name;
    692  1.3    darran 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
    693  1.3    darran 	const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
    694  1.1    darran 	int i;
    695  1.1    darran 	uint32_t *ctfoff;
    696  1.1    darran 	uint32_t objtoff = hp->cth_objtoff;
    697  1.1    darran 	uint32_t funcoff = hp->cth_funcoff;
    698  1.1    darran 	ushort_t info;
    699  1.1    darran 	ushort_t vlen;
    700  1.3    darran 	int nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym;
    701  1.1    darran 
    702  1.1    darran 	/* Sanity check. */
    703  1.1    darran 	if (hp->cth_magic != CTF_MAGIC) {
    704  1.3    darran 		printf("Bad magic value in CTF data of '%s'\n",
    705  1.3    darran 			mod->mod_info->mi_name);
    706  1.1    darran 		return (EINVAL);
    707  1.1    darran 	}
    708  1.1    darran 
    709  1.3    darran 	if (mc->symtab == NULL) {
    710  1.3    darran 		printf("No symbol table in '%s'\n",
    711  1.3    darran 			mod->mod_info->mi_name);
    712  1.1    darran 		return (EINVAL);
    713  1.1    darran 	}
    714  1.1    darran 
    715  1.3    darran 	if ((ctfoff = malloc(sizeof(uint32_t) * nsyms, M_FBT, M_WAITOK)) == NULL)
    716  1.1    darran 		return (ENOMEM);
    717  1.1    darran 
    718  1.3    darran 	mc->ctfoffp = ctfoff;
    719  1.3    darran 
    720  1.3    darran 	for (i = 0; i < nsyms; i++, ctfoff++, symp++) {
    721  1.3    darran 	   	if (mc->nmap != NULL) {
    722  1.3    darran 			if (mc->nmap[i] == 0) {
    723  1.3    darran 				printf("%s.%d: Error! Got zero nmap!\n",
    724  1.3    darran 					__func__, __LINE__);
    725  1.3    darran 				continue;
    726  1.3    darran 			}
    727  1.3    darran 
    728  1.3    darran 			/* CTF expects the pre-sorted symbol ordering,
    729  1.3    darran 			 * so map it from that to the current sorted
    730  1.3    darran 			 * and trimmed symbol table.
    731  1.3    darran 			 * ctfoff[new-ind] = oldind symbol info.
    732  1.3    darran 			 */
    733  1.3    darran 
    734  1.3    darran 			/* map old index to new symbol table */
    735  1.3    darran 			symp = &mc->symtab[mc->nmap[i] - 1];
    736  1.3    darran 
    737  1.3    darran 			/* map old index to new ctfoff index */
    738  1.3    darran 			ctfoff = &mc->ctfoffp[mc->nmap[i]-1];
    739  1.3    darran 		}
    740  1.1    darran 
    741  1.1    darran 		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
    742  1.1    darran 			*ctfoff = 0xffffffff;
    743  1.1    darran 			continue;
    744  1.1    darran 		}
    745  1.1    darran 
    746  1.3    darran 		if (symp->st_name < mc->strcnt)
    747  1.3    darran 			name = mc->strtab + symp->st_name;
    748  1.1    darran 		else
    749  1.1    darran 			name = "(?)";
    750  1.1    darran 
    751  1.1    darran 		switch (ELF_ST_TYPE(symp->st_info)) {
    752  1.1    darran 		case STT_OBJECT:
    753  1.1    darran 			if (objtoff >= hp->cth_funcoff ||
    754  1.1    darran                             (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
    755  1.1    darran 				*ctfoff = 0xffffffff;
    756  1.1    darran                                 break;
    757  1.1    darran                         }
    758  1.1    darran 
    759  1.1    darran                         *ctfoff = objtoff;
    760  1.1    darran                         objtoff += sizeof (ushort_t);
    761  1.1    darran 			break;
    762  1.1    darran 
    763  1.1    darran 		case STT_FUNC:
    764  1.1    darran 			if (funcoff >= hp->cth_typeoff) {
    765  1.1    darran 				*ctfoff = 0xffffffff;
    766  1.1    darran 				break;
    767  1.1    darran 			}
    768  1.1    darran 
    769  1.1    darran 			*ctfoff = funcoff;
    770  1.1    darran 
    771  1.1    darran 			info = *((const ushort_t *)(ctfdata + funcoff));
    772  1.1    darran 			vlen = CTF_INFO_VLEN(info);
    773  1.1    darran 
    774  1.1    darran 			/*
    775  1.1    darran 			 * If we encounter a zero pad at the end, just skip it.
    776  1.1    darran 			 * Otherwise skip over the function and its return type
    777  1.1    darran 			 * (+2) and the argument list (vlen).
    778  1.1    darran 			 */
    779  1.1    darran 			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
    780  1.1    darran 				funcoff += sizeof (ushort_t); /* skip pad */
    781  1.1    darran 			else
    782  1.1    darran 				funcoff += sizeof (ushort_t) * (vlen + 2);
    783  1.1    darran 			break;
    784  1.1    darran 
    785  1.1    darran 		default:
    786  1.1    darran 			*ctfoff = 0xffffffff;
    787  1.1    darran 			break;
    788  1.1    darran 		}
    789  1.1    darran 	}
    790  1.1    darran 
    791  1.1    darran 	return (0);
    792  1.1    darran }
    793  1.1    darran 
    794  1.1    darran static ssize_t
    795  1.9  christos fbt_get_ctt_size(uint8_t xversion, const ctf_type_t *tp, ssize_t *sizep,
    796  1.1    darran     ssize_t *incrementp)
    797  1.1    darran {
    798  1.1    darran 	ssize_t size, increment;
    799  1.1    darran 
    800  1.9  christos 	if (xversion > CTF_VERSION_1 &&
    801  1.1    darran 	    tp->ctt_size == CTF_LSIZE_SENT) {
    802  1.1    darran 		size = CTF_TYPE_LSIZE(tp);
    803  1.1    darran 		increment = sizeof (ctf_type_t);
    804  1.1    darran 	} else {
    805  1.1    darran 		size = tp->ctt_size;
    806  1.1    darran 		increment = sizeof (ctf_stype_t);
    807  1.1    darran 	}
    808  1.1    darran 
    809  1.1    darran 	if (sizep)
    810  1.1    darran 		*sizep = size;
    811  1.1    darran 	if (incrementp)
    812  1.1    darran 		*incrementp = increment;
    813  1.1    darran 
    814  1.1    darran 	return (size);
    815  1.1    darran }
    816  1.1    darran 
    817  1.1    darran static int
    818  1.3    darran fbt_typoff_init(mod_ctf_t *mc)
    819  1.1    darran {
    820  1.3    darran 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
    821  1.1    darran 	const ctf_type_t *tbuf;
    822  1.1    darran 	const ctf_type_t *tend;
    823  1.1    darran 	const ctf_type_t *tp;
    824  1.3    darran 	const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
    825  1.1    darran 	int ctf_typemax = 0;
    826  1.1    darran 	uint32_t *xp;
    827  1.1    darran 	ulong_t pop[CTF_K_MAX + 1] = { 0 };
    828  1.1    darran 
    829  1.1    darran 	/* Sanity check. */
    830  1.1    darran 	if (hp->cth_magic != CTF_MAGIC)
    831  1.1    darran 		return (EINVAL);
    832  1.1    darran 
    833  1.1    darran 	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
    834  1.1    darran 	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
    835  1.1    darran 
    836  1.1    darran 	int child = hp->cth_parname != 0;
    837  1.1    darran 
    838  1.1    darran 	/*
    839  1.1    darran 	 * We make two passes through the entire type section.  In this first
    840  1.1    darran 	 * pass, we count the number of each type and the total number of types.
    841  1.1    darran 	 */
    842  1.1    darran 	for (tp = tbuf; tp < tend; ctf_typemax++) {
    843  1.1    darran 		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
    844  1.1    darran 		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
    845  1.1    darran 		ssize_t size, increment;
    846  1.1    darran 
    847  1.1    darran 		size_t vbytes;
    848  1.1    darran 		uint_t n;
    849  1.1    darran 
    850  1.1    darran 		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
    851  1.1    darran 
    852  1.1    darran 		switch (kind) {
    853  1.1    darran 		case CTF_K_INTEGER:
    854  1.1    darran 		case CTF_K_FLOAT:
    855  1.1    darran 			vbytes = sizeof (uint_t);
    856  1.1    darran 			break;
    857  1.1    darran 		case CTF_K_ARRAY:
    858  1.1    darran 			vbytes = sizeof (ctf_array_t);
    859  1.1    darran 			break;
    860  1.1    darran 		case CTF_K_FUNCTION:
    861  1.1    darran 			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
    862  1.1    darran 			break;
    863  1.1    darran 		case CTF_K_STRUCT:
    864  1.1    darran 		case CTF_K_UNION:
    865  1.1    darran 			if (size < CTF_LSTRUCT_THRESH) {
    866  1.1    darran 				ctf_member_t *mp = (ctf_member_t *)
    867  1.1    darran 				    ((uintptr_t)tp + increment);
    868  1.1    darran 
    869  1.1    darran 				vbytes = sizeof (ctf_member_t) * vlen;
    870  1.1    darran 				for (n = vlen; n != 0; n--, mp++)
    871  1.1    darran 					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
    872  1.1    darran 			} else {
    873  1.1    darran 				ctf_lmember_t *lmp = (ctf_lmember_t *)
    874  1.1    darran 				    ((uintptr_t)tp + increment);
    875  1.1    darran 
    876  1.1    darran 				vbytes = sizeof (ctf_lmember_t) * vlen;
    877  1.1    darran 				for (n = vlen; n != 0; n--, lmp++)
    878  1.1    darran 					child |=
    879  1.1    darran 					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
    880  1.1    darran 			}
    881  1.1    darran 			break;
    882  1.1    darran 		case CTF_K_ENUM:
    883  1.1    darran 			vbytes = sizeof (ctf_enum_t) * vlen;
    884  1.1    darran 			break;
    885  1.1    darran 		case CTF_K_FORWARD:
    886  1.1    darran 			/*
    887  1.1    darran 			 * For forward declarations, ctt_type is the CTF_K_*
    888  1.1    darran 			 * kind for the tag, so bump that population count too.
    889  1.1    darran 			 * If ctt_type is unknown, treat the tag as a struct.
    890  1.1    darran 			 */
    891  1.1    darran 			if (tp->ctt_type == CTF_K_UNKNOWN ||
    892  1.1    darran 			    tp->ctt_type >= CTF_K_MAX)
    893  1.1    darran 				pop[CTF_K_STRUCT]++;
    894  1.1    darran 			else
    895  1.1    darran 				pop[tp->ctt_type]++;
    896  1.1    darran 			/*FALLTHRU*/
    897  1.1    darran 		case CTF_K_UNKNOWN:
    898  1.1    darran 			vbytes = 0;
    899  1.1    darran 			break;
    900  1.1    darran 		case CTF_K_POINTER:
    901  1.1    darran 		case CTF_K_TYPEDEF:
    902  1.1    darran 		case CTF_K_VOLATILE:
    903  1.1    darran 		case CTF_K_CONST:
    904  1.1    darran 		case CTF_K_RESTRICT:
    905  1.1    darran 			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
    906  1.1    darran 			vbytes = 0;
    907  1.1    darran 			break;
    908  1.1    darran 		default:
    909  1.1    darran 			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
    910  1.1    darran 			return (EIO);
    911  1.1    darran 		}
    912  1.1    darran 		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
    913  1.1    darran 		pop[kind]++;
    914  1.1    darran 	}
    915  1.1    darran 
    916  1.3    darran 	mc->typlen = ctf_typemax;
    917  1.1    darran 
    918  1.3    darran 	if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_FBT, M_ZERO | M_WAITOK)) == NULL)
    919  1.1    darran 		return (ENOMEM);
    920  1.1    darran 
    921  1.3    darran 	mc->typoffp = xp;
    922  1.1    darran 
    923  1.1    darran 	/* type id 0 is used as a sentinel value */
    924  1.1    darran 	*xp++ = 0;
    925  1.1    darran 
    926  1.1    darran 	/*
    927  1.1    darran 	 * In the second pass, fill in the type offset.
    928  1.1    darran 	 */
    929  1.1    darran 	for (tp = tbuf; tp < tend; xp++) {
    930  1.1    darran 		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
    931  1.1    darran 		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
    932  1.1    darran 		ssize_t size, increment;
    933  1.1    darran 
    934  1.1    darran 		size_t vbytes;
    935  1.1    darran 		uint_t n;
    936  1.1    darran 
    937  1.1    darran 		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
    938  1.1    darran 
    939  1.1    darran 		switch (kind) {
    940  1.1    darran 		case CTF_K_INTEGER:
    941  1.1    darran 		case CTF_K_FLOAT:
    942  1.1    darran 			vbytes = sizeof (uint_t);
    943  1.1    darran 			break;
    944  1.1    darran 		case CTF_K_ARRAY:
    945  1.1    darran 			vbytes = sizeof (ctf_array_t);
    946  1.1    darran 			break;
    947  1.1    darran 		case CTF_K_FUNCTION:
    948  1.1    darran 			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
    949  1.1    darran 			break;
    950  1.1    darran 		case CTF_K_STRUCT:
    951  1.1    darran 		case CTF_K_UNION:
    952  1.1    darran 			if (size < CTF_LSTRUCT_THRESH) {
    953  1.1    darran 				ctf_member_t *mp = (ctf_member_t *)
    954  1.1    darran 				    ((uintptr_t)tp + increment);
    955  1.1    darran 
    956  1.1    darran 				vbytes = sizeof (ctf_member_t) * vlen;
    957  1.1    darran 				for (n = vlen; n != 0; n--, mp++)
    958  1.1    darran 					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
    959  1.1    darran 			} else {
    960  1.1    darran 				ctf_lmember_t *lmp = (ctf_lmember_t *)
    961  1.1    darran 				    ((uintptr_t)tp + increment);
    962  1.1    darran 
    963  1.1    darran 				vbytes = sizeof (ctf_lmember_t) * vlen;
    964  1.1    darran 				for (n = vlen; n != 0; n--, lmp++)
    965  1.1    darran 					child |=
    966  1.1    darran 					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
    967  1.1    darran 			}
    968  1.1    darran 			break;
    969  1.1    darran 		case CTF_K_ENUM:
    970  1.1    darran 			vbytes = sizeof (ctf_enum_t) * vlen;
    971  1.1    darran 			break;
    972  1.1    darran 		case CTF_K_FORWARD:
    973  1.1    darran 		case CTF_K_UNKNOWN:
    974  1.1    darran 			vbytes = 0;
    975  1.1    darran 			break;
    976  1.1    darran 		case CTF_K_POINTER:
    977  1.1    darran 		case CTF_K_TYPEDEF:
    978  1.1    darran 		case CTF_K_VOLATILE:
    979  1.1    darran 		case CTF_K_CONST:
    980  1.1    darran 		case CTF_K_RESTRICT:
    981  1.1    darran 			vbytes = 0;
    982  1.1    darran 			break;
    983  1.1    darran 		default:
    984  1.1    darran 			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
    985  1.1    darran 			return (EIO);
    986  1.1    darran 		}
    987  1.1    darran 		*xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
    988  1.1    darran 		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
    989  1.1    darran 	}
    990  1.1    darran 
    991  1.1    darran 	return (0);
    992  1.1    darran }
    993  1.1    darran 
    994  1.1    darran /*
    995  1.1    darran  * CTF Declaration Stack
    996  1.1    darran  *
    997  1.1    darran  * In order to implement ctf_type_name(), we must convert a type graph back
    998  1.1    darran  * into a C type declaration.  Unfortunately, a type graph represents a storage
    999  1.1    darran  * class ordering of the type whereas a type declaration must obey the C rules
   1000  1.1    darran  * for operator precedence, and the two orderings are frequently in conflict.
   1001  1.1    darran  * For example, consider these CTF type graphs and their C declarations:
   1002  1.1    darran  *
   1003  1.1    darran  * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
   1004  1.1    darran  * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
   1005  1.1    darran  *
   1006  1.1    darran  * In each case, parentheses are used to raise operator * to higher lexical
   1007  1.1    darran  * precedence, so the string form of the C declaration cannot be constructed by
   1008  1.1    darran  * walking the type graph links and forming the string from left to right.
   1009  1.1    darran  *
   1010  1.1    darran  * The functions in this file build a set of stacks from the type graph nodes
   1011  1.1    darran  * corresponding to the C operator precedence levels in the appropriate order.
   1012  1.1    darran  * The code in ctf_type_name() can then iterate over the levels and nodes in
   1013  1.1    darran  * lexical precedence order and construct the final C declaration string.
   1014  1.1    darran  */
   1015  1.1    darran typedef struct ctf_list {
   1016  1.1    darran 	struct ctf_list *l_prev; /* previous pointer or tail pointer */
   1017  1.1    darran 	struct ctf_list *l_next; /* next pointer or head pointer */
   1018  1.1    darran } ctf_list_t;
   1019  1.1    darran 
   1020  1.1    darran #define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
   1021  1.1    darran #define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
   1022  1.1    darran 
   1023  1.1    darran typedef enum {
   1024  1.1    darran 	CTF_PREC_BASE,
   1025  1.1    darran 	CTF_PREC_POINTER,
   1026  1.1    darran 	CTF_PREC_ARRAY,
   1027  1.1    darran 	CTF_PREC_FUNCTION,
   1028  1.1    darran 	CTF_PREC_MAX
   1029  1.1    darran } ctf_decl_prec_t;
   1030  1.1    darran 
   1031  1.1    darran typedef struct ctf_decl_node {
   1032  1.1    darran 	ctf_list_t cd_list;			/* linked list pointers */
   1033  1.1    darran 	ctf_id_t cd_type;			/* type identifier */
   1034  1.1    darran 	uint_t cd_kind;				/* type kind */
   1035  1.1    darran 	uint_t cd_n;				/* type dimension if array */
   1036  1.1    darran } ctf_decl_node_t;
   1037  1.1    darran 
   1038  1.1    darran typedef struct ctf_decl {
   1039  1.1    darran 	ctf_list_t cd_nodes[CTF_PREC_MAX];	/* declaration node stacks */
   1040  1.1    darran 	int cd_order[CTF_PREC_MAX];		/* storage order of decls */
   1041  1.1    darran 	ctf_decl_prec_t cd_qualp;		/* qualifier precision */
   1042  1.1    darran 	ctf_decl_prec_t cd_ordp;		/* ordered precision */
   1043  1.1    darran 	char *cd_buf;				/* buffer for output */
   1044  1.1    darran 	char *cd_ptr;				/* buffer location */
   1045  1.1    darran 	char *cd_end;				/* buffer limit */
   1046  1.1    darran 	size_t cd_len;				/* buffer space required */
   1047  1.1    darran 	int cd_err;				/* saved error value */
   1048  1.1    darran } ctf_decl_t;
   1049  1.1    darran 
   1050  1.1    darran /*
   1051  1.1    darran  * Simple doubly-linked list append routine.  This implementation assumes that
   1052  1.1    darran  * each list element contains an embedded ctf_list_t as the first member.
   1053  1.1    darran  * An additional ctf_list_t is used to store the head (l_next) and tail
   1054  1.1    darran  * (l_prev) pointers.  The current head and tail list elements have their
   1055  1.1    darran  * previous and next pointers set to NULL, respectively.
   1056  1.1    darran  */
   1057  1.1    darran static void
   1058  1.1    darran ctf_list_append(ctf_list_t *lp, void *new)
   1059  1.1    darran {
   1060  1.1    darran 	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
   1061  1.1    darran 	ctf_list_t *q = new;		/* q = new list element */
   1062  1.1    darran 
   1063  1.1    darran 	lp->l_prev = q;
   1064  1.1    darran 	q->l_prev = p;
   1065  1.1    darran 	q->l_next = NULL;
   1066  1.1    darran 
   1067  1.1    darran 	if (p != NULL)
   1068  1.1    darran 		p->l_next = q;
   1069  1.1    darran 	else
   1070  1.1    darran 		lp->l_next = q;
   1071  1.1    darran }
   1072  1.1    darran 
   1073  1.1    darran /*
   1074  1.1    darran  * Prepend the specified existing element to the given ctf_list_t.  The
   1075  1.1    darran  * existing pointer should be pointing at a struct with embedded ctf_list_t.
   1076  1.1    darran  */
   1077  1.1    darran static void
   1078  1.1    darran ctf_list_prepend(ctf_list_t *lp, void *new)
   1079  1.1    darran {
   1080  1.1    darran 	ctf_list_t *p = new;		/* p = new list element */
   1081  1.1    darran 	ctf_list_t *q = lp->l_next;	/* q = head list element */
   1082  1.1    darran 
   1083  1.1    darran 	lp->l_next = p;
   1084  1.1    darran 	p->l_prev = NULL;
   1085  1.1    darran 	p->l_next = q;
   1086  1.1    darran 
   1087  1.1    darran 	if (q != NULL)
   1088  1.1    darran 		q->l_prev = p;
   1089  1.1    darran 	else
   1090  1.1    darran 		lp->l_prev = p;
   1091  1.1    darran }
   1092  1.1    darran 
   1093  1.1    darran static void
   1094  1.1    darran ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
   1095  1.1    darran {
   1096  1.1    darran 	int i;
   1097  1.1    darran 
   1098  1.1    darran 	bzero(cd, sizeof (ctf_decl_t));
   1099  1.1    darran 
   1100  1.1    darran 	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
   1101  1.1    darran 		cd->cd_order[i] = CTF_PREC_BASE - 1;
   1102  1.1    darran 
   1103  1.1    darran 	cd->cd_qualp = CTF_PREC_BASE;
   1104  1.1    darran 	cd->cd_ordp = CTF_PREC_BASE;
   1105  1.1    darran 
   1106  1.1    darran 	cd->cd_buf = buf;
   1107  1.1    darran 	cd->cd_ptr = buf;
   1108  1.1    darran 	cd->cd_end = buf + len;
   1109  1.1    darran }
   1110  1.1    darran 
   1111  1.1    darran static void
   1112  1.1    darran ctf_decl_fini(ctf_decl_t *cd)
   1113  1.1    darran {
   1114  1.1    darran 	ctf_decl_node_t *cdp, *ndp;
   1115  1.1    darran 	int i;
   1116  1.1    darran 
   1117  1.1    darran 	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
   1118  1.1    darran 		for (cdp = ctf_list_next(&cd->cd_nodes[i]);
   1119  1.1    darran 		    cdp != NULL; cdp = ndp) {
   1120  1.1    darran 			ndp = ctf_list_next(cdp);
   1121  1.1    darran 			free(cdp, M_FBT);
   1122  1.1    darran 		}
   1123  1.1    darran 	}
   1124  1.1    darran }
   1125  1.1    darran 
   1126  1.1    darran static const ctf_type_t *
   1127  1.3    darran ctf_lookup_by_id(mod_ctf_t *mc, ctf_id_t type)
   1128  1.1    darran {
   1129  1.1    darran 	const ctf_type_t *tp;
   1130  1.1    darran 	uint32_t offset;
   1131  1.3    darran 	uint32_t *typoff = mc->typoffp;
   1132  1.1    darran 
   1133  1.3    darran 	if (type >= mc->typlen) {
   1134  1.3    darran 		printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,mc->typlen);
   1135  1.1    darran 		return(NULL);
   1136  1.1    darran 	}
   1137  1.1    darran 
   1138  1.1    darran 	/* Check if the type isn't cross-referenced. */
   1139  1.1    darran 	if ((offset = typoff[type]) == 0) {
   1140  1.1    darran 		printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
   1141  1.1    darran 		return(NULL);
   1142  1.1    darran 	}
   1143  1.1    darran 
   1144  1.3    darran 	tp = (const ctf_type_t *)(mc->ctftab + offset + sizeof(ctf_header_t));
   1145  1.1    darran 
   1146  1.1    darran 	return (tp);
   1147  1.1    darran }
   1148  1.1    darran 
   1149  1.1    darran static void
   1150  1.3    darran fbt_array_info(mod_ctf_t *mc, ctf_id_t type, ctf_arinfo_t *arp)
   1151  1.1    darran {
   1152  1.3    darran 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
   1153  1.1    darran 	const ctf_type_t *tp;
   1154  1.1    darran 	const ctf_array_t *ap;
   1155  1.1    darran 	ssize_t increment;
   1156  1.1    darran 
   1157  1.1    darran 	bzero(arp, sizeof(*arp));
   1158  1.1    darran 
   1159  1.3    darran 	if ((tp = ctf_lookup_by_id(mc, type)) == NULL)
   1160  1.1    darran 		return;
   1161  1.1    darran 
   1162  1.1    darran 	if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
   1163  1.1    darran 		return;
   1164  1.1    darran 
   1165  1.1    darran 	(void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
   1166  1.1    darran 
   1167  1.1    darran 	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
   1168  1.1    darran 	arp->ctr_contents = ap->cta_contents;
   1169  1.1    darran 	arp->ctr_index = ap->cta_index;
   1170  1.1    darran 	arp->ctr_nelems = ap->cta_nelems;
   1171  1.1    darran }
   1172  1.1    darran 
   1173  1.1    darran static const char *
   1174  1.3    darran ctf_strptr(mod_ctf_t *mc, int name)
   1175  1.1    darran {
   1176  1.3    darran 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;;
   1177  1.1    darran 	const char *strp = "";
   1178  1.1    darran 
   1179  1.1    darran 	if (name < 0 || name >= hp->cth_strlen)
   1180  1.1    darran 		return(strp);
   1181  1.1    darran 
   1182  1.3    darran 	strp = (const char *)(mc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
   1183  1.1    darran 
   1184  1.1    darran 	return (strp);
   1185  1.1    darran }
   1186  1.1    darran 
   1187  1.1    darran static void
   1188  1.3    darran ctf_decl_push(ctf_decl_t *cd, mod_ctf_t *mc, ctf_id_t type)
   1189  1.1    darran {
   1190  1.1    darran 	ctf_decl_node_t *cdp;
   1191  1.1    darran 	ctf_decl_prec_t prec;
   1192  1.1    darran 	uint_t kind, n = 1;
   1193  1.1    darran 	int is_qual = 0;
   1194  1.1    darran 
   1195  1.1    darran 	const ctf_type_t *tp;
   1196  1.1    darran 	ctf_arinfo_t ar;
   1197  1.1    darran 
   1198  1.3    darran 	if ((tp = ctf_lookup_by_id(mc, type)) == NULL) {
   1199  1.1    darran 		cd->cd_err = ENOENT;
   1200  1.1    darran 		return;
   1201  1.1    darran 	}
   1202  1.1    darran 
   1203  1.1    darran 	switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
   1204  1.1    darran 	case CTF_K_ARRAY:
   1205  1.3    darran 		fbt_array_info(mc, type, &ar);
   1206  1.3    darran 		ctf_decl_push(cd, mc, ar.ctr_contents);
   1207  1.1    darran 		n = ar.ctr_nelems;
   1208  1.1    darran 		prec = CTF_PREC_ARRAY;
   1209  1.1    darran 		break;
   1210  1.1    darran 
   1211  1.1    darran 	case CTF_K_TYPEDEF:
   1212  1.3    darran 		if (ctf_strptr(mc, tp->ctt_name)[0] == '\0') {
   1213  1.3    darran 			ctf_decl_push(cd, mc, tp->ctt_type);
   1214  1.1    darran 			return;
   1215  1.1    darran 		}
   1216  1.1    darran 		prec = CTF_PREC_BASE;
   1217  1.1    darran 		break;
   1218  1.1    darran 
   1219  1.1    darran 	case CTF_K_FUNCTION:
   1220  1.3    darran 		ctf_decl_push(cd, mc, tp->ctt_type);
   1221  1.1    darran 		prec = CTF_PREC_FUNCTION;
   1222  1.1    darran 		break;
   1223  1.1    darran 
   1224  1.1    darran 	case CTF_K_POINTER:
   1225  1.3    darran 		ctf_decl_push(cd, mc, tp->ctt_type);
   1226  1.1    darran 		prec = CTF_PREC_POINTER;
   1227  1.1    darran 		break;
   1228  1.1    darran 
   1229  1.1    darran 	case CTF_K_VOLATILE:
   1230  1.1    darran 	case CTF_K_CONST:
   1231  1.1    darran 	case CTF_K_RESTRICT:
   1232  1.3    darran 		ctf_decl_push(cd, mc, tp->ctt_type);
   1233  1.1    darran 		prec = cd->cd_qualp;
   1234  1.1    darran 		is_qual++;
   1235  1.1    darran 		break;
   1236  1.1    darran 
   1237  1.1    darran 	default:
   1238  1.1    darran 		prec = CTF_PREC_BASE;
   1239  1.1    darran 	}
   1240  1.1    darran 
   1241  1.1    darran 	if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) {
   1242  1.1    darran 		cd->cd_err = EAGAIN;
   1243  1.1    darran 		return;
   1244  1.1    darran 	}
   1245  1.1    darran 
   1246  1.1    darran 	cdp->cd_type = type;
   1247  1.1    darran 	cdp->cd_kind = kind;
   1248  1.1    darran 	cdp->cd_n = n;
   1249  1.1    darran 
   1250  1.1    darran 	if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
   1251  1.1    darran 		cd->cd_order[prec] = cd->cd_ordp++;
   1252  1.1    darran 
   1253  1.1    darran 	/*
   1254  1.1    darran 	 * Reset cd_qualp to the highest precedence level that we've seen so
   1255  1.1    darran 	 * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
   1256  1.1    darran 	 */
   1257  1.1    darran 	if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
   1258  1.1    darran 		cd->cd_qualp = prec;
   1259  1.1    darran 
   1260  1.1    darran 	/*
   1261  1.1    darran 	 * C array declarators are ordered inside out so prepend them.  Also by
   1262  1.1    darran 	 * convention qualifiers of base types precede the type specifier (e.g.
   1263  1.1    darran 	 * const int vs. int const) even though the two forms are equivalent.
   1264  1.1    darran 	 */
   1265  1.1    darran 	if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
   1266  1.1    darran 		ctf_list_prepend(&cd->cd_nodes[prec], cdp);
   1267  1.1    darran 	else
   1268  1.1    darran 		ctf_list_append(&cd->cd_nodes[prec], cdp);
   1269  1.1    darran }
   1270  1.1    darran 
   1271  1.1    darran static void
   1272  1.1    darran ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
   1273  1.1    darran {
   1274  1.1    darran 	size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
   1275  1.1    darran 	va_list ap;
   1276  1.1    darran 	size_t n;
   1277  1.1    darran 
   1278  1.1    darran 	va_start(ap, format);
   1279  1.1    darran 	n = vsnprintf(cd->cd_ptr, len, format, ap);
   1280  1.1    darran 	va_end(ap);
   1281  1.1    darran 
   1282  1.1    darran 	cd->cd_ptr += MIN(n, len);
   1283  1.1    darran 	cd->cd_len += n;
   1284  1.1    darran }
   1285  1.1    darran 
   1286  1.1    darran static ssize_t
   1287  1.3    darran fbt_type_name(mod_ctf_t *mc, ctf_id_t type, char *buf, size_t len)
   1288  1.1    darran {
   1289  1.1    darran 	ctf_decl_t cd;
   1290  1.1    darran 	ctf_decl_node_t *cdp;
   1291  1.1    darran 	ctf_decl_prec_t prec, lp, rp;
   1292  1.1    darran 	int ptr, arr;
   1293  1.1    darran 	uint_t k;
   1294  1.1    darran 
   1295  1.3    darran 	if (mc == NULL && type == CTF_ERR)
   1296  1.1    darran 		return (-1); /* simplify caller code by permitting CTF_ERR */
   1297  1.1    darran 
   1298  1.1    darran 	ctf_decl_init(&cd, buf, len);
   1299  1.3    darran 	ctf_decl_push(&cd, mc, type);
   1300  1.1    darran 
   1301  1.1    darran 	if (cd.cd_err != 0) {
   1302  1.1    darran 		ctf_decl_fini(&cd);
   1303  1.1    darran 		return (-1);
   1304  1.1    darran 	}
   1305  1.1    darran 
   1306  1.1    darran 	/*
   1307  1.1    darran 	 * If the type graph's order conflicts with lexical precedence order
   1308  1.1    darran 	 * for pointers or arrays, then we need to surround the declarations at
   1309  1.1    darran 	 * the corresponding lexical precedence with parentheses.  This can
   1310  1.1    darran 	 * result in either a parenthesized pointer (*) as in int (*)() or
   1311  1.1    darran 	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
   1312  1.1    darran 	 */
   1313  1.1    darran 	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
   1314  1.1    darran 	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
   1315  1.1    darran 
   1316  1.1    darran 	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
   1317  1.1    darran 	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
   1318  1.1    darran 
   1319  1.1    darran 	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
   1320  1.1    darran 
   1321  1.1    darran 	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
   1322  1.1    darran 		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
   1323  1.1    darran 		    cdp != NULL; cdp = ctf_list_next(cdp)) {
   1324  1.1    darran 
   1325  1.1    darran 			const ctf_type_t *tp =
   1326  1.3    darran 			    ctf_lookup_by_id(mc, cdp->cd_type);
   1327  1.3    darran 			const char *name = ctf_strptr(mc, tp->ctt_name);
   1328  1.1    darran 
   1329  1.1    darran 			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
   1330  1.1    darran 				ctf_decl_sprintf(&cd, " ");
   1331  1.1    darran 
   1332  1.1    darran 			if (lp == prec) {
   1333  1.1    darran 				ctf_decl_sprintf(&cd, "(");
   1334  1.1    darran 				lp = -1;
   1335  1.1    darran 			}
   1336  1.1    darran 
   1337  1.1    darran 			switch (cdp->cd_kind) {
   1338  1.1    darran 			case CTF_K_INTEGER:
   1339  1.1    darran 			case CTF_K_FLOAT:
   1340  1.1    darran 			case CTF_K_TYPEDEF:
   1341  1.1    darran 				ctf_decl_sprintf(&cd, "%s", name);
   1342  1.1    darran 				break;
   1343  1.1    darran 			case CTF_K_POINTER:
   1344  1.1    darran 				ctf_decl_sprintf(&cd, "*");
   1345  1.1    darran 				break;
   1346  1.1    darran 			case CTF_K_ARRAY:
   1347  1.1    darran 				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
   1348  1.1    darran 				break;
   1349  1.1    darran 			case CTF_K_FUNCTION:
   1350  1.1    darran 				ctf_decl_sprintf(&cd, "()");
   1351  1.1    darran 				break;
   1352  1.1    darran 			case CTF_K_STRUCT:
   1353  1.1    darran 			case CTF_K_FORWARD:
   1354  1.1    darran 				ctf_decl_sprintf(&cd, "struct %s", name);
   1355  1.1    darran 				break;
   1356  1.1    darran 			case CTF_K_UNION:
   1357  1.1    darran 				ctf_decl_sprintf(&cd, "union %s", name);
   1358  1.1    darran 				break;
   1359  1.1    darran 			case CTF_K_ENUM:
   1360  1.1    darran 				ctf_decl_sprintf(&cd, "enum %s", name);
   1361  1.1    darran 				break;
   1362  1.1    darran 			case CTF_K_VOLATILE:
   1363  1.1    darran 				ctf_decl_sprintf(&cd, "volatile");
   1364  1.1    darran 				break;
   1365  1.1    darran 			case CTF_K_CONST:
   1366  1.1    darran 				ctf_decl_sprintf(&cd, "const");
   1367  1.1    darran 				break;
   1368  1.1    darran 			case CTF_K_RESTRICT:
   1369  1.1    darran 				ctf_decl_sprintf(&cd, "restrict");
   1370  1.1    darran 				break;
   1371  1.1    darran 			}
   1372  1.1    darran 
   1373  1.1    darran 			k = cdp->cd_kind;
   1374  1.1    darran 		}
   1375  1.1    darran 
   1376  1.1    darran 		if (rp == prec)
   1377  1.1    darran 			ctf_decl_sprintf(&cd, ")");
   1378  1.1    darran 	}
   1379  1.1    darran 
   1380  1.1    darran 	ctf_decl_fini(&cd);
   1381  1.1    darran 	return (cd.cd_len);
   1382  1.1    darran }
   1383  1.1    darran 
   1384  1.1    darran static void
   1385  1.1    darran fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
   1386  1.1    darran {
   1387  1.1    darran 	const ushort_t *dp;
   1388  1.1    darran 	fbt_probe_t *fbt = parg;
   1389  1.3    darran 	mod_ctf_t mc;
   1390  1.3    darran 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
   1391  1.1    darran 	int ndx = desc->dtargd_ndx;
   1392  1.1    darran 	int symindx = fbt->fbtp_symindx;
   1393  1.1    darran 	uint32_t *ctfoff;
   1394  1.1    darran 	uint32_t offset;
   1395  1.1    darran 	ushort_t info, kind, n;
   1396  1.3    darran 	int nsyms;
   1397  1.1    darran 
   1398  1.1    darran 	desc->dtargd_ndx = DTRACE_ARGNONE;
   1399  1.1    darran 
   1400  1.1    darran 	/* Get a pointer to the CTF data and it's length. */
   1401  1.3    darran 	if (mod_ctf_get(ctl, &mc) != 0) {
   1402  1.6    darran 		static int report=0;
   1403  1.6    darran 		if (report < 1) {
   1404  1.6    darran 		    report++;
   1405  1.6    darran 		    printf("FBT: Error no CTF section found in module \"%s\"\n",
   1406  1.6    darran 			    ctl->mod_info->mi_name);
   1407  1.6    darran 		}
   1408  1.1    darran 		/* No CTF data? Something wrong? *shrug* */
   1409  1.1    darran 		return;
   1410  1.3    darran 	}
   1411  1.3    darran 
   1412  1.3    darran 	nsyms = (mc.nmap != NULL) ? mc.nmapsize : mc.nsym;
   1413  1.1    darran 
   1414  1.1    darran 	/* Check if this module hasn't been initialised yet. */
   1415  1.3    darran 	if (mc.ctfoffp == NULL) {
   1416  1.1    darran 		/*
   1417  1.1    darran 		 * Initialise the CTF object and function symindx to
   1418  1.1    darran 		 * byte offset array.
   1419  1.1    darran 		 */
   1420  1.3    darran 		if (fbt_ctfoff_init(ctl, &mc) != 0) {
   1421  1.1    darran 			return;
   1422  1.3    darran 		}
   1423  1.1    darran 
   1424  1.1    darran 		/* Initialise the CTF type to byte offset array. */
   1425  1.3    darran 		if (fbt_typoff_init(&mc) != 0) {
   1426  1.1    darran 			return;
   1427  1.3    darran 		}
   1428  1.1    darran 	}
   1429  1.1    darran 
   1430  1.3    darran 	ctfoff = mc.ctfoffp;
   1431  1.1    darran 
   1432  1.3    darran 	if (ctfoff == NULL || mc.typoffp == NULL) {
   1433  1.1    darran 		return;
   1434  1.3    darran 	}
   1435  1.1    darran 
   1436  1.1    darran 	/* Check if the symbol index is out of range. */
   1437  1.3    darran 	if (symindx >= nsyms)
   1438  1.1    darran 		return;
   1439  1.1    darran 
   1440  1.1    darran 	/* Check if the symbol isn't cross-referenced. */
   1441  1.1    darran 	if ((offset = ctfoff[symindx]) == 0xffffffff)
   1442  1.1    darran 		return;
   1443  1.1    darran 
   1444  1.3    darran 	dp = (const ushort_t *)(mc.ctftab + offset + sizeof(ctf_header_t));
   1445  1.1    darran 
   1446  1.1    darran 	info = *dp++;
   1447  1.1    darran 	kind = CTF_INFO_KIND(info);
   1448  1.1    darran 	n = CTF_INFO_VLEN(info);
   1449  1.1    darran 
   1450  1.1    darran 	if (kind == CTF_K_UNKNOWN && n == 0) {
   1451  1.1    darran 		printf("%s(%d): Unknown function!\n",__func__,__LINE__);
   1452  1.1    darran 		return;
   1453  1.1    darran 	}
   1454  1.1    darran 
   1455  1.1    darran 	if (kind != CTF_K_FUNCTION) {
   1456  1.1    darran 		printf("%s(%d): Expected a function!\n",__func__,__LINE__);
   1457  1.1    darran 		return;
   1458  1.1    darran 	}
   1459  1.1    darran 
   1460  1.1    darran 	/* Check if the requested argument doesn't exist. */
   1461  1.1    darran 	if (ndx >= n)
   1462  1.1    darran 		return;
   1463  1.1    darran 
   1464  1.1    darran 	/* Skip the return type and arguments up to the one requested. */
   1465  1.1    darran 	dp += ndx + 1;
   1466  1.1    darran 
   1467  1.3    darran 	if (fbt_type_name(&mc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0) {
   1468  1.1    darran 		desc->dtargd_ndx = ndx;
   1469  1.3    darran 	}
   1470  1.1    darran 
   1471  1.1    darran 	return;
   1472  1.1    darran }
   1473  1.1    darran 
   1474  1.1    darran static void
   1475  1.3    darran fbt_load(void)
   1476  1.1    darran {
   1477  1.1    darran 	/* Default the probe table size if not specified. */
   1478  1.1    darran 	if (fbt_probetab_size == 0)
   1479  1.1    darran 		fbt_probetab_size = FBT_PROBETAB_SIZE;
   1480  1.1    darran 
   1481  1.1    darran 	/* Choose the hash mask for the probe table. */
   1482  1.1    darran 	fbt_probetab_mask = fbt_probetab_size - 1;
   1483  1.1    darran 
   1484  1.1    darran 	/* Allocate memory for the probe table. */
   1485  1.1    darran 	fbt_probetab =
   1486  1.1    darran 	    malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
   1487  1.1    darran 
   1488  1.1    darran 	dtrace_doubletrap_func = fbt_doubletrap;
   1489  1.1    darran 	dtrace_invop_add(fbt_invop);
   1490  1.1    darran 
   1491  1.1    darran 	if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
   1492  1.1    darran 	    NULL, &fbt_pops, NULL, &fbt_id) != 0)
   1493  1.1    darran 		return;
   1494  1.1    darran }
   1495  1.1    darran 
   1496  1.1    darran 
   1497  1.1    darran static int
   1498  1.3    darran fbt_unload(void)
   1499  1.1    darran {
   1500  1.1    darran 	int error = 0;
   1501  1.1    darran 
   1502  1.1    darran 	/* De-register the invalid opcode handler. */
   1503  1.1    darran 	dtrace_invop_remove(fbt_invop);
   1504  1.1    darran 
   1505  1.1    darran 	dtrace_doubletrap_func = NULL;
   1506  1.1    darran 
   1507  1.1    darran 	/* De-register this DTrace provider. */
   1508  1.1    darran 	if ((error = dtrace_unregister(fbt_id)) != 0)
   1509  1.1    darran 		return (error);
   1510  1.1    darran 
   1511  1.1    darran 	/* Free the probe table. */
   1512  1.1    darran 	free(fbt_probetab, M_FBT);
   1513  1.1    darran 	fbt_probetab = NULL;
   1514  1.1    darran 	fbt_probetab_mask = 0;
   1515  1.1    darran 
   1516  1.1    darran 	return (error);
   1517  1.1    darran }
   1518  1.1    darran 
   1519  1.3    darran 
   1520  1.1    darran static int
   1521  1.3    darran fbt_modcmd(modcmd_t cmd, void *data)
   1522  1.1    darran {
   1523  1.3    darran 	int bmajor = -1, cmajor = -1;
   1524  1.1    darran 
   1525  1.3    darran 	switch (cmd) {
   1526  1.3    darran 	case MODULE_CMD_INIT:
   1527  1.3    darran 		fbt_load();
   1528  1.3    darran 		return devsw_attach("fbt", NULL, &bmajor,
   1529  1.3    darran 		    &fbt_cdevsw, &cmajor);
   1530  1.3    darran 	case MODULE_CMD_FINI:
   1531  1.3    darran 		fbt_unload();
   1532  1.3    darran 		return devsw_detach(NULL, &fbt_cdevsw);
   1533  1.1    darran 	default:
   1534  1.3    darran 		return ENOTTY;
   1535  1.1    darran 	}
   1536  1.1    darran }
   1537  1.1    darran 
   1538  1.1    darran static int
   1539  1.3    darran fbt_open(dev_t dev, int flags, int mode, struct lwp *l)
   1540  1.1    darran {
   1541  1.1    darran 	return (0);
   1542  1.1    darran }
   1543  1.1    darran 
   1544  1.3    darran MODULE(MODULE_CLASS_MISC, fbt, "dtrace");
   1545