aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile9
-rw-r--r--elf/dl-open.c64
-rw-r--r--elf/tst-tls19.c27
-rw-r--r--elf/tst-tls19mod1.c15
-rw-r--r--elf/tst-tls19mod2.c13
-rw-r--r--elf/tst-tls19mod3.c16
6 files changed, 118 insertions, 26 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 8d9657d..6efb86c 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -76,6 +76,7 @@ distribute := rtld-Rules \
tst-tlsmod12.c tst-tls10.h tst-alignmod.c tst-alignmod2.c \
circlemod1.c circlemod1a.c circlemod2.c circlemod2a.c \
circlemod3.c circlemod3a.c nodlopenmod2.c \
+ tst-tls19mod1.c tst-tls19mod2.c tst-tls19mod3.c \
tls-macros.h \
reldep8mod1.c reldep8mod2.c reldep8mod3.c \
nodel2mod1.c nodel2mod2.c nodel2mod3.c \
@@ -194,7 +195,7 @@ 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-tls15 \
- tst-tls16 tst-tls17 tst-tls18 tst-tls-dlinfo \
+ tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \
tst-dlmodcount tst-dlopenrpath tst-deep1 \
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
@@ -240,6 +241,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \
tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \
$(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \
+ tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
circlemod1 circlemod1a circlemod2 circlemod2a \
circlemod3 circlemod3a \
reldep8mod1 reldep8mod2 reldep8mod3 \
@@ -525,6 +527,8 @@ $(objpfx)tst-tlsmod13a.so: $(objpfx)tst-tlsmod13.so
# For tst-tls9-static, make sure the modules it dlopens have libc.so in DT_NEEDED
$(objpfx)tst-tlsmod5.so: $(common-objpfx)libc.so
$(objpfx)tst-tlsmod6.so: $(common-objpfx)libc.so
+$(objpfx)tst-tls19mod1.so: $(objpfx)tst-tls19mod2.so $(objpfx)tst-tls19mod3.so
+$(objpfx)tst-tls19mod3.so: $(objpfx)ld.so
$(objpfx)reldep8mod3.so: $(objpfx)reldep8mod1.so $(objpfx)reldep8mod2.so
$(objpfx)nodel2mod3.so: $(objpfx)nodel2mod1.so $(objpfx)nodel2mod2.so
$(objpfx)reldep9mod2.so: $(objpfx)reldep9mod1.so
@@ -822,6 +826,9 @@ $(patsubst %,$(objpfx)%.os,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.os : t
$(compile-command.c) -DN=$*
$(patsubst %,$(objpfx)%.so,$(tlsmod18a-modules)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so
+$(objpfx)tst-tls19: $(libdl)
+$(objpfx)tst-tls19.out: $(objpfx)tst-tls19mod1.so
+
CFLAGS-tst-align.c = $(stack-align-test-flags)
CFLAGS-tst-align2.c = $(stack-align-test-flags)
CFLAGS-tst-alignmod.c = $(stack-align-test-flags)
diff --git a/elf/dl-open.c b/elf/dl-open.c
index cf8e8cc..8d90b56 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -1,5 +1,5 @@
/* Load a shared object at runtime, relocate it, and run its initializer.
- Copyright (C) 1996-2007, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1996-2007, 2009, 2010, 2011 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
@@ -347,6 +347,7 @@ dl_open_worker (void *a)
/* If the file is not loaded now as a dependency, add the search
list of the newly loaded object to the scope. */
bool any_tls = false;
+ unsigned int first_static_tls = new->l_searchlist.r_nlist;
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
{
struct link_map *imap = new->l_searchlist.r_list[i];
@@ -425,30 +426,9 @@ dl_open_worker (void *a)
might have to increase its size. */
_dl_add_to_slotinfo (imap);
- if (imap->l_need_tls_init)
- {
- /* For static TLS we have to allocate the memory here
- and now. This includes allocating memory in the DTV.
- But we cannot change any DTV other than our own. So,
- if we cannot guarantee that there is room in the DTV
- we don't even try it and fail the load.
-
- XXX We could track the minimum DTV slots allocated in
- all threads. */
- if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
- _dl_signal_error (0, "dlopen", NULL, N_("\
-cannot load any more object with static TLS"));
-
- imap->l_need_tls_init = 0;
-#ifdef SHARED
- /* Update the slot information data for at least the
- generation of the DSO we are allocating data for. */
- _dl_update_slotinfo (imap->l_tls_modid);
-#endif
-
- GL(dl_init_static_tls) (imap);
- assert (imap->l_need_tls_init == 0);
- }
+ if (imap->l_need_tls_init
+ && first_static_tls == new->l_searchlist.r_nlist)
+ first_static_tls = i;
/* We have to bump the generation counter. */
any_tls = true;
@@ -460,6 +440,40 @@ cannot load any more object with static TLS"));
_dl_fatal_printf (N_("\
TLS generation counter wrapped! Please report this."));
+ /* We need a second pass for static tls data, because _dl_update_slotinfo
+ must not be run while calls to _dl_add_to_slotinfo are still pending. */
+ for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
+ {
+ struct link_map *imap = new->l_searchlist.r_list[i];
+
+ if (imap->l_need_tls_init
+ && ! imap->l_init_called
+ && imap->l_tls_blocksize > 0)
+ {
+ /* For static TLS we have to allocate the memory here and
+ now. This includes allocating memory in the DTV. But we
+ cannot change any DTV other than our own. So, if we
+ cannot guarantee that there is room in the DTV we don't
+ even try it and fail the load.
+
+ XXX We could track the minimum DTV slots allocated in
+ all threads. */
+ if (! RTLD_SINGLE_THREAD_P && imap->l_tls_modid > DTV_SURPLUS)
+ _dl_signal_error (0, "dlopen", NULL, N_("\
+cannot load any more object with static TLS"));
+
+ imap->l_need_tls_init = 0;
+#ifdef SHARED
+ /* Update the slot information data for at least the
+ generation of the DSO we are allocating data for. */
+ _dl_update_slotinfo (imap->l_tls_modid);
+#endif
+
+ GL(dl_init_static_tls) (imap);
+ assert (imap->l_need_tls_init == 0);
+ }
+ }
+
/* Run the initializer functions of new objects. */
_dl_init (new, args->argc, args->argv, args->env);
diff --git a/elf/tst-tls19.c b/elf/tst-tls19.c
new file mode 100644
index 0000000..acbc1d6
--- /dev/null
+++ b/elf/tst-tls19.c
@@ -0,0 +1,27 @@
+// BZ 12453
+#include <stdio.h>
+#include <dlfcn.h>
+
+
+static int
+do_test (void)
+{
+ void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (dl == NULL)
+ {
+ printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ());
+ return 1;
+ }
+
+ int (*fn) (void) = dlsym (dl, "foo");
+ if (fn == NULL)
+ {
+ printf("Error obtaining symbol foo\n");
+ return 1;
+ }
+
+ return fn ();
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/tst-tls19mod1.c b/elf/tst-tls19mod1.c
new file mode 100644
index 0000000..2790097
--- /dev/null
+++ b/elf/tst-tls19mod1.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+extern int bar (void);
+extern int baz (void);
+
+int
+foo (void)
+{
+ int v1 = bar ();
+ int v2 = baz ();
+
+ printf ("bar=%d, baz=%d\n", v1, v2);
+
+ return v1 != 666 || v2 != 42;
+}
diff --git a/elf/tst-tls19mod2.c b/elf/tst-tls19mod2.c
new file mode 100644
index 0000000..cae702f
--- /dev/null
+++ b/elf/tst-tls19mod2.c
@@ -0,0 +1,13 @@
+static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666;
+
+void
+setter (int a)
+{
+ tbar = a;
+}
+
+int
+bar (void)
+{
+ return tbar;
+}
diff --git a/elf/tst-tls19mod3.c b/elf/tst-tls19mod3.c
new file mode 100644
index 0000000..e7b2801
--- /dev/null
+++ b/elf/tst-tls19mod3.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42;
+
+void
+setter2 (int a)
+{
+ tbaz = a;
+}
+
+int
+baz (void)
+{
+ printf ("&tbaz=%p\n", &tbaz);
+ return tbaz;
+}