about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/ldsodefs.h3
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.c48
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.h87
3 files changed, 77 insertions, 61 deletions
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 8be15b1cae..12151ce69d 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -795,6 +795,9 @@ rtld_hidden_proto (_dl_allocate_tls)
 extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp)
      internal_function;
 
+extern void _dl_allocate_static_tls (struct link_map *map)
+     internal_function attribute_hidden;
+
 /* These are internal entry points to the two halves of _dl_allocate_tls,
    only used within rtld.c itself at startup time.  */
 extern void *_dl_allocate_tls_storage (void)
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c
index 866380a940..2e071c85af 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.c
+++ b/sysdeps/powerpc/powerpc32/dl-machine.c
@@ -397,6 +397,7 @@ _dl_reloc_overflow (struct link_map *map,
 void
 __process_machine_rela (struct link_map *map,
 			const Elf32_Rela *reloc,
+			struct link_map *sym_map,
 			const Elf32_Sym *sym,
 			const Elf32_Sym *refsym,
 			Elf32_Addr *const reloc_addr,
@@ -541,6 +542,53 @@ __process_machine_rela (struct link_map *map,
       }
       break;
 
+#ifdef USE_TLS
+#define CHECK_STATIC_TLS(map, sym_map)					      \
+    do {								      \
+      if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0))     \
+	_dl_allocate_static_tls (sym_map);				      \
+    } while (0)
+# define DO_TLS_RELOC(suffix)						      \
+    case R_PPC_DTPREL##suffix:						      \
+      /* During relocation all TLS symbols are defined and used.	      \
+	 Therefore the offset is already correct.  */			      \
+      if (sym_map != NULL)						      \
+	do_reloc##suffix ("R_PPC_DTPREL"#suffix,			      \
+			  TLS_DTPREL_VALUE (sym, reloc));		      \
+      break;								      \
+    case R_PPC_TPREL##suffix:						      \
+      if (sym_map != NULL)						      \
+	{								      \
+	  CHECK_STATIC_TLS (map, sym_map);				      \
+	  do_reloc##suffix ("R_PPC_TPREL"#suffix,			      \
+			    TLS_TPREL_VALUE (sym_map, sym, reloc));	      \
+	}								      \
+      break;
+
+    inline void do_reloc16 (const char *r_name, Elf32_Addr value)
+      {
+	if (__builtin_expect (value > 0x7fff && value < 0xffff8000, 0))
+	  _dl_reloc_overflow (map, r_name, reloc_addr, sym, refsym);
+	*(Elf32_Half *) reloc_addr = value;
+      }
+    inline void do_reloc16_LO (const char *r_name, Elf32_Addr value)
+      {
+	*(Elf32_Half *) reloc_addr = value;
+      }
+    inline void do_reloc16_HI (const char *r_name, Elf32_Addr value)
+      {
+	*(Elf32_Half *) reloc_addr = value >> 16;
+      }
+    inline void do_reloc16_HA (const char *r_name, Elf32_Addr value)
+      {
+	*(Elf32_Half *) reloc_addr = (value + 0x8000) >> 16;
+      }
+    DO_TLS_RELOC (16)
+    DO_TLS_RELOC (16_LO)
+    DO_TLS_RELOC (16_HI)
+    DO_TLS_RELOC (16_HA)
+#endif
+
     default:
       _dl_reloc_bad_type (map, rinfo, 0);
       return;
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index 2f35275af9..e26c2d544b 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -336,6 +336,7 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
    has been determined.  */
 extern void __process_machine_rela (struct link_map *map,
 				    const Elf32_Rela *reloc,
+				    struct link_map *sym_map,
 				    const Elf32_Sym *sym,
 				    const Elf32_Sym *refsym,
 				    Elf32_Addr *const reloc_addr,
@@ -361,9 +362,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   const Elf32_Sym *const refsym = sym;
   Elf32_Addr value;
   const int r_type = ELF32_R_TYPE (reloc->r_info);
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
-  struct link_map *sym_map;
-#endif
+  struct link_map *sym_map = NULL;
 
 #ifndef RESOLVE_CONFLICT_FIND_MAP
   if (r_type == R_PPC_RELATIVE)
@@ -411,71 +410,37 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
       *reloc_addr = value;
       break;
 
-#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
-    case R_PPC_DTPMOD32:
-# ifdef RTLD_BOOTSTRAP
-      /* During startup the dynamic linker is always index 1.  */
-      *reloc_addr = 1;
-# else
-      /* Get the information from the link map returned by the
-	 RESOLVE_MAP function.  */
-      if (sym_map != NULL)
-	*reloc_addr = sym_map->l_tls_modid;
-# endif
-      break;
-
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \
+    && !defined RESOLVE_CONFLICT_FIND_MAP
 # ifdef RTLD_BOOTSTRAP
 #  define NOT_BOOTSTRAP 0
 # else
 #  define NOT_BOOTSTRAP 1
 # endif
-# define DO_TLS_RELOC(suffix)						      \
-    case R_PPC_DTPREL##suffix:						      \
-      /* During relocation all TLS symbols are defined and used.	      \
-	 Therefore the offset is already correct.  */			      \
-      if (NOT_BOOTSTRAP)						      \
-	do_reloc##suffix ("R_PPC_DTPREL"#suffix,			      \
-			  TLS_DTPREL_VALUE (sym, reloc));		      \
-      break;								      \
-    case R_PPC_TPREL##suffix:						      \
-      if (!NOT_BOOTSTRAP || sym_map)					      \
-	{								      \
-	  if (NOT_BOOTSTRAP)						      \
-	    CHECK_STATIC_TLS (map, sym_map);				      \
-	  do_reloc##suffix ("R_PPC_TPREL"#suffix,			      \
-			    TLS_TPREL_VALUE (sym_map, sym, reloc));	      \
-	}								      \
-      break;
 
