This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PPC64 tls fixes


This fix applies to both glibc-2.3.2 and current cvs head.

The --with-tls build fails because TLS_TP_OFFSET is not defined for none
SHARED. In sysdeps/powerpc/dl-tls.h, moved the defines for TLS_TP_OFFSET
and TLS_DTV_OFFSET outside the #ifdef SHARED so they are defined for
both cases.

Significant rework of dl-machine.h (elf_machine_rela). Include dl-tls.h
to get TLS_TP_OFFSET defined. Removed all DTPREL relocations. Alan Modra
assures me that the ld will never emit dynamic DTPREL relocations.
Rearranged the switch (r_type) cases so that all tls related relocations
are together and conditional on:

#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)

Defined a new static function elf_machine_tprel to encapsulate the TP
relative value calculations. Then used this function for all the tls
TPREL relocations.


2003-03-03  Steven Munroe  <sjmunroe at us dot ibm dot com>

	* sysdeps/powerpc/dl-tls.h (TLS_TP_OFFSET, TLS_DTV_OFFSET):
	Define unconditionally.
	* sysdeps/powerpc/powerpc64/dl-machine.h: Include dl-tls.h
	[USE_TLS] (elf_machine_tprel): New function.
	(elf_machine_rela): Remove all DTPREL*_16 relocations.
	(elf_machine_rela) [USE_TLS]: Declare tprel_value.  Group all
	tls relocations under this conditional.  Use elf_machine_tprel
	function for all TPREL class relocations.

-- 
Steven Munroe
sjmunroe at us dot ibm dot com
Linux on PowerPC-64 Development
GLIBC for PowerPC-64 Development
diff -rupP libc23-cvstip-20030228/sysdeps/powerpc/dl-tls.h libc23/sysdeps/powerpc/dl-tls.h
--- libc23-cvstip-20030228/sysdeps/powerpc/dl-tls.h	2003-02-27 22:54:53.000000000 -0600
+++ libc23/sysdeps/powerpc/dl-tls.h	2003-02-28 10:23:33.000000000 -0600
@@ -25,11 +25,6 @@ typedef struct
   unsigned long int ti_offset;
 } tls_index;
 
-
-#ifdef SHARED
-
-extern void *__tls_get_addr (tls_index *ti);
-
 /* The thread pointer points 0x7000 past the first static TLS block.  */
 # define TLS_TP_OFFSET		0x7000
 
