about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-05 08:02:04 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-05 08:02:04 +0000
commit5d6feea8f54fe67cbeb7c35e35539b2efd4ead29 (patch)
tree66e0786e2913d8d1984dd7345d12201fa9db4736 /sysdeps
parent535b764df5ca722066c2db615190e6a70688c6a6 (diff)
downloadglibc-5d6feea8f54fe67cbeb7c35e35539b2efd4ead29.tar.gz
glibc-5d6feea8f54fe67cbeb7c35e35539b2efd4ead29.tar.xz
glibc-5d6feea8f54fe67cbeb7c35e35539b2efd4ead29.zip
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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-cache.h3
-rw-r--r--sysdeps/generic/ldsodefs.h6
-rw-r--r--sysdeps/i386/dl-lookupcfg.h28
-rw-r--r--sysdeps/i386/dl-machine.h57
4 files changed, 69 insertions, 25 deletions
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 <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
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;
 	}
     }