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>
|
||||
|
||||
* 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
|
||||
thread-pointer as soon as possible.
|
||||
* 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(Phdr) *phdr;
|
||||
size_t cnt;
|
||||
size_t tlssize = 0;
|
||||
size_t tlsimagesize = 0;
|
||||
const void *tlsimage = NULL;
|
||||
void *tlsblock = NULL;
|
||||
dtv_t initdtv[2];
|
||||
#endif
|
||||
|
||||
@ -261,23 +257,26 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||
for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
|
||||
if (phdr[cnt].p_type == PT_TLS)
|
||||
{
|
||||
void *tlsblock;
|
||||
size_t align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
|
||||
|
||||
tlssize = phdr[cnt].p_memsz;
|
||||
tlsimagesize = phdr[cnt].p_filesz;
|
||||
tlsimage = (void *) (bootstrap_map_p->l_addr + phdr[cnt].p_offset);
|
||||
GL(dl_rtld_map).l_tls_blocksize = phdr[cnt].p_memsz;
|
||||
GL(dl_rtld_map).l_tls_initimage_size = phdr[cnt].p_filesz;
|
||||
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
|
||||
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 (tlssize, TLS_INIT_TCB_ALIGN)
|
||||
tlsblock = alloca (roundup (GL(dl_rtld_map).l_tls_blocksize,
|
||||
TLS_INIT_TCB_ALIGN)
|
||||
+ TLS_INIT_TCB_SIZE
|
||||
+ align);
|
||||
# elif TLS_DTV_AT_TP
|
||||
tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align)
|
||||
+ tlssize
|
||||
+ GL(dl_rtld_map).l_tls_blocksize
|
||||
+ align);
|
||||
# else
|
||||
/* 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
|
||||
initdtv[1].pointer = tlsblock;
|
||||
# elif TLS_DTV_AT_TP
|
||||
GL(rtld_tlsoffset) = roundup (TLS_INIT_TCB_SIZE, phdr[cnt].p_align);
|
||||
initdtv[1].pointer = (char *) tlsblock + GL(rtld_tlsoffset);
|
||||
GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
|
||||
phdr[cnt].p_align);
|
||||
initdtv[1].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, tlsimage, tlsimagesize),
|
||||
'\0', tlssize - tlsimagesize);
|
||||
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));
|
||||
|
||||
/* Initialize the thread pointer. */
|
||||
# if TLS_TCB_AT_TP
|
||||
GL(rtld_tlsoffset) = roundup (tlssize, TLS_INIT_TCB_ALIGN);
|
||||
TLS_INIT_TP ((char *) tlsblock + GL(rtld_tlsoffset), initdtv);
|
||||
GL(dl_rtld_map).l_tls_offset
|
||||
= 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
|
||||
TLS_INIT_TP (tlsblock, intidtv);
|
||||
TLS_INIT_TP (tlsblock, initdtv);
|
||||
# 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;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Data structure for communication from the run-time dynamic linker for
|
||||
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.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -21,9 +21,9 @@
|
||||
#ifndef _LINK_H
|
||||
#define _LINK_H 1
|
||||
|
||||
#include <features.h>
|
||||
#include <elf.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* We use this macro to refer to ELF types independent of the native wordsize.
|
||||
@ -254,6 +254,21 @@ struct link_map
|
||||
#endif
|
||||
const ElfW(Sym) *ret;
|
||||
} 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
|
||||
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)))
|
||||
|
||||
static int
|
||||
__attribute__ ((__unused__))
|
||||
_dl_cache_libcmp (const char *p1, const char *p2)
|
||||
{
|
||||
while (*p1 != '\0')
|
||||
|
@ -288,8 +288,10 @@ struct rtld_global
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
/* Offset of the TLS block for ld.so from the thread-pointer. */
|
||||
EXTERN size_t _rtld_tlsoffset;
|
||||
/* Beginning of the list of link maps for objects which contain
|
||||
thread-local storage sections. This will be traversed to
|
||||
initialize new TLS blocks. */
|
||||
EXTERN struct link_map *_dl_initimage_list;
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
#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;
|
||||
#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);
|
||||
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
if (sym)
|
||||
if (sym != NULL)
|
||||
# endif
|
||||
value += sym->st_value;
|
||||
#endif
|
||||
|
||||
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. */
|
||||
|
||||
#ifdef USE_TLS
|
||||
case R_386_TLS_DTPMOD32:
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
/* 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. */
|
||||
*reloc_addr = 1;
|
||||
# else
|
||||
/* XXX Implement. RESOLVE must return the map from which we
|
||||
get the module ID. */
|
||||
_exit (99);
|
||||
/* Get the information from the link map returned by the
|
||||
resolv function. */
|
||||
if (sym_map != NULL)
|
||||
*reloc_addr = sym_map->l_tls_modid;
|
||||
# endif
|
||||
break;
|
||||
case R_386_TLS_DTPOFF32:
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
/* During relocation all TLS symbols are defined and used.
|
||||
Therefore the offset is already correct. */
|
||||
*reloc_addr = sym->st_value;
|
||||
if (sym != NULL)
|
||||
*reloc_addr = sym->st_value;
|
||||
# endif
|
||||
break;
|
||||
case R_386_TLS_TPOFF32:
|
||||
/* The offset is positive, backward from the thread pointer. */
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
*reloc_addr = GL(rtld_tlsoffset) - sym->st_value;
|
||||
*reloc_addr = GL(dl_rtld_map).l_tls_offset - sym->st_value;
|
||||
# else
|
||||
/* XXX Implement. */
|
||||
_exit (98);
|
||||
/* We know the offset of object the symbol is contained is.
|
||||
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
|
||||
break;
|
||||
#endif /* use TLS */
|
||||
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
case R_386_32:
|
||||
*reloc_addr += value;
|
||||
break;
|
||||
@ -426,9 +432,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
||||
default:
|
||||
_dl_reloc_bad_type (map, r_type, 0);
|
||||
break;
|
||||
# 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,
|
||||
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)
|
||||
*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));
|
||||
if (sym)
|
||||
if (sym != NULL)
|
||||
value += sym->st_value;
|
||||
#endif
|
||||
|
||||
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:
|
||||
*reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||
break;
|
||||
/* XXX Do we have to handle the TLS relocation here? */
|
||||
default:
|
||||
/* We add these checks in the version to relocate ld.so only
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user