1179193Sjb/* 2179193Sjb * CDDL HEADER START 3179193Sjb * 4179193Sjb * The contents of this file are subject to the terms of the 5179193Sjb * Common Development and Distribution License (the "License"). 6179193Sjb * You may not use this file except in compliance with the License. 7179193Sjb * 8179193Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9179193Sjb * or http://www.opensolaris.org/os/licensing. 10179193Sjb * See the License for the specific language governing permissions 11179193Sjb * and limitations under the License. 12179193Sjb * 13179193Sjb * When distributing Covered Code, include this CDDL HEADER in each 14179193Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15179193Sjb * If applicable, add the following below this CDDL HEADER, with the 16179193Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17179193Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18179193Sjb * 19179193Sjb * CDDL HEADER END 20179193Sjb */ 21179193Sjb 22179193Sjb/* 23179193Sjb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24179193Sjb * Use is subject to license terms. 25179193Sjb */ 26179193Sjb 27237624Spfg/* 28267941Srpaulo * Copyright (c) 2013, Joyent, Inc. All rights reserved. 29267941Srpaulo * Copyright (c) 2013 by Delphix. All rights reserved. 30237624Spfg */ 31237624Spfg 32179193Sjb#ifndef _SYS_DTRACE_H 33179193Sjb#define _SYS_DTRACE_H 34179193Sjb 35179193Sjb#ifdef __cplusplus 36179193Sjbextern "C" { 37179193Sjb#endif 38179193Sjb 39179193Sjb/* 40179193Sjb * DTrace Dynamic Tracing Software: Kernel Interfaces 41179193Sjb * 42179193Sjb * Note: The contents of this file are private to the implementation of the 43179193Sjb * Solaris system and DTrace subsystem and are subject to change at any time 44179193Sjb * without notice. Applications and drivers using these interfaces will fail 45179193Sjb * to run on future releases. These interfaces should not be used for any 46179193Sjb * purpose except those expressly outlined in dtrace(7D) and libdtrace(3LIB). 47179193Sjb * Please refer to the "Solaris Dynamic Tracing Guide" for more information. 48179193Sjb */ 49179193Sjb 50179193Sjb#ifndef _ASM 51179193Sjb 52179193Sjb#include <sys/types.h> 53179193Sjb#include <sys/modctl.h> 54179193Sjb#include <sys/processor.h> 55277300Ssmh#ifdef illumos 56179193Sjb#include <sys/systm.h> 57179198Sjb#else 58275576Savg#include <sys/cpuvar.h> 59179198Sjb#include <sys/param.h> 60179198Sjb#include <sys/linker.h> 61179198Sjb#include <sys/ioccom.h> 62179198Sjb#include <sys/ucred.h> 63179198Sjbtypedef int model_t; 64179198Sjb#endif 65179193Sjb#include <sys/ctf_api.h> 66277300Ssmh#ifdef illumos 67179193Sjb#include <sys/cyclic.h> 68179193Sjb#include <sys/int_limits.h> 69179198Sjb#else 70179198Sjb#include <sys/stdint.h> 71179198Sjb#endif 72179193Sjb 73179193Sjb/* 74179193Sjb * DTrace Universal Constants and Typedefs 75179193Sjb */ 76179193Sjb#define DTRACE_CPUALL -1 /* all CPUs */ 77179193Sjb#define DTRACE_IDNONE 0 /* invalid probe identifier */ 78179193Sjb#define DTRACE_EPIDNONE 0 /* invalid enabled probe identifier */ 79179193Sjb#define DTRACE_AGGIDNONE 0 /* invalid aggregation identifier */ 80179193Sjb#define DTRACE_AGGVARIDNONE 0 /* invalid aggregation variable ID */ 81179193Sjb#define DTRACE_CACHEIDNONE 0 /* invalid predicate cache */ 82179193Sjb#define DTRACE_PROVNONE 0 /* invalid provider identifier */ 83179193Sjb#define DTRACE_METAPROVNONE 0 /* invalid meta-provider identifier */ 84179193Sjb#define DTRACE_ARGNONE -1 /* invalid argument index */ 85179193Sjb 86179193Sjb#define DTRACE_PROVNAMELEN 64 87179193Sjb#define DTRACE_MODNAMELEN 64 88298590Smarkj#define DTRACE_FUNCNAMELEN 192 89179193Sjb#define DTRACE_NAMELEN 64 90179193Sjb#define DTRACE_FULLNAMELEN (DTRACE_PROVNAMELEN + DTRACE_MODNAMELEN + \ 91179193Sjb DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 4) 92179193Sjb#define DTRACE_ARGTYPELEN 128 93179193Sjb 94179193Sjbtypedef uint32_t dtrace_id_t; /* probe identifier */ 95179193Sjbtypedef uint32_t dtrace_epid_t; /* enabled probe identifier */ 96179193Sjbtypedef uint32_t dtrace_aggid_t; /* aggregation identifier */ 97179193Sjbtypedef int64_t dtrace_aggvarid_t; /* aggregation variable identifier */ 98179193Sjbtypedef uint16_t dtrace_actkind_t; /* action kind */ 99179193Sjbtypedef int64_t dtrace_optval_t; /* option value */ 100179193Sjbtypedef uint32_t dtrace_cacheid_t; /* predicate cache identifier */ 101179193Sjb 102179193Sjbtypedef enum dtrace_probespec { 103179193Sjb DTRACE_PROBESPEC_NONE = -1, 104179193Sjb DTRACE_PROBESPEC_PROVIDER = 0, 105179193Sjb DTRACE_PROBESPEC_MOD, 106179193Sjb DTRACE_PROBESPEC_FUNC, 107179193Sjb DTRACE_PROBESPEC_NAME 108179193Sjb} dtrace_probespec_t; 109179193Sjb 110179193Sjb/* 111179193Sjb * DTrace Intermediate Format (DIF) 112179193Sjb * 113179193Sjb * The following definitions describe the DTrace Intermediate Format (DIF), a 114179193Sjb * a RISC-like instruction set and program encoding used to represent 115179193Sjb * predicates and actions that can be bound to DTrace probes. The constants 116179193Sjb * below defining the number of available registers are suggested minimums; the 117179193Sjb * compiler should use DTRACEIOC_CONF to dynamically obtain the number of 118179193Sjb * registers provided by the current DTrace implementation. 119179193Sjb */ 120179193Sjb#define DIF_VERSION_1 1 /* DIF version 1: Solaris 10 Beta */ 121179193Sjb#define DIF_VERSION_2 2 /* DIF version 2: Solaris 10 FCS */ 122179193Sjb#define DIF_VERSION DIF_VERSION_2 /* latest DIF instruction set version */ 123179193Sjb#define DIF_DIR_NREGS 8 /* number of DIF integer registers */ 124179193Sjb#define DIF_DTR_NREGS 8 /* number of DIF tuple registers */ 125179193Sjb 126179193Sjb#define DIF_OP_OR 1 /* or r1, r2, rd */ 127179193Sjb#define DIF_OP_XOR 2 /* xor r1, r2, rd */ 128179193Sjb#define DIF_OP_AND 3 /* and r1, r2, rd */ 129179193Sjb#define DIF_OP_SLL 4 /* sll r1, r2, rd */ 130179193Sjb#define DIF_OP_SRL 5 /* srl r1, r2, rd */ 131179193Sjb#define DIF_OP_SUB 6 /* sub r1, r2, rd */ 132179193Sjb#define DIF_OP_ADD 7 /* add r1, r2, rd */ 133179193Sjb#define DIF_OP_MUL 8 /* mul r1, r2, rd */ 134179193Sjb#define DIF_OP_SDIV 9 /* sdiv r1, r2, rd */ 135179193Sjb#define DIF_OP_UDIV 10 /* udiv r1, r2, rd */ 136179193Sjb#define DIF_OP_SREM 11 /* srem r1, r2, rd */ 137179193Sjb#define DIF_OP_UREM 12 /* urem r1, r2, rd */ 138179193Sjb#define DIF_OP_NOT 13 /* not r1, rd */ 139179193Sjb#define DIF_OP_MOV 14 /* mov r1, rd */ 140179193Sjb#define DIF_OP_CMP 15 /* cmp r1, r2 */ 141179193Sjb#define DIF_OP_TST 16 /* tst r1 */ 142179193Sjb#define DIF_OP_BA 17 /* ba label */ 143179193Sjb#define DIF_OP_BE 18 /* be label */ 144179193Sjb#define DIF_OP_BNE 19 /* bne label */ 145179193Sjb#define DIF_OP_BG 20 /* bg label */ 146179193Sjb#define DIF_OP_BGU 21 /* bgu label */ 147179193Sjb#define DIF_OP_BGE 22 /* bge label */ 148179193Sjb#define DIF_OP_BGEU 23 /* bgeu label */ 149179193Sjb#define DIF_OP_BL 24 /* bl label */ 150179193Sjb#define DIF_OP_BLU 25 /* blu label */ 151179193Sjb#define DIF_OP_BLE 26 /* ble label */ 152179193Sjb#define DIF_OP_BLEU 27 /* bleu label */ 153179193Sjb#define DIF_OP_LDSB 28 /* ldsb [r1], rd */ 154179193Sjb#define DIF_OP_LDSH 29 /* ldsh [r1], rd */ 155179193Sjb#define DIF_OP_LDSW 30 /* ldsw [r1], rd */ 156179193Sjb#define DIF_OP_LDUB 31 /* ldub [r1], rd */ 157179193Sjb#define DIF_OP_LDUH 32 /* lduh [r1], rd */ 158179193Sjb#define DIF_OP_LDUW 33 /* lduw [r1], rd */ 159179193Sjb#define DIF_OP_LDX 34 /* ldx [r1], rd */ 160179193Sjb#define DIF_OP_RET 35 /* ret rd */ 161179193Sjb#define DIF_OP_NOP 36 /* nop */ 162179193Sjb#define DIF_OP_SETX 37 /* setx intindex, rd */ 163179193Sjb#define DIF_OP_SETS 38 /* sets strindex, rd */ 164179193Sjb#define DIF_OP_SCMP 39 /* scmp r1, r2 */ 165179193Sjb#define DIF_OP_LDGA 40 /* ldga var, ri, rd */ 166179193Sjb#define DIF_OP_LDGS 41 /* ldgs var, rd */ 167179193Sjb#define DIF_OP_STGS 42 /* stgs var, rs */ 168179193Sjb#define DIF_OP_LDTA 43 /* ldta var, ri, rd */ 169179193Sjb#define DIF_OP_LDTS 44 /* ldts var, rd */ 170179193Sjb#define DIF_OP_STTS 45 /* stts var, rs */ 171179193Sjb#define DIF_OP_SRA 46 /* sra r1, r2, rd */ 172179193Sjb#define DIF_OP_CALL 47 /* call subr, rd */ 173179193Sjb#define DIF_OP_PUSHTR 48 /* pushtr type, rs, rr */ 174179193Sjb#define DIF_OP_PUSHTV 49 /* pushtv type, rs, rv */ 175179193Sjb#define DIF_OP_POPTS 50 /* popts */ 176179193Sjb#define DIF_OP_FLUSHTS 51 /* flushts */ 177179193Sjb#define DIF_OP_LDGAA 52 /* ldgaa var, rd */ 178179193Sjb#define DIF_OP_LDTAA 53 /* ldtaa var, rd */ 179179193Sjb#define DIF_OP_STGAA 54 /* stgaa var, rs */ 180179193Sjb#define DIF_OP_STTAA 55 /* sttaa var, rs */ 181179193Sjb#define DIF_OP_LDLS 56 /* ldls var, rd */ 182179193Sjb#define DIF_OP_STLS 57 /* stls var, rs */ 183179193Sjb#define DIF_OP_ALLOCS 58 /* allocs r1, rd */ 184179193Sjb#define DIF_OP_COPYS 59 /* copys r1, r2, rd */ 185179193Sjb#define DIF_OP_STB 60 /* stb r1, [rd] */ 186179193Sjb#define DIF_OP_STH 61 /* sth r1, [rd] */ 187179193Sjb#define DIF_OP_STW 62 /* stw r1, [rd] */ 188179193Sjb#define DIF_OP_STX 63 /* stx r1, [rd] */ 189179193Sjb#define DIF_OP_ULDSB 64 /* uldsb [r1], rd */ 190179193Sjb#define DIF_OP_ULDSH 65 /* uldsh [r1], rd */ 191179193Sjb#define DIF_OP_ULDSW 66 /* uldsw [r1], rd */ 192179193Sjb#define DIF_OP_ULDUB 67 /* uldub [r1], rd */ 193179193Sjb#define DIF_OP_ULDUH 68 /* ulduh [r1], rd */ 194179193Sjb#define DIF_OP_ULDUW 69 /* ulduw [r1], rd */ 195179193Sjb#define DIF_OP_ULDX 70 /* uldx [r1], rd */ 196179193Sjb#define DIF_OP_RLDSB 71 /* rldsb [r1], rd */ 197179193Sjb#define DIF_OP_RLDSH 72 /* rldsh [r1], rd */ 198179193Sjb#define DIF_OP_RLDSW 73 /* rldsw [r1], rd */ 199179193Sjb#define DIF_OP_RLDUB 74 /* rldub [r1], rd */ 200179193Sjb#define DIF_OP_RLDUH 75 /* rlduh [r1], rd */ 201179193Sjb#define DIF_OP_RLDUW 76 /* rlduw [r1], rd */ 202179193Sjb#define DIF_OP_RLDX 77 /* rldx [r1], rd */ 203179193Sjb#define DIF_OP_XLATE 78 /* xlate xlrindex, rd */ 204179193Sjb#define DIF_OP_XLARG 79 /* xlarg xlrindex, rd */ 205179193Sjb 206179193Sjb#define DIF_INTOFF_MAX 0xffff /* highest integer table offset */ 207179193Sjb#define DIF_STROFF_MAX 0xffff /* highest string table offset */ 208179193Sjb#define DIF_REGISTER_MAX 0xff /* highest register number */ 209179193Sjb#define DIF_VARIABLE_MAX 0xffff /* highest variable identifier */ 210179193Sjb#define DIF_SUBROUTINE_MAX 0xffff /* highest subroutine code */ 211179193Sjb 212179193Sjb#define DIF_VAR_ARRAY_MIN 0x0000 /* lowest numbered array variable */ 213179193Sjb#define DIF_VAR_ARRAY_UBASE 0x0080 /* lowest user-defined array */ 214179193Sjb#define DIF_VAR_ARRAY_MAX 0x00ff /* highest numbered array variable */ 215179193Sjb 216179193Sjb#define DIF_VAR_OTHER_MIN 0x0100 /* lowest numbered scalar or assc */ 217179193Sjb#define DIF_VAR_OTHER_UBASE 0x0500 /* lowest user-defined scalar or assc */ 218179193Sjb#define DIF_VAR_OTHER_MAX 0xffff /* highest numbered scalar or assc */ 219179193Sjb 220179193Sjb#define DIF_VAR_ARGS 0x0000 /* arguments array */ 221179193Sjb#define DIF_VAR_REGS 0x0001 /* registers array */ 222179193Sjb#define DIF_VAR_UREGS 0x0002 /* user registers array */ 223179193Sjb#define DIF_VAR_CURTHREAD 0x0100 /* thread pointer */ 224179193Sjb#define DIF_VAR_TIMESTAMP 0x0101 /* timestamp */ 225179193Sjb#define DIF_VAR_VTIMESTAMP 0x0102 /* virtual timestamp */ 226179193Sjb#define DIF_VAR_IPL 0x0103 /* interrupt priority level */ 227179193Sjb#define DIF_VAR_EPID 0x0104 /* enabled probe ID */ 228179193Sjb#define DIF_VAR_ID 0x0105 /* probe ID */ 229179193Sjb#define DIF_VAR_ARG0 0x0106 /* first argument */ 230179193Sjb#define DIF_VAR_ARG1 0x0107 /* second argument */ 231179193Sjb#define DIF_VAR_ARG2 0x0108 /* third argument */ 232179193Sjb#define DIF_VAR_ARG3 0x0109 /* fourth argument */ 233179193Sjb#define DIF_VAR_ARG4 0x010a /* fifth argument */ 234179193Sjb#define DIF_VAR_ARG5 0x010b /* sixth argument */ 235179193Sjb#define DIF_VAR_ARG6 0x010c /* seventh argument */ 236179193Sjb#define DIF_VAR_ARG7 0x010d /* eighth argument */ 237179193Sjb#define DIF_VAR_ARG8 0x010e /* ninth argument */ 238179193Sjb#define DIF_VAR_ARG9 0x010f /* tenth argument */ 239179193Sjb#define DIF_VAR_STACKDEPTH 0x0110 /* stack depth */ 240179193Sjb#define DIF_VAR_CALLER 0x0111 /* caller */ 241179193Sjb#define DIF_VAR_PROBEPROV 0x0112 /* probe provider */ 242179193Sjb#define DIF_VAR_PROBEMOD 0x0113 /* probe module */ 243179193Sjb#define DIF_VAR_PROBEFUNC 0x0114 /* probe function */ 244179193Sjb#define DIF_VAR_PROBENAME 0x0115 /* probe name */ 245179193Sjb#define DIF_VAR_PID 0x0116 /* process ID */ 246179193Sjb#define DIF_VAR_TID 0x0117 /* (per-process) thread ID */ 247179193Sjb#define DIF_VAR_EXECNAME 0x0118 /* name of executable */ 248179193Sjb#define DIF_VAR_ZONENAME 0x0119 /* zone name associated with process */ 249179193Sjb#define DIF_VAR_WALLTIMESTAMP 0x011a /* wall-clock timestamp */ 250179193Sjb#define DIF_VAR_USTACKDEPTH 0x011b /* user-land stack depth */ 251179193Sjb#define DIF_VAR_UCALLER 0x011c /* user-level caller */ 252179193Sjb#define DIF_VAR_PPID 0x011d /* parent process ID */ 253179193Sjb#define DIF_VAR_UID 0x011e /* process user ID */ 254179193Sjb#define DIF_VAR_GID 0x011f /* process group ID */ 255179193Sjb#define DIF_VAR_ERRNO 0x0120 /* thread errno */ 256179198Sjb#define DIF_VAR_EXECARGS 0x0121 /* process arguments */ 257329249Smarkj#define DIF_VAR_JID 0x0122 /* process jail id */ 258329249Smarkj#define DIF_VAR_JAILNAME 0x0123 /* process jail name */ 259179193Sjb 260277300Ssmh#ifndef illumos 261234691Srstone#define DIF_VAR_CPU 0x0200 262234691Srstone#endif 263234691Srstone 264179193Sjb#define DIF_SUBR_RAND 0 265179193Sjb#define DIF_SUBR_MUTEX_OWNED 1 266179193Sjb#define DIF_SUBR_MUTEX_OWNER 2 267179193Sjb#define DIF_SUBR_MUTEX_TYPE_ADAPTIVE 3 268179193Sjb#define DIF_SUBR_MUTEX_TYPE_SPIN 4 269179193Sjb#define DIF_SUBR_RW_READ_HELD 5 270179193Sjb#define DIF_SUBR_RW_WRITE_HELD 6 271179193Sjb#define DIF_SUBR_RW_ISWRITER 7 272179193Sjb#define DIF_SUBR_COPYIN 8 273179193Sjb#define DIF_SUBR_COPYINSTR 9 274179193Sjb#define DIF_SUBR_SPECULATION 10 275179193Sjb#define DIF_SUBR_PROGENYOF 11 276179193Sjb#define DIF_SUBR_STRLEN 12 277179193Sjb#define DIF_SUBR_COPYOUT 13 278179193Sjb#define DIF_SUBR_COPYOUTSTR 14 279179193Sjb#define DIF_SUBR_ALLOCA 15 280179193Sjb#define DIF_SUBR_BCOPY 16 281179193Sjb#define DIF_SUBR_COPYINTO 17 282179193Sjb#define DIF_SUBR_MSGDSIZE 18 283179193Sjb#define DIF_SUBR_MSGSIZE 19 284179193Sjb#define DIF_SUBR_GETMAJOR 20 285179193Sjb#define DIF_SUBR_GETMINOR 21 286179193Sjb#define DIF_SUBR_DDI_PATHNAME 22 287179193Sjb#define DIF_SUBR_STRJOIN 23 288179193Sjb#define DIF_SUBR_LLTOSTR 24 289179193Sjb#define DIF_SUBR_BASENAME 25 290179193Sjb#define DIF_SUBR_DIRNAME 26 291179193Sjb#define DIF_SUBR_CLEANPATH 27 292179193Sjb#define DIF_SUBR_STRCHR 28 293179193Sjb#define DIF_SUBR_STRRCHR 29 294179193Sjb#define DIF_SUBR_STRSTR 30 295179193Sjb#define DIF_SUBR_STRTOK 31 296179193Sjb#define DIF_SUBR_SUBSTR 32 297179193Sjb#define DIF_SUBR_INDEX 33 298179193Sjb#define DIF_SUBR_RINDEX 34 299179193Sjb#define DIF_SUBR_HTONS 35 300179193Sjb#define DIF_SUBR_HTONL 36 301179193Sjb#define DIF_SUBR_HTONLL 37 302179193Sjb#define DIF_SUBR_NTOHS 38 303179193Sjb#define DIF_SUBR_NTOHL 39 304179193Sjb#define DIF_SUBR_NTOHLL 40 305179193Sjb#define DIF_SUBR_INET_NTOP 41 306179193Sjb#define DIF_SUBR_INET_NTOA 42 307179193Sjb#define DIF_SUBR_INET_NTOA6 43 308248706Spfg#define DIF_SUBR_TOUPPER 44 309248706Spfg#define DIF_SUBR_TOLOWER 45 310248706Spfg#define DIF_SUBR_MEMREF 46 311248706Spfg#define DIF_SUBR_TYPEREF 47 312248706Spfg#define DIF_SUBR_SX_SHARED_HELD 48 313248706Spfg#define DIF_SUBR_SX_EXCLUSIVE_HELD 49 314248706Spfg#define DIF_SUBR_SX_ISEXCLUSIVE 50 315256571Smarkj#define DIF_SUBR_MEMSTR 51 316267929Srpaulo#define DIF_SUBR_GETF 52 317267937Srpaulo#define DIF_SUBR_JSON 53 318267937Srpaulo#define DIF_SUBR_STRTOLL 54 319267937Srpaulo#define DIF_SUBR_MAX 54 /* max subroutine value */ 320179193Sjb 321179193Sjbtypedef uint32_t dif_instr_t; 322179193Sjb 323179193Sjb#define DIF_INSTR_OP(i) (((i) >> 24) & 0xff) 324179193Sjb#define DIF_INSTR_R1(i) (((i) >> 16) & 0xff) 325179193Sjb#define DIF_INSTR_R2(i) (((i) >> 8) & 0xff) 326179193Sjb#define DIF_INSTR_RD(i) ((i) & 0xff) 327179193Sjb#define DIF_INSTR_RS(i) ((i) & 0xff) 328179193Sjb#define DIF_INSTR_LABEL(i) ((i) & 0xffffff) 329179193Sjb#define DIF_INSTR_VAR(i) (((i) >> 8) & 0xffff) 330179193Sjb#define DIF_INSTR_INTEGER(i) (((i) >> 8) & 0xffff) 331179193Sjb#define DIF_INSTR_STRING(i) (((i) >> 8) & 0xffff) 332179193Sjb#define DIF_INSTR_SUBR(i) (((i) >> 8) & 0xffff) 333179193Sjb#define DIF_INSTR_TYPE(i) (((i) >> 16) & 0xff) 334179193Sjb#define DIF_INSTR_XLREF(i) (((i) >> 8) & 0xffff) 335179193Sjb 336179193Sjb#define DIF_INSTR_FMT(op, r1, r2, d) \ 337179193Sjb (((op) << 24) | ((r1) << 16) | ((r2) << 8) | (d)) 338179193Sjb 339179193Sjb#define DIF_INSTR_NOT(r1, d) (DIF_INSTR_FMT(DIF_OP_NOT, r1, 0, d)) 340179193Sjb#define DIF_INSTR_MOV(r1, d) (DIF_INSTR_FMT(DIF_OP_MOV, r1, 0, d)) 341179193Sjb#define DIF_INSTR_CMP(op, r1, r2) (DIF_INSTR_FMT(op, r1, r2, 0)) 342179193Sjb#define DIF_INSTR_TST(r1) (DIF_INSTR_FMT(DIF_OP_TST, r1, 0, 0)) 343179193Sjb#define DIF_INSTR_BRANCH(op, label) (((op) << 24) | (label)) 344179193Sjb#define DIF_INSTR_LOAD(op, r1, d) (DIF_INSTR_FMT(op, r1, 0, d)) 345179193Sjb#define DIF_INSTR_STORE(op, r1, d) (DIF_INSTR_FMT(op, r1, 0, d)) 346179193Sjb#define DIF_INSTR_SETX(i, d) ((DIF_OP_SETX << 24) | ((i) << 8) | (d)) 347179193Sjb#define DIF_INSTR_SETS(s, d) ((DIF_OP_SETS << 24) | ((s) << 8) | (d)) 348179193Sjb#define DIF_INSTR_RET(d) (DIF_INSTR_FMT(DIF_OP_RET, 0, 0, d)) 349179193Sjb#define DIF_INSTR_NOP (DIF_OP_NOP << 24) 350179193Sjb#define DIF_INSTR_LDA(op, v, r, d) (DIF_INSTR_FMT(op, v, r, d)) 351179193Sjb#define DIF_INSTR_LDV(op, v, d) (((op) << 24) | ((v) << 8) | (d)) 352179193Sjb#define DIF_INSTR_STV(op, v, rs) (((op) << 24) | ((v) << 8) | (rs)) 353179193Sjb#define DIF_INSTR_CALL(s, d) ((DIF_OP_CALL << 24) | ((s) << 8) | (d)) 354179193Sjb#define DIF_INSTR_PUSHTS(op, t, r2, rs) (DIF_INSTR_FMT(op, t, r2, rs)) 355179193Sjb#define DIF_INSTR_POPTS (DIF_OP_POPTS << 24) 356179193Sjb#define DIF_INSTR_FLUSHTS (DIF_OP_FLUSHTS << 24) 357179193Sjb#define DIF_INSTR_ALLOCS(r1, d) (DIF_INSTR_FMT(DIF_OP_ALLOCS, r1, 0, d)) 358179193Sjb#define DIF_INSTR_COPYS(r1, r2, d) (DIF_INSTR_FMT(DIF_OP_COPYS, r1, r2, d)) 359179193Sjb#define DIF_INSTR_XLATE(op, r, d) (((op) << 24) | ((r) << 8) | (d)) 360179193Sjb 361179193Sjb#define DIF_REG_R0 0 /* %r0 is always set to zero */ 362179193Sjb 363179193Sjb/* 364179193Sjb * A DTrace Intermediate Format Type (DIF Type) is used to represent the types 365179193Sjb * of variables, function and associative array arguments, and the return type 366179193Sjb * for each DIF object (shown below). It contains a description of the type, 367179193Sjb * its size in bytes, and a module identifier. 368179193Sjb */ 369179193Sjbtypedef struct dtrace_diftype { 370179193Sjb uint8_t dtdt_kind; /* type kind (see below) */ 371179193Sjb uint8_t dtdt_ckind; /* type kind in CTF */ 372179193Sjb uint8_t dtdt_flags; /* type flags (see below) */ 373179193Sjb uint8_t dtdt_pad; /* reserved for future use */ 374179193Sjb uint32_t dtdt_size; /* type size in bytes (unless string) */ 375179193Sjb} dtrace_diftype_t; 376179193Sjb 377179193Sjb#define DIF_TYPE_CTF 0 /* type is a CTF type */ 378179193Sjb#define DIF_TYPE_STRING 1 /* type is a D string */ 379179193Sjb 380179193Sjb#define DIF_TF_BYREF 0x1 /* type is passed by reference */ 381267941Srpaulo#define DIF_TF_BYUREF 0x2 /* user type is passed by reference */ 382179193Sjb 383179193Sjb/* 384179193Sjb * A DTrace Intermediate Format variable record is used to describe each of the 385179193Sjb * variables referenced by a given DIF object. It contains an integer variable 386179193Sjb * identifier along with variable scope and properties, as shown below. The 387179193Sjb * size of this structure must be sizeof (int) aligned. 388179193Sjb */ 389179193Sjbtypedef struct dtrace_difv { 390179193Sjb uint32_t dtdv_name; /* variable name index in dtdo_strtab */ 391179193Sjb uint32_t dtdv_id; /* variable reference identifier */ 392179193Sjb uint8_t dtdv_kind; /* variable kind (see below) */ 393179193Sjb uint8_t dtdv_scope; /* variable scope (see below) */ 394179193Sjb uint16_t dtdv_flags; /* variable flags (see below) */ 395179193Sjb dtrace_diftype_t dtdv_type; /* variable type (see above) */ 396179193Sjb} dtrace_difv_t; 397179193Sjb 398179193Sjb#define DIFV_KIND_ARRAY 0 /* variable is an array of quantities */ 399179193Sjb#define DIFV_KIND_SCALAR 1 /* variable is a scalar quantity */ 400179193Sjb 401179193Sjb#define DIFV_SCOPE_GLOBAL 0 /* variable has global scope */ 402179193Sjb#define DIFV_SCOPE_THREAD 1 /* variable has thread scope */ 403179193Sjb#define DIFV_SCOPE_LOCAL 2 /* variable has local scope */ 404179193Sjb 405179193Sjb#define DIFV_F_REF 0x1 /* variable is referenced by DIFO */ 406179193Sjb#define DIFV_F_MOD 0x2 /* variable is written by DIFO */ 407179193Sjb 408179193Sjb/* 409179193Sjb * DTrace Actions 410179193Sjb * 411179193Sjb * The upper byte determines the class of the action; the low bytes determines 412179193Sjb * the specific action within that class. The classes of actions are as 413179193Sjb * follows: 414179193Sjb * 415179193Sjb * [ no class ] <= May record process- or kernel-related data 416179193Sjb * DTRACEACT_PROC <= Only records process-related data 417179193Sjb * DTRACEACT_PROC_DESTRUCTIVE <= Potentially destructive to processes 418179193Sjb * DTRACEACT_KERNEL <= Only records kernel-related data 419179193Sjb * DTRACEACT_KERNEL_DESTRUCTIVE <= Potentially destructive to the kernel 420179193Sjb * DTRACEACT_SPECULATIVE <= Speculation-related action 421179193Sjb * DTRACEACT_AGGREGATION <= Aggregating action 422179193Sjb */ 423179193Sjb#define DTRACEACT_NONE 0 /* no action */ 424179193Sjb#define DTRACEACT_DIFEXPR 1 /* action is DIF expression */ 425179193Sjb#define DTRACEACT_EXIT 2 /* exit() action */ 426179193Sjb#define DTRACEACT_PRINTF 3 /* printf() action */ 427179193Sjb#define DTRACEACT_PRINTA 4 /* printa() action */ 428179193Sjb#define DTRACEACT_LIBACT 5 /* library-controlled action */ 429248690Spfg#define DTRACEACT_TRACEMEM 6 /* tracemem() action */ 430248690Spfg#define DTRACEACT_TRACEMEM_DYNSIZE 7 /* dynamic tracemem() size */ 431248690Spfg#define DTRACEACT_PRINTM 8 /* printm() action (BSD) */ 432248690Spfg#define DTRACEACT_PRINTT 9 /* printt() action (BSD) */ 433179193Sjb 434179193Sjb#define DTRACEACT_PROC 0x0100 435179193Sjb#define DTRACEACT_USTACK (DTRACEACT_PROC + 1) 436179193Sjb#define DTRACEACT_JSTACK (DTRACEACT_PROC + 2) 437179193Sjb#define DTRACEACT_USYM (DTRACEACT_PROC + 3) 438179193Sjb#define DTRACEACT_UMOD (DTRACEACT_PROC + 4) 439179193Sjb#define DTRACEACT_UADDR (DTRACEACT_PROC + 5) 440179193Sjb 441179193Sjb#define DTRACEACT_PROC_DESTRUCTIVE 0x0200 442179193Sjb#define DTRACEACT_STOP (DTRACEACT_PROC_DESTRUCTIVE + 1) 443179193Sjb#define DTRACEACT_RAISE (DTRACEACT_PROC_DESTRUCTIVE + 2) 444179193Sjb#define DTRACEACT_SYSTEM (DTRACEACT_PROC_DESTRUCTIVE + 3) 445179193Sjb#define DTRACEACT_FREOPEN (DTRACEACT_PROC_DESTRUCTIVE + 4) 446179193Sjb 447179193Sjb#define DTRACEACT_PROC_CONTROL 0x0300 448179193Sjb 449179193Sjb#define DTRACEACT_KERNEL 0x0400 450179193Sjb#define DTRACEACT_STACK (DTRACEACT_KERNEL + 1) 451179193Sjb#define DTRACEACT_SYM (DTRACEACT_KERNEL + 2) 452179193Sjb#define DTRACEACT_MOD (DTRACEACT_KERNEL + 3) 453179193Sjb 454179193Sjb#define DTRACEACT_KERNEL_DESTRUCTIVE 0x0500 455179193Sjb#define DTRACEACT_BREAKPOINT (DTRACEACT_KERNEL_DESTRUCTIVE + 1) 456179193Sjb#define DTRACEACT_PANIC (DTRACEACT_KERNEL_DESTRUCTIVE + 2) 457179193Sjb#define DTRACEACT_CHILL (DTRACEACT_KERNEL_DESTRUCTIVE + 3) 458179193Sjb 459179193Sjb#define DTRACEACT_SPECULATIVE 0x0600 460179193Sjb#define DTRACEACT_SPECULATE (DTRACEACT_SPECULATIVE + 1) 461179193Sjb#define DTRACEACT_COMMIT (DTRACEACT_SPECULATIVE + 2) 462179193Sjb#define DTRACEACT_DISCARD (DTRACEACT_SPECULATIVE + 3) 463179193Sjb 464179193Sjb#define DTRACEACT_CLASS(x) ((x) & 0xff00) 465179193Sjb 466179193Sjb#define DTRACEACT_ISDESTRUCTIVE(x) \ 467179193Sjb (DTRACEACT_CLASS(x) == DTRACEACT_PROC_DESTRUCTIVE || \ 468179193Sjb DTRACEACT_CLASS(x) == DTRACEACT_KERNEL_DESTRUCTIVE) 469179193Sjb 470179193Sjb#define DTRACEACT_ISSPECULATIVE(x) \ 471179193Sjb (DTRACEACT_CLASS(x) == DTRACEACT_SPECULATIVE) 472179193Sjb 473179193Sjb#define DTRACEACT_ISPRINTFLIKE(x) \ 474179193Sjb ((x) == DTRACEACT_PRINTF || (x) == DTRACEACT_PRINTA || \ 475179193Sjb (x) == DTRACEACT_SYSTEM || (x) == DTRACEACT_FREOPEN) 476179193Sjb 477179193Sjb/* 478179193Sjb * DTrace Aggregating Actions 479179193Sjb * 480179193Sjb * These are functions f(x) for which the following is true: 481179193Sjb * 482179193Sjb * f(f(x_0) U f(x_1) U ... U f(x_n)) = f(x_0 U x_1 U ... U x_n) 483179193Sjb * 484179193Sjb * where x_n is a set of arbitrary data. Aggregating actions are in their own 485179193Sjb * DTrace action class, DTTRACEACT_AGGREGATION. The macros provided here allow 486179193Sjb * for easier processing of the aggregation argument and data payload for a few 487179193Sjb * aggregating actions (notably: quantize(), lquantize(), and ustack()). 488179193Sjb */ 489179193Sjb#define DTRACEACT_AGGREGATION 0x0700 490179193Sjb#define DTRACEAGG_COUNT (DTRACEACT_AGGREGATION + 1) 491179193Sjb#define DTRACEAGG_MIN (DTRACEACT_AGGREGATION + 2) 492179193Sjb#define DTRACEAGG_MAX (DTRACEACT_AGGREGATION + 3) 493179193Sjb#define DTRACEAGG_AVG (DTRACEACT_AGGREGATION + 4) 494179193Sjb#define DTRACEAGG_SUM (DTRACEACT_AGGREGATION + 5) 495179193Sjb#define DTRACEAGG_STDDEV (DTRACEACT_AGGREGATION + 6) 496179193Sjb#define DTRACEAGG_QUANTIZE (DTRACEACT_AGGREGATION + 7) 497179193Sjb#define DTRACEAGG_LQUANTIZE (DTRACEACT_AGGREGATION + 8) 498237624Spfg#define DTRACEAGG_LLQUANTIZE (DTRACEACT_AGGREGATION + 9) 499179193Sjb 500179193Sjb#define DTRACEACT_ISAGG(x) \ 501179193Sjb (DTRACEACT_CLASS(x) == DTRACEACT_AGGREGATION) 502179193Sjb 503179193Sjb#define DTRACE_QUANTIZE_NBUCKETS \ 504179193Sjb (((sizeof (uint64_t) * NBBY) - 1) * 2 + 1) 505179193Sjb 506179193Sjb#define DTRACE_QUANTIZE_ZEROBUCKET ((sizeof (uint64_t) * NBBY) - 1) 507179193Sjb 508179193Sjb#define DTRACE_QUANTIZE_BUCKETVAL(buck) \ 509179193Sjb (int64_t)((buck) < DTRACE_QUANTIZE_ZEROBUCKET ? \ 510179193Sjb -(1LL << (DTRACE_QUANTIZE_ZEROBUCKET - 1 - (buck))) : \ 511179193Sjb (buck) == DTRACE_QUANTIZE_ZEROBUCKET ? 0 : \ 512179193Sjb 1LL << ((buck) - DTRACE_QUANTIZE_ZEROBUCKET - 1)) 513179193Sjb 514179193Sjb#define DTRACE_LQUANTIZE_STEPSHIFT 48 515179193Sjb#define DTRACE_LQUANTIZE_STEPMASK ((uint64_t)UINT16_MAX << 48) 516179193Sjb#define DTRACE_LQUANTIZE_LEVELSHIFT 32 517179193Sjb#define DTRACE_LQUANTIZE_LEVELMASK ((uint64_t)UINT16_MAX << 32) 518179193Sjb#define DTRACE_LQUANTIZE_BASESHIFT 0 519179193Sjb#define DTRACE_LQUANTIZE_BASEMASK UINT32_MAX 520179193Sjb 521179193Sjb#define DTRACE_LQUANTIZE_STEP(x) \ 522179193Sjb (uint16_t)(((x) & DTRACE_LQUANTIZE_STEPMASK) >> \ 523179193Sjb DTRACE_LQUANTIZE_STEPSHIFT) 524179193Sjb 525179193Sjb#define DTRACE_LQUANTIZE_LEVELS(x) \ 526179193Sjb (uint16_t)(((x) & DTRACE_LQUANTIZE_LEVELMASK) >> \ 527179193Sjb DTRACE_LQUANTIZE_LEVELSHIFT) 528179193Sjb 529179193Sjb#define DTRACE_LQUANTIZE_BASE(x) \ 530179193Sjb (int32_t)(((x) & DTRACE_LQUANTIZE_BASEMASK) >> \ 531179193Sjb DTRACE_LQUANTIZE_BASESHIFT) 532179193Sjb 533237624Spfg#define DTRACE_LLQUANTIZE_FACTORSHIFT 48 534237624Spfg#define DTRACE_LLQUANTIZE_FACTORMASK ((uint64_t)UINT16_MAX << 48) 535237624Spfg#define DTRACE_LLQUANTIZE_LOWSHIFT 32 536237624Spfg#define DTRACE_LLQUANTIZE_LOWMASK ((uint64_t)UINT16_MAX << 32) 537237624Spfg#define DTRACE_LLQUANTIZE_HIGHSHIFT 16 538237624Spfg#define DTRACE_LLQUANTIZE_HIGHMASK ((uint64_t)UINT16_MAX << 16) 539237624Spfg#define DTRACE_LLQUANTIZE_NSTEPSHIFT 0 540237624Spfg#define DTRACE_LLQUANTIZE_NSTEPMASK UINT16_MAX 541237624Spfg 542237624Spfg#define DTRACE_LLQUANTIZE_FACTOR(x) \ 543237624Spfg (uint16_t)(((x) & DTRACE_LLQUANTIZE_FACTORMASK) >> \ 544237624Spfg DTRACE_LLQUANTIZE_FACTORSHIFT) 545237624Spfg 546237624Spfg#define DTRACE_LLQUANTIZE_LOW(x) \ 547237624Spfg (uint16_t)(((x) & DTRACE_LLQUANTIZE_LOWMASK) >> \ 548237624Spfg DTRACE_LLQUANTIZE_LOWSHIFT) 549237624Spfg 550237624Spfg#define DTRACE_LLQUANTIZE_HIGH(x) \ 551237624Spfg (uint16_t)(((x) & DTRACE_LLQUANTIZE_HIGHMASK) >> \ 552237624Spfg DTRACE_LLQUANTIZE_HIGHSHIFT) 553237624Spfg 554237624Spfg#define DTRACE_LLQUANTIZE_NSTEP(x) \ 555237624Spfg (uint16_t)(((x) & DTRACE_LLQUANTIZE_NSTEPMASK) >> \ 556237624Spfg DTRACE_LLQUANTIZE_NSTEPSHIFT) 557237624Spfg 558179193Sjb#define DTRACE_USTACK_NFRAMES(x) (uint32_t)((x) & UINT32_MAX) 559179193Sjb#define DTRACE_USTACK_STRSIZE(x) (uint32_t)((x) >> 32) 560179193Sjb#define DTRACE_USTACK_ARG(x, y) \ 561179193Sjb ((((uint64_t)(y)) << 32) | ((x) & UINT32_MAX)) 562179193Sjb 563179193Sjb#ifndef _LP64 564179198Sjb#if BYTE_ORDER == _BIG_ENDIAN 565179193Sjb#define DTRACE_PTR(type, name) uint32_t name##pad; type *name 566179193Sjb#else 567179193Sjb#define DTRACE_PTR(type, name) type *name; uint32_t name##pad 568179193Sjb#endif 569179193Sjb#else 570179193Sjb#define DTRACE_PTR(type, name) type *name 571179193Sjb#endif 572179193Sjb 573179193Sjb/* 574179193Sjb * DTrace Object Format (DOF) 575179193Sjb * 576179193Sjb * DTrace programs can be persistently encoded in the DOF format so that they 577179193Sjb * may be embedded in other programs (for example, in an ELF file) or in the 578179193Sjb * dtrace driver configuration file for use in anonymous tracing. The DOF 579179193Sjb * format is versioned and extensible so that it can be revised and so that 580179193Sjb * internal data structures can be modified or extended compatibly. All DOF 581179193Sjb * structures use fixed-size types, so the 32-bit and 64-bit representations 582179193Sjb * are identical and consumers can use either data model transparently. 583179193Sjb * 584179193Sjb * The file layout is structured as follows: 585179193Sjb * 586179193Sjb * +---------------+-------------------+----- ... ----+---- ... ------+ 587179193Sjb * | dof_hdr_t | dof_sec_t[ ... ] | loadable | non-loadable | 588179193Sjb * | (file header) | (section headers) | section data | section data | 589179193Sjb * +---------------+-------------------+----- ... ----+---- ... ------+ 590179193Sjb * |<------------ dof_hdr.dofh_loadsz --------------->| | 591179193Sjb * |<------------ dof_hdr.dofh_filesz ------------------------------->| 592179193Sjb * 593179193Sjb * The file header stores meta-data including a magic number, data model for 594179193Sjb * the instrumentation, data encoding, and properties of the DIF code within. 595179193Sjb * The header describes its own size and the size of the section headers. By 596179193Sjb * convention, an array of section headers follows the file header, and then 597179193Sjb * the data for all loadable sections and unloadable sections. This permits 598179193Sjb * consumer code to easily download the headers and all loadable data into the 599179193Sjb * DTrace driver in one contiguous chunk, omitting other extraneous sections. 600179193Sjb * 601179193Sjb * The section headers describe the size, offset, alignment, and section type 602179193Sjb * for each section. Sections are described using a set of #defines that tell 603179193Sjb * the consumer what kind of data is expected. Sections can contain links to 604179193Sjb * other sections by storing a dof_secidx_t, an index into the section header 605179193Sjb * array, inside of the section data structures. The section header includes 606179193Sjb * an entry size so that sections with data arrays can grow their structures. 607179193Sjb * 608179193Sjb * The DOF data itself can contain many snippets of DIF (i.e. >1 DIFOs), which 609179193Sjb * are represented themselves as a collection of related DOF sections. This 610179193Sjb * permits us to change the set of sections associated with a DIFO over time, 611179193Sjb * and also permits us to encode DIFOs that contain different sets of sections. 612179193Sjb * When a DOF section wants to refer to a DIFO, it stores the dof_secidx_t of a 613179193Sjb * section of type DOF_SECT_DIFOHDR. This section's data is then an array of 614179193Sjb * dof_secidx_t's which in turn denote the sections associated with this DIFO. 615179193Sjb * 616179193Sjb * This loose coupling of the file structure (header and sections) to the 617179193Sjb * structure of the DTrace program itself (ECB descriptions, action 618179193Sjb * descriptions, and DIFOs) permits activities such as relocation processing 619179193Sjb * to occur in a single pass without having to understand D program structure. 620179193Sjb * 621179193Sjb * Finally, strings are always stored in ELF-style string tables along with a 622179193Sjb * string table section index and string table offset. Therefore strings in 623179193Sjb * DOF are always arbitrary-length and not bound to the current implementation. 624179193Sjb */ 625179193Sjb 626179193Sjb#define DOF_ID_SIZE 16 /* total size of dofh_ident[] in bytes */ 627179193Sjb 628179193Sjbtypedef struct dof_hdr { 629179193Sjb uint8_t dofh_ident[DOF_ID_SIZE]; /* identification bytes (see below) */ 630179193Sjb uint32_t dofh_flags; /* file attribute flags (if any) */ 631179193Sjb uint32_t dofh_hdrsize; /* size of file header in bytes */ 632179193Sjb uint32_t dofh_secsize; /* size of section header in bytes */ 633179193Sjb uint32_t dofh_secnum; /* number of section headers */ 634179193Sjb uint64_t dofh_secoff; /* file offset of section headers */ 635179193Sjb uint64_t dofh_loadsz; /* file size of loadable portion */ 636179193Sjb uint64_t dofh_filesz; /* file size of entire DOF file */ 637179193Sjb uint64_t dofh_pad; /* reserved for future use */ 638179193Sjb} dof_hdr_t; 639179193Sjb 640179193Sjb#define DOF_ID_MAG0 0 /* first byte of magic number */ 641179193Sjb#define DOF_ID_MAG1 1 /* second byte of magic number */ 642179193Sjb#define DOF_ID_MAG2 2 /* third byte of magic number */ 643179193Sjb#define DOF_ID_MAG3 3 /* fourth byte of magic number */ 644179193Sjb#define DOF_ID_MODEL 4 /* DOF data model (see below) */ 645179193Sjb#define DOF_ID_ENCODING 5 /* DOF data encoding (see below) */ 646179193Sjb#define DOF_ID_VERSION 6 /* DOF file format major version (see below) */ 647179193Sjb#define DOF_ID_DIFVERS 7 /* DIF instruction set version */ 648179193Sjb#define DOF_ID_DIFIREG 8 /* DIF integer registers used by compiler */ 649179193Sjb#define DOF_ID_DIFTREG 9 /* DIF tuple registers used by compiler */ 650179193Sjb#define DOF_ID_PAD 10 /* start of padding bytes (all zeroes) */ 651179193Sjb 652179193Sjb#define DOF_MAG_MAG0 0x7F /* DOF_ID_MAG[0-3] */ 653179193Sjb#define DOF_MAG_MAG1 'D' 654179193Sjb#define DOF_MAG_MAG2 'O' 655179193Sjb#define DOF_MAG_MAG3 'F' 656179193Sjb 657179193Sjb#define DOF_MAG_STRING "\177DOF" 658179193Sjb#define DOF_MAG_STRLEN 4 659179193Sjb 660179193Sjb#define DOF_MODEL_NONE 0 /* DOF_ID_MODEL */ 661179193Sjb#define DOF_MODEL_ILP32 1 662179193Sjb#define DOF_MODEL_LP64 2 663179193Sjb 664179193Sjb#ifdef _LP64 665179193Sjb#define DOF_MODEL_NATIVE DOF_MODEL_LP64 666179193Sjb#else 667179193Sjb#define DOF_MODEL_NATIVE DOF_MODEL_ILP32 668179193Sjb#endif 669179193Sjb 670179193Sjb#define DOF_ENCODE_NONE 0 /* DOF_ID_ENCODING */ 671179193Sjb#define DOF_ENCODE_LSB 1 672179193Sjb#define DOF_ENCODE_MSB 2 673179193Sjb 674179198Sjb#if BYTE_ORDER == _BIG_ENDIAN 675179193Sjb#define DOF_ENCODE_NATIVE DOF_ENCODE_MSB 676179193Sjb#else 677179193Sjb#define DOF_ENCODE_NATIVE DOF_ENCODE_LSB 678179193Sjb#endif 679179193Sjb 680179193Sjb#define DOF_VERSION_1 1 /* DOF version 1: Solaris 10 FCS */ 681179193Sjb#define DOF_VERSION_2 2 /* DOF version 2: Solaris Express 6/06 */ 682179193Sjb#define DOF_VERSION DOF_VERSION_2 /* Latest DOF version */ 683179193Sjb 684179193Sjb#define DOF_FL_VALID 0 /* mask of all valid dofh_flags bits */ 685179193Sjb 686179193Sjbtypedef uint32_t dof_secidx_t; /* section header table index type */ 687179193Sjbtypedef uint32_t dof_stridx_t; /* string table index type */ 688179193Sjb 689179193Sjb#define DOF_SECIDX_NONE (-1U) /* null value for section indices */ 690179193Sjb#define DOF_STRIDX_NONE (-1U) /* null value for string indices */ 691179193Sjb 692179193Sjbtypedef struct dof_sec { 693179193Sjb uint32_t dofs_type; /* section type (see below) */ 694179193Sjb uint32_t dofs_align; /* section data memory alignment */ 695179193Sjb uint32_t dofs_flags; /* section flags (if any) */ 696179193Sjb uint32_t dofs_entsize; /* size of section entry (if table) */ 697179193Sjb uint64_t dofs_offset; /* offset of section data within file */ 698179193Sjb uint64_t dofs_size; /* size of section data in bytes */ 699179193Sjb} dof_sec_t; 700179193Sjb 701179193Sjb#define DOF_SECT_NONE 0 /* null section */ 702179193Sjb#define DOF_SECT_COMMENTS 1 /* compiler comments */ 703179193Sjb#define DOF_SECT_SOURCE 2 /* D program source code */ 704179193Sjb#define DOF_SECT_ECBDESC 3 /* dof_ecbdesc_t */ 705179193Sjb#define DOF_SECT_PROBEDESC 4 /* dof_probedesc_t */ 706179193Sjb#define DOF_SECT_ACTDESC 5 /* dof_actdesc_t array */ 707179193Sjb#define DOF_SECT_DIFOHDR 6 /* dof_difohdr_t (variable length) */ 708179193Sjb#define DOF_SECT_DIF 7 /* uint32_t array of byte code */ 709179193Sjb#define DOF_SECT_STRTAB 8 /* string table */ 710179193Sjb#define DOF_SECT_VARTAB 9 /* dtrace_difv_t array */ 711179193Sjb#define DOF_SECT_RELTAB 10 /* dof_relodesc_t array */ 712179193Sjb#define DOF_SECT_TYPTAB 11 /* dtrace_diftype_t array */ 713179193Sjb#define DOF_SECT_URELHDR 12 /* dof_relohdr_t (user relocations) */ 714179193Sjb#define DOF_SECT_KRELHDR 13 /* dof_relohdr_t (kernel relocations) */ 715179193Sjb#define DOF_SECT_OPTDESC 14 /* dof_optdesc_t array */ 716179193Sjb#define DOF_SECT_PROVIDER 15 /* dof_provider_t */ 717179193Sjb#define DOF_SECT_PROBES 16 /* dof_probe_t array */ 718179193Sjb#define DOF_SECT_PRARGS 17 /* uint8_t array (probe arg mappings) */ 719179193Sjb#define DOF_SECT_PROFFS 18 /* uint32_t array (probe arg offsets) */ 720179193Sjb#define DOF_SECT_INTTAB 19 /* uint64_t array */ 721179193Sjb#define DOF_SECT_UTSNAME 20 /* struct utsname */ 722179193Sjb#define DOF_SECT_XLTAB 21 /* dof_xlref_t array */ 723179193Sjb#define DOF_SECT_XLMEMBERS 22 /* dof_xlmember_t array */ 724179193Sjb#define DOF_SECT_XLIMPORT 23 /* dof_xlator_t */ 725179193Sjb#define DOF_SECT_XLEXPORT 24 /* dof_xlator_t */ 726179193Sjb#define DOF_SECT_PREXPORT 25 /* dof_secidx_t array (exported objs) */ 727179193Sjb#define DOF_SECT_PRENOFFS 26 /* uint32_t array (enabled offsets) */ 728179193Sjb 729179193Sjb#define DOF_SECF_LOAD 1 /* section should be loaded */ 730179193Sjb 731268224Spfg#define DOF_SEC_ISLOADABLE(x) \ 732268224Spfg (((x) == DOF_SECT_ECBDESC) || ((x) == DOF_SECT_PROBEDESC) || \ 733268224Spfg ((x) == DOF_SECT_ACTDESC) || ((x) == DOF_SECT_DIFOHDR) || \ 734268224Spfg ((x) == DOF_SECT_DIF) || ((x) == DOF_SECT_STRTAB) || \ 735268224Spfg ((x) == DOF_SECT_VARTAB) || ((x) == DOF_SECT_RELTAB) || \ 736268224Spfg ((x) == DOF_SECT_TYPTAB) || ((x) == DOF_SECT_URELHDR) || \ 737268224Spfg ((x) == DOF_SECT_KRELHDR) || ((x) == DOF_SECT_OPTDESC) || \ 738268224Spfg ((x) == DOF_SECT_PROVIDER) || ((x) == DOF_SECT_PROBES) || \ 739268224Spfg ((x) == DOF_SECT_PRARGS) || ((x) == DOF_SECT_PROFFS) || \ 740268224Spfg ((x) == DOF_SECT_INTTAB) || ((x) == DOF_SECT_XLTAB) || \ 741268224Spfg ((x) == DOF_SECT_XLMEMBERS) || ((x) == DOF_SECT_XLIMPORT) || \ 742310795Sgnn ((x) == DOF_SECT_XLEXPORT) || ((x) == DOF_SECT_PREXPORT) || \ 743310795Sgnn ((x) == DOF_SECT_PRENOFFS)) 744268224Spfg 745179193Sjbtypedef struct dof_ecbdesc { 746179193Sjb dof_secidx_t dofe_probes; /* link to DOF_SECT_PROBEDESC */ 747179193Sjb dof_secidx_t dofe_pred; /* link to DOF_SECT_DIFOHDR */ 748179193Sjb dof_secidx_t dofe_actions; /* link to DOF_SECT_ACTDESC */ 749179193Sjb uint32_t dofe_pad; /* reserved for future use */ 750179193Sjb uint64_t dofe_uarg; /* user-supplied library argument */ 751179193Sjb} dof_ecbdesc_t; 752179193Sjb 753179193Sjbtypedef struct dof_probedesc { 754179193Sjb dof_secidx_t dofp_strtab; /* link to DOF_SECT_STRTAB section */ 755179193Sjb dof_stridx_t dofp_provider; /* provider string */ 756179193Sjb dof_stridx_t dofp_mod; /* module string */ 757179193Sjb dof_stridx_t dofp_func; /* function string */ 758179193Sjb dof_stridx_t dofp_name; /* name string */ 759179193Sjb uint32_t dofp_id; /* probe identifier (or zero) */ 760179193Sjb} dof_probedesc_t; 761179193Sjb 762179193Sjbtypedef struct dof_actdesc { 763179193Sjb dof_secidx_t dofa_difo; /* link to DOF_SECT_DIFOHDR */ 764179193Sjb dof_secidx_t dofa_strtab; /* link to DOF_SECT_STRTAB section */ 765179193Sjb uint32_t dofa_kind; /* action kind (DTRACEACT_* constant) */ 766179193Sjb uint32_t dofa_ntuple; /* number of subsequent tuple actions */ 767179193Sjb uint64_t dofa_arg; /* kind-specific argument */ 768179193Sjb uint64_t dofa_uarg; /* user-supplied argument */ 769179193Sjb} dof_actdesc_t; 770179193Sjb 771179193Sjbtypedef struct dof_difohdr { 772179193Sjb dtrace_diftype_t dofd_rtype; /* return type for this fragment */ 773179193Sjb dof_secidx_t dofd_links[1]; /* variable length array of indices */ 774179193Sjb} dof_difohdr_t; 775179193Sjb 776179193Sjbtypedef struct dof_relohdr { 777179193Sjb dof_secidx_t dofr_strtab; /* link to DOF_SECT_STRTAB for names */ 778179193Sjb dof_secidx_t dofr_relsec; /* link to DOF_SECT_RELTAB for relos */ 779179193Sjb dof_secidx_t dofr_tgtsec; /* link to section we are relocating */ 780179193Sjb} dof_relohdr_t; 781179193Sjb 782179193Sjbtypedef struct dof_relodesc { 783179193Sjb dof_stridx_t dofr_name; /* string name of relocation symbol */ 784179193Sjb uint32_t dofr_type; /* relo type (DOF_RELO_* constant) */ 785179193Sjb uint64_t dofr_offset; /* byte offset for relocation */ 786179193Sjb uint64_t dofr_data; /* additional type-specific data */ 787179193Sjb} dof_relodesc_t; 788179193Sjb 789179193Sjb#define DOF_RELO_NONE 0 /* empty relocation entry */ 790179193Sjb#define DOF_RELO_SETX 1 /* relocate setx value */ 791361088Sdim#define DOF_RELO_DOFREL 2 /* relocate DOF-relative value */ 792179193Sjb 793179193Sjbtypedef struct dof_optdesc { 794179193Sjb uint32_t dofo_option; /* option identifier */ 795179193Sjb dof_secidx_t dofo_strtab; /* string table, if string option */ 796179193Sjb uint64_t dofo_value; /* option value or string index */ 797179193Sjb} dof_optdesc_t; 798179193Sjb 799179193Sjbtypedef uint32_t dof_attr_t; /* encoded stability attributes */ 800179193Sjb 801179193Sjb#define DOF_ATTR(n, d, c) (((n) << 24) | ((d) << 16) | ((c) << 8)) 802179193Sjb#define DOF_ATTR_NAME(a) (((a) >> 24) & 0xff) 803179193Sjb#define DOF_ATTR_DATA(a) (((a) >> 16) & 0xff) 804179193Sjb#define DOF_ATTR_CLASS(a) (((a) >> 8) & 0xff) 805179193Sjb 806179193Sjbtypedef struct dof_provider { 807179193Sjb dof_secidx_t dofpv_strtab; /* link to DOF_SECT_STRTAB section */ 808179193Sjb dof_secidx_t dofpv_probes; /* link to DOF_SECT_PROBES section */ 809179193Sjb dof_secidx_t dofpv_prargs; /* link to DOF_SECT_PRARGS section */ 810179193Sjb dof_secidx_t dofpv_proffs; /* link to DOF_SECT_PROFFS section */ 811179193Sjb dof_stridx_t dofpv_name; /* provider name string */ 812179193Sjb dof_attr_t dofpv_provattr; /* provider attributes */ 813179193Sjb dof_attr_t dofpv_modattr; /* module attributes */ 814179193Sjb dof_attr_t dofpv_funcattr; /* function attributes */ 815179193Sjb dof_attr_t dofpv_nameattr; /* name attributes */ 816179193Sjb dof_attr_t dofpv_argsattr; /* args attributes */ 817179193Sjb dof_secidx_t dofpv_prenoffs; /* link to DOF_SECT_PRENOFFS section */ 818179193Sjb} dof_provider_t; 819179193Sjb 820179193Sjbtypedef struct dof_probe { 821179193Sjb uint64_t dofpr_addr; /* probe base address or offset */ 822179193Sjb dof_stridx_t dofpr_func; /* probe function string */ 823179193Sjb dof_stridx_t dofpr_name; /* probe name string */ 824179193Sjb dof_stridx_t dofpr_nargv; /* native argument type strings */ 825179193Sjb dof_stridx_t dofpr_xargv; /* translated argument type strings */ 826179193Sjb uint32_t dofpr_argidx; /* index of first argument mapping */ 827179193Sjb uint32_t dofpr_offidx; /* index of first offset entry */ 828179193Sjb uint8_t dofpr_nargc; /* native argument count */ 829179193Sjb uint8_t dofpr_xargc; /* translated argument count */ 830179193Sjb uint16_t dofpr_noffs; /* number of offset entries for probe */ 831179193Sjb uint32_t dofpr_enoffidx; /* index of first is-enabled offset */ 832179193Sjb uint16_t dofpr_nenoffs; /* number of is-enabled offsets */ 833179193Sjb uint16_t dofpr_pad1; /* reserved for future use */ 834179193Sjb uint32_t dofpr_pad2; /* reserved for future use */ 835179193Sjb} dof_probe_t; 836179193Sjb 837179193Sjbtypedef struct dof_xlator { 838179193Sjb dof_secidx_t dofxl_members; /* link to DOF_SECT_XLMEMBERS section */ 839179193Sjb dof_secidx_t dofxl_strtab; /* link to DOF_SECT_STRTAB section */ 840179193Sjb dof_stridx_t dofxl_argv; /* input parameter type strings */ 841179193Sjb uint32_t dofxl_argc; /* input parameter list length */ 842179193Sjb dof_stridx_t dofxl_type; /* output type string name */ 843179193Sjb dof_attr_t dofxl_attr; /* output stability attributes */ 844179193Sjb} dof_xlator_t; 845179193Sjb 846179193Sjbtypedef struct dof_xlmember { 847179193Sjb dof_secidx_t dofxm_difo; /* member link to DOF_SECT_DIFOHDR */ 848179193Sjb dof_stridx_t dofxm_name; /* member name */ 849179193Sjb dtrace_diftype_t dofxm_type; /* member type */ 850179193Sjb} dof_xlmember_t; 851179193Sjb 852179193Sjbtypedef struct dof_xlref { 853179193Sjb dof_secidx_t dofxr_xlator; /* link to DOF_SECT_XLATORS section */ 854179193Sjb uint32_t dofxr_member; /* index of referenced dof_xlmember */ 855179193Sjb uint32_t dofxr_argn; /* index of argument for DIF_OP_XLARG */ 856179193Sjb} dof_xlref_t; 857179193Sjb 858179193Sjb/* 859179193Sjb * DTrace Intermediate Format Object (DIFO) 860179193Sjb * 861179193Sjb * A DIFO is used to store the compiled DIF for a D expression, its return 862179193Sjb * type, and its string and variable tables. The string table is a single 863179193Sjb * buffer of character data into which sets instructions and variable 864179193Sjb * references can reference strings using a byte offset. The variable table 865179193Sjb * is an array of dtrace_difv_t structures that describe the name and type of 866179193Sjb * each variable and the id used in the DIF code. This structure is described 867179193Sjb * above in the DIF section of this header file. The DIFO is used at both 868179193Sjb * user-level (in the library) and in the kernel, but the structure is never 869179193Sjb * passed between the two: the DOF structures form the only interface. As a 870179193Sjb * result, the definition can change depending on the presence of _KERNEL. 871179193Sjb */ 872179193Sjbtypedef struct dtrace_difo { 873179193Sjb dif_instr_t *dtdo_buf; /* instruction buffer */ 874179193Sjb uint64_t *dtdo_inttab; /* integer table (optional) */ 875179193Sjb char *dtdo_strtab; /* string table (optional) */ 876179193Sjb dtrace_difv_t *dtdo_vartab; /* variable table (optional) */ 877179193Sjb uint_t dtdo_len; /* length of instruction buffer */ 878179193Sjb uint_t dtdo_intlen; /* length of integer table */ 879179193Sjb uint_t dtdo_strlen; /* length of string table */ 880179193Sjb uint_t dtdo_varlen; /* length of variable table */ 881179193Sjb dtrace_diftype_t dtdo_rtype; /* return type */ 882179193Sjb uint_t dtdo_refcnt; /* owner reference count */ 883179193Sjb uint_t dtdo_destructive; /* invokes destructive subroutines */ 884179193Sjb#ifndef _KERNEL 885179193Sjb dof_relodesc_t *dtdo_kreltab; /* kernel relocations */ 886179193Sjb dof_relodesc_t *dtdo_ureltab; /* user relocations */ 887179193Sjb struct dt_node **dtdo_xlmtab; /* translator references */ 888179193Sjb uint_t dtdo_krelen; /* length of krelo table */ 889179193Sjb uint_t dtdo_urelen; /* length of urelo table */ 890179193Sjb uint_t dtdo_xlmlen; /* length of translator table */ 891179193Sjb#endif 892179193Sjb} dtrace_difo_t; 893179193Sjb 894179193Sjb/* 895179193Sjb * DTrace Enabling Description Structures 896179193Sjb * 897179193Sjb * When DTrace is tracking the description of a DTrace enabling entity (probe, 898179193Sjb * predicate, action, ECB, record, etc.), it does so in a description 899179193Sjb * structure. These structures all end in "desc", and are used at both 900179193Sjb * user-level and in the kernel -- but (with the exception of 901179193Sjb * dtrace_probedesc_t) they are never passed between them. Typically, 902179193Sjb * user-level will use the description structures when assembling an enabling. 903179193Sjb * It will then distill those description structures into a DOF object (see 904179193Sjb * above), and send it into the kernel. The kernel will again use the 905179193Sjb * description structures to create a description of the enabling as it reads 906179193Sjb * the DOF. When the description is complete, the enabling will be actually 907179193Sjb * created -- turning it into the structures that represent the enabling 908179193Sjb * instead of merely describing it. Not surprisingly, the description 909179193Sjb * structures bear a strong resemblance to the DOF structures that act as their 910179193Sjb * conduit. 911179193Sjb */ 912179193Sjbstruct dtrace_predicate; 913179193Sjb 914179193Sjbtypedef struct dtrace_probedesc { 915179193Sjb dtrace_id_t dtpd_id; /* probe identifier */ 916179193Sjb char dtpd_provider[DTRACE_PROVNAMELEN]; /* probe provider name */ 917179193Sjb char dtpd_mod[DTRACE_MODNAMELEN]; /* probe module name */ 918179193Sjb char dtpd_func[DTRACE_FUNCNAMELEN]; /* probe function name */ 919179193Sjb char dtpd_name[DTRACE_NAMELEN]; /* probe name */ 920179193Sjb} dtrace_probedesc_t; 921179193Sjb 922179193Sjbtypedef struct dtrace_repldesc { 923179193Sjb dtrace_probedesc_t dtrpd_match; /* probe descr. to match */ 924179193Sjb dtrace_probedesc_t dtrpd_create; /* probe descr. to create */ 925179193Sjb} dtrace_repldesc_t; 926179193Sjb 927179193Sjbtypedef struct dtrace_preddesc { 928179193Sjb dtrace_difo_t *dtpdd_difo; /* pointer to DIF object */ 929179193Sjb struct dtrace_predicate *dtpdd_predicate; /* pointer to predicate */ 930179193Sjb} dtrace_preddesc_t; 931179193Sjb 932179193Sjbtypedef struct dtrace_actdesc { 933179193Sjb dtrace_difo_t *dtad_difo; /* pointer to DIF object */ 934179193Sjb struct dtrace_actdesc *dtad_next; /* next action */ 935179193Sjb dtrace_actkind_t dtad_kind; /* kind of action */ 936179193Sjb uint32_t dtad_ntuple; /* number in tuple */ 937179193Sjb uint64_t dtad_arg; /* action argument */ 938179193Sjb uint64_t dtad_uarg; /* user argument */ 939179193Sjb int dtad_refcnt; /* reference count */ 940179193Sjb} dtrace_actdesc_t; 941179193Sjb 942179193Sjbtypedef struct dtrace_ecbdesc { 943179193Sjb dtrace_actdesc_t *dted_action; /* action description(s) */ 944179193Sjb dtrace_preddesc_t dted_pred; /* predicate description */ 945179193Sjb dtrace_probedesc_t dted_probe; /* probe description */ 946179193Sjb uint64_t dted_uarg; /* library argument */ 947179193Sjb int dted_refcnt; /* reference count */ 948179193Sjb} dtrace_ecbdesc_t; 949179193Sjb 950179193Sjb/* 951179193Sjb * DTrace Metadata Description Structures 952179193Sjb * 953179193Sjb * DTrace separates the trace data stream from the metadata stream. The only 954250574Smarkj * metadata tokens placed in the data stream are the dtrace_rechdr_t (EPID + 955250574Smarkj * timestamp) or (in the case of aggregations) aggregation identifiers. To 956250574Smarkj * determine the structure of the data, DTrace consumers pass the token to the 957250574Smarkj * kernel, and receive in return a corresponding description of the enabled 958179193Sjb * probe (via the dtrace_eprobedesc structure) or the aggregation (via the 959179193Sjb * dtrace_aggdesc structure). Both of these structures are expressed in terms 960179193Sjb * of record descriptions (via the dtrace_recdesc structure) that describe the 961179193Sjb * exact structure of the data. Some record descriptions may also contain a 962179193Sjb * format identifier; this additional bit of metadata can be retrieved from the 963179193Sjb * kernel, for which a format description is returned via the dtrace_fmtdesc 964179193Sjb * structure. Note that all four of these structures must be bitness-neutral 965179193Sjb * to allow for a 32-bit DTrace consumer on a 64-bit kernel. 966179193Sjb */ 967179193Sjbtypedef struct dtrace_recdesc { 968179193Sjb dtrace_actkind_t dtrd_action; /* kind of action */ 969179193Sjb uint32_t dtrd_size; /* size of record */ 970179193Sjb uint32_t dtrd_offset; /* offset in ECB's data */ 971179193Sjb uint16_t dtrd_alignment; /* required alignment */ 972179193Sjb uint16_t dtrd_format; /* format, if any */ 973179193Sjb uint64_t dtrd_arg; /* action argument */ 974179193Sjb uint64_t dtrd_uarg; /* user argument */ 975179193Sjb} dtrace_recdesc_t; 976179193Sjb 977179193Sjbtypedef struct dtrace_eprobedesc { 978179193Sjb dtrace_epid_t dtepd_epid; /* enabled probe ID */ 979179193Sjb dtrace_id_t dtepd_probeid; /* probe ID */ 980179193Sjb uint64_t dtepd_uarg; /* library argument */ 981179193Sjb uint32_t dtepd_size; /* total size */ 982179193Sjb int dtepd_nrecs; /* number of records */ 983179193Sjb dtrace_recdesc_t dtepd_rec[1]; /* records themselves */ 984179193Sjb} dtrace_eprobedesc_t; 985179193Sjb 986179193Sjbtypedef struct dtrace_aggdesc { 987179193Sjb DTRACE_PTR(char, dtagd_name); /* not filled in by kernel */ 988179193Sjb dtrace_aggvarid_t dtagd_varid; /* not filled in by kernel */ 989179193Sjb int dtagd_flags; /* not filled in by kernel */ 990179193Sjb dtrace_aggid_t dtagd_id; /* aggregation ID */ 991179193Sjb dtrace_epid_t dtagd_epid; /* enabled probe ID */ 992179193Sjb uint32_t dtagd_size; /* size in bytes */ 993179193Sjb int dtagd_nrecs; /* number of records */ 994179193Sjb uint32_t dtagd_pad; /* explicit padding */ 995179193Sjb dtrace_recdesc_t dtagd_rec[1]; /* record descriptions */ 996179193Sjb} dtrace_aggdesc_t; 997179193Sjb 998179193Sjbtypedef struct dtrace_fmtdesc { 999179193Sjb DTRACE_PTR(char, dtfd_string); /* format string */ 1000179193Sjb int dtfd_length; /* length of format string */ 1001179193Sjb uint16_t dtfd_format; /* format identifier */ 1002179193Sjb} dtrace_fmtdesc_t; 1003179193Sjb 1004179193Sjb#define DTRACE_SIZEOF_EPROBEDESC(desc) \ 1005179193Sjb (sizeof (dtrace_eprobedesc_t) + ((desc)->dtepd_nrecs ? \ 1006179193Sjb (((desc)->dtepd_nrecs - 1) * sizeof (dtrace_recdesc_t)) : 0)) 1007179193Sjb 1008179193Sjb#define DTRACE_SIZEOF_AGGDESC(desc) \ 1009179193Sjb (sizeof (dtrace_aggdesc_t) + ((desc)->dtagd_nrecs ? \ 1010179193Sjb (((desc)->dtagd_nrecs - 1) * sizeof (dtrace_recdesc_t)) : 0)) 1011179193Sjb 1012179193Sjb/* 1013179193Sjb * DTrace Option Interface 1014179193Sjb * 1015179193Sjb * Run-time DTrace options are set and retrieved via DOF_SECT_OPTDESC sections 1016179193Sjb * in a DOF image. The dof_optdesc structure contains an option identifier and 1017179193Sjb * an option value. The valid option identifiers are found below; the mapping 1018179193Sjb * between option identifiers and option identifying strings is maintained at 1019179193Sjb * user-level. Note that the value of DTRACEOPT_UNSET is such that all of the 1020179193Sjb * following are potentially valid option values: all positive integers, zero 1021179193Sjb * and negative one. Some options (notably "bufpolicy" and "bufresize") take 1022179193Sjb * predefined tokens as their values; these are defined with 1023179193Sjb * DTRACEOPT_{option}_{token}. 1024179193Sjb */ 1025179193Sjb#define DTRACEOPT_BUFSIZE 0 /* buffer size */ 1026179193Sjb#define DTRACEOPT_BUFPOLICY 1 /* buffer policy */ 1027179193Sjb#define DTRACEOPT_DYNVARSIZE 2 /* dynamic variable size */ 1028179193Sjb#define DTRACEOPT_AGGSIZE 3 /* aggregation size */ 1029179193Sjb#define DTRACEOPT_SPECSIZE 4 /* speculation size */ 1030179193Sjb#define DTRACEOPT_NSPEC 5 /* number of speculations */ 1031179193Sjb#define DTRACEOPT_STRSIZE 6 /* string size */ 1032179193Sjb#define DTRACEOPT_CLEANRATE 7 /* dynvar cleaning rate */ 1033179193Sjb#define DTRACEOPT_CPU 8 /* CPU to trace */ 1034179193Sjb#define DTRACEOPT_BUFRESIZE 9 /* buffer resizing policy */ 1035179193Sjb#define DTRACEOPT_GRABANON 10 /* grab anonymous state, if any */ 1036179193Sjb#define DTRACEOPT_FLOWINDENT 11 /* indent function entry/return */ 1037179193Sjb#define DTRACEOPT_QUIET 12 /* only output explicitly traced data */ 1038179193Sjb#define DTRACEOPT_STACKFRAMES 13 /* number of stack frames */ 1039179193Sjb#define DTRACEOPT_USTACKFRAMES 14 /* number of user stack frames */ 1040179193Sjb#define DTRACEOPT_AGGRATE 15 /* aggregation snapshot rate */ 1041179193Sjb#define DTRACEOPT_SWITCHRATE 16 /* buffer switching rate */ 1042179193Sjb#define DTRACEOPT_STATUSRATE 17 /* status rate */ 1043179193Sjb#define DTRACEOPT_DESTRUCTIVE 18 /* destructive actions allowed */ 1044179193Sjb#define DTRACEOPT_STACKINDENT 19 /* output indent for stack traces */ 1045179193Sjb#define DTRACEOPT_RAWBYTES 20 /* always print bytes in raw form */ 1046179193Sjb#define DTRACEOPT_JSTACKFRAMES 21 /* number of jstack() frames */ 1047179193Sjb#define DTRACEOPT_JSTACKSTRSIZE 22 /* size of jstack() string table */ 1048179193Sjb#define DTRACEOPT_AGGSORTKEY 23 /* sort aggregations by key */ 1049179193Sjb#define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */ 1050179193Sjb#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */ 1051179193Sjb#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */ 1052250574Smarkj#define DTRACEOPT_TEMPORAL 27 /* temporally ordered output */ 1053267942Srpaulo#define DTRACEOPT_AGGHIST 28 /* histogram aggregation output */ 1054267942Srpaulo#define DTRACEOPT_AGGPACK 29 /* packed aggregation output */ 1055267942Srpaulo#define DTRACEOPT_AGGZOOM 30 /* zoomed aggregation scaling */ 1056267942Srpaulo#define DTRACEOPT_ZONE 31 /* zone in which to enable probes */ 1057267942Srpaulo#define DTRACEOPT_MAX 32 /* number of options */ 1058179193Sjb 1059179193Sjb#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */ 1060179193Sjb 1061179193Sjb#define DTRACEOPT_BUFPOLICY_RING 0 /* ring buffer */ 1062179193Sjb#define DTRACEOPT_BUFPOLICY_FILL 1 /* fill buffer, then stop */ 1063179193Sjb#define DTRACEOPT_BUFPOLICY_SWITCH 2 /* switch buffers */ 1064179193Sjb 1065179193Sjb#define DTRACEOPT_BUFRESIZE_AUTO 0 /* automatic resizing */ 1066179193Sjb#define DTRACEOPT_BUFRESIZE_MANUAL 1 /* manual resizing */ 1067179193Sjb 1068179193Sjb/* 1069179193Sjb * DTrace Buffer Interface 1070179193Sjb * 1071179193Sjb * In order to get a snapshot of the principal or aggregation buffer, 1072179193Sjb * user-level passes a buffer description to the kernel with the dtrace_bufdesc 1073179193Sjb * structure. This describes which CPU user-level is interested in, and 1074179193Sjb * where user-level wishes the kernel to snapshot the buffer to (the 1075179193Sjb * dtbd_data field). The kernel uses the same structure to pass back some 1076179193Sjb * information regarding the buffer: the size of data actually copied out, the 1077250574Smarkj * number of drops, the number of errors, the offset of the oldest record, 1078250574Smarkj * and the time of the snapshot. 1079250574Smarkj * 1080179193Sjb * If the buffer policy is a "switch" policy, taking a snapshot of the 1081179193Sjb * principal buffer has the additional effect of switching the active and 1082179193Sjb * inactive buffers. Taking a snapshot of the aggregation buffer _always_ has 1083179193Sjb * the additional effect of switching the active and inactive buffers. 1084179193Sjb */ 1085179193Sjbtypedef struct dtrace_bufdesc { 1086179193Sjb uint64_t dtbd_size; /* size of buffer */ 1087179193Sjb uint32_t dtbd_cpu; /* CPU or DTRACE_CPUALL */ 1088179193Sjb uint32_t dtbd_errors; /* number of errors */ 1089179193Sjb uint64_t dtbd_drops; /* number of drops */ 1090179193Sjb DTRACE_PTR(char, dtbd_data); /* data */ 1091179193Sjb uint64_t dtbd_oldest; /* offset of oldest record */ 1092250574Smarkj uint64_t dtbd_timestamp; /* hrtime of snapshot */ 1093179193Sjb} dtrace_bufdesc_t; 1094179193Sjb 1095179193Sjb/* 1096250574Smarkj * Each record in the buffer (dtbd_data) begins with a header that includes 1097250574Smarkj * the epid and a timestamp. The timestamp is split into two 4-byte parts 1098250574Smarkj * so that we do not require 8-byte alignment. 1099250574Smarkj */ 1100250574Smarkjtypedef struct dtrace_rechdr { 1101250574Smarkj dtrace_epid_t dtrh_epid; /* enabled probe id */ 1102250574Smarkj uint32_t dtrh_timestamp_hi; /* high bits of hrtime_t */ 1103250574Smarkj uint32_t dtrh_timestamp_lo; /* low bits of hrtime_t */ 1104250574Smarkj} dtrace_rechdr_t; 1105250574Smarkj 1106250574Smarkj#define DTRACE_RECORD_LOAD_TIMESTAMP(dtrh) \ 1107250574Smarkj ((dtrh)->dtrh_timestamp_lo + \ 1108250574Smarkj ((uint64_t)(dtrh)->dtrh_timestamp_hi << 32)) 1109250574Smarkj 1110250574Smarkj#define DTRACE_RECORD_STORE_TIMESTAMP(dtrh, hrtime) { \ 1111250574Smarkj (dtrh)->dtrh_timestamp_lo = (uint32_t)hrtime; \ 1112250574Smarkj (dtrh)->dtrh_timestamp_hi = hrtime >> 32; \ 1113250574Smarkj} 1114250574Smarkj 1115250574Smarkj/* 1116179193Sjb * DTrace Status 1117179193Sjb * 1118179193Sjb * The status of DTrace is relayed via the dtrace_status structure. This 1119179193Sjb * structure contains members to count drops other than the capacity drops 1120179193Sjb * available via the buffer interface (see above). This consists of dynamic 1121179193Sjb * drops (including capacity dynamic drops, rinsing drops and dirty drops), and 1122179193Sjb * speculative drops (including capacity speculative drops, drops due to busy 1123179193Sjb * speculative buffers and drops due to unavailable speculative buffers). 1124179193Sjb * Additionally, the status structure contains a field to indicate the number 1125179193Sjb * of "fill"-policy buffers have been filled and a boolean field to indicate 1126179193Sjb * that exit() has been called. If the dtst_exiting field is non-zero, no 1127179193Sjb * further data will be generated until tracing is stopped (at which time any 1128179193Sjb * enablings of the END action will be processed); if user-level sees that 1129179193Sjb * this field is non-zero, tracing should be stopped as soon as possible. 1130179193Sjb */ 1131179193Sjbtypedef struct dtrace_status { 1132179193Sjb uint64_t dtst_dyndrops; /* dynamic drops */ 1133179193Sjb uint64_t dtst_dyndrops_rinsing; /* dyn drops due to rinsing */ 1134179193Sjb uint64_t dtst_dyndrops_dirty; /* dyn drops due to dirty */ 1135179193Sjb uint64_t dtst_specdrops; /* speculative drops */ 1136179193Sjb uint64_t dtst_specdrops_busy; /* spec drops due to busy */ 1137179193Sjb uint64_t dtst_specdrops_unavail; /* spec drops due to unavail */ 1138179193Sjb uint64_t dtst_errors; /* total errors */ 1139179193Sjb uint64_t dtst_filled; /* number of filled bufs */ 1140179193Sjb uint64_t dtst_stkstroverflows; /* stack string tab overflows */ 1141179193Sjb uint64_t dtst_dblerrors; /* errors in ERROR probes */ 1142179193Sjb char dtst_killed; /* non-zero if killed */ 1143179193Sjb char dtst_exiting; /* non-zero if exit() called */ 1144179193Sjb char dtst_pad[6]; /* pad out to 64-bit align */ 1145179193Sjb} dtrace_status_t; 1146179193Sjb 1147179193Sjb/* 1148179193Sjb * DTrace Configuration 1149179193Sjb * 1150179193Sjb * User-level may need to understand some elements of the kernel DTrace 1151179193Sjb * configuration in order to generate correct DIF. This information is 1152179193Sjb * conveyed via the dtrace_conf structure. 1153179193Sjb */ 1154179193Sjbtypedef struct dtrace_conf { 1155179193Sjb uint_t dtc_difversion; /* supported DIF version */ 1156179193Sjb uint_t dtc_difintregs; /* # of DIF integer registers */ 1157179193Sjb uint_t dtc_diftupregs; /* # of DIF tuple registers */ 1158179193Sjb uint_t dtc_ctfmodel; /* CTF data model */ 1159179193Sjb uint_t dtc_pad[8]; /* reserved for future use */ 1160179193Sjb} dtrace_conf_t; 1161179193Sjb 1162179193Sjb/* 1163179193Sjb * DTrace Faults 1164179193Sjb * 1165179193Sjb * The constants below DTRACEFLT_LIBRARY indicate probe processing faults; 1166179193Sjb * constants at or above DTRACEFLT_LIBRARY indicate faults in probe 1167179193Sjb * postprocessing at user-level. Probe processing faults induce an ERROR 1168179193Sjb * probe and are replicated in unistd.d to allow users' ERROR probes to decode 1169179193Sjb * the error condition using thse symbolic labels. 1170179193Sjb */ 1171179193Sjb#define DTRACEFLT_UNKNOWN 0 /* Unknown fault */ 1172179193Sjb#define DTRACEFLT_BADADDR 1 /* Bad address */ 1173179193Sjb#define DTRACEFLT_BADALIGN 2 /* Bad alignment */ 1174179193Sjb#define DTRACEFLT_ILLOP 3 /* Illegal operation */ 1175179193Sjb#define DTRACEFLT_DIVZERO 4 /* Divide-by-zero */ 1176179193Sjb#define DTRACEFLT_NOSCRATCH 5 /* Out of scratch space */ 1177179193Sjb#define DTRACEFLT_KPRIV 6 /* Illegal kernel access */ 1178179193Sjb#define DTRACEFLT_UPRIV 7 /* Illegal user access */ 1179179193Sjb#define DTRACEFLT_TUPOFLOW 8 /* Tuple stack overflow */ 1180179193Sjb#define DTRACEFLT_BADSTACK 9 /* Bad stack */ 1181179193Sjb 1182179193Sjb#define DTRACEFLT_LIBRARY 1000 /* Library-level fault */ 1183179193Sjb 1184179193Sjb/* 1185179193Sjb * DTrace Argument Types 1186179193Sjb * 1187179193Sjb * Because it would waste both space and time, argument types do not reside 1188179193Sjb * with the probe. In order to determine argument types for args[X] 1189179193Sjb * variables, the D compiler queries for argument types on a probe-by-probe 1190179193Sjb * basis. (This optimizes for the common case that arguments are either not 1191179193Sjb * used or used in an untyped fashion.) Typed arguments are specified with a 1192179193Sjb * string of the type name in the dtragd_native member of the argument 1193179193Sjb * description structure. Typed arguments may be further translated to types 1194179193Sjb * of greater stability; the provider indicates such a translated argument by 1195179193Sjb * filling in the dtargd_xlate member with the string of the translated type. 1196179193Sjb * Finally, the provider may indicate which argument value a given argument 1197179193Sjb * maps to by setting the dtargd_mapping member -- allowing a single argument 1198179193Sjb * to map to multiple args[X] variables. 1199179193Sjb */ 1200179193Sjbtypedef struct dtrace_argdesc { 1201179193Sjb dtrace_id_t dtargd_id; /* probe identifier */ 1202179193Sjb int dtargd_ndx; /* arg number (-1 iff none) */ 1203179193Sjb int dtargd_mapping; /* value mapping */ 1204179193Sjb char dtargd_native[DTRACE_ARGTYPELEN]; /* native type name */ 1205179193Sjb char dtargd_xlate[DTRACE_ARGTYPELEN]; /* translated type name */ 1206179193Sjb} dtrace_argdesc_t; 1207179193Sjb 1208179193Sjb/* 1209179193Sjb * DTrace Stability Attributes 1210179193Sjb * 1211179193Sjb * Each DTrace provider advertises the name and data stability of each of its 1212179193Sjb * probe description components, as well as its architectural dependencies. 1213179193Sjb * The D compiler can query the provider attributes (dtrace_pattr_t below) in 1214179193Sjb * order to compute the properties of an input program and report them. 1215179193Sjb */ 1216179193Sjbtypedef uint8_t dtrace_stability_t; /* stability code (see attributes(5)) */ 1217179193Sjbtypedef uint8_t dtrace_class_t; /* architectural dependency class */ 1218179193Sjb 1219179193Sjb#define DTRACE_STABILITY_INTERNAL 0 /* private to DTrace itself */ 1220179193Sjb#define DTRACE_STABILITY_PRIVATE 1 /* private to Sun (see docs) */ 1221179193Sjb#define DTRACE_STABILITY_OBSOLETE 2 /* scheduled for removal */ 1222179193Sjb#define DTRACE_STABILITY_EXTERNAL 3 /* not controlled by Sun */ 1223179193Sjb#define DTRACE_STABILITY_UNSTABLE 4 /* new or rapidly changing */ 1224179193Sjb#define DTRACE_STABILITY_EVOLVING 5 /* less rapidly changing */ 1225179193Sjb#define DTRACE_STABILITY_STABLE 6 /* mature interface from Sun */ 1226179193Sjb#define DTRACE_STABILITY_STANDARD 7 /* industry standard */ 1227179193Sjb#define DTRACE_STABILITY_MAX 7 /* maximum valid stability */ 1228179193Sjb 1229179193Sjb#define DTRACE_CLASS_UNKNOWN 0 /* unknown architectural dependency */ 1230179193Sjb#define DTRACE_CLASS_CPU 1 /* CPU-module-specific */ 1231179193Sjb#define DTRACE_CLASS_PLATFORM 2 /* platform-specific (uname -i) */ 1232179193Sjb#define DTRACE_CLASS_GROUP 3 /* hardware-group-specific (uname -m) */ 1233179193Sjb#define DTRACE_CLASS_ISA 4 /* ISA-specific (uname -p) */ 1234179193Sjb#define DTRACE_CLASS_COMMON 5 /* common to all systems */ 1235179193Sjb#define DTRACE_CLASS_MAX 5 /* maximum valid class */ 1236179193Sjb 1237179193Sjb#define DTRACE_PRIV_NONE 0x0000 1238179193Sjb#define DTRACE_PRIV_KERNEL 0x0001 1239179193Sjb#define DTRACE_PRIV_USER 0x0002 1240179193Sjb#define DTRACE_PRIV_PROC 0x0004 1241179193Sjb#define DTRACE_PRIV_OWNER 0x0008 1242179193Sjb#define DTRACE_PRIV_ZONEOWNER 0x0010 1243179193Sjb 1244179193Sjb#define DTRACE_PRIV_ALL \ 1245179193Sjb (DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER | \ 1246179193Sjb DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER | DTRACE_PRIV_ZONEOWNER) 1247179193Sjb 1248179193Sjbtypedef struct dtrace_ppriv { 1249179193Sjb uint32_t dtpp_flags; /* privilege flags */ 1250179193Sjb uid_t dtpp_uid; /* user ID */ 1251179193Sjb zoneid_t dtpp_zoneid; /* zone ID */ 1252179193Sjb} dtrace_ppriv_t; 1253179193Sjb 1254179193Sjbtypedef struct dtrace_attribute { 1255179193Sjb dtrace_stability_t dtat_name; /* entity name stability */ 1256179193Sjb dtrace_stability_t dtat_data; /* entity data stability */ 1257179193Sjb dtrace_class_t dtat_class; /* entity data dependency */ 1258179193Sjb} dtrace_attribute_t; 1259179193Sjb 1260179193Sjbtypedef struct dtrace_pattr { 1261179193Sjb dtrace_attribute_t dtpa_provider; /* provider attributes */ 1262179193Sjb dtrace_attribute_t dtpa_mod; /* module attributes */ 1263179193Sjb dtrace_attribute_t dtpa_func; /* function attributes */ 1264179193Sjb dtrace_attribute_t dtpa_name; /* name attributes */ 1265179193Sjb dtrace_attribute_t dtpa_args; /* args[] attributes */ 1266179193Sjb} dtrace_pattr_t; 1267179193Sjb 1268179193Sjbtypedef struct dtrace_providerdesc { 1269179193Sjb char dtvd_name[DTRACE_PROVNAMELEN]; /* provider name */ 1270179193Sjb dtrace_pattr_t dtvd_attr; /* stability attributes */ 1271179193Sjb dtrace_ppriv_t dtvd_priv; /* privileges required */ 1272179193Sjb} dtrace_providerdesc_t; 1273179193Sjb 1274179193Sjb/* 1275179193Sjb * DTrace Pseudodevice Interface 1276179193Sjb * 1277179193Sjb * DTrace is controlled through ioctl(2)'s to the in-kernel dtrace:dtrace 1278179193Sjb * pseudodevice driver. These ioctls comprise the user-kernel interface to 1279179193Sjb * DTrace. 1280179193Sjb */ 1281277300Ssmh#ifdef illumos 1282179193Sjb#define DTRACEIOC (('d' << 24) | ('t' << 16) | ('r' << 8)) 1283179193Sjb#define DTRACEIOC_PROVIDER (DTRACEIOC | 1) /* provider query */ 1284179193Sjb#define DTRACEIOC_PROBES (DTRACEIOC | 2) /* probe query */ 1285179193Sjb#define DTRACEIOC_BUFSNAP (DTRACEIOC | 4) /* snapshot buffer */ 1286179193Sjb#define DTRACEIOC_PROBEMATCH (DTRACEIOC | 5) /* match probes */ 1287179193Sjb#define DTRACEIOC_ENABLE (DTRACEIOC | 6) /* enable probes */ 1288179193Sjb#define DTRACEIOC_AGGSNAP (DTRACEIOC | 7) /* snapshot agg. */ 1289179193Sjb#define DTRACEIOC_EPROBE (DTRACEIOC | 8) /* get eprobe desc. */ 1290179193Sjb#define DTRACEIOC_PROBEARG (DTRACEIOC | 9) /* get probe arg */ 1291179193Sjb#define DTRACEIOC_CONF (DTRACEIOC | 10) /* get config. */ 1292179193Sjb#define DTRACEIOC_STATUS (DTRACEIOC | 11) /* get status */ 1293179193Sjb#define DTRACEIOC_GO (DTRACEIOC | 12) /* start tracing */ 1294179193Sjb#define DTRACEIOC_STOP (DTRACEIOC | 13) /* stop tracing */ 1295179193Sjb#define DTRACEIOC_AGGDESC (DTRACEIOC | 15) /* get agg. desc. */ 1296179193Sjb#define DTRACEIOC_FORMAT (DTRACEIOC | 16) /* get format str */ 1297179193Sjb#define DTRACEIOC_DOFGET (DTRACEIOC | 17) /* get DOF */ 1298179193Sjb#define DTRACEIOC_REPLICATE (DTRACEIOC | 18) /* replicate enab */ 1299179198Sjb#else 1300179198Sjb#define DTRACEIOC_PROVIDER _IOWR('x',1,dtrace_providerdesc_t) 1301179198Sjb /* provider query */ 1302179198Sjb#define DTRACEIOC_PROBES _IOWR('x',2,dtrace_probedesc_t) 1303179198Sjb /* probe query */ 1304179198Sjb#define DTRACEIOC_BUFSNAP _IOW('x',4,dtrace_bufdesc_t *) 1305179198Sjb /* snapshot buffer */ 1306179198Sjb#define DTRACEIOC_PROBEMATCH _IOWR('x',5,dtrace_probedesc_t) 1307179198Sjb /* match probes */ 1308179198Sjbtypedef struct { 1309179198Sjb void *dof; /* DOF userland address written to driver. */ 1310179198Sjb int n_matched; /* # matches returned by driver. */ 1311179198Sjb} dtrace_enable_io_t; 1312179198Sjb#define DTRACEIOC_ENABLE _IOWR('x',6,dtrace_enable_io_t) 1313179198Sjb /* enable probes */ 1314179198Sjb#define DTRACEIOC_AGGSNAP _IOW('x',7,dtrace_bufdesc_t *) 1315179198Sjb /* snapshot agg. */ 1316179198Sjb#define DTRACEIOC_EPROBE _IOW('x',8,dtrace_eprobedesc_t) 1317179198Sjb /* get eprobe desc. */ 1318179198Sjb#define DTRACEIOC_PROBEARG _IOWR('x',9,dtrace_argdesc_t) 1319179198Sjb /* get probe arg */ 1320179198Sjb#define DTRACEIOC_CONF _IOR('x',10,dtrace_conf_t) 1321179198Sjb /* get config. */ 1322179198Sjb#define DTRACEIOC_STATUS _IOR('x',11,dtrace_status_t) 1323179198Sjb /* get status */ 1324179198Sjb#define DTRACEIOC_GO _IOR('x',12,processorid_t) 1325179198Sjb /* start tracing */ 1326179198Sjb#define DTRACEIOC_STOP _IOWR('x',13,processorid_t) 1327179198Sjb /* stop tracing */ 1328179198Sjb#define DTRACEIOC_AGGDESC _IOW('x',15,dtrace_aggdesc_t *) 1329179198Sjb /* get agg. desc. */ 1330179198Sjb#define DTRACEIOC_FORMAT _IOWR('x',16,dtrace_fmtdesc_t) 1331179198Sjb /* get format str */ 1332179198Sjb#define DTRACEIOC_DOFGET _IOW('x',17,dof_hdr_t *) 1333179198Sjb /* get DOF */ 1334179198Sjb#define DTRACEIOC_REPLICATE _IOW('x',18,dtrace_repldesc_t) 1335179198Sjb /* replicate enab */ 1336179198Sjb#endif 1337179193Sjb 1338179193Sjb/* 1339179193Sjb * DTrace Helpers 1340179193Sjb * 1341179193Sjb * In general, DTrace establishes probes in processes and takes actions on 1342179193Sjb * processes without knowing their specific user-level structures. Instead of 1343179193Sjb * existing in the framework, process-specific knowledge is contained by the 1344179193Sjb * enabling D program -- which can apply process-specific knowledge by making 1345179193Sjb * appropriate use of DTrace primitives like copyin() and copyinstr() to 1346179193Sjb * operate on user-level data. However, there may exist some specific probes 1347179193Sjb * of particular semantic relevance that the application developer may wish to 1348179193Sjb * explicitly export. For example, an application may wish to export a probe 1349179193Sjb * at the point that it begins and ends certain well-defined transactions. In 1350179193Sjb * addition to providing probes, programs may wish to offer assistance for 1351179193Sjb * certain actions. For example, in highly dynamic environments (e.g., Java), 1352179193Sjb * it may be difficult to obtain a stack trace in terms of meaningful symbol 1353179193Sjb * names (the translation from instruction addresses to corresponding symbol 1354179193Sjb * names may only be possible in situ); these environments may wish to define 1355179193Sjb * a series of actions to be applied in situ to obtain a meaningful stack 1356179193Sjb * trace. 1357179193Sjb * 1358179193Sjb * These two mechanisms -- user-level statically defined tracing and assisting 1359179193Sjb * DTrace actions -- are provided via DTrace _helpers_. Helpers are specified 1360179193Sjb * via DOF, but unlike enabling DOF, helper DOF may contain definitions of 1361179193Sjb * providers, probes and their arguments. If a helper wishes to provide 1362179193Sjb * action assistance, probe descriptions and corresponding DIF actions may be 1363179193Sjb * specified in the helper DOF. For such helper actions, however, the probe 1364179193Sjb * description describes the specific helper: all DTrace helpers have the 1365179193Sjb * provider name "dtrace" and the module name "helper", and the name of the 1366179193Sjb * helper is contained in the function name (for example, the ustack() helper 1367179193Sjb * is named "ustack"). Any helper-specific name may be contained in the name 1368179193Sjb * (for example, if a helper were to have a constructor, it might be named 1369179193Sjb * "dtrace:helper:<helper>:init"). Helper actions are only called when the 1370179193Sjb * action that they are helping is taken. Helper actions may only return DIF 1371179193Sjb * expressions, and may only call the following subroutines: 1372179193Sjb * 1373179193Sjb * alloca() <= Allocates memory out of the consumer's scratch space 1374179193Sjb * bcopy() <= Copies memory to scratch space 1375179193Sjb * copyin() <= Copies memory from user-level into consumer's scratch 1376179193Sjb * copyinto() <= Copies memory into a specific location in scratch 1377179193Sjb * copyinstr() <= Copies a string into a specific location in scratch 1378179193Sjb * 1379179193Sjb * Helper actions may only access the following built-in variables: 1380179193Sjb * 1381179193Sjb * curthread <= Current kthread_t pointer 1382179193Sjb * tid <= Current thread identifier 1383179193Sjb * pid <= Current process identifier 1384179193Sjb * ppid <= Parent process identifier 1385179193Sjb * uid <= Current user ID 1386179193Sjb * gid <= Current group ID 1387179193Sjb * execname <= Current executable name 1388179193Sjb * zonename <= Current zone name 1389179193Sjb * 1390179193Sjb * Helper actions may not manipulate or allocate dynamic variables, but they 1391179193Sjb * may have clause-local and statically-allocated global variables. The 1392179193Sjb * helper action variable state is specific to the helper action -- variables 1393179193Sjb * used by the helper action may not be accessed outside of the helper 1394179193Sjb * action, and the helper action may not access variables that like outside 1395179193Sjb * of it. Helper actions may not load from kernel memory at-large; they are 1396179193Sjb * restricting to loading current user state (via copyin() and variants) and 1397179193Sjb * scratch space. As with probe enablings, helper actions are executed in 1398179193Sjb * program order. The result of the helper action is the result of the last 1399179193Sjb * executing helper expression. 1400179193Sjb * 1401179193Sjb * Helpers -- composed of either providers/probes or probes/actions (or both) 1402179193Sjb * -- are added by opening the "helper" minor node, and issuing an ioctl(2) 1403179193Sjb * (DTRACEHIOC_ADDDOF) that specifies the dof_helper_t structure. This 1404179193Sjb * encapsulates the name and base address of the user-level library or 1405179193Sjb * executable publishing the helpers and probes as well as the DOF that 1406179193Sjb * contains the definitions of those helpers and probes. 1407179193Sjb * 1408179193Sjb * The DTRACEHIOC_ADD and DTRACEHIOC_REMOVE are left in place for legacy 1409179193Sjb * helpers and should no longer be used. No other ioctls are valid on the 1410179193Sjb * helper minor node. 1411179193Sjb */ 1412277300Ssmh#ifdef illumos 1413179193Sjb#define DTRACEHIOC (('d' << 24) | ('t' << 16) | ('h' << 8)) 1414179193Sjb#define DTRACEHIOC_ADD (DTRACEHIOC | 1) /* add helper */ 1415179193Sjb#define DTRACEHIOC_REMOVE (DTRACEHIOC | 2) /* remove helper */ 1416179193Sjb#define DTRACEHIOC_ADDDOF (DTRACEHIOC | 3) /* add helper DOF */ 1417211555Srpaulo#else 1418211555Srpaulo#define DTRACEHIOC_REMOVE _IOW('z', 2, int) /* remove helper */ 1419211555Srpaulo#define DTRACEHIOC_ADDDOF _IOWR('z', 3, dof_helper_t)/* add helper DOF */ 1420211555Srpaulo#endif 1421179193Sjb 1422179193Sjbtypedef struct dof_helper { 1423179193Sjb char dofhp_mod[DTRACE_MODNAMELEN]; /* executable or library name */ 1424179193Sjb uint64_t dofhp_addr; /* base address of object */ 1425179193Sjb uint64_t dofhp_dof; /* address of helper DOF */ 1426281257Smarkj#ifdef __FreeBSD__ 1427281257Smarkj pid_t dofhp_pid; /* target process ID */ 1428281257Smarkj int dofhp_gen; 1429211555Srpaulo#endif 1430179193Sjb} dof_helper_t; 1431179193Sjb 1432179193Sjb#define DTRACEMNR_DTRACE "dtrace" /* node for DTrace ops */ 1433179193Sjb#define DTRACEMNR_HELPER "helper" /* node for helpers */ 1434179193Sjb#define DTRACEMNRN_DTRACE 0 /* minor for DTrace ops */ 1435179193Sjb#define DTRACEMNRN_HELPER 1 /* minor for helpers */ 1436179193Sjb#define DTRACEMNRN_CLONE 2 /* first clone minor */ 1437179193Sjb 1438179193Sjb#ifdef _KERNEL 1439179193Sjb 1440179193Sjb/* 1441179193Sjb * DTrace Provider API 1442179193Sjb * 1443179193Sjb * The following functions are implemented by the DTrace framework and are 1444179193Sjb * used to implement separate in-kernel DTrace providers. Common functions 1445179193Sjb * are provided in uts/common/os/dtrace.c. ISA-dependent subroutines are 1446179193Sjb * defined in uts/<isa>/dtrace/dtrace_asm.s or uts/<isa>/dtrace/dtrace_isa.c. 1447179193Sjb * 1448179193Sjb * The provider API has two halves: the API that the providers consume from 1449179193Sjb * DTrace, and the API that providers make available to DTrace. 1450179193Sjb * 1451179193Sjb * 1 Framework-to-Provider API 1452179193Sjb * 1453179193Sjb * 1.1 Overview 1454179193Sjb * 1455179193Sjb * The Framework-to-Provider API is represented by the dtrace_pops structure 1456179193Sjb * that the provider passes to the framework when registering itself. This 1457179193Sjb * structure consists of the following members: 1458179193Sjb * 1459179193Sjb * dtps_provide() <-- Provide all probes, all modules 1460179193Sjb * dtps_provide_module() <-- Provide all probes in specified module 1461179193Sjb * dtps_enable() <-- Enable specified probe 1462179193Sjb * dtps_disable() <-- Disable specified probe 1463179193Sjb * dtps_suspend() <-- Suspend specified probe 1464179193Sjb * dtps_resume() <-- Resume specified probe 1465179193Sjb * dtps_getargdesc() <-- Get the argument description for args[X] 1466179193Sjb * dtps_getargval() <-- Get the value for an argX or args[X] variable 1467179193Sjb * dtps_usermode() <-- Find out if the probe was fired in user mode 1468179193Sjb * dtps_destroy() <-- Destroy all state associated with this probe 1469179193Sjb * 1470179193Sjb * 1.2 void dtps_provide(void *arg, const dtrace_probedesc_t *spec) 1471179193Sjb * 1472179193Sjb * 1.2.1 Overview 1473179193Sjb * 1474179193Sjb * Called to indicate that the provider should provide all probes. If the 1475179193Sjb * specified description is non-NULL, dtps_provide() is being called because 1476179193Sjb * no probe matched a specified probe -- if the provider has the ability to 1477179193Sjb * create custom probes, it may wish to create a probe that matches the 1478179193Sjb * specified description. 1479179193Sjb * 1480179193Sjb * 1.2.2 Arguments and notes 1481179193Sjb * 1482179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1483179193Sjb * second argument is a pointer to a probe description that the provider may 1484179193Sjb * wish to consider when creating custom probes. The provider is expected to 1485179193Sjb * call back into the DTrace framework via dtrace_probe_create() to create 1486179193Sjb * any necessary probes. dtps_provide() may be called even if the provider 1487179193Sjb * has made available all probes; the provider should check the return value 1488179193Sjb * of dtrace_probe_create() to handle this case. Note that the provider need 1489179193Sjb * not implement both dtps_provide() and dtps_provide_module(); see 1490179193Sjb * "Arguments and Notes" for dtrace_register(), below. 1491179193Sjb * 1492179193Sjb * 1.2.3 Return value 1493179193Sjb * 1494179193Sjb * None. 1495179193Sjb * 1496179193Sjb * 1.2.4 Caller's context 1497179193Sjb * 1498179193Sjb * dtps_provide() is typically called from open() or ioctl() context, but may 1499179193Sjb * be called from other contexts as well. The DTrace framework is locked in 1500179193Sjb * such a way that providers may not register or unregister. This means that 1501179193Sjb * the provider may not call any DTrace API that affects its registration with 1502179193Sjb * the framework, including dtrace_register(), dtrace_unregister(), 1503179193Sjb * dtrace_invalidate(), and dtrace_condense(). However, the context is such 1504179193Sjb * that the provider may (and indeed, is expected to) call probe-related 1505179193Sjb * DTrace routines, including dtrace_probe_create(), dtrace_probe_lookup(), 1506179193Sjb * and dtrace_probe_arg(). 1507179193Sjb * 1508179198Sjb * 1.3 void dtps_provide_module(void *arg, modctl_t *mp) 1509179193Sjb * 1510179193Sjb * 1.3.1 Overview 1511179193Sjb * 1512179193Sjb * Called to indicate that the provider should provide all probes in the 1513179193Sjb * specified module. 1514179193Sjb * 1515179193Sjb * 1.3.2 Arguments and notes 1516179193Sjb * 1517179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1518179193Sjb * second argument is a pointer to a modctl structure that indicates the 1519179193Sjb * module for which probes should be created. 1520179193Sjb * 1521179193Sjb * 1.3.3 Return value 1522179193Sjb * 1523179193Sjb * None. 1524179193Sjb * 1525179193Sjb * 1.3.4 Caller's context 1526179193Sjb * 1527179193Sjb * dtps_provide_module() may be called from open() or ioctl() context, but 1528179193Sjb * may also be called from a module loading context. mod_lock is held, and 1529179193Sjb * the DTrace framework is locked in such a way that providers may not 1530179193Sjb * register or unregister. This means that the provider may not call any 1531179193Sjb * DTrace API that affects its registration with the framework, including 1532179193Sjb * dtrace_register(), dtrace_unregister(), dtrace_invalidate(), and 1533179193Sjb * dtrace_condense(). However, the context is such that the provider may (and 1534179193Sjb * indeed, is expected to) call probe-related DTrace routines, including 1535179193Sjb * dtrace_probe_create(), dtrace_probe_lookup(), and dtrace_probe_arg(). Note 1536179193Sjb * that the provider need not implement both dtps_provide() and 1537179193Sjb * dtps_provide_module(); see "Arguments and Notes" for dtrace_register(), 1538179193Sjb * below. 1539179193Sjb * 1540179193Sjb * 1.4 void dtps_enable(void *arg, dtrace_id_t id, void *parg) 1541179193Sjb * 1542179193Sjb * 1.4.1 Overview 1543179193Sjb * 1544179193Sjb * Called to enable the specified probe. 1545179193Sjb * 1546179193Sjb * 1.4.2 Arguments and notes 1547179193Sjb * 1548179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1549179193Sjb * second argument is the identifier of the probe to be enabled. The third 1550179193Sjb * argument is the probe argument as passed to dtrace_probe_create(). 1551179193Sjb * dtps_enable() will be called when a probe transitions from not being 1552179193Sjb * enabled at all to having one or more ECB. The number of ECBs associated 1553179193Sjb * with the probe may change without subsequent calls into the provider. 1554179193Sjb * When the number of ECBs drops to zero, the provider will be explicitly 1555179193Sjb * told to disable the probe via dtps_disable(). dtrace_probe() should never 1556179193Sjb * be called for a probe identifier that hasn't been explicitly enabled via 1557179193Sjb * dtps_enable(). 1558179193Sjb * 1559179193Sjb * 1.4.3 Return value 1560179193Sjb * 1561179193Sjb * None. 1562179193Sjb * 1563179193Sjb * 1.4.4 Caller's context 1564179193Sjb * 1565179193Sjb * The DTrace framework is locked in such a way that it may not be called 1566179193Sjb * back into at all. cpu_lock is held. mod_lock is not held and may not 1567179193Sjb * be acquired. 1568179193Sjb * 1569179193Sjb * 1.5 void dtps_disable(void *arg, dtrace_id_t id, void *parg) 1570179193Sjb * 1571179193Sjb * 1.5.1 Overview 1572179193Sjb * 1573179193Sjb * Called to disable the specified probe. 1574179193Sjb * 1575179193Sjb * 1.5.2 Arguments and notes 1576179193Sjb * 1577179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1578179193Sjb * second argument is the identifier of the probe to be disabled. The third 1579179193Sjb * argument is the probe argument as passed to dtrace_probe_create(). 1580179193Sjb * dtps_disable() will be called when a probe transitions from being enabled 1581179193Sjb * to having zero ECBs. dtrace_probe() should never be called for a probe 1582179193Sjb * identifier that has been explicitly enabled via dtps_disable(). 1583179193Sjb * 1584179193Sjb * 1.5.3 Return value 1585179193Sjb * 1586179193Sjb * None. 1587179193Sjb * 1588179193Sjb * 1.5.4 Caller's context 1589179193Sjb * 1590179193Sjb * The DTrace framework is locked in such a way that it may not be called 1591179193Sjb * back into at all. cpu_lock is held. mod_lock is not held and may not 1592179193Sjb * be acquired. 1593179193Sjb * 1594179193Sjb * 1.6 void dtps_suspend(void *arg, dtrace_id_t id, void *parg) 1595179193Sjb * 1596179193Sjb * 1.6.1 Overview 1597179193Sjb * 1598179193Sjb * Called to suspend the specified enabled probe. This entry point is for 1599179193Sjb * providers that may need to suspend some or all of their probes when CPUs 1600179193Sjb * are being powered on or when the boot monitor is being entered for a 1601179193Sjb * prolonged period of time. 1602179193Sjb * 1603179193Sjb * 1.6.2 Arguments and notes 1604179193Sjb * 1605179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1606179193Sjb * second argument is the identifier of the probe to be suspended. The 1607179193Sjb * third argument is the probe argument as passed to dtrace_probe_create(). 1608179193Sjb * dtps_suspend will only be called on an enabled probe. Providers that 1609179193Sjb * provide a dtps_suspend entry point will want to take roughly the action 1610179193Sjb * that it takes for dtps_disable. 1611179193Sjb * 1612179193Sjb * 1.6.3 Return value 1613179193Sjb * 1614179193Sjb * None. 1615179193Sjb * 1616179193Sjb * 1.6.4 Caller's context 1617179193Sjb * 1618179193Sjb * Interrupts are disabled. The DTrace framework is in a state such that the 1619179193Sjb * specified probe cannot be disabled or destroyed for the duration of 1620179193Sjb * dtps_suspend(). As interrupts are disabled, the provider is afforded 1621179193Sjb * little latitude; the provider is expected to do no more than a store to 1622179193Sjb * memory. 1623179193Sjb * 1624179193Sjb * 1.7 void dtps_resume(void *arg, dtrace_id_t id, void *parg) 1625179193Sjb * 1626179193Sjb * 1.7.1 Overview 1627179193Sjb * 1628179193Sjb * Called to resume the specified enabled probe. This entry point is for 1629179193Sjb * providers that may need to resume some or all of their probes after the 1630179193Sjb * completion of an event that induced a call to dtps_suspend(). 1631179193Sjb * 1632179193Sjb * 1.7.2 Arguments and notes 1633179193Sjb * 1634179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1635179193Sjb * second argument is the identifier of the probe to be resumed. The 1636179193Sjb * third argument is the probe argument as passed to dtrace_probe_create(). 1637179193Sjb * dtps_resume will only be called on an enabled probe. Providers that 1638179193Sjb * provide a dtps_resume entry point will want to take roughly the action 1639179193Sjb * that it takes for dtps_enable. 1640179193Sjb * 1641179193Sjb * 1.7.3 Return value 1642179193Sjb * 1643179193Sjb * None. 1644179193Sjb * 1645179193Sjb * 1.7.4 Caller's context 1646179193Sjb * 1647179193Sjb * Interrupts are disabled. The DTrace framework is in a state such that the 1648179193Sjb * specified probe cannot be disabled or destroyed for the duration of 1649179193Sjb * dtps_resume(). As interrupts are disabled, the provider is afforded 1650179193Sjb * little latitude; the provider is expected to do no more than a store to 1651179193Sjb * memory. 1652179193Sjb * 1653179193Sjb * 1.8 void dtps_getargdesc(void *arg, dtrace_id_t id, void *parg, 1654179193Sjb * dtrace_argdesc_t *desc) 1655179193Sjb * 1656179193Sjb * 1.8.1 Overview 1657179193Sjb * 1658179193Sjb * Called to retrieve the argument description for an args[X] variable. 1659179193Sjb * 1660179193Sjb * 1.8.2 Arguments and notes 1661179193Sjb * 1662179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1663179193Sjb * second argument is the identifier of the current probe. The third 1664179193Sjb * argument is the probe argument as passed to dtrace_probe_create(). The 1665179193Sjb * fourth argument is a pointer to the argument description. This 1666179193Sjb * description is both an input and output parameter: it contains the 1667179193Sjb * index of the desired argument in the dtargd_ndx field, and expects 1668179193Sjb * the other fields to be filled in upon return. If there is no argument 1669179193Sjb * corresponding to the specified index, the dtargd_ndx field should be set 1670179193Sjb * to DTRACE_ARGNONE. 1671179193Sjb * 1672179193Sjb * 1.8.3 Return value 1673179193Sjb * 1674179193Sjb * None. The dtargd_ndx, dtargd_native, dtargd_xlate and dtargd_mapping 1675179193Sjb * members of the dtrace_argdesc_t structure are all output values. 1676179193Sjb * 1677179193Sjb * 1.8.4 Caller's context 1678179193Sjb * 1679179193Sjb * dtps_getargdesc() is called from ioctl() context. mod_lock is held, and 1680179193Sjb * the DTrace framework is locked in such a way that providers may not 1681179193Sjb * register or unregister. This means that the provider may not call any 1682179193Sjb * DTrace API that affects its registration with the framework, including 1683179193Sjb * dtrace_register(), dtrace_unregister(), dtrace_invalidate(), and 1684179193Sjb * dtrace_condense(). 1685179193Sjb * 1686179193Sjb * 1.9 uint64_t dtps_getargval(void *arg, dtrace_id_t id, void *parg, 1687179193Sjb * int argno, int aframes) 1688179193Sjb * 1689179193Sjb * 1.9.1 Overview 1690179193Sjb * 1691179193Sjb * Called to retrieve a value for an argX or args[X] variable. 1692179193Sjb * 1693179193Sjb * 1.9.2 Arguments and notes 1694179193Sjb * 1695179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1696179193Sjb * second argument is the identifier of the current probe. The third 1697179193Sjb * argument is the probe argument as passed to dtrace_probe_create(). The 1698179193Sjb * fourth argument is the number of the argument (the X in the example in 1699179193Sjb * 1.9.1). The fifth argument is the number of stack frames that were used 1700179193Sjb * to get from the actual place in the code that fired the probe to 1701179193Sjb * dtrace_probe() itself, the so-called artificial frames. This argument may 1702179193Sjb * be used to descend an appropriate number of frames to find the correct 1703179193Sjb * values. If this entry point is left NULL, the dtrace_getarg() built-in 1704179193Sjb * function is used. 1705179193Sjb * 1706179193Sjb * 1.9.3 Return value 1707179193Sjb * 1708179193Sjb * The value of the argument. 1709179193Sjb * 1710179193Sjb * 1.9.4 Caller's context 1711179193Sjb * 1712179193Sjb * This is called from within dtrace_probe() meaning that interrupts 1713179193Sjb * are disabled. No locks should be taken within this entry point. 1714179193Sjb * 1715179193Sjb * 1.10 int dtps_usermode(void *arg, dtrace_id_t id, void *parg) 1716179193Sjb * 1717179193Sjb * 1.10.1 Overview 1718179193Sjb * 1719179193Sjb * Called to determine if the probe was fired in a user context. 1720179193Sjb * 1721179193Sjb * 1.10.2 Arguments and notes 1722179193Sjb * 1723179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1724179193Sjb * second argument is the identifier of the current probe. The third 1725179193Sjb * argument is the probe argument as passed to dtrace_probe_create(). This 1726179193Sjb * entry point must not be left NULL for providers whose probes allow for 1727179193Sjb * mixed mode tracing, that is to say those probes that can fire during 1728179193Sjb * kernel- _or_ user-mode execution 1729179193Sjb * 1730179193Sjb * 1.10.3 Return value 1731179193Sjb * 1732267929Srpaulo * A bitwise OR that encapsulates both the mode (either DTRACE_MODE_KERNEL 1733267929Srpaulo * or DTRACE_MODE_USER) and the policy when the privilege of the enabling 1734267929Srpaulo * is insufficient for that mode (a combination of DTRACE_MODE_NOPRIV_DROP, 1735267929Srpaulo * DTRACE_MODE_NOPRIV_RESTRICT, and DTRACE_MODE_LIMITEDPRIV_RESTRICT). If 1736267929Srpaulo * DTRACE_MODE_NOPRIV_DROP bit is set, insufficient privilege will result 1737267929Srpaulo * in the probe firing being silently ignored for the enabling; if the 1738267929Srpaulo * DTRACE_NODE_NOPRIV_RESTRICT bit is set, insufficient privilege will not 1739267929Srpaulo * prevent probe processing for the enabling, but restrictions will be in 1740267929Srpaulo * place that induce a UPRIV fault upon attempt to examine probe arguments 1741267929Srpaulo * or current process state. If the DTRACE_MODE_LIMITEDPRIV_RESTRICT bit 1742267929Srpaulo * is set, similar restrictions will be placed upon operation if the 1743267929Srpaulo * privilege is sufficient to process the enabling, but does not otherwise 1744267929Srpaulo * entitle the enabling to all zones. The DTRACE_MODE_NOPRIV_DROP and 1745267929Srpaulo * DTRACE_MODE_NOPRIV_RESTRICT are mutually exclusive (and one of these 1746267929Srpaulo * two policies must be specified), but either may be combined (or not) 1747267929Srpaulo * with DTRACE_MODE_LIMITEDPRIV_RESTRICT. 1748179193Sjb * 1749179193Sjb * 1.10.4 Caller's context 1750179193Sjb * 1751179193Sjb * This is called from within dtrace_probe() meaning that interrupts 1752179193Sjb * are disabled. No locks should be taken within this entry point. 1753179193Sjb * 1754179193Sjb * 1.11 void dtps_destroy(void *arg, dtrace_id_t id, void *parg) 1755179193Sjb * 1756179193Sjb * 1.11.1 Overview 1757179193Sjb * 1758179193Sjb * Called to destroy the specified probe. 1759179193Sjb * 1760179193Sjb * 1.11.2 Arguments and notes 1761179193Sjb * 1762179193Sjb * The first argument is the cookie as passed to dtrace_register(). The 1763179193Sjb * second argument is the identifier of the probe to be destroyed. The third 1764179193Sjb * argument is the probe argument as passed to dtrace_probe_create(). The 1765179193Sjb * provider should free all state associated with the probe. The framework 1766179193Sjb * guarantees that dtps_destroy() is only called for probes that have either 1767179193Sjb * been disabled via dtps_disable() or were never enabled via dtps_enable(). 1768179193Sjb * Once dtps_disable() has been called for a probe, no further call will be 1769179193Sjb * made specifying the probe. 1770179193Sjb * 1771179193Sjb * 1.11.3 Return value 1772179193Sjb * 1773179193Sjb * None. 1774179193Sjb * 1775179193Sjb * 1.11.4 Caller's context 1776179193Sjb * 1777179193Sjb * The DTrace framework is locked in such a way that it may not be called 1778179193Sjb * back into at all. mod_lock is held. cpu_lock is not held, and may not be 1779179193Sjb * acquired. 1780179193Sjb * 1781179193Sjb * 1782179193Sjb * 2 Provider-to-Framework API 1783179193Sjb * 1784179193Sjb * 2.1 Overview 1785179193Sjb * 1786179193Sjb * The Provider-to-Framework API provides the mechanism for the provider to 1787179193Sjb * register itself with the DTrace framework, to create probes, to lookup 1788179193Sjb * probes and (most importantly) to fire probes. The Provider-to-Framework 1789179193Sjb * consists of: 1790179193Sjb * 1791179193Sjb * dtrace_register() <-- Register a provider with the DTrace framework 1792179193Sjb * dtrace_unregister() <-- Remove a provider's DTrace registration 1793179193Sjb * dtrace_invalidate() <-- Invalidate the specified provider 1794179193Sjb * dtrace_condense() <-- Remove a provider's unenabled probes 1795179193Sjb * dtrace_attached() <-- Indicates whether or not DTrace has attached 1796179193Sjb * dtrace_probe_create() <-- Create a DTrace probe 1797179193Sjb * dtrace_probe_lookup() <-- Lookup a DTrace probe based on its name 1798179193Sjb * dtrace_probe_arg() <-- Return the probe argument for a specific probe 1799179193Sjb * dtrace_probe() <-- Fire the specified probe 1800179193Sjb * 1801179193Sjb * 2.2 int dtrace_register(const char *name, const dtrace_pattr_t *pap, 1802179193Sjb * uint32_t priv, cred_t *cr, const dtrace_pops_t *pops, void *arg, 1803179193Sjb * dtrace_provider_id_t *idp) 1804179193Sjb * 1805179193Sjb * 2.2.1 Overview 1806179193Sjb * 1807179193Sjb * dtrace_register() registers the calling provider with the DTrace 1808179193Sjb * framework. It should generally be called by DTrace providers in their 1809179193Sjb * attach(9E) entry point. 1810179193Sjb * 1811179193Sjb * 2.2.2 Arguments and Notes 1812179193Sjb * 1813179193Sjb * The first argument is the name of the provider. The second argument is a 1814179193Sjb * pointer to the stability attributes for the provider. The third argument 1815179193Sjb * is the privilege flags for the provider, and must be some combination of: 1816179193Sjb * 1817179193Sjb * DTRACE_PRIV_NONE <= All users may enable probes from this provider 1818179193Sjb * 1819179193Sjb * DTRACE_PRIV_PROC <= Any user with privilege of PRIV_DTRACE_PROC may 1820179193Sjb * enable probes from this provider 1821179193Sjb * 1822179193Sjb * DTRACE_PRIV_USER <= Any user with privilege of PRIV_DTRACE_USER may 1823179193Sjb * enable probes from this provider 1824179193Sjb * 1825179193Sjb * DTRACE_PRIV_KERNEL <= Any user with privilege of PRIV_DTRACE_KERNEL 1826179193Sjb * may enable probes from this provider 1827179193Sjb * 1828179193Sjb * DTRACE_PRIV_OWNER <= This flag places an additional constraint on 1829179193Sjb * the privilege requirements above. These probes 1830179193Sjb * require either (a) a user ID matching the user 1831179193Sjb * ID of the cred passed in the fourth argument 1832179193Sjb * or (b) the PRIV_PROC_OWNER privilege. 1833179193Sjb * 1834179193Sjb * DTRACE_PRIV_ZONEOWNER<= This flag places an additional constraint on 1835179193Sjb * the privilege requirements above. These probes 1836179193Sjb * require either (a) a zone ID matching the zone 1837179193Sjb * ID of the cred passed in the fourth argument 1838179193Sjb * or (b) the PRIV_PROC_ZONE privilege. 1839179193Sjb * 1840179193Sjb * Note that these flags designate the _visibility_ of the probes, not 1841179193Sjb * the conditions under which they may or may not fire. 1842179193Sjb * 1843179193Sjb * The fourth argument is the credential that is associated with the 1844179193Sjb * provider. This argument should be NULL if the privilege flags don't 1845179193Sjb * include DTRACE_PRIV_OWNER or DTRACE_PRIV_ZONEOWNER. If non-NULL, the 1846179193Sjb * framework stashes the uid and zoneid represented by this credential 1847179193Sjb * for use at probe-time, in implicit predicates. These limit visibility 1848179193Sjb * of the probes to users and/or zones which have sufficient privilege to 1849179193Sjb * access them. 1850179193Sjb * 1851179193Sjb * The fifth argument is a DTrace provider operations vector, which provides 1852179193Sjb * the implementation for the Framework-to-Provider API. (See Section 1, 1853179193Sjb * above.) This must be non-NULL, and each member must be non-NULL. The 1854179193Sjb * exceptions to this are (1) the dtps_provide() and dtps_provide_module() 1855179193Sjb * members (if the provider so desires, _one_ of these members may be left 1856179193Sjb * NULL -- denoting that the provider only implements the other) and (2) 1857179193Sjb * the dtps_suspend() and dtps_resume() members, which must either both be 1858179193Sjb * NULL or both be non-NULL. 1859179193Sjb * 1860179193Sjb * The sixth argument is a cookie to be specified as the first argument for 1861179193Sjb * each function in the Framework-to-Provider API. This argument may have 1862179193Sjb * any value. 1863179193Sjb * 1864179193Sjb * The final argument is a pointer to dtrace_provider_id_t. If 1865179193Sjb * dtrace_register() successfully completes, the provider identifier will be 1866179193Sjb * stored in the memory pointed to be this argument. This argument must be 1867179193Sjb * non-NULL. 1868179193Sjb * 1869179193Sjb * 2.2.3 Return value 1870179193Sjb * 1871179193Sjb * On success, dtrace_register() returns 0 and stores the new provider's 1872179193Sjb * identifier into the memory pointed to by the idp argument. On failure, 1873179193Sjb * dtrace_register() returns an errno: 1874179193Sjb * 1875179193Sjb * EINVAL The arguments passed to dtrace_register() were somehow invalid. 1876179193Sjb * This may because a parameter that must be non-NULL was NULL, 1877179193Sjb * because the name was invalid (either empty or an illegal 1878179193Sjb * provider name) or because the attributes were invalid. 1879179193Sjb * 1880179193Sjb * No other failure code is returned. 1881179193Sjb * 1882179193Sjb * 2.2.4 Caller's context 1883179193Sjb * 1884179193Sjb * dtrace_register() may induce calls to dtrace_provide(); the provider must 1885179193Sjb * hold no locks across dtrace_register() that may also be acquired by 1886179193Sjb * dtrace_provide(). cpu_lock and mod_lock must not be held. 1887179193Sjb * 1888179193Sjb * 2.3 int dtrace_unregister(dtrace_provider_t id) 1889179193Sjb * 1890179193Sjb * 2.3.1 Overview 1891179193Sjb * 1892179193Sjb * Unregisters the specified provider from the DTrace framework. It should 1893179193Sjb * generally be called by DTrace providers in their detach(9E) entry point. 1894179193Sjb * 1895179193Sjb * 2.3.2 Arguments and Notes 1896179193Sjb * 1897179193Sjb * The only argument is the provider identifier, as returned from a 1898179193Sjb * successful call to dtrace_register(). As a result of calling 1899179193Sjb * dtrace_unregister(), the DTrace framework will call back into the provider 1900179193Sjb * via the dtps_destroy() entry point. Once dtrace_unregister() successfully 1901179193Sjb * completes, however, the DTrace framework will no longer make calls through 1902179193Sjb * the Framework-to-Provider API. 1903179193Sjb * 1904179193Sjb * 2.3.3 Return value 1905179193Sjb * 1906179193Sjb * On success, dtrace_unregister returns 0. On failure, dtrace_unregister() 1907179193Sjb * returns an errno: 1908179193Sjb * 1909179193Sjb * EBUSY There are currently processes that have the DTrace pseudodevice 1910179193Sjb * open, or there exists an anonymous enabling that hasn't yet 1911179193Sjb * been claimed. 1912179193Sjb * 1913179193Sjb * No other failure code is returned. 1914179193Sjb * 1915179193Sjb * 2.3.4 Caller's context 1916179193Sjb * 1917179193Sjb * Because a call to dtrace_unregister() may induce calls through the 1918179193Sjb * Framework-to-Provider API, the caller may not hold any lock across 1919179193Sjb * dtrace_register() that is also acquired in any of the Framework-to- 1920179193Sjb * Provider API functions. Additionally, mod_lock may not be held. 1921179193Sjb * 1922179193Sjb * 2.4 void dtrace_invalidate(dtrace_provider_id_t id) 1923179193Sjb * 1924179193Sjb * 2.4.1 Overview 1925179193Sjb * 1926179193Sjb * Invalidates the specified provider. All subsequent probe lookups for the 1927179193Sjb * specified provider will fail, but its probes will not be removed. 1928179193Sjb * 1929179193Sjb * 2.4.2 Arguments and note 1930179193Sjb * 1931179193Sjb * The only argument is the provider identifier, as returned from a 1932179193Sjb * successful call to dtrace_register(). In general, a provider's probes 1933179193Sjb * always remain valid; dtrace_invalidate() is a mechanism for invalidating 1934179193Sjb * an entire provider, regardless of whether or not probes are enabled or 1935179193Sjb * not. Note that dtrace_invalidate() will _not_ prevent already enabled 1936179193Sjb * probes from firing -- it will merely prevent any new enablings of the 1937179193Sjb * provider's probes. 1938179193Sjb * 1939179193Sjb * 2.5 int dtrace_condense(dtrace_provider_id_t id) 1940179193Sjb * 1941179193Sjb * 2.5.1 Overview 1942179193Sjb * 1943179193Sjb * Removes all the unenabled probes for the given provider. This function is 1944179193Sjb * not unlike dtrace_unregister(), except that it doesn't remove the 1945179193Sjb * provider just as many of its associated probes as it can. 1946179193Sjb * 1947179193Sjb * 2.5.2 Arguments and Notes 1948179193Sjb * 1949179193Sjb * As with dtrace_unregister(), the sole argument is the provider identifier 1950179193Sjb * as returned from a successful call to dtrace_register(). As a result of 1951179193Sjb * calling dtrace_condense(), the DTrace framework will call back into the 1952179193Sjb * given provider's dtps_destroy() entry point for each of the provider's 1953179193Sjb * unenabled probes. 1954179193Sjb * 1955179193Sjb * 2.5.3 Return value 1956179193Sjb * 1957179193Sjb * Currently, dtrace_condense() always returns 0. However, consumers of this 1958179193Sjb * function should check the return value as appropriate; its behavior may 1959179193Sjb * change in the future. 1960179193Sjb * 1961179193Sjb * 2.5.4 Caller's context 1962179193Sjb * 1963179193Sjb * As with dtrace_unregister(), the caller may not hold any lock across 1964179193Sjb * dtrace_condense() that is also acquired in the provider's entry points. 1965179193Sjb * Also, mod_lock may not be held. 1966179193Sjb * 1967179193Sjb * 2.6 int dtrace_attached() 1968179193Sjb * 1969179193Sjb * 2.6.1 Overview 1970179193Sjb * 1971179193Sjb * Indicates whether or not DTrace has attached. 1972179193Sjb * 1973179193Sjb * 2.6.2 Arguments and Notes 1974179193Sjb * 1975179193Sjb * For most providers, DTrace makes initial contact beyond registration. 1976179193Sjb * That is, once a provider has registered with DTrace, it waits to hear 1977179193Sjb * from DTrace to create probes. However, some providers may wish to 1978179193Sjb * proactively create probes without first being told by DTrace to do so. 1979179193Sjb * If providers wish to do this, they must first call dtrace_attached() to 1980179193Sjb * determine if DTrace itself has attached. If dtrace_attached() returns 0, 1981179193Sjb * the provider must not make any other Provider-to-Framework API call. 1982179193Sjb * 1983179193Sjb * 2.6.3 Return value 1984179193Sjb * 1985179193Sjb * dtrace_attached() returns 1 if DTrace has attached, 0 otherwise. 1986179193Sjb * 1987179193Sjb * 2.7 int dtrace_probe_create(dtrace_provider_t id, const char *mod, 1988179193Sjb * const char *func, const char *name, int aframes, void *arg) 1989179193Sjb * 1990179193Sjb * 2.7.1 Overview 1991179193Sjb * 1992179193Sjb * Creates a probe with specified module name, function name, and name. 1993179193Sjb * 1994179193Sjb * 2.7.2 Arguments and Notes 1995179193Sjb * 1996179193Sjb * The first argument is the provider identifier, as returned from a 1997179193Sjb * successful call to dtrace_register(). The second, third, and fourth 1998179193Sjb * arguments are the module name, function name, and probe name, 1999179193Sjb * respectively. Of these, module name and function name may both be NULL 2000179193Sjb * (in which case the probe is considered to be unanchored), or they may both 2001179193Sjb * be non-NULL. The name must be non-NULL, and must point to a non-empty 2002179193Sjb * string. 2003179193Sjb * 2004179193Sjb * The fifth argument is the number of artificial stack frames that will be 2005179193Sjb * found on the stack when dtrace_probe() is called for the new probe. These 2006179193Sjb * artificial frames will be automatically be pruned should the stack() or 2007179193Sjb * stackdepth() functions be called as part of one of the probe's ECBs. If 2008179193Sjb * the parameter doesn't add an artificial frame, this parameter should be 2009179193Sjb * zero. 2010179193Sjb * 2011179193Sjb * The final argument is a probe argument that will be passed back to the 2012179193Sjb * provider when a probe-specific operation is called. (e.g., via 2013179193Sjb * dtps_enable(), dtps_disable(), etc.) 2014179193Sjb * 2015179193Sjb * Note that it is up to the provider to be sure that the probe that it 2016179193Sjb * creates does not already exist -- if the provider is unsure of the probe's 2017179193Sjb * existence, it should assure its absence with dtrace_probe_lookup() before 2018179193Sjb * calling dtrace_probe_create(). 2019179193Sjb * 2020179193Sjb * 2.7.3 Return value 2021179193Sjb * 2022179193Sjb * dtrace_probe_create() always succeeds, and always returns the identifier 2023179193Sjb * of the newly-created probe. 2024179193Sjb * 2025179193Sjb * 2.7.4 Caller's context 2026179193Sjb * 2027179193Sjb * While dtrace_probe_create() is generally expected to be called from 2028179193Sjb * dtps_provide() and/or dtps_provide_module(), it may be called from other 2029179193Sjb * non-DTrace contexts. Neither cpu_lock nor mod_lock may be held. 2030179193Sjb * 2031179193Sjb * 2.8 dtrace_id_t dtrace_probe_lookup(dtrace_provider_t id, const char *mod, 2032179193Sjb * const char *func, const char *name) 2033179193Sjb * 2034179193Sjb * 2.8.1 Overview 2035179193Sjb * 2036179193Sjb * Looks up a probe based on provdider and one or more of module name, 2037179193Sjb * function name and probe name. 2038179193Sjb * 2039179193Sjb * 2.8.2 Arguments and Notes 2040179193Sjb * 2041179193Sjb * The first argument is the provider identifier, as returned from a 2042179193Sjb * successful call to dtrace_register(). The second, third, and fourth 2043179193Sjb * arguments are the module name, function name, and probe name, 2044179193Sjb * respectively. Any of these may be NULL; dtrace_probe_lookup() will return 2045179193Sjb * the identifier of the first probe that is provided by the specified 2046179193Sjb * provider and matches all of the non-NULL matching criteria. 2047179193Sjb * dtrace_probe_lookup() is generally used by a provider to be check the 2048179193Sjb * existence of a probe before creating it with dtrace_probe_create(). 2049179193Sjb * 2050179193Sjb * 2.8.3 Return value 2051179193Sjb * 2052179193Sjb * If the probe exists, returns its identifier. If the probe does not exist, 2053179193Sjb * return DTRACE_IDNONE. 2054179193Sjb * 2055179193Sjb * 2.8.4 Caller's context 2056179193Sjb * 2057179193Sjb * While dtrace_probe_lookup() is generally expected to be called from 2058179193Sjb * dtps_provide() and/or dtps_provide_module(), it may also be called from 2059179193Sjb * other non-DTrace contexts. Neither cpu_lock nor mod_lock may be held. 2060179193Sjb * 2061179193Sjb * 2.9 void *dtrace_probe_arg(dtrace_provider_t id, dtrace_id_t probe) 2062179193Sjb * 2063179193Sjb * 2.9.1 Overview 2064179193Sjb * 2065179193Sjb * Returns the probe argument associated with the specified probe. 2066179193Sjb * 2067179193Sjb * 2.9.2 Arguments and Notes 2068179193Sjb * 2069179193Sjb * The first argument is the provider identifier, as returned from a 2070179193Sjb * successful call to dtrace_register(). The second argument is a probe 2071179193Sjb * identifier, as returned from dtrace_probe_lookup() or 2072179193Sjb * dtrace_probe_create(). This is useful if a probe has multiple 2073179193Sjb * provider-specific components to it: the provider can create the probe 2074179193Sjb * once with provider-specific state, and then add to the state by looking 2075179193Sjb * up the probe based on probe identifier. 2076179193Sjb * 2077179193Sjb * 2.9.3 Return value 2078179193Sjb * 2079179193Sjb * Returns the argument associated with the specified probe. If the 2080179193Sjb * specified probe does not exist, or if the specified probe is not provided 2081179193Sjb * by the specified provider, NULL is returned. 2082179193Sjb * 2083179193Sjb * 2.9.4 Caller's context 2084179193Sjb * 2085179193Sjb * While dtrace_probe_arg() is generally expected to be called from 2086179193Sjb * dtps_provide() and/or dtps_provide_module(), it may also be called from 2087179193Sjb * other non-DTrace contexts. Neither cpu_lock nor mod_lock may be held. 2088179193Sjb * 2089179193Sjb * 2.10 void dtrace_probe(dtrace_id_t probe, uintptr_t arg0, uintptr_t arg1, 2090179193Sjb * uintptr_t arg2, uintptr_t arg3, uintptr_t arg4) 2091179193Sjb * 2092179193Sjb * 2.10.1 Overview 2093179193Sjb * 2094179193Sjb * The epicenter of DTrace: fires the specified probes with the specified 2095179193Sjb * arguments. 2096179193Sjb * 2097179193Sjb * 2.10.2 Arguments and Notes 2098179193Sjb * 2099179193Sjb * The first argument is a probe identifier as returned by 2100179193Sjb * dtrace_probe_create() or dtrace_probe_lookup(). The second through sixth 2101179193Sjb * arguments are the values to which the D variables "arg0" through "arg4" 2102179193Sjb * will be mapped. 2103179193Sjb * 2104179193Sjb * dtrace_probe() should be called whenever the specified probe has fired -- 2105179193Sjb * however the provider defines it. 2106179193Sjb * 2107179193Sjb * 2.10.3 Return value 2108179193Sjb * 2109179193Sjb * None. 2110179193Sjb * 2111179193Sjb * 2.10.4 Caller's context 2112179193Sjb * 2113179193Sjb * dtrace_probe() may be called in virtually any context: kernel, user, 2114179193Sjb * interrupt, high-level interrupt, with arbitrary adaptive locks held, with 2115179193Sjb * dispatcher locks held, with interrupts disabled, etc. The only latitude 2116179193Sjb * that must be afforded to DTrace is the ability to make calls within 2117179193Sjb * itself (and to its in-kernel subroutines) and the ability to access 2118179193Sjb * arbitrary (but mapped) memory. On some platforms, this constrains 2119179193Sjb * context. For example, on UltraSPARC, dtrace_probe() cannot be called 2120179193Sjb * from any context in which TL is greater than zero. dtrace_probe() may 2121179193Sjb * also not be called from any routine which may be called by dtrace_probe() 2122179193Sjb * -- which includes functions in the DTrace framework and some in-kernel 2123179193Sjb * DTrace subroutines. All such functions "dtrace_"; providers that 2124179193Sjb * instrument the kernel arbitrarily should be sure to not instrument these 2125179193Sjb * routines. 2126179193Sjb */ 2127179193Sjbtypedef struct dtrace_pops { 2128179198Sjb void (*dtps_provide)(void *arg, dtrace_probedesc_t *spec); 2129179198Sjb void (*dtps_provide_module)(void *arg, modctl_t *mp); 2130179193Sjb void (*dtps_enable)(void *arg, dtrace_id_t id, void *parg); 2131179193Sjb void (*dtps_disable)(void *arg, dtrace_id_t id, void *parg); 2132179193Sjb void (*dtps_suspend)(void *arg, dtrace_id_t id, void *parg); 2133179193Sjb void (*dtps_resume)(void *arg, dtrace_id_t id, void *parg); 2134179193Sjb void (*dtps_getargdesc)(void *arg, dtrace_id_t id, void *parg, 2135179193Sjb dtrace_argdesc_t *desc); 2136179193Sjb uint64_t (*dtps_getargval)(void *arg, dtrace_id_t id, void *parg, 2137179193Sjb int argno, int aframes); 2138179193Sjb int (*dtps_usermode)(void *arg, dtrace_id_t id, void *parg); 2139179193Sjb void (*dtps_destroy)(void *arg, dtrace_id_t id, void *parg); 2140179193Sjb} dtrace_pops_t; 2141179193Sjb 2142267929Srpaulo#define DTRACE_MODE_KERNEL 0x01 2143267929Srpaulo#define DTRACE_MODE_USER 0x02 2144267929Srpaulo#define DTRACE_MODE_NOPRIV_DROP 0x10 2145267929Srpaulo#define DTRACE_MODE_NOPRIV_RESTRICT 0x20 2146267929Srpaulo#define DTRACE_MODE_LIMITEDPRIV_RESTRICT 0x40 2147267929Srpaulo 2148179193Sjbtypedef uintptr_t dtrace_provider_id_t; 2149179193Sjb 2150179193Sjbextern int dtrace_register(const char *, const dtrace_pattr_t *, uint32_t, 2151179193Sjb cred_t *, const dtrace_pops_t *, void *, dtrace_provider_id_t *); 2152179193Sjbextern int dtrace_unregister(dtrace_provider_id_t); 2153179193Sjbextern int dtrace_condense(dtrace_provider_id_t); 2154179193Sjbextern void dtrace_invalidate(dtrace_provider_id_t); 2155179198Sjbextern dtrace_id_t dtrace_probe_lookup(dtrace_provider_id_t, char *, 2156179198Sjb char *, char *); 2157179193Sjbextern dtrace_id_t dtrace_probe_create(dtrace_provider_id_t, const char *, 2158179193Sjb const char *, const char *, int, void *); 2159179193Sjbextern void *dtrace_probe_arg(dtrace_provider_id_t, dtrace_id_t); 2160179193Sjbextern void dtrace_probe(dtrace_id_t, uintptr_t arg0, uintptr_t arg1, 2161179193Sjb uintptr_t arg2, uintptr_t arg3, uintptr_t arg4); 2162179193Sjb 2163179193Sjb/* 2164179193Sjb * DTrace Meta Provider API 2165179193Sjb * 2166179193Sjb * The following functions are implemented by the DTrace framework and are 2167179193Sjb * used to implement meta providers. Meta providers plug into the DTrace 2168179193Sjb * framework and are used to instantiate new providers on the fly. At 2169179193Sjb * present, there is only one type of meta provider and only one meta 2170179193Sjb * provider may be registered with the DTrace framework at a time. The 2171179193Sjb * sole meta provider type provides user-land static tracing facilities 2172179193Sjb * by taking meta probe descriptions and adding a corresponding provider 2173179193Sjb * into the DTrace framework. 2174179193Sjb * 2175179193Sjb * 1 Framework-to-Provider 2176179193Sjb * 2177179193Sjb * 1.1 Overview 2178179193Sjb * 2179179193Sjb * The Framework-to-Provider API is represented by the dtrace_mops structure 2180179193Sjb * that the meta provider passes to the framework when registering itself as 2181179193Sjb * a meta provider. This structure consists of the following members: 2182179193Sjb * 2183179193Sjb * dtms_create_probe() <-- Add a new probe to a created provider 2184179193Sjb * dtms_provide_pid() <-- Create a new provider for a given process 2185179193Sjb * dtms_remove_pid() <-- Remove a previously created provider 2186179193Sjb * 2187179193Sjb * 1.2 void dtms_create_probe(void *arg, void *parg, 2188179193Sjb * dtrace_helper_probedesc_t *probedesc); 2189179193Sjb * 2190179193Sjb * 1.2.1 Overview 2191179193Sjb * 2192179193Sjb * Called by the DTrace framework to create a new probe in a provider 2193179193Sjb * created by this meta provider. 2194179193Sjb * 2195179193Sjb * 1.2.2 Arguments and notes 2196179193Sjb * 2197179193Sjb * The first argument is the cookie as passed to dtrace_meta_register(). 2198179193Sjb * The second argument is the provider cookie for the associated provider; 2199179193Sjb * this is obtained from the return value of dtms_provide_pid(). The third 2200179193Sjb * argument is the helper probe description. 2201179193Sjb * 2202179193Sjb * 1.2.3 Return value 2203179193Sjb * 2204179193Sjb * None 2205179193Sjb * 2206179193Sjb * 1.2.4 Caller's context 2207179193Sjb * 2208291963Smarkj * dtms_create_probe() is called from either ioctl() or module load context 2209291963Smarkj * in the context of a newly-created provider (that is, a provider that 2210291963Smarkj * is a result of a call to dtms_provide_pid()). The DTrace framework is 2211291963Smarkj * locked in such a way that meta providers may not register or unregister, 2212291963Smarkj * such that no other thread can call into a meta provider operation and that 2213291963Smarkj * atomicity is assured with respect to meta provider operations across 2214291963Smarkj * dtms_provide_pid() and subsequent calls to dtms_create_probe(). 2215291963Smarkj * The context is thus effectively single-threaded with respect to the meta 2216291963Smarkj * provider, and that the meta provider cannot call dtrace_meta_register() 2217291963Smarkj * or dtrace_meta_unregister(). However, the context is such that the 2218291963Smarkj * provider may (and is expected to) call provider-related DTrace provider 2219291963Smarkj * APIs including dtrace_probe_create(). 2220179193Sjb * 2221179193Sjb * 1.3 void *dtms_provide_pid(void *arg, dtrace_meta_provider_t *mprov, 2222179193Sjb * pid_t pid) 2223179193Sjb * 2224179193Sjb * 1.3.1 Overview 2225179193Sjb * 2226179193Sjb * Called by the DTrace framework to instantiate a new provider given the 2227179193Sjb * description of the provider and probes in the mprov argument. The 2228179193Sjb * meta provider should call dtrace_register() to insert the new provider 2229179193Sjb * into the DTrace framework. 2230179193Sjb * 2231179193Sjb * 1.3.2 Arguments and notes 2232179193Sjb * 2233179193Sjb * The first argument is the cookie as passed to dtrace_meta_register(). 2234179193Sjb * The second argument is a pointer to a structure describing the new 2235179193Sjb * helper provider. The third argument is the process identifier for 2236179193Sjb * process associated with this new provider. Note that the name of the 2237179193Sjb * provider as passed to dtrace_register() should be the contatenation of 2238179193Sjb * the dtmpb_provname member of the mprov argument and the processs 2239179193Sjb * identifier as a string. 2240179193Sjb * 2241179193Sjb * 1.3.3 Return value 2242179193Sjb * 2243179193Sjb * The cookie for the provider that the meta provider creates. This is 2244179193Sjb * the same value that it passed to dtrace_register(). 2245179193Sjb * 2246179193Sjb * 1.3.4 Caller's context 2247179193Sjb * 2248179193Sjb * dtms_provide_pid() is called from either ioctl() or module load context. 2249179193Sjb * The DTrace framework is locked in such a way that meta providers may not 2250179193Sjb * register or unregister. This means that the meta provider cannot call 2251179193Sjb * dtrace_meta_register() or dtrace_meta_unregister(). However, the context 2252179193Sjb * is such that the provider may -- and is expected to -- call 2253179193Sjb * provider-related DTrace provider APIs including dtrace_register(). 2254179193Sjb * 2255179193Sjb * 1.4 void dtms_remove_pid(void *arg, dtrace_meta_provider_t *mprov, 2256179193Sjb * pid_t pid) 2257179193Sjb * 2258179193Sjb * 1.4.1 Overview 2259179193Sjb * 2260179193Sjb * Called by the DTrace framework to remove a provider that had previously 2261179193Sjb * been instantiated via the dtms_provide_pid() entry point. The meta 2262179193Sjb * provider need not remove the provider immediately, but this entry 2263179193Sjb * point indicates that the provider should be removed as soon as possible 2264179193Sjb * using the dtrace_unregister() API. 2265179193Sjb * 2266179193Sjb * 1.4.2 Arguments and notes 2267179193Sjb * 2268179193Sjb * The first argument is the cookie as passed to dtrace_meta_register(). 2269179193Sjb * The second argument is a pointer to a structure describing the helper 2270179193Sjb * provider. The third argument is the process identifier for process 2271179193Sjb * associated with this new provider. 2272179193Sjb * 2273179193Sjb * 1.4.3 Return value 2274179193Sjb * 2275179193Sjb * None 2276179193Sjb * 2277179193Sjb * 1.4.4 Caller's context 2278179193Sjb * 2279179193Sjb * dtms_remove_pid() is called from either ioctl() or exit() context. 2280179193Sjb * The DTrace framework is locked in such a way that meta providers may not 2281179193Sjb * register or unregister. This means that the meta provider cannot call 2282179193Sjb * dtrace_meta_register() or dtrace_meta_unregister(). However, the context 2283179193Sjb * is such that the provider may -- and is expected to -- call 2284179193Sjb * provider-related DTrace provider APIs including dtrace_unregister(). 2285179193Sjb */ 2286179193Sjbtypedef struct dtrace_helper_probedesc { 2287179193Sjb char *dthpb_mod; /* probe module */ 2288179193Sjb char *dthpb_func; /* probe function */ 2289179193Sjb char *dthpb_name; /* probe name */ 2290179193Sjb uint64_t dthpb_base; /* base address */ 2291179193Sjb uint32_t *dthpb_offs; /* offsets array */ 2292179193Sjb uint32_t *dthpb_enoffs; /* is-enabled offsets array */ 2293179193Sjb uint32_t dthpb_noffs; /* offsets count */ 2294179193Sjb uint32_t dthpb_nenoffs; /* is-enabled offsets count */ 2295179193Sjb uint8_t *dthpb_args; /* argument mapping array */ 2296179193Sjb uint8_t dthpb_xargc; /* translated argument count */ 2297179193Sjb uint8_t dthpb_nargc; /* native argument count */ 2298179193Sjb char *dthpb_xtypes; /* translated types strings */ 2299179193Sjb char *dthpb_ntypes; /* native types strings */ 2300179193Sjb} dtrace_helper_probedesc_t; 2301179193Sjb 2302179193Sjbtypedef struct dtrace_helper_provdesc { 2303179193Sjb char *dthpv_provname; /* provider name */ 2304179193Sjb dtrace_pattr_t dthpv_pattr; /* stability attributes */ 2305179193Sjb} dtrace_helper_provdesc_t; 2306179193Sjb 2307179193Sjbtypedef struct dtrace_mops { 2308179193Sjb void (*dtms_create_probe)(void *, void *, dtrace_helper_probedesc_t *); 2309179193Sjb void *(*dtms_provide_pid)(void *, dtrace_helper_provdesc_t *, pid_t); 2310179193Sjb void (*dtms_remove_pid)(void *, dtrace_helper_provdesc_t *, pid_t); 2311179193Sjb} dtrace_mops_t; 2312179193Sjb 2313179193Sjbtypedef uintptr_t dtrace_meta_provider_id_t; 2314179193Sjb 2315179193Sjbextern int dtrace_meta_register(const char *, const dtrace_mops_t *, void *, 2316179193Sjb dtrace_meta_provider_id_t *); 2317179193Sjbextern int dtrace_meta_unregister(dtrace_meta_provider_id_t); 2318179193Sjb 2319179193Sjb/* 2320179193Sjb * DTrace Kernel Hooks 2321179193Sjb * 2322179193Sjb * The following functions are implemented by the base kernel and form a set of 2323179193Sjb * hooks used by the DTrace framework. DTrace hooks are implemented in either 2324179193Sjb * uts/common/os/dtrace_subr.c, an ISA-specific assembly file, or in a 2325179193Sjb * uts/<platform>/os/dtrace_subr.c corresponding to each hardware platform. 2326179193Sjb */ 2327179193Sjb 2328179193Sjbtypedef enum dtrace_vtime_state { 2329179193Sjb DTRACE_VTIME_INACTIVE = 0, /* No DTrace, no TNF */ 2330179193Sjb DTRACE_VTIME_ACTIVE, /* DTrace virtual time, no TNF */ 2331179193Sjb DTRACE_VTIME_INACTIVE_TNF, /* No DTrace, TNF active */ 2332179193Sjb DTRACE_VTIME_ACTIVE_TNF /* DTrace virtual time _and_ TNF */ 2333179193Sjb} dtrace_vtime_state_t; 2334179193Sjb 2335277300Ssmh#ifdef illumos 2336179193Sjbextern dtrace_vtime_state_t dtrace_vtime_active; 2337179198Sjb#endif 2338179193Sjbextern void dtrace_vtime_switch(kthread_t *next); 2339179193Sjbextern void dtrace_vtime_enable_tnf(void); 2340179193Sjbextern void dtrace_vtime_disable_tnf(void); 2341179193Sjbextern void dtrace_vtime_enable(void); 2342179193Sjbextern void dtrace_vtime_disable(void); 2343179193Sjb 2344179193Sjbstruct regs; 2345211555Srpaulostruct reg; 2346179193Sjb 2347277300Ssmh#ifdef illumos 2348211555Srpauloextern int (*dtrace_pid_probe_ptr)(struct reg *); 2349211555Srpauloextern int (*dtrace_return_probe_ptr)(struct reg *); 2350179193Sjbextern void (*dtrace_fasttrap_fork_ptr)(proc_t *, proc_t *); 2351179193Sjbextern void (*dtrace_fasttrap_exec_ptr)(proc_t *); 2352179193Sjbextern void (*dtrace_fasttrap_exit_ptr)(proc_t *); 2353179193Sjbextern void dtrace_fasttrap_fork(proc_t *, proc_t *); 2354179198Sjb#endif 2355179193Sjb 2356179193Sjbtypedef uintptr_t dtrace_icookie_t; 2357179193Sjbtypedef void (*dtrace_xcall_t)(void *); 2358179193Sjb 2359179193Sjbextern dtrace_icookie_t dtrace_interrupt_disable(void); 2360179193Sjbextern void dtrace_interrupt_enable(dtrace_icookie_t); 2361179193Sjb 2362179193Sjbextern void dtrace_membar_producer(void); 2363179193Sjbextern void dtrace_membar_consumer(void); 2364179193Sjb 2365179193Sjbextern void (*dtrace_cpu_init)(processorid_t); 2366277300Ssmh#ifdef illumos 2367179198Sjbextern void (*dtrace_modload)(modctl_t *); 2368179198Sjbextern void (*dtrace_modunload)(modctl_t *); 2369254268Smarkj#endif 2370179198Sjbextern void (*dtrace_helpers_cleanup)(void); 2371179193Sjbextern void (*dtrace_helpers_fork)(proc_t *parent, proc_t *child); 2372179198Sjbextern void (*dtrace_cpustart_init)(void); 2373179198Sjbextern void (*dtrace_cpustart_fini)(void); 2374267929Srpauloextern void (*dtrace_closef)(void); 2375179193Sjb 2376179198Sjbextern void (*dtrace_debugger_init)(void); 2377179198Sjbextern void (*dtrace_debugger_fini)(void); 2378179193Sjbextern dtrace_cacheid_t dtrace_predcache_id; 2379179193Sjb 2380277300Ssmh#ifdef illumos 2381179193Sjbextern hrtime_t dtrace_gethrtime(void); 2382179198Sjb#else 2383179198Sjbvoid dtrace_debug_printf(const char *, ...) __printflike(1, 2); 2384179198Sjb#endif 2385179193Sjbextern void dtrace_sync(void); 2386179193Sjbextern void dtrace_toxic_ranges(void (*)(uintptr_t, uintptr_t)); 2387179193Sjbextern void dtrace_xcall(processorid_t, dtrace_xcall_t, void *); 2388179193Sjbextern void dtrace_vpanic(const char *, __va_list); 2389179193Sjbextern void dtrace_panic(const char *, ...); 2390179193Sjb 2391179193Sjbextern int dtrace_safe_defer_signal(void); 2392179193Sjbextern void dtrace_safe_synchronous_signal(void); 2393179193Sjb 2394179193Sjbextern int dtrace_mach_aframes(void); 2395179193Sjb 2396179193Sjb#if defined(__i386) || defined(__amd64) 2397179193Sjbextern int dtrace_instr_size(uchar_t *instr); 2398179193Sjbextern int dtrace_instr_size_isa(uchar_t *, model_t, int *); 2399248457Sjhibbitsextern void dtrace_invop_callsite(void); 2400248457Sjhibbits#endif 2401298171Smarkjextern void dtrace_invop_add(int (*)(uintptr_t, struct trapframe *, uintptr_t)); 2402298171Smarkjextern void dtrace_invop_remove(int (*)(uintptr_t, struct trapframe *, 2403298171Smarkj uintptr_t)); 2404179193Sjb 2405179193Sjb#ifdef __sparc 2406179193Sjbextern int dtrace_blksuword32(uintptr_t, uint32_t *, int); 2407179193Sjbextern void dtrace_getfsr(uint64_t *); 2408179193Sjb#endif 2409179193Sjb 2410277300Ssmh#ifndef illumos 2411212357Srpauloextern void dtrace_helpers_duplicate(proc_t *, proc_t *); 2412212357Srpauloextern void dtrace_helpers_destroy(proc_t *); 2413212357Srpaulo#endif 2414212357Srpaulo 2415179193Sjb#define DTRACE_CPUFLAG_ISSET(flag) \ 2416179198Sjb (cpu_core[curcpu].cpuc_dtrace_flags & (flag)) 2417179193Sjb 2418179193Sjb#define DTRACE_CPUFLAG_SET(flag) \ 2419179198Sjb (cpu_core[curcpu].cpuc_dtrace_flags |= (flag)) 2420179193Sjb 2421179193Sjb#define DTRACE_CPUFLAG_CLEAR(flag) \ 2422179198Sjb (cpu_core[curcpu].cpuc_dtrace_flags &= ~(flag)) 2423179193Sjb 2424179193Sjb#endif /* _KERNEL */ 2425179193Sjb 2426179193Sjb#endif /* _ASM */ 2427179193Sjb 2428179193Sjb#if defined(__i386) || defined(__amd64) 2429179193Sjb 2430179193Sjb#define DTRACE_INVOP_PUSHL_EBP 1 2431298171Smarkj#define DTRACE_INVOP_PUSHQ_RBP DTRACE_INVOP_PUSHL_EBP 2432179193Sjb#define DTRACE_INVOP_POPL_EBP 2 2433298171Smarkj#define DTRACE_INVOP_POPQ_RBP DTRACE_INVOP_POPL_EBP 2434179193Sjb#define DTRACE_INVOP_LEAVE 3 2435179193Sjb#define DTRACE_INVOP_NOP 4 2436179193Sjb#define DTRACE_INVOP_RET 5 2437179193Sjb 2438248457Sjhibbits#elif defined(__powerpc__) 2439248457Sjhibbits 2440248457Sjhibbits#define DTRACE_INVOP_RET 1 2441248457Sjhibbits#define DTRACE_INVOP_BCTR 2 2442248457Sjhibbits#define DTRACE_INVOP_BLR 3 2443248457Sjhibbits#define DTRACE_INVOP_JUMP 4 2444248457Sjhibbits#define DTRACE_INVOP_MFLR_R0 5 2445248457Sjhibbits#define DTRACE_INVOP_NOP 6 2446248457Sjhibbits 2447278529Sgnn#elif defined(__arm__) 2448278529Sgnn 2449279667Sandrew#define DTRACE_INVOP_SHIFT 4 2450279667Sandrew#define DTRACE_INVOP_MASK ((1 << DTRACE_INVOP_SHIFT) - 1) 2451279667Sandrew#define DTRACE_INVOP_DATA(x) ((x) >> DTRACE_INVOP_SHIFT) 2452279667Sandrew 2453278529Sgnn#define DTRACE_INVOP_PUSHM 1 2454278529Sgnn#define DTRACE_INVOP_POPM 2 2455278529Sgnn#define DTRACE_INVOP_B 3 2456278529Sgnn 2457285009Sbr#elif defined(__aarch64__) 2458278529Sgnn 2459285009Sbr#define INSN_SIZE 4 2460285009Sbr 2461285009Sbr#define B_MASK 0xff000000 2462285009Sbr#define B_DATA_MASK 0x00ffffff 2463285009Sbr#define B_INSTR 0x14000000 2464285009Sbr 2465285009Sbr#define RET_INSTR 0xd65f03c0 2466285009Sbr 2467285009Sbr#define LDP_STP_MASK 0xffc00000 2468285009Sbr#define STP_32 0x29800000 2469285009Sbr#define STP_64 0xa9800000 2470285009Sbr#define LDP_32 0x28c00000 2471285009Sbr#define LDP_64 0xa8c00000 2472285009Sbr#define LDP_STP_PREIND (1 << 24) 2473285009Sbr#define LDP_STP_DIR (1 << 22) /* Load instruction */ 2474285009Sbr#define ARG1_SHIFT 0 2475285009Sbr#define ARG1_MASK 0x1f 2476285009Sbr#define ARG2_SHIFT 10 2477285009Sbr#define ARG2_MASK 0x1f 2478285009Sbr#define OFFSET_SHIFT 15 2479285009Sbr#define OFFSET_SIZE 7 2480285009Sbr#define OFFSET_MASK ((1 << OFFSET_SIZE) - 1) 2481285009Sbr 2482285009Sbr#define DTRACE_INVOP_PUSHM 1 2483285009Sbr#define DTRACE_INVOP_RET 2 2484285009Sbr#define DTRACE_INVOP_B 3 2485285009Sbr 2486299118Sbr#elif defined(__mips__) 2487299118Sbr 2488299118Sbr#define INSN_SIZE 4 2489299118Sbr 2490299118Sbr/* Load/Store double RA to/from SP */ 2491299118Sbr#define LDSD_RA_SP_MASK 0xffff0000 2492299118Sbr#define LDSD_DATA_MASK 0x0000ffff 2493299118Sbr#define SD_RA_SP 0xffbf0000 2494299118Sbr#define LD_RA_SP 0xdfbf0000 2495299118Sbr 2496299118Sbr#define DTRACE_INVOP_SD 1 2497299118Sbr#define DTRACE_INVOP_LD 2 2498300618Sbr 2499300618Sbr#elif defined(__riscv__) 2500300618Sbr 2501300618Sbr#define SD_RA_SP_MASK 0x1fff07f 2502300618Sbr#define SD_RA_SP 0x0113023 2503300618Sbr 2504300618Sbr#define DTRACE_INVOP_SD 1 2505300618Sbr#define DTRACE_INVOP_RET 2 2506300618Sbr#define DTRACE_INVOP_NOP 3 2507300618Sbr 2508179193Sjb#endif 2509179193Sjb 2510179193Sjb#ifdef __cplusplus 2511179193Sjb} 2512179193Sjb#endif 2513179193Sjb 2514179193Sjb#endif /* _SYS_DTRACE_H */ 2515