diff options
author | Ulrich Drepper <drepper@redhat.com> | 2002-07-20 01:14:41 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2002-07-20 01:14:41 +0000 |
commit | 739d440d2a748be4b0139d4e5e0a566098abfcec (patch) | |
tree | 395d06a998290892d7d92568471adee8e1e4824f /elf | |
parent | 9df63767d4078fdaf90307f5aa153422f7ec0722 (diff) | |
download | glibc-739d440d2a748be4b0139d4e5e0a566098abfcec.tar.gz |
Update.
2002-07-19 Ulrich Drepper <drepper@redhat.com>
* configure.in: Add test for __thread support in compiler.
* config.h.in: Add HAVE___THREAD.
* Makefile (headers): Remove errno.h, sys/errno.h, and bits/errno.h.
* include/sys/errno.h: Moved to...
* stdlib/sys/errno.h: ...here. New file.
* stdlib/errno.h: New file. Moved from...
* include/errno.h: ...here. Changed into an internal header defining
libc-local things like __set_errno.
* stdlib/Makefile (headers): Add errno.h, sys/errno.h, and
bits/errno.h.
* elf/dl-minimal.c: Include <tls.h>. Define errno as thread-local
variable if USE_TLS && HAVE___THREAD. Don't define __errno_location
either.
* elf/rtld.c (_dl_start): Add code to initialize TLS for ld.so
from...
(_dl_start_final): ...here. Add code to initialize tls elements from
bootstrap_map.
* sysdeps/generic/errno-loc.c: Define errno as thread-local variable
if USE_TLS && HAVE___THREAD.
* sysdeps/generic/bits/errno.h: Remove __set_errno definition.
* sysdeps/mach/hurd/bits/errno.h: Likewise.
* sysdeps/standalone/arm/bits/errno.h: Likewise.
* sysdeps/standalone/bits/errno.h: Likewise.
* sysdeps/unix/bsd/bsd4.4/bits/errno.h: Likewise.
* sysdeps/unix/sysv/aix/bits/errno.h: Likewise.
* sysdeps/unix/sysv/hpux/bits/errno.h: Likewise.
* sysdeps/unix/sysv/linux/bits/errno.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/bits/errno.h: Likewise.
* sysdeps/unix/sysv/linux/mips/bits/errno.h: Likewise.
* sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h: Likewise.
* sysdeps/i386/dl-machine.c (elf_machine_rel) [RTLD_BOOTSTRAP]: Don't
use GL(dl_rtld_map), use map parameter.
* sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise.
* sysdeps/unix/sysv/linux/i386/sysdep.S: Define errno in .tbss if
USE_TLS && HAVE___THREAD.
* sysdeps/unix/sysv/linux/i386/sysdep.h: Unify SETUP_PIC_REG
definitions. If USE_TLS && HAVE___THREAD store errooor value using
TLS code sequence.
* sysdeps/unix/sysv/linux/i386/i686/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/getcwd.c: No real need to restore errno.
* sysdeps/unix/sysv/linux/grantpt.c: Likewise.
* sysdeps/unix/sysv/linux/internal_statvfs.c: Likewise.
* sysdeps/unix/sysv/linux/msgctl.c: Likewise.
* sysdeps/unix/sysv/linux/readv.c: Likewise.
* sysdeps/unix/sysv/linux/writev.c: Likewise.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-minimal.c | 6 | ||||
-rw-r--r-- | elf/rtld.c | 207 |
2 files changed, 120 insertions, 93 deletions
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index 0f284d0a80..a6c1803b34 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -20,6 +20,7 @@ #include <errno.h> #include <limits.h> #include <string.h> +#include <tls.h> #include <unistd.h> #include <sys/mman.h> #include <sys/param.h> @@ -354,8 +355,12 @@ const char INTUSE(_itoa_lower_digits)[16] attribute_hidden = "0123456789abcdef"; + #undef errno /* The 'errno' in ld.so is not exported. */ +#if USE_TLS && HAVE___THREAD +extern __thread int errno attribute_hidden; +#else extern int errno attribute_hidden; int * @@ -363,3 +368,4 @@ __errno_location (void) { return &errno; } +#endif diff --git a/elf/rtld.c b/elf/rtld.c index 9ec250214b..85d8108813 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -130,9 +130,14 @@ _dl_start (void *arg) { struct link_map bootstrap_map; hp_timing_t start_time; -#ifndef HAVE_BUILTIN_MEMSET +#if !defined HAVE_BUILTIN_MEMSET || defined USE_TLS size_t cnt; #endif +#ifdef USE_TLS + ElfW(Ehdr) *ehdr; + ElfW(Phdr) *phdr; + dtv_t initdtv[3]; +#endif /* This #define produces dynamic linking inline functions for bootstrap relocation instead of general-purpose relocation. */ @@ -166,6 +171,97 @@ _dl_start (void *arg) bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); elf_get_dynamic_info (&bootstrap_map); +#if USE_TLS +# ifndef HAVE___THREAD + /* Signal that we have not found TLS data so far. */ + bootstrap_map.l_tls_modid = 0; +# endif + + /* Get the dynamic linkers program header. */ + ehdr = (ElfW(Ehdr) *) bootstrap_map.l_addr; + phdr = (ElfW(Phdr) *) (bootstrap_map.l_addr + ehdr->e_phoff); + for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) + if (phdr[cnt].p_type == PT_TLS) + { + void *tlsblock; + size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align); + + bootstrap_map.l_tls_blocksize = phdr[cnt].p_memsz; + bootstrap_map.l_tls_align = phdr[cnt].p_align; + assert (bootstrap_map.l_tls_blocksize != 0); + bootstrap_map.l_tls_initimage_size = phdr[cnt].p_filesz; + bootstrap_map.l_tls_initimage = (void *) (bootstrap_map.l_addr + + phdr[cnt].p_offset); + + /* We can now allocate the initial TLS block. This can happen + on the stack. We'll get the final memory later when we + know all about the various objects loaded at startup + time. */ +# if TLS_TCB_AT_TP + tlsblock = alloca (roundup (bootstrap_map.l_tls_blocksize, + TLS_INIT_TCB_ALIGN) + + TLS_INIT_TCB_SIZE + + max_align); +# elif TLS_DTV_AT_TP + tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, + bootstrap_map.l_tls_align) + + bootstrap_map.l_tls_blocksize + + max_align); +# else + /* In case a model with a different layout for the TCB and DTV + is defined add another #elif here and in the following #ifs. */ +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + /* Align the TLS block. */ + tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) + & ~(max_align - 1)); + + /* Initialize the dtv. [0] is the length, [1] the generation + counter. */ + initdtv[0].counter = 1; + initdtv[1].counter = 0; + + /* Initialize the TLS block. */ +# if TLS_TCB_AT_TP + initdtv[2].pointer = tlsblock; +# elif TLS_DTV_AT_TP + bootstrap_map.l_tls_offset = roundup (TLS_INIT_TCB_SIZE, + bootstrap_map.l_tls_align); + initdtv[2].pointer = (char *) tlsblock + bootstrap_map.l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + memset (__mempcpy (initdtv[2].pointer, bootstrap_map.l_tls_initimage, + bootstrap_map.l_tls_initimage_size), + '\0', (bootstrap_map.l_tls_blocksize + - bootstrap_map.l_tls_initimage_size)); + + /* Install the pointer to the dtv. */ + + /* Initialize the thread pointer. */ +# if TLS_TCB_AT_TP + bootstrap_map.l_tls_offset + = roundup (bootstrap_map.l_tls_blocksize, TLS_INIT_TCB_ALIGN); + + INSTALL_DTV ((char *) tlsblock + bootstrap_map.l_tls_offset, + initdtv); + + TLS_INIT_TP ((char *) tlsblock + bootstrap_map.l_tls_offset); +# elif TLS_DTV_AT_TP + INSTALL_DTV (tlsblock, initdtv); + TLS_INIT_TP (tlsblock); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* So far this is module number one. */ + bootstrap_map.l_tls_modid = 1; + + /* There can only be one PT_TLS entry. */ + break; + } +#endif /* use TLS */ + #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info); #endif @@ -220,12 +316,6 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p, ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr))); extern char _begin[] attribute_hidden; extern char _end[] attribute_hidden; -#ifdef USE_TLS - ElfW(Ehdr) *ehdr; - ElfW(Phdr) *phdr; - size_t cnt; - dtv_t initdtv[3]; -#endif if (HP_TIMING_AVAIL) { @@ -247,96 +337,27 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p, GL(dl_rtld_map).l_mach = bootstrap_map_p->l_mach; GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin; GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; - -#if HP_TIMING_AVAIL - HP_TIMING_NOW (GL(dl_cpuclock_offset)); -#endif - + /* Copy the TLS related data if necessary. */ #if USE_TLS - /* Get the dynamic linkers program header. */ - ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start; - phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start + ehdr->e_phoff); - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) - if (phdr[cnt].p_type == PT_TLS) - { - void *tlsblock; - size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align); - - GL(dl_rtld_map).l_tls_blocksize = phdr[cnt].p_memsz; - GL(dl_rtld_map).l_tls_align = phdr[cnt].p_align; - assert (GL(dl_rtld_map).l_tls_blocksize != 0); - GL(dl_rtld_map).l_tls_initimage_size = phdr[cnt].p_filesz; - GL(dl_rtld_map).l_tls_initimage = (void *) (GL(dl_rtld_map).l_map_start - + phdr[cnt].p_offset); - - /* We can now allocate the initial TLS block. This can happen - on the stack. We'll get the final memory later when we - know all about the various objects loaded at startup - time. */ -# if TLS_TCB_AT_TP - tlsblock = alloca (roundup (GL(dl_rtld_map).l_tls_blocksize, - TLS_INIT_TCB_ALIGN) - + TLS_INIT_TCB_SIZE - + max_align); -# elif TLS_DTV_AT_TP - tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, - GL(dl_rtld_map).l_tls_align) - + GL(dl_rtld_map).l_tls_blocksize - + max_align); -# else - /* In case a model with a different layout for the TCB and DTV - is defined add another #elif here and in the following #ifs. */ -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -# endif - /* Align the TLS block. */ - tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) - & ~(max_align - 1)); - - /* Initialize the dtv. [0] is the length, [1] the generation - counter. */ - initdtv[0].counter = 1; - initdtv[1].counter = 0; - - /* Initialize the TLS block. */ -# if TLS_TCB_AT_TP - initdtv[2].pointer = tlsblock; -# elif TLS_DTV_AT_TP - GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE, - GL(dl_rtld_map).l_tls_align); - initdtv[2].pointer = (char *) tlsblock + GL(dl_rtld_map).l_tls_offset; -# else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -# endif - memset (__mempcpy (initdtv[1].pointer, GL(dl_rtld_map).l_tls_initimage, - GL(dl_rtld_map).l_tls_initimage_size), - '\0', (GL(dl_rtld_map).l_tls_blocksize - - GL(dl_rtld_map).l_tls_initimage_size)); - - /* Install the pointer to the dtv. */ - - /* Initialize the thread pointer. */ -# if TLS_TCB_AT_TP - GL(dl_rtld_map).l_tls_offset - = roundup (GL(dl_rtld_map).l_tls_blocksize, TLS_INIT_TCB_ALIGN); - - INSTALL_DTV ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset, - initdtv); - - TLS_INIT_TP ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset); -# elif TLS_DTV_AT_TP - INSTALL_DTV (tlsblock, initdtv); - TLS_INIT_TP (tlsblock); +# ifdef HAVE___THREAD + assert (bootstrap_map_p->l_tls_modid != 0); # else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" + if (bootstrap_map_p->l_tls_modid != 0) # endif + { + GL(dl_rtld_map).l_tls_blocksize = bootstrap_map_p->l_tls_blocksize; + GL(dl_rtld_map).l_tls_align = bootstrap_map_p->l_tls_align; + GL(dl_rtld_map).l_tls_initimage_size + = bootstrap_map_p->l_tls_initimage_size; + GL(dl_rtld_map).l_tls_initimage = bootstrap_map_p->l_tls_initimage; + GL(dl_rtld_map).l_tls_offset = bootstrap_map_p->l_tls_offset; + GL(dl_rtld_map).l_tls_modid = 1; + } +#endif - /* So far this is module number one. */ - GL(dl_rtld_map).l_tls_modid = 1; - - /* There can only be one PT_TLS entry. */ - break; - } -#endif /* use TLS */ +#if HP_TIMING_AVAIL + HP_TIMING_NOW (GL(dl_cpuclock_offset)); +#endif /* Call the OS-dependent function to set up life so we can do things like file access. It will call `dl_main' (below) to do all the real work |