Blame SOURCES/binutils-2.23.52.0.1-aarch64-local-GOT-entries.patch

d570a8
--- binutils-2.23.52.0.1.orig/bfd/elf64-aarch64.c	2015-07-29 15:17:32.056365096 +0100
d570a8
+++ binutils-2.23.52.0.1/bfd/elf64-aarch64.c	2015-07-29 16:37:17.550432586 +0100
d570a8
@@ -3932,10 +3932,11 @@ elf64_aarch64_final_link_relocate (reloc
d570a8
   unsigned int r_type = howto->type;
d570a8
   unsigned long r_symndx;
d570a8
   bfd_byte *hit_data = contents + rel->r_offset;
d570a8
-  bfd_vma place;
d570a8
+  bfd_vma place, off;
d570a8
   bfd_signed_vma signed_addend;
d570a8
   struct elf64_aarch64_link_hash_table *globals;
d570a8
   bfd_boolean weak_undef_p;
d570a8
+  asection *base_got;
d570a8
 
d570a8
   globals = elf64_aarch64_hash_table (info);
d570a8
 
d570a8
@@ -3971,8 +3972,6 @@ elf64_aarch64_final_link_relocate (reloc
d570a8
     {
d570a8
       asection *plt;
d570a8
       const char *name;
d570a8
-      asection *base_got;
d570a8
-      bfd_vma off;
d570a8
 
d570a8
       if ((input_section->flags & SEC_ALLOC) == 0
d570a8
 	  || h->plt.offset == (bfd_vma) -1)
d570a8
@@ -4326,6 +4325,58 @@ elf64_aarch64_final_link_relocate (reloc
d570a8
 	  value = aarch64_resolve_relocation (r_type, place, value,
d570a8
 					      0, weak_undef_p);
d570a8
 	}
d570a8
+      else
d570a8
+	{
d570a8
+	  struct elf_aarch64_local_symbol *locals
d570a8
+	    = elf64_aarch64_locals (input_bfd);
d570a8
+
d570a8
+	  if (locals == NULL)
d570a8
+	    {
d570a8
+	      (*_bfd_error_handler)
d570a8
+		(_("%B: Local symbol descriptor table be NULL when applying "
d570a8
+		   "relocation against local symbol"),
d570a8
+		 input_bfd);
d570a8
+	      abort ();
d570a8
+	    }
d570a8
+
d570a8
+	  off = symbol_got_offset (input_bfd, h, r_symndx);
d570a8
+	  base_got = globals->root.sgot;
d570a8
+	  bfd_vma got_entry_addr = (base_got->output_section->vma
d570a8
+				    + base_got->output_offset + off);
d570a8
+
d570a8
+	  if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
d570a8
+	    {
d570a8
+	      bfd_put_64 (output_bfd, value, base_got->contents + off);
d570a8
+
d570a8
+	      if (info->shared)
d570a8
+		{
d570a8
+		  asection *s;
d570a8
+		  Elf_Internal_Rela outrel;
d570a8
+
d570a8
+		  /* For local symbol, we have done absolute relocation in static
d570a8
+		     linking stageh. While for share library, we need to update
d570a8
+		     the content of GOT entry according to the share objects
d570a8
+		     loading base address. So we need to generate a
d570a8
+		     R_AARCH64_RELATIVE reloc for dynamic linker.  */
d570a8
+		  s = globals->root.srelgot;
d570a8
+		  if (s == NULL)
d570a8
+		    abort ();
d570a8
+
d570a8
+		  outrel.r_offset = got_entry_addr;
d570a8
+		  outrel.r_info = ELF64_R_INFO (0, R_AARCH64_RELATIVE);
d570a8
+		  outrel.r_addend = value;
d570a8
+		  elf_append_rela (output_bfd, s, &outrel);
d570a8
+		}
d570a8
+
d570a8
+	      symbol_got_offset_mark (input_bfd, h, r_symndx);
d570a8
+	    }
d570a8
+
d570a8
+	  /* Update the relocation value to GOT entry addr as we have transformed
d570a8
+	     the direct data access into indirect data access through GOT.  */
d570a8
+	  value = got_entry_addr;
d570a8
+	  value = aarch64_resolve_relocation (r_type, place, value,
d570a8
+					      0, weak_undef_p);
d570a8
+	}
d570a8
       break;
d570a8
 
d570a8
     case R_AARCH64_TLSGD_ADR_PAGE21:
d570a8
@@ -7032,7 +7083,8 @@ elf64_aarch64_size_dynamic_sections (bfd
d570a8
 		  htab->root.sgot->size += GOT_ENTRY_SIZE * 2;
d570a8
 		}
d570a8
 
d570a8
-	      if (got_type & GOT_TLS_IE)
d570a8
+	      if (got_type & GOT_TLS_IE
d570a8
+		  || got_type & GOT_NORMAL)
d570a8
 		{
d570a8
 		  locals[i].got_offset = htab->root.sgot->size;
d570a8
 		  htab->root.sgot->size += GOT_ENTRY_SIZE;
d570a8
@@ -7042,10 +7094,6 @@ elf64_aarch64_size_dynamic_sections (bfd
d570a8
 		{
d570a8
 		}
d570a8
 
d570a8
-	      if (got_type == GOT_NORMAL)
d570a8
-		{
d570a8
-		}
d570a8
-
d570a8
 	      if (info->shared)
d570a8
 		{
d570a8
 		  if (got_type & GOT_TLSDESC_GD)
d570a8
@@ -7058,7 +7106,8 @@ elf64_aarch64_size_dynamic_sections (bfd
d570a8
 		  if (got_type & GOT_TLS_GD)
d570a8
 		    htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
d570a8
 
d570a8
-		  if (got_type & GOT_TLS_IE)
d570a8
+		  if (got_type & GOT_TLS_IE
d570a8
+		      || got_type & GOT_NORMAL)
d570a8
 		    htab->root.srelgot->size += RELOC_SIZE (htab);
d570a8
 		}
d570a8
 	    }