diff options
author | jhaslam <none@none> | 2007-11-14 03:55:39 -0800 |
---|---|---|
committer | jhaslam <none@none> | 2007-11-14 03:55:39 -0800 |
commit | c9d6cd77e4180c3831afde367c7eb129e72f0b2c (patch) | |
tree | f441212843bc379a8981accc1210101ee997e73a /usr/src/lib/libdtrace/common | |
parent | fa66589cbc72e2aa1c5d6dd376ae1be20ff3dfe3 (diff) | |
download | illumos-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.c | 320 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_impl.h | 17 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_lex.l | 30 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_parser.h | 10 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_pragma.c | 36 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dtrace.h | 10 |
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 []); |