Mark Wielaard b82746
commit 96d3b0aeddbb8c5557fdc5769e4d73eac81d74fd
Mark Wielaard b82746
Author: Mark Wielaard <mjw@redhat.com>
Mark Wielaard b82746
Date:   Thu Dec 19 16:11:19 2013 +0100
Mark Wielaard b82746
Mark Wielaard b82746
    backends: aarch64 always has _GLOBAL_OFFSET_TABLE_ point to .got[0].
Mark Wielaard b82746
    
Mark Wielaard b82746
    Like some other architectures aarch64 has a special rule for the
Mark Wielaard b82746
    _GLOBAL_OFFSET_TABLE_ symbol. Even if there is a .plt.got section the symbol
Mark Wielaard b82746
    value still points to the start of the .got section. This is also what the
Mark Wielaard b82746
    dynamic linker expects.
Mark Wielaard b82746
    
Mark Wielaard b82746
    See https://sourceware.org/ml/libc-ports/2013-06/msg00057.html
Mark Wielaard b82746
    
Mark Wielaard b82746
    Signed-off-by: Mark Wielaard <mjw@redhat.com>
Mark Wielaard b82746
Mark Wielaard b82746
diff --git a/backends/aarch64_init.c b/backends/aarch64_init.c
Mark Wielaard b82746
index 749af2a..d663d40 100644
Mark Wielaard b82746
--- a/backends/aarch64_init.c
Mark Wielaard b82746
+++ b/backends/aarch64_init.c
Mark Wielaard b82746
@@ -56,6 +56,7 @@ aarch64_init (elf, machine, eh, ehlen)
Mark Wielaard b82746
   HOOK (eh, core_note);
Mark Wielaard b82746
   HOOK (eh, reloc_simple_type);
Mark Wielaard b82746
   HOOK (eh, return_value_location);
Mark Wielaard b82746
+  HOOK (eh, check_special_symbol);
Mark Wielaard b82746
 
Mark Wielaard b82746
   return MODVERSION;
Mark Wielaard b82746
 }
Mark Wielaard b82746
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
Mark Wielaard b82746
index b0f3377..4e1dbd8 100644
Mark Wielaard b82746
--- a/backends/aarch64_symbol.c
Mark Wielaard b82746
+++ b/backends/aarch64_symbol.c
Mark Wielaard b82746
@@ -32,6 +32,7 @@
Mark Wielaard b82746
 
Mark Wielaard b82746
 #include <elf.h>
Mark Wielaard b82746
 #include <stddef.h>
Mark Wielaard b82746
+#include <string.h>
Mark Wielaard b82746
 
Mark Wielaard b82746
 #define BACKEND		aarch64_
Mark Wielaard b82746
 #include "libebl_CPU.h"
Mark Wielaard b82746
@@ -54,3 +55,30 @@ aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
Mark Wielaard b82746
       return ELF_T_NUM;
Mark Wielaard b82746
     }
Mark Wielaard b82746
 }
Mark Wielaard b82746
+
Mark Wielaard b82746
+/* If this is the _GLOBAL_OFFSET_TABLE_ symbol, then it should point to
Mark Wielaard b82746
+   .got[0] even if there is a .got.plt section.  */
Mark Wielaard b82746
+bool
Mark Wielaard b82746
+aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
Mark Wielaard b82746
+                              const char *name, const GElf_Shdr *destshdr)
Mark Wielaard b82746
+{
Mark Wielaard b82746
+  if (name != NULL
Mark Wielaard b82746
+      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
Mark Wielaard b82746
+    {
Mark Wielaard b82746
+      const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
Mark Wielaard b82746
+      if (sname != NULL && strcmp (sname, ".got.plt") == 0)
Mark Wielaard b82746
+	{
Mark Wielaard b82746
+	  Elf_Scn *scn = NULL;
Mark Wielaard b82746
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
Mark Wielaard b82746
+	    {
Mark Wielaard b82746
+	      GElf_Shdr shdr_mem;
Mark Wielaard b82746
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Mark Wielaard b82746
+	      sname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name);
Mark Wielaard b82746
+	      if (name != NULL && strcmp (sname, ".got") == 0)
Mark Wielaard b82746
+		return sym->st_value == shdr->sh_addr;
Mark Wielaard b82746
+	    }
Mark Wielaard b82746
+	}
Mark Wielaard b82746
+    }
Mark Wielaard b82746
+
Mark Wielaard b82746
+  return false;
Mark Wielaard b82746
+}