Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
39562 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License (the "License").5* You may not use this file except in compliance with the License.6*7* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE8* or http://www.opensolaris.org/os/licensing.9* See the License for the specific language governing permissions10* and limitations under the License.11*12* When distributing Covered Code, include this CDDL HEADER in each13* file and include the License file at usr/src/OPENSOLARIS.LICENSE.14* If applicable, add the following below this CDDL HEADER, with the15* fields enclosed by brackets "[]" replaced with your own identifying16* information: Portions Copyright [yyyy] [name of copyright owner]17*18* CDDL HEADER END19*/2021/*22* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.23* Copyright (c) 2013, Joyent, Inc. All rights reserved.24* Copyright (c) 2012, 2016 by Delphix. All rights reserved.25*/2627#include <sys/types.h>28#ifdef illumos29#include <sys/modctl.h>30#include <sys/systeminfo.h>31#else32#include <sys/param.h>33#include <sys/module.h>34#include <sys/linker.h>35#endif36#include <sys/resource.h>3738#include <libelf.h>39#include <strings.h>40#ifdef illumos41#include <alloca.h>42#endif43#include <limits.h>44#include <unistd.h>45#include <stdlib.h>46#include <stdio.h>47#include <fcntl.h>48#include <errno.h>49#include <assert.h>5051#define _POSIX_PTHREAD_SEMANTICS52#include <dirent.h>53#undef _POSIX_PTHREAD_SEMANTICS5455#include <dt_impl.h>56#include <dt_program.h>57#include <dt_module.h>58#include <dt_printf.h>59#include <dt_string.h>60#include <dt_provider.h>61#include <dt_oformat.h>62#ifndef illumos63#include <sys/sysctl.h>64#include <string.h>65#endif66#if defined(__i386__)67#include <ieeefp.h>68#endif6970/*71* Stability and versioning definitions. These #defines are used in the tables72* of identifiers below to fill in the attribute and version fields associated73* with each identifier. The DT_ATTR_* macros are a convenience to permit more74* concise declarations of common attributes such as Stable/Stable/Common. The75* DT_VERS_* macros declare the encoded integer values of all versions used so76* far. DT_VERS_LATEST must correspond to the latest version value among all77* versions exported by the D compiler. DT_VERS_STRING must be an ASCII string78* that contains DT_VERS_LATEST within it along with any suffixes (e.g. Beta).79* You must update DT_VERS_LATEST and DT_VERS_STRING when adding a new version,80* and then add the new version to the _dtrace_versions[] array declared below.81* Refer to the Solaris Dynamic Tracing Guide Stability and Versioning chapters82* respectively for an explanation of these DTrace features and their values.83*84* NOTE: Although the DTrace versioning scheme supports the labeling and85* introduction of incompatible changes (e.g. dropping an interface in a86* major release), the libdtrace code does not currently support this.87* All versions are assumed to strictly inherit from one another. If88* we ever need to provide divergent interfaces, this will need work.89*/90#define DT_ATTR_STABCMN { DTRACE_STABILITY_STABLE, \91DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }9293#define DT_ATTR_EVOLCMN { DTRACE_STABILITY_EVOLVING, \94DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON \95}9697/*98* The version number should be increased for every customer visible release99* of DTrace. The major number should be incremented when a fundamental100* change has been made that would affect all consumers, and would reflect101* sweeping changes to DTrace or the D language. The minor number should be102* incremented when a change is introduced that could break scripts that had103* previously worked; for example, adding a new built-in variable could break104* a script which was already using that identifier. The micro number should105* be changed when introducing functionality changes or major bug fixes that106* do not affect backward compatibility -- this is merely to make capabilities107* easily determined from the version number. Minor bugs do not require any108* modification to the version number.109*/110#define DT_VERS_1_0 DT_VERSION_NUMBER(1, 0, 0)111#define DT_VERS_1_1 DT_VERSION_NUMBER(1, 1, 0)112#define DT_VERS_1_2 DT_VERSION_NUMBER(1, 2, 0)113#define DT_VERS_1_2_1 DT_VERSION_NUMBER(1, 2, 1)114#define DT_VERS_1_2_2 DT_VERSION_NUMBER(1, 2, 2)115#define DT_VERS_1_3 DT_VERSION_NUMBER(1, 3, 0)116#define DT_VERS_1_4 DT_VERSION_NUMBER(1, 4, 0)117#define DT_VERS_1_4_1 DT_VERSION_NUMBER(1, 4, 1)118#define DT_VERS_1_5 DT_VERSION_NUMBER(1, 5, 0)119#define DT_VERS_1_6 DT_VERSION_NUMBER(1, 6, 0)120#define DT_VERS_1_6_1 DT_VERSION_NUMBER(1, 6, 1)121#define DT_VERS_1_6_2 DT_VERSION_NUMBER(1, 6, 2)122#define DT_VERS_1_6_3 DT_VERSION_NUMBER(1, 6, 3)123#define DT_VERS_1_7 DT_VERSION_NUMBER(1, 7, 0)124#define DT_VERS_1_7_1 DT_VERSION_NUMBER(1, 7, 1)125#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)126#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)127#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)128#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)129#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)130#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)131#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)132#define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1)133#define DT_VERS_1_13 DT_VERSION_NUMBER(1, 13, 0)134#define DT_VERS_LATEST DT_VERS_1_13135#define DT_VERS_STRING "Sun D 1.13"136137const dt_version_t _dtrace_versions[] = {138DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */139DT_VERS_1_1, /* D API 1.1.0 Solaris Express 6/05 */140DT_VERS_1_2, /* D API 1.2.0 Solaris 10 Update 1 */141DT_VERS_1_2_1, /* D API 1.2.1 Solaris Express 4/06 */142DT_VERS_1_2_2, /* D API 1.2.2 Solaris Express 6/06 */143DT_VERS_1_3, /* D API 1.3 Solaris Express 10/06 */144DT_VERS_1_4, /* D API 1.4 Solaris Express 2/07 */145DT_VERS_1_4_1, /* D API 1.4.1 Solaris Express 4/07 */146DT_VERS_1_5, /* D API 1.5 Solaris Express 7/07 */147DT_VERS_1_6, /* D API 1.6 */148DT_VERS_1_6_1, /* D API 1.6.1 */149DT_VERS_1_6_2, /* D API 1.6.2 */150DT_VERS_1_6_3, /* D API 1.6.3 */151DT_VERS_1_7, /* D API 1.7 */152DT_VERS_1_7_1, /* D API 1.7.1 */153DT_VERS_1_8, /* D API 1.8 */154DT_VERS_1_8_1, /* D API 1.8.1 */155DT_VERS_1_9, /* D API 1.9 */156DT_VERS_1_9_1, /* D API 1.9.1 */157DT_VERS_1_10, /* D API 1.10 */158DT_VERS_1_11, /* D API 1.11 */159DT_VERS_1_12, /* D API 1.12 */160DT_VERS_1_12_1, /* D API 1.12.1 */161DT_VERS_1_13, /* D API 1.13 */1620163};164165/*166* Global variables that are formatted on FreeBSD based on the kernel file name.167*/168#ifndef illumos169static char curthread_str[MAXPATHLEN];170static char intmtx_str[MAXPATHLEN];171static char threadmtx_str[MAXPATHLEN];172static char rwlock_str[MAXPATHLEN];173static char sxlock_str[MAXPATHLEN];174#endif175176/*177* Table of global identifiers. This is used to populate the global identifier178* hash when a new dtrace client open occurs. For more info see dt_ident.h.179* The global identifiers that represent functions use the dt_idops_func ops180* and specify the private data pointer as a prototype string which is parsed181* when the identifier is first encountered. These prototypes look like ANSI182* C function prototypes except that the special symbol "@" can be used as a183* wildcard to represent a single parameter of any type (i.e. any dt_node_t).184* The standard "..." notation can also be used to represent varargs. An empty185* parameter list is taken to mean void (that is, no arguments are permitted).186* A parameter enclosed in square brackets (e.g. "[int]") denotes an optional187* argument.188*/189static const dt_ident_t _dtrace_globals[] = {190{ "alloca", DT_IDENT_FUNC, 0, DIF_SUBR_ALLOCA, DT_ATTR_STABCMN, DT_VERS_1_0,191&dt_idops_func, "void *(size_t)" },192{ "arg0", DT_IDENT_SCALAR, 0, DIF_VAR_ARG0, DT_ATTR_STABCMN, DT_VERS_1_0,193&dt_idops_type, "int64_t" },194{ "arg1", DT_IDENT_SCALAR, 0, DIF_VAR_ARG1, DT_ATTR_STABCMN, DT_VERS_1_0,195&dt_idops_type, "int64_t" },196{ "arg2", DT_IDENT_SCALAR, 0, DIF_VAR_ARG2, DT_ATTR_STABCMN, DT_VERS_1_0,197&dt_idops_type, "int64_t" },198{ "arg3", DT_IDENT_SCALAR, 0, DIF_VAR_ARG3, DT_ATTR_STABCMN, DT_VERS_1_0,199&dt_idops_type, "int64_t" },200{ "arg4", DT_IDENT_SCALAR, 0, DIF_VAR_ARG4, DT_ATTR_STABCMN, DT_VERS_1_0,201&dt_idops_type, "int64_t" },202{ "arg5", DT_IDENT_SCALAR, 0, DIF_VAR_ARG5, DT_ATTR_STABCMN, DT_VERS_1_0,203&dt_idops_type, "int64_t" },204{ "arg6", DT_IDENT_SCALAR, 0, DIF_VAR_ARG6, DT_ATTR_STABCMN, DT_VERS_1_0,205&dt_idops_type, "int64_t" },206{ "arg7", DT_IDENT_SCALAR, 0, DIF_VAR_ARG7, DT_ATTR_STABCMN, DT_VERS_1_0,207&dt_idops_type, "int64_t" },208{ "arg8", DT_IDENT_SCALAR, 0, DIF_VAR_ARG8, DT_ATTR_STABCMN, DT_VERS_1_0,209&dt_idops_type, "int64_t" },210{ "arg9", DT_IDENT_SCALAR, 0, DIF_VAR_ARG9, DT_ATTR_STABCMN, DT_VERS_1_0,211&dt_idops_type, "int64_t" },212{ "args", DT_IDENT_ARRAY, 0, DIF_VAR_ARGS, DT_ATTR_STABCMN, DT_VERS_1_0,213&dt_idops_args, NULL },214{ "avg", DT_IDENT_AGGFUNC, 0, DTRACEAGG_AVG, DT_ATTR_STABCMN, DT_VERS_1_0,215&dt_idops_func, "void(@)" },216{ "basename", DT_IDENT_FUNC, 0, DIF_SUBR_BASENAME, DT_ATTR_STABCMN, DT_VERS_1_0,217&dt_idops_func, "string(const char *)" },218{ "bcopy", DT_IDENT_FUNC, 0, DIF_SUBR_BCOPY, DT_ATTR_STABCMN, DT_VERS_1_0,219&dt_idops_func, "void(void *, void *, size_t)" },220{ "breakpoint", DT_IDENT_ACTFUNC, 0, DT_ACT_BREAKPOINT,221DT_ATTR_STABCMN, DT_VERS_1_0,222&dt_idops_func, "void()" },223{ "caller", DT_IDENT_SCALAR, 0, DIF_VAR_CALLER, DT_ATTR_STABCMN, DT_VERS_1_0,224&dt_idops_type, "uintptr_t" },225{ "chill", DT_IDENT_ACTFUNC, 0, DT_ACT_CHILL, DT_ATTR_STABCMN, DT_VERS_1_0,226&dt_idops_func, "void(int)" },227{ "cleanpath", DT_IDENT_FUNC, 0, DIF_SUBR_CLEANPATH, DT_ATTR_STABCMN,228DT_VERS_1_0, &dt_idops_func, "string(const char *)" },229{ "clear", DT_IDENT_ACTFUNC, 0, DT_ACT_CLEAR, DT_ATTR_STABCMN, DT_VERS_1_0,230&dt_idops_func, "void(...)" },231{ "commit", DT_IDENT_ACTFUNC, 0, DT_ACT_COMMIT, DT_ATTR_STABCMN, DT_VERS_1_0,232&dt_idops_func, "void(int)" },233{ "copyin", DT_IDENT_FUNC, 0, DIF_SUBR_COPYIN, DT_ATTR_STABCMN, DT_VERS_1_0,234&dt_idops_func, "void *(uintptr_t, size_t)" },235{ "copyinstr", DT_IDENT_FUNC, 0, DIF_SUBR_COPYINSTR,236DT_ATTR_STABCMN, DT_VERS_1_0,237&dt_idops_func, "string(uintptr_t, [size_t])" },238{ "copyinto", DT_IDENT_FUNC, 0, DIF_SUBR_COPYINTO, DT_ATTR_STABCMN,239DT_VERS_1_0, &dt_idops_func, "void(uintptr_t, size_t, void *)" },240{ "copyout", DT_IDENT_FUNC, 0, DIF_SUBR_COPYOUT, DT_ATTR_STABCMN, DT_VERS_1_0,241&dt_idops_func, "void(void *, uintptr_t, size_t)" },242{ "copyoutstr", DT_IDENT_FUNC, 0, DIF_SUBR_COPYOUTSTR,243DT_ATTR_STABCMN, DT_VERS_1_0,244&dt_idops_func, "void(char *, uintptr_t, size_t)" },245{ "count", DT_IDENT_AGGFUNC, 0, DTRACEAGG_COUNT, DT_ATTR_STABCMN, DT_VERS_1_0,246&dt_idops_func, "void()" },247{ "curthread", DT_IDENT_SCALAR, 0, DIF_VAR_CURTHREAD,248{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_PRIVATE,249DTRACE_CLASS_COMMON }, DT_VERS_1_0,250#ifdef illumos251&dt_idops_type, "genunix`kthread_t *" },252#else253&dt_idops_type, curthread_str },254#endif255{ "ddi_pathname", DT_IDENT_FUNC, 0, DIF_SUBR_DDI_PATHNAME,256DT_ATTR_EVOLCMN, DT_VERS_1_0,257&dt_idops_func, "string(void *, int64_t)" },258{ "denormalize", DT_IDENT_ACTFUNC, 0, DT_ACT_DENORMALIZE, DT_ATTR_STABCMN,259DT_VERS_1_0, &dt_idops_func, "void(...)" },260{ "dirname", DT_IDENT_FUNC, 0, DIF_SUBR_DIRNAME, DT_ATTR_STABCMN, DT_VERS_1_0,261&dt_idops_func, "string(const char *)" },262{ "discard", DT_IDENT_ACTFUNC, 0, DT_ACT_DISCARD, DT_ATTR_STABCMN, DT_VERS_1_0,263&dt_idops_func, "void(int)" },264{ "epid", DT_IDENT_SCALAR, 0, DIF_VAR_EPID, DT_ATTR_STABCMN, DT_VERS_1_0,265&dt_idops_type, "uint_t" },266{ "errno", DT_IDENT_SCALAR, 0, DIF_VAR_ERRNO, DT_ATTR_STABCMN, DT_VERS_1_0,267&dt_idops_type, "int" },268{ "execargs", DT_IDENT_SCALAR, 0, DIF_VAR_EXECARGS,269DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },270{ "execname", DT_IDENT_SCALAR, 0, DIF_VAR_EXECNAME,271DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },272{ "exit", DT_IDENT_ACTFUNC, 0, DT_ACT_EXIT, DT_ATTR_STABCMN, DT_VERS_1_0,273&dt_idops_func, "void(int)" },274{ "freopen", DT_IDENT_ACTFUNC, 0, DT_ACT_FREOPEN, DT_ATTR_STABCMN,275DT_VERS_1_1, &dt_idops_func, "void(@, ...)" },276{ "ftruncate", DT_IDENT_ACTFUNC, 0, DT_ACT_FTRUNCATE, DT_ATTR_STABCMN,277DT_VERS_1_0, &dt_idops_func, "void()" },278{ "func", DT_IDENT_ACTFUNC, 0, DT_ACT_SYM, DT_ATTR_STABCMN,279DT_VERS_1_2, &dt_idops_func, "_symaddr(uintptr_t)" },280{ "getmajor", DT_IDENT_FUNC, 0, DIF_SUBR_GETMAJOR,281DT_ATTR_EVOLCMN, DT_VERS_1_0,282&dt_idops_func, "genunix`major_t(genunix`dev_t)" },283{ "getminor", DT_IDENT_FUNC, 0, DIF_SUBR_GETMINOR,284DT_ATTR_EVOLCMN, DT_VERS_1_0,285&dt_idops_func, "genunix`minor_t(genunix`dev_t)" },286{ "htonl", DT_IDENT_FUNC, 0, DIF_SUBR_HTONL, DT_ATTR_EVOLCMN, DT_VERS_1_3,287&dt_idops_func, "uint32_t(uint32_t)" },288{ "htonll", DT_IDENT_FUNC, 0, DIF_SUBR_HTONLL, DT_ATTR_EVOLCMN, DT_VERS_1_3,289&dt_idops_func, "uint64_t(uint64_t)" },290{ "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3,291&dt_idops_func, "uint16_t(uint16_t)" },292{ "getf", DT_IDENT_FUNC, 0, DIF_SUBR_GETF, DT_ATTR_STABCMN, DT_VERS_1_10,293&dt_idops_func, "file_t *(int)" },294{ "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0,295&dt_idops_type, "gid_t" },296{ "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0,297&dt_idops_type, "uint_t" },298{ "index", DT_IDENT_FUNC, 0, DIF_SUBR_INDEX, DT_ATTR_STABCMN, DT_VERS_1_1,299&dt_idops_func, "int(const char *, const char *, [int])" },300{ "inet_ntoa", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA, DT_ATTR_STABCMN,301#ifdef illumos302DT_VERS_1_5, &dt_idops_func, "string(ipaddr_t *)" },303#else304DT_VERS_1_5, &dt_idops_func, "string(in_addr_t *)" },305#endif306{ "inet_ntoa6", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA6, DT_ATTR_STABCMN,307#ifdef illumos308DT_VERS_1_5, &dt_idops_func, "string(in6_addr_t *)" },309#else310DT_VERS_1_5, &dt_idops_func, "string(struct in6_addr *)" },311#endif312{ "inet_ntop", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOP, DT_ATTR_STABCMN,313DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },314{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,315&dt_idops_type, "uint_t" },316#ifdef __FreeBSD__317{ "jailname", DT_IDENT_SCALAR, 0, DIF_VAR_JAILNAME,318DT_ATTR_STABCMN, DT_VERS_1_13, &dt_idops_type, "string" },319{ "jid", DT_IDENT_SCALAR, 0, DIF_VAR_JID, DT_ATTR_STABCMN, DT_VERS_1_13,320&dt_idops_type, "int" },321#endif322{ "json", DT_IDENT_FUNC, 0, DIF_SUBR_JSON, DT_ATTR_STABCMN, DT_VERS_1_11,323&dt_idops_func, "string(const char *, const char *)" },324{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,325&dt_idops_func, "stack(...)" },326{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,327&dt_idops_func, "string(int64_t, [int])" },328{ "llquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LLQUANTIZE, DT_ATTR_STABCMN,329DT_VERS_1_7, &dt_idops_func,330"void(@, int32_t, int32_t, int32_t, int32_t, ...)" },331{ "lquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LQUANTIZE,332DT_ATTR_STABCMN, DT_VERS_1_0,333&dt_idops_func, "void(@, int32_t, int32_t, ...)" },334{ "max", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MAX, DT_ATTR_STABCMN, DT_VERS_1_0,335&dt_idops_func, "void(@)" },336{ "memref", DT_IDENT_FUNC, 0, DIF_SUBR_MEMREF, DT_ATTR_STABCMN, DT_VERS_1_1,337&dt_idops_func, "uintptr_t *(void *, size_t)" },338#ifndef illumos339{ "memstr", DT_IDENT_FUNC, 0, DIF_SUBR_MEMSTR, DT_ATTR_STABCMN, DT_VERS_1_0,340&dt_idops_func, "string(void *, char, size_t)" },341#endif342{ "min", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MIN, DT_ATTR_STABCMN, DT_VERS_1_0,343&dt_idops_func, "void(@)" },344{ "mod", DT_IDENT_ACTFUNC, 0, DT_ACT_MOD, DT_ATTR_STABCMN,345DT_VERS_1_2, &dt_idops_func, "_symaddr(uintptr_t)" },346#ifdef illumos347{ "msgdsize", DT_IDENT_FUNC, 0, DIF_SUBR_MSGDSIZE,348DT_ATTR_STABCMN, DT_VERS_1_0,349&dt_idops_func, "size_t(mblk_t *)" },350{ "msgsize", DT_IDENT_FUNC, 0, DIF_SUBR_MSGSIZE,351DT_ATTR_STABCMN, DT_VERS_1_0,352&dt_idops_func, "size_t(mblk_t *)" },353{ "mutex_owned", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNED,354DT_ATTR_EVOLCMN, DT_VERS_1_0,355&dt_idops_func, "int(genunix`kmutex_t *)" },356{ "mutex_owner", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNER,357DT_ATTR_EVOLCMN, DT_VERS_1_0,358&dt_idops_func, "genunix`kthread_t *(genunix`kmutex_t *)" },359{ "mutex_type_adaptive", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_ADAPTIVE,360DT_ATTR_EVOLCMN, DT_VERS_1_0,361&dt_idops_func, "int(genunix`kmutex_t *)" },362{ "mutex_type_spin", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_SPIN,363DT_ATTR_EVOLCMN, DT_VERS_1_0,364&dt_idops_func, "int(genunix`kmutex_t *)" },365#else366{ "mutex_owned", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNED,367DT_ATTR_EVOLCMN, DT_VERS_1_0,368&dt_idops_func, intmtx_str },369{ "mutex_owner", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNER,370DT_ATTR_EVOLCMN, DT_VERS_1_0,371&dt_idops_func, threadmtx_str },372{ "mutex_type_adaptive", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_ADAPTIVE,373DT_ATTR_EVOLCMN, DT_VERS_1_0,374&dt_idops_func, intmtx_str },375{ "mutex_type_spin", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_SPIN,376DT_ATTR_EVOLCMN, DT_VERS_1_0,377&dt_idops_func, intmtx_str },378#endif379{ "ntohl", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHL, DT_ATTR_EVOLCMN, DT_VERS_1_3,380&dt_idops_func, "uint32_t(uint32_t)" },381{ "ntohll", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHLL, DT_ATTR_EVOLCMN, DT_VERS_1_3,382&dt_idops_func, "uint64_t(uint64_t)" },383{ "ntohs", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHS, DT_ATTR_EVOLCMN, DT_VERS_1_3,384&dt_idops_func, "uint16_t(uint16_t)" },385{ "normalize", DT_IDENT_ACTFUNC, 0, DT_ACT_NORMALIZE, DT_ATTR_STABCMN,386DT_VERS_1_0, &dt_idops_func, "void(...)" },387{ "panic", DT_IDENT_ACTFUNC, 0, DT_ACT_PANIC, DT_ATTR_STABCMN, DT_VERS_1_0,388&dt_idops_func, "void()" },389{ "pid", DT_IDENT_SCALAR, 0, DIF_VAR_PID, DT_ATTR_STABCMN, DT_VERS_1_0,390&dt_idops_type, "pid_t" },391{ "ppid", DT_IDENT_SCALAR, 0, DIF_VAR_PPID, DT_ATTR_STABCMN, DT_VERS_1_0,392&dt_idops_type, "pid_t" },393{ "print", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINT, DT_ATTR_STABCMN, DT_VERS_1_9,394&dt_idops_func, "void(@)" },395{ "printa", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTA, DT_ATTR_STABCMN, DT_VERS_1_0,396&dt_idops_func, "void(@, ...)" },397{ "printf", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTF, DT_ATTR_STABCMN, DT_VERS_1_0,398&dt_idops_func, "void(@, ...)" },399{ "printm", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTM, DT_ATTR_STABCMN, DT_VERS_1_0,400&dt_idops_func, "void(size_t, uintptr_t *)" },401{ "probefunc", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEFUNC,402DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },403{ "probemod", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEMOD,404DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },405{ "probename", DT_IDENT_SCALAR, 0, DIF_VAR_PROBENAME,406DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },407{ "probeprov", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEPROV,408DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },409{ "progenyof", DT_IDENT_FUNC, 0, DIF_SUBR_PROGENYOF,410DT_ATTR_STABCMN, DT_VERS_1_0,411&dt_idops_func, "int(pid_t)" },412{ "quantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_QUANTIZE,413DT_ATTR_STABCMN, DT_VERS_1_0,414&dt_idops_func, "void(@, ...)" },415{ "raise", DT_IDENT_ACTFUNC, 0, DT_ACT_RAISE, DT_ATTR_STABCMN, DT_VERS_1_0,416&dt_idops_func, "void(int)" },417{ "rand", DT_IDENT_FUNC, 0, DIF_SUBR_RAND, DT_ATTR_STABCMN, DT_VERS_1_0,418&dt_idops_func, "int()" },419{ "regs", DT_IDENT_ARRAY, 0, DIF_VAR_REGS, DT_ATTR_STABCMN, DT_VERS_1_13,420&dt_idops_regs, NULL },421{ "rindex", DT_IDENT_FUNC, 0, DIF_SUBR_RINDEX, DT_ATTR_STABCMN, DT_VERS_1_1,422&dt_idops_func, "int(const char *, const char *, [int])" },423#ifdef illumos424{ "rw_iswriter", DT_IDENT_FUNC, 0, DIF_SUBR_RW_ISWRITER,425DT_ATTR_EVOLCMN, DT_VERS_1_0,426&dt_idops_func, "int(genunix`krwlock_t *)" },427{ "rw_read_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_READ_HELD,428DT_ATTR_EVOLCMN, DT_VERS_1_0,429&dt_idops_func, "int(genunix`krwlock_t *)" },430{ "rw_write_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_WRITE_HELD,431DT_ATTR_EVOLCMN, DT_VERS_1_0,432&dt_idops_func, "int(genunix`krwlock_t *)" },433#else434{ "rw_iswriter", DT_IDENT_FUNC, 0, DIF_SUBR_RW_ISWRITER,435DT_ATTR_EVOLCMN, DT_VERS_1_0,436&dt_idops_func, rwlock_str },437{ "rw_read_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_READ_HELD,438DT_ATTR_EVOLCMN, DT_VERS_1_0,439&dt_idops_func, rwlock_str },440{ "rw_write_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_WRITE_HELD,441DT_ATTR_EVOLCMN, DT_VERS_1_0,442&dt_idops_func, rwlock_str },443#endif444{ "self", DT_IDENT_PTR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0,445&dt_idops_type, "void" },446{ "setopt", DT_IDENT_ACTFUNC, 0, DT_ACT_SETOPT, DT_ATTR_STABCMN,447DT_VERS_1_2, &dt_idops_func, "void(const char *, [const char *])" },448{ "speculate", DT_IDENT_ACTFUNC, 0, DT_ACT_SPECULATE,449DT_ATTR_STABCMN, DT_VERS_1_0,450&dt_idops_func, "void(int)" },451{ "speculation", DT_IDENT_FUNC, 0, DIF_SUBR_SPECULATION,452DT_ATTR_STABCMN, DT_VERS_1_0,453&dt_idops_func, "int()" },454{ "stack", DT_IDENT_ACTFUNC, 0, DT_ACT_STACK, DT_ATTR_STABCMN, DT_VERS_1_0,455&dt_idops_func, "stack(...)" },456{ "stackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_STACKDEPTH,457DT_ATTR_STABCMN, DT_VERS_1_0,458&dt_idops_type, "uint32_t" },459{ "stddev", DT_IDENT_AGGFUNC, 0, DTRACEAGG_STDDEV, DT_ATTR_STABCMN,460DT_VERS_1_6, &dt_idops_func, "void(@)" },461{ "stop", DT_IDENT_ACTFUNC, 0, DT_ACT_STOP, DT_ATTR_STABCMN, DT_VERS_1_0,462&dt_idops_func, "void()" },463{ "strchr", DT_IDENT_FUNC, 0, DIF_SUBR_STRCHR, DT_ATTR_STABCMN, DT_VERS_1_1,464&dt_idops_func, "string(const char *, char)" },465{ "strlen", DT_IDENT_FUNC, 0, DIF_SUBR_STRLEN, DT_ATTR_STABCMN, DT_VERS_1_0,466&dt_idops_func, "size_t(const char *)" },467{ "strjoin", DT_IDENT_FUNC, 0, DIF_SUBR_STRJOIN, DT_ATTR_STABCMN, DT_VERS_1_0,468&dt_idops_func, "string(const char *, const char *)" },469{ "strrchr", DT_IDENT_FUNC, 0, DIF_SUBR_STRRCHR, DT_ATTR_STABCMN, DT_VERS_1_1,470&dt_idops_func, "string(const char *, char)" },471{ "strstr", DT_IDENT_FUNC, 0, DIF_SUBR_STRSTR, DT_ATTR_STABCMN, DT_VERS_1_1,472&dt_idops_func, "string(const char *, const char *)" },473{ "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,474&dt_idops_func, "string(const char *, const char *)" },475{ "strtoll", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOLL, DT_ATTR_STABCMN, DT_VERS_1_11,476&dt_idops_func, "int64_t(const char *, [int])" },477{ "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1,478&dt_idops_func, "string(const char *, int, [int])" },479{ "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,480&dt_idops_func, "void(@)" },481#ifndef illumos482{ "sx_isexclusive", DT_IDENT_FUNC, 0, DIF_SUBR_SX_ISEXCLUSIVE,483DT_ATTR_EVOLCMN, DT_VERS_1_0,484&dt_idops_func, sxlock_str },485{ "sx_shared_held", DT_IDENT_FUNC, 0, DIF_SUBR_SX_SHARED_HELD,486DT_ATTR_EVOLCMN, DT_VERS_1_0,487&dt_idops_func, sxlock_str },488{ "sx_exclusive_held", DT_IDENT_FUNC, 0, DIF_SUBR_SX_EXCLUSIVE_HELD,489DT_ATTR_EVOLCMN, DT_VERS_1_0,490&dt_idops_func, sxlock_str },491#endif492{ "sym", DT_IDENT_ACTFUNC, 0, DT_ACT_SYM, DT_ATTR_STABCMN,493DT_VERS_1_2, &dt_idops_func, "_symaddr(uintptr_t)" },494{ "system", DT_IDENT_ACTFUNC, 0, DT_ACT_SYSTEM, DT_ATTR_STABCMN, DT_VERS_1_0,495&dt_idops_func, "void(@, ...)" },496{ "this", DT_IDENT_PTR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0,497&dt_idops_type, "void" },498{ "tid", DT_IDENT_SCALAR, 0, DIF_VAR_TID, DT_ATTR_STABCMN, DT_VERS_1_0,499&dt_idops_type, "id_t" },500{ "timestamp", DT_IDENT_SCALAR, 0, DIF_VAR_TIMESTAMP,501DT_ATTR_STABCMN, DT_VERS_1_0,502&dt_idops_type, "uint64_t" },503{ "tolower", DT_IDENT_FUNC, 0, DIF_SUBR_TOLOWER, DT_ATTR_STABCMN, DT_VERS_1_8,504&dt_idops_func, "string(const char *)" },505{ "toupper", DT_IDENT_FUNC, 0, DIF_SUBR_TOUPPER, DT_ATTR_STABCMN, DT_VERS_1_8,506&dt_idops_func, "string(const char *)" },507{ "trace", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACE, DT_ATTR_STABCMN, DT_VERS_1_0,508&dt_idops_func, "void(@)" },509{ "tracemem", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACEMEM,510DT_ATTR_STABCMN, DT_VERS_1_0,511&dt_idops_func, "void(@, size_t, ...)" },512{ "trunc", DT_IDENT_ACTFUNC, 0, DT_ACT_TRUNC, DT_ATTR_STABCMN,513DT_VERS_1_0, &dt_idops_func, "void(...)" },514{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,515DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },516{ "ucaller", DT_IDENT_SCALAR, 0, DIF_VAR_UCALLER, DT_ATTR_STABCMN,517DT_VERS_1_2, &dt_idops_type, "uint64_t" },518{ "ufunc", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,519DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },520{ "uid", DT_IDENT_SCALAR, 0, DIF_VAR_UID, DT_ATTR_STABCMN, DT_VERS_1_0,521&dt_idops_type, "uid_t" },522{ "umod", DT_IDENT_ACTFUNC, 0, DT_ACT_UMOD, DT_ATTR_STABCMN,523DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },524{ "uregs", DT_IDENT_ARRAY, 0, DIF_VAR_UREGS, DT_ATTR_STABCMN, DT_VERS_1_0,525&dt_idops_regs, NULL },526{ "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0,527&dt_idops_func, "stack(...)" },528{ "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH,529DT_ATTR_STABCMN, DT_VERS_1_2,530&dt_idops_type, "uint32_t" },531{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,532DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },533{ "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP,534DT_ATTR_STABCMN, DT_VERS_1_0,535&dt_idops_type, "uint64_t" },536{ "walltimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_WALLTIMESTAMP,537DT_ATTR_STABCMN, DT_VERS_1_0,538&dt_idops_type, "int64_t" },539{ "zonename", DT_IDENT_SCALAR, 0, DIF_VAR_ZONENAME,540DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },541542#ifndef illumos543{ "cpu", DT_IDENT_SCALAR, 0, DIF_VAR_CPU,544DT_ATTR_STABCMN, DT_VERS_1_6_3, &dt_idops_type, "int" },545#endif546547{ NULL, 0, 0, 0, { 0, 0, 0 }, 0, NULL, NULL }548};549550/*551* Tables of ILP32 intrinsic integer and floating-point type templates to use552* to populate the dynamic "C" CTF type container.553*/554static const dt_intrinsic_t _dtrace_intrinsics_32[] = {555{ "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },556{ "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },557{ "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },558{ "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },559{ "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },560{ "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },561{ "long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },562{ "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },563{ "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },564{ "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },565{ "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },566{ "signed long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },567{ "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },568{ "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },569{ "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },570{ "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },571{ "unsigned long", { 0, 0, 32 }, CTF_K_INTEGER },572{ "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },573{ "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },574{ "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },575{ "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },576{ "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },577{ "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },578{ "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },579{ "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },580{ "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },581{ "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },582{ "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },583{ NULL, { 0, 0, 0 }, 0 }584};585586/*587* Tables of LP64 intrinsic integer and floating-point type templates to use588* to populate the dynamic "C" CTF type container.589*/590static const dt_intrinsic_t _dtrace_intrinsics_64[] = {591{ "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },592{ "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },593{ "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },594{ "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },595{ "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },596{ "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },597{ "long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },598{ "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },599{ "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },600{ "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },601{ "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },602{ "signed long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },603{ "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },604{ "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },605{ "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },606{ "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },607{ "unsigned long", { 0, 0, 64 }, CTF_K_INTEGER },608{ "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },609{ "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },610{ "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },611{ "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },612{ "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },613{ "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },614{ "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },615{ "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },616{ "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },617{ "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },618{ "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },619{ NULL, { 0, 0, 0 }, 0 }620};621622/*623* Tables of ILP32 typedefs to use to populate the dynamic "D" CTF container.624* These aliases ensure that D definitions can use typical <sys/types.h> names.625*/626static const dt_typedef_t _dtrace_typedefs_32[] = {627{ "char", "int8_t" },628{ "short", "int16_t" },629{ "int", "int32_t" },630{ "long long", "int64_t" },631{ "int", "intptr_t" },632{ "int", "ssize_t" },633{ "unsigned char", "uint8_t" },634{ "unsigned short", "uint16_t" },635{ "unsigned", "uint32_t" },636{ "unsigned long long", "uint64_t" },637{ "unsigned char", "uchar_t" },638{ "unsigned short", "ushort_t" },639{ "unsigned", "uint_t" },640{ "unsigned long", "ulong_t" },641{ "unsigned long long", "u_longlong_t" },642{ "int", "ptrdiff_t" },643{ "unsigned", "uintptr_t" },644{ "unsigned", "size_t" },645{ "long", "id_t" },646{ "long", "pid_t" },647{ NULL, NULL }648};649650/*651* Tables of LP64 typedefs to use to populate the dynamic "D" CTF container.652* These aliases ensure that D definitions can use typical <sys/types.h> names.653*/654static const dt_typedef_t _dtrace_typedefs_64[] = {655{ "char", "int8_t" },656{ "short", "int16_t" },657{ "int", "int32_t" },658{ "long", "int64_t" },659{ "long", "intptr_t" },660{ "long", "ssize_t" },661{ "unsigned char", "uint8_t" },662{ "unsigned short", "uint16_t" },663{ "unsigned", "uint32_t" },664{ "unsigned long", "uint64_t" },665{ "unsigned char", "uchar_t" },666{ "unsigned short", "ushort_t" },667{ "unsigned", "uint_t" },668{ "unsigned long", "ulong_t" },669{ "unsigned long long", "u_longlong_t" },670{ "long", "ptrdiff_t" },671{ "unsigned long", "uintptr_t" },672{ "unsigned long", "size_t" },673{ "int", "id_t" },674{ "int", "pid_t" },675{ NULL, NULL }676};677678/*679* Tables of ILP32 integer type templates used to populate the dtp->dt_ints[]680* cache when a new dtrace client open occurs. Values are set by dtrace_open().681*/682static const dt_intdesc_t _dtrace_ints_32[] = {683{ "int", NULL, CTF_ERR, 0x7fffffffULL },684{ "unsigned int", NULL, CTF_ERR, 0xffffffffULL },685{ "long", NULL, CTF_ERR, 0x7fffffffULL },686{ "unsigned long", NULL, CTF_ERR, 0xffffffffULL },687{ "long long", NULL, CTF_ERR, 0x7fffffffffffffffULL },688{ "unsigned long long", NULL, CTF_ERR, 0xffffffffffffffffULL }689};690691/*692* Tables of LP64 integer type templates used to populate the dtp->dt_ints[]693* cache when a new dtrace client open occurs. Values are set by dtrace_open().694*/695static const dt_intdesc_t _dtrace_ints_64[] = {696{ "int", NULL, CTF_ERR, 0x7fffffffULL },697{ "unsigned int", NULL, CTF_ERR, 0xffffffffULL },698{ "long", NULL, CTF_ERR, 0x7fffffffffffffffULL },699{ "unsigned long", NULL, CTF_ERR, 0xffffffffffffffffULL },700{ "long long", NULL, CTF_ERR, 0x7fffffffffffffffULL },701{ "unsigned long long", NULL, CTF_ERR, 0xffffffffffffffffULL }702};703704/*705* Table of macro variable templates used to populate the macro identifier hash706* when a new dtrace client open occurs. Values are set by dtrace_update().707*/708static const dt_ident_t _dtrace_macros[] = {709{ "egid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },710{ "euid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },711{ "gid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },712{ "pid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },713{ "pgid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },714{ "ppid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },715{ "projid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },716{ "sid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },717{ "taskid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },718{ "target", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },719{ "uid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },720{ NULL, 0, 0, 0, { 0, 0, 0 }, 0 }721};722723/*724* Hard-wired definition string to be compiled and cached every time a new725* DTrace library handle is initialized. This string should only be used to726* contain definitions that should be present regardless of DTRACE_O_NOLIBS.727*/728static const char _dtrace_hardwire[] = "\729inline long NULL = 0; \n\730#pragma D binding \"1.0\" NULL\n\731";732733/*734* Default DTrace configuration to use when opening libdtrace DTRACE_O_NODEV.735* If DTRACE_O_NODEV is not set, we load the configuration from the kernel.736* The use of CTF_MODEL_NATIVE is more subtle than it might appear: we are737* relying on the fact that when running dtrace(1M), isaexec will invoke the738* binary with the same bitness as the kernel, which is what we want by default739* when generating our DIF. The user can override the choice using oflags.740*/741static const dtrace_conf_t _dtrace_conf = {742DIF_VERSION, /* dtc_difversion */743DIF_DIR_NREGS, /* dtc_difintregs */744DIF_DTR_NREGS, /* dtc_diftupregs */745CTF_MODEL_NATIVE /* dtc_ctfmodel */746};747748const dtrace_attribute_t _dtrace_maxattr = {749DTRACE_STABILITY_MAX,750DTRACE_STABILITY_MAX,751DTRACE_CLASS_MAX752};753754const dtrace_attribute_t _dtrace_defattr = {755DTRACE_STABILITY_STABLE,756DTRACE_STABILITY_STABLE,757DTRACE_CLASS_COMMON758};759760const dtrace_attribute_t _dtrace_symattr = {761DTRACE_STABILITY_PRIVATE,762DTRACE_STABILITY_PRIVATE,763DTRACE_CLASS_UNKNOWN764};765766const dtrace_attribute_t _dtrace_typattr = {767DTRACE_STABILITY_PRIVATE,768DTRACE_STABILITY_PRIVATE,769DTRACE_CLASS_UNKNOWN770};771772const dtrace_attribute_t _dtrace_prvattr = {773DTRACE_STABILITY_PRIVATE,774DTRACE_STABILITY_PRIVATE,775DTRACE_CLASS_UNKNOWN776};777778const dtrace_pattr_t _dtrace_prvdesc = {779{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },780{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },781{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },782{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },783{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },784};785786#ifdef illumos787const char *_dtrace_defcpp = "/usr/ccs/lib/cpp"; /* default cpp(1) to invoke */788const char *_dtrace_defld = "/usr/ccs/bin/ld"; /* default ld(1) to invoke */789#else790const char *_dtrace_defcpp = "cpp"; /* default cpp(1) to invoke */791const char *_dtrace_defld = "ld"; /* default ld(1) to invoke */792const char *_dtrace_defobjcopy = "objcopy"; /* default objcopy(1) to invoke */793#endif794795const char *_dtrace_libdir = "/usr/lib/dtrace"; /* default library directory */796#ifdef illumos797const char *_dtrace_provdir = "/dev/dtrace/provider"; /* provider directory */798#else799const char *_dtrace_libdir32 = "/usr/lib32/dtrace";800const char *_dtrace_provdir = "/dev/dtrace"; /* provider directory */801#endif802803int _dtrace_strbuckets = 211; /* default number of hash buckets (prime) */804int _dtrace_intbuckets = 256; /* default number of integer buckets (Pof2) */805uint_t _dtrace_strsize = 256; /* default size of string intrinsic type */806uint_t _dtrace_stkindent = 14; /* default whitespace indent for stack/ustack */807uint_t _dtrace_pidbuckets = 64; /* default number of pid hash buckets */808uint_t _dtrace_pidlrulim = 8; /* default number of pid handles to cache */809size_t _dtrace_bufsize = 512; /* default dt_buf_create() size */810int _dtrace_argmax = 32; /* default maximum number of probe arguments */811812int _dtrace_debug = 0; /* debug messages enabled (off) */813const char *const _dtrace_version = DT_VERS_STRING; /* API version string */814int _dtrace_rdvers = RD_VERSION; /* rtld_db feature version */815816typedef struct dt_fdlist {817int *df_fds; /* array of provider driver file descriptors */818uint_t df_ents; /* number of valid elements in df_fds[] */819uint_t df_size; /* size of df_fds[] */820} dt_fdlist_t;821822#ifdef illumos823#pragma init(_dtrace_init)824#else825void _dtrace_init(void) __attribute__ ((constructor));826#endif827void828_dtrace_init(void)829{830_dtrace_debug = getenv("DTRACE_DEBUG") != NULL;831832for (; _dtrace_rdvers > 0; _dtrace_rdvers--) {833if (rd_init(_dtrace_rdvers) == RD_OK)834break;835}836#if defined(__i386__)837/* make long doubles 64 bits -sson */838(void) fpsetprec(FP_PE);839#endif840}841842static dtrace_hdl_t *843set_open_errno(dtrace_hdl_t *dtp, int *errp, int err)844{845if (dtp != NULL)846dtrace_close(dtp);847if (errp != NULL)848*errp = err;849return (NULL);850}851852static void853dt_provmod_open(dt_provmod_t **provmod, dt_fdlist_t *dfp)854{855dt_provmod_t *prov;856char path[PATH_MAX];857int fd;858#ifdef illumos859struct dirent *dp, *ep;860DIR *dirp;861862if ((dirp = opendir(_dtrace_provdir)) == NULL)863return; /* failed to open directory; just skip it */864865ep = alloca(sizeof (struct dirent) + PATH_MAX + 1);866bzero(ep, sizeof (struct dirent) + PATH_MAX + 1);867868while (readdir_r(dirp, ep, &dp) == 0 && dp != NULL) {869if (dp->d_name[0] == '.')870continue; /* skip "." and ".." */871872if (dfp->df_ents == dfp->df_size) {873uint_t size = dfp->df_size ? dfp->df_size * 2 : 16;874int *fds = realloc(dfp->df_fds, size * sizeof (int));875876if (fds == NULL)877break; /* skip the rest of this directory */878879dfp->df_fds = fds;880dfp->df_size = size;881}882883(void) snprintf(path, sizeof (path), "%s/%s",884_dtrace_provdir, dp->d_name);885886if ((fd = open(path, O_RDONLY)) == -1)887continue; /* failed to open driver; just skip it */888889if (((prov = malloc(sizeof (dt_provmod_t))) == NULL) ||890(prov->dp_name = malloc(strlen(dp->d_name) + 1)) == NULL) {891free(prov);892(void) close(fd);893break;894}895896(void) strcpy(prov->dp_name, dp->d_name);897prov->dp_next = *provmod;898*provmod = prov;899900dt_dprintf("opened provider %s\n", dp->d_name);901dfp->df_fds[dfp->df_ents++] = fd;902}903904(void) closedir(dirp);905#else /* !illumos */906char *p;907char *p1;908char *p_providers = NULL;909int error;910size_t len = 0;911912/*913* Loop to allocate/reallocate memory for the string of provider914* names and retry:915*/916while(1) {917/*918* The first time around, get the string length. The next time,919* hopefully we've allocated enough memory.920*/921error = sysctlbyname("debug.dtrace.providers",p_providers,&len,NULL,0);922if (len == 0)923/* No providers? That's strange. Where's dtrace? */924break;925else if (error == 0 && p_providers == NULL) {926/*927* Allocate the initial memory which should be enough928* unless another provider loads before we have929* time to go back and get the string.930*/931if ((p_providers = malloc(len)) == NULL)932/* How do we report errors here? */933return;934} else if (error == -1 && errno == ENOMEM) {935/*936* The current buffer isn't large enough, so937* reallocate it. We normally won't need to do this938* because providers aren't being loaded all the time.939*/940if ((p = realloc(p_providers,len)) == NULL) {941free(p_providers);942/* How do we report errors here? */943return;944}945p_providers = p;946} else947break;948}949950/* Check if we got a string of provider names: */951if (error == 0 && len > 0 && p_providers != NULL) {952p = p_providers;953954/*955* Parse the string containing the space separated956* provider names.957*/958while ((p1 = strsep(&p," ")) != NULL) {959if (dfp->df_ents == dfp->df_size) {960uint_t size = dfp->df_size ? dfp->df_size * 2 : 16;961int *fds = realloc(dfp->df_fds, size * sizeof (int));962963if (fds == NULL)964break;965966dfp->df_fds = fds;967dfp->df_size = size;968}969970(void) snprintf(path, sizeof (path), "/dev/dtrace/%s", p1);971972if ((fd = open(path, O_RDONLY | O_CLOEXEC)) == -1)973continue; /* failed to open driver; just skip it */974975if (((prov = malloc(sizeof (dt_provmod_t))) == NULL) ||976(prov->dp_name = malloc(strlen(p1) + 1)) == NULL) {977free(prov);978(void) close(fd);979break;980}981982(void) strcpy(prov->dp_name, p1);983prov->dp_next = *provmod;984*provmod = prov;985986dt_dprintf("opened provider %s\n", p1);987dfp->df_fds[dfp->df_ents++] = fd;988}989}990if (p_providers != NULL)991free(p_providers);992#endif /* illumos */993}994995static void996dt_provmod_destroy(dt_provmod_t **provmod)997{998dt_provmod_t *next, *current;9991000for (current = *provmod; current != NULL; current = next) {1001next = current->dp_next;1002free(current->dp_name);1003free(current);1004}10051006*provmod = NULL;1007}10081009#ifdef illumos1010static const char *1011dt_get_sysinfo(int cmd, char *buf, size_t len)1012{1013ssize_t rv = sysinfo(cmd, buf, len);1014char *p = buf;10151016if (rv < 0 || rv > len)1017(void) snprintf(buf, len, "%s", "Unknown");10181019while ((p = strchr(p, '.')) != NULL)1020*p++ = '_';10211022return (buf);1023}1024#endif10251026static dtrace_hdl_t *1027dt_vopen(int version, int flags, int *errp,1028const dtrace_vector_t *vector, void *arg)1029{1030dtrace_hdl_t *dtp = NULL;1031int dtfd = -1, ftfd = -1, fterr = 0;1032dtrace_prog_t *pgp;1033dt_module_t *dmp;1034dt_provmod_t *provmod = NULL;1035int i, err;1036struct rlimit rl;10371038const dt_intrinsic_t *dinp;1039const dt_typedef_t *dtyp;1040const dt_ident_t *idp;10411042dtrace_typeinfo_t dtt;1043ctf_funcinfo_t ctc;1044ctf_arinfo_t ctr;10451046dt_fdlist_t df = { NULL, 0, 0 };10471048char isadef[32], utsdef[32];1049char s1[64], s2[64];10501051if (version <= 0)1052return (set_open_errno(dtp, errp, EINVAL));10531054if (version > DTRACE_VERSION)1055return (set_open_errno(dtp, errp, EDT_VERSION));10561057if (version < DTRACE_VERSION) {1058/*1059* Currently, increasing the library version number is used to1060* denote a binary incompatible change. That is, a consumer1061* of the library cannot run on a version of the library with1062* a higher DTRACE_VERSION number than the consumer compiled1063* against. Once the library API has been committed to,1064* backwards binary compatibility will be required; at that1065* time, this check should change to return EDT_OVERSION only1066* if the specified version number is less than the version1067* number at the time of interface commitment.1068*/1069return (set_open_errno(dtp, errp, EDT_OVERSION));1070}10711072if (flags & ~DTRACE_O_MASK)1073return (set_open_errno(dtp, errp, EINVAL));10741075switch (flags & DTRACE_O_MODEL_MASK) {1076case 0: /* native model */1077case DTRACE_O_ILP32:1078case DTRACE_O_LP64:1079break;1080default:1081return (set_open_errno(dtp, errp, EINVAL));1082}10831084if (vector == NULL && arg != NULL)1085return (set_open_errno(dtp, errp, EINVAL));10861087if (elf_version(EV_CURRENT) == EV_NONE)1088return (set_open_errno(dtp, errp, EDT_ELFVERSION));10891090if (vector != NULL || (flags & DTRACE_O_NODEV))1091goto alloc; /* do not attempt to open dtrace device */10921093/*1094* Before we get going, crank our limit on file descriptors up to the1095* hard limit. This is to allow for the fact that libproc keeps file1096* descriptors to objects open for the lifetime of the proc handle;1097* without raising our hard limit, we would have an acceptably small1098* bound on the number of processes that we could concurrently1099* instrument with the pid provider.1100*/1101if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {1102rl.rlim_cur = rl.rlim_max;1103(void) setrlimit(RLIMIT_NOFILE, &rl);1104}11051106/*1107* Get the device path of each of the providers. We hold them open1108* in the df.df_fds list until we open the DTrace driver itself,1109* allowing us to see all of the probes provided on this system. Once1110* we have the DTrace driver open, we can safely close all the providers1111* now that they have registered with the framework.1112*/1113dt_provmod_open(&provmod, &df);11141115dtfd = open("/dev/dtrace/dtrace", O_RDWR | O_CLOEXEC);1116err = dtfd == -1 ? errno : 0; /* save errno from opening dtfd */1117#if defined(__FreeBSD__)1118/*1119* Automatically load the 'dtraceall' module if we couldn't open the1120* char device.1121*/1122if (err == ENOENT && modfind("dtraceall") < 0) {1123kldload("dtraceall"); /* ignore the error */1124#if __SIZEOF_LONG__ == 81125if (modfind("linux64elf") >= 0)1126kldload("systrace_linux");1127if (modfind("linuxelf") >= 0)1128kldload("systrace_linux32");1129#else1130if (modfind("linuxelf") >= 0)1131kldload("systrace_linux");1132#endif1133dtfd = open("/dev/dtrace/dtrace", O_RDWR | O_CLOEXEC);1134err = errno;1135}1136#endif1137#ifdef illumos1138ftfd = open("/dev/dtrace/provider/fasttrap", O_RDWR);1139#else1140ftfd = open("/dev/dtrace/fasttrap", O_RDWR | O_CLOEXEC);1141#endif1142fterr = ftfd == -1 ? errno : 0; /* save errno from open ftfd */11431144while (df.df_ents-- != 0)1145(void) close(df.df_fds[df.df_ents]);11461147free(df.df_fds);11481149/*1150* If we failed to open the dtrace device, fail dtrace_open().1151* We convert some kernel errnos to custom libdtrace errnos to1152* improve the resulting message from the usual strerror().1153*/1154if (dtfd == -1) {1155dt_provmod_destroy(&provmod);1156switch (err) {1157case ENOENT:1158err = EDT_NOENT;1159break;1160case EBUSY:1161err = EDT_BUSY;1162break;1163case EACCES:1164err = EDT_ACCESS;1165break;1166}1167return (set_open_errno(dtp, errp, err));1168}11691170alloc:1171if ((dtp = malloc(sizeof (dtrace_hdl_t))) == NULL) {1172dt_provmod_destroy(&provmod);1173return (set_open_errno(dtp, errp, EDT_NOMEM));1174}11751176bzero(dtp, sizeof (dtrace_hdl_t));1177dtp->dt_oflags = flags;1178#ifdef illumos1179dtp->dt_prcmode = DT_PROC_STOP_PREINIT;1180#else1181dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;1182#endif1183dtp->dt_linkmode = DT_LINK_KERNEL;1184dtp->dt_linktype = DT_LTYP_ELF;1185dtp->dt_xlatemode = DT_XL_STATIC;1186dtp->dt_stdcmode = DT_STDC_XA;1187dtp->dt_encoding = DT_ENCODING_UNSET;1188dtp->dt_version = version;1189dtp->dt_fd = dtfd;1190dtp->dt_ftfd = ftfd;1191dtp->dt_kinstfd = -1;1192dtp->dt_fterr = fterr;1193dtp->dt_cdefs_fd = -1;1194dtp->dt_ddefs_fd = -1;1195#ifdef illumos1196dtp->dt_stdout_fd = -1;1197#else1198dtp->dt_freopen_fp = NULL;1199#endif1200dtp->dt_modbuckets = _dtrace_strbuckets;1201dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));1202#ifdef __FreeBSD__1203dtp->dt_kmods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));1204#endif1205dtp->dt_provbuckets = _dtrace_strbuckets;1206dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));1207dt_proc_init(dtp);1208dtp->dt_vmax = DT_VERS_LATEST;1209dtp->dt_cpp_path = strdup(_dtrace_defcpp);1210dtp->dt_cpp_argv = malloc(sizeof (char *));1211dtp->dt_cpp_argc = 1;1212dtp->dt_cpp_args = 1;1213dtp->dt_ld_path = strdup(_dtrace_defld);1214#ifdef __FreeBSD__1215dtp->dt_objcopy_path = strdup(_dtrace_defobjcopy);1216#endif1217dtp->dt_provmod = provmod;1218dtp->dt_vector = vector;1219dtp->dt_varg = arg;1220dt_dof_init(dtp);1221(void) uname(&dtp->dt_uts);12221223if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||1224dtp->dt_procs == NULL || dtp->dt_proc_env == NULL ||1225dtp->dt_ld_path == NULL || dtp->dt_cpp_path == NULL ||1226#ifdef __FreeBSD__1227dtp->dt_kmods == NULL ||1228dtp->dt_objcopy_path == NULL ||1229#endif1230dtp->dt_cpp_argv == NULL)1231return (set_open_errno(dtp, errp, EDT_NOMEM));12321233for (i = 0; i < DTRACEOPT_MAX; i++)1234dtp->dt_options[i] = DTRACEOPT_UNSET;12351236dtp->dt_cpp_argv[0] = (char *)strbasename(dtp->dt_cpp_path);12371238#ifdef illumos1239(void) snprintf(isadef, sizeof (isadef), "-D__SUNW_D_%u",1240(uint_t)(sizeof (void *) * NBBY));12411242(void) snprintf(utsdef, sizeof (utsdef), "-D__%s_%s",1243dt_get_sysinfo(SI_SYSNAME, s1, sizeof (s1)),1244dt_get_sysinfo(SI_RELEASE, s2, sizeof (s2)));12451246if (dt_cpp_add_arg(dtp, "-D__sun") == NULL ||1247dt_cpp_add_arg(dtp, "-D__unix") == NULL ||1248dt_cpp_add_arg(dtp, "-D__SVR4") == NULL ||1249dt_cpp_add_arg(dtp, "-D__SUNW_D=1") == NULL ||1250dt_cpp_add_arg(dtp, isadef) == NULL ||1251dt_cpp_add_arg(dtp, utsdef) == NULL)1252return (set_open_errno(dtp, errp, EDT_NOMEM));1253#endif12541255if (flags & DTRACE_O_NODEV)1256bcopy(&_dtrace_conf, &dtp->dt_conf, sizeof (_dtrace_conf));1257else if (dt_ioctl(dtp, DTRACEIOC_CONF, &dtp->dt_conf) != 0)1258return (set_open_errno(dtp, errp, errno));12591260if (flags & DTRACE_O_LP64)1261dtp->dt_conf.dtc_ctfmodel = CTF_MODEL_LP64;1262else if (flags & DTRACE_O_ILP32)1263dtp->dt_conf.dtc_ctfmodel = CTF_MODEL_ILP32;12641265#ifdef __sparc1266/*1267* On SPARC systems, __sparc is always defined for <sys/isa_defs.h>1268* and __sparcv9 is defined if we are doing a 64-bit compile.1269*/1270if (dt_cpp_add_arg(dtp, "-D__sparc") == NULL)1271return (set_open_errno(dtp, errp, EDT_NOMEM));12721273if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64 &&1274dt_cpp_add_arg(dtp, "-D__sparcv9") == NULL)1275return (set_open_errno(dtp, errp, EDT_NOMEM));1276#endif12771278#ifdef illumos1279#ifdef __x861280/*1281* On x86 systems, __i386 is defined for <sys/isa_defs.h> for 32-bit1282* compiles and __amd64 is defined for 64-bit compiles. Unlike SPARC,1283* they are defined exclusive of one another (see PSARC 2004/619).1284*/1285if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) {1286if (dt_cpp_add_arg(dtp, "-D__amd64") == NULL)1287return (set_open_errno(dtp, errp, EDT_NOMEM));1288} else {1289if (dt_cpp_add_arg(dtp, "-D__i386") == NULL)1290return (set_open_errno(dtp, errp, EDT_NOMEM));1291}1292#endif1293#else1294#if defined(__amd64__) || defined(__i386__)1295if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) {1296if (dt_cpp_add_arg(dtp, "-m64") == NULL)1297return (set_open_errno(dtp, errp, EDT_NOMEM));1298} else {1299if (dt_cpp_add_arg(dtp, "-m32") == NULL)1300return (set_open_errno(dtp, errp, EDT_NOMEM));1301}1302#endif1303#endif13041305if (dtp->dt_conf.dtc_difversion < DIF_VERSION)1306return (set_open_errno(dtp, errp, EDT_DIFVERS));13071308if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_ILP32)1309bcopy(_dtrace_ints_32, dtp->dt_ints, sizeof (_dtrace_ints_32));1310else1311bcopy(_dtrace_ints_64, dtp->dt_ints, sizeof (_dtrace_ints_64));13121313/*1314* On FreeBSD the kernel module name can't be hard-coded. The1315* 'kern.bootfile' sysctl value tells us exactly which file is being1316* used as the kernel.1317*/1318#ifndef illumos1319{1320char bootfile[MAXPATHLEN];1321char *p;1322int i;1323size_t len = sizeof(bootfile);13241325/* This call shouldn't fail, but use a default just in case. */1326if (sysctlbyname("kern.bootfile", bootfile, &len, NULL, 0) != 0)1327strlcpy(bootfile, "kernel", sizeof(bootfile));13281329if ((p = strrchr(bootfile, '/')) != NULL)1330p++;1331else1332p = bootfile;13331334/*1335* Format the global variables based on the kernel module name.1336*/1337snprintf(curthread_str, sizeof(curthread_str), "%s`struct thread *",p);1338snprintf(intmtx_str, sizeof(intmtx_str), "int(%s`struct mtx *)",p);1339snprintf(threadmtx_str, sizeof(threadmtx_str), "struct thread *(%s`struct mtx *)",p);1340snprintf(rwlock_str, sizeof(rwlock_str), "int(%s`struct rwlock *)",p);1341snprintf(sxlock_str, sizeof(sxlock_str), "int(%s`struct sx *)",p);1342}1343#endif13441345dtp->dt_macros = dt_idhash_create("macro", NULL, 0, UINT_MAX);1346dtp->dt_aggs = dt_idhash_create("aggregation", NULL,1347DTRACE_AGGVARIDNONE + 1, UINT_MAX);13481349dtp->dt_globals = dt_idhash_create("global", _dtrace_globals,1350DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);13511352dtp->dt_tls = dt_idhash_create("thread local", NULL,1353DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);13541355if (dtp->dt_macros == NULL || dtp->dt_aggs == NULL ||1356dtp->dt_globals == NULL || dtp->dt_tls == NULL)1357return (set_open_errno(dtp, errp, EDT_NOMEM));13581359/*1360* Populate the dt_macros identifier hash table by hand: we can't use1361* the dt_idhash_populate() mechanism because we're not yet compiling1362* and dtrace_update() needs to immediately reference these idents.1363*/1364for (idp = _dtrace_macros; idp->di_name != NULL; idp++) {1365if (dt_idhash_insert(dtp->dt_macros, idp->di_name,1366idp->di_kind, idp->di_flags, idp->di_id, idp->di_attr,1367idp->di_vers, idp->di_ops ? idp->di_ops : &dt_idops_thaw,1368idp->di_iarg, 0) == NULL)1369return (set_open_errno(dtp, errp, EDT_NOMEM));1370}13711372/*1373* Update the module list using /system/object and load the values for1374* the macro variable definitions according to the current process.1375*/1376dtrace_update(dtp);13771378/*1379* Select the intrinsics and typedefs we want based on the data model.1380* The intrinsics are under "C". The typedefs are added under "D".1381*/1382if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_ILP32) {1383dinp = _dtrace_intrinsics_32;1384dtyp = _dtrace_typedefs_32;1385} else {1386dinp = _dtrace_intrinsics_64;1387dtyp = _dtrace_typedefs_64;1388}13891390/*1391* Create a dynamic CTF container under the "C" scope for intrinsic1392* types and types defined in ANSI-C header files that are included.1393*/1394if ((dmp = dtp->dt_cdefs = dt_module_create(dtp, "C")) == NULL)1395return (set_open_errno(dtp, errp, EDT_NOMEM));13961397if ((dmp->dm_ctfp = ctf_create(&dtp->dt_ctferr)) == NULL)1398return (set_open_errno(dtp, errp, EDT_CTF));13991400dt_dprintf("created CTF container for %s (%p)\n",1401dmp->dm_name, (void *)dmp->dm_ctfp);14021403(void) ctf_setmodel(dmp->dm_ctfp, dtp->dt_conf.dtc_ctfmodel);1404ctf_setspecific(dmp->dm_ctfp, dmp);14051406dmp->dm_flags = DT_DM_LOADED; /* fake up loaded bit */1407dmp->dm_modid = -1; /* no module ID */14081409/*1410* Fill the dynamic "C" CTF container with all of the intrinsic1411* integer and floating-point types appropriate for this data model.1412*/1413for (; dinp->din_name != NULL; dinp++) {1414if (dinp->din_kind == CTF_K_INTEGER) {1415err = ctf_add_integer(dmp->dm_ctfp, CTF_ADD_ROOT,1416dinp->din_name, &dinp->din_data);1417} else {1418err = ctf_add_float(dmp->dm_ctfp, CTF_ADD_ROOT,1419dinp->din_name, &dinp->din_data);1420}14211422if (err == CTF_ERR) {1423dt_dprintf("failed to add %s to C container: %s\n",1424dinp->din_name, ctf_errmsg(1425ctf_errno(dmp->dm_ctfp)));1426return (set_open_errno(dtp, errp, EDT_CTF));1427}1428}14291430if (ctf_update(dmp->dm_ctfp) != 0) {1431dt_dprintf("failed to update C container: %s\n",1432ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1433return (set_open_errno(dtp, errp, EDT_CTF));1434}14351436/*1437* Add intrinsic pointer types that are needed to initialize printf1438* format dictionary types (see table in dt_printf.c).1439*/1440(void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT,1441ctf_lookup_by_name(dmp->dm_ctfp, "void"));14421443(void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT,1444ctf_lookup_by_name(dmp->dm_ctfp, "char"));14451446(void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT,1447ctf_lookup_by_name(dmp->dm_ctfp, "int"));14481449if (ctf_update(dmp->dm_ctfp) != 0) {1450dt_dprintf("failed to update C container: %s\n",1451ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1452return (set_open_errno(dtp, errp, EDT_CTF));1453}14541455/*1456* Create a dynamic CTF container under the "D" scope for types that1457* are defined by the D program itself or on-the-fly by the D compiler.1458* The "D" CTF container is a child of the "C" CTF container.1459*/1460if ((dmp = dtp->dt_ddefs = dt_module_create(dtp, "D")) == NULL)1461return (set_open_errno(dtp, errp, EDT_NOMEM));14621463if ((dmp->dm_ctfp = ctf_create(&dtp->dt_ctferr)) == NULL)1464return (set_open_errno(dtp, errp, EDT_CTF));14651466dt_dprintf("created CTF container for %s (%p)\n",1467dmp->dm_name, (void *)dmp->dm_ctfp);14681469(void) ctf_setmodel(dmp->dm_ctfp, dtp->dt_conf.dtc_ctfmodel);1470ctf_setspecific(dmp->dm_ctfp, dmp);14711472dmp->dm_flags = DT_DM_LOADED; /* fake up loaded bit */1473dmp->dm_modid = -1; /* no module ID */14741475if (ctf_import(dmp->dm_ctfp, dtp->dt_cdefs->dm_ctfp) == CTF_ERR) {1476dt_dprintf("failed to import D parent container: %s\n",1477ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1478return (set_open_errno(dtp, errp, EDT_CTF));1479}14801481/*1482* Fill the dynamic "D" CTF container with all of the built-in typedefs1483* that we need to use for our D variable and function definitions.1484* This ensures that basic inttypes.h names are always available to us.1485*/1486for (; dtyp->dty_src != NULL; dtyp++) {1487if (ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,1488dtyp->dty_dst, ctf_lookup_by_name(dmp->dm_ctfp,1489dtyp->dty_src)) == CTF_ERR) {1490dt_dprintf("failed to add typedef %s %s to D "1491"container: %s\n", dtyp->dty_src, dtyp->dty_dst,1492ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1493return (set_open_errno(dtp, errp, EDT_CTF));1494}1495}14961497/*1498* Insert a CTF ID corresponding to a pointer to a type of kind1499* CTF_K_FUNCTION we can use in the compiler for function pointers.1500* CTF treats all function pointers as "int (*)()" so we only need one.1501*/1502ctc.ctc_return = ctf_lookup_by_name(dmp->dm_ctfp, "int");1503ctc.ctc_argc = 0;1504ctc.ctc_flags = 0;15051506dtp->dt_type_func = ctf_add_function(dmp->dm_ctfp,1507CTF_ADD_ROOT, &ctc, NULL);15081509dtp->dt_type_fptr = ctf_add_pointer(dmp->dm_ctfp,1510CTF_ADD_ROOT, dtp->dt_type_func);15111512/*1513* We also insert CTF definitions for the special D intrinsic types1514* string and <DYN> into the D container. The string type is added1515* as a typedef of char[n]. The <DYN> type is an alias for void.1516* We compare types to these special CTF ids throughout the compiler.1517*/1518ctr.ctr_contents = ctf_lookup_by_name(dmp->dm_ctfp, "char");1519ctr.ctr_index = ctf_lookup_by_name(dmp->dm_ctfp, "long");1520ctr.ctr_nelems = _dtrace_strsize;15211522dtp->dt_type_str = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,1523"string", ctf_add_array(dmp->dm_ctfp, CTF_ADD_ROOT, &ctr));15241525dtp->dt_type_dyn = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,1526"<DYN>", ctf_lookup_by_name(dmp->dm_ctfp, "void"));15271528dtp->dt_type_stack = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,1529"stack", ctf_lookup_by_name(dmp->dm_ctfp, "void"));15301531dtp->dt_type_symaddr = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,1532"_symaddr", ctf_lookup_by_name(dmp->dm_ctfp, "void"));15331534dtp->dt_type_usymaddr = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,1535"_usymaddr", ctf_lookup_by_name(dmp->dm_ctfp, "void"));15361537if (dtp->dt_type_func == CTF_ERR || dtp->dt_type_fptr == CTF_ERR ||1538dtp->dt_type_str == CTF_ERR || dtp->dt_type_dyn == CTF_ERR ||1539dtp->dt_type_stack == CTF_ERR || dtp->dt_type_symaddr == CTF_ERR ||1540dtp->dt_type_usymaddr == CTF_ERR) {1541dt_dprintf("failed to add intrinsic to D container: %s\n",1542ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1543return (set_open_errno(dtp, errp, EDT_CTF));1544}15451546if (ctf_update(dmp->dm_ctfp) != 0) {1547dt_dprintf("failed update D container: %s\n",1548ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1549return (set_open_errno(dtp, errp, EDT_CTF));1550}15511552/*1553* Initialize the integer description table used to convert integer1554* constants to the appropriate types. Refer to the comments above1555* dt_node_int() for a complete description of how this table is used.1556*/1557for (i = 0; i < sizeof (dtp->dt_ints) / sizeof (dtp->dt_ints[0]); i++) {1558if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_EVERY,1559dtp->dt_ints[i].did_name, &dtt) != 0) {1560dt_dprintf("failed to lookup integer type %s: %s\n",1561dtp->dt_ints[i].did_name,1562dtrace_errmsg(dtp, dtrace_errno(dtp)));1563return (set_open_errno(dtp, errp, dtp->dt_errno));1564}1565dtp->dt_ints[i].did_ctfp = dtt.dtt_ctfp;1566dtp->dt_ints[i].did_type = dtt.dtt_type;1567}15681569/*1570* Now that we've created the "C" and "D" containers, move them to the1571* start of the module list so that these types and symbols are found1572* first (for stability) when iterating through the module list.1573*/1574dt_list_delete(&dtp->dt_modlist, dtp->dt_ddefs);1575dt_list_prepend(&dtp->dt_modlist, dtp->dt_ddefs);15761577dt_list_delete(&dtp->dt_modlist, dtp->dt_cdefs);1578dt_list_prepend(&dtp->dt_modlist, dtp->dt_cdefs);15791580if (dt_pfdict_create(dtp) == -1)1581return (set_open_errno(dtp, errp, dtp->dt_errno));15821583/*1584* If we are opening libdtrace DTRACE_O_NODEV enable C_ZDEFS by default1585* because without /dev/dtrace open, we will not be able to load the1586* names and attributes of any providers or probes from the kernel.1587*/1588if (flags & DTRACE_O_NODEV)1589dtp->dt_cflags |= DTRACE_C_ZDEFS;15901591/*1592* Load hard-wired inlines into the definition cache by calling the1593* compiler on the raw definition string defined above.1594*/1595if ((pgp = dtrace_program_strcompile(dtp, _dtrace_hardwire,1596DTRACE_PROBESPEC_NONE, DTRACE_C_EMPTY, 0, NULL)) == NULL) {1597dt_dprintf("failed to load hard-wired definitions: %s\n",1598dtrace_errmsg(dtp, dtrace_errno(dtp)));1599return (set_open_errno(dtp, errp, EDT_HARDWIRE));1600}16011602dt_program_destroy(dtp, pgp);16031604/*1605* Set up the default DTrace library path. Once set, the next call to1606* dt_compile() will compile all the libraries. We intentionally defer1607* library processing to improve overhead for clients that don't ever1608* compile, and to provide better error reporting (because the full1609* reporting of compiler errors requires dtrace_open() to succeed).1610*/1611#ifdef __FreeBSD__1612#ifdef __LP64__1613if ((dtp->dt_oflags & DTRACE_O_ILP32) != 0) {1614if (dtrace_setopt(dtp, "libdir", _dtrace_libdir32) != 0)1615return (set_open_errno(dtp, errp, dtp->dt_errno));1616}1617#endif1618if (dtrace_setopt(dtp, "libdir", _dtrace_libdir) != 0)1619return (set_open_errno(dtp, errp, dtp->dt_errno));1620#else1621if (dtrace_setopt(dtp, "libdir", _dtrace_libdir) != 0)1622return (set_open_errno(dtp, errp, dtp->dt_errno));1623#endif16241625return (dtp);1626}16271628dtrace_hdl_t *1629dtrace_open(int version, int flags, int *errp)1630{1631return (dt_vopen(version, flags, errp, NULL, NULL));1632}16331634dtrace_hdl_t *1635dtrace_vopen(int version, int flags, int *errp,1636const dtrace_vector_t *vector, void *arg)1637{1638return (dt_vopen(version, flags, errp, vector, arg));1639}16401641void1642dtrace_close(dtrace_hdl_t *dtp)1643{1644dt_ident_t *idp, *ndp;1645dt_module_t *dmp;1646dt_provider_t *pvp;1647dtrace_prog_t *pgp;1648dt_xlator_t *dxp;1649dt_dirpath_t *dirp;1650#ifdef __FreeBSD__1651dt_kmodule_t *dkm;1652uint_t h;1653#endif1654int i;16551656if (dtp->dt_procs != NULL)1657dt_proc_fini(dtp);16581659while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)1660dt_program_destroy(dtp, pgp);16611662while ((dxp = dt_list_next(&dtp->dt_xlators)) != NULL)1663dt_xlator_destroy(dtp, dxp);16641665dt_free(dtp, dtp->dt_xlatormap);16661667for (idp = dtp->dt_externs; idp != NULL; idp = ndp) {1668ndp = idp->di_next;1669dt_ident_destroy(idp);1670}16711672if (dtp->dt_macros != NULL)1673dt_idhash_destroy(dtp->dt_macros);1674if (dtp->dt_aggs != NULL)1675dt_idhash_destroy(dtp->dt_aggs);1676if (dtp->dt_globals != NULL)1677dt_idhash_destroy(dtp->dt_globals);1678if (dtp->dt_tls != NULL)1679dt_idhash_destroy(dtp->dt_tls);16801681#ifdef __FreeBSD__1682for (h = 0; h < dtp->dt_modbuckets; h++)1683while ((dkm = dtp->dt_kmods[h]) != NULL) {1684dtp->dt_kmods[h] = dkm->dkm_next;1685free(dkm->dkm_name);1686free(dkm);1687}1688#endif16891690while ((dmp = dt_list_next(&dtp->dt_modlist)) != NULL)1691dt_module_destroy(dtp, dmp);16921693while ((pvp = dt_list_next(&dtp->dt_provlist)) != NULL)1694dt_provider_destroy(dtp, pvp);16951696if (dtp->dt_fd != -1)1697(void) close(dtp->dt_fd);1698if (dtp->dt_ftfd != -1)1699(void) close(dtp->dt_ftfd);1700if (dtp->dt_kinstfd != -1)1701(void) close(dtp->dt_kinstfd);1702if (dtp->dt_cdefs_fd != -1)1703(void) close(dtp->dt_cdefs_fd);1704if (dtp->dt_ddefs_fd != -1)1705(void) close(dtp->dt_ddefs_fd);1706#ifdef illumos1707if (dtp->dt_stdout_fd != -1)1708(void) close(dtp->dt_stdout_fd);1709#else1710if (dtp->dt_freopen_fp != NULL)1711(void) fclose(dtp->dt_freopen_fp);1712#endif17131714dt_epid_destroy(dtp);1715dt_aggid_destroy(dtp);1716dt_format_destroy(dtp);1717dt_strdata_destroy(dtp);1718dt_buffered_destroy(dtp);1719dt_aggregate_destroy(dtp);1720dt_pfdict_destroy(dtp);1721dt_provmod_destroy(&dtp->dt_provmod);1722dt_dof_fini(dtp);17231724for (i = 1; i < dtp->dt_cpp_argc; i++)1725free(dtp->dt_cpp_argv[i]);17261727while ((dirp = dt_list_next(&dtp->dt_lib_path)) != NULL) {1728dt_list_delete(&dtp->dt_lib_path, dirp);1729free(dirp->dir_path);1730free(dirp);1731}17321733free(dtp->dt_cpp_argv);1734free(dtp->dt_cpp_path);1735free(dtp->dt_ld_path);1736#ifdef __FreeBSD__1737free(dtp->dt_objcopy_path);1738#endif17391740free(dtp->dt_mods);1741#ifdef __FreeBSD__1742free(dtp->dt_kmods);1743#endif1744free(dtp->dt_provs);17451746xo_finish();1747free(dtp);1748}17491750int1751dtrace_provider_modules(dtrace_hdl_t *dtp, const char **mods, int nmods)1752{1753dt_provmod_t *prov;1754int i = 0;17551756for (prov = dtp->dt_provmod; prov != NULL; prov = prov->dp_next, i++) {1757if (i < nmods)1758mods[i] = prov->dp_name;1759}17601761return (i);1762}17631764int1765dtrace_ctlfd(dtrace_hdl_t *dtp)1766{1767return (dtp->dt_fd);1768}176917701771