[prev in list] [next in list] [prev in thread] [next in thread] 

List:       binutils-cvs
Subject:    [binutils-gdb] [AArch64] Only override the symbol dynamic decision on undefined weak symbol
From:       Jiong Wang <jiwang () sourceware ! org>
Date:       2017-06-29 10:54:00
Message-ID: 20170629105400.10297.qmail () sourceware ! org
[Download RAW message or body]

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ff07562f1e369b6e37eafb2a888dc48fa2453e86

commit ff07562f1e369b6e37eafb2a888dc48fa2453e86
Author: Jiong Wang <jiong.wang@arm.com>
Date:   Thu Jun 29 11:47:43 2017 +0100

    [AArch64] Only override the symbol dynamic decision on undefined weak symbol
    
    This fix is an adaption of the x86-64 PR ld/21402 fix to AArch64.
    
    After the generic code deciding one symbol is not dynamic, AArch64 backend
    only overrides the decision on undefined weak symbols.
    
    bfd/
    	PR ld/21402
    	* elfnn-aarch64.c (elfNN_aarch64_allocate_dynrelocs): Only make
    	undefined weak symbols into dynamic.
    	(elfNN_aarch64_final_link_relocate): Generate runtime RELATIVE
    	relocation for non-dynamic symbols.
    	(elfNN_aarch64_finish_dynamic_symbol): Add sanity check.

Diff:
---
 bfd/ChangeLog       |  9 ++++++
 bfd/elfnn-aarch64.c | 82 ++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 68 insertions(+), 23 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 8975b26..5045c81 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,14 @@
 2017-06-29  Jiong Wang  <jiong.wang@arm.com>
 
+        PR ld/21402
+	* elfnn-aarch64.c (elfNN_aarch64_allocate_dynrelocs): Only make
+	undefined weak symbols into dynamic.
+	(elfNN_aarch64_final_link_relocate): Generate runtime RELATIVE
+	relocation for non-dynamic symbols.
+	(elfNN_aarch64_finish_dynamic_symbol): Add sanity check.
+
+2017-06-29  Jiong Wang  <jiong.wang@arm.com>
+
 	* elfnn-aarch64.c (aarch64_relocation_aginst_gp_p): New function.
 	(elfNN_aarch64_final_link_relocate): Delete duplicated code for
 	BFD_RELOC_AARCH64_LD64_GOTOFF_LO15, BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC,
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4817e42..1195448 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4944,11 +4944,13 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     = elfNN_aarch64_bfd_reloc_from_howto (howto);
   unsigned long r_symndx;
   bfd_byte *hit_data = contents + rel->r_offset;
-  bfd_vma place, off;
+  bfd_vma place, off, got_entry_addr;
   bfd_signed_vma signed_addend;
   struct elf_aarch64_link_hash_table *globals;
   bfd_boolean weak_undef_p;
+  bfd_boolean relative_reloc;
   asection *base_got;
+  bfd_vma orig_value = value;
 
   globals = elf_aarch64_hash_table (info);
 
@@ -5383,12 +5385,32 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
       if (globals->root.sgot == NULL)
 	BFD_ASSERT (h != NULL);
 
