# # Patch provided by Ulrich Drepper in BZ#919562. # # Patch has not been sent upstream. # # 2013-03-08 Ulrich Drepper # # * elf/rtld.c (dl_main): Correctly determine when the application # required DSOs with TLS and bump the generation counter in that # case. The current condition does not account for an audit # module using TLS. # * elf/dl-tls.c (_dl_count_modids): New function. # (_dl_allocate_tls_init): Add assertion to check TLS # generation. # * sysdeps/generic/ldsodefs.h: Declare _dl_count_modids. # * elf/Makefile: Add rules to build and run tst-audit9. # * elf/tst-audit9.c: New file. # * elf/tst-auditmod9a.c: New file. # * elf/tst-auditmod9b.c: New file. # diff -urN glibc-2.17-c758a686/elf/dl-tls.c glibc-2.17-c758a686/elf/dl-tls.c --- glibc-2.17-c758a686/elf/dl-tls.c 2013-04-24 16:06:10.410756438 -0400 +++ glibc-2.17-c758a686/elf/dl-tls.c 2013-04-24 16:06:49.092604707 -0400 @@ -109,6 +109,28 @@ } +size_t +internal_function +_dl_count_modids (void) +{ + if (! __builtin_expect (GL(dl_tls_dtv_gaps), true)) + return GL(dl_tls_max_dtv_idx); + + size_t n = 0; + struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); + while (runp != NULL) + { + for (size_t i = 0; i < runp->len; ++i) + if (runp->slotinfo[i].map != NULL) + ++n; + + runp = runp->next; + } + + return n; +} + + #ifdef SHARED void internal_function @@ -411,6 +433,7 @@ /* Keep track of the maximum generation number. This might not be the generation counter. */ + assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation)); maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); if (map->l_tls_offset == NO_TLS_OFFSET diff -urN glibc-2.17-c758a686/elf/Makefile glibc-2.17-c758a686/elf/Makefile --- glibc-2.17-c758a686/elf/Makefile 2013-04-24 16:06:10.408756448 -0400 +++ glibc-2.17-c758a686/elf/Makefile 2013-04-24 16:07:29.475457962 -0400 @@ -198,7 +200,7 @@ tst-dlmodcount tst-dlopenrpath tst-deep1 \ tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ - tst-audit1 tst-audit2 tst-audit8 \ + tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ tst-stackguard1 tst-addr1 tst-thrlock \ tst-unique1 tst-unique2 tst-unique3 tst-unique4 \ tst-initorder tst-initorder2 tst-relsort1 @@ -251,7 +253,8 @@ unload8mod1 unload8mod1x unload8mod2 unload8mod3 \ order2mod1 order2mod2 order2mod3 order2mod4 \ tst-unique1mod1 tst-unique1mod2 \ - tst-unique2mod1 tst-unique2mod2 \ + tst-unique2mod1 tst-unique2mod2 \ + tst-auditmod9a tst-auditmod9b \ tst-unique3lib tst-unique3lib2 \ tst-unique4lib \ tst-initordera1 tst-initorderb1 \ @@ -574,6 +577,8 @@ ifuncmod1.so-no-z-defs = yes ifuncmod5.so-no-z-defs = yes ifuncmod6.so-no-z-defs = yes +tst-auditmod9a.so-no-z-defs = yes +tst-auditmod9b.so-no-z-defs = yes ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -1015,6 +1020,10 @@ $(objpfx)tst-audit7.out: $(objpfx)tst-auditmod7b.so tst-audit7-ENV = LD_AUDIT=$(objpfx)tst-auditmod7b.so +$(objpfx)tst-audit9: $(libdl) +$(objpfx)tst-audit9.out: $(objpfx)tst-auditmod9a.so $(objpfx)tst-auditmod9b.so +tst-audit9-ENV = LD_AUDIT=$(objpfx)tst-auditmod9a.so + $(objpfx)tst-audit8: $(common-objpfx)math/libm.so $(objpfx)tst-audit8.out: $(objpfx)tst-auditmod1.so tst-audit8-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so diff -urN glibc-2.17-c758a686/elf/rtld.c glibc-2.17-c758a686/elf/rtld.c --- glibc-2.17-c758a686/elf/rtld.c 2013-04-24 16:06:10.410756438 -0400 +++ glibc-2.17-c758a686/elf/rtld.c 2013-04-24 16:06:49.096604693 -0400 @@ -1637,6 +1637,10 @@ } } + /* Keep track of the currently loaded modules to count how many + non-audit modules which use TLS are loaded. */ + size_t count_modids = _dl_count_modids (); + /* Set up debugging before the debugger is notified for the first time. */ #ifdef ELF_MACHINE_DEBUG_SETUP /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ @@ -2281,7 +2285,8 @@ # define NONTLS_INIT_TP do { } while (0) #endif - if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) + if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) + || count_modids != _dl_count_modids ()) ++GL(dl_tls_generation); /* Now that we have completed relocation, the initializer data diff -urN glibc-2.17-c758a686/elf/tst-audit9.c glibc-2.17-c758a686/elf/tst-audit9.c --- glibc-2.17-c758a686/elf/tst-audit9.c 1969-12-31 19:00:00.000000000 -0500 +++ glibc-2.17-c758a686/elf/tst-audit9.c 2013-04-24 16:06:49.096604693 -0400 @@ -0,0 +1,8 @@ +#include + +int main(void) +{ + void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY); + int (*fp)(void) = dlsym(h, "f"); + return fp() - 1; +} diff -urN glibc-2.17-c758a686/elf/tst-auditmod9a.c glibc-2.17-c758a686/elf/tst-auditmod9a.c --- glibc-2.17-c758a686/elf/tst-auditmod9a.c 1969-12-31 19:00:00.000000000 -0500 +++ glibc-2.17-c758a686/elf/tst-auditmod9a.c 2013-04-24 16:06:49.097604689 -0400 @@ -0,0 +1,16 @@ +#include + +__thread int var; + +unsigned int +la_version (unsigned int v) +{ + return v; +} + +void +la_activity (uintptr_t *cookie, unsigned int flag) +{ + ++var; +} + diff -urN glibc-2.17-c758a686/elf/tst-auditmod9b.c glibc-2.17-c758a686/elf/tst-auditmod9b.c --- glibc-2.17-c758a686/elf/tst-auditmod9b.c 1969-12-31 19:00:00.000000000 -0500 +++ glibc-2.17-c758a686/elf/tst-auditmod9b.c 2013-04-24 16:06:49.097604689 -0400 @@ -0,0 +1,6 @@ +__thread int a; + +int f(void) +{ + return ++a; +} diff -urN glibc-2.17-c758a686/sysdeps/generic/ldsodefs.h glibc-2.17-c758a686/sysdeps/generic/ldsodefs.h --- glibc-2.17-c758a686/sysdeps/generic/ldsodefs.h 2013-04-24 16:06:10.545755798 -0400 +++ glibc-2.17-c758a686/sysdeps/generic/ldsodefs.h 2013-04-24 16:06:49.098604686 -0400 @@ -1031,6 +1031,9 @@ /* Determine next available module ID. */ extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden; +/* Count the modules with TLS segments. */ +extern size_t _dl_count_modids (void) internal_function attribute_hidden; + /* Calculate offset of the TLS blocks in the static TLS block. */ extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden;