dt_open.c revision 267937
198944Sobrien/*
298944Sobrien * CDDL HEADER START
398944Sobrien *
498944Sobrien * The contents of this file are subject to the terms of the
598944Sobrien * Common Development and Distribution License (the "License").
698944Sobrien * You may not use this file except in compliance with the License.
798944Sobrien *
898944Sobrien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
998944Sobrien * or http://www.opensolaris.org/os/licensing.
1098944Sobrien * See the License for the specific language governing permissions
1198944Sobrien * and limitations under the License.
1298944Sobrien *
1398944Sobrien * When distributing Covered Code, include this CDDL HEADER in each
1498944Sobrien * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1598944Sobrien * If applicable, add the following below this CDDL HEADER, with the
1698944Sobrien * fields enclosed by brackets "[]" replaced with your own identifying
1798944Sobrien * information: Portions Copyright [yyyy] [name of copyright owner]
1898944Sobrien *
1998944Sobrien * CDDL HEADER END
2098944Sobrien */
2198944Sobrien
2298944Sobrien/*
2398944Sobrien * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2498944Sobrien * Copyright (c) 2012, Joyent, Inc. All rights reserved.
2598944Sobrien * Copyright (c) 2012 by Delphix. All rights reserved.
2698944Sobrien */
2798944Sobrien
2898944Sobrien#include <sys/types.h>
2998944Sobrien#if defined(sun)
3098944Sobrien#include <sys/modctl.h>
3198944Sobrien#include <sys/systeminfo.h>
3298944Sobrien#endif
3398944Sobrien#include <sys/resource.h>
3498944Sobrien
3598944Sobrien#include <libelf.h>
3698944Sobrien#include <strings.h>
3798944Sobrien#if defined(sun)
3898944Sobrien#include <alloca.h>
3998944Sobrien#endif
4098944Sobrien#include <limits.h>
4198944Sobrien#include <unistd.h>
4298944Sobrien#include <stdlib.h>
4398944Sobrien#include <stdio.h>
4498944Sobrien#include <fcntl.h>
4598944Sobrien#include <errno.h>
4698944Sobrien#include <assert.h>
4798944Sobrien
4898944Sobrien#define	_POSIX_PTHREAD_SEMANTICS
4998944Sobrien#include <dirent.h>
5098944Sobrien#undef	_POSIX_PTHREAD_SEMANTICS
5198944Sobrien
5298944Sobrien#include <dt_impl.h>
5398944Sobrien#include <dt_program.h>
5498944Sobrien#include <dt_module.h>
5598944Sobrien#include <dt_printf.h>
5698944Sobrien#include <dt_string.h>
5798944Sobrien#include <dt_provider.h>
5898944Sobrien#if !defined(sun)
5998944Sobrien#include <sys/sysctl.h>
6098944Sobrien#include <string.h>
6198944Sobrien#endif
6298944Sobrien#if defined(__i386__)
6398944Sobrien#include <ieeefp.h>
6498944Sobrien#endif
6598944Sobrien
6698944Sobrien/*
6798944Sobrien * Stability and versioning definitions.  These #defines are used in the tables
6898944Sobrien * of identifiers below to fill in the attribute and version fields associated
6998944Sobrien * with each identifier.  The DT_ATTR_* macros are a convenience to permit more
7098944Sobrien * concise declarations of common attributes such as Stable/Stable/Common.  The
7198944Sobrien * DT_VERS_* macros declare the encoded integer values of all versions used so
7298944Sobrien * far.  DT_VERS_LATEST must correspond to the latest version value among all
7398944Sobrien * versions exported by the D compiler.  DT_VERS_STRING must be an ASCII string
7498944Sobrien * that contains DT_VERS_LATEST within it along with any suffixes (e.g. Beta).
7598944Sobrien * You must update DT_VERS_LATEST and DT_VERS_STRING when adding a new version,
7698944Sobrien * and then add the new version to the _dtrace_versions[] array declared below.
7798944Sobrien * Refer to the Solaris Dynamic Tracing Guide Stability and Versioning chapters
7898944Sobrien * respectively for an explanation of these DTrace features and their values.
7998944Sobrien *
8098944Sobrien * NOTE: Although the DTrace versioning scheme supports the labeling and
8198944Sobrien *       introduction of incompatible changes (e.g. dropping an interface in a
8298944Sobrien *       major release), the libdtrace code does not currently support this.
8398944Sobrien *       All versions are assumed to strictly inherit from one another.  If
8498944Sobrien *       we ever need to provide divergent interfaces, this will need work.
8598944Sobrien */
8698944Sobrien#define	DT_ATTR_STABCMN	{ DTRACE_STABILITY_STABLE, \
8798944Sobrien	DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }
8898944Sobrien
8998944Sobrien#define	DT_ATTR_EVOLCMN { DTRACE_STABILITY_EVOLVING, \
9098944Sobrien	DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON \
9198944Sobrien}
9298944Sobrien
9398944Sobrien/*
9498944Sobrien * The version number should be increased for every customer visible release
9598944Sobrien * of DTrace. The major number should be incremented when a fundamental
9698944Sobrien * change has been made that would affect all consumers, and would reflect
9798944Sobrien * sweeping changes to DTrace or the D language. The minor number should be
9898944Sobrien * incremented when a change is introduced that could break scripts that had
9998944Sobrien * previously worked; for example, adding a new built-in variable could break
10098944Sobrien * a script which was already using that identifier. The micro number should
10198944Sobrien * be changed when introducing functionality changes or major bug fixes that
10298944Sobrien * do not affect backward compatibility -- this is merely to make capabilities
10398944Sobrien * easily determined from the version number. Minor bugs do not require any
10498944Sobrien * modification to the version number.
10598944Sobrien */
10698944Sobrien#define	DT_VERS_1_0	DT_VERSION_NUMBER(1, 0, 0)
10798944Sobrien#define	DT_VERS_1_1	DT_VERSION_NUMBER(1, 1, 0)
10898944Sobrien#define	DT_VERS_1_2	DT_VERSION_NUMBER(1, 2, 0)
10998944Sobrien#define	DT_VERS_1_2_1	DT_VERSION_NUMBER(1, 2, 1)
11098944Sobrien#define	DT_VERS_1_2_2	DT_VERSION_NUMBER(1, 2, 2)
11198944Sobrien#define	DT_VERS_1_3	DT_VERSION_NUMBER(1, 3, 0)
11298944Sobrien#define	DT_VERS_1_4	DT_VERSION_NUMBER(1, 4, 0)
11398944Sobrien#define	DT_VERS_1_4_1	DT_VERSION_NUMBER(1, 4, 1)
11498944Sobrien#define	DT_VERS_1_5	DT_VERSION_NUMBER(1, 5, 0)
11598944Sobrien#define	DT_VERS_1_6	DT_VERSION_NUMBER(1, 6, 0)
11698944Sobrien#define	DT_VERS_1_6_1	DT_VERSION_NUMBER(1, 6, 1)
11798944Sobrien#define	DT_VERS_1_6_2	DT_VERSION_NUMBER(1, 6, 2)
11898944Sobrien#define	DT_VERS_1_6_3	DT_VERSION_NUMBER(1, 6, 3)
119130803Smarcel#define	DT_VERS_1_7	DT_VERSION_NUMBER(1, 7, 0)
120130803Smarcel#define	DT_VERS_1_7_1	DT_VERSION_NUMBER(1, 7, 1)
121130803Smarcel#define	DT_VERS_1_8	DT_VERSION_NUMBER(1, 8, 0)
122130803Smarcel#define	DT_VERS_1_8_1	DT_VERSION_NUMBER(1, 8, 1)
123130803Smarcel#define	DT_VERS_1_9	DT_VERSION_NUMBER(1, 9, 0)
124130803Smarcel#define	DT_VERS_1_9_1	DT_VERSION_NUMBER(1, 9, 1)
125130803Smarcel#define	DT_VERS_1_10	DT_VERSION_NUMBER(1, 10, 0)
126130803Smarcel#define	DT_VERS_1_11	DT_VERSION_NUMBER(1, 11, 0)
12798944Sobrien#define	DT_VERS_LATEST	DT_VERS_1_11
12898944Sobrien#define	DT_VERS_STRING	"Sun D 1.11"
12998944Sobrien
13098944Sobrienconst dt_version_t _dtrace_versions[] = {
13198944Sobrien	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
13298944Sobrien	DT_VERS_1_1,	/* D API 1.1.0 Solaris Express 6/05 */
13398944Sobrien	DT_VERS_1_2,	/* D API 1.2.0 Solaris 10 Update 1 */
13498944Sobrien	DT_VERS_1_2_1,	/* D API 1.2.1 Solaris Express 4/06 */
13598944Sobrien	DT_VERS_1_2_2,	/* D API 1.2.2 Solaris Express 6/06 */
13698944Sobrien	DT_VERS_1_3,	/* D API 1.3 Solaris Express 10/06 */
13798944Sobrien	DT_VERS_1_4,	/* D API 1.4 Solaris Express 2/07 */
13898944Sobrien	DT_VERS_1_4_1,	/* D API 1.4.1 Solaris Express 4/07 */
13998944Sobrien	DT_VERS_1_5,	/* D API 1.5 Solaris Express 7/07 */
14098944Sobrien	DT_VERS_1_6,	/* D API 1.6 */
14198944Sobrien	DT_VERS_1_6_1,	/* D API 1.6.1 */
14298944Sobrien	DT_VERS_1_6_2,	/* D API 1.6.2 */
14398944Sobrien	DT_VERS_1_6_3,	/* D API 1.6.3 */
14498944Sobrien	DT_VERS_1_7,	/* D API 1.7 */
14598944Sobrien	DT_VERS_1_7_1,	/* D API 1.7.1 */
14698944Sobrien	DT_VERS_1_8,	/* D API 1.8 */
14798944Sobrien	DT_VERS_1_8_1,	/* D API 1.8.1 */
14898944Sobrien	DT_VERS_1_9,	/* D API 1.9 */
14998944Sobrien	DT_VERS_1_9_1,	/* D API 1.9.1 */
15098944Sobrien	DT_VERS_1_10,	/* D API 1.10 */
15198944Sobrien	DT_VERS_1_11,	/* D API 1.11 */
15298944Sobrien	0
15398944Sobrien};
15498944Sobrien
15598944Sobrien/*
15698944Sobrien * Global variables that are formatted on FreeBSD based on the kernel file name.
15798944Sobrien */
15898944Sobrien#if !defined(sun)
15998944Sobrienstatic char	curthread_str[MAXPATHLEN];
16098944Sobrienstatic char	intmtx_str[MAXPATHLEN];
16198944Sobrienstatic char	threadmtx_str[MAXPATHLEN];
16298944Sobrienstatic char	rwlock_str[MAXPATHLEN];
16398944Sobrienstatic char	sxlock_str[MAXPATHLEN];
16498944Sobrien#endif
16598944Sobrien
16698944Sobrien/*
16798944Sobrien * Table of global identifiers.  This is used to populate the global identifier
16898944Sobrien * hash when a new dtrace client open occurs.  For more info see dt_ident.h.
16998944Sobrien * The global identifiers that represent functions use the dt_idops_func ops
17098944Sobrien * and specify the private data pointer as a prototype string which is parsed
17198944Sobrien * when the identifier is first encountered.  These prototypes look like ANSI
17298944Sobrien * C function prototypes except that the special symbol "@" can be used as a
17398944Sobrien * wildcard to represent a single parameter of any type (i.e. any dt_node_t).
17498944Sobrien * The standard "..." notation can also be used to represent varargs.  An empty
17598944Sobrien * parameter list is taken to mean void (that is, no arguments are permitted).
17698944Sobrien * A parameter enclosed in square brackets (e.g. "[int]") denotes an optional
17798944Sobrien * argument.
17898944Sobrien */
17998944Sobrienstatic const dt_ident_t _dtrace_globals[] = {
18098944Sobrien{ "alloca", DT_IDENT_FUNC, 0, DIF_SUBR_ALLOCA, DT_ATTR_STABCMN, DT_VERS_1_0,
18198944Sobrien	&dt_idops_func, "void *(size_t)" },
18298944Sobrien{ "arg0", DT_IDENT_SCALAR, 0, DIF_VAR_ARG0, DT_ATTR_STABCMN, DT_VERS_1_0,
18398944Sobrien	&dt_idops_type, "int64_t" },
18498944Sobrien{ "arg1", DT_IDENT_SCALAR, 0, DIF_VAR_ARG1, DT_ATTR_STABCMN, DT_VERS_1_0,
18598944Sobrien	&dt_idops_type, "int64_t" },
18698944Sobrien{ "arg2", DT_IDENT_SCALAR, 0, DIF_VAR_ARG2, DT_ATTR_STABCMN, DT_VERS_1_0,
18798944Sobrien	&dt_idops_type, "int64_t" },
18898944Sobrien{ "arg3", DT_IDENT_SCALAR, 0, DIF_VAR_ARG3, DT_ATTR_STABCMN, DT_VERS_1_0,
18998944Sobrien	&dt_idops_type, "int64_t" },
19098944Sobrien{ "arg4", DT_IDENT_SCALAR, 0, DIF_VAR_ARG4, DT_ATTR_STABCMN, DT_VERS_1_0,
19198944Sobrien	&dt_idops_type, "int64_t" },
19298944Sobrien{ "arg5", DT_IDENT_SCALAR, 0, DIF_VAR_ARG5, DT_ATTR_STABCMN, DT_VERS_1_0,
19398944Sobrien	&dt_idops_type, "int64_t" },
19498944Sobrien{ "arg6", DT_IDENT_SCALAR, 0, DIF_VAR_ARG6, DT_ATTR_STABCMN, DT_VERS_1_0,
19598944Sobrien	&dt_idops_type, "int64_t" },
19698944Sobrien{ "arg7", DT_IDENT_SCALAR, 0, DIF_VAR_ARG7, DT_ATTR_STABCMN, DT_VERS_1_0,
19798944Sobrien	&dt_idops_type, "int64_t" },
19898944Sobrien{ "arg8", DT_IDENT_SCALAR, 0, DIF_VAR_ARG8, DT_ATTR_STABCMN, DT_VERS_1_0,
19998944Sobrien	&dt_idops_type, "int64_t" },
20098944Sobrien{ "arg9", DT_IDENT_SCALAR, 0, DIF_VAR_ARG9, DT_ATTR_STABCMN, DT_VERS_1_0,
20198944Sobrien	&dt_idops_type, "int64_t" },
20298944Sobrien{ "args", DT_IDENT_ARRAY, 0, DIF_VAR_ARGS, DT_ATTR_STABCMN, DT_VERS_1_0,
20398944Sobrien	&dt_idops_args, NULL },
20498944Sobrien{ "avg", DT_IDENT_AGGFUNC, 0, DTRACEAGG_AVG, DT_ATTR_STABCMN, DT_VERS_1_0,
20598944Sobrien	&dt_idops_func, "void(@)" },
20698944Sobrien{ "basename", DT_IDENT_FUNC, 0, DIF_SUBR_BASENAME, DT_ATTR_STABCMN, DT_VERS_1_0,
20798944Sobrien	&dt_idops_func, "string(const char *)" },
20898944Sobrien{ "bcopy", DT_IDENT_FUNC, 0, DIF_SUBR_BCOPY, DT_ATTR_STABCMN, DT_VERS_1_0,
20998944Sobrien	&dt_idops_func, "void(void *, void *, size_t)" },
21098944Sobrien{ "breakpoint", DT_IDENT_ACTFUNC, 0, DT_ACT_BREAKPOINT,
21198944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
21298944Sobrien	&dt_idops_func, "void()" },
21398944Sobrien{ "caller", DT_IDENT_SCALAR, 0, DIF_VAR_CALLER, DT_ATTR_STABCMN, DT_VERS_1_0,
21498944Sobrien	&dt_idops_type, "uintptr_t" },
21598944Sobrien{ "chill", DT_IDENT_ACTFUNC, 0, DT_ACT_CHILL, DT_ATTR_STABCMN, DT_VERS_1_0,
21698944Sobrien	&dt_idops_func, "void(int)" },
21798944Sobrien{ "cleanpath", DT_IDENT_FUNC, 0, DIF_SUBR_CLEANPATH, DT_ATTR_STABCMN,
21898944Sobrien	DT_VERS_1_0, &dt_idops_func, "string(const char *)" },
21998944Sobrien{ "clear", DT_IDENT_ACTFUNC, 0, DT_ACT_CLEAR, DT_ATTR_STABCMN, DT_VERS_1_0,
22098944Sobrien	&dt_idops_func, "void(...)" },
22198944Sobrien{ "commit", DT_IDENT_ACTFUNC, 0, DT_ACT_COMMIT, DT_ATTR_STABCMN, DT_VERS_1_0,
22298944Sobrien	&dt_idops_func, "void(int)" },
22398944Sobrien{ "copyin", DT_IDENT_FUNC, 0, DIF_SUBR_COPYIN, DT_ATTR_STABCMN, DT_VERS_1_0,
22498944Sobrien	&dt_idops_func, "void *(uintptr_t, size_t)" },
22598944Sobrien{ "copyinstr", DT_IDENT_FUNC, 0, DIF_SUBR_COPYINSTR,
22698944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
22798944Sobrien	&dt_idops_func, "string(uintptr_t, [size_t])" },
22898944Sobrien{ "copyinto", DT_IDENT_FUNC, 0, DIF_SUBR_COPYINTO, DT_ATTR_STABCMN,
22998944Sobrien	DT_VERS_1_0, &dt_idops_func, "void(uintptr_t, size_t, void *)" },
23098944Sobrien{ "copyout", DT_IDENT_FUNC, 0, DIF_SUBR_COPYOUT, DT_ATTR_STABCMN, DT_VERS_1_0,
23198944Sobrien	&dt_idops_func, "void(void *, uintptr_t, size_t)" },
23298944Sobrien{ "copyoutstr", DT_IDENT_FUNC, 0, DIF_SUBR_COPYOUTSTR,
23398944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
23498944Sobrien	&dt_idops_func, "void(char *, uintptr_t, size_t)" },
23598944Sobrien{ "count", DT_IDENT_AGGFUNC, 0, DTRACEAGG_COUNT, DT_ATTR_STABCMN, DT_VERS_1_0,
23698944Sobrien	&dt_idops_func, "void()" },
23798944Sobrien{ "curthread", DT_IDENT_SCALAR, 0, DIF_VAR_CURTHREAD,
23898944Sobrien	{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_PRIVATE,
23998944Sobrien	DTRACE_CLASS_COMMON }, DT_VERS_1_0,
24098944Sobrien#if defined(sun)
24198944Sobrien	&dt_idops_type, "genunix`kthread_t *" },
24298944Sobrien#else
24398944Sobrien	&dt_idops_type, curthread_str },
24498944Sobrien#endif
24598944Sobrien{ "ddi_pathname", DT_IDENT_FUNC, 0, DIF_SUBR_DDI_PATHNAME,
24698944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
24798944Sobrien	&dt_idops_func, "string(void *, int64_t)" },
24898944Sobrien{ "denormalize", DT_IDENT_ACTFUNC, 0, DT_ACT_DENORMALIZE, DT_ATTR_STABCMN,
24998944Sobrien	DT_VERS_1_0, &dt_idops_func, "void(...)" },
25098944Sobrien{ "dirname", DT_IDENT_FUNC, 0, DIF_SUBR_DIRNAME, DT_ATTR_STABCMN, DT_VERS_1_0,
25198944Sobrien	&dt_idops_func, "string(const char *)" },
25298944Sobrien{ "discard", DT_IDENT_ACTFUNC, 0, DT_ACT_DISCARD, DT_ATTR_STABCMN, DT_VERS_1_0,
25398944Sobrien	&dt_idops_func, "void(int)" },
25498944Sobrien{ "epid", DT_IDENT_SCALAR, 0, DIF_VAR_EPID, DT_ATTR_STABCMN, DT_VERS_1_0,
25598944Sobrien	&dt_idops_type, "uint_t" },
25698944Sobrien{ "errno", DT_IDENT_SCALAR, 0, DIF_VAR_ERRNO, DT_ATTR_STABCMN, DT_VERS_1_0,
25798944Sobrien	&dt_idops_type, "int" },
25898944Sobrien{ "execargs", DT_IDENT_SCALAR, 0, DIF_VAR_EXECARGS,
25998944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
26098944Sobrien{ "execname", DT_IDENT_SCALAR, 0, DIF_VAR_EXECNAME,
26198944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
26298944Sobrien{ "exit", DT_IDENT_ACTFUNC, 0, DT_ACT_EXIT, DT_ATTR_STABCMN, DT_VERS_1_0,
26398944Sobrien	&dt_idops_func, "void(int)" },
26498944Sobrien{ "freopen", DT_IDENT_ACTFUNC, 0, DT_ACT_FREOPEN, DT_ATTR_STABCMN,
26598944Sobrien	DT_VERS_1_1, &dt_idops_func, "void(@, ...)" },
26698944Sobrien{ "ftruncate", DT_IDENT_ACTFUNC, 0, DT_ACT_FTRUNCATE, DT_ATTR_STABCMN,
26798944Sobrien	DT_VERS_1_0, &dt_idops_func, "void()" },
26898944Sobrien{ "func", DT_IDENT_ACTFUNC, 0, DT_ACT_SYM, DT_ATTR_STABCMN,
26998944Sobrien	DT_VERS_1_2, &dt_idops_func, "_symaddr(uintptr_t)" },
27098944Sobrien{ "getmajor", DT_IDENT_FUNC, 0, DIF_SUBR_GETMAJOR,
27198944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
27298944Sobrien	&dt_idops_func, "genunix`major_t(genunix`dev_t)" },
27398944Sobrien{ "getminor", DT_IDENT_FUNC, 0, DIF_SUBR_GETMINOR,
27498944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
27598944Sobrien	&dt_idops_func, "genunix`minor_t(genunix`dev_t)" },
27698944Sobrien{ "htonl", DT_IDENT_FUNC, 0, DIF_SUBR_HTONL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
27798944Sobrien	&dt_idops_func, "uint32_t(uint32_t)" },
27898944Sobrien{ "htonll", DT_IDENT_FUNC, 0, DIF_SUBR_HTONLL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
27998944Sobrien	&dt_idops_func, "uint64_t(uint64_t)" },
28098944Sobrien{ "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
28198944Sobrien	&dt_idops_func, "uint16_t(uint16_t)" },
28298944Sobrien{ "getf", DT_IDENT_FUNC, 0, DIF_SUBR_GETF, DT_ATTR_STABCMN, DT_VERS_1_10,
28398944Sobrien	&dt_idops_func, "file_t *(int)" },
28498944Sobrien{ "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0,
28598944Sobrien	&dt_idops_type, "gid_t" },
28698944Sobrien{ "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0,
28798944Sobrien	&dt_idops_type, "uint_t" },
28898944Sobrien{ "index", DT_IDENT_FUNC, 0, DIF_SUBR_INDEX, DT_ATTR_STABCMN, DT_VERS_1_1,
28998944Sobrien	&dt_idops_func, "int(const char *, const char *, [int])" },
29098944Sobrien{ "inet_ntoa", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA, DT_ATTR_STABCMN,
29198944Sobrien#if defined(sun)
29298944Sobrien	DT_VERS_1_5, &dt_idops_func, "string(ipaddr_t *)" },
29398944Sobrien#else
29498944Sobrien	DT_VERS_1_5, &dt_idops_func, "string(in_addr_t *)" },
29598944Sobrien#endif
29698944Sobrien{ "inet_ntoa6", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA6, DT_ATTR_STABCMN,
29798944Sobrien#if defined(sun)
29898944Sobrien	DT_VERS_1_5, &dt_idops_func, "string(in6_addr_t *)" },
29998944Sobrien#else
30098944Sobrien	DT_VERS_1_5, &dt_idops_func, "string(struct in6_addr *)" },
30198944Sobrien#endif
30298944Sobrien{ "inet_ntop", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOP, DT_ATTR_STABCMN,
30398944Sobrien	DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
30498944Sobrien{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
30598944Sobrien	&dt_idops_type, "uint_t" },
30698944Sobrien{ "json", DT_IDENT_FUNC, 0, DIF_SUBR_JSON, DT_ATTR_STABCMN, DT_VERS_1_11,
30798944Sobrien	&dt_idops_func, "string(const char *, const char *)" },
30898944Sobrien{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
30998944Sobrien	&dt_idops_func, "stack(...)" },
31098944Sobrien{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
31198944Sobrien	&dt_idops_func, "string(int64_t, [int])" },
31298944Sobrien{ "llquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LLQUANTIZE, DT_ATTR_STABCMN,
31398944Sobrien	DT_VERS_1_7, &dt_idops_func,
31498944Sobrien	"void(@, int32_t, int32_t, int32_t, int32_t, ...)" },
31598944Sobrien{ "lquantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_LQUANTIZE,
31698944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
31798944Sobrien	&dt_idops_func, "void(@, int32_t, int32_t, ...)" },
31898944Sobrien{ "max", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MAX, DT_ATTR_STABCMN, DT_VERS_1_0,
31998944Sobrien	&dt_idops_func, "void(@)" },
32098944Sobrien{ "memref", DT_IDENT_FUNC, 0, DIF_SUBR_MEMREF, DT_ATTR_STABCMN, DT_VERS_1_1,
32198944Sobrien	&dt_idops_func, "uintptr_t *(void *, size_t)" },
32298944Sobrien#if !defined(sun)
32398944Sobrien{ "memstr", DT_IDENT_FUNC, 0, DIF_SUBR_MEMSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
32498944Sobrien	&dt_idops_func, "string(void *, char, size_t)" },
32598944Sobrien#endif
32698944Sobrien{ "min", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MIN, DT_ATTR_STABCMN, DT_VERS_1_0,
32798944Sobrien	&dt_idops_func, "void(@)" },
32898944Sobrien{ "mod", DT_IDENT_ACTFUNC, 0, DT_ACT_MOD, DT_ATTR_STABCMN,
32998944Sobrien	DT_VERS_1_2, &dt_idops_func, "_symaddr(uintptr_t)" },
33098944Sobrien{ "msgdsize", DT_IDENT_FUNC, 0, DIF_SUBR_MSGDSIZE,
33198944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
33298944Sobrien	&dt_idops_func, "size_t(mblk_t *)" },
33398944Sobrien{ "msgsize", DT_IDENT_FUNC, 0, DIF_SUBR_MSGSIZE,
33498944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
33598944Sobrien	&dt_idops_func, "size_t(mblk_t *)" },
33698944Sobrien#if defined(sun)
33798944Sobrien{ "mutex_owned", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNED,
33898944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
33998944Sobrien	&dt_idops_func, "int(genunix`kmutex_t *)" },
34098944Sobrien{ "mutex_owner", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNER,
34198944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
34298944Sobrien	&dt_idops_func, "genunix`kthread_t *(genunix`kmutex_t *)" },
34398944Sobrien{ "mutex_type_adaptive", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_ADAPTIVE,
34498944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
34598944Sobrien	&dt_idops_func, "int(genunix`kmutex_t *)" },
34698944Sobrien{ "mutex_type_spin", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_SPIN,
34798944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
34898944Sobrien	&dt_idops_func, "int(genunix`kmutex_t *)" },
34998944Sobrien#else
35098944Sobrien{ "mutex_owned", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNED,
35198944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
35298944Sobrien	&dt_idops_func, intmtx_str },
35398944Sobrien{ "mutex_owner", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_OWNER,
35498944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
35598944Sobrien	&dt_idops_func, threadmtx_str },
35698944Sobrien{ "mutex_type_adaptive", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_ADAPTIVE,
35798944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
35898944Sobrien	&dt_idops_func, intmtx_str },
35998944Sobrien{ "mutex_type_spin", DT_IDENT_FUNC, 0, DIF_SUBR_MUTEX_TYPE_SPIN,
36098944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
36198944Sobrien	&dt_idops_func, intmtx_str },
36298944Sobrien#endif
36398944Sobrien{ "ntohl", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
36498944Sobrien	&dt_idops_func, "uint32_t(uint32_t)" },
36598944Sobrien{ "ntohll", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHLL, DT_ATTR_EVOLCMN, DT_VERS_1_3,
36698944Sobrien	&dt_idops_func, "uint64_t(uint64_t)" },
36798944Sobrien{ "ntohs", DT_IDENT_FUNC, 0, DIF_SUBR_NTOHS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
36898944Sobrien	&dt_idops_func, "uint16_t(uint16_t)" },
36998944Sobrien{ "normalize", DT_IDENT_ACTFUNC, 0, DT_ACT_NORMALIZE, DT_ATTR_STABCMN,
37098944Sobrien	DT_VERS_1_0, &dt_idops_func, "void(...)" },
37198944Sobrien{ "panic", DT_IDENT_ACTFUNC, 0, DT_ACT_PANIC, DT_ATTR_STABCMN, DT_VERS_1_0,
37298944Sobrien	&dt_idops_func, "void()" },
37398944Sobrien{ "pid", DT_IDENT_SCALAR, 0, DIF_VAR_PID, DT_ATTR_STABCMN, DT_VERS_1_0,
37498944Sobrien	&dt_idops_type, "pid_t" },
37598944Sobrien{ "ppid", DT_IDENT_SCALAR, 0, DIF_VAR_PPID, DT_ATTR_STABCMN, DT_VERS_1_0,
37698944Sobrien	&dt_idops_type, "pid_t" },
37798944Sobrien{ "print", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINT, DT_ATTR_STABCMN, DT_VERS_1_9,
37898944Sobrien	&dt_idops_func, "void(@)" },
37998944Sobrien{ "printa", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTA, DT_ATTR_STABCMN, DT_VERS_1_0,
38098944Sobrien	&dt_idops_func, "void(@, ...)" },
38198944Sobrien{ "printf", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTF, DT_ATTR_STABCMN, DT_VERS_1_0,
38298944Sobrien	&dt_idops_func, "void(@, ...)" },
38398944Sobrien{ "printm", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTM, DT_ATTR_STABCMN, DT_VERS_1_0,
38498944Sobrien	&dt_idops_func, "void(size_t, uintptr_t *)" },
38598944Sobrien{ "printt", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTT, DT_ATTR_STABCMN, DT_VERS_1_0,
38698944Sobrien	&dt_idops_func, "void(size_t, uintptr_t *)" },
38798944Sobrien{ "probefunc", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEFUNC,
38898944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
38998944Sobrien{ "probemod", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEMOD,
39098944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
39198944Sobrien{ "probename", DT_IDENT_SCALAR, 0, DIF_VAR_PROBENAME,
39298944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
39398944Sobrien{ "probeprov", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEPROV,
39498944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
39598944Sobrien{ "progenyof", DT_IDENT_FUNC, 0, DIF_SUBR_PROGENYOF,
39698944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
39798944Sobrien	&dt_idops_func, "int(pid_t)" },
39898944Sobrien{ "quantize", DT_IDENT_AGGFUNC, 0, DTRACEAGG_QUANTIZE,
39998944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
40098944Sobrien	&dt_idops_func, "void(@, ...)" },
40198944Sobrien{ "raise", DT_IDENT_ACTFUNC, 0, DT_ACT_RAISE, DT_ATTR_STABCMN, DT_VERS_1_0,
40298944Sobrien	&dt_idops_func, "void(int)" },
40398944Sobrien{ "rand", DT_IDENT_FUNC, 0, DIF_SUBR_RAND, DT_ATTR_STABCMN, DT_VERS_1_0,
40498944Sobrien	&dt_idops_func, "int()" },
40598944Sobrien{ "rindex", DT_IDENT_FUNC, 0, DIF_SUBR_RINDEX, DT_ATTR_STABCMN, DT_VERS_1_1,
40698944Sobrien	&dt_idops_func, "int(const char *, const char *, [int])" },
40798944Sobrien#if defined(sun)
40898944Sobrien{ "rw_iswriter", DT_IDENT_FUNC, 0, DIF_SUBR_RW_ISWRITER,
40998944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
41098944Sobrien	&dt_idops_func, "int(genunix`krwlock_t *)" },
41198944Sobrien{ "rw_read_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_READ_HELD,
41298944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
41398944Sobrien	&dt_idops_func, "int(genunix`krwlock_t *)" },
41498944Sobrien{ "rw_write_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_WRITE_HELD,
41598944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
41698944Sobrien	&dt_idops_func, "int(genunix`krwlock_t *)" },
41798944Sobrien#else
41898944Sobrien{ "rw_iswriter", DT_IDENT_FUNC, 0, DIF_SUBR_RW_ISWRITER,
41998944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
42098944Sobrien	&dt_idops_func, rwlock_str },
42198944Sobrien{ "rw_read_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_READ_HELD,
42298944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
42398944Sobrien	&dt_idops_func, rwlock_str },
42498944Sobrien{ "rw_write_held", DT_IDENT_FUNC, 0, DIF_SUBR_RW_WRITE_HELD,
42598944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
42698944Sobrien	&dt_idops_func, rwlock_str },
42798944Sobrien#endif
42898944Sobrien{ "self", DT_IDENT_PTR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0,
42998944Sobrien	&dt_idops_type, "void" },
43098944Sobrien{ "setopt", DT_IDENT_ACTFUNC, 0, DT_ACT_SETOPT, DT_ATTR_STABCMN,
43198944Sobrien	DT_VERS_1_2, &dt_idops_func, "void(const char *, [const char *])" },
43298944Sobrien{ "speculate", DT_IDENT_ACTFUNC, 0, DT_ACT_SPECULATE,
43398944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
43498944Sobrien	&dt_idops_func, "void(int)" },
43598944Sobrien{ "speculation", DT_IDENT_FUNC, 0, DIF_SUBR_SPECULATION,
43698944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
43798944Sobrien	&dt_idops_func, "int()" },
43898944Sobrien{ "stack", DT_IDENT_ACTFUNC, 0, DT_ACT_STACK, DT_ATTR_STABCMN, DT_VERS_1_0,
43998944Sobrien	&dt_idops_func, "stack(...)" },
44098944Sobrien{ "stackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_STACKDEPTH,
44198944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
44298944Sobrien	&dt_idops_type, "uint32_t" },
44398944Sobrien{ "stddev", DT_IDENT_AGGFUNC, 0, DTRACEAGG_STDDEV, DT_ATTR_STABCMN,
44498944Sobrien	DT_VERS_1_6, &dt_idops_func, "void(@)" },
44598944Sobrien{ "stop", DT_IDENT_ACTFUNC, 0, DT_ACT_STOP, DT_ATTR_STABCMN, DT_VERS_1_0,
44698944Sobrien	&dt_idops_func, "void()" },
44798944Sobrien{ "strchr", DT_IDENT_FUNC, 0, DIF_SUBR_STRCHR, DT_ATTR_STABCMN, DT_VERS_1_1,
44898944Sobrien	&dt_idops_func, "string(const char *, char)" },
44998944Sobrien{ "strlen", DT_IDENT_FUNC, 0, DIF_SUBR_STRLEN, DT_ATTR_STABCMN, DT_VERS_1_0,
45098944Sobrien	&dt_idops_func, "size_t(const char *)" },
45198944Sobrien{ "strjoin", DT_IDENT_FUNC, 0, DIF_SUBR_STRJOIN, DT_ATTR_STABCMN, DT_VERS_1_0,
45298944Sobrien	&dt_idops_func, "string(const char *, const char *)" },
45398944Sobrien{ "strrchr", DT_IDENT_FUNC, 0, DIF_SUBR_STRRCHR, DT_ATTR_STABCMN, DT_VERS_1_1,
45498944Sobrien	&dt_idops_func, "string(const char *, char)" },
45598944Sobrien{ "strstr", DT_IDENT_FUNC, 0, DIF_SUBR_STRSTR, DT_ATTR_STABCMN, DT_VERS_1_1,
45698944Sobrien	&dt_idops_func, "string(const char *, const char *)" },
45798944Sobrien{ "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,
45898944Sobrien	&dt_idops_func, "string(const char *, const char *)" },
45998944Sobrien{ "strtoll", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOLL, DT_ATTR_STABCMN, DT_VERS_1_11,
46098944Sobrien	&dt_idops_func, "int64_t(const char *, [int])" },
46198944Sobrien{ "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1,
46298944Sobrien	&dt_idops_func, "string(const char *, int, [int])" },
46398944Sobrien{ "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,
46498944Sobrien	&dt_idops_func, "void(@)" },
46598944Sobrien#if !defined(sun)
46698944Sobrien{ "sx_isexclusive", DT_IDENT_FUNC, 0, DIF_SUBR_SX_ISEXCLUSIVE,
46798944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
46898944Sobrien	&dt_idops_func, sxlock_str },
46998944Sobrien{ "sx_shared_held", DT_IDENT_FUNC, 0, DIF_SUBR_SX_SHARED_HELD,
47098944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
47198944Sobrien	&dt_idops_func, sxlock_str },
47298944Sobrien{ "sx_exclusive_held", DT_IDENT_FUNC, 0, DIF_SUBR_SX_EXCLUSIVE_HELD,
47398944Sobrien	DT_ATTR_EVOLCMN, DT_VERS_1_0,
47498944Sobrien	&dt_idops_func, sxlock_str },
47598944Sobrien#endif
47698944Sobrien{ "sym", DT_IDENT_ACTFUNC, 0, DT_ACT_SYM, DT_ATTR_STABCMN,
47798944Sobrien	DT_VERS_1_2, &dt_idops_func, "_symaddr(uintptr_t)" },
47898944Sobrien{ "system", DT_IDENT_ACTFUNC, 0, DT_ACT_SYSTEM, DT_ATTR_STABCMN, DT_VERS_1_0,
47998944Sobrien	&dt_idops_func, "void(@, ...)" },
48098944Sobrien{ "this", DT_IDENT_PTR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0,
48198944Sobrien	&dt_idops_type, "void" },
48298944Sobrien{ "tid", DT_IDENT_SCALAR, 0, DIF_VAR_TID, DT_ATTR_STABCMN, DT_VERS_1_0,
48398944Sobrien	&dt_idops_type, "id_t" },
48498944Sobrien{ "timestamp", DT_IDENT_SCALAR, 0, DIF_VAR_TIMESTAMP,
48598944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
48698944Sobrien	&dt_idops_type, "uint64_t" },
48798944Sobrien{ "tolower", DT_IDENT_FUNC, 0, DIF_SUBR_TOLOWER, DT_ATTR_STABCMN, DT_VERS_1_8,
48898944Sobrien	&dt_idops_func, "string(const char *)" },
48998944Sobrien{ "toupper", DT_IDENT_FUNC, 0, DIF_SUBR_TOUPPER, DT_ATTR_STABCMN, DT_VERS_1_8,
49098944Sobrien	&dt_idops_func, "string(const char *)" },
49198944Sobrien{ "trace", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACE, DT_ATTR_STABCMN, DT_VERS_1_0,
49298944Sobrien	&dt_idops_func, "void(@)" },
49398944Sobrien{ "tracemem", DT_IDENT_ACTFUNC, 0, DT_ACT_TRACEMEM,
49498944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
49598944Sobrien	&dt_idops_func, "void(@, size_t, ...)" },
49698944Sobrien{ "trunc", DT_IDENT_ACTFUNC, 0, DT_ACT_TRUNC, DT_ATTR_STABCMN,
49798944Sobrien	DT_VERS_1_0, &dt_idops_func, "void(...)" },
49898944Sobrien{ "typeref", DT_IDENT_FUNC, 0, DIF_SUBR_TYPEREF, DT_ATTR_STABCMN, DT_VERS_1_1,
49998944Sobrien	&dt_idops_func, "uintptr_t *(void *, size_t, string, size_t)" },
50098944Sobrien{ "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN,
50198944Sobrien	DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
50298944Sobrien{ "ucaller", DT_IDENT_SCALAR, 0, DIF_VAR_UCALLER, DT_ATTR_STABCMN,
50398944Sobrien	DT_VERS_1_2, &dt_idops_type, "uint64_t" },
50498944Sobrien{ "ufunc", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
50598944Sobrien	DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
50698944Sobrien{ "uid", DT_IDENT_SCALAR, 0, DIF_VAR_UID, DT_ATTR_STABCMN, DT_VERS_1_0,
50798944Sobrien	&dt_idops_type, "uid_t" },
50898944Sobrien{ "umod", DT_IDENT_ACTFUNC, 0, DT_ACT_UMOD, DT_ATTR_STABCMN,
50998944Sobrien	DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
51098944Sobrien{ "uregs", DT_IDENT_ARRAY, 0, DIF_VAR_UREGS, DT_ATTR_STABCMN, DT_VERS_1_0,
51198944Sobrien	&dt_idops_regs, NULL },
51298944Sobrien{ "ustack", DT_IDENT_ACTFUNC, 0, DT_ACT_USTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
51398944Sobrien	&dt_idops_func, "stack(...)" },
51498944Sobrien{ "ustackdepth", DT_IDENT_SCALAR, 0, DIF_VAR_USTACKDEPTH,
51598944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_2,
51698944Sobrien	&dt_idops_type, "uint32_t" },
51798944Sobrien{ "usym", DT_IDENT_ACTFUNC, 0, DT_ACT_USYM, DT_ATTR_STABCMN,
51898944Sobrien	DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" },
51998944Sobrien{ "vtimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_VTIMESTAMP,
52098944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
52198944Sobrien	&dt_idops_type, "uint64_t" },
52298944Sobrien{ "walltimestamp", DT_IDENT_SCALAR, 0, DIF_VAR_WALLTIMESTAMP,
52398944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0,
52498944Sobrien	&dt_idops_type, "int64_t" },
52598944Sobrien#if defined(sun)
52698944Sobrien{ "zonename", DT_IDENT_SCALAR, 0, DIF_VAR_ZONENAME,
52798944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
52898944Sobrien#endif
52998944Sobrien
53098944Sobrien#if !defined(sun)
53198944Sobrien{ "cpu", DT_IDENT_SCALAR, 0, DIF_VAR_CPU,
53298944Sobrien	DT_ATTR_STABCMN, DT_VERS_1_6_3, &dt_idops_type, "int" },
53398944Sobrien#endif
53498944Sobrien
53598944Sobrien{ NULL, 0, 0, 0, { 0, 0, 0 }, 0, NULL, NULL }
53698944Sobrien};
53798944Sobrien
53898944Sobrien/*
53998944Sobrien * Tables of ILP32 intrinsic integer and floating-point type templates to use
54098944Sobrien * to populate the dynamic "C" CTF type container.
54198944Sobrien */
54298944Sobrienstatic const dt_intrinsic_t _dtrace_intrinsics_32[] = {
54398944Sobrien{ "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },
54498944Sobrien{ "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
54598944Sobrien{ "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },
54698944Sobrien{ "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
54798944Sobrien{ "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
54898944Sobrien{ "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
54998944Sobrien{ "long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
55098944Sobrien{ "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
55198944Sobrien{ "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
55298944Sobrien{ "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
55398944Sobrien{ "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
55498944Sobrien{ "signed long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
55598944Sobrien{ "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
55698944Sobrien{ "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
55798944Sobrien{ "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },
55898944Sobrien{ "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },
55998944Sobrien{ "unsigned long", { 0, 0, 32 }, CTF_K_INTEGER },
56098944Sobrien{ "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },
56198944Sobrien{ "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },
56298944Sobrien{ "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },
56398944Sobrien{ "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },
56498944Sobrien{ "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },
56598944Sobrien{ "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },
56698944Sobrien{ "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },
56798944Sobrien{ "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },
56898944Sobrien{ "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },
56998944Sobrien{ "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },
57098944Sobrien{ "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },
57198944Sobrien{ NULL, { 0, 0, 0 }, 0 }
57298944Sobrien};
57398944Sobrien
57498944Sobrien/*
57598944Sobrien * Tables of LP64 intrinsic integer and floating-point type templates to use
57698944Sobrien * to populate the dynamic "C" CTF type container.
57798944Sobrien */
57898944Sobrienstatic const dt_intrinsic_t _dtrace_intrinsics_64[] = {
57998944Sobrien{ "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },
58098944Sobrien{ "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
58198944Sobrien{ "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },
58298944Sobrien{ "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
58398944Sobrien{ "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
58498944Sobrien{ "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
58598944Sobrien{ "long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
58698944Sobrien{ "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
58798944Sobrien{ "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
58898944Sobrien{ "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
58998944Sobrien{ "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
59098944Sobrien{ "signed long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
59198944Sobrien{ "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
59298944Sobrien{ "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
59398944Sobrien{ "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },
59498944Sobrien{ "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },
59598944Sobrien{ "unsigned long", { 0, 0, 64 }, CTF_K_INTEGER },
59698944Sobrien{ "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },
59798944Sobrien{ "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },
59898944Sobrien{ "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },
59998944Sobrien{ "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },
60098944Sobrien{ "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },
60198944Sobrien{ "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },
60298944Sobrien{ "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },
60398944Sobrien{ "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },
60498944Sobrien{ "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },
60598944Sobrien{ "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },
60698944Sobrien{ "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },
60798944Sobrien{ NULL, { 0, 0, 0 }, 0 }
60898944Sobrien};
60998944Sobrien
61098944Sobrien/*
61198944Sobrien * Tables of ILP32 typedefs to use to populate the dynamic "D" CTF container.
61298944Sobrien * These aliases ensure that D definitions can use typical <sys/types.h> names.
61398944Sobrien */
61498944Sobrienstatic const dt_typedef_t _dtrace_typedefs_32[] = {
61598944Sobrien{ "char", "int8_t" },
61698944Sobrien{ "short", "int16_t" },
61798944Sobrien{ "int", "int32_t" },
61898944Sobrien{ "long long", "int64_t" },
61998944Sobrien{ "int", "intptr_t" },
62098944Sobrien{ "int", "ssize_t" },
62198944Sobrien{ "unsigned char", "uint8_t" },
62298944Sobrien{ "unsigned short", "uint16_t" },
62398944Sobrien{ "unsigned", "uint32_t" },
62498944Sobrien{ "unsigned long long", "uint64_t" },
62598944Sobrien{ "unsigned char", "uchar_t" },
62698944Sobrien{ "unsigned short", "ushort_t" },
62798944Sobrien{ "unsigned", "uint_t" },
62898944Sobrien{ "unsigned long", "ulong_t" },
62998944Sobrien{ "unsigned long long", "u_longlong_t" },
63098944Sobrien{ "int", "ptrdiff_t" },
63198944Sobrien{ "unsigned", "uintptr_t" },
63298944Sobrien{ "unsigned", "size_t" },
63398944Sobrien{ "long", "id_t" },
63498944Sobrien{ "long", "pid_t" },
63598944Sobrien{ NULL, NULL }
63698944Sobrien};
63798944Sobrien
63898944Sobrien/*
63998944Sobrien * Tables of LP64 typedefs to use to populate the dynamic "D" CTF container.
64098944Sobrien * These aliases ensure that D definitions can use typical <sys/types.h> names.
64198944Sobrien */
64298944Sobrienstatic const dt_typedef_t _dtrace_typedefs_64[] = {
64398944Sobrien{ "char", "int8_t" },
64498944Sobrien{ "short", "int16_t" },
64598944Sobrien{ "int", "int32_t" },
64698944Sobrien{ "long", "int64_t" },
64798944Sobrien{ "long", "intptr_t" },
64898944Sobrien{ "long", "ssize_t" },
64998944Sobrien{ "unsigned char", "uint8_t" },
65098944Sobrien{ "unsigned short", "uint16_t" },
65198944Sobrien{ "unsigned", "uint32_t" },
65298944Sobrien{ "unsigned long", "uint64_t" },
65398944Sobrien{ "unsigned char", "uchar_t" },
65498944Sobrien{ "unsigned short", "ushort_t" },
65598944Sobrien{ "unsigned", "uint_t" },
65698944Sobrien{ "unsigned long", "ulong_t" },
65798944Sobrien{ "unsigned long long", "u_longlong_t" },
65898944Sobrien{ "long", "ptrdiff_t" },
65998944Sobrien{ "unsigned long", "uintptr_t" },
66098944Sobrien{ "unsigned long", "size_t" },
66198944Sobrien{ "int", "id_t" },
66298944Sobrien{ "int", "pid_t" },
66398944Sobrien{ NULL, NULL }
66498944Sobrien};
66598944Sobrien
66698944Sobrien/*
66798944Sobrien * Tables of ILP32 integer type templates used to populate the dtp->dt_ints[]
66898944Sobrien * cache when a new dtrace client open occurs.  Values are set by dtrace_open().
66998944Sobrien */
67098944Sobrienstatic const dt_intdesc_t _dtrace_ints_32[] = {
67198944Sobrien{ "int", NULL, CTF_ERR, 0x7fffffffULL },
67298944Sobrien{ "unsigned int", NULL, CTF_ERR, 0xffffffffULL },
67398944Sobrien{ "long", NULL, CTF_ERR, 0x7fffffffULL },
67498944Sobrien{ "unsigned long", NULL, CTF_ERR, 0xffffffffULL },
67598944Sobrien{ "long long", NULL, CTF_ERR, 0x7fffffffffffffffULL },
67698944Sobrien{ "unsigned long long", NULL, CTF_ERR, 0xffffffffffffffffULL }
67798944Sobrien};
67898944Sobrien
67998944Sobrien/*
68098944Sobrien * Tables of LP64 integer type templates used to populate the dtp->dt_ints[]
68198944Sobrien * cache when a new dtrace client open occurs.  Values are set by dtrace_open().
68298944Sobrien */
68398944Sobrienstatic const dt_intdesc_t _dtrace_ints_64[] = {
68498944Sobrien{ "int", NULL, CTF_ERR, 0x7fffffffULL },
68598944Sobrien{ "unsigned int", NULL, CTF_ERR, 0xffffffffULL },
68698944Sobrien{ "long", NULL, CTF_ERR, 0x7fffffffffffffffULL },
68798944Sobrien{ "unsigned long", NULL, CTF_ERR, 0xffffffffffffffffULL },
68898944Sobrien{ "long long", NULL, CTF_ERR, 0x7fffffffffffffffULL },
68998944Sobrien{ "unsigned long long", NULL, CTF_ERR, 0xffffffffffffffffULL }
69098944Sobrien};
69198944Sobrien
69298944Sobrien/*
69398944Sobrien * Table of macro variable templates used to populate the macro identifier hash
69498944Sobrien * when a new dtrace client open occurs.  Values are set by dtrace_update().
69598944Sobrien */
69698944Sobrienstatic const dt_ident_t _dtrace_macros[] = {
69798944Sobrien{ "egid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
69898944Sobrien{ "euid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
69998944Sobrien{ "gid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70098944Sobrien{ "pid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70198944Sobrien{ "pgid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70298944Sobrien{ "ppid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70398944Sobrien{ "projid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70498944Sobrien{ "sid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70598944Sobrien{ "taskid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70698944Sobrien{ "target", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70798944Sobrien{ "uid", DT_IDENT_SCALAR, 0, 0, DT_ATTR_STABCMN, DT_VERS_1_0 },
70898944Sobrien{ NULL, 0, 0, 0, { 0, 0, 0 }, 0 }
70998944Sobrien};
71098944Sobrien
71198944Sobrien/*
71298944Sobrien * Hard-wired definition string to be compiled and cached every time a new
71398944Sobrien * DTrace library handle is initialized.  This string should only be used to
71498944Sobrien * contain definitions that should be present regardless of DTRACE_O_NOLIBS.
71598944Sobrien */
71698944Sobrienstatic const char _dtrace_hardwire[] = "\
71798944Sobrieninline long NULL = 0; \n\
71898944Sobrien#pragma D binding \"1.0\" NULL\n\
71998944Sobrien";
72098944Sobrien
72198944Sobrien/*
72298944Sobrien * Default DTrace configuration to use when opening libdtrace DTRACE_O_NODEV.
72398944Sobrien * If DTRACE_O_NODEV is not set, we load the configuration from the kernel.
72498944Sobrien * The use of CTF_MODEL_NATIVE is more subtle than it might appear: we are
72598944Sobrien * relying on the fact that when running dtrace(1M), isaexec will invoke the
72698944Sobrien * binary with the same bitness as the kernel, which is what we want by default
72798944Sobrien * when generating our DIF.  The user can override the choice using oflags.
72898944Sobrien */
72998944Sobrienstatic const dtrace_conf_t _dtrace_conf = {
73098944Sobrien	DIF_VERSION,		/* dtc_difversion */
73198944Sobrien	DIF_DIR_NREGS,		/* dtc_difintregs */
73298944Sobrien	DIF_DTR_NREGS,		/* dtc_diftupregs */
73398944Sobrien	CTF_MODEL_NATIVE	/* dtc_ctfmodel */
73498944Sobrien};
73598944Sobrien
73698944Sobrienconst dtrace_attribute_t _dtrace_maxattr = {
73798944Sobrien	DTRACE_STABILITY_MAX,
73898944Sobrien	DTRACE_STABILITY_MAX,
73998944Sobrien	DTRACE_CLASS_MAX
74098944Sobrien};
74198944Sobrien
74298944Sobrienconst dtrace_attribute_t _dtrace_defattr = {
74398944Sobrien	DTRACE_STABILITY_STABLE,
74498944Sobrien	DTRACE_STABILITY_STABLE,
74598944Sobrien	DTRACE_CLASS_COMMON
74698944Sobrien};
74798944Sobrien
74898944Sobrienconst dtrace_attribute_t _dtrace_symattr = {
74998944Sobrien	DTRACE_STABILITY_PRIVATE,
75098944Sobrien	DTRACE_STABILITY_PRIVATE,
75198944Sobrien	DTRACE_CLASS_UNKNOWN
75298944Sobrien};
75398944Sobrien
75498944Sobrienconst dtrace_attribute_t _dtrace_typattr = {
75598944Sobrien	DTRACE_STABILITY_PRIVATE,
75698944Sobrien	DTRACE_STABILITY_PRIVATE,
75798944Sobrien	DTRACE_CLASS_UNKNOWN
75898944Sobrien};
75998944Sobrien
76098944Sobrienconst dtrace_attribute_t _dtrace_prvattr = {
76198944Sobrien	DTRACE_STABILITY_PRIVATE,
76298944Sobrien	DTRACE_STABILITY_PRIVATE,
76398944Sobrien	DTRACE_CLASS_UNKNOWN
76498944Sobrien};
76598944Sobrien
76698944Sobrienconst dtrace_pattr_t _dtrace_prvdesc = {
76798944Sobrien{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },
76898944Sobrien{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },
76998944Sobrien{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },
77098944Sobrien{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },
77198944Sobrien{ DTRACE_STABILITY_UNSTABLE, DTRACE_STABILITY_UNSTABLE, DTRACE_CLASS_COMMON },
77298944Sobrien};
77398944Sobrien
77498944Sobrien#if defined(sun)
77598944Sobrienconst char *_dtrace_defcpp = "/usr/ccs/lib/cpp"; /* default cpp(1) to invoke */
77698944Sobrienconst char *_dtrace_defld = "/usr/ccs/bin/ld";   /* default ld(1) to invoke */
77798944Sobrien#else
77898944Sobrienconst char *_dtrace_defcpp = "cpp"; /* default cpp(1) to invoke */
77998944Sobrienconst char *_dtrace_defld = "ld";   /* default ld(1) to invoke */
78098944Sobrien#endif
78198944Sobrien
78298944Sobrienconst char *_dtrace_libdir = "/usr/lib/dtrace"; /* default library directory */
78398944Sobrien#if defined(sun)
78498944Sobrienconst char *_dtrace_provdir = "/dev/dtrace/provider"; /* provider directory */
78598944Sobrien#else
78698944Sobrienconst char *_dtrace_provdir = "/dev/dtrace"; /* provider directory */
78798944Sobrien#endif
78898944Sobrien
78998944Sobrienint _dtrace_strbuckets = 211;	/* default number of hash buckets (prime) */
79098944Sobrienint _dtrace_intbuckets = 256;	/* default number of integer buckets (Pof2) */
79198944Sobrienuint_t _dtrace_strsize = 256;	/* default size of string intrinsic type */
79298944Sobrienuint_t _dtrace_stkindent = 14;	/* default whitespace indent for stack/ustack */
79398944Sobrienuint_t _dtrace_pidbuckets = 64; /* default number of pid hash buckets */
79498944Sobrienuint_t _dtrace_pidlrulim = 8;	/* default number of pid handles to cache */
79598944Sobriensize_t _dtrace_bufsize = 512;	/* default dt_buf_create() size */
79698944Sobrienint _dtrace_argmax = 32;	/* default maximum number of probe arguments */
79798944Sobrien
79898944Sobrienint _dtrace_debug = 0;		/* debug messages enabled (off) */
79998944Sobrienconst char *const _dtrace_version = DT_VERS_STRING; /* API version string */
80098944Sobrienint _dtrace_rdvers = RD_VERSION; /* rtld_db feature version */
80198944Sobrien
80298944Sobrientypedef struct dt_fdlist {
80398944Sobrien	int *df_fds;		/* array of provider driver file descriptors */
80498944Sobrien	uint_t df_ents;		/* number of valid elements in df_fds[] */
80598944Sobrien	uint_t df_size;		/* size of df_fds[] */
80698944Sobrien} dt_fdlist_t;
80798944Sobrien
80898944Sobrien#if defined(sun)
80998944Sobrien#pragma init(_dtrace_init)
81098944Sobrien#else
81198944Sobrienvoid _dtrace_init(void) __attribute__ ((constructor));
81298944Sobrien#endif
81398944Sobrienvoid
81498944Sobrien_dtrace_init(void)
81598944Sobrien{
81698944Sobrien	_dtrace_debug = getenv("DTRACE_DEBUG") != NULL;
81798944Sobrien
81898944Sobrien	for (; _dtrace_rdvers > 0; _dtrace_rdvers--) {
81998944Sobrien		if (rd_init(_dtrace_rdvers) == RD_OK)
82098944Sobrien			break;
82198944Sobrien	}
82298944Sobrien#if defined(__i386__)
82398944Sobrien	/* make long doubles 64 bits -sson */
82498944Sobrien	(void) fpsetprec(FP_PE);
82598944Sobrien#endif
82698944Sobrien}
82798944Sobrien
82898944Sobrienstatic dtrace_hdl_t *
82998944Sobrienset_open_errno(dtrace_hdl_t *dtp, int *errp, int err)
83098944Sobrien{
83198944Sobrien	if (dtp != NULL)
83298944Sobrien		dtrace_close(dtp);
83398944Sobrien	if (errp != NULL)
83498944Sobrien		*errp = err;
83598944Sobrien	return (NULL);
83698944Sobrien}
83798944Sobrien
83898944Sobrienstatic void
83998944Sobriendt_provmod_open(dt_provmod_t **provmod, dt_fdlist_t *dfp)
84098944Sobrien{
84198944Sobrien	dt_provmod_t *prov;
84298944Sobrien	char path[PATH_MAX];
84398944Sobrien	int fd;
84498944Sobrien#if defined(sun)
84598944Sobrien	struct dirent *dp, *ep;
84698944Sobrien	DIR *dirp;
84798944Sobrien
84898944Sobrien	if ((dirp = opendir(_dtrace_provdir)) == NULL)
84998944Sobrien		return; /* failed to open directory; just skip it */
85098944Sobrien
85198944Sobrien	ep = alloca(sizeof (struct dirent) + PATH_MAX + 1);
85298944Sobrien	bzero(ep, sizeof (struct dirent) + PATH_MAX + 1);
85398944Sobrien
85498944Sobrien	while (readdir_r(dirp, ep, &dp) == 0 && dp != NULL) {
85598944Sobrien		if (dp->d_name[0] == '.')
85698944Sobrien			continue; /* skip "." and ".." */
85798944Sobrien
85898944Sobrien		if (dfp->df_ents == dfp->df_size) {
85998944Sobrien			uint_t size = dfp->df_size ? dfp->df_size * 2 : 16;
86098944Sobrien			int *fds = realloc(dfp->df_fds, size * sizeof (int));
86198944Sobrien
86298944Sobrien			if (fds == NULL)
86398944Sobrien				break; /* skip the rest of this directory */
86498944Sobrien
86598944Sobrien			dfp->df_fds = fds;
86698944Sobrien			dfp->df_size = size;
86798944Sobrien		}
86898944Sobrien
86998944Sobrien		(void) snprintf(path, sizeof (path), "%s/%s",
87098944Sobrien		    _dtrace_provdir, dp->d_name);
87198944Sobrien
87298944Sobrien		if ((fd = open(path, O_RDONLY)) == -1)
87398944Sobrien			continue; /* failed to open driver; just skip it */
87498944Sobrien
87598944Sobrien		if (((prov = malloc(sizeof (dt_provmod_t))) == NULL) ||
87698944Sobrien		    (prov->dp_name = malloc(strlen(dp->d_name) + 1)) == NULL) {
87798944Sobrien			free(prov);
87898944Sobrien			(void) close(fd);
87998944Sobrien			break;
88098944Sobrien		}
88198944Sobrien
88298944Sobrien		(void) strcpy(prov->dp_name, dp->d_name);
88398944Sobrien		prov->dp_next = *provmod;
88498944Sobrien		*provmod = prov;
88598944Sobrien
88698944Sobrien		dt_dprintf("opened provider %s\n", dp->d_name);
88798944Sobrien		dfp->df_fds[dfp->df_ents++] = fd;
88898944Sobrien	}
88998944Sobrien
89098944Sobrien	(void) closedir(dirp);
89198944Sobrien#else
89298944Sobrien	char	*p;
89398944Sobrien	char	*p1;
89498944Sobrien	char	*p_providers = NULL;
89598944Sobrien	int	error;
89698944Sobrien	size_t	len = 0;
89798944Sobrien
89898944Sobrien	/*
89998944Sobrien	 * Loop to allocate/reallocate memory for the string of provider
90098944Sobrien	 * names and retry:
90198944Sobrien	 */
90298944Sobrien	while(1) {
90398944Sobrien		/*
90498944Sobrien		 * The first time around, get the string length. The next time,
90598944Sobrien		 * hopefully we've allocated enough memory.
90698944Sobrien		 */
90798944Sobrien		error = sysctlbyname("debug.dtrace.providers",p_providers,&len,NULL,0);
90898944Sobrien		if (len == 0)
90998944Sobrien			/* No providers? That's strange. Where's dtrace? */
91098944Sobrien			break;
91198944Sobrien		else if (error == 0 && p_providers == NULL) {
91298944Sobrien			/*
91398944Sobrien			 * Allocate the initial memory which should be enough
91498944Sobrien			 * unless another provider loads before we have
91598944Sobrien			 * time to go back and get the string.
91698944Sobrien			 */
91798944Sobrien			if ((p_providers = malloc(len)) == NULL)
91898944Sobrien				/* How do we report errors here? */
91998944Sobrien				return;
92098944Sobrien		} else if (error == -1 && errno == ENOMEM) {
92198944Sobrien			/*
92298944Sobrien			 * The current buffer isn't large enough, so
92398944Sobrien			 * reallocate it. We normally won't need to do this
92498944Sobrien			 * because providers aren't being loaded all the time.
92598944Sobrien			 */
92698944Sobrien			if ((p = realloc(p_providers,len)) == NULL)
92798944Sobrien				/* How do we report errors here? */
92898944Sobrien				return;
92998944Sobrien			p_providers = p;
93098944Sobrien		} else
93198944Sobrien			break;
93298944Sobrien	}
93398944Sobrien
93498944Sobrien	/* Check if we got a string of provider names: */
93598944Sobrien	if (error == 0 && len > 0 && p_providers != NULL) {
93698944Sobrien		p = p_providers;
93798944Sobrien
93898944Sobrien		/*
93998944Sobrien		 * Parse the string containing the space separated
94098944Sobrien		 * provider names.
94198944Sobrien		 */
94298944Sobrien		while ((p1 = strsep(&p," ")) != NULL) {
94398944Sobrien			if (dfp->df_ents == dfp->df_size) {
94498944Sobrien				uint_t size = dfp->df_size ? dfp->df_size * 2 : 16;
94598944Sobrien				int *fds = realloc(dfp->df_fds, size * sizeof (int));
94698944Sobrien
94798944Sobrien				if (fds == NULL)
94898944Sobrien					break;
94998944Sobrien
95098944Sobrien				dfp->df_fds = fds;
95198944Sobrien				dfp->df_size = size;
95298944Sobrien			}
95398944Sobrien
95498944Sobrien			(void) snprintf(path, sizeof (path), "/dev/dtrace/%s", p1);
95598944Sobrien
95698944Sobrien			if ((fd = open(path, O_RDONLY)) == -1)
95798944Sobrien				continue; /* failed to open driver; just skip it */
95898944Sobrien
95998944Sobrien			if (((prov = malloc(sizeof (dt_provmod_t))) == NULL) ||
96098944Sobrien			    (prov->dp_name = malloc(strlen(p1) + 1)) == NULL) {
96198944Sobrien				free(prov);
96298944Sobrien				(void) close(fd);
96398944Sobrien				break;
96498944Sobrien			}
96598944Sobrien
96698944Sobrien			(void) strcpy(prov->dp_name, p1);
96798944Sobrien			prov->dp_next = *provmod;
96898944Sobrien			*provmod = prov;
96998944Sobrien
97098944Sobrien			dt_dprintf("opened provider %s\n", p1);
97198944Sobrien			dfp->df_fds[dfp->df_ents++] = fd;
97298944Sobrien		}
97398944Sobrien	}
97498944Sobrien	if (p_providers != NULL)
97598944Sobrien		free(p_providers);
97698944Sobrien#endif
97798944Sobrien}
97898944Sobrien
97998944Sobrienstatic void
98098944Sobriendt_provmod_destroy(dt_provmod_t **provmod)
98198944Sobrien{
98298944Sobrien	dt_provmod_t *next, *current;
98398944Sobrien
98498944Sobrien	for (current = *provmod; current != NULL; current = next) {
98598944Sobrien		next = current->dp_next;
98698944Sobrien		free(current->dp_name);
98798944Sobrien		free(current);
98898944Sobrien	}
98998944Sobrien
99098944Sobrien	*provmod = NULL;
99198944Sobrien}
99298944Sobrien
99398944Sobrien#if defined(sun)
99498944Sobrienstatic const char *
99598944Sobriendt_get_sysinfo(int cmd, char *buf, size_t len)
99698944Sobrien{
99798944Sobrien	ssize_t rv = sysinfo(cmd, buf, len);
99898944Sobrien	char *p = buf;
99998944Sobrien
100098944Sobrien	if (rv < 0 || rv > len)
100198944Sobrien		(void) snprintf(buf, len, "%s", "Unknown");
100298944Sobrien
100398944Sobrien	while ((p = strchr(p, '.')) != NULL)
100498944Sobrien		*p++ = '_';
100598944Sobrien
100698944Sobrien	return (buf);
100798944Sobrien}
100898944Sobrien#endif
100998944Sobrien
101098944Sobrienstatic dtrace_hdl_t *
101198944Sobriendt_vopen(int version, int flags, int *errp,
101298944Sobrien    const dtrace_vector_t *vector, void *arg)
101398944Sobrien{
101498944Sobrien	dtrace_hdl_t *dtp = NULL;
101598944Sobrien	int dtfd = -1, ftfd = -1, fterr = 0;
101698944Sobrien	dtrace_prog_t *pgp;
101798944Sobrien	dt_module_t *dmp;
101898944Sobrien	dt_provmod_t *provmod = NULL;
101998944Sobrien	int i, err;
102098944Sobrien	struct rlimit rl;
102198944Sobrien
102298944Sobrien	const dt_intrinsic_t *dinp;
102398944Sobrien	const dt_typedef_t *dtyp;
102498944Sobrien	const dt_ident_t *idp;
102598944Sobrien
102698944Sobrien	dtrace_typeinfo_t dtt;
102798944Sobrien	ctf_funcinfo_t ctc;
102898944Sobrien	ctf_arinfo_t ctr;
102998944Sobrien
103098944Sobrien	dt_fdlist_t df = { NULL, 0, 0 };
103198944Sobrien
103298944Sobrien	char isadef[32], utsdef[32];
103398944Sobrien	char s1[64], s2[64];
103498944Sobrien
103598944Sobrien	if (version <= 0)
103698944Sobrien		return (set_open_errno(dtp, errp, EINVAL));
103798944Sobrien
103898944Sobrien	if (version > DTRACE_VERSION)
103998944Sobrien		return (set_open_errno(dtp, errp, EDT_VERSION));
104098944Sobrien
104198944Sobrien	if (version < DTRACE_VERSION) {
104298944Sobrien		/*
104398944Sobrien		 * Currently, increasing the library version number is used to
104498944Sobrien		 * denote a binary incompatible change.  That is, a consumer
104598944Sobrien		 * of the library cannot run on a version of the library with
104698944Sobrien		 * a higher DTRACE_VERSION number than the consumer compiled
104798944Sobrien		 * against.  Once the library API has been committed to,
104898944Sobrien		 * backwards binary compatibility will be required; at that
104998944Sobrien		 * time, this check should change to return EDT_OVERSION only
105098944Sobrien		 * if the specified version number is less than the version
105198944Sobrien		 * number at the time of interface commitment.
105298944Sobrien		 */
105398944Sobrien		return (set_open_errno(dtp, errp, EDT_OVERSION));
105498944Sobrien	}
105598944Sobrien
105698944Sobrien	if (flags & ~DTRACE_O_MASK)
105798944Sobrien		return (set_open_errno(dtp, errp, EINVAL));
105898944Sobrien
105998944Sobrien	if ((flags & DTRACE_O_LP64) && (flags & DTRACE_O_ILP32))
106098944Sobrien		return (set_open_errno(dtp, errp, EINVAL));
106198944Sobrien
106298944Sobrien	if (vector == NULL && arg != NULL)
106398944Sobrien		return (set_open_errno(dtp, errp, EINVAL));
106498944Sobrien
106598944Sobrien	if (elf_version(EV_CURRENT) == EV_NONE)
106698944Sobrien		return (set_open_errno(dtp, errp, EDT_ELFVERSION));
106798944Sobrien
1068	if (vector != NULL || (flags & DTRACE_O_NODEV))
1069		goto alloc; /* do not attempt to open dtrace device */
1070
1071	/*
1072	 * Before we get going, crank our limit on file descriptors up to the
1073	 * hard limit.  This is to allow for the fact that libproc keeps file
1074	 * descriptors to objects open for the lifetime of the proc handle;
1075	 * without raising our hard limit, we would have an acceptably small
1076	 * bound on the number of processes that we could concurrently
1077	 * instrument with the pid provider.
1078	 */
1079	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
1080		rl.rlim_cur = rl.rlim_max;
1081		(void) setrlimit(RLIMIT_NOFILE, &rl);
1082	}
1083
1084	/*
1085	 * Get the device path of each of the providers.  We hold them open
1086	 * in the df.df_fds list until we open the DTrace driver itself,
1087	 * allowing us to see all of the probes provided on this system.  Once
1088	 * we have the DTrace driver open, we can safely close all the providers
1089	 * now that they have registered with the framework.
1090	 */
1091	dt_provmod_open(&provmod, &df);
1092
1093	dtfd = open("/dev/dtrace/dtrace", O_RDWR);
1094	err = errno; /* save errno from opening dtfd */
1095#if defined(__FreeBSD__)
1096	/*
1097	 * Automatically load the 'dtraceall' module if we couldn't open the
1098	 * char device.
1099	 */
1100	if (err == ENOENT && modfind("dtraceall") < 0) {
1101		kldload("dtraceall"); /* ignore the error */
1102		dtfd = open("/dev/dtrace/dtrace", O_RDWR);
1103		err = errno;
1104	}
1105#endif
1106#if defined(sun)
1107	ftfd = open("/dev/dtrace/provider/fasttrap", O_RDWR);
1108#else
1109	ftfd = open("/dev/dtrace/fasttrap", O_RDWR);
1110#endif
1111	fterr = ftfd == -1 ? errno : 0; /* save errno from open ftfd */
1112
1113	while (df.df_ents-- != 0)
1114		(void) close(df.df_fds[df.df_ents]);
1115
1116	free(df.df_fds);
1117
1118	/*
1119	 * If we failed to open the dtrace device, fail dtrace_open().
1120	 * We convert some kernel errnos to custom libdtrace errnos to
1121	 * improve the resulting message from the usual strerror().
1122	 */
1123	if (dtfd == -1) {
1124		dt_provmod_destroy(&provmod);
1125		switch (err) {
1126		case ENOENT:
1127			err = EDT_NOENT;
1128			break;
1129		case EBUSY:
1130			err = EDT_BUSY;
1131			break;
1132		case EACCES:
1133			err = EDT_ACCESS;
1134			break;
1135		}
1136		return (set_open_errno(dtp, errp, err));
1137	}
1138
1139	(void) fcntl(dtfd, F_SETFD, FD_CLOEXEC);
1140	(void) fcntl(ftfd, F_SETFD, FD_CLOEXEC);
1141
1142alloc:
1143	if ((dtp = malloc(sizeof (dtrace_hdl_t))) == NULL)
1144		return (set_open_errno(dtp, errp, EDT_NOMEM));
1145
1146	bzero(dtp, sizeof (dtrace_hdl_t));
1147	dtp->dt_oflags = flags;
1148#if defined(sun)
1149	dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
1150#else
1151	dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
1152#endif
1153	dtp->dt_linkmode = DT_LINK_KERNEL;
1154	dtp->dt_linktype = DT_LTYP_ELF;
1155	dtp->dt_xlatemode = DT_XL_STATIC;
1156	dtp->dt_stdcmode = DT_STDC_XA;
1157	dtp->dt_version = version;
1158	dtp->dt_fd = dtfd;
1159	dtp->dt_ftfd = ftfd;
1160	dtp->dt_fterr = fterr;
1161	dtp->dt_cdefs_fd = -1;
1162	dtp->dt_ddefs_fd = -1;
1163#if defined(sun)
1164	dtp->dt_stdout_fd = -1;
1165#else
1166	dtp->dt_freopen_fp = NULL;
1167#endif
1168	dtp->dt_modbuckets = _dtrace_strbuckets;
1169	dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
1170	dtp->dt_provbuckets = _dtrace_strbuckets;
1171	dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
1172	dt_proc_hash_create(dtp);
1173	dtp->dt_vmax = DT_VERS_LATEST;
1174	dtp->dt_cpp_path = strdup(_dtrace_defcpp);
1175	dtp->dt_cpp_argv = malloc(sizeof (char *));
1176	dtp->dt_cpp_argc = 1;
1177	dtp->dt_cpp_args = 1;
1178	dtp->dt_ld_path = strdup(_dtrace_defld);
1179	dtp->dt_provmod = provmod;
1180	dtp->dt_vector = vector;
1181	dtp->dt_varg = arg;
1182	dt_dof_init(dtp);
1183	(void) uname(&dtp->dt_uts);
1184
1185	if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
1186	    dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
1187	    dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
1188		return (set_open_errno(dtp, errp, EDT_NOMEM));
1189
1190	for (i = 0; i < DTRACEOPT_MAX; i++)
1191		dtp->dt_options[i] = DTRACEOPT_UNSET;
1192
1193	dtp->dt_cpp_argv[0] = (char *)strbasename(dtp->dt_cpp_path);
1194
1195#if defined(sun)
1196	(void) snprintf(isadef, sizeof (isadef), "-D__SUNW_D_%u",
1197	    (uint_t)(sizeof (void *) * NBBY));
1198
1199	(void) snprintf(utsdef, sizeof (utsdef), "-D__%s_%s",
1200	    dt_get_sysinfo(SI_SYSNAME, s1, sizeof (s1)),
1201	    dt_get_sysinfo(SI_RELEASE, s2, sizeof (s2)));
1202
1203	if (dt_cpp_add_arg(dtp, "-D__sun") == NULL ||
1204	    dt_cpp_add_arg(dtp, "-D__unix") == NULL ||
1205	    dt_cpp_add_arg(dtp, "-D__SVR4") == NULL ||
1206	    dt_cpp_add_arg(dtp, "-D__SUNW_D=1") == NULL ||
1207	    dt_cpp_add_arg(dtp, isadef) == NULL ||
1208	    dt_cpp_add_arg(dtp, utsdef) == NULL)
1209		return (set_open_errno(dtp, errp, EDT_NOMEM));
1210#endif
1211
1212	if (flags & DTRACE_O_NODEV)
1213		bcopy(&_dtrace_conf, &dtp->dt_conf, sizeof (_dtrace_conf));
1214	else if (dt_ioctl(dtp, DTRACEIOC_CONF, &dtp->dt_conf) != 0)
1215		return (set_open_errno(dtp, errp, errno));
1216
1217	if (flags & DTRACE_O_LP64)
1218		dtp->dt_conf.dtc_ctfmodel = CTF_MODEL_LP64;
1219	else if (flags & DTRACE_O_ILP32)
1220		dtp->dt_conf.dtc_ctfmodel = CTF_MODEL_ILP32;
1221
1222#ifdef __sparc
1223	/*
1224	 * On SPARC systems, __sparc is always defined for <sys/isa_defs.h>
1225	 * and __sparcv9 is defined if we are doing a 64-bit compile.
1226	 */
1227	if (dt_cpp_add_arg(dtp, "-D__sparc") == NULL)
1228		return (set_open_errno(dtp, errp, EDT_NOMEM));
1229
1230	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64 &&
1231	    dt_cpp_add_arg(dtp, "-D__sparcv9") == NULL)
1232		return (set_open_errno(dtp, errp, EDT_NOMEM));
1233#endif
1234
1235#if defined(sun)
1236#ifdef __x86
1237	/*
1238	 * On x86 systems, __i386 is defined for <sys/isa_defs.h> for 32-bit
1239	 * compiles and __amd64 is defined for 64-bit compiles.  Unlike SPARC,
1240	 * they are defined exclusive of one another (see PSARC 2004/619).
1241	 */
1242	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) {
1243		if (dt_cpp_add_arg(dtp, "-D__amd64") == NULL)
1244			return (set_open_errno(dtp, errp, EDT_NOMEM));
1245	} else {
1246		if (dt_cpp_add_arg(dtp, "-D__i386") == NULL)
1247			return (set_open_errno(dtp, errp, EDT_NOMEM));
1248	}
1249#endif
1250#else
1251#if defined(__amd64__) || defined(__i386__)
1252	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) {
1253		if (dt_cpp_add_arg(dtp, "-m64") == NULL)
1254			return (set_open_errno(dtp, errp, EDT_NOMEM));
1255	} else {
1256		if (dt_cpp_add_arg(dtp, "-m32") == NULL)
1257			return (set_open_errno(dtp, errp, EDT_NOMEM));
1258	}
1259#endif
1260#endif
1261
1262	if (dtp->dt_conf.dtc_difversion < DIF_VERSION)
1263		return (set_open_errno(dtp, errp, EDT_DIFVERS));
1264
1265	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_ILP32)
1266		bcopy(_dtrace_ints_32, dtp->dt_ints, sizeof (_dtrace_ints_32));
1267	else
1268		bcopy(_dtrace_ints_64, dtp->dt_ints, sizeof (_dtrace_ints_64));
1269
1270	/*
1271	 * On FreeBSD the kernel module name can't be hard-coded. The
1272	 * 'kern.bootfile' sysctl value tells us exactly which file is being
1273	 * used as the kernel.
1274	 */
1275#if !defined(sun)
1276	{
1277	char bootfile[MAXPATHLEN];
1278	char *p;
1279	int i;
1280	size_t len = sizeof(bootfile);
1281
1282	/* This call shouldn't fail, but use a default just in case. */
1283	if (sysctlbyname("kern.bootfile", bootfile, &len, NULL, 0) != 0)
1284		strlcpy(bootfile, "kernel", sizeof(bootfile));
1285
1286	if ((p = strrchr(bootfile, '/')) != NULL)
1287		p++;
1288	else
1289		p = bootfile;
1290
1291	/*
1292	 * Format the global variables based on the kernel module name.
1293	 */
1294	snprintf(curthread_str, sizeof(curthread_str), "%s`struct thread *",p);
1295	snprintf(intmtx_str, sizeof(intmtx_str), "int(%s`struct mtx *)",p);
1296	snprintf(threadmtx_str, sizeof(threadmtx_str), "struct thread *(%s`struct mtx *)",p);
1297	snprintf(rwlock_str, sizeof(rwlock_str), "int(%s`struct rwlock *)",p);
1298	snprintf(sxlock_str, sizeof(sxlock_str), "int(%s`struct sxlock *)",p);
1299	}
1300#endif
1301
1302	dtp->dt_macros = dt_idhash_create("macro", NULL, 0, UINT_MAX);
1303	dtp->dt_aggs = dt_idhash_create("aggregation", NULL,
1304	    DTRACE_AGGVARIDNONE + 1, UINT_MAX);
1305
1306	dtp->dt_globals = dt_idhash_create("global", _dtrace_globals,
1307	    DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);
1308
1309	dtp->dt_tls = dt_idhash_create("thread local", NULL,
1310	    DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);
1311
1312	if (dtp->dt_macros == NULL || dtp->dt_aggs == NULL ||
1313	    dtp->dt_globals == NULL || dtp->dt_tls == NULL)
1314		return (set_open_errno(dtp, errp, EDT_NOMEM));
1315
1316	/*
1317	 * Populate the dt_macros identifier hash table by hand: we can't use
1318	 * the dt_idhash_populate() mechanism because we're not yet compiling
1319	 * and dtrace_update() needs to immediately reference these idents.
1320	 */
1321	for (idp = _dtrace_macros; idp->di_name != NULL; idp++) {
1322		if (dt_idhash_insert(dtp->dt_macros, idp->di_name,
1323		    idp->di_kind, idp->di_flags, idp->di_id, idp->di_attr,
1324		    idp->di_vers, idp->di_ops ? idp->di_ops : &dt_idops_thaw,
1325		    idp->di_iarg, 0) == NULL)
1326			return (set_open_errno(dtp, errp, EDT_NOMEM));
1327	}
1328
1329	/*
1330	 * Update the module list using /system/object and load the values for
1331	 * the macro variable definitions according to the current process.
1332	 */
1333	dtrace_update(dtp);
1334
1335	/*
1336	 * Select the intrinsics and typedefs we want based on the data model.
1337	 * The intrinsics are under "C".  The typedefs are added under "D".
1338	 */
1339	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_ILP32) {
1340		dinp = _dtrace_intrinsics_32;
1341		dtyp = _dtrace_typedefs_32;
1342	} else {
1343		dinp = _dtrace_intrinsics_64;
1344		dtyp = _dtrace_typedefs_64;
1345	}
1346
1347	/*
1348	 * Create a dynamic CTF container under the "C" scope for intrinsic
1349	 * types and types defined in ANSI-C header files that are included.
1350	 */
1351	if ((dmp = dtp->dt_cdefs = dt_module_create(dtp, "C")) == NULL)
1352		return (set_open_errno(dtp, errp, EDT_NOMEM));
1353
1354	if ((dmp->dm_ctfp = ctf_create(&dtp->dt_ctferr)) == NULL)
1355		return (set_open_errno(dtp, errp, EDT_CTF));
1356
1357	dt_dprintf("created CTF container for %s (%p)\n",
1358	    dmp->dm_name, (void *)dmp->dm_ctfp);
1359
1360	(void) ctf_setmodel(dmp->dm_ctfp, dtp->dt_conf.dtc_ctfmodel);
1361	ctf_setspecific(dmp->dm_ctfp, dmp);
1362
1363	dmp->dm_flags = DT_DM_LOADED; /* fake up loaded bit */
1364	dmp->dm_modid = -1; /* no module ID */
1365
1366	/*
1367	 * Fill the dynamic "C" CTF container with all of the intrinsic
1368	 * integer and floating-point types appropriate for this data model.
1369	 */
1370	for (; dinp->din_name != NULL; dinp++) {
1371		if (dinp->din_kind == CTF_K_INTEGER) {
1372			err = ctf_add_integer(dmp->dm_ctfp, CTF_ADD_ROOT,
1373			    dinp->din_name, &dinp->din_data);
1374		} else {
1375			err = ctf_add_float(dmp->dm_ctfp, CTF_ADD_ROOT,
1376			    dinp->din_name, &dinp->din_data);
1377		}
1378
1379		if (err == CTF_ERR) {
1380			dt_dprintf("failed to add %s to C container: %s\n",
1381			    dinp->din_name, ctf_errmsg(
1382			    ctf_errno(dmp->dm_ctfp)));
1383			return (set_open_errno(dtp, errp, EDT_CTF));
1384		}
1385	}
1386
1387	if (ctf_update(dmp->dm_ctfp) != 0) {
1388		dt_dprintf("failed to update C container: %s\n",
1389		    ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
1390		return (set_open_errno(dtp, errp, EDT_CTF));
1391	}
1392
1393	/*
1394	 * Add intrinsic pointer types that are needed to initialize printf
1395	 * format dictionary types (see table in dt_printf.c).
1396	 */
1397	(void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT,
1398	    ctf_lookup_by_name(dmp->dm_ctfp, "void"));
1399
1400	(void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT,
1401	    ctf_lookup_by_name(dmp->dm_ctfp, "char"));
1402
1403	(void) ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT,
1404	    ctf_lookup_by_name(dmp->dm_ctfp, "int"));
1405
1406	if (ctf_update(dmp->dm_ctfp) != 0) {
1407		dt_dprintf("failed to update C container: %s\n",
1408		    ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
1409		return (set_open_errno(dtp, errp, EDT_CTF));
1410	}
1411
1412	/*
1413	 * Create a dynamic CTF container under the "D" scope for types that
1414	 * are defined by the D program itself or on-the-fly by the D compiler.
1415	 * The "D" CTF container is a child of the "C" CTF container.
1416	 */
1417	if ((dmp = dtp->dt_ddefs = dt_module_create(dtp, "D")) == NULL)
1418		return (set_open_errno(dtp, errp, EDT_NOMEM));
1419
1420	if ((dmp->dm_ctfp = ctf_create(&dtp->dt_ctferr)) == NULL)
1421		return (set_open_errno(dtp, errp, EDT_CTF));
1422
1423	dt_dprintf("created CTF container for %s (%p)\n",
1424	    dmp->dm_name, (void *)dmp->dm_ctfp);
1425
1426	(void) ctf_setmodel(dmp->dm_ctfp, dtp->dt_conf.dtc_ctfmodel);
1427	ctf_setspecific(dmp->dm_ctfp, dmp);
1428
1429	dmp->dm_flags = DT_DM_LOADED; /* fake up loaded bit */
1430	dmp->dm_modid = -1; /* no module ID */
1431
1432	if (ctf_import(dmp->dm_ctfp, dtp->dt_cdefs->dm_ctfp) == CTF_ERR) {
1433		dt_dprintf("failed to import D parent container: %s\n",
1434		    ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
1435		return (set_open_errno(dtp, errp, EDT_CTF));
1436	}
1437
1438	/*
1439	 * Fill the dynamic "D" CTF container with all of the built-in typedefs
1440	 * that we need to use for our D variable and function definitions.
1441	 * This ensures that basic inttypes.h names are always available to us.
1442	 */
1443	for (; dtyp->dty_src != NULL; dtyp++) {
1444		if (ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,
1445		    dtyp->dty_dst, ctf_lookup_by_name(dmp->dm_ctfp,
1446		    dtyp->dty_src)) == CTF_ERR) {
1447			dt_dprintf("failed to add typedef %s %s to D "
1448			    "container: %s", dtyp->dty_src, dtyp->dty_dst,
1449			    ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
1450			return (set_open_errno(dtp, errp, EDT_CTF));
1451		}
1452	}
1453
1454	/*
1455	 * Insert a CTF ID corresponding to a pointer to a type of kind
1456	 * CTF_K_FUNCTION we can use in the compiler for function pointers.
1457	 * CTF treats all function pointers as "int (*)()" so we only need one.
1458	 */
1459	ctc.ctc_return = ctf_lookup_by_name(dmp->dm_ctfp, "int");
1460	ctc.ctc_argc = 0;
1461	ctc.ctc_flags = 0;
1462
1463	dtp->dt_type_func = ctf_add_function(dmp->dm_ctfp,
1464	    CTF_ADD_ROOT, &ctc, NULL);
1465
1466	dtp->dt_type_fptr = ctf_add_pointer(dmp->dm_ctfp,
1467	    CTF_ADD_ROOT, dtp->dt_type_func);
1468
1469	/*
1470	 * We also insert CTF definitions for the special D intrinsic types
1471	 * string and <DYN> into the D container.  The string type is added
1472	 * as a typedef of char[n].  The <DYN> type is an alias for void.
1473	 * We compare types to these special CTF ids throughout the compiler.
1474	 */
1475	ctr.ctr_contents = ctf_lookup_by_name(dmp->dm_ctfp, "char");
1476	ctr.ctr_index = ctf_lookup_by_name(dmp->dm_ctfp, "long");
1477	ctr.ctr_nelems = _dtrace_strsize;
1478
1479	dtp->dt_type_str = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,
1480	    "string", ctf_add_array(dmp->dm_ctfp, CTF_ADD_ROOT, &ctr));
1481
1482	dtp->dt_type_dyn = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,
1483	    "<DYN>", ctf_lookup_by_name(dmp->dm_ctfp, "void"));
1484
1485	dtp->dt_type_stack = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,
1486	    "stack", ctf_lookup_by_name(dmp->dm_ctfp, "void"));
1487
1488	dtp->dt_type_symaddr = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,
1489	    "_symaddr", ctf_lookup_by_name(dmp->dm_ctfp, "void"));
1490
1491	dtp->dt_type_usymaddr = ctf_add_typedef(dmp->dm_ctfp, CTF_ADD_ROOT,
1492	    "_usymaddr", ctf_lookup_by_name(dmp->dm_ctfp, "void"));
1493
1494	if (dtp->dt_type_func == CTF_ERR || dtp->dt_type_fptr == CTF_ERR ||
1495	    dtp->dt_type_str == CTF_ERR || dtp->dt_type_dyn == CTF_ERR ||
1496	    dtp->dt_type_stack == CTF_ERR || dtp->dt_type_symaddr == CTF_ERR ||
1497	    dtp->dt_type_usymaddr == CTF_ERR) {
1498		dt_dprintf("failed to add intrinsic to D container: %s\n",
1499		    ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
1500		return (set_open_errno(dtp, errp, EDT_CTF));
1501	}
1502
1503	if (ctf_update(dmp->dm_ctfp) != 0) {
1504		dt_dprintf("failed update D container: %s\n",
1505		    ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
1506		return (set_open_errno(dtp, errp, EDT_CTF));
1507	}
1508
1509	/*
1510	 * Initialize the integer description table used to convert integer
1511	 * constants to the appropriate types.  Refer to the comments above
1512	 * dt_node_int() for a complete description of how this table is used.
1513	 */
1514	for (i = 0; i < sizeof (dtp->dt_ints) / sizeof (dtp->dt_ints[0]); i++) {
1515		if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_EVERY,
1516		    dtp->dt_ints[i].did_name, &dtt) != 0) {
1517			dt_dprintf("failed to lookup integer type %s: %s\n",
1518			    dtp->dt_ints[i].did_name,
1519			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
1520			return (set_open_errno(dtp, errp, dtp->dt_errno));
1521		}
1522		dtp->dt_ints[i].did_ctfp = dtt.dtt_ctfp;
1523		dtp->dt_ints[i].did_type = dtt.dtt_type;
1524	}
1525
1526	/*
1527	 * Now that we've created the "C" and "D" containers, move them to the
1528	 * start of the module list so that these types and symbols are found
1529	 * first (for stability) when iterating through the module list.
1530	 */
1531	dt_list_delete(&dtp->dt_modlist, dtp->dt_ddefs);
1532	dt_list_prepend(&dtp->dt_modlist, dtp->dt_ddefs);
1533
1534	dt_list_delete(&dtp->dt_modlist, dtp->dt_cdefs);
1535	dt_list_prepend(&dtp->dt_modlist, dtp->dt_cdefs);
1536
1537	if (dt_pfdict_create(dtp) == -1)
1538		return (set_open_errno(dtp, errp, dtp->dt_errno));
1539
1540	/*
1541	 * If we are opening libdtrace DTRACE_O_NODEV enable C_ZDEFS by default
1542	 * because without /dev/dtrace open, we will not be able to load the
1543	 * names and attributes of any providers or probes from the kernel.
1544	 */
1545	if (flags & DTRACE_O_NODEV)
1546		dtp->dt_cflags |= DTRACE_C_ZDEFS;
1547
1548	/*
1549	 * Load hard-wired inlines into the definition cache by calling the
1550	 * compiler on the raw definition string defined above.
1551	 */
1552	if ((pgp = dtrace_program_strcompile(dtp, _dtrace_hardwire,
1553	    DTRACE_PROBESPEC_NONE, DTRACE_C_EMPTY, 0, NULL)) == NULL) {
1554		dt_dprintf("failed to load hard-wired definitions: %s\n",
1555		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
1556		return (set_open_errno(dtp, errp, EDT_HARDWIRE));
1557	}
1558
1559	dt_program_destroy(dtp, pgp);
1560
1561	/*
1562	 * Set up the default DTrace library path.  Once set, the next call to
1563	 * dt_compile() will compile all the libraries.  We intentionally defer
1564	 * library processing to improve overhead for clients that don't ever
1565	 * compile, and to provide better error reporting (because the full
1566	 * reporting of compiler errors requires dtrace_open() to succeed).
1567	 */
1568	if (dtrace_setopt(dtp, "libdir", _dtrace_libdir) != 0)
1569		return (set_open_errno(dtp, errp, dtp->dt_errno));
1570
1571	return (dtp);
1572}
1573
1574dtrace_hdl_t *
1575dtrace_open(int version, int flags, int *errp)
1576{
1577	return (dt_vopen(version, flags, errp, NULL, NULL));
1578}
1579
1580dtrace_hdl_t *
1581dtrace_vopen(int version, int flags, int *errp,
1582    const dtrace_vector_t *vector, void *arg)
1583{
1584	return (dt_vopen(version, flags, errp, vector, arg));
1585}
1586
1587void
1588dtrace_close(dtrace_hdl_t *dtp)
1589{
1590	dt_ident_t *idp, *ndp;
1591	dt_module_t *dmp;
1592	dt_provider_t *pvp;
1593	dtrace_prog_t *pgp;
1594	dt_xlator_t *dxp;
1595	dt_dirpath_t *dirp;
1596	int i;
1597
1598	if (dtp->dt_procs != NULL)
1599		dt_proc_hash_destroy(dtp);
1600
1601	while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
1602		dt_program_destroy(dtp, pgp);
1603
1604	while ((dxp = dt_list_next(&dtp->dt_xlators)) != NULL)
1605		dt_xlator_destroy(dtp, dxp);
1606
1607	dt_free(dtp, dtp->dt_xlatormap);
1608
1609	for (idp = dtp->dt_externs; idp != NULL; idp = ndp) {
1610		ndp = idp->di_next;
1611		dt_ident_destroy(idp);
1612	}
1613
1614	if (dtp->dt_macros != NULL)
1615		dt_idhash_destroy(dtp->dt_macros);
1616	if (dtp->dt_aggs != NULL)
1617		dt_idhash_destroy(dtp->dt_aggs);
1618	if (dtp->dt_globals != NULL)
1619		dt_idhash_destroy(dtp->dt_globals);
1620	if (dtp->dt_tls != NULL)
1621		dt_idhash_destroy(dtp->dt_tls);
1622
1623	while ((dmp = dt_list_next(&dtp->dt_modlist)) != NULL)
1624		dt_module_destroy(dtp, dmp);
1625
1626	while ((pvp = dt_list_next(&dtp->dt_provlist)) != NULL)
1627		dt_provider_destroy(dtp, pvp);
1628
1629	if (dtp->dt_fd != -1)
1630		(void) close(dtp->dt_fd);
1631	if (dtp->dt_ftfd != -1)
1632		(void) close(dtp->dt_ftfd);
1633	if (dtp->dt_cdefs_fd != -1)
1634		(void) close(dtp->dt_cdefs_fd);
1635	if (dtp->dt_ddefs_fd != -1)
1636		(void) close(dtp->dt_ddefs_fd);
1637#if defined(sun)
1638	if (dtp->dt_stdout_fd != -1)
1639		(void) close(dtp->dt_stdout_fd);
1640#else
1641	if (dtp->dt_freopen_fp != NULL)
1642		(void) fclose(dtp->dt_freopen_fp);
1643#endif
1644
1645	dt_epid_destroy(dtp);
1646	dt_aggid_destroy(dtp);
1647	dt_format_destroy(dtp);
1648	dt_strdata_destroy(dtp);
1649	dt_buffered_destroy(dtp);
1650	dt_aggregate_destroy(dtp);
1651	dt_pfdict_destroy(dtp);
1652	dt_provmod_destroy(&dtp->dt_provmod);
1653	dt_dof_fini(dtp);
1654
1655	for (i = 1; i < dtp->dt_cpp_argc; i++)
1656		free(dtp->dt_cpp_argv[i]);
1657
1658	while ((dirp = dt_list_next(&dtp->dt_lib_path)) != NULL) {
1659		dt_list_delete(&dtp->dt_lib_path, dirp);
1660		free(dirp->dir_path);
1661		free(dirp);
1662	}
1663
1664	free(dtp->dt_cpp_argv);
1665	free(dtp->dt_cpp_path);
1666	free(dtp->dt_ld_path);
1667
1668	free(dtp->dt_mods);
1669	free(dtp->dt_provs);
1670	free(dtp);
1671}
1672
1673int
1674dtrace_provider_modules(dtrace_hdl_t *dtp, const char **mods, int nmods)
1675{
1676	dt_provmod_t *prov;
1677	int i = 0;
1678
1679	for (prov = dtp->dt_provmod; prov != NULL; prov = prov->dp_next, i++) {
1680		if (i < nmods)
1681			mods[i] = prov->dp_name;
1682	}
1683
1684	return (i);
1685}
1686
1687int
1688dtrace_ctlfd(dtrace_hdl_t *dtp)
1689{
1690	return (dtp->dt_fd);
1691}
1692