about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--elf/dl-lookup.c16
-rw-r--r--elf/elf.h17
-rw-r--r--linuxthreads/ChangeLog7
-rw-r--r--linuxthreads/sysdeps/i386/tls.h8
-rw-r--r--linuxthreads/sysdeps/i386/useldt.h26
-rw-r--r--sysdeps/i386/dl-machine.h38
7 files changed, 82 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index e54b612eab..ca3ebb7cbf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2002-09-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* elf/dl-lookup.c (_dl_debug_bindings): Print TLS lookups always.
+
+	* elf/elf.h (R_386_TLS_TPOFF, R_386_TLS_IE, R_386_TLS_GOTIE,
+	R_386_TLS_LE): Define.
+	(R_386_TLS_IE_32, R_386_TLS_LE_32, R_386_TLS_TPOFF32): Update
+	comments.
+	* sysdeps/i386/dl-machine.h (elf_machine_type_class): Return
+	ELF_RTYPE_CLASS_PLT for R_386_TLS_TPOFF.
+	(elf_machine_rel): Handle R_386_TLS_TPOFF.
+	(elf_machine_rela): Likewise.
+	Remove unnecessary RTLD_BOOTSTRAP #ifdefs.
+
 2002-09-17  Roland McGrath  <roland@redhat.com>
 
 	* malloc/Makefile ($(objpfx)memusagestat.o: sysincludes): Define
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 6f14aaf498..e2f5506030 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -647,9 +647,17 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
 	    conflict = 1;
 	}
 
+#ifdef USE_TLS
+      if (value->s
+	  && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
+				== STT_TLS, 0)))
+	type_class = 4;
+#endif
+
       if (conflict
 	  || GL(dl_trace_prelink_map) == undef_map
-	  || GL(dl_trace_prelink_map) == NULL)
+	  || GL(dl_trace_prelink_map) == NULL
+	  || type_class == 4)
 	{
 	  _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
 		      conflict ? "conflict" : "lookup",
@@ -668,12 +676,6 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
 			(int) sizeof (ElfW(Addr)) * 2,
 			(ElfW(Addr)) (val.s ? val.s->st_value : 0));
 
-#ifdef USE_TLS
-          if (value->s
-	      && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
-				    == STT_TLS, 0)))
-	    type_class = 4;
-#endif
 	  _dl_printf ("/%x %s\n", type_class, undef_name);
 	}
     }
diff --git a/elf/elf.h b/elf/elf.h
index 2edf8e081b..b664c5d279 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1073,6 +1073,13 @@ typedef struct
 #define R_386_GOTOFF	   9		/* 32 bit offset to GOT */
 #define R_386_GOTPC	   10		/* 32 bit PC relative offset to GOT */
 #define R_386_32PLT	   11
+#define R_386_TLS_TPOFF	   14		/* Offset in static TLS block */
+#define R_386_TLS_IE	   15		/* Address of GOT entry for static TLS
+					   block offset */
+#define R_386_TLS_GOTIE	   16		/* GOT entry for static TLS block
+					   offset */
+#define R_386_TLS_LE	   17		/* Offset relative to static TLS
+					   block */
 #define R_386_TLS_GD	   18		/* Direct 32 bit for GNU version of
 					   general dynamic thread local data */
 #define R_386_TLS_LDM	   19		/* Direct 32 bit for GNU version of
@@ -1095,13 +1102,13 @@ typedef struct
 					   __tls_get_addr() in LDM code */
 #define R_386_TLS_LDM_POP  31		/* Tag for popl in LDM TLS code */
 #define R_386_TLS_LDO_32   32		/* Offset relative to TLS block */
-#define R_386_TLS_IE_32	   33		/* GOT entry for static TLS block
-					   offset */
-#define R_386_TLS_LE_32	   34		/* Offset relative to static TLS
-					   block */
+#define R_386_TLS_IE_32	   33		/* GOT entry for negated static TLS
+					   block offset */
+#define R_386_TLS_LE_32	   34		/* Negated offset relative to static
+					   TLS block */
 #define R_386_TLS_DTPMOD32 35		/* ID of module containing symbol */
 #define R_386_TLS_DTPOFF32 36		/* Offset in TLS block */
