Home | History | Annotate | Download | only in sys
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #ifndef _SYS_DTRACE_H
     28 #define	_SYS_DTRACE_H
     29 
     30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31 
     32 #ifdef	__cplusplus
     33 extern "C" {
     34 #endif
     35 
     36 /*
     37  * DTrace Dynamic Tracing Software: Kernel Interfaces
     38  *
     39  * Note: The contents of this file are private to the implementation of the
     40  * Solaris system and DTrace subsystem and are subject to change at any time
     41  * without notice.  Applications and drivers using these interfaces will fail
     42  * to run on future releases.  These interfaces should not be used for any
     43  * purpose except those expressly outlined in dtrace(7D) and libdtrace(3LIB).
     44  * Please refer to the "Solaris Dynamic Tracing Guide" for more information.
     45  */
     46 
     47 #ifndef _ASM
     48 
     49 #include <sys/types.h>
     50 #include <sys/modctl.h>
     51 #include <sys/processor.h>
     52 #include <sys/systm.h>
     53 #include <sys/ctf_api.h>
     54 #include <sys/cyclic.h>
     55 #include <sys/int_limits.h>
     56 
     57 /*
     58  * DTrace Universal Constants and Typedefs
     59  */
     60 #define	DTRACE_CPUALL		-1	/* all CPUs */
     61 #define	DTRACE_IDNONE		0	/* invalid probe identifier */
     62 #define	DTRACE_EPIDNONE		0	/* invalid enabled probe identifier */
     63 #define	DTRACE_AGGIDNONE	0	/* invalid aggregation identifier */
     64 #define	DTRACE_AGGVARIDNONE	0	/* invalid aggregation variable ID */
     65 #define	DTRACE_CACHEIDNONE	0	/* invalid predicate cache */
     66 #define	DTRACE_PROVNONE		0	/* invalid provider identifier */
     67 #define	DTRACE_METAPROVNONE	0	/* invalid meta-provider identifier */
     68 #define	DTRACE_ARGNONE		-1	/* invalid argument index */
     69 
     70 #define	DTRACE_PROVNAMELEN	64
     71 #define	DTRACE_MODNAMELEN	64
     72 #define	DTRACE_FUNCNAMELEN	128
     73 #define	DTRACE_NAMELEN		64
     74 #define	DTRACE_FULLNAMELEN	(DTRACE_PROVNAMELEN + DTRACE_MODNAMELEN + \
     75 				DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 4)
     76 #define	DTRACE_ARGTYPELEN	128
     77 
     78 typedef uint32_t dtrace_id_t;		/* probe identifier */
     79 typedef uint32_t dtrace_epid_t;		/* enabled probe identifier */
     80 typedef uint32_t dtrace_aggid_t;	/* aggregation identifier */
     81 typedef int64_t dtrace_aggvarid_t;	/* aggregation variable identifier */
     82 typedef uint16_t dtrace_actkind_t;	/* action kind */
     83 typedef int64_t dtrace_optval_t;	/* option value */
     84 typedef uint32_t dtrace_cacheid_t;	/* predicate cache identifier */
     85 
     86 typedef enum dtrace_probespec {
     87 	DTRACE_PROBESPEC_NONE = -1,
     88 	DTRACE_PROBESPEC_PROVIDER = 0,
     89 	DTRACE_PROBESPEC_MOD,
     90 	DTRACE_PROBESPEC_FUNC,
     91 	DTRACE_PROBESPEC_NAME
     92 } dtrace_probespec_t;
     93 
     94 /*
     95  * DTrace Intermediate Format (DIF)
     96  *
     97  * The following definitions describe the DTrace Intermediate Format (DIF), a
     98  * a RISC-like instruction set and program encoding used to represent
     99  * predicates and actions that can be bound to DTrace probes.  The constants
    100  * below defining the number of available registers are suggested minimums; the
    101  * compiler should use DTRACEIOC_CONF to dynamically obtain the number of
    102  * registers provided by the current DTrace implementation.
    103  */
    104 #define	DIF_VERSION_1	1		/* DIF version 1: Solaris 10 Beta */
    105 #define	DIF_VERSION_2	2		/* DIF version 2: Solaris 10 FCS */
    106 #define	DIF_VERSION	DIF_VERSION_2	/* latest DIF instruction set version */
    107 #define	DIF_DIR_NREGS	8		/* number of DIF integer registers */
    108 #define	DIF_DTR_NREGS	8		/* number of DIF tuple registers */
    109 
    110 #define	DIF_OP_OR	1		/* or	r1, r2, rd */
    111 #define	DIF_OP_XOR	2		/* xor	r1, r2, rd */
    112 #define	DIF_OP_AND	3		/* and	r1, r2, rd */
    113 #define	DIF_OP_SLL	4		/* sll	r1, r2, rd */
    114 #define	DIF_OP_SRL	5		/* srl	r1, r2, rd */
    115 #define	DIF_OP_SUB	6		/* sub	r1, r2, rd */
    116 #define	DIF_OP_ADD	7		/* add	r1, r2, rd */
    117 #define	DIF_OP_MUL	8		/* mul	r1, r2, rd */
    118 #define	DIF_OP_SDIV	9		/* sdiv	r1, r2, rd */
    119 #define	DIF_OP_UDIV	10		/* udiv r1, r2, rd */
    120 #define	DIF_OP_SREM	11		/* srem r1, r2, rd */
    121 #define	DIF_OP_UREM	12		/* urem r1, r2, rd */
    122 #define	DIF_OP_NOT	13		/* not	r1, rd */
    123 #define	DIF_OP_MOV	14		/* mov	r1, rd */
    124 #define	DIF_OP_CMP	15		/* cmp	r1, r2 */
    125 #define	DIF_OP_TST	16		/* tst  r1 */
    126 #define	DIF_OP_BA	17		/* ba	label */
    127 #define	DIF_OP_BE	18		/* be	label */
    128 #define	DIF_OP_BNE	19		/* bne	label */
    129 #define	DIF_OP_BG	20		/* bg	label */
    130 #define	DIF_OP_BGU	21		/* bgu	label */
    131 #define	DIF_OP_BGE	22		/* bge	label */
    132 #define	DIF_OP_BGEU	23		/* bgeu	label */
    133 #define	DIF_OP_BL	24		/* bl	label */
    134 #define	DIF_OP_BLU	25		/* blu	label */
    135 #define	DIF_OP_BLE	26		/* ble	label */
    136 #define	DIF_OP_BLEU	27		/* bleu	label */
    137 #define	DIF_OP_LDSB	28		/* ldsb	[r1], rd */
    138 #define	DIF_OP_LDSH	29		/* ldsh	[r1], rd */
    139 #define	DIF_OP_LDSW	30		/* ldsw [r1], rd */
    140 #define	DIF_OP_LDUB	31		/* ldub	[r1], rd */
    141 #define	DIF_OP_LDUH	32		/* lduh	[r1], rd */
    142 #define	DIF_OP_LDUW	33		/* lduw	[r1], rd */
    143 #define	DIF_OP_LDX	34		/* ldx	[r1], rd */
    144 #define	DIF_OP_RET	35		/* ret	rd */
    145 #define	DIF_OP_NOP	36		/* nop */
    146 #define	DIF_OP_SETX	37		/* setx	intindex, rd */
    147 #define	DIF_OP_SETS	38		/* sets strindex, rd */
    148 #define	DIF_OP_SCMP	39		/* scmp	r1, r2 */
    149 #define	DIF_OP_LDGA	40		/* ldga	var, ri, rd */
    150 #define	DIF_OP_LDGS	41		/* ldgs var, rd */
    151 #define	DIF_OP_STGS	42		/* stgs var, rs */
    152 #define	DIF_OP_LDTA	43		/* ldta var, ri, rd */
    153 #define	DIF_OP_LDTS	44		/* ldts var, rd */
    154 #define	DIF_OP_STTS	45		/* stts var, rs */
    155 #define	DIF_OP_SRA	46		/* sra	r1, r2, rd */
    156 #define	DIF_OP_CALL	47		/* call	subr, rd */
    157 #define	DIF_OP_PUSHTR	48		/* pushtr type, rs, rr */
    158 #define	DIF_OP_PUSHTV	49		/* pushtv type, rs, rv */
    159 #define	DIF_OP_POPTS	50		/* popts */
    160 #define	DIF_OP_FLUSHTS	51		/* flushts */
    161 #define	DIF_OP_LDGAA	52		/* ldgaa var, rd */
    162 #define	DIF_OP_LDTAA	53		/* ldtaa var, rd */
    163 #define	DIF_OP_STGAA	54		/* stgaa var, rs */
    164 #define	DIF_OP_STTAA	55		/* sttaa var, rs */
    165 #define	DIF_OP_LDLS	56		/* ldls	var, rd */
    166 #define	DIF_OP_STLS	57		/* stls	var, rs */
    167 #define	DIF_OP_ALLOCS	58		/* allocs r1, rd */
    168 #define	DIF_OP_COPYS	59		/* copys  r1, r2, rd */
    169 #define	DIF_OP_STB	60		/* stb	r1, [rd] */
    170 #define	DIF_OP_STH	61		/* sth	r1, [rd] */
    171 #define	DIF_OP_STW	62		/* stw	r1, [rd] */
    172 #define	DIF_OP_STX	63		/* stx	r1, [rd] */
    173 #define	DIF_OP_ULDSB	64		/* uldsb [r1], rd */
    174 #define	DIF_OP_ULDSH	65		/* uldsh [r1], rd */
    175 #define	DIF_OP_ULDSW	66		/* uldsw [r1], rd */
    176 #define	DIF_OP_ULDUB	67		/* uldub [r1], rd */
    177 #define	DIF_OP_ULDUH	68		/* ulduh [r1], rd */
    178 #define	DIF_OP_ULDUW	69		/* ulduw [r1], rd */
    179 #define	DIF_OP_ULDX	70		/* uldx  [r1], rd */
    180 #define	DIF_OP_RLDSB	71		/* rldsb [r1], rd */
    181 #define	DIF_OP_RLDSH	72		/* rldsh [r1], rd */
    182 #define	DIF_OP_RLDSW	73		/* rldsw [r1], rd */
    183 #define	DIF_OP_RLDUB	74		/* rldub [r1], rd */
    184 #define	DIF_OP_RLDUH	75		/* rlduh [r1], rd */
    185 #define	DIF_OP_RLDUW	76		/* rlduw [r1], rd */
    186 #define	DIF_OP_RLDX	77		/* rldx  [r1], rd */
    187 #define	DIF_OP_XLATE	78		/* xlate xlrindex, rd */
    188 #define	DIF_OP_XLARG	79		/* xlarg xlrindex, rd */
    189 
    190 #define	DIF_INTOFF_MAX		0xffff	/* highest integer table offset */
    191 #define	DIF_STROFF_MAX		0xffff	/* highest string table offset */
    192 #define	DIF_REGISTER_MAX	0xff	/* highest register number */
    193 #define	DIF_VARIABLE_MAX	0xffff	/* highest variable identifier */
    194 #define	DIF_SUBROUTINE_MAX	0xffff	/* highest subroutine code */
    195 
    196 #define	DIF_VAR_ARRAY_MIN	0x0000	/* lowest numbered array variable */
    197 #define	DIF_VAR_ARRAY_UBASE	0x0080	/* lowest user-defined array */
    198 #define	DIF_VAR_ARRAY_MAX	0x00ff	/* highest numbered array variable */
    199 
    200 #define	DIF_VAR_OTHER_MIN	0x0100	/* lowest numbered scalar or assc */
    201 #define	DIF_VAR_OTHER_UBASE	0x0500	/* lowest user-defined scalar or assc */
    202 #define	DIF_VAR_OTHER_MAX	0xffff	/* highest numbered scalar or assc */
    203 
    204 #define	DIF_VAR_ARGS		0x0000	/* arguments array */
    205 #define	DIF_VAR_REGS		0x0001	/* registers array */
    206 #define	DIF_VAR_UREGS		0x0002	/* user registers array */
    207 #define	DIF_VAR_CURTHREAD	0x0100	/* thread pointer */
    208 #define	DIF_VAR_TIMESTAMP	0x0101	/* timestamp */
    209 #define	DIF_VAR_VTIMESTAMP	0x0102	/* virtual timestamp */
    210 #define	DIF_VAR_IPL		0x0103	/* interrupt priority level */
    211 #define	DIF_VAR_EPID		0x0104	/* enabled probe ID */
    212 #define	DIF_VAR_ID		0x0105	/* probe ID */
    213 #define	DIF_VAR_ARG0		0x0106	/* first argument */
    214 #define	DIF_VAR_ARG1		0x0107	/* second argument */
    215 #define	DIF_VAR_ARG2		0x0108	/* third argument */
    216 #define	DIF_VAR_ARG3		0x0109	/* fourth argument */
    217 #define	DIF_VAR_ARG4		0x010a	/* fifth argument */
    218 #define	DIF_VAR_ARG5		0x010b	/* sixth argument */
    219 #define	DIF_VAR_ARG6		0x010c	/* seventh argument */
    220 #define	DIF_VAR_ARG7		0x010d	/* eighth argument */
    221 #define	DIF_VAR_ARG8		0x010e	/* ninth argument */
    222 #define	DIF_VAR_ARG9		0x010f	/* tenth argument */
    223 #define	DIF_VAR_STACKDEPTH	0x0110	/* stack depth */
    224 #define	DIF_VAR_CALLER		0x0111	/* caller */
    225 #define	DIF_VAR_PROBEPROV	0x0112	/* probe provider */
    226 #define	DIF_VAR_PROBEMOD	0x0113	/* probe module */
    227 #define	DIF_VAR_PROBEFUNC	0x0114	/* probe function */
    228 #define	DIF_VAR_PROBENAME	0x0115	/* probe name */
    229 #define	DIF_VAR_PID		0x0116	/* process ID */
    230 #define	DIF_VAR_TID		0x0117	/* (per-process) thread ID */
    231 #define	DIF_VAR_EXECNAME	0x0118	/* name of executable */
    232 #define	DIF_VAR_ZONENAME	0x0119	/* zone name associated with process */
    233 #define	DIF_VAR_WALLTIMESTAMP	0x011a	/* wall-clock timestamp */
    234 #define	DIF_VAR_USTACKDEPTH	0x011b	/* user-land stack depth */
    235 #define	DIF_VAR_UCALLER		0x011c	/* user-level caller */
    236 #define	DIF_VAR_PPID		0x011d	/* parent process ID */
    237 #define	DIF_VAR_UID		0x011e	/* process user ID */
    238 #define	DIF_VAR_GID		0x011f	/* process group ID */
    239 #define	DIF_VAR_ERRNO		0x0120	/* thread errno */
    240 
    241 #define	DIF_SUBR_RAND			0
    242 #define	DIF_SUBR_MUTEX_OWNED		1
    243 #define	DIF_SUBR_MUTEX_OWNER		2
    244 #define	DIF_SUBR_MUTEX_TYPE_ADAPTIVE	3
    245 #define	DIF_SUBR_MUTEX_TYPE_SPIN	4
    246 #define	DIF_SUBR_RW_READ_HELD		5
    247 #define	DIF_SUBR_RW_WRITE_HELD		6
    248 #define	DIF_SUBR_RW_ISWRITER		7
    249 #define	DIF_SUBR_COPYIN			8
    250 #define	DIF_SUBR_COPYINSTR		9
    251 #define	DIF_SUBR_SPECULATION		10
    252 #define	DIF_SUBR_PROGENYOF		11
    253 #define	DIF_SUBR_STRLEN			12
    254 #define	DIF_SUBR_COPYOUT		13
    255 #define	DIF_SUBR_COPYOUTSTR		14
    256 #define	DIF_SUBR_ALLOCA			15
    257 #define	DIF_SUBR_BCOPY			16
    258 #define	DIF_SUBR_COPYINTO		17
    259 #define	DIF_SUBR_MSGDSIZE		18
    260 #define	DIF_SUBR_MSGSIZE		19
    261 #define	DIF_SUBR_GETMAJOR		20
    262 #define	DIF_SUBR_GETMINOR		21
    263 #define	DIF_SUBR_DDI_PATHNAME		22
    264 #define	DIF_SUBR_STRJOIN		23
    265 #define	DIF_SUBR_LLTOSTR		24
    266 #define	DIF_SUBR_BASENAME		25
    267 #define	DIF_SUBR_DIRNAME		26
    268 #define	DIF_SUBR_CLEANPATH		27
    269 #define	DIF_SUBR_STRCHR			28
    270 #define	DIF_SUBR_STRRCHR		29
    271 #define	DIF_SUBR_STRSTR			30
    272 #define	DIF_SUBR_STRTOK			31
    273 #define	DIF_SUBR_SUBSTR			32
    274 #define	DIF_SUBR_INDEX			33
    275 #define	DIF_SUBR_RINDEX			34
    276 #define	DIF_SUBR_HTONS			35
    277 #define	DIF_SUBR_HTONL			36
    278 #define	DIF_SUBR_HTONLL			37
    279 #define	DIF_SUBR_NTOHS			38
    280 #define	DIF_SUBR_NTOHL			39
    281 #define	DIF_SUBR_NTOHLL			40
    282 #define	DIF_SUBR_INET_NTOP		41
    283 #define	DIF_SUBR_INET_NTOA		42
    284 #define	DIF_SUBR_INET_NTOA6		43
    285 
    286 #define	DIF_SUBR_MAX			43	/* max subroutine value */
    287 
    288 typedef uint32_t dif_instr_t;
    289 
    290 #define	DIF_INSTR_OP(i)			(((i) >> 24) & 0xff)
    291 #define	DIF_INSTR_R1(i)			(((i) >> 16) & 0xff)
    292 #define	DIF_INSTR_R2(i)			(((i) >>  8) & 0xff)
    293 #define	DIF_INSTR_RD(i)			((i) & 0xff)
    294 #define	DIF_INSTR_RS(i)			((i) & 0xff)
    295 #define	DIF_INSTR_LABEL(i)		((i) & 0xffffff)
    296 #define	DIF_INSTR_VAR(i)		(((i) >>  8) & 0xffff)
    297 #define	DIF_INSTR_INTEGER(i)		(((i) >>  8) & 0xffff)
    298 #define	DIF_INSTR_STRING(i)		(((i) >>  8) & 0xffff)
    299 #define	DIF_INSTR_SUBR(i)		(((i) >>  8) & 0xffff)
    300 #define	DIF_INSTR_TYPE(i)		(((i) >> 16) & 0xff)
    301 #define	DIF_INSTR_XLREF(i)		(((i) >>  8) & 0xffff)
    302 
    303 #define	DIF_INSTR_FMT(op, r1, r2, d) \
    304 	(((op) << 24) | ((r1) << 16) | ((r2) << 8) | (d))
    305 
    306 #define	DIF_INSTR_NOT(r1, d)		(DIF_INSTR_FMT(DIF_OP_NOT, r1, 0, d))
    307 #define	DIF_INSTR_MOV(r1, d)		(DIF_INSTR_FMT(DIF_OP_MOV, r1, 0, d))
    308 #define	DIF_INSTR_CMP(op, r1, r2)	(DIF_INSTR_FMT(op, r1, r2, 0))
    309 #define	DIF_INSTR_TST(r1)		(DIF_INSTR_FMT(DIF_OP_TST, r1, 0, 0))
    310 #define	DIF_INSTR_BRANCH(op, label)	(((op) << 24) | (label))
    311 #define	DIF_INSTR_LOAD(op, r1, d)	(DIF_INSTR_FMT(op, r1, 0, d))
    312 #define	DIF_INSTR_STORE(op, r1, d)	(DIF_INSTR_FMT(op, r1, 0, d))
    313 #define	DIF_INSTR_SETX(i, d)		((DIF_OP_SETX << 24) | ((i) << 8) | (d))
    314 #define	DIF_INSTR_SETS(s, d)		((DIF_OP_SETS << 24) | ((s) << 8) | (d))
    315 #define	DIF_INSTR_RET(d)		(DIF_INSTR_FMT(DIF_OP_RET, 0, 0, d))
    316 #define	DIF_INSTR_NOP			(DIF_OP_NOP << 24)
    317 #define	DIF_INSTR_LDA(op, v, r, d)	(DIF_INSTR_FMT(op, v, r, d))
    318 #define	DIF_INSTR_LDV(op, v, d)		(((op) << 24) | ((v) << 8) | (d))
    319 #define	DIF_INSTR_STV(op, v, rs)	(((op) << 24) | ((v) << 8) | (rs))
    320 #define	DIF_INSTR_CALL(s, d)		((DIF_OP_CALL << 24) | ((s) << 8) | (d))
    321 #define	DIF_INSTR_PUSHTS(op, t, r2, rs)	(DIF_INSTR_FMT(op, t, r2, rs))
    322 #define	DIF_INSTR_POPTS			(DIF_OP_POPTS << 24)
    323 #define	DIF_INSTR_FLUSHTS		(DIF_OP_FLUSHTS << 24)
    324 #define	DIF_INSTR_ALLOCS(r1, d)		(DIF_INSTR_FMT(DIF_OP_ALLOCS, r1, 0, d))
    325 #define	DIF_INSTR_COPYS(r1, r2, d)	(DIF_INSTR_FMT(DIF_OP_COPYS, r1, r2, d))
    326 #define	DIF_INSTR_XLATE(op, r, d)	(((op) << 24) | ((r) << 8) | (d))
    327 
    328 #define	DIF_REG_R0	0		/* %r0 is always set to zero */
    329 
    330 /*
    331  * A DTrace Intermediate Format Type (DIF Type) is used to represent the types
    332  * of variables, function and associative array arguments, and the return type
    333  * for each DIF object (shown below).  It contains a description of the type,
    334  * its size in bytes, and a module identifier.
    335  */
    336 typedef struct dtrace_diftype {
    337 	uint8_t dtdt_kind;		/* type kind (see below) */
    338 	uint8_t dtdt_ckind;		/* type kind in CTF */
    339 	uint8_t dtdt_flags;		/* type flags (see below) */
    340 	uint8_t dtdt_pad;		/* reserved for future use */
    341 	uint32_t dtdt_size;		/* type size in bytes (unless string) */
    342 } dtrace_diftype_t;
    343 
    344 #define	DIF_TYPE_CTF		0	/* type is a CTF type */
    345 #define	DIF_TYPE_STRING		1	/* type is a D string */
    346 
    347 #define	DIF_TF_BYREF		0x1	/* type is passed by reference */
    348 
    349 /*
    350  * A DTrace Intermediate Format variable record is used to describe each of the
    351  * variables referenced by a given DIF object.  It contains an integer variable
    352  * identifier along with variable scope and properties, as shown below.  The
    353  * size of this structure must be sizeof (int) aligned.
    354  */
    355 typedef struct dtrace_difv {
    356 	uint32_t dtdv_name;		/* variable name index in dtdo_strtab */
    357 	uint32_t dtdv_id;		/* variable reference identifier */
    358 	uint8_t dtdv_kind;		/* variable kind (see below) */
    359 	uint8_t dtdv_scope;		/* variable scope (see below) */
    360 	uint16_t dtdv_flags;		/* variable flags (see below) */
    361 	dtrace_diftype_t dtdv_type;	/* variable type (see above) */
    362 } dtrace_difv_t;
    363 
    364 #define	DIFV_KIND_ARRAY		0	/* variable is an array of quantities */
    365 #define	DIFV_KIND_SCALAR	1	/* variable is a scalar quantity */
    366 
    367 #define	DIFV_SCOPE_GLOBAL	0	/* variable has global scope */
    368 #define	DIFV_SCOPE_THREAD	1	/* variable has thread scope */
    369 #define	DIFV_SCOPE_LOCAL	2	/* variable has local scope */
    370 
    371 #define	DIFV_F_REF		0x1	/* variable is referenced by DIFO */
    372 #define	DIFV_F_MOD		0x2	/* variable is written by DIFO */
    373 
    374 /*
    375  * DTrace Actions
    376  *
    377  * The upper byte determines the class of the action; the low bytes determines
    378  * the specific action within that class.  The classes of actions are as
    379  * follows:
    380  *
    381  *   [ no class ]                  <= May record process- or kernel-related data
    382  *   DTRACEACT_PROC                <= Only records process-related data
    383  *   DTRACEACT_PROC_DESTRUCTIVE    <= Potentially destructive to processes
    384  *   DTRACEACT_KERNEL              <= Only records kernel-related data
    385  *   DTRACEACT_KERNEL_DESTRUCTIVE  <= Potentially destructive to the kernel
    386  *   DTRACEACT_SPECULATIVE         <= Speculation-related action
    387  *   DTRACEACT_AGGREGATION         <= Aggregating action
    388  */
    389 #define	DTRACEACT_NONE			0	/* no action */
    390 #define	DTRACEACT_DIFEXPR		1	/* action is DIF expression */
    391 #define	DTRACEACT_EXIT			2	/* exit() action */
    392 #define	DTRACEACT_PRINTF		3	/* printf() action */
    393 #define	DTRACEACT_PRINTA		4	/* printa() action */
    394 #define	DTRACEACT_LIBACT		5	/* library-controlled action */
    395 
    396 #define	DTRACEACT_PROC			0x0100
    397 #define	DTRACEACT_USTACK		(DTRACEACT_PROC + 1)
    398 #define	DTRACEACT_JSTACK		(DTRACEACT_PROC + 2)
    399 #define	DTRACEACT_USYM			(DTRACEACT_PROC + 3)
    400 #define	DTRACEACT_UMOD			(DTRACEACT_PROC + 4)
    401 #define	DTRACEACT_UADDR			(DTRACEACT_PROC + 5)
    402 
    403 #define	DTRACEACT_PROC_DESTRUCTIVE	0x0200
    404 #define	DTRACEACT_STOP			(DTRACEACT_PROC_DESTRUCTIVE + 1)
    405 #define	DTRACEACT_RAISE			(DTRACEACT_PROC_DESTRUCTIVE + 2)
    406 #define	DTRACEACT_SYSTEM		(DTRACEACT_PROC_DESTRUCTIVE + 3)
    407 #define	DTRACEACT_FREOPEN		(DTRACEACT_PROC_DESTRUCTIVE + 4)
    408 
    409 #define	DTRACEACT_PROC_CONTROL		0x0300
    410 
    411 #define	DTRACEACT_KERNEL		0x0400
    412 #define	DTRACEACT_STACK			(DTRACEACT_KERNEL + 1)
    413 #define	DTRACEACT_SYM			(DTRACEACT_KERNEL + 2)
    414 #define	DTRACEACT_MOD			(DTRACEACT_KERNEL + 3)
    415 
    416 #define	DTRACEACT_KERNEL_DESTRUCTIVE	0x0500
    417 #define	DTRACEACT_BREAKPOINT		(DTRACEACT_KERNEL_DESTRUCTIVE + 1)
    418 #define	DTRACEACT_PANIC			(DTRACEACT_KERNEL_DESTRUCTIVE + 2)
    419 #define	DTRACEACT_CHILL			(DTRACEACT_KERNEL_DESTRUCTIVE + 3)
    420 
    421 #define	DTRACEACT_SPECULATIVE		0x0600
    422 #define	DTRACEACT_SPECULATE		(DTRACEACT_SPECULATIVE + 1)
    423 #define	DTRACEACT_COMMIT		(DTRACEACT_SPECULATIVE + 2)
    424 #define	DTRACEACT_DISCARD		(DTRACEACT_SPECULATIVE + 3)
    425 
    426 #define	DTRACEACT_CLASS(x)		((x) & 0xff00)
    427 
    428 #define	DTRACEACT_ISDESTRUCTIVE(x)	\
    429 	(DTRACEACT_CLASS(x) == DTRACEACT_PROC_DESTRUCTIVE || \
    430 	DTRACEACT_CLASS(x) == DTRACEACT_KERNEL_DESTRUCTIVE)
    431 
    432 #define	DTRACEACT_ISSPECULATIVE(x)	\
    433 	(DTRACEACT_CLASS(x) == DTRACEACT_SPECULATIVE)
    434 
    435 #define	DTRACEACT_ISPRINTFLIKE(x)	\
    436 	((x) == DTRACEACT_PRINTF || (x) == DTRACEACT_PRINTA || \
    437 	(x) == DTRACEACT_SYSTEM || (x) == DTRACEACT_FREOPEN)
    438 
    439 /*
    440  * DTrace Aggregating Actions
    441  *
    442  * These are functions f(x) for which the following is true:
    443  *
    444  *    f(f(x_0) U f(x_1) U ... U f(x_n)) = f(x_0 U x_1 U ... U x_n)
    445  *
    446  * where x_n is a set of arbitrary data.  Aggregating actions are in their own
    447  * DTrace action class, DTTRACEACT_AGGREGATION.  The macros provided here allow
    448  * for easier processing of the aggregation argument and data payload for a few
    449  * aggregating actions (notably:  quantize(), lquantize(), and ustack()).
    450  */
    451 #define	DTRACEACT_AGGREGATION		0x0700
    452 #define	DTRACEAGG_COUNT			(DTRACEACT_AGGREGATION + 1)
    453 #define	DTRACEAGG_MIN			(DTRACEACT_AGGREGATION + 2)
    454 #define	DTRACEAGG_MAX			(DTRACEACT_AGGREGATION + 3)
    455 #define	DTRACEAGG_AVG			(DTRACEACT_AGGREGATION + 4)
    456 #define	DTRACEAGG_SUM			(DTRACEACT_AGGREGATION + 5)
    457 #define	DTRACEAGG_STDDEV		(DTRACEACT_AGGREGATION + 6)
    458 #define	DTRACEAGG_QUANTIZE		(DTRACEACT_AGGREGATION + 7)
    459 #define	DTRACEAGG_LQUANTIZE		(DTRACEACT_AGGREGATION + 8)
    460 
    461 #define	DTRACEACT_ISAGG(x)		\
    462 	(DTRACEACT_CLASS(x) == DTRACEACT_AGGREGATION)
    463 
    464 #define	DTRACE_QUANTIZE_NBUCKETS	\
    465 	(((sizeof (uint64_t) * NBBY) - 1) * 2 + 1)
    466 
    467 #define	DTRACE_QUANTIZE_ZEROBUCKET	((sizeof (uint64_t) * NBBY) - 1)
    468 
    469 #define	DTRACE_QUANTIZE_BUCKETVAL(buck)					\
    470 	(int64_t)((buck) < DTRACE_QUANTIZE_ZEROBUCKET ?			\
    471 	-(1LL << (DTRACE_QUANTIZE_ZEROBUCKET - 1 - (buck))) :		\
    472 	(buck) == DTRACE_QUANTIZE_ZEROBUCKET ? 0 :			\
    473 	1LL << ((buck) - DTRACE_QUANTIZE_ZEROBUCKET - 1))
    474 
    475 #define	DTRACE_LQUANTIZE_STEPSHIFT		48
    476 #define	DTRACE_LQUANTIZE_STEPMASK		((uint64_t)UINT16_MAX << 48)
    477 #define	DTRACE_LQUANTIZE_LEVELSHIFT		32
    478 #define	DTRACE_LQUANTIZE_LEVELMASK		((uint64_t)UINT16_MAX << 32)
    479 #define	DTRACE_LQUANTIZE_BASESHIFT		0
    480 #define	DTRACE_LQUANTIZE_BASEMASK		UINT32_MAX
    481 
    482 #define	DTRACE_LQUANTIZE_STEP(x)		\
    483 	(uint16_t)(((x) & DTRACE_LQUANTIZE_STEPMASK) >> \
    484 	DTRACE_LQUANTIZE_STEPSHIFT)
    485 
    486 #define	DTRACE_LQUANTIZE_LEVELS(x)		\
    487 	(uint16_t)(((x) & DTRACE_LQUANTIZE_LEVELMASK) >> \
    488 	DTRACE_LQUANTIZE_LEVELSHIFT)
    489 
    490 #define	DTRACE_LQUANTIZE_BASE(x)		\
    491 	(int32_t)(((x) & DTRACE_LQUANTIZE_BASEMASK) >> \
    492 	DTRACE_LQUANTIZE_BASESHIFT)
    493 
    494 #define	DTRACE_USTACK_NFRAMES(x)	(uint32_t)((x) & UINT32_MAX)
    495 #define	DTRACE_USTACK_STRSIZE(x)	(uint32_t)((x) >> 32)
    496 #define	DTRACE_USTACK_ARG(x, y)		\
    497 	((((uint64_t)(y)) << 32) | ((x) & UINT32_MAX))
    498 
    499 #ifndef _LP64
    500 #ifndef _LITTLE_ENDIAN
    501 #define	DTRACE_PTR(type, name)	uint32_t name##pad; type *name
    502 #else
    503 #define	DTRACE_PTR(type, name)	type *name; uint32_t name##pad
    504 #endif
    505 #else
    506 #define	DTRACE_PTR(type, name)	type *name
    507 #endif
    508 
    509 /*
    510  * DTrace Object Format (DOF)
    511  *
    512  * DTrace programs can be persistently encoded in the DOF format so that they
    513  * may be embedded in other programs (for example, in an ELF file) or in the
    514  * dtrace driver configuration file for use in anonymous tracing.  The DOF
    515  * format is versioned and extensible so that it can be revised and so that
    516  * internal data structures can be modified or extended compatibly.  All DOF
    517  * structures use fixed-size types, so the 32-bit and 64-bit representations
    518  * are identical and consumers can use either data model transparently.
    519  *
    520  * The file layout is structured as follows:
    521  *
    522  * +---------------+-------------------+----- ... ----+---- ... ------+
    523  * |   dof_hdr_t   |  dof_sec_t[ ... ] |   loadable   | non-loadable  |
    524  * | (file header) | (section headers) | section data | section data  |
    525  * +---------------+-------------------+----- ... ----+---- ... ------+
    526  * |<------------ dof_hdr.dofh_loadsz --------------->|               |
    527  * |<------------ dof_hdr.dofh_filesz ------------------------------->|
    528  *
    529  * The file header stores meta-data including a magic number, data model for
    530  * the instrumentation, data encoding, and properties of the DIF code within.
    531  * The header describes its own size and the size of the section headers.  By
    532  * convention, an array of section headers follows the file header, and then
    533  * the data for all loadable sections and unloadable sections.  This permits
    534  * consumer code to easily download the headers and all loadable data into the
    535  * DTrace driver in one contiguous chunk, omitting other extraneous sections.
    536  *
    537  * The section headers describe the size, offset, alignment, and section type
    538  * for each section.  Sections are described using a set of #defines that tell
    539  * the consumer what kind of data is expected.  Sections can contain links to
    540  * other sections by storing a dof_secidx_t, an index into the section header
    541  * array, inside of the section data structures.  The section header includes
    542  * an entry size so that sections with data arrays can grow their structures.
    543  *
    544  * The DOF data itself can contain many snippets of DIF (i.e. >1 DIFOs), which
    545  * are represented themselves as a collection of related DOF sections.  This
    546  * permits us to change the set of sections associated with a DIFO over time,
    547  * and also permits us to encode DIFOs that contain different sets of sections.
    548  * When a DOF section wants to refer to a DIFO, it stores the dof_secidx_t of a
    549  * section of type DOF_SECT_DIFOHDR.  This section's data is then an array of
    550  * dof_secidx_t's which in turn denote the sections associated with this DIFO.
    551  *
    552  * This loose coupling of the file structure (header and sections) to the
    553  * structure of the DTrace program itself (ECB descriptions, action
    554  * descriptions, and DIFOs) permits activities such as relocation processing
    555  * to occur in a single pass without having to understand D program structure.
    556  *
    557  * Finally, strings are always stored in ELF-style string tables along with a
    558  * string table section index and string table offset.  Therefore strings in
    559  * DOF are always arbitrary-length and not bound to the current implementation.
    560  */
    561 
    562 #define	DOF_ID_SIZE	16	/* total size of dofh_ident[] in bytes */
    563 
    564 typedef struct dof_hdr {
    565 	uint8_t dofh_ident[DOF_ID_SIZE]; /* identification bytes (see below) */
    566 	uint32_t dofh_flags;		/* file attribute flags (if any) */
    567 	uint32_t dofh_hdrsize;		/* size of file header in bytes */
    568 	uint32_t dofh_secsize;		/* size of section header in bytes */
    569 	uint32_t dofh_secnum;		/* number of section headers */
    570 	uint64_t dofh_secoff;		/* file offset of section headers */
    571 	uint64_t dofh_loadsz;		/* file size of loadable portion */
    572 	uint64_t dofh_filesz;		/* file size of entire DOF file */
    573 	uint64_t dofh_pad;		/* reserved for future use */
    574 } dof_hdr_t;
    575 
    576 #define	DOF_ID_MAG0	0	/* first byte of magic number */
    577 #define	DOF_ID_MAG1	1	/* second byte of magic number */
    578 #define	DOF_ID_MAG2	2	/* third byte of magic number */
    579 #define	DOF_ID_MAG3	3	/* fourth byte of magic number */
    580 #define	DOF_ID_MODEL	4	/* DOF data model (see below) */
    581 #define	DOF_ID_ENCODING	5	/* DOF data encoding (see below) */
    582 #define	DOF_ID_VERSION	6	/* DOF file format major version (see below) */
    583 #define	DOF_ID_DIFVERS	7	/* DIF instruction set version */
    584 #define	DOF_ID_DIFIREG	8	/* DIF integer registers used by compiler */
    585 #define	DOF_ID_DIFTREG	9	/* DIF tuple registers used by compiler */
    586 #define	DOF_ID_PAD	10	/* start of padding bytes (all zeroes) */
    587 
    588 #define	DOF_MAG_MAG0	0x7F	/* DOF_ID_MAG[0-3] */
    589 #define	DOF_MAG_MAG1	'D'
    590 #define	DOF_MAG_MAG2	'O'
    591 #define	DOF_MAG_MAG3	'F'
    592 
    593 #define	DOF_MAG_STRING	"\177DOF"
    594 #define	DOF_MAG_STRLEN	4
    595 
    596 #define	DOF_MODEL_NONE	0	/* DOF_ID_MODEL */
    597 #define	DOF_MODEL_ILP32	1
    598 #define	DOF_MODEL_LP64	2
    599 
    600 #ifdef _LP64
    601 #define	DOF_MODEL_NATIVE	DOF_MODEL_LP64
    602 #else
    603 #define	DOF_MODEL_NATIVE	DOF_MODEL_ILP32
    604 #endif
    605 
    606 #define	DOF_ENCODE_NONE	0	/* DOF_ID_ENCODING */
    607 #define	DOF_ENCODE_LSB	1
    608 #define	DOF_ENCODE_MSB	2
    609 
    610 #ifdef _BIG_ENDIAN
    611 #define	DOF_ENCODE_NATIVE	DOF_ENCODE_MSB
    612 #else
    613 #define	DOF_ENCODE_NATIVE	DOF_ENCODE_LSB
    614 #endif
    615 
    616 #define	DOF_VERSION_1	1	/* DOF version 1: Solaris 10 FCS */
    617 #define	DOF_VERSION_2	2	/* DOF version 2: Solaris Express 6/06 */
    618 #define	DOF_VERSION	DOF_VERSION_2	/* Latest DOF version */
    619 
    620 #define	DOF_FL_VALID	0	/* mask of all valid dofh_flags bits */
    621 
    622 typedef uint32_t dof_secidx_t;	/* section header table index type */
    623 typedef uint32_t dof_stridx_t;	/* string table index type */
    624 
    625 #define	DOF_SECIDX_NONE	(-1U)	/* null value for section indices */
    626 #define	DOF_STRIDX_NONE	(-1U)	/* null value for string indices */
    627 
    628 typedef struct dof_sec {
    629 	uint32_t dofs_type;	/* section type (see below) */
    630 	uint32_t dofs_align;	/* section data memory alignment */
    631 	uint32_t dofs_flags;	/* section flags (if any) */
    632 	uint32_t dofs_entsize;	/* size of section entry (if table) */
    633 	uint64_t dofs_offset;	/* offset of section data within file */
    634 	uint64_t dofs_size;	/* size of section data in bytes */
    635 } dof_sec_t;
    636 
    637 #define	DOF_SECT_NONE		0	/* null section */
    638 #define	DOF_SECT_COMMENTS	1	/* compiler comments */
    639 #define	DOF_SECT_SOURCE		2	/* D program source code */
    640 #define	DOF_SECT_ECBDESC	3	/* dof_ecbdesc_t */
    641 #define	DOF_SECT_PROBEDESC	4	/* dof_probedesc_t */
    642 #define	DOF_SECT_ACTDESC	5	/* dof_actdesc_t array */
    643 #define	DOF_SECT_DIFOHDR	6	/* dof_difohdr_t (variable length) */
    644 #define	DOF_SECT_DIF		7	/* uint32_t array of byte code */
    645 #define	DOF_SECT_STRTAB		8	/* string table */
    646 #define	DOF_SECT_VARTAB		9	/* dtrace_difv_t array */
    647 #define	DOF_SECT_RELTAB		10	/* dof_relodesc_t array */
    648 #define	DOF_SECT_TYPTAB		11	/* dtrace_diftype_t array */
    649 #define	DOF_SECT_URELHDR	12	/* dof_relohdr_t (user relocations) */
    650 #define	DOF_SECT_KRELHDR	13	/* dof_relohdr_t (kernel relocations) */
    651 #define	DOF_SECT_OPTDESC	14	/* dof_optdesc_t array */
    652 #define	DOF_SECT_PROVIDER	15	/* dof_provider_t */
    653 #define	DOF_SECT_PROBES		16	/* dof_probe_t array */
    654 #define	DOF_SECT_PRARGS		17	/* uint8_t array (probe arg mappings) */
    655 #define	DOF_SECT_PROFFS		18	/* uint32_t array (probe arg offsets) */
    656 #define	DOF_SECT_INTTAB		19	/* uint64_t array */
    657 #define	DOF_SECT_UTSNAME	20	/* struct utsname */
    658 #define	DOF_SECT_XLTAB		21	/* dof_xlref_t array */
    659 #define	DOF_SECT_XLMEMBERS	22	/* dof_xlmember_t array */
    660 #define	DOF_SECT_XLIMPORT	23	/* dof_xlator_t */
    661 #define	DOF_SECT_XLEXPORT	24	/* dof_xlator_t */
    662 #define	DOF_SECT_PREXPORT	25	/* dof_secidx_t array (exported objs) */
    663 #define	DOF_SECT_PRENOFFS	26	/* uint32_t array (enabled offsets) */
    664 
    665 #define	DOF_SECF_LOAD		1	/* section should be loaded */
    666 
    667 typedef struct dof_ecbdesc {
    668 	dof_secidx_t dofe_probes;	/* link to DOF_SECT_PROBEDESC */
    669 	dof_secidx_t dofe_pred;		/* link to DOF_SECT_DIFOHDR */
    670 	dof_secidx_t dofe_actions;	/* link to DOF_SECT_ACTDESC */
    671 	uint32_t dofe_pad;		/* reserved for future use */
    672 	uint64_t dofe_uarg;		/* user-supplied library argument */
    673 } dof_ecbdesc_t;
    674 
    675 typedef struct dof_probedesc {
    676 	dof_secidx_t dofp_strtab;	/* link to DOF_SECT_STRTAB section */
    677 	dof_stridx_t dofp_provider;	/* provider string */
    678 	dof_stridx_t dofp_mod;		/* module string */
    679 	dof_stridx_t dofp_func;		/* function string */
    680 	dof_stridx_t dofp_name;		/* name string */
    681 	uint32_t dofp_id;		/* probe identifier (or zero) */
    682 } dof_probedesc_t;
    683 
    684 typedef struct dof_actdesc {
    685 	dof_secidx_t dofa_difo;		/* link to DOF_SECT_DIFOHDR */
    686 	dof_secidx_t dofa_strtab;	/* link to DOF_SECT_STRTAB section */
    687 	uint32_t dofa_kind;		/* action kind (DTRACEACT_* constant) */
    688 	uint32_t dofa_ntuple;		/* number of subsequent tuple actions */
    689 	uint64_t dofa_arg;		/* kind-specific argument */
    690 	uint64_t dofa_uarg;		/* user-supplied argument */
    691 } dof_actdesc_t;
    692 
    693 typedef struct dof_difohdr {
    694 	dtrace_diftype_t dofd_rtype;	/* return type for this fragment */
    695 	dof_secidx_t dofd_links[1];	/* variable length array of indices */
    696 } dof_difohdr_t;
    697 
    698 typedef struct dof_relohdr {
    699 	dof_secidx_t dofr_strtab;	/* link to DOF_SECT_STRTAB for names */
    700 	dof_secidx_t dofr_relsec;	/* link to DOF_SECT_RELTAB for relos */
    701 	dof_secidx_t dofr_tgtsec;	/* link to section we are relocating */
    702 } dof_relohdr_t;
    703 
    704 typedef struct dof_relodesc {
    705 	dof_stridx_t dofr_name;		/* string name of relocation symbol */
    706 	uint32_t dofr_type;		/* relo type (DOF_RELO_* constant) */
    707 	uint64_t dofr_offset;		/* byte offset for relocation */
    708 	uint64_t dofr_data;		/* additional type-specific data */
    709 } dof_relodesc_t;
    710 
    711 #define	DOF_RELO_NONE	0		/* empty relocation entry */
    712 #define	DOF_RELO_SETX	1		/* relocate setx value */
    713 
    714 typedef struct dof_optdesc {
    715 	uint32_t dofo_option;		/* option identifier */
    716 	dof_secidx_t dofo_strtab;	/* string table, if string option */
    717 	uint64_t dofo_value;		/* option value or string index */
    718 } dof_optdesc_t;
    719 
    720 typedef uint32_t dof_attr_t;		/* encoded stability attributes */
    721 
    722 #define	DOF_ATTR(n, d, c)	(((n) << 24) | ((d) << 16) | ((c) << 8))
    723 #define	DOF_ATTR_NAME(a)	(((a) >> 24) & 0xff)
    724 #define	DOF_ATTR_DATA(a)	(((a) >> 16) & 0xff)
    725 #define	DOF_ATTR_CLASS(a)	(((a) >>  8) & 0xff)
    726 
    727 typedef struct dof_provider {
    728 	dof_secidx_t dofpv_strtab;