2004-09-23  Ulrich Drepper  <drepper@redhat.com>

	* 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.
This commit is contained in:
Ulrich Drepper 2004-09-23 07:45:38 +00:00
parent bbb5e55c10
commit 1fc074913b
14 changed files with 142 additions and 20 deletions

View File

@ -1,3 +1,23 @@
2004-09-23 Ulrich Drepper <drepper@redhat.com>
* 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 <jakub@redhat.com> 2004-09-23 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/alpha/sysdep.h (inline_syscall[0-6]): Change name * sysdeps/unix/alpha/sysdep.h (inline_syscall[0-6]): Change name

View File

@ -1,5 +1,5 @@
/* System dependent definitions for run-time dynamic loading. /* 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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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_NOW 0x00002 /* Immediate function call binding. */
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
#define RTLD_NOLOAD 0x00004 /* Do not load the object. */ #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', /* If the following bit is set in the MODE argument to `dlopen',
the symbols of the loaded object and its dependencies are made the symbols of the loaded object and its dependencies are made

View File

@ -82,7 +82,8 @@ distribute := rtld-Rules \
tst-array1.exp tst-array2.exp tst-array4.exp \ tst-array1.exp tst-array2.exp tst-array4.exp \
tst-array2dep.c tst-piemod1.c \ tst-array2dep.c tst-piemod1.c \
tst-execstack-mod.c tst-dlmodcount.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-runtime.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-dl-lookup.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 \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ 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 \ 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 # reldep9
test-srcs = tst-pathopt test-srcs = tst-pathopt
tests-vis-yes = vismain tests-vis-yes = vismain
@ -185,7 +187,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
reldep8mod1 reldep8mod2 reldep8mod3 \ reldep8mod1 reldep8mod2 reldep8mod3 \
reldep9mod1 reldep9mod2 reldep9mod3 \ reldep9mod1 reldep9mod2 reldep9mod3 \
tst-alignmod $(modules-execstack-$(have-z-execstack)) \ tst-alignmod $(modules-execstack-$(have-z-execstack)) \
tst-dlopenrpathmod tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3
ifeq (yes,$(have-initfini-array)) ifeq (yes,$(have-initfini-array))
modules-names += tst-array2dep modules-names += tst-array2dep
endif endif
@ -754,3 +756,9 @@ $(objpfx)tst-dlopenrpath: $(objpfx)tst-dlopenrpathmod.so $(libdl)
CFLAGS-tst-dlopenrpath.c += -DPFX=\"$(objpfx)\" CFLAGS-tst-dlopenrpath.c += -DPFX=\"$(objpfx)\"
LDFLAGS-tst-dlopenrpathmod.so += -Wl,-rpath,\$$ORIGIN/test-subdir LDFLAGS-tst-dlopenrpathmod.so += -Wl,-rpath,\$$ORIGIN/test-subdir
$(objpfx)tst-dlopenrpath.out: $(objpfx)firstobj.so $(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

View File

@ -509,7 +509,7 @@ _dl_map_object_deps (struct link_map *map,
runp->map->l_reserved = 0; 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)) && map == GL(dl_loaded))
{ {
/* If we are to compute conflicts, we have to build local scope /* If we are to compute conflicts, we have to build local scope

View File

@ -881,7 +881,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
#endif #endif
/* Enter the new object in the list of loaded objects. */ /* 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)) if (__builtin_expect (! l, 0))
{ {
errstring = N_("cannot create shared object descriptor"); 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 /* If this object has DT_SYMBOLIC set modify now its scope. We don't
have to do this for the main map. */ 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]) && &l->l_searchlist != l->l_scope[0])
{ {
/* Create an appropriate searchlist. It contains only this map. /* Create an appropriate searchlist. It contains only this map.
This is the definition of DT_SYMBOLIC in SysVr4. */
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. */
l->l_symbolic_searchlist.r_list = l->l_symbolic_searchlist.r_list =
(struct link_map **) malloc (sizeof (struct link_map *)); (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. */ /* Enter the new object in the list of loaded objects. */
if ((name_copy = local_strdup (name)) == NULL 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, _dl_signal_error (ENOMEM, name, NULL,
N_("cannot create shared object descriptor")); N_("cannot create shared object descriptor"));
/* Signal that this is a faked entry. */ /* Signal that this is a faked entry. */

View File

@ -32,7 +32,7 @@
struct link_map * struct link_map *
internal_function internal_function
_dl_new_object (char *realname, const char *libname, int type, _dl_new_object (char *realname, const char *libname, int type,
struct link_map *loader) struct link_map *loader, int mode)
{ {
struct link_map *l; struct link_map *l;
int idx; 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. */ /* Insert the scope if it isn't the global scope we already added. */
if (idx == 0 || &loader->l_searchlist != new->l_scope[0]) 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; new->l_local_scope[0] = &new->l_searchlist;

View File

@ -272,7 +272,8 @@ dl_open_worker (void *a)
} }
/* Load that object's dependencies. */ /* 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. */ /* So far, so good. Now check the versions. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i) for (i = 0; i < new->l_searchlist.r_nlist; ++i)

View File

@ -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. /* Create a link_map for the executable itself.
This will be what dlopen on "" returns. */ 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) if (GL(dl_loaded) == NULL)
_dl_fatal_printf ("cannot allocate memory for link map\n"); _dl_fatal_printf ("cannot allocate memory for link map\n");
GL(dl_loaded)->l_phdr = phdr; 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). 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 We just want our data structures to describe it as if we had just
mapped and relocated it normally. */ 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)) if (__builtin_expect (l != NULL, 1))
{ {
static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;

36
elf/tst-deep1.c Normal file
View File

@ -0,0 +1,36 @@
#include <dlfcn.h>
#include <stdio.h>
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"

14
elf/tst-deep1mod1.c Normal file
View File

@ -0,0 +1,14 @@
#include <stdio.h>
int
foo (void)
{
printf ("%s:%s\n", __FILE__, __func__);
return 1;
}
int
baz (void)
{
printf ("%s:%s\n", __FILE__, __func__);
return 20;
}

16
elf/tst-deep1mod2.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
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;
}

17
elf/tst-deep1mod3.c Normal file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
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;
}

View File

@ -1,5 +1,5 @@
/* System dependent definitions for run-time dynamic loading. /* 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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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_NOW 0x00002 /* Immediate function call binding. */
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
#define RTLD_NOLOAD 0x00004 /* Do not load the object. */ #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', /* If the following bit is set in the MODE argument to `dlopen',
the symbols of the loaded object and its dependencies are made the symbols of the loaded object and its dependencies are made

View File

@ -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, /* Allocate a `struct link_map' for a new object being loaded,
and enter it into the _dl_main_map list. */ and enter it into the _dl_main_map list. */
extern struct link_map *_dl_new_object (char *realname, const char *libname, 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; internal_function attribute_hidden;
/* Relocate the given object (if it hasn't already been). /* Relocate the given object (if it hasn't already been).