From 1fc074913b0d1f0d57afb585daa41df47ea1ac31 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 23 Sep 2004 07:45:38 +0000 Subject: [PATCH] Update. 2004-09-23 Ulrich Drepper * sysdeps/generic/bits/dlfcn.h: Add RTLD_DEEPBIND. * elf/dl-object.c (_dl_new_object): Add new parameter mode. If mode has RTLD_DEEPBIND set add local searchlist before global scope. * sysdeps/generic/ldsodefs.h (_dl_new_object): Adjust prototype. * elf/rtld.c: Adjust callers of _dl_new_object. * elf/dl-load.c: Likewise. (_dl_map_object_from_fd): If RTLD_DEEPBIND is used, don't do anything for DF_SYMBOLIC. * elf/dl-open.c (dl_open_writer): Pass RTLD_DEEPBIND flag on to _dl_map_object_deps. * elf/tst-deep1.c: New file. * elf/tst-deep1mod1.c: New file. * elf/tst-deep1mod2.c: New file. * elf/tst-deep1mod3.c: New file. * elf/Makefile: Add rules to build and run new tests. * elf/dl-deps.c: Pretty printing. --- ChangeLog | 20 ++++++++++++++++++++ bits/dlfcn.h | 3 ++- elf/Makefile | 14 +++++++++++--- elf/dl-deps.c | 2 +- elf/dl-load.c | 14 ++++++-------- elf/dl-object.c | 12 ++++++++++-- elf/dl-open.c | 3 ++- elf/rtld.c | 5 +++-- elf/tst-deep1.c | 36 ++++++++++++++++++++++++++++++++++++ elf/tst-deep1mod1.c | 14 ++++++++++++++ elf/tst-deep1mod2.c | 16 ++++++++++++++++ elf/tst-deep1mod3.c | 17 +++++++++++++++++ sysdeps/generic/bits/dlfcn.h | 3 ++- sysdeps/generic/ldsodefs.h | 3 ++- 14 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 elf/tst-deep1.c create mode 100644 elf/tst-deep1mod1.c create mode 100644 elf/tst-deep1mod2.c create mode 100644 elf/tst-deep1mod3.c diff --git a/ChangeLog b/ChangeLog index aeb4726e55..11d9810f8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2004-09-23 Ulrich Drepper + + * sysdeps/generic/bits/dlfcn.h: Add RTLD_DEEPBIND. + * elf/dl-object.c (_dl_new_object): Add new parameter mode. If mode + has RTLD_DEEPBIND set add local searchlist before global scope. + * sysdeps/generic/ldsodefs.h (_dl_new_object): Adjust prototype. + * elf/rtld.c: Adjust callers of _dl_new_object. + * elf/dl-load.c: Likewise. + (_dl_map_object_from_fd): If RTLD_DEEPBIND is used, don't do anything + for DF_SYMBOLIC. + * elf/dl-open.c (dl_open_writer): Pass RTLD_DEEPBIND flag on to + _dl_map_object_deps. + * elf/tst-deep1.c: New file. + * elf/tst-deep1mod1.c: New file. + * elf/tst-deep1mod2.c: New file. + * elf/tst-deep1mod3.c: New file. + * elf/Makefile: Add rules to build and run new tests. + + * elf/dl-deps.c: Pretty printing. + 2004-09-23 Jakub Jelinek * sysdeps/unix/alpha/sysdep.h (inline_syscall[0-6]): Change name diff --git a/bits/dlfcn.h b/bits/dlfcn.h index e96b5c17ae..67fd96a22a 100644 --- a/bits/dlfcn.h +++ b/bits/dlfcn.h @@ -1,5 +1,5 @@ /* System dependent definitions for run-time dynamic loading. - Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,6 +26,7 @@ #define RTLD_NOW 0x00002 /* Immediate function call binding. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_NOLOAD 0x00004 /* Do not load the object. */ +#define RTLD_DEEPBIND 0x00008 /* Use deep binding. */ /* If the following bit is set in the MODE argument to `dlopen', the symbols of the loaded object and its dependencies are made diff --git a/elf/Makefile b/elf/Makefile index ac8319bc5f..d40d3fd6a7 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -82,7 +82,8 @@ distribute := rtld-Rules \ tst-array1.exp tst-array2.exp tst-array4.exp \ tst-array2dep.c tst-piemod1.c \ tst-execstack-mod.c tst-dlmodcount.c \ - check-textrel.c dl-sysdep.h test-dlopenrpathmod.c + check-textrel.c dl-sysdep.h test-dlopenrpathmod.c \ + tst-deep1mod1.c tst-deep1mod2.c tst-deep1mod3.c CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables @@ -152,7 +153,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \ - $(tests-execstack-$(have-z-execstack)) tst-dlmodcount tst-dlopenrpath + $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \ + tst-dlopenrpath tst-deep1 # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -185,7 +187,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ reldep8mod1 reldep8mod2 reldep8mod3 \ reldep9mod1 reldep9mod2 reldep9mod3 \ tst-alignmod $(modules-execstack-$(have-z-execstack)) \ - tst-dlopenrpathmod + tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 ifeq (yes,$(have-initfini-array)) modules-names += tst-array2dep endif @@ -754,3 +756,9 @@ $(objpfx)tst-dlopenrpath: $(objpfx)tst-dlopenrpathmod.so $(libdl) CFLAGS-tst-dlopenrpath.c += -DPFX=\"$(objpfx)\" LDFLAGS-tst-dlopenrpathmod.so += -Wl,-rpath,\$$ORIGIN/test-subdir $(objpfx)tst-dlopenrpath.out: $(objpfx)firstobj.so + +$(objpfx)tst-deep1mod2.so: $(objpfx)tst-deep1mod3.so +$(objpfx)tst-deep1: $(libdl) $(objpfx)tst-deep1mod1.so +$(objpfx)tst-deep1.out: $(objpfx)tst-deep1mod2.so +LDFLAGS-tst-deep1 += -rdynamic +tst-deep1mod3.so-no-z-defs = yes diff --git a/elf/dl-deps.c b/elf/dl-deps.c index b8dee8ab52..1a0fedf988 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -509,7 +509,7 @@ _dl_map_object_deps (struct link_map *map, runp->map->l_reserved = 0; } - if (__builtin_expect(GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0 + if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0 && map == GL(dl_loaded)) { /* If we are to compute conflicts, we have to build local scope diff --git a/elf/dl-load.c b/elf/dl-load.c index 73112bce23..15fff3c5e1 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -881,7 +881,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, #endif /* Enter the new object in the list of loaded objects. */ - l = _dl_new_object (realname, name, l_type, loader); + l = _dl_new_object (realname, name, l_type, loader, mode); if (__builtin_expect (! l, 0)) { errstring = N_("cannot create shared object descriptor"); @@ -1355,15 +1355,12 @@ cannot enable executable stack as shared object requires"); /* If this object has DT_SYMBOLIC set modify now its scope. We don't have to do this for the main map. */ - if (__builtin_expect (l->l_info[DT_SYMBOLIC] != NULL, 0) + if ((mode & RTLD_DEEPBIND) == 0 + && __builtin_expect (l->l_info[DT_SYMBOLIC] != NULL, 0) && &l->l_searchlist != l->l_scope[0]) { /* Create an appropriate searchlist. It contains only this map. - - XXX This is the definition of DT_SYMBOLIC in SysVr4. The old - GNU ld.so implementation had a different interpretation which - is more reasonable. We are prepared to add this possibility - back as part of a GNU extension of the ELF format. */ + This is the definition of DT_SYMBOLIC in SysVr4. */ l->l_symbolic_searchlist.r_list = (struct link_map **) malloc (sizeof (struct link_map *)); @@ -1968,7 +1965,8 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, /* Enter the new object in the list of loaded objects. */ if ((name_copy = local_strdup (name)) == NULL - || (l = _dl_new_object (name_copy, name, type, loader)) == NULL) + || (l = _dl_new_object (name_copy, name, type, loader, + mode)) == NULL) _dl_signal_error (ENOMEM, name, NULL, N_("cannot create shared object descriptor")); /* Signal that this is a faked entry. */ diff --git a/elf/dl-object.c b/elf/dl-object.c index 52131181b3..91b1fa2187 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -32,7 +32,7 @@ struct link_map * internal_function _dl_new_object (char *realname, const char *libname, int type, - struct link_map *loader) + struct link_map *loader, int mode) { struct link_map *l; int idx; @@ -95,7 +95,15 @@ _dl_new_object (char *realname, const char *libname, int type, /* Insert the scope if it isn't the global scope we already added. */ if (idx == 0 || &loader->l_searchlist != new->l_scope[0]) - new->l_scope[idx] = &loader->l_searchlist; + { + if ((mode & RTLD_DEEPBIND) != 0 && idx != 0) + { + new->l_scope[1] = new->l_scope[0]; + idx = 0; + } + + new->l_scope[idx] = &loader->l_searchlist; + } new->l_local_scope[0] = &new->l_searchlist; diff --git a/elf/dl-open.c b/elf/dl-open.c index c352722e27..c9b4a45596 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -272,7 +272,8 @@ dl_open_worker (void *a) } /* Load that object's dependencies. */ - GLRO(dl_map_object_deps) (new, NULL, 0, 0, mode & __RTLD_DLOPEN); + GLRO(dl_map_object_deps) (new, NULL, 0, 0, + mode & (__RTLD_DLOPEN | RTLD_DEEPBIND)); /* So far, so good. Now check the versions. */ for (i = 0; i < new->l_searchlist.r_nlist; ++i) diff --git a/elf/rtld.c b/elf/rtld.c index 2daf05a6d6..1ee875a088 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -879,7 +879,7 @@ of this helper program; chances are you did not intend to run this program.\n\ { /* Create a link_map for the executable itself. This will be what dlopen on "" returns. */ - _dl_new_object ((char *) "", "", lt_executable, NULL); + _dl_new_object ((char *) "", "", lt_executable, NULL, 0); if (GL(dl_loaded) == NULL) _dl_fatal_printf ("cannot allocate memory for link map\n"); GL(dl_loaded)->l_phdr = phdr; @@ -1271,7 +1271,8 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n", better be, since it's read-only and so we couldn't relocate it). We just want our data structures to describe it as if we had just mapped and relocated it normally. */ - struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL); + struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL, + 0); if (__builtin_expect (l != NULL, 1)) { static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; diff --git a/elf/tst-deep1.c b/elf/tst-deep1.c new file mode 100644 index 0000000000..5428d13de4 --- /dev/null +++ b/elf/tst-deep1.c @@ -0,0 +1,36 @@ +#include +#include + +int +xyzzy (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return 21; +} + +int +back (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return 1; +} + +extern int foo (void); + +static int +do_test (void) +{ + void *p = dlopen ("$ORIGIN/tst-deep1mod2.so", RTLD_LAZY|RTLD_DEEPBIND); + + int (*f) (void) = dlsym (p, "bar"); + if (f == NULL) + { + puts (dlerror ()); + return 1; + } + + return foo () + f (); +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-deep1mod1.c b/elf/tst-deep1mod1.c new file mode 100644 index 0000000000..cc922e6ea5 --- /dev/null +++ b/elf/tst-deep1mod1.c @@ -0,0 +1,14 @@ +#include +int +foo (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return 1; +} + +int +baz (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return 20; +} diff --git a/elf/tst-deep1mod2.c b/elf/tst-deep1mod2.c new file mode 100644 index 0000000000..b99caf0328 --- /dev/null +++ b/elf/tst-deep1mod2.c @@ -0,0 +1,16 @@ +#include +extern int baz (void); +extern int xyzzy (void); +int +bar (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return baz () + xyzzy ();; +} + +int +back (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return -1; +} diff --git a/elf/tst-deep1mod3.c b/elf/tst-deep1mod3.c new file mode 100644 index 0000000000..eee7d5c97b --- /dev/null +++ b/elf/tst-deep1mod3.c @@ -0,0 +1,17 @@ +#include + +extern int back (void); + +int +baz (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return back (); +} + +int +xyzzy (void) +{ + printf ("%s:%s\n", __FILE__, __func__); + return 0; +} diff --git a/sysdeps/generic/bits/dlfcn.h b/sysdeps/generic/bits/dlfcn.h index e96b5c17ae..67fd96a22a 100644 --- a/sysdeps/generic/bits/dlfcn.h +++ b/sysdeps/generic/bits/dlfcn.h @@ -1,5 +1,5 @@ /* System dependent definitions for run-time dynamic loading. - Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,6 +26,7 @@ #define RTLD_NOW 0x00002 /* Immediate function call binding. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_NOLOAD 0x00004 /* Do not load the object. */ +#define RTLD_DEEPBIND 0x00008 /* Use deep binding. */ /* If the following bit is set in the MODE argument to `dlopen', the symbols of the loaded object and its dependencies are made diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index be3d2dd61f..2b526867ad 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -722,7 +722,8 @@ extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name) /* Allocate a `struct link_map' for a new object being loaded, and enter it into the _dl_main_map list. */ extern struct link_map *_dl_new_object (char *realname, const char *libname, - int type, struct link_map *loader) + int type, struct link_map *loader, + int mode) internal_function attribute_hidden; /* Relocate the given object (if it hasn't already been).