+2014-02-25 Ulrich Drepper <drepper@gmail.com>
+ Carlos O'Donell <carlos@redhat.com>
+
+ [BZ #16613]
+ * elf/dl-tls.c (_dl_count_modids): New function.
+ * sysdeps/generic/ldsodefs.h: Declare _dl_count_modids.
+ * elf/rtld.c (dl_main): Call _dl_count_modids to track TLS usage in
+ audit library and increment generation counter.
+ (_dl_allocate_tls_init): Add assertion to check TLS generation count.
+ * elf/tst-audit9.c: New file.
+ * elf/tst-auditmod9a.c: New file.
+ * elf/tst-auditmod9b.c: New file.
+ * elf/Makefile: Add rules to build and run tst-audit9.
+
2014-02-25 Florian Weimer <fweimer@redhat.com>
[BZ #15347]
* The following bugs are resolved with this release:
- 15347, 15804, 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611.
+ 15347, 15804, 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611,
+ 16613.
* The am33 port, which had not worked for several years, has been removed
from ports.
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 tst-null-argv \
order2mod1 order2mod2 order2mod3 order2mod4 \
tst-unique1mod1 tst-unique1mod2 \
tst-unique2mod1 tst-unique2mod2 \
+ tst-auditmod9a tst-auditmod9b \
tst-unique3lib tst-unique3lib2 \
tst-unique4lib \
tst-initordera1 tst-initorderb1 \
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.
$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.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
}
+size_t
+internal_function
+_dl_count_modids (void)
+{
+ /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
+ we fail to load a module and unload it leaving a gap. If we don't
+ have gaps then the number of modids is the current maximum so
+ return that. */
+ if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
+ return GL(dl_tls_max_dtv_idx);
+
+ /* We have gaps and are forced to count the non-NULL entries. */
+ 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
/* 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
}
}
+ /* 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. */
_dl_start_profile ();
}
- 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
--- /dev/null
+#include <dlfcn.h>
+
+int main(void)
+{
+ void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
+ int (*fp)(void) = dlsym(h, "f");
+ return fp() - 1;
+}
--- /dev/null
+#include <stdint.h>
+
+__thread int var;
+
+unsigned int
+la_version (unsigned int v)
+{
+ return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ ++var;
+}
--- /dev/null
+__thread int a;
+
+int f(void)
+{
+ return ++a;
+}
/* 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;