-      inline void do_reloc32 (const char *r_name, Elf32_Addr value)
+    case R_PPC_DTPMOD32:
+      if (!NOT_BOOTSTRAP)
+	/* During startup the dynamic linker is always index 1.  */
+	*reloc_addr = 1;
+      else if (sym_map != NULL)
+	/* Get the information from the link map returned by the
+	   RESOLVE_MAP function.  */
+	*reloc_addr = sym_map->l_tls_modid;
+      break;
+    case R_PPC_DTPREL32:
+      /* During relocation all TLS symbols are defined and used.
+	 Therefore the offset is already correct.  */
+      if (NOT_BOOTSTRAP && sym_map != NULL)
+	*reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
+      break;
+    case R_PPC_TPREL32:
+      if (!NOT_BOOTSTRAP || sym_map != NULL)
 	{
-	  *reloc_addr = value;
+	  if (NOT_BOOTSTRAP)
+	    CHECK_STATIC_TLS (map, sym_map);
+	  *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
 	}
-    DO_TLS_RELOC (32)
-# ifndef RTLD_BOOTSTRAP		/* PIC code like ld.so doesn't use these.  */
-    inline void do_reloc16 (const char *r_name, Elf32_Addr value)
-      {
-	if (__builtin_expect (value > 0x7fff && value < 0xffff8000, 0))
-	  _dl_reloc_overflow (map,  "R_PPC_ADDR16", reloc_addr, sym, refsym);
-	*(Elf32_Half *) reloc_addr = value;
-      }
-    inline void do_reloc16_LO (const char *r_name, Elf32_Addr value)
-      {
-	*(Elf32_Half *) reloc_addr = value;
-      }
-    inline void do_reloc16_HI (const char *r_name, Elf32_Addr value)
-      {
-	*(Elf32_Half *) reloc_addr = value >> 16;
-      }
-    inline void do_reloc16_HA (const char *r_name, Elf32_Addr value)
-      {
-	*(Elf32_Half *) reloc_addr = (value + 0x8000) >> 16;
-      }
-    DO_TLS_RELOC (16)
-    DO_TLS_RELOC (16_LO)
-    DO_TLS_RELOC (16_HI)
-    DO_TLS_RELOC (16_HA)
-# endif
+      break;
 #endif /* USE_TLS etc. */
 
 #ifdef RESOLVE_CONFLICT_FIND_MAP
@@ -485,7 +450,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 #endif
 
     default:
-      __process_machine_rela (map, reloc, sym, refsym,
+      __process_machine_rela (map, reloc, sym_map, sym, refsym,
 			      reloc_addr, value, r_type);
     }
 }