about summary refs log tree commit diff
path: root/sysdeps/powerpc/powerpc32/dl-machine.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2003-04-24 17:10:52 +0000
committerRoland McGrath <roland@gnu.org>2003-04-24 17:10:52 +0000
commit545dbc9345c81963ee3b48b0104807f06fda7b28 (patch)
treea881f7258fe383ddf1c20e0ca4f1e28f28f70ad1 /sysdeps/powerpc/powerpc32/dl-machine.c
parent345d920835ed818a09cf242da31adf7e9981f614 (diff)
downloadglibc-545dbc9345c81963ee3b48b0104807f06fda7b28.tar.gz
glibc-545dbc9345c81963ee3b48b0104807f06fda7b28.tar.xz
glibc-545dbc9345c81963ee3b48b0104807f06fda7b28.zip
2003-04-24 Jakub Jelinek <jakub@redhat.com>
	* elf/dl-reloc.c (allocate_static_tls): Rename to...
	(_dl_allocate_static_tls): ... this function.  No longer static.
	(CHECK_STATIC_TLS): Adjust.
	* sysdeps/generic/ldsodefs.h (_dl_allocate_static_tls): New prototype.
	* sysdeps/powerpc/powerpc32/dl-machine.h (__process_machine_rela):
	Add SYM_MAP argument.
	(elf_machine_rela): Adjust caller.  Declare SYM_MAP unconditionally.
	Check if SYM_MAP != NULL for R_PPC_DTPREL32.  Only handle 32-bit
	TLS relocs here.  #ifdef out relocs which never appear in
	.gnu.conflict section from dl-conflict.c processing.
	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
	Add SYM_MAP argument.  Handle 16-bit TLS relocs here.
Diffstat (limited to 'sysdeps/powerpc/powerpc32/dl-machine.c')
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.c48
1 files changed, 48 insertions, 0 deletions
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;