+      relative_reloc = FALSE;
       if (h != NULL)
 	{
 	  bfd_vma addend = 0;
+
+	  /* If a symbol is not dynamic and is not undefined weak, bind it
+	     locally and generate a RELATIVE relocation under PIC mode.
+
+	     NOTE: one symbol may be referenced by several relocations, we
+	     should only generate one RELATIVE relocation for that symbol.
+	     Therefore, check GOT offset mark first.  */
+	  if (h->dynindx == -1
+	      && !h->forced_local
+	      && h->root.type != bfd_link_hash_undefweak
+	      && bfd_link_pic (info)
+	      && !symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+	    relative_reloc = TRUE;
+
 	  value = aarch64_calculate_got_entry_vma (h, globals, info, value,
 						   output_bfd,
 						   unresolved_reloc_p);
+	  /* Record the GOT entry address which will be used when generating
+	     RELATIVE relocation.  */
+	  if (relative_reloc)
+	    got_entry_addr = value;
+
 	  if (aarch64_relocation_aginst_gp_p (bfd_r_type))
 	    addend = (globals->root.sgot->output_section->vma
 		      + globals->root.sgot->output_offset);
@@ -5414,32 +5436,20 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 
 	off = symbol_got_offset (input_bfd, h, r_symndx);
 	base_got = globals->root.sgot;
-	bfd_vma got_entry_addr = (base_got->output_section->vma
-				  + base_got->output_offset + off);
+	got_entry_addr = (base_got->output_section->vma
+			  + base_got->output_offset + off);
 
 	if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
 	  {
 	    bfd_put_64 (output_bfd, value, base_got->contents + off);
 
+	    /* For local symbol, we have done absolute relocation in static
+	       linking stage.  While for shared library, we need to update the
+	       content of GOT entry according to the shared object's runtime
+	       base address.  So, we need to generate a R_AARCH64_RELATIVE reloc
+	       for dynamic linker.  */
 	    if (bfd_link_pic (info))
-	      {
-		asection *s;
-		Elf_Internal_Rela outrel;
-
-		/* For local symbol, we have done absolute relocation in static
-		   linking stageh. While for share library, we need to update
-		   the content of GOT entry according to the share objects
-		   loading base address. So we need to generate a
-		   R_AARCH64_RELATIVE reloc for dynamic linker.  */
-		s = globals->root.srelgot;
-		if (s == NULL)
-		  abort ();
-
-		outrel.r_offset = got_entry_addr;
-		outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
-		outrel.r_addend = value;
-		elf_append_rela (output_bfd, s, &outrel);
-	      }
+	      relative_reloc = TRUE;
 
 	    symbol_got_offset_mark (input_bfd, h, r_symndx);
 	  }
@@ -5454,6 +5464,21 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 	value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
 						     addend, weak_undef_p);
       }
+
+      if (relative_reloc)
+	{
+	  asection *s;
+	  Elf_Internal_Rela outrel;
+
+	  s = globals->root.srelgot;
+	  if (s == NULL)
+	    abort ();
+
+	  outrel.r_offset = got_entry_addr;
+	  outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
+	  outrel.r_addend = orig_value;
+	  elf_append_rela (output_bfd, s, &outrel);
+	}
       break;
 
     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
@@ -8021,7 +8046,8 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
     {
       /* Make sure this symbol is output as a dynamic symbol.
          Undefined weak syms won't yet be marked as dynamic.  */
-      if (h->dynindx == -1 && !h->forced_local)
+      if (h->dynindx == -1 && !h->forced_local
+	  && h->root.type == bfd_link_hash_undefweak)
 	{
 	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
 	    return FALSE;
@@ -8102,7 +8128,8 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* Make sure this symbol is output as a dynamic symbol.
          Undefined weak syms won't yet be marked as dynamic.  */
-      if (dyn && h->dynindx == -1 && !h->forced_local)
+      if (dyn && h->dynindx == -1 && !h->forced_local
+	  && h->root.type == bfd_link_hash_undefweak)
 	{
 	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
 	    return FALSE;
@@ -8221,6 +8248,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	     symbol in PIEs.  */
 	  else if (h->dynindx == -1
 		   && !h->forced_local
+		   && h->root.type == bfd_link_hash_undefweak
 		   && !bfd_elf_link_record_dynamic_symbol (info, h))
 	    return FALSE;
 	}
@@ -8243,6 +8271,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	     Undefined weak syms won't yet be marked as dynamic.  */
 	  if (h->dynindx == -1
 	      && !h->forced_local
+	      && h->root.type == bfd_link_hash_undefweak
 	      && !bfd_elf_link_record_dynamic_symbol (info, h))
 	    return FALSE;
 
@@ -8863,6 +8892,13 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
   struct elf_aarch64_link_hash_table *htab;
   htab = elf_aarch64_hash_table (info);
 
+  /* Sanity check to make sure no unexpected symbol reaches here.  */
+    if (h->dynindx == -1
+	&& !h->forced_local
+	&& h->root.type != bfd_link_hash_undefweak
+	&& bfd_link_pic (info))
+      abort ();
+
   if (h->plt.offset != (bfd_vma) - 1)
     {
       asection *plt, *gotplt, *relplt;

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic