mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
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.
This commit is contained in:
207
elf/rtld.c
207
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,97 +337,28 @@ _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;
|
||||
/* Copy the TLS related data if necessary. */
|
||||
#if USE_TLS
|
||||
# ifdef HAVE___THREAD
|
||||
assert (bootstrap_map_p->l_tls_modid != 0);
|
||||
# else
|
||||
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
|
||||
|
||||
#if HP_TIMING_AVAIL
|
||||
HP_TIMING_NOW (GL(dl_cpuclock_offset));
|
||||
#endif
|
||||
|
||||
#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);
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# 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 */
|
||||
|
||||
/* 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
|
||||
of the dynamic linker, and then unwind our frame and run the user
|
||||
|
Reference in New Issue
Block a user