+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>
* sysdeps/unix/alpha/sysdep.h (inline_syscall[0-6]): Change name
/* 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
#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
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
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
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
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
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
#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");
/* 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 *));
/* 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. */
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;
/* 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;
}
/* 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)
{
/* 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;
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;
--- /dev/null
+#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"
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
/* 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
#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
/* 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).