From 5d6feea8f54fe67cbeb7c35e35539b2efd4ead29 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 5 Feb 2002 08:02:04 +0000 Subject: 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. --- sysdeps/generic/dl-cache.h | 3 ++- sysdeps/generic/ldsodefs.h | 6 +++-- sysdeps/i386/dl-lookupcfg.h | 28 ++++++++++++++++++++++ sysdeps/i386/dl-machine.h | 57 ++++++++++++++++++++++++++++----------------- 4 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 sysdeps/i386/dl-lookupcfg.h (limited to 'sysdeps') diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h index ad6b0106d1..d02c1739c1 100644 --- a/sysdeps/generic/dl-cache.h +++ b/sysdeps/generic/dl-cache.h @@ -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') diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 08785a818e..4e4fecf712 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -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). */ diff --git a/sysdeps/i386/dl-lookupcfg.h b/sysdeps/i386/dl-lookupcfg.h new file mode 100644 index 0000000000..8daf7a8a75 --- /dev/null +++ b/sysdeps/i386/dl-lookupcfg.h @@ -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 + +/* 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 diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index f791fa3ffa..3e471805d7 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -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; } } -- cgit v1.2.3