From 739d440d2a748be4b0139d4e5e0a566098abfcec Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 20 Jul 2002 01:14:41 +0000 Subject: Update. 2002-07-19 Ulrich Drepper * 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 . 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. --- elf/rtld.c | 207 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 114 insertions(+), 93 deletions(-) (limited to 'elf/rtld.c') diff --git a/elf/rtld.c b/elf/rtld.c index 9ec2502..85d8108 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 -- cgit v1.1