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
This commit is contained in:
commit
694a0093a7
@ -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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user