diff options
author | Pedro F. Giffuni <pfg@FreeBSD.org> | 2012-07-17 19:57:34 +0000 |
---|---|---|
committer | Pedro F. Giffuni <pfg@FreeBSD.org> | 2012-07-17 19:57:34 +0000 |
commit | 694a0093a74c742ebd1fbec3a68685947cdab30f (patch) | |
tree | 514723b2e08585e273c82e445c37452f8ce9f815 | |
parent | d638e8dcde9d1d93465e0afc50139d8553e70a7d (diff) | |
parent | 1aa03d3a8432d812a4400b9b99cf10959bc5c43c (diff) | |
download | src-694a0093a74c742ebd1fbec3a68685947cdab30f.tar.gz src-694a0093a74c742ebd1fbec3a68685947cdab30f.zip |
Dtrace: improve handling of library paths.
Merge changes from illumos
906 dtrace depends_on pragma should search all library paths, not just the
current one
949 dtrace should only include the first instance of a library found on
its library path
Illumos Revisions: 13353:936a1e45726c
13354:2b2c36a81512
Reference:
https://www.illumos.org/issues/906
https://www.illumos.org/issues/949
Tested by: Fabian Keil
Obtained from: Illumos
MFC after: 3 weeks
Notes
Notes:
svn path=/head/; revision=238558
4 files changed, 254 insertions, 22 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/include/tst.includefirst.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/include/tst.includefirst.ksh new file mode 100644 index 000000000000..b8240d64367c --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/include/tst.includefirst.ksh @@ -0,0 +1,76 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# 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. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2011, Joyent Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# This test verifies that we only use the first entry of a file with a given +# name in the library path +# + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +firstinc=${TMPDIR:-/tmp}/firstinc.$$ +secondinc=${TMPDIR:-/tmp}/secondinc.$$ +expexit=23 + +setup_include() +{ + mkdir $firstinc + mkdir $secondinc + cat > $firstinc/lib.d <<EOF +inline int foobar = $expexit; +#pragma D binding "1.0" foobar +EOF + cat > $secondinc/lib.d <<EOF +inline int foobar = 42; +#pragma D binding "1.0" foobar +EOF +} + +clean() +{ + rm -rf $firstinc + rm -rf $secondinc +} + +fail() +{ + echo "$@" + clean + exit 1 +} + +setup_include + +dtrace -L$firstinc -L$secondinc -e -n 'BEGIN{ exit(foobar) }' +[[ $? != 0 ]] && fail "Failed to compile with same file in include path twice" +dtrace -L$firstinc -L$secondinc -n 'BEGIN{ exit(foobar) }' +status=$? +[[ $status != $expexit ]] && fail "Exited with unexpected status code: $status" +clean +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pragma/tst.libdepsepdir.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pragma/tst.libdepsepdir.ksh new file mode 100644 index 000000000000..ced65849b98d --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pragma/tst.libdepsepdir.ksh @@ -0,0 +1,76 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# 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. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2011, Joyent Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Test to catch that we properly look for libraries dependencies in +# our full library parth +# + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +libdira=${TMPDIR:-/tmp}/libdepa.$$ +libdirb=${TMPDIR:-/tmp}/libdepb.$$ +libdirc=${TMPDIR:-/tmp}/libdepc.$$ +dtrace=$1 + +setup_libs() +{ + mkdir $libdira + mkdir $libdirb + mkdir $libdirc + cat > $libdira/liba.$$.d <<EOF +#pragma D depends_on library libb.$$.d +#pragma D depends_on library libc.$$.d +#pragma D depends_on library libd.$$.d +EOF + cat > $libdirb/libb.$$.d <<EOF +#pragma D depends_on library libc.$$.d +EOF + cat > $libdirb/libc.$$.d <<EOF +EOF + cat > $libdirb/libd.$$.d <<EOF +EOF + cat > $libdirc/libe.$$.d <<EOF +#pragma D depends_on library liba.$$.d +EOF + cat > $libdirc/libf.$$.d <<EOF +EOF +} + + +setup_libs + +$dtrace -L$libdira -L$libdirb -L$libdirc -e + +status=$? +rm -rf $libdira +rm -rf $libdirb +rm -rf $libdirc +return $status + diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c index 6714757060ca..d5423f634d6f 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ /* @@ -2150,25 +2151,23 @@ dt_lib_depend_free(dtrace_hdl_t *dtp) } } - /* - * 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. + * Open all the .d library files found in the specified directory and + * compile each one of them. 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. */ static int dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) { struct dirent *dp; - const char *p; + const char *p, *end; DIR *dirp; char fname[PATH_MAX]; - dtrace_prog_t *pgp; FILE *fp; void *rv; dt_lib_depend_t *dld; @@ -2192,9 +2191,28 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) continue; } + /* + * Skip files whose name match an already processed library + */ + for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL; + dld = dt_list_next(dld)) { + end = strrchr(dld->dtld_library, '/'); + /* dt_lib_depend_add ensures this */ + assert(end != NULL); + if (strcmp(end + 1, dp->d_name) == 0) + break; + } + + if (dld != NULL) { + dt_dprintf("skipping library %s, already processed " + "library with the same name: %s", dp->d_name, + dld->dtld_library); + continue; + } + dtp->dt_filetag = fname; if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0) - goto err; + return (-1); /* preserve dt_errno */ rv = dt_compile(dtp, DT_CTX_DPROG, DTRACE_PROBESPEC_NAME, NULL, @@ -2203,7 +2221,7 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) if (rv != NULL && dtp->dt_errno && (dtp->dt_errno != EDT_COMPILER || dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) - goto err; + return (-1); /* preserve dt_errno */ if (dtp->dt_errno) dt_dprintf("error parsing library %s: %s\n", @@ -2214,6 +2232,27 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) } (void) closedir(dirp); + + return (0); +} + +/* + * Perform a topological sorting of all the libraries found across the entire + * dt_lib_path. Once sorted, 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. + */ +static int +dt_load_libs_sort(dtrace_hdl_t *dtp) +{ + dtrace_prog_t *pgp; + FILE *fp; + dt_lib_depend_t *dld; + /* * Finish building the graph containing the library dependencies * and perform a topological sort to generate an ordered list @@ -2274,7 +2313,14 @@ dt_load_libs(dtrace_hdl_t *dtp) dtp->dt_cflags |= DTRACE_C_NOLIBS; - for (dirp = dt_list_next(&dtp->dt_lib_path); + /* + * /usr/lib/dtrace is always at the head of the list. The rest of the + * list is specified in the precedence order the user requested. Process + * everything other than the head first. DTRACE_C_NOLIBS has already + * been spcified so dt_vopen will ensure that there is always one entry + * in dt_lib_path. + */ + for (dirp = dt_list_next(dt_list_next(&dtp->dt_lib_path)); dirp != NULL; dirp = dt_list_next(dirp)) { if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) { dtp->dt_cflags &= ~DTRACE_C_NOLIBS; @@ -2282,6 +2328,16 @@ dt_load_libs(dtrace_hdl_t *dtp) } } + /* Handle /usr/lib/dtrace */ + dirp = dt_list_next(&dtp->dt_lib_path); + if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) { + dtp->dt_cflags &= ~DTRACE_C_NOLIBS; + return (-1); /* errno is set for us */ + } + + if (dt_load_libs_sort(dtp) < 0) + return (-1); /* errno is set for us */ + return (0); } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c index a9328ab067b9..00578f43350f 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c @@ -21,7 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -31,9 +31,13 @@ #if defined(sun) #include <alloca.h> #endif +#include <fcntl.h> #include <stdlib.h> #include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + #include <dt_parser.h> #include <dt_impl.h> #include <dt_provider.h> @@ -201,6 +205,29 @@ dt_pragma_binding(const char *prname, dt_node_t *dnp) dtp->dt_globals->dh_defer = &dt_pragma_apply; } +static void +dt_pragma_depends_finddep(dtrace_hdl_t *dtp, const char *lname, char *lib, + size_t len) +{ + dt_dirpath_t *dirp; + struct stat sbuf; + int found = 0; + + for (dirp = dt_list_next(&dtp->dt_lib_path); dirp != NULL; + dirp = dt_list_next(dirp)) { + (void) snprintf(lib, len, "%s/%s", dirp->dir_path, lname); + + if (stat(lib, &sbuf) == 0) { + found = 1; + break; + } + } + + if (!found) + xyerror(D_PRAGMA_DEPEND, + "failed to find dependency in libpath: %s", lname); +} + /* * The #pragma depends_on directive can be used to express a dependency on a * module, provider or library which if not present will cause processing to @@ -230,16 +257,13 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp) if (yypcb->pcb_cflags & DTRACE_C_CTL) { assert(dtp->dt_filetag != NULL); - /* - * We have the file we are working on in dtp->dt_filetag - * so find that node and add the dependency in. - */ + dt_pragma_depends_finddep(dtp, nnp->dn_string, lib, + sizeof (lib)); + dld = dt_lib_depend_lookup(&dtp->dt_lib_dep, dtp->dt_filetag); assert(dld != NULL); - (void) snprintf(lib, sizeof (lib), "%s%s", - dld->dtld_libpath, nnp->dn_string); if ((dt_lib_depend_add(dtp, &dld->dtld_dependencies, lib)) != 0) { xyerror(D_PRAGMA_DEPEND, @@ -261,8 +285,8 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp) dtp->dt_filetag); assert(dld != NULL); - (void) snprintf(lib, sizeof (lib), "%s%s", - dld->dtld_libpath, nnp->dn_string); + dt_pragma_depends_finddep(dtp, nnp->dn_string, lib, + sizeof (lib)); dld = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted, lib); assert(dld != NULL); |