diff mbox

Support for R_ARM_IRELATIVE relocations

Message ID g48vwh3ced.fsf@linaro.org
State Accepted
Headers show

Commit Message

Richard Sandiford March 14, 2011, 4:16 p.m. UTC
ARM have allocated R_ARM_IRELATIVE the relocation number 160 (thanks).
This patch adds GLIBC support for it.  Like PPC, the relocation is only
allowed in the normal DT_REL(A) table, not in DT_JMPREL.

Tested on arm-linux-gnueabi with --enable-multi-arch.  All ifunc* tests
passed.  (I actually cross-tested using EGLIBC, with a local patch to
make the ifunc tests cross-testing friendly.  I also used a dummy
arm/multiarch/Makefile, so that --enable-multi-arch was honoured.)

Please install if OK.

Richard


2011-03-14  Richard Sandiford  <richard.sandiford@linaro.org>

libc/
	* elf/elf.h (R_ARM_IRELATIVE): Define.

ports/
	* sysdeps/arm/dl-machine.h (elf_machine_rel): Handle STT_GNU_IFUNC
	and R_ARM_IRELATIVE.
	(elf_machine_rela): Likewise.
	* sysdeps/arm/dl-irel.h: New file.

Comments

Joseph Myers March 17, 2011, 7:43 p.m. UTC | #1
On Mon, 14 Mar 2011, Richard Sandiford wrote:

> libc/
> 	* elf/elf.h (R_ARM_IRELATIVE): Define.

You'll need to send this part of the patch to libc-alpha - relative to 
current sources since the patch as sent here won't apply to current 
sources now R_ARM_THM_TLS_DESCSEQ has been added there.  (I haven't 
checked whether the ARM-specific patch also needs updates to apply cleanly 
after the TLS descriptors changes went in, but it certainly depends on 
having the relocation number defined in libc.)
Joseph Myers April 26, 2011, 9:02 p.m. UTC | #2
On Mon, 14 Mar 2011, Richard Sandiford wrote:

> ARM have allocated R_ARM_IRELATIVE the relocation number 160 (thanks).
> This patch adds GLIBC support for it.  Like PPC, the relocation is only
> allowed in the normal DT_REL(A) table, not in DT_JMPREL.
> 
> Tested on arm-linux-gnueabi with --enable-multi-arch.  All ifunc* tests
> passed.  (I actually cross-tested using EGLIBC, with a local patch to
> make the ifunc tests cross-testing friendly.  I also used a dummy
> arm/multiarch/Makefile, so that --enable-multi-arch was honoured.)
> 
> Please install if OK.

Thanks.  I've committed the ports changes now that the relocation is in 
libc.
diff mbox

Patch

Index: libc/elf/elf.h
===================================================================
--- libc/elf/elf.h	2011-03-14 16:12:41.000000000 +0000
+++ libc/elf/elf.h	2011-03-14 16:12:56.000000000 +0000
@@ -2353,6 +2353,7 @@  #define R_ARM_TLS_IE32		107	/* PC-rel 32
 					   static TLS block offset */
 #define R_ARM_TLS_LE32		108	/* 32 bit offset relative to static
 					   TLS block */
+#define R_ARM_IRELATIVE		160
 #define R_ARM_RXPC25		249
 #define R_ARM_RSBREL32		250
 #define R_ARM_THM_RPC22		251
Index: ports/sysdeps/arm/dl-irel.h
===================================================================
--- /dev/null	2011-03-14 08:51:58.266827044 +0000
+++ ports/sysdeps/arm/dl-irel.h	2011-03-14 16:12:56.000000000 +0000
@@ -0,0 +1,45 @@ 
+/* Machine-dependent ELF indirect relocation inline functions.
+   ARM version.
+   Copyright (C) 2009, 2010 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.  */
+
+#ifndef _DL_IREL_H
+#define _DL_IREL_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define ELF_MACHINE_IREL	1
+
+static inline void
+__attribute ((always_inline))
+elf_irel (const Elf32_Rel *reloc)
+{
+  Elf32_Addr *const reloc_addr = (void *) reloc->r_offset;
+  const unsigned long int r_type = ELF32_R_TYPE (reloc->r_info);
+
+  if (__builtin_expect (r_type == R_ARM_IRELATIVE, 1))
+    {
+      Elf32_Addr value = ((Elf32_Addr (*) (void)) (*reloc_addr)) ();
+      *reloc_addr = value;
+    }
+  else
+    __libc_fatal ("unexpected reloc type in static binary");
+}
+
+#endif /* dl-irel.h */
Index: ports/sysdeps/arm/dl-machine.h
===================================================================
--- ports/sysdeps/arm/dl-machine.h	2011-03-14 16:12:41.000000000 +0000
+++ ports/sysdeps/arm/dl-machine.h	2011-03-14 16:12:56.000000000 +0000
@@ -367,6 +367,12 @@  elf_machine_rel (struct link_map *map, c
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
+      if (sym != NULL
+	  && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
+			       0)
+	  && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+	value = ((Elf32_Addr (*) (void)) value) ();
+
       switch (r_type)
 	{
 	case R_ARM_COPY:
@@ -447,7 +453,8 @@  elf_machine_rel (struct link_map *map, c
 	     *reloc_addr = value;
 	  }
 	  break;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+#if !defined RTLD_BOOTSTRAP
+#if defined USE_TLS
 	case R_ARM_TLS_DTPMOD32:
 	  /* Get the information from the link map returned by the
 	     resolv function.  */
@@ -468,6 +475,12 @@  elf_machine_rel (struct link_map *map, c
 	    }
 	  break;
 #endif
+	case R_ARM_IRELATIVE:
+	  value = map->l_addr + *reloc_addr;
+	  value = ((Elf32_Addr (*) (void)) value) ();
+	  *reloc_addr = value;
+	  break;
+#endif
 	default:
 	  _dl_reloc_bad_type (map, r_type, 0);
 	  break;
@@ -497,6 +510,12 @@  elf_machine_rela (struct link_map *map, 
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
+      if (sym != NULL
+	  && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
+			       0)
+	  && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+	value = ((Elf32_Addr (*) (void)) value) ();
+
       switch (r_type)
 	{
 #  ifndef RESOLVE_CONFLICT_FIND_MAP
@@ -548,7 +567,8 @@  elf_machine_rela (struct link_map *map, 
 	     *reloc_addr = value;
 	  }
 	  break;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+#if !defined RTLD_BOOTSTRAP
+#if defined USE_TLS
 	case R_ARM_TLS_DTPMOD32:
 	  /* Get the information from the link map returned by the
 	     resolv function.  */
@@ -569,6 +589,12 @@  elf_machine_rela (struct link_map *map, 
 	    }
 	  break;
 #endif
+	case R_ARM_IRELATIVE:
+	  value = map->l_addr + *reloc_addr;
+	  value = ((Elf32_Addr (*) (void)) value) ();
+	  *reloc_addr = value;
+	  break;
+#endif
 	default:
 	  _dl_reloc_bad_type (map, r_type, 0);
 	  break;