diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 7 | ||||
-rw-r--r-- | elf/dl-close.c | 51 | ||||
-rw-r--r-- | elf/dl-reloc.c | 4 | ||||
-rw-r--r-- | elf/tst-tls8.c | 8 | ||||
-rw-r--r-- | elf/tst-tlsmod13.c | 14 | ||||
-rw-r--r-- | elf/tst-tlsmod13a.c | 16 |
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]; +} |