-#define R_386_TLS_TPOFF32  37		/* Offset in static TLS block */
+#define R_386_TLS_TPOFF32  37		/* Negated offset in static TLS block */
 /* Keep this the last entry.  */
 #define R_386_NUM	   38
 
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index fd23cfff66..40913b630b 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,10 @@
+2002-09-17  Roland McGrath  <roland@redhat.com>
+
+	* sysdeps/i386/tls.h (TLS_DO_MODIFY_LDT, TLS_DO_SET_THREAD_AREA):
+	Set the descriptor limit to the full 4GB, so %gs:OFFSET works for any
+	offset (positive or negative) relative to the thread struct.
+	* sysdeps/i386/useldt.h (DO_MODIFY_LDT, DO_SET_THREAD_AREA): Likewise.
+
 2002-09-12  Jakub Jelinek  <jakub@redhat.com>
 
 	* sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: Move...
diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h
index a0c822759f..7715303d95 100644
--- a/linuxthreads/sysdeps/i386/tls.h
+++ b/linuxthreads/sysdeps/i386/tls.h
@@ -99,8 +99,8 @@ typedef struct
 #  define TLS_DO_MODIFY_LDT(descr, nr)					      \
 ({									      \
   struct modify_ldt_ldt_s ldt_entry =					      \
-    { nr, (unsigned long int) (descr), sizeof (struct _pthread_descr_struct), \
-      1, 0, 0, 0, 0, 1, 0 };						      \
+    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
   int result;								      \
   asm volatile (TLS_LOAD_EBX						      \
 		"int $0x80\n\t"						      \
@@ -118,8 +118,8 @@ typedef struct
 #  define TLS_DO_SET_THREAD_AREA(descr, secondcall)			      \
 ({									      \
   struct modify_ldt_ldt_s ldt_entry =					      \
-    { -1, (unsigned long int) (descr), sizeof (struct _pthread_descr_struct), \
-      1, 0, 0, 0, 0, 1, 0 };						      \
+    { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
   int result;								      \
   if (secondcall)							      \
     ldt_entry.entry_number = ({ int _gs;				      \
diff --git a/linuxthreads/sysdeps/i386/useldt.h b/linuxthreads/sysdeps/i386/useldt.h
index 2b30cafa9e..31893b4013 100644
--- a/linuxthreads/sysdeps/i386/useldt.h
+++ b/linuxthreads/sysdeps/i386/useldt.h
@@ -11,22 +11,22 @@
 
    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
+   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; see the file COPYING.LIB.  If not,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Boston, MA 02111-1307, USA.	*/
 
 #ifndef __ASSEMBLER__
 #include <stddef.h>	/* For offsetof.  */
-#include <stdlib.h>	/* For abort().  */
-#include <sysdep.h>	/* For INLINE_SYSCALL.  */
+#include <stdlib.h>	/* For abort().	 */
+#include <sysdep.h>	/* For INLINE_SYSCALL.	*/
 
 
-/* We don't want to include the kernel header.  So duplicate the
-   information.  */
+/* We don't want to include the kernel header.	So duplicate the
+   information.	 */
 
 /* Structure passed on `modify_ldt' call.  */
 struct modify_ldt_ldt_s
@@ -63,13 +63,13 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
 })
 
 
-/* Initialize the thread-unique value.  Two possible ways to do it.  */
+/* Initialize the thread-unique value.	Two possible ways to do it.  */
 
 #define DO_MODIFY_LDT(descr, nr)					      \
 ({									      \
   struct modify_ldt_ldt_s ldt_entry =					      \
-    { nr, (unsigned long int) descr, sizeof (struct _pthread_descr_struct),   \
-      1, 0, 0, 0, 0, 1, 0 };						      \
+    { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+      1, 0, 0, 1, 0, 1, 0 };						      \
   if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0)		      \
     abort ();								      \
   asm ("movw %w0, %%gs" : : "q" (nr * 8 + 7));				      \
@@ -93,8 +93,8 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
       asm ("movw %%gs, %w0" : "=q" (__gs));				      \
       struct modify_ldt_ldt_s ldt_entry =				      \
 	{ (__gs & 0xffff) >> 3,						      \
-	  (unsigned long int) descr, sizeof (struct _pthread_descr_struct),   \
-	  1, 0, 0, 0, 0, 1, 0 };					      \
+	  (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+	  1, 0, 0, 1, 0, 1, 0 };					      \
       if (__builtin_expect (INLINE_SYSCALL (set_thread_area, 1, &ldt_entry),  \
 			    0) == 0)					      \
 	asm ("movw %w0, %%gs" :: "q" (__gs));				      \
@@ -105,8 +105,8 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
     {									      \
       struct modify_ldt_ldt_s ldt_entry =				      \
 	{ -1,								      \
-	  (unsigned long int) descr, sizeof (struct _pthread_descr_struct),   \
-	  1, 0, 0, 0, 0, 1, 0 };					      \
+	  (unsigned long int) (descr), 0xfffff /* 4GB in pages */,	      \
+	  1, 0, 0, 1, 0, 1, 0 };					      \
       if (__builtin_expect (INLINE_SYSCALL (set_thread_area, 1, &ldt_entry),  \
 			    0) == 0)					      \
 	{								      \
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 8f17441dd8..1784a3a737 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -302,7 +302,8 @@ _dl_start_user:\n\
 #ifdef USE_TLS
 # define elf_machine_type_class(type) \
   ((((type) == R_386_JMP_SLOT || (type) == R_386_TLS_DTPMOD32		      \
-     || (type) == R_386_TLS_DTPOFF32 || (type) == R_386_TLS_TPOFF32)	      \
+     || (type) == R_386_TLS_DTPOFF32 || (type) == R_386_TLS_TPOFF32	      \
+     || (type) == R_386_TLS_TPOFF)					      \
     * ELF_RTYPE_CLASS_PLT)						      \
    | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
 #else
@@ -446,6 +447,18 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	    *reloc_addr += sym_map->l_tls_offset - sym->st_value;
 # endif
 	  break;
+	case R_386_TLS_TPOFF:
+	  /* The offset is negative, forward from the thread pointer.  */
+# ifdef RTLD_BOOTSTRAP
+	  *reloc_addr += sym->st_value - map->l_tls_offset;
+# else
+	  /* We know the offset of object the symbol is contained in.
+	     It is a negative value which will be added to the
+	     thread pointer.  */
+	  if (sym != NULL)
+	    *reloc_addr += sym->st_value - sym_map->l_tls_offset;
+# endif
+	  break;
 #endif	/* use TLS */
 
 #ifndef RTLD_BOOTSTRAP
@@ -517,31 +530,18 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 
 #ifdef USE_TLS
 	case R_386_TLS_DTPMOD32:
-# ifdef RTLD_BOOTSTRAP
-	  /* During startup the dynamic linker is always the module
-	     with index 1.
-	     XXX If this relocation is necessary move before RESOLVE
-	     call.  */
-	  *reloc_addr = 1;
-# else
 	  /* 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 == NULL ? 0 : sym->st_value) + reloc->r_addend;
-# endif
 	  break;
 	case R_386_TLS_TPOFF32:
 	  /* The offset is positive, backward from the thread pointer.  */
-# ifdef RTLD_BOOTSTRAP
-	  *reloc_addr = map->l_tls_offset - sym->st_value + reloc->r_addend;
-# else
 	  /* We know the offset of object the symbol is contained in.
 	     It is a positive value which will be subtracted from the
 	     thread pointer.  To get the variable position in the TLS
@@ -549,7 +549,15 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	  *reloc_addr
 	    = (sym == NULL ? 0 : sym_map->l_tls_offset - sym->st_value)
 	      + reloc->r_addend;
-# endif
+	  break;
+	case R_386_TLS_TPOFF:
+	  /* The offset is negative, forward from the thread pointer.  */
+	  /* We know the offset of object the symbol is contained in.
+	     It is a negative value which will be added to the
+	     thread pointer.  */
+	  *reloc_addr
+	    = (sym == NULL ? 0 : sym->st_value - sym_map->l_tls_offset)
+	      + reloc->r_addend;
 	  break;
 #endif	/* use TLS */
 	default: