mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-22 13:00:06 +00:00
Update.
* elf/rtld.c (_dl_start): Fill TLS values in link map for rtld. * include/link.h (struct link_map): Add various members for TLS information. * sysdeps/generic/ldsodefs.h (struct rtld_global): Remove _rtld_tlsoffset, add _dl_initimage_list. * sysdeps/i386/dl-lookupcfg.h: New file. * sysdeps/i386/dl-machine.h (elf_machine_rel): Implement missing TLS relocation. When using TLS we now use RESOLVE_MAP. (elf_machine_rela): Use RESOLVE_MAP instead of RESOLVE_MAP if TLS is used. * sysdeps/generic/dl-cache.c (_dl_cache_libcmp): Mark as possibly unused.
This commit is contained in:
parent
535b764df5
commit
5d6feea8f5
14
ChangeLog
14
ChangeLog
@ -1,5 +1,19 @@
|
|||||||
2002-02-04 Ulrich Drepper <drepper@redhat.com>
|
2002-02-04 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* elf/rtld.c (_dl_start): Fill TLS values in link map for rtld.
|
||||||
|
* include/link.h (struct link_map): Add various members for TLS
|
||||||
|
information.
|
||||||
|
* sysdeps/generic/ldsodefs.h (struct rtld_global): Remove
|
||||||
|
_rtld_tlsoffset, add _dl_initimage_list.
|
||||||
|
* sysdeps/i386/dl-lookupcfg.h: New file.
|
||||||
|
* sysdeps/i386/dl-machine.h (elf_machine_rel): Implement missing
|
||||||
|
TLS relocation. When using TLS we now use RESOLVE_MAP.
|
||||||
|
(elf_machine_rela): Use RESOLVE_MAP instead of RESOLVE_MAP if TLS
|
||||||
|
is used.
|
||||||
|
|
||||||
|
* sysdeps/generic/dl-cache.c (_dl_cache_libcmp): Mark as possibly
|
||||||
|
unused.
|
||||||
|
|
||||||
* elf/rtld.c (_dl_start_final): Allocate TLS and initialize
|
* elf/rtld.c (_dl_start_final): Allocate TLS and initialize
|
||||||
thread-pointer as soon as possible.
|
thread-pointer as soon as possible.
|
||||||
* sysdeps/generic/ldsodefs.h: Include <tls.h>. Define first TLS
|
* sysdeps/generic/ldsodefs.h: Include <tls.h>. Define first TLS
|
||||||
|
39
elf/rtld.c
39
elf/rtld.c
@ -222,10 +222,6 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
|||||||
ElfW(Ehdr) *ehdr;
|
ElfW(Ehdr) *ehdr;
|
||||||
ElfW(Phdr) *phdr;
|
ElfW(Phdr) *phdr;
|
||||||
size_t cnt;
|
size_t cnt;
|
||||||
size_t tlssize = 0;
|
|
||||||
size_t tlsimagesize = 0;
|
|
||||||
const void *tlsimage = NULL;
|
|
||||||
void *tlsblock = NULL;
|
|
||||||
dtv_t initdtv[2];
|
dtv_t initdtv[2];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -261,23 +257,26 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
|||||||
for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
|
for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
|
||||||
if (phdr[cnt].p_type == PT_TLS)
|
if (phdr[cnt].p_type == PT_TLS)
|
||||||
{
|
{
|
||||||
|
void *tlsblock;
|
||||||
size_t align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
|
size_t align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
|
||||||
|
|
||||||
tlssize = phdr[cnt].p_memsz;
|
GL(dl_rtld_map).l_tls_blocksize = phdr[cnt].p_memsz;
|
||||||
tlsimagesize = phdr[cnt].p_filesz;
|
GL(dl_rtld_map).l_tls_initimage_size = phdr[cnt].p_filesz;
|
||||||
tlsimage = (void *) (bootstrap_map_p->l_addr + phdr[cnt].p_offset);
|
GL(dl_rtld_map).l_tls_initimage = (void *) (bootstrap_map_p->l_addr
|
||||||
|
+ phdr[cnt].p_offset);
|
||||||
|
|
||||||
/* We can now allocate the initial TLS block. This can happen
|
/* We can now allocate the initial TLS block. This can happen
|
||||||
on the stack. We'll get the final memory later when we
|
on the stack. We'll get the final memory later when we
|
||||||
know all about the various objects loaded at startup
|
know all about the various objects loaded at startup
|
||||||
time. */
|
time. */
|
||||||
# if TLS_TCB_AT_TP
|
# if TLS_TCB_AT_TP
|
||||||
tlsblock = alloca (roundup (tlssize, TLS_INIT_TCB_ALIGN)
|
tlsblock = alloca (roundup (GL(dl_rtld_map).l_tls_blocksize,
|
||||||
|
TLS_INIT_TCB_ALIGN)
|
||||||
+ TLS_INIT_TCB_SIZE
|
+ TLS_INIT_TCB_SIZE
|
||||||
+ align);
|
+ align);
|
||||||
# elif TLS_DTV_AT_TP
|
# elif TLS_DTV_AT_TP
|
||||||
tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align)
|
tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align)
|
||||||
+ tlssize
|
+ GL(dl_rtld_map).l_tls_blocksize
|
||||||
+ align);
|
+ align);
|
||||||
# else
|
# else
|
||||||
/* In case a model with a different layout for the TCB and DTV
|
/* In case a model with a different layout for the TCB and DTV
|
||||||
@ -295,24 +294,32 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
|||||||
# if TLS_TCB_AT_TP
|
# if TLS_TCB_AT_TP
|
||||||
initdtv[1].pointer = tlsblock;
|
initdtv[1].pointer = tlsblock;
|
||||||
# elif TLS_DTV_AT_TP
|
# elif TLS_DTV_AT_TP
|
||||||
GL(rtld_tlsoffset) = roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align);
|
GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
|
||||||
initdtv[1].pointer = (char *) tlsblock + GL(rtld_tlsoffset);
|
phdr[cnt].p_align);
|
||||||
|
initdtv[1].pointer = (char *) tlsblock + GL(dl_rtld_map).l_tls_offset);
|
||||||
# else
|
# else
|
||||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||||
# endif
|
# endif
|
||||||
memset (__mempcpy (initdtv[1].pointer, tlsimage, tlsimagesize),
|
memset (__mempcpy (initdtv[1].pointer, GL(dl_rtld_map).l_tls_initimage,
|
||||||
'\0', tlssize - tlsimagesize);
|
GL(dl_rtld_map).l_tls_initimage_size),
|
||||||
|
'\0', (GL(dl_rtld_map).l_tls_blocksize
|
||||||
|
- GL(dl_rtld_map).l_tls_initimage_size));
|
||||||
|
|
||||||
/* Initialize the thread pointer. */
|
/* Initialize the thread pointer. */
|
||||||
# if TLS_TCB_AT_TP
|
# if TLS_TCB_AT_TP
|
||||||
GL(rtld_tlsoffset) = roundup (tlssize, TLS_INIT_TCB_ALIGN);
|
GL(dl_rtld_map).l_tls_offset
|
||||||
TLS_INIT_TP ((char *) tlsblock + GL(rtld_tlsoffset), initdtv);
|
= roundup (GL(dl_rtld_map).l_tls_blocksize, TLS_INIT_TCB_ALIGN);
|
||||||
|
TLS_INIT_TP ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset,
|
||||||
|
initdtv);
|
||||||
# elif TLS_DTV_AT_TP
|
# elif TLS_DTV_AT_TP
|
||||||
TLS_INIT_TP (tlsblock, intidtv);
|
TLS_INIT_TP (tlsblock, initdtv);
|
||||||
# else
|
# else
|
||||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
/* So far this is module number one. */
|
||||||
|
GL(dl_rtld_map).l_tls_modid = 1;
|
||||||
|
|
||||||
/* There can only be one PT_TLS entry. */
|
/* There can only be one PT_TLS entry. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Data structure for communication from the run-time dynamic linker for
|
/* Data structure for communication from the run-time dynamic linker for
|
||||||
loaded ELF shared objects.
|
loaded ELF shared objects.
|
||||||
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
|
Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -21,9 +21,9 @@
|
|||||||
#ifndef _LINK_H
|
#ifndef _LINK_H
|
||||||
#define _LINK_H 1
|
#define _LINK_H 1
|
||||||
|
|
||||||
#include <features.h>
|
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
/* We use this macro to refer to ELF types independent of the native wordsize.
|
/* We use this macro to refer to ELF types independent of the native wordsize.
|
||||||
@ -254,6 +254,21 @@ struct link_map
|
|||||||
#endif
|
#endif
|
||||||
const ElfW(Sym) *ret;
|
const ElfW(Sym) *ret;
|
||||||
} l_lookup_cache;
|
} l_lookup_cache;
|
||||||
|
|
||||||
|
/* Thread-local storage related info. */
|
||||||
|
|
||||||
|
/* Next module in list of initialization images. */
|
||||||
|
struct link_map *l_tls_nextimage;
|
||||||
|
/* Start of the initialization image. */
|
||||||
|
void *l_tls_initimage;
|
||||||
|
/* Size of the initialization image. */
|
||||||
|
size_t l_tls_initimage_size;
|
||||||
|
/* Size of the TLS block. */
|
||||||
|
size_t l_tls_blocksize;
|
||||||
|
/* For objects present at startup time: offset in the static TLS block. */
|
||||||
|
ptrdiff_t l_tls_offset;
|
||||||
|
/* Index of the module in the dtv array. */
|
||||||
|
size_t l_tls_modid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dl_phdr_info
|
struct dl_phdr_info
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
|
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
|
||||||
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -98,6 +98,7 @@ struct cache_file_new
|
|||||||
& (~(__alignof__ (struct cache_file_new) - 1)))
|
& (~(__alignof__ (struct cache_file_new) - 1)))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
__attribute__ ((__unused__))
|
||||||
_dl_cache_libcmp (const char *p1, const char *p2)
|
_dl_cache_libcmp (const char *p1, const char *p2)
|
||||||
{
|
{
|
||||||
while (*p1 != '\0')
|
while (*p1 != '\0')
|
||||||
|
@ -288,8 +288,10 @@ struct rtld_global
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TLS
|
#ifdef USE_TLS
|
||||||
/* Offset of the TLS block for ld.so from the thread-pointer. */
|
/* Beginning of the list of link maps for objects which contain
|
||||||
EXTERN size_t _rtld_tlsoffset;
|
thread-local storage sections. This will be traversed to
|
||||||
|
initialize new TLS blocks. */
|
||||||
|
EXTERN struct link_map *_dl_initimage_list;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Name of the shared object to be profiled (if any). */
|
/* Name of the shared object to be profiled (if any). */
|
||||||
|
28
sysdeps/i386/dl-lookupcfg.h
Normal file
28
sysdeps/i386/dl-lookupcfg.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* Configuration of lookup functions. i386 version.
|
||||||
|
Copyright (C) 2000, 2002 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <tls.h>
|
||||||
|
|
||||||
|
/* Some platforms need more information from the symbol lookup function
|
||||||
|
than just the address. For x86 we need it when we support TLS. */
|
||||||
|
#ifdef USE_TLS
|
||||||
|
# define DL_LOOKUP_RETURNS_MAP
|
||||||
|
#else
|
||||||
|
# undef DL_LOOKUP_RETURNS_MAP
|
||||||
|
#endif
|
@ -342,20 +342,18 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if defined RTLD_BOOTSTRAP && !defined USE_TLS
|
|
||||||
Elf32_Addr value;
|
|
||||||
|
|
||||||
assert (r_type == R_386_GLOB_DAT || r_type == R_386_JMP_SLOT);
|
|
||||||
|
|
||||||
value = RESOLVE (&sym, version, r_type);
|
|
||||||
*reloc_addr = value + sym->st_value;
|
|
||||||
#else
|
|
||||||
const Elf32_Sym *const refsym = sym;
|
const Elf32_Sym *const refsym = sym;
|
||||||
|
#if defined USE_TLS && !defined RTLD_BOOTSTRAP
|
||||||
|
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
|
||||||
|
Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
|
||||||
|
#else
|
||||||
Elf32_Addr value = RESOLVE (&sym, version, r_type);
|
Elf32_Addr value = RESOLVE (&sym, version, r_type);
|
||||||
|
|
||||||
# ifndef RTLD_BOOTSTRAP
|
# ifndef RTLD_BOOTSTRAP
|
||||||
if (sym)
|
if (sym != NULL)
|
||||||
# endif
|
# endif
|
||||||
value += sym->st_value;
|
value += sym->st_value;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
@ -366,6 +364,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
|||||||
|
|
||||||
/* XXX Remove TLS relocations which are not needed. */
|
/* XXX Remove TLS relocations which are not needed. */
|
||||||
|
|
||||||
|
#ifdef USE_TLS
|
||||||
case R_386_TLS_DTPMOD32:
|
case R_386_TLS_DTPMOD32:
|
||||||
# ifdef RTLD_BOOTSTRAP
|
# ifdef RTLD_BOOTSTRAP
|
||||||
/* During startup the dynamic linker is always the module
|
/* During startup the dynamic linker is always the module
|
||||||
@ -374,29 +373,36 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
|||||||
call. */
|
call. */
|
||||||
*reloc_addr = 1;
|
*reloc_addr = 1;
|
||||||
# else
|
# else
|
||||||
/* XXX Implement. RESOLVE must return the map from which we
|
/* Get the information from the link map returned by the
|
||||||
get the module ID. */
|
resolv function. */
|
||||||
_exit (99);
|
if (sym_map != NULL)
|
||||||
|
*reloc_addr = sym_map->l_tls_modid;
|
||||||
# endif
|
# endif
|
||||||
break;
|
break;
|
||||||
case R_386_TLS_DTPOFF32:
|
case R_386_TLS_DTPOFF32:
|
||||||
# ifndef RTLD_BOOTSTRAP
|
# ifndef RTLD_BOOTSTRAP
|
||||||
/* During relocation all TLS symbols are defined and used.
|
/* During relocation all TLS symbols are defined and used.
|
||||||
Therefore the offset is already correct. */
|
Therefore the offset is already correct. */
|
||||||
*reloc_addr = sym->st_value;
|
if (sym != NULL)
|
||||||
|
*reloc_addr = sym->st_value;
|
||||||
# endif
|
# endif
|
||||||
break;
|
break;
|
||||||
case R_386_TLS_TPOFF32:
|
case R_386_TLS_TPOFF32:
|
||||||
/* The offset is positive, backward from the thread pointer. */
|
/* The offset is positive, backward from the thread pointer. */
|
||||||
# ifdef RTLD_BOOTSTRAP
|
# ifdef RTLD_BOOTSTRAP
|
||||||
*reloc_addr = GL(rtld_tlsoffset) - sym->st_value;
|
*reloc_addr = GL(dl_rtld_map).l_tls_offset - sym->st_value;
|
||||||
# else
|
# else
|
||||||
/* XXX Implement. */
|
/* We know the offset of object the symbol is contained is.
|
||||||
_exit (98);
|
It is a positive value which will be subtracted from the
|
||||||
|
thread pointer. To get the variable position in the TLS
|
||||||
|
block we subtract the offset from that of the TLS block. */
|
||||||
|
if (sym_map != NULL && sym != NULL)
|
||||||
|
*reloc_addr = sym_map->l_tls_offset - sym->st_value;
|
||||||
# endif
|
# endif
|
||||||
break;
|
break;
|
||||||
|
#endif /* use TLS */
|
||||||
|
|
||||||
# ifndef RTLD_BOOTSTRAP
|
#ifndef RTLD_BOOTSTRAP
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
*reloc_addr += value;
|
*reloc_addr += value;
|
||||||
break;
|
break;
|
||||||
@ -426,9 +432,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
|||||||
default:
|
default:
|
||||||
_dl_reloc_bad_type (map, r_type, 0);
|
_dl_reloc_bad_type (map, r_type, 0);
|
||||||
break;
|
break;
|
||||||
# endif
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,13 +443,20 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
|||||||
const Elf32_Sym *sym, const struct r_found_version *version,
|
const Elf32_Sym *sym, const struct r_found_version *version,
|
||||||
Elf32_Addr *const reloc_addr)
|
Elf32_Addr *const reloc_addr)
|
||||||
{
|
{
|
||||||
|
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||||
|
|
||||||
if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
|
if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
|
||||||
*reloc_addr = map->l_addr + reloc->r_addend;
|
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||||
else if (ELF32_R_TYPE (reloc->r_info) != R_386_NONE)
|
else if (r_type != R_386_NONE)
|
||||||
{
|
{
|
||||||
|
# ifdef USE_TLS
|
||||||
|
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
|
||||||
|
Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
|
||||||
|
# else
|
||||||
Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info));
|
Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info));
|
||||||
if (sym)
|
if (sym != NULL)
|
||||||
value += sym->st_value;
|
value += sym->st_value;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (ELF32_R_TYPE (reloc->r_info))
|
switch (ELF32_R_TYPE (reloc->r_info))
|
||||||
{
|
{
|
||||||
@ -456,10 +468,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
|||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
*reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr);
|
*reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||||
break;
|
break;
|
||||||
|
/* XXX Do we have to handle the TLS relocation here? */
|
||||||
default:
|
default:
|
||||||
/* We add these checks in the version to relocate ld.so only
|
/* We add these checks in the version to relocate ld.so only
|
||||||
if we are still debugging. */
|
if we are still debugging. */
|
||||||
_dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 0);
|
_dl_reloc_bad_type (map, r_type, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user