@@ -37,6 +32,11 @@ extern void *__tls_get_addr (tls_index *
    TLS block.  */
 # define TLS_DTV_OFFSET		0x8000
 
+
+#ifdef SHARED
+
+extern void *__tls_get_addr (tls_index *ti);
+
 # define GET_ADDR_OFFSET	(ti->ti_offset + TLS_DTV_OFFSET)
 # define __TLS_GET_ADDR(__ti)	(__tls_get_addr (__ti) - TLS_DTV_OFFSET)
 
diff -rupP libc23-cvstip-20030228/sysdeps/powerpc/powerpc64/dl-machine.h libc23/sysdeps/powerpc/powerpc64/dl-machine.h
--- libc23-cvstip-20030228/sysdeps/powerpc/powerpc64/dl-machine.h	2003-02-27 22:54:56.000000000 -0600
+++ libc23/sysdeps/powerpc/powerpc64/dl-machine.h	2003-03-01 11:34:43.000000000 -0600
@@ -26,6 +26,7 @@
 
 #include <assert.h>
 #include <sys/param.h>
+#include <dl-tls.h>
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -546,6 +547,28 @@ elf_machine_rela_relative (Elf64_Addr l_
   *reloc_addr = l_addr + reloc->r_addend;
 }
 
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+static Elf64_Addr
+elf_machine_tprel ( struct link_map *map, 
+                    struct link_map *sym_map,
+  	                Elf64_Addr raw_value)
+{
+  Elf64_Addr tprel_value = 0;	      
+# ifdef RTLD_BOOTSTRAP
+  tprel_value = (sym_map->l_tls_offset - TLS_TCB_SIZE
+                + raw_value - TLS_TP_OFFSET);
+# else
+  if (sym_map)
+    {
+      CHECK_STATIC_TLS (map, sym_map);
+      tprel_value = (sym_map->l_tls_offset - TLS_TCB_SIZE
+                    + raw_value - TLS_TP_OFFSET);
+    }
+# endif
+  return tprel_value;
+}
+#endif
+
 /* Perform the relocation specified by RELOC and SYM (which is fully
    resolved).  MAP is the object containing the reloc.  */
 static inline void
@@ -561,6 +584,9 @@ elf_machine_rela (struct link_map *map,
 #ifndef RTLD_BOOTSTRAP
   const Elf64_Sym *const refsym = sym;
 #endif
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+  Elf64_Addr tprel_value = 0;
+#endif
 
   if (r_type == R_PPC64_RELATIVE)
     {
@@ -587,7 +613,6 @@ elf_machine_rela (struct link_map *map,
       return;
 
 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
-
     case R_PPC64_DTPMOD64:
 #ifdef RTLD_BOOTSTRAP
     /* During startup the dynamic linker is always index 1.  */
@@ -596,102 +621,136 @@ elf_machine_rela (struct link_map *map,
     /* Get the information from the link map returned by the
        resolve function.  */
       if (sym_map != NULL)
-	*reloc_addr = sym_map->l_tls_modid;
+        *reloc_addr = sym_map->l_tls_modid;
 #endif
       return;
 
     case R_PPC64_TPREL64:
-#ifdef RTLD_BOOTSTRAP
-      *reloc_addr = (sym_map->l_tls_offset - TLS_TCB_SIZE
-		     + raw_value - TLS_TP_OFFSET);
-#else
-      if (sym_map)
-	{
-	  CHECK_STATIC_TLS (map, sym_map);
-	  *reloc_addr = (sym_map->l_tls_offset - TLS_TCB_SIZE
-			 + raw_value - TLS_TP_OFFSET);
-	}
-#endif
+      *reloc_addr = elf_machine_tprel (map, sym_map, raw_value);
       return;
 
     case R_PPC64_DTPREL64:
 #ifndef RTLD_BOOTSTRAP
       /* During relocation all TLS symbols are defined and used.
-	 Therefore the offset is already correct.  */
+         Therefore the offset is already correct.  */
       *reloc_addr = raw_value - TLS_DTV_OFFSET;
 #endif
-      return;
-#endif
-
-    case R_PPC64_JMP_SLOT:
+      return;      
 
-      elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
-      return;
-
-#ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
-    case R_PPC64_ADDR16_LO_DS:
-      if (dont_expect ((value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS",
+    case R_PPC64_TPREL16_LO_DS:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      if (dont_expect ((tprel_value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS",
                             reloc_addr, sym, refsym);
       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-					       value, 0xfffc);
+                                              tprel_value, 0xfffc);
       break;
 
-    case R_PPC64_TPREL16_LO_DS:
-      if (dont_expect ((value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS",
+    case R_PPC64_GOT_TPREL16_LO_DS:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      if (dont_expect ((tprel_value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_LO_DS",
                             reloc_addr, sym, refsym);
       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
+                                              tprel_value, 0xfffc);
       break;
 
-    case R_PPC64_DTPREL16_LO_DS:
-      if (dont_expect ((value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_DTPREL16_LO_DS",
-                            reloc_addr, sym, refsym);
+    case R_PPC64_TPREL16_DS:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      if (dont_expect ((tprel_value + 0x8000) >= 0x10000 
+                    || (tprel_value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr,
+                            sym, refsym);
       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
+                                              tprel_value, 0xfffc);
       break;
 
-    case R_PPC64_GOT_TPREL16_LO_DS:
-      if (dont_expect ((value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_LO_DS",
-                            reloc_addr, sym, refsym);
+    case R_PPC64_GOT_TPREL16_DS:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      if (dont_expect ((tprel_value + 0x8000) >= 0x10000 
+                    || (tprel_value & 3) != 0))
+        _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_DS", reloc_addr,
+                            sym, refsym);
       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
+                                              tprel_value, 0xfffc);
+      break;
+ 
+    case R_PPC64_GOT_TLSGD16_LO:
+    case R_PPC64_GOT_TLSLD16_LO:
+      *(Elf64_Half *) reloc_addr = PPC_LO (value);
+      break;
+      
+    case R_PPC64_TPREL16_LO:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_LO (tprel_value);
       break;
+      
+    case R_PPC64_GOT_TLSGD16_HI:
+    case R_PPC64_GOT_TLSLD16_HI:
+      *(Elf64_Half *) reloc_addr = PPC_HI (value);      
+      break;
+      
+    case R_PPC64_TPREL16_HI:
+    case R_PPC64_GOT_TPREL16_HI:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_HI (tprel_value);
+      break;
+      
+    case R_PPC64_GOT_TLSGD16_HA:
+    case R_PPC64_GOT_TLSLD16_HA:
+      *(Elf64_Half *) reloc_addr = PPC_HA (value);
+      break;
+      
+    case R_PPC64_TPREL16_HA:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_HA (tprel_value);
+      break;
+      
+    case R_PPC64_TPREL16_HIGHER:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_HIGHER (tprel_value);
+      break;
+      
+    case R_PPC64_TPREL16_HIGHEST:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_HIGHEST (tprel_value);
+      break;
+      
+    case R_PPC64_TPREL16_HIGHERA:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_HIGHERA (tprel_value);
+      break;
+      
+    case R_PPC64_TPREL16_HIGHESTA:
+      tprel_value = elf_machine_tprel (map, sym_map, raw_value);
+      *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (tprel_value);
+      break;
+      
+#endif /* USE_TLS.  */
+
+    case R_PPC64_JMP_SLOT:
+
+      elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
+      return;
 
-    case R_PPC64_GOT_DTPREL16_LO_DS:
+#ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
+    case R_PPC64_ADDR16_LO_DS:
       if (dont_expect ((value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_GOT_DTPREL16_LO_DS",
+        _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS",
                             reloc_addr, sym, refsym);
       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
+					       value, 0xfffc);
       break;
 
     case R_PPC64_ADDR16_LO:
-    case R_PPC64_TPREL16_LO:
-    case R_PPC64_DTPREL16_LO:
-    case R_PPC64_GOT_TLSGD16_LO:
-    case R_PPC64_GOT_TLSLD16_LO:
       *(Elf64_Half *) reloc_addr = PPC_LO (value);
       break;
 
     case R_PPC64_ADDR16_HI:
-    case R_PPC64_TPREL16_HI:
-    case R_PPC64_DTPREL16_HI:
-    case R_PPC64_GOT_TPREL16_HI:
-    case R_PPC64_GOT_DTPREL16_HI:
-    case R_PPC64_GOT_TLSGD16_HI:
-    case R_PPC64_GOT_TLSLD16_HI:
-      *(Elf64_Half *) reloc_addr = PPC_HI (value);
+      *(Elf64_Half *) reloc_addr = PPC_HI (value);      
       break;
 
     case R_PPC64_ADDR16_HA:
-    case R_PPC64_TPREL16_HA:
-    case R_PPC64_DTPREL16_HA:
-    case R_PPC64_GOT_TLSGD16_HA:
-    case R_PPC64_GOT_TLSLD16_HA:
       *(Elf64_Half *) reloc_addr = PPC_HA (value);
       break;
 
@@ -772,59 +831,19 @@ elf_machine_rela (struct link_map *map,
 					       value, 0xfffc);
       break;
 
-    case R_PPC64_TPREL16_DS:
-      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr,
-                            sym, refsym);
-      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
-      break;
-
-    case R_PPC64_DTPREL16_DS:
-      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_DTPREL16_DS", reloc_addr,
-                            sym, refsym);
-      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
-      break;
-
-    case R_PPC64_GOT_TPREL16_DS:
-      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_DS", reloc_addr,
-                            sym, refsym);
-      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
-      break;
-
-    case R_PPC64_GOT_DTPREL16_DS:
-      if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
-        _dl_reloc_overflow (map, "R_PPC64_GOT_DTPREL16_DS",
-                            reloc_addr, sym, refsym);
-      *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
-                                              value, 0xfffc);
-      break;
-
     case R_PPC64_ADDR16_HIGHER:
-    case R_PPC64_TPREL16_HIGHER:
-    case R_PPC64_DTPREL16_HIGHER:
       *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
       break;
 
     case R_PPC64_ADDR16_HIGHEST:
-    case R_PPC64_TPREL16_HIGHEST:
-    case R_PPC64_DTPREL16_HIGHEST:
       *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
       break;
 
     case R_PPC64_ADDR16_HIGHERA:
-    case R_PPC64_TPREL16_HIGHERA:
-    case R_PPC64_DTPREL16_HIGHERA:
-      *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
+      *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);      
       break;
 
     case R_PPC64_ADDR16_HIGHESTA:
-    case R_PPC64_TPREL16_HIGHESTA:
-    case R_PPC64_DTPREL16_HIGHESTA:
       *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
       break;
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]