summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdtrace/common
diff options
context:
space:
mode:
authorjhaslam <none@none>2007-11-14 03:55:39 -0800
committerjhaslam <none@none>2007-11-14 03:55:39 -0800
commitc9d6cd77e4180c3831afde367c7eb129e72f0b2c (patch)
treef441212843bc379a8981accc1210101ee997e73a /usr/src/lib/libdtrace/common
parentfa66589cbc72e2aa1c5d6dd376ae1be20ff3dfe3 (diff)
downloadillumos-gate-c9d6cd77e4180c3831afde367c7eb129e72f0b2c.tar.gz
6600430 library dependencies for DTrace
6602183 names of all non USDT based providers should be able to end with a digit
Diffstat (limited to 'usr/src/lib/libdtrace/common')
-rw-r--r--usr/src/lib/libdtrace/common/dt_cc.c320
-rw-r--r--usr/src/lib/libdtrace/common/dt_impl.h17
-rw-r--r--usr/src/lib/libdtrace/common/dt_lex.l30
-rw-r--r--usr/src/lib/libdtrace/common/dt_parser.h10
-rw-r--r--usr/src/lib/libdtrace/common/dt_pragma.c36
-rw-r--r--usr/src/lib/libdtrace/common/dtrace.h10
6 files changed, 366 insertions, 57 deletions
diff --git a/usr/src/lib/libdtrace/common/dt_cc.c b/usr/src/lib/libdtrace/common/dt_cc.c
index 9d95f480c1..64b2922049 100644
--- a/usr/src/lib/libdtrace/common/dt_cc.c
+++ b/usr/src/lib/libdtrace/common/dt_cc.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -116,6 +115,10 @@ static const dtrace_diftype_t dt_int_rtype = {
DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, sizeof (uint64_t)
};
+static void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *,
+ uint_t, int, char *const[], FILE *, const char *);
+
+
/*ARGSUSED*/
static int
dt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
@@ -1428,18 +1431,26 @@ dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
{
const dtrace_pattr_t *pap;
dt_probe_t *prp;
+ dt_provider_t *pvp;
dt_ident_t *idp;
char attrstr[8];
int err;
/*
- * If the provider name ends with what could be interpreted as a
- * number, we assume that it's a pid and that we may need to
- * dynamically create those probes for that process. On an error,
- * dt_pid_create_probes() will set the error message and tag --
- * we just have to longjmp() out of here.
+ * Both kernel and pid based providers are allowed to have names
+ * ending with what could be interpreted as a number. We assume it's
+ * a pid and that we may need to dynamically create probes for
+ * that process if:
+ *
+ * (1) The provider doesn't exist, or,
+ * (2) The provider exists and has DTRACE_PRIV_PROC privilege.
+ *
+ * On an error, dt_pid_create_probes() will set the error message
+ * and tag -- we just have to longjmp() out of here.
*/
if (isdigit(pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1]) &&
+ ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) == NULL ||
+ pvp->pv_desc.dtvd_priv.dtpp_flags & DTRACE_PRIV_PROC) &&
dt_pid_create_probes(pdp, dtp, yypcb) != 0) {
longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
}
@@ -1700,21 +1711,220 @@ err:
return (NULL);
}
+static void
+dt_lib_depend_error(dtrace_hdl_t *dtp, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
+ va_end(ap);
+}
+
+int
+dt_lib_depend_add(dtrace_hdl_t *dtp, dt_list_t *dlp, const char *arg)
+{
+ dt_lib_depend_t *dld;
+ const char *end;
+
+ assert(arg != NULL);
+
+ if ((end = strrchr(arg, '/')) == NULL)
+ return (dt_set_errno(dtp, EINVAL));
+
+ if ((dld = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL)
+ return (-1);
+
+ if ((dld->dtld_libpath = dt_alloc(dtp, MAXPATHLEN)) == NULL) {
+ dt_free(dtp, dld);
+ return (-1);
+ }
+
+ (void) strlcpy(dld->dtld_libpath, arg, end - arg + 2);
+ if ((dld->dtld_library = strdup(arg)) == NULL) {
+ dt_free(dtp, dld->dtld_libpath);
+ dt_free(dtp, dld);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ dt_list_append(dlp, dld);
+ return (0);
+}
+
+dt_lib_depend_t *
+dt_lib_depend_lookup(dt_list_t *dld, const char *arg)
+{
+ dt_lib_depend_t *dldn;
+
+ for (dldn = dt_list_next(dld); dldn != NULL;
+ dldn = dt_list_next(dldn)) {
+ if (strcmp(dldn->dtld_library, arg) == 0)
+ return (dldn);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Go through all the library files, and, if any library dependencies exist for
+ * that file, add it to that node's list of dependents. The result of this
+ * will be a graph which can then be topologically sorted to produce a
+ * compilation order.
+ */
+static int
+dt_lib_build_graph(dtrace_hdl_t *dtp)
+{
+ dt_lib_depend_t *dld, *dpld;
+
+ for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
+ dld = dt_list_next(dld)) {
+ char *library = dld->dtld_library;
+
+ for (dpld = dt_list_next(&dld->dtld_dependencies); dpld != NULL;
+ dpld = dt_list_next(dpld)) {
+ dt_lib_depend_t *dlda;
+
+ if ((dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep,
+ dpld->dtld_library)) == NULL) {
+ dt_lib_depend_error(dtp,
+ "Invalid library dependency in %s: %s\n",
+ dld->dtld_library, dpld->dtld_library);
+
+ return (dt_set_errno(dtp, EDT_COMPILER));
+ }
+
+ if ((dt_lib_depend_add(dtp, &dlda->dtld_dependents,
+ library)) != 0) {
+ return (-1); /* preserve dt_errno */
+ }
+ }
+ }
+ return (0);
+}
+
+static int
+dt_topo_sort(dtrace_hdl_t *dtp, dt_lib_depend_t *dld, int *count)
+{
+ dt_lib_depend_t *dpld, *dlda, *new;
+
+ dld->dtld_start = ++(*count);
+
+ for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL;
+ dpld = dt_list_next(dpld)) {
+ dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep,
+ dpld->dtld_library);
+ assert(dlda != NULL);
+
+ if (dlda->dtld_start == 0 &&
+ dt_topo_sort(dtp, dlda, count) == -1)
+ return (-1);
+ }
+
+ if ((new = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL)
+ return (-1);
+
+ if ((new->dtld_library = strdup(dld->dtld_library)) == NULL) {
+ dt_free(dtp, new);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ new->dtld_start = dld->dtld_start;
+ new->dtld_finish = dld->dtld_finish = ++(*count);
+ dt_list_prepend(&dtp->dt_lib_dep_sorted, new);
+
+ dt_dprintf("library %s sorted (%d/%d)\n", new->dtld_library,
+ new->dtld_start, new->dtld_finish);
+
+ return (0);
+}
+
+static int
+dt_lib_depend_sort(dtrace_hdl_t *dtp)
+{
+ dt_lib_depend_t *dld, *dpld, *dlda;
+ int count = 0;
+
+ if (dt_lib_build_graph(dtp) == -1)
+ return (-1); /* preserve dt_errno */
+
+ /*
+ * Perform a topological sort of the graph that hangs off
+ * dtp->dt_lib_dep. The result of this process will be a
+ * dependency ordered list located at dtp->dt_lib_dep_sorted.
+ */
+ for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
+ dld = dt_list_next(dld)) {
+ if (dld->dtld_start == 0 &&
+ dt_topo_sort(dtp, dld, &count) == -1)
+ return (-1); /* preserve dt_errno */;
+ }
+
+ /*
+ * Check the graph for cycles. If an ancestor's finishing time is
+ * less than any of its dependent's finishing times then a back edge
+ * exists in the graph and this is a cycle.
+ */
+ for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
+ dld = dt_list_next(dld)) {
+ for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL;
+ dpld = dt_list_next(dpld)) {
+ dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted,
+ dpld->dtld_library);
+ assert(dlda != NULL);
+
+ if (dlda->dtld_finish > dld->dtld_finish) {
+ dt_lib_depend_error(dtp,
+ "Cyclic dependency detected: %s => %s\n",
+ dld->dtld_library, dpld->dtld_library);
+
+ return (dt_set_errno(dtp, EDT_COMPILER));
+ }
+ }
+ }
+
+ return (0);
+}
+
+static void
+dt_lib_depend_free(dtrace_hdl_t *dtp)
+{
+ dt_lib_depend_t *dld, *dlda;
+
+ while ((dld = dt_list_next(&dtp->dt_lib_dep)) != NULL) {
+ while ((dlda = dt_list_next(&dld->dtld_dependencies)) != NULL) {
+ dt_list_delete(&dld->dtld_dependencies, dlda);
+ dt_free(dtp, dlda->dtld_library);
+ dt_free(dtp, dlda->dtld_libpath);
+ dt_free(dtp, dlda);
+ }
+ while ((dlda = dt_list_next(&dld->dtld_dependents)) != NULL) {
+ dt_list_delete(&dld->dtld_dependents, dlda);
+ dt_free(dtp, dlda->dtld_library);
+ dt_free(dtp, dlda->dtld_libpath);
+ dt_free(dtp, dlda);
+ }
+ dt_list_delete(&dtp->dt_lib_dep, dld);
+ dt_free(dtp, dld->dtld_library);
+ dt_free(dtp, dld->dtld_libpath);
+ dt_free(dtp, dld);
+ }
+
+ while ((dld = dt_list_next(&dtp->dt_lib_dep_sorted)) != NULL) {
+ dt_list_delete(&dtp->dt_lib_dep_sorted, dld);
+ dt_free(dtp, dld->dtld_library);
+ dt_free(dtp, dld);
+ }
+}
+
+
/*
- * Open all of the .d library files found in the specified directory and try to
- * compile each one in order to cache its inlines and translators, etc. We
- * silently ignore any missing directories and other files found therein.
- * We only fail (and thereby fail dt_load_libs()) if we fail to compile a
- * library and the error is something other than #pragma D depends_on.
+ * Open all of the .d library files found in the specified directory and
+ * compile each one in topological order to cache its inlines and translators,
+ * etc. We silently ignore any missing directories and other files found
+ * therein. We only fail (and thereby fail dt_load_libs()) if we fail to
+ * compile a library and the error is something other than #pragma D depends_on.
* Dependency errors are silently ignored to permit a library directory to
* contain libraries which may not be accessible depending on our privileges.
- *
- * Note that at present, no ordering is defined between library files found in
- * the same directory: if cross-library dependencies are eventually required,
- * we will need to extend the #pragma D depends_on directive with an additional
- * class for libraries, and this function will need to create a graph of the
- * various library pathnames and then perform a topological ordering using the
- * dependency information before we attempt to compile any of them.
*/
static int
dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
@@ -1726,12 +1936,15 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
char fname[PATH_MAX];
dtrace_prog_t *pgp;
FILE *fp;
+ void *rv;
+ dt_lib_depend_t *dld;
if ((dirp = opendir(path)) == NULL) {
dt_dprintf("skipping lib dir %s: %s\n", path, strerror(errno));
return (0);
}
+ /* First, parse each file for library dependencies. */
while ((dp = readdir(dirp)) != NULL) {
if ((p = strrchr(dp->d_name, '.')) == NULL || strcmp(p, ".d"))
continue; /* skip any filename not ending in .d */
@@ -1746,25 +1959,67 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
}
dtp->dt_filetag = fname;
+ if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0)
+ goto err;
+
+ rv = dt_compile(dtp, DT_CTX_DPROG,
+ DTRACE_PROBESPEC_NAME, NULL,
+ DTRACE_C_EMPTY | DTRACE_C_CTL, 0, NULL, fp, NULL);
+
+ if (rv != NULL && dtp->dt_errno &&
+ (dtp->dt_errno != EDT_COMPILER ||
+ dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
+ goto err;
+
+ if (dtp->dt_errno)
+ dt_dprintf("error parsing library %s: %s\n",
+ fname, dtrace_errmsg(dtp, dtrace_errno(dtp)));
+
+ (void) fclose(fp);
+ dtp->dt_filetag = NULL;
+ }
+
+ (void) closedir(dirp);
+ /*
+ * Finish building the graph containing the library dependencies
+ * and perform a topological sort to generate an ordered list
+ * for compilation.
+ */
+ if (dt_lib_depend_sort(dtp) == -1)
+ goto err;
+
+ for (dld = dt_list_next(&dtp->dt_lib_dep_sorted); dld != NULL;
+ dld = dt_list_next(dld)) {
+
+ if ((fp = fopen(dld->dtld_library, "r")) == NULL) {
+ dt_dprintf("skipping library %s: %s\n",
+ dld->dtld_library, strerror(errno));
+ continue;
+ }
+
+ dtp->dt_filetag = dld->dtld_library;
pgp = dtrace_program_fcompile(dtp, fp, DTRACE_C_EMPTY, 0, NULL);
(void) fclose(fp);
dtp->dt_filetag = NULL;
if (pgp == NULL && (dtp->dt_errno != EDT_COMPILER ||
- dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) {
- (void) closedir(dirp);
- return (-1); /* preserve dt_errno */
- }
+ dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
+ goto err;
if (pgp == NULL) {
- dt_dprintf("skipping library: %s\n",
+ dt_dprintf("skipping library %s: %s\n",
+ dld->dtld_library,
dtrace_errmsg(dtp, dtrace_errno(dtp)));
} else
dt_program_destroy(dtp, pgp);
}
- (void) closedir(dirp);
+ dt_lib_depend_free(dtp);
return (0);
+
+err:
+ dt_lib_depend_free(dtp);
+ return (-1); /* preserve dt_errno */
}
/*
@@ -1837,10 +2092,12 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
pcb.pcb_context = context;
pcb.pcb_token = context;
- if (context == DT_CTX_DPROG)
- yybegin(YYS_CLAUSE);
- else
+ if (context != DT_CTX_DPROG)
yybegin(YYS_EXPR);
+ else if (cflags & DTRACE_C_CTL)
+ yybegin(YYS_CONTROL);
+ else
+ yybegin(YYS_CLAUSE);
if ((err = setjmp(yypcb->pcb_jmpbuf)) != 0)
goto out;
@@ -1866,6 +2123,9 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
yybegin(YYS_DONE);
+ if (cflags & DTRACE_C_CTL)
+ goto out;
+
if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 1))
dt_node_printr(yypcb->pcb_root, stderr, 0);
diff --git a/usr/src/lib/libdtrace/common/dt_impl.h b/usr/src/lib/libdtrace/common/dt_impl.h
index acf30cd911..2262bf208a 100644
--- a/usr/src/lib/libdtrace/common/dt_impl.h
+++ b/usr/src/lib/libdtrace/common/dt_impl.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -177,6 +177,16 @@ typedef struct dt_dirpath {
char *dir_path; /* directory pathname */
} dt_dirpath_t;
+typedef struct dt_lib_depend {
+ dt_list_t dtld_deplist; /* linked-list forward/back pointers */
+ char *dtld_library; /* library name */
+ char *dtld_libpath; /* library pathname */
+ uint_t dtld_finish; /* completion time in tsort for lib */
+ uint_t dtld_start; /* starting time in tsort for lib */
+ dt_list_t dtld_dependencies; /* linked-list of lib dependencies */
+ dt_list_t dtld_dependents; /* linked-list of lib dependents */
+} dt_lib_depend_t;
+
typedef uint32_t dt_version_t; /* encoded version (see below) */
struct dtrace_hdl {
@@ -285,6 +295,8 @@ struct dtrace_hdl {
void *dt_bufarg; /* buffered handler argument */
dt_dof_t dt_dof; /* DOF generation buffers (see dt_dof.c) */
struct utsname dt_uts; /* uname(2) information for system */
+ dt_list_t dt_lib_dep; /* scratch linked-list of lib dependencies */
+ dt_list_t dt_lib_dep_sorted; /* dependency sorted library list */
};
/*
@@ -604,6 +616,9 @@ extern int dt_handle_status(dtrace_hdl_t *,
dtrace_status_t *, dtrace_status_t *);
extern int dt_handle_setopt(dtrace_hdl_t *, dtrace_setoptdata_t *);
+extern int dt_lib_depend_add(dtrace_hdl_t *, dt_list_t *, const char *);
+extern dt_lib_depend_t *dt_lib_depend_lookup(dt_list_t *, const char *);
+
extern dt_pcb_t *yypcb; /* pointer to current parser control block */
extern char yyintprefix; /* int token prefix for macros (+/-) */
extern char yyintsuffix[4]; /* int token suffix ([uUlL]*) */
diff --git a/usr/src/lib/libdtrace/common/dt_lex.l b/usr/src/lib/libdtrace/common/dt_lex.l
index 2e03c77582..fc74df15e0 100644
--- a/usr/src/lib/libdtrace/common/dt_lex.l
+++ b/usr/src/lib/libdtrace/common/dt_lex.l
@@ -3,9 +3,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
*
* CDDL HEADER END
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,19 +50,21 @@ static void unput(int);
/*
* We first define a set of labeled states for use in the D lexer and then a
- * set of regular expressions to simplify things below. The lexer states are:
+ * set of regular expressions to simplify things below. The lexer states are:
*
* S0 - D program clause and expression lexing
* S1 - D comments (i.e. skip everything until end of comment)
* S2 - D program outer scope (probe specifiers and declarations)
* S3 - D control line parsing (i.e. after ^# is seen but before \n)
+ * S4 - D control line scan (locate control directives only and invoke S3)
*/
%}
-%e 1400 /* maximum nodes */
+%e 1500 /* maximum nodes */
%p 3700 /* maximum positions */
+%n 600 /* maximum states */
-%s S0 S1 S2 S3
+%s S0 S1 S2 S3 S4
RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
@@ -425,15 +426,19 @@ if (yypcb->pcb_token != 0) {
}
<S0>{RGX_INTERP} |
-<S2>{RGX_INTERP} ; /* discard any #! lines */
+<S2>{RGX_INTERP} ; /* discard any #! lines */
<S0>{RGX_CTL} |
-<S2>{RGX_CTL} {
+<S2>{RGX_CTL} |
+<S4>{RGX_CTL} {
assert(yypragma == NULL);
yypcb->pcb_cstate = (YYSTATE);
BEGIN(S3);
}
+<S4>. ; /* discard */
+<S4>"\n" ; /* discard */
+
<S0>"/" {
int c, tok;
@@ -658,8 +663,8 @@ yybegin(yystate_t state)
return; /* nothing to do if we're in the state already */
if (yypcb->pcb_yystate == YYS_DEFINE) {
- yypcb->pcb_list = yypcb->pcb_hold;
- yypcb->pcb_hold = NULL;
+ yypcb->pcb_list = yypcb->pcb_hold;
+ yypcb->pcb_hold = NULL;
}
switch (state) {
@@ -676,6 +681,9 @@ yybegin(yystate_t state)
break;
case YYS_DONE:
break;
+ case YYS_CONTROL:
+ BEGIN(S4);
+ break;
default:
xyerror(D_UNKNOWN, "internal error -- bad yystate %d\n", state);
}
diff --git a/usr/src/lib/libdtrace/common/dt_parser.h b/usr/src/lib/libdtrace/common/dt_parser.h
index ebd828b3a1..6064efb2e6 100644
--- a/usr/src/lib/libdtrace/common/dt_parser.h
+++ b/usr/src/lib/libdtrace/common/dt_parser.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -257,7 +256,8 @@ typedef enum {
YYS_CLAUSE, /* lex/yacc state for finding program clauses */
YYS_DEFINE, /* lex/yacc state for parsing persistent definitions */
YYS_EXPR, /* lex/yacc state for parsing D expressions */
- YYS_DONE /* lex/yacc state for indicating parse tree is done */
+ YYS_DONE, /* lex/yacc state for indicating parse tree is done */
+ YYS_CONTROL /* lex/yacc state for parsing control lines */
} yystate_t;
extern void dnerror(const dt_node_t *, dt_errtag_t, const char *, ...);
diff --git a/usr/src/lib/libdtrace/common/dt_pragma.c b/usr/src/lib/libdtrace/common/dt_pragma.c
index 6c26b6deff..00b826978f 100644
--- a/usr/src/lib/libdtrace/common/dt_pragma.c
+++ b/usr/src/lib/libdtrace/common/dt_pragma.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <assert.h>
#include <strings.h>
#include <alloca.h>
#include <stdlib.h>
@@ -200,7 +200,8 @@ dt_pragma_binding(const char *prname, dt_node_t *dnp)
/*
* The #pragma depends_on directive can be used to express a dependency on a
- * module or provider, which if not present will cause processing to abort.
+ * module, provider or library which if not present will cause processing to
+ * abort.
*/
static void
dt_pragma_depends(const char *prname, dt_node_t *cnp)
@@ -208,6 +209,7 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
dt_node_t *nnp = cnp ? cnp->dn_list : NULL;
int found;
+ dt_lib_depend_t *dld;
if (cnp == NULL || nnp == NULL ||
cnp->dn_kind != DT_NODE_IDENT || nnp->dn_kind != DT_NODE_IDENT) {
@@ -220,6 +222,30 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
else if (strcmp(cnp->dn_string, "module") == 0) {
dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
found = mp != NULL && dt_module_getctf(dtp, mp) != NULL;
+ } else if (strcmp(cnp->dn_string, "library") == 0) {
+
+ /*
+ * We have the file we are working on in dtp->dt_filetag
+ * so find that node and add the dependency in.
+ */
+ if (yypcb->pcb_cflags & DTRACE_C_CTL) {
+ char lib[MAXPATHLEN];
+
+ dld = dt_lib_depend_lookup(&dtp->dt_lib_dep,
+ dtp->dt_filetag);
+ assert(dld != NULL);
+
+ (void) snprintf(lib, MAXPATHLEN, "%s%s",
+ dld->dtld_libpath, nnp->dn_string);
+ if ((dt_lib_depend_add(dtp, &dld->dtld_dependencies,
+ lib)) != 0) {
+ xyerror(D_PRAGMA_DEPEND,
+ "failed to add dependency %s:%s\n",
+ lib,
+ dtrace_errmsg(dtp, dtrace_errno(dtp)));
+ }
+ }
+ found = 1;
} else {
xyerror(D_PRAGMA_INVAL, "invalid class %s "
"specified by #pragma %s\n", cnp->dn_string, prname);
diff --git a/usr/src/lib/libdtrace/common/dtrace.h b/usr/src/lib/libdtrace/common/dtrace.h
index fb0738bf38..1c041207c0 100644
--- a/usr/src/lib/libdtrace/common/dtrace.h
+++ b/usr/src/lib/libdtrace/common/dtrace.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -114,7 +113,8 @@ typedef struct dtrace_proginfo {
#define DTRACE_C_ARGREF 0x0200 /* Do not require all macro args to be used */
#define DTRACE_C_DEFARG 0x0800 /* Use 0/"" as value for unspecified args */
#define DTRACE_C_NOLIBS 0x1000 /* Do not process D system libraries */
-#define DTRACE_C_MASK 0x1bff /* mask of all valid flags to dtrace_*compile */
+#define DTRACE_C_CTL 0x2000 /* Only process control directives */
+#define DTRACE_C_MASK 0x3bff /* mask of all valid flags to dtrace_*compile */
extern dtrace_prog_t *dtrace_program_strcompile(dtrace_hdl_t *,
const char *, dtrace_probespec_t, uint_t, int, char *const []);