aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile7
-rw-r--r--elf/dl-close.c51
-rw-r--r--elf/dl-reloc.c4
-rw-r--r--elf/tst-tls8.c8
-rw-r--r--elf/tst-tlsmod13.c14
-rw-r--r--elf/tst-tlsmod13a.c16
6 files changed, 91 insertions, 9 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 3838a11..c557bd8 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -145,7 +145,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
neededtest3 neededtest4 unload2 lateglobal initfirst global \
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-tls10 tst-tls11 tst-tls12 tst-tls13
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@@ -168,6 +168,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \
tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \
tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \
+ tst-tlsmod13 tst-tlsmod13a \
circlemod1 circlemod1a circlemod2 circlemod2a \
circlemod3 circlemod3a \
reldep8mod1 reldep8mod2 reldep8mod3 \
@@ -383,6 +384,7 @@ $(objpfx)tst-tlsmod3.so: $(objpfx)tst-tlsmod2.so
$(objpfx)tst-tlsmod8.so: $(objpfx)tst-tlsmod7.so
$(objpfx)tst-tlsmod10.so: $(objpfx)tst-tlsmod9.so
$(objpfx)tst-tlsmod12.so: $(objpfx)tst-tlsmod11.so
+$(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
@@ -590,6 +592,9 @@ $(objpfx)tst-tls11: $(objpfx)tst-tlsmod10.so
$(objpfx)tst-tls12: $(objpfx)tst-tlsmod12.so
+$(objpfx)tst-tls13: $(libdl)
+$(objpfx)tst-tls13.out: $(objpfx)tst-tlsmod13a.so
+
ifdef libdl
$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 78b143f..b482e89 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -321,8 +321,9 @@ _dl_close (void *_map)
_dl_debug_state ();
#ifdef USE_TLS
- size_t tls_free_start, tls_free_end;
- tls_free_start = tls_free_end = GL(dl_tls_static_used);
+ size_t tls_free_start;
+ size_t tls_free_end;
+ tls_free_start = tls_free_end = NO_TLS_OFFSET;
#endif
/* Check each element of the search list to see if all references to
@@ -371,9 +372,50 @@ _dl_close (void *_map)
this search list, going in either direction. When the
whole chunk is at the end of the used area then we can
reclaim it. */
+# if TLS_TCB_AT_TP
+ if (tls_free_start == NO_TLS_OFFSET
+ || (size_t) imap->l_tls_offset == tls_free_start)
+ {
+ /* Extend the contiguous chunk being reclaimed. */
+ tls_free_start
+ = imap->l_tls_offset - imap->l_tls_blocksize;
+
+ if (tls_free_end == NO_TLS_OFFSET)
+ tls_free_end = imap->l_tls_offset;
+ }
+ else if (imap->l_tls_offset - imap->l_tls_blocksize
+ == tls_free_end)
+ /* Extend the chunk backwards. */
+ tls_free_end = imap->l_tls_offset;
+ else
+ {
+ /* This isn't contiguous with the last chunk freed.
+ One of them will be leaked unless we can free
+ one block right away. */
+ if (tls_free_end == GL(dl_tls_static_used))
+ {
+ GL(dl_tls_static_used) = tls_free_start;
+ tls_free_end = imap->l_tls_offset;
+ tls_free_start
+ = tls_free_end - imap->l_tls_blocksize;
+ }
+ else if ((size_t) imap->l_tls_offset
+ == GL(dl_tls_static_used))
+ GL(dl_tls_static_used)
+ = imap->l_tls_offset - imap->l_tls_blocksize;
+ else if (tls_free_end < (size_t) imap->l_tls_offset)
+ {
+ /* We pick the later block. It has a chance to
+ be freed. */
+ tls_free_end = imap->l_tls_offset;
+ tls_free_start
+ = tls_free_end - imap->l_tls_blocksize;
+ }
+ }
+# elif TLS_DTV_AT_TP
if ((size_t) imap->l_tls_offset == tls_free_end)
/* Extend the contiguous chunk being reclaimed. */
- tls_free_end += imap->l_tls_blocksize;
+ tls_free_end -= imap->l_tls_blocksize;
else if (imap->l_tls_offset + imap->l_tls_blocksize
== tls_free_start)
/* Extend the chunk backwards. */
@@ -387,6 +429,9 @@ _dl_close (void *_map)
tls_free_start = imap->l_tls_offset;
tls_free_end = tls_free_start + imap->l_tls_blocksize;
}
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
}
}
#endif
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index c7f1f34..6165fe4 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -45,7 +45,9 @@ void
internal_function __attribute_noinline__
_dl_allocate_static_tls (struct link_map *map)
{
- size_t offset, used, check;
+ size_t offset;
+ size_t used;
+ size_t check;
# if TLS_TCB_AT_TP
offset = roundup (GL(dl_tls_static_used) + map->l_tls_blocksize,
diff --git a/elf/tst-tls8.c b/elf/tst-tls8.c
index e300bc5..97b4a25 100644
--- a/elf/tst-tls8.c
+++ b/elf/tst-tls8.c
@@ -19,8 +19,8 @@ do_test (void)
void *h1;
void *h2;
int i;
- int modid1 = -1;
- int modid2 = -1;
+ size_t modid1 = (size_t) -1;
+ size_t modid2 = (size_t) -1;
int *bazp;
for (i = 0; i < 10; ++i)
@@ -35,7 +35,7 @@ do_test (void)
/* Dirty test code here: we peek into a private data structure.
We make sure that the module gets assigned the same ID every
time. The value of the first round is used. */
- if (modid1 == -1)
+ if (modid1 == (size_t) -1)
modid1 = ((struct link_map *) h1)->l_tls_modid;
else if (((struct link_map *) h1)->l_tls_modid != modid1)
{
@@ -65,7 +65,7 @@ do_test (void)
/* Dirty test code here: we peek into a private data structure.
We make sure that the module gets assigned the same ID every
time. The value of the first round is used. */
- if (modid2 == -1)
+ if (modid2 == (size_t) -1)
modid2 = ((struct link_map *) h1)->l_tls_modid;
else if (((struct link_map *) h1)->l_tls_modid != modid2)
{
diff --git a/elf/tst-tlsmod13.c b/elf/tst-tlsmod13.c
new file mode 100644
index 0000000..beca89f
--- /dev/null
+++ b/elf/tst-tlsmod13.c
@@ -0,0 +1,14 @@
+#include <tls.h>
+
+#if defined USE_TLS && defined HAVE___THREAD \
+ && defined HAVE_TLS_MODEL_ATTRIBUTE
+__thread int a[2] __attribute__ ((tls_model ("initial-exec")));
+#else
+int a[2];
+#endif
+
+int
+foo (void)
+{
+ return a[0];
+}
diff --git a/elf/tst-tlsmod13a.c b/elf/tst-tlsmod13a.c
new file mode 100644
index 0000000..14b12b0
--- /dev/null
+++ b/elf/tst-tlsmod13a.c
@@ -0,0 +1,16 @@
+#include <tls.h>
+
+#if defined USE_TLS && defined HAVE___THREAD \
+ && defined HAVE_TLS_MODEL_ATTRIBUTE
+__thread int b[2] __attribute__ ((tls_model ("initial-exec")));
+#else
+int b[2];
+#endif
+
+extern int foo (void);
+
+int
+bar (void)
+{
+ return foo () + b[0];
+}