[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[patches] Backport MIPS prelinker patches to 2.5



This patch backports the MIPS prelinker patches to 2.5.
Tested on MIPS.  OK to install?

Richard

libc/
	Backport from mainline:

	2006-10-27  Richard Sandiford  <richard@xxxxxxxxxxxxxxxx>

	* elf/elf.h (R_MIPS_GLOB_DAT): Define.
	(R_MIPS_NUM): Bump by 1.

ports/
	Backport from mainline:

	2007-01-08  Richard Sandiford  <richard@xxxxxxxxxxxxxxxx>

	* sysdeps/mips/dl-machine.h (ELF_MACHINE_NO_RELA): Delete.
	(elf_machine_reloc): New function, retaining the body of
	elf_machine_rel.  Take the reloc's r_info field as an argument,
	not the reloc itself.  Add extra r_addend and inplace_p arguments.
	When inplace_p is false, use r_addend as the addend, not the contents
	of the relocation field.  Hoist the conversion of reloc_addr to
	"ELFW(Addr) *".  Don't try to apply TLS relocations against
	undefined symbols.  Add R_MIPS_GLOB_DAT support.
	(elf_machine_rel, elf_machine_rela): Use elf_machine_reloc.
	(elf_machine_lazy_rel): Change the reloc type from ElfW(Rel)
	to ElfW(Rela).

Index: elf/elf.h
===================================================================
--- elf/elf.h	(revision 1541)
+++ elf/elf.h	(working copy)
@@ -1511,8 +1511,9 @@ #define R_MIPS_TLS_TPREL32	47	/* TP-rela
 #define R_MIPS_TLS_TPREL64	48	/* TP-relative offset, 64 bit */
 #define R_MIPS_TLS_TPREL_HI16	49	/* TP-relative offset, high 16 bits */
 #define R_MIPS_TLS_TPREL_LO16	50	/* TP-relative offset, low 16 bits */
+#define R_MIPS_GLOB_DAT		51
 /* Keep this the last entry.  */
-#define R_MIPS_NUM		51
+#define R_MIPS_NUM		52
 
 /* Legal values for p_type field of Elf32_Phdr.  */
 
Index: sysdeps/mips/dl-machine.h
===================================================================
--- sysdeps/mips/dl-machine.h	(revision 1541)
+++ sysdeps/mips/dl-machine.h	(working copy)
@@ -282,9 +282,6 @@ #define RTLD_START asm (\
 	".previous"\
 );
 
-/* The MIPS never uses Elfxx_Rela relocations.  */
-#define ELF_MACHINE_NO_RELA 1
-
 /* Names of the architecture-specific auditing callback functions.  */
 # if _MIPS_SIM == _ABIO32
 #  define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
@@ -301,16 +298,18 @@ #define ELF_MACHINE_NO_RELA 1
 
 #ifdef RESOLVE_MAP
 
-/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+/* Perform a relocation described by R_INFO at the location pointed to
+   by RELOC_ADDR.  SYM is the relocation symbol specified by R_INFO and
    MAP is the object containing the reloc.  */
 
 auto inline void
 __attribute__ ((always_inline))
-elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
-		 const ElfW(Sym) *sym, const struct r_found_version *version,
-		 void *const reloc_addr)
+elf_machine_reloc (struct link_map *map, ElfW(Word) r_info,
+		   const ElfW(Sym) *sym, const struct r_found_version *version,
+		   void *reloc_addr, ElfW(Addr) r_addend, int inplace_p)
 {
-  const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
+  const unsigned long int r_type = ELFW(R_TYPE) (r_info);
+  ElfW(Addr) *addr_field = (ElfW(Addr) *) reloc_addr;
 
 #if !defined RTLD_BOOTSTRAP && !defined SHARED
   /* This is defined in rtld.c, but nowhere in the static libc.a;
@@ -342,18 +341,28 @@ elf_machine_rel (struct link_map *map, c
 	  case R_MIPS_TLS_DTPMOD64:
 	  case R_MIPS_TLS_DTPMOD32:
 	    if (sym_map)
-	      *(ElfW(Addr) *)reloc_addr = sym_map->l_tls_modid;
+	      *addr_field = sym_map->l_tls_modid;
 	    break;
 
 	  case R_MIPS_TLS_DTPREL64:
 	  case R_MIPS_TLS_DTPREL32:
-	    *(ElfW(Addr) *)reloc_addr += TLS_DTPREL_VALUE (sym);
+	    if (sym)
+	      {
+		if (inplace_p)
+		  r_addend = *addr_field;
+		*addr_field = r_addend + TLS_DTPREL_VALUE (sym);
+	      }
 	    break;
 
 	  case R_MIPS_TLS_TPREL32:
 	  case R_MIPS_TLS_TPREL64:
-	    CHECK_STATIC_TLS (map, sym_map);
-	    *(ElfW(Addr) *)reloc_addr += TLS_TPREL_VALUE (sym_map, sym);
+	    if (sym)
+	      {
+		CHECK_STATIC_TLS (map, sym_map);
+		if (inplace_p)
+		  r_addend = *addr_field;
+		*addr_field = r_addend + TLS_TPREL_VALUE (sym_map, sym);
+	      }
 	    break;
 	  }
 
@@ -367,13 +376,14 @@ elf_machine_rel (struct link_map *map, c
     case R_MIPS_REL32:
 #endif
       {
-	int symidx = ELFW(R_SYM) (reloc->r_info);
+	int symidx = ELFW(R_SYM) (r_info);
 	ElfW(Addr) reloc_value;
 
-	/* Support relocations on mis-aligned offsets.  Should we ever
-	   implement RELA, this should be replaced with an assignment
-	   from reloc->r_addend.  */
-	__builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
+	if (inplace_p)
+	  /* Support relocations on mis-aligned offsets.  */
+	  __builtin_memcpy (&reloc_value, reloc_addr, sizeof (reloc_value));
+	else
+	  reloc_value = r_addend;
 
 	if (symidx)
 	  {
@@ -424,6 +434,31 @@ elf_machine_rel (struct link_map *map, c
 	__builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
       }
       break;
+#ifndef RTLD_BOOTSTRAP
+#if _MIPS_SIM == _ABI64
+    case (R_MIPS_64 << 8) | R_MIPS_GLOB_DAT:
+#else
+    case R_MIPS_GLOB_DAT:
+#endif
+      {
+	int symidx = ELFW(R_SYM) (r_info);
+	const ElfW(Word) gotsym
+	  = (const ElfW(Word)) map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
+
+	if (__builtin_expect ((ElfW(Word)) symidx >= gotsym, 1))
+	  {
+	    const ElfW(Addr) *got
+	      = (const ElfW(Addr) *) D_PTR (map, l_info[DT_PLTGOT]);
+	    const ElfW(Word) local_gotno
+	      = ((const ElfW(Word))
+		 map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val);
+
+	    ElfW(Addr) reloc_value = got[symidx + local_gotno - gotsym];
+	    __builtin_memcpy (reloc_addr, &reloc_value, sizeof (reloc_value));
+	  }
+      }
+      break;
+#endif
     case R_MIPS_NONE:		/* Alright, Wilbur.  */
       break;
 #if _MIPS_SIM == _ABI64
@@ -436,7 +471,7 @@ elf_machine_rel (struct link_map *map, c
 	 itself.  For ABI compliance, we ignore such _64 dummy
 	 relocations.  For RELA, this may be simply removed, since
 	 it's totally unnecessary.  */
-      if (ELFW(R_SYM) (reloc->r_info) == 0)
+      if (ELFW(R_SYM) (r_info) == 0)
 	break;
       /* Fall through.  */
 #endif
@@ -446,6 +481,18 @@ elf_machine_rel (struct link_map *map, c
     }
 }
 
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+   MAP is the object containing the reloc.  */
+
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
+		 const ElfW(Sym) *sym, const struct r_found_version *version,
+		 void *const reloc_addr)
+{
+  elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr, 0, 1);
+}
+
 auto inline void
 __attribute__((always_inline))
 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
@@ -457,7 +504,7 @@ elf_machine_rel_relative (ElfW(Addr) l_a
 auto inline void
 __attribute__((always_inline))
 elf_machine_lazy_rel (struct link_map *map,
-		      ElfW(Addr) l_addr, const ElfW(Rel) *reloc)
+		      ElfW(Addr) l_addr, const ElfW(Rela) *reloc)
 {
   /* Do nothing.  */
 }
@@ -468,6 +515,8 @@ elf_machine_rela (struct link_map *map, 
 		  const ElfW(Sym) *sym, const struct r_found_version *version,
 		 void *const reloc_addr)
 {
+  elf_machine_reloc (map, reloc->r_info, sym, version, reloc_addr,
+		     reloc->r_addend, 0);
 }
 
 auto inline void