summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-12-04 12:30:40 +0000
committerRoland McGrath <roland@gnu.org>2002-12-04 12:30:40 +0000
commit216455bc284f57dbaf939059f815935e23456c02 (patch)
tree3ae488a18ace0ebe18d7923eae29ae65a3badada /sysdeps
parent68dc80ca28a192d686b3190373df8468b4ce5cb8 (diff)
downloadglibc-216455bc284f57dbaf939059f815935e23456c02.tar.gz
* sysdeps/generic/ldsodefs.h (struct rtld_global): Move all [USE_TLS]
members to the end, so a libpthread compiled with !USE_TLS will still find other members properly. * sysdeps/i386/i486/bits/string.h (__strcpy_g): Add dummy output operand for DEST memory. Fix dummy input operand to use SRC. Reported by Davin McCall <davmac@ozonline.com.au>. * sysdeps/generic/libc-tls.c (__libc_setup_tls): Account for TCB alignment when initializing the DTV entry. * elf/dl-load.c (_dl_map_object_from_fd): If we hit a TLS segment when TLS has not been set up, try to set it up if we can. * elf/tst-tls4.c: Revert last change. * elf/tst-tls5.c: Likewise. * elf/tst-tls6.c: Likewise. * elf/tst-tls7.c: Likewise. * elf/tst-tls8.c: Likewise. * elf/tst-tls9.c: Likewise. * sysdeps/generic/dl-tls.c [SHARED] (_dl_tls_setup): New function. * sysdeps/generic/ldsodefs.h: Declare it. * elf/Versions (ld: GLIBC_PRIVATE): Add it. * sysdeps/generic/libc-tls.c (init_slotinfo): New static inline function, broken out of __libc_setup_tls. (init_static_tls): Likewise. (__libc_setup_tls): Call them. (_dl_tls_setup): New function, uses new subroutines. * elf/dl-close.c (free_slotinfo): Make argument pointer to pointer. Clear the pointer when returning true. (libc_freeres_fn) [SHARED]: If GL(dl_initial_dtv) is null, free the first element of the slotinfo list too. * sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Define only if [SHARED]. * sysdeps/generic/ldsodefs.h (_dl_next_tls_modid): Declare as hidden. (_dl_determine_tlsoffset): Likewise. * elf/rtld.c (_dl_initial_error_catch_tsd): Renamed from startup_error_tsd, made global. (dl_main): Update initialization. * elf/dl-tsd.c: Likewise. * sysdeps/generic/ldsodefs.h: Declare it.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-tls.c36
-rw-r--r--sysdeps/generic/libc-tls.c85
-rw-r--r--sysdeps/i386/i486/bits/string.h5
3 files changed, 96 insertions, 30 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 850df8d76f..550de56530 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -110,6 +110,7 @@ _dl_next_tls_modid (void)
return result;
}
+# ifdef SHARED
void
internal_function
@@ -204,6 +205,41 @@ _dl_determine_tlsoffset (void)
}
+/* This is called only when the data structure setup was skipped at startup,
+ when there was no need for it then. Now we have dynamically loaded
+ something needing TLS, or libpthread needs it. */
+int
+internal_function
+_dl_tls_setup (void)
+{
+ assert (GL(dl_tls_dtv_slotinfo_list) == NULL);
+ assert (GL(dl_tls_max_dtv_idx) == 0);
+
+ const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS;
+
+ GL(dl_tls_dtv_slotinfo_list) =
+ malloc (sizeof (struct dtv_slotinfo_list)
+ + nelem * sizeof (struct dtv_slotinfo));
+ if (GL(dl_tls_dtv_slotinfo_list) == NULL)
+ return -1;
+
+ memset (GL(dl_tls_dtv_slotinfo_list)->slotinfo, '\0',
+ nelem * sizeof (struct dtv_slotinfo));
+ GL(dl_tls_dtv_slotinfo_list)->len = nelem;
+ GL(dl_tls_dtv_slotinfo_list)->next = NULL;
+
+ /* Number of elements in the static TLS block. It can't be zero
+ because of various assumptions. The one element is null. */
+ GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1;
+
+ /* This initializes more variables for us. */
+ _dl_determine_tlsoffset ();
+
+ return 0;
+}
+rtld_hidden_def (_dl_tls_setup)
+# endif
+
static void *
internal_function
allocate_dtv (void *result)
diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c
index a6a0504f44..756a2bf57c 100644
--- a/sysdeps/generic/libc-tls.c
+++ b/sysdeps/generic/libc-tls.c
@@ -74,6 +74,35 @@ size_t _dl_tls_generation;
TLS_INIT_HELPER
#endif
+static inline void
+init_slotinfo (void)
+{
+ /* Create the slotinfo list. */
+ static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
+ - (char *) &static_slotinfo.si.slotinfo[0])
+ / sizeof static_slotinfo.si.slotinfo[0]);
+ // static_slotinfo.si.next = NULL; already zero
+
+ /* The slotinfo list. Will be extended by the code doing dynamic
+ linking. */
+ GL(dl_tls_max_dtv_idx) = 1;
+ GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
+}
+
+static inline void
+init_static_tls (size_t memsz, size_t align)
+{
+ /* That is the size of the TLS memory for this object. The initialized
+ value of _dl_tls_static_size is provided by dl-open.c to request some
+ surplus that permits dynamic loading of modules with IE-model TLS. */
+ GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
+ TLS_TCB_ALIGN);
+ GL(dl_tls_static_used) = memsz;
+ /* The alignment requirement for the static TLS block. */
+ GL(dl_tls_static_align) = align;
+ /* Number of elements in the static TLS block. */
+ GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
+}
void
__libc_setup_tls (size_t tcbsize, size_t tcbalign)
@@ -117,8 +146,8 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
to request some surplus that permits dynamic loading of modules with
IE-model TLS. */
# if TLS_TCB_AT_TP
- tlsblock = __sbrk (roundup (memsz, tcbalign) + tcbsize + max_align
- + GL(dl_tls_static_size));
+ tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
+ tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
# elif TLS_DTV_AT_TP
tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align
+ GL(dl_tls_static_size));
@@ -138,10 +167,13 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
/* Initialize the TLS block. */
# if TLS_TCB_AT_TP
- static_dtv[2].pointer = tlsblock;
+ static_dtv[2].pointer = ((char *) tlsblock + tcb_offset
+ - roundup (memsz, align));
+ static_map.l_tls_offset = roundup (memsz, align);
# elif TLS_DTV_AT_TP
tcb_offset = roundup (tcbsize, align);
static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
+ static_map.l_tls_offset = tcb_offset;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
@@ -152,8 +184,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
/* Initialize the thread pointer. */
# if TLS_TCB_AT_TP
- tcb_offset = roundup (memsz, tcbalign);
-
INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
@@ -171,39 +201,38 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
static_map.l_tls_blocksize = memsz;
static_map.l_tls_initimage = initimage;
static_map.l_tls_initimage_size = filesz;
- static_map.l_tls_offset = tcb_offset;
static_map.l_type = lt_executable;
static_map.l_tls_modid = 1;
- /* Create the slotinfo list. */
- static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
- - (char *) &static_slotinfo.si.slotinfo[0])
- / sizeof static_slotinfo.si.slotinfo[0]);
- // static_slotinfo.si.next = NULL; already zero
-
- static_slotinfo.si.slotinfo[1].gen = 0;
+ init_slotinfo ();
+ // static_slotinfo.si.slotinfo[1].gen = 0; already zero
static_slotinfo.si.slotinfo[1].map = &static_map;
- /* The slotinfo list. Will be extended by the code doing dynamic
- linking. */
- GL(dl_tls_max_dtv_idx) = 1;
- GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
-
memsz = roundup (memsz, align ?: 1);
+
# if TLS_TCB_AT_TP
memsz += tcbsize;
# endif
- /* That is the size of the TLS memory for this object. The initialized
- value of _dl_tls_static_size is provided by dl-open.c to request some
- surplus that permits dynamic loading of modules with IE-model TLS. */
- GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
- TLS_TCB_ALIGN);
- GL(dl_tls_static_used) = memsz;
- /* The alignment requirement for the static TLS block. */
- GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align);
- /* Number of elements in the static TLS block. */
- GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
+ init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
+}
+
+/* This is called only when the data structure setup was skipped at startup,
+ when there was no need for it then. Now we have dynamically loaded
+ something needing TLS, or libpthread needs it. */
+int
+internal_function
+_dl_tls_setup (void)
+{
+ init_slotinfo ();
+ init_static_tls (
+# if TLS_TCB_AT_TP
+ TLS_TCB_SIZE,
+# else
+ 0,
+# endif
+ TLS_TCB_ALIGN);
+ return 0;
}
diff --git a/sysdeps/i386/i486/bits/string.h b/sysdeps/i386/i486/bits/string.h
index cc8594ff36..3a2ee2f6d7 100644
--- a/sysdeps/i386/i486/bits/string.h
+++ b/sysdeps/i386/i486/bits/string.h
@@ -636,9 +636,10 @@ __strcpy_g (char *__dest, __const char *__src)
"leal 1(%1),%1\n\t"
"testb %b2,%b2\n\t"
"jne 1b"
- : "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy)
+ : "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy),
+ "=m" ( *(struct { char __x[0xfffffff]; } *)__dest)
: "0" (__src), "1" (__tmp),
- "m" ( *(struct { char __x[0xfffffff]; } *)__dest)
+ "m" ( *(struct { char __x[0xfffffff]; } *)__src)
: "cc");
return __dest;
}