aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2012-11-21 07:06:15 -0800
committerH.J. Lu <hjl.tools@gmail.com>2012-11-21 12:36:20 -0800
commit78e479f3fb0be02cabfd0512132ea61daa4f2a6d (patch)
treeba0d6ffd8d7796a9039f7d78d2725dc83a6231bf
parent6bfea97493900d456245ca9f29765e1f0ee9d649 (diff)
downloadglibc-78e479f3fb0be02cabfd0512132ea61daa4f2a6d.zip
glibc-78e479f3fb0be02cabfd0512132ea61daa4f2a6d.tar.gz
glibc-78e479f3fb0be02cabfd0512132ea61daa4f2a6d.tar.bz2
Support DF_1_GLOBAL
-rw-r--r--elf/Makefile6
-rw-r--r--elf/dl-open.c5
-rw-r--r--elf/reldep10.c101
-rw-r--r--include/elf.h2
4 files changed, 112 insertions, 2 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 7e5c9c8..aa744e4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -145,7 +145,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit1 tst-audit2 tst-audit8 \
tst-stackguard1 tst-addr1 tst-thrlock \
tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
- tst-initorder tst-initorder2 tst-relsort1
+ tst-initorder tst-initorder2 tst-relsort1 reldep10
# reldep9
test-srcs = tst-pathopt
selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
@@ -745,6 +745,10 @@ $(objpfx)nodelete2.out: $(objpfx)nodel2mod3.so
$(objpfx)reldep9: $(libdl)
$(objpfx)reldep9.out: $(objpfx)reldep9mod3.so
+LDFLAGS-reldep10 = -Wl,-z,global
+$(objpfx)reldep10: $(libdl)
+$(objpfx)reldep10.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod3.so
+
$(objpfx)tst-tls3: $(objpfx)tst-tlsmod1.so
$(objpfx)tst-tls4: $(libdl)
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 9c39a34..2e3e7ec 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -240,6 +240,11 @@ dl_open_worker (void *a)
/* This happens only if we load a DSO for 'sprof'. */
return;
+ /* Make the symbols defined in the object available for symbol resolution
+ of subsequently loaded objects if it is marked with DF_1_GLOBAL. */
+ if (__builtin_expect (new->l_flags_1 & DF_1_GLOBAL, 0))
+ mode |= RTLD_GLOBAL;
+
/* This object is directly loaded. */
++new->l_direct_opencount;
diff --git a/elf/reldep10.c b/elf/reldep10.c
new file mode 100644
index 0000000..45ebcf9
--- /dev/null
+++ b/elf/reldep10.c
@@ -0,0 +1,101 @@
+#include <dlfcn.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ void *h1;
+ void *h2;
+ int (*fp) (void);
+ int *vp;
+
+ mtrace ();
+
+ /* Open the two objects. */
+ h1 = dlopen ("reldepmod1.so", RTLD_LAZY);
+ if (h1 == NULL)
+ {
+ printf ("cannot open reldepmod1.so: %s\n", dlerror ());
+ exit (1);
+ }
+ h2 = dlopen ("reldepmod3.so", RTLD_LAZY);
+ if (h2 == NULL)
+ {
+ printf ("cannot open reldepmod3.so: %s\n", dlerror ());
+ exit (1);
+ }
+
+ /* Get the address of the variable in reldepmod1.so. */
+ vp = dlsym (h1, "some_var");
+ if (vp == NULL)
+ {
+ printf ("cannot get address of \"some_var\": %s\n", dlerror ());
+ exit (1);
+ }
+
+ *vp = 42;
+
+ /* Get the function `call_me' in the second object. This has a
+ dependency which is resolved by a definition in reldepmod1.so. */
+ fp = dlsym (h2, "call_me");
+ if (fp == NULL)
+ {
+ printf ("cannot get address of \"call_me\": %s\n", dlerror ());
+ exit (1);
+ }
+
+ /* Call the function. */
+ if (fp () != 0)
+ {
+ puts ("function \"call_me\" returned wrong result");
+ exit (1);
+ }
+
+ /* Now close the first object. It must still be around since we have
+ an implicit dependency. */
+ if (dlclose (h1) != 0)
+ {
+ printf ("closing h1 failed: %s\n", dlerror ());
+ exit (1);
+ }
+
+ /* Open the first object again. */
+ h1 = dlopen ("reldepmod1.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (h1 == NULL)
+ {
+ printf ("cannot open reldepmod1.so the second time: %s\n", dlerror ());
+ exit (1);
+ }
+
+ /* Get the variable address again. */
+ vp = dlsym (h1, "some_var");
+ if (vp == NULL)
+ {
+ printf ("cannot get address of \"some_var\" the second time: %s\n",
+ dlerror ());
+ exit (1);
+ }
+
+ /* The variable now must have its originial value. */
+ if (*vp != 42)
+ {
+ puts ("variable \"some_var\" reset");
+ exit (1);
+ }
+
+ /* Close the first object again, we are done. */
+ if (dlclose (h1) != 0)
+ {
+ printf ("closing h1 failed: %s\n", dlerror ());
+ exit (1);
+ }
+ if (dlclose (h2) != 0)
+ {
+ printf ("closing h2 failed: %s\n", dlerror ());
+ exit (1);
+ }
+
+ return 0;
+}
diff --git a/include/elf.h b/include/elf.h
index 60658c6..d594bf5 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -7,6 +7,6 @@
# error DT_1_SUPPORTED_MASK is defined!
# endif
# define DT_1_SUPPORTED_MASK \
- (DF_1_NOW | DF_1_NODELETE | DF_1_INITFIRST | DF_1_NOOPEN \
+ (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE | DF_1_INITFIRST | DF_1_NOOPEN \
| DF_1_ORIGIN | DF_1_NODEFLIB)
#endif