Blob Blame History Raw
commit 59c108f731e32b4292c4c31c072a9c11f3ca1404
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Mar 8 17:37:30 2013 +0000

            * elf64-aarch64.c (elf_backend_can_gc_sections): Enable
    gc-section support.
            (elf64_aarch64_gc_sweep_hook): Handle GOT, TLS and PLT related relocs.
    
            * lib/ld-lib.exp (check_gc_sections_available): Remove aarch64
    from list of
            targets that don't support gc-section.

diff --git a/bfd/elf64-aarch64.c b/bfd/elf64-aarch64.c
index 61909b9..94d90c5 100644
--- a/bfd/elf64-aarch64.c
+++ b/bfd/elf64-aarch64.c
@@ -1,5 +1,5 @@
 /* ELF support for AArch64.
-   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Copyright 2009-2013 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -4875,6 +4875,137 @@ elf64_aarch64_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
 			     const Elf_Internal_Rela *
 			     relocs ATTRIBUTE_UNUSED)
 {
+  struct elf64_aarch64_link_hash_table *htab;
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  bfd_signed_vma *local_got_refcounts;
+  const Elf_Internal_Rela *rel, *relend;
+
+  if (info->relocatable)
+    return TRUE;
+
+  htab = elf64_aarch64_hash_table (info);
+
+  if (htab == NULL)
+    return FALSE;
+
+  elf_section_data (sec)->local_dynrel = NULL;
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = elf_sym_hashes (abfd);
+
+  local_got_refcounts = elf_local_got_refcounts (abfd);
+
+  relend = relocs + sec->reloc_count;
+  for (rel = relocs; rel < relend; rel++)
+    {
+      unsigned long r_symndx;
+      unsigned int r_type;
+      struct elf_link_hash_entry *h = NULL;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+
+      if (r_symndx >= symtab_hdr->sh_info)
+	{
+	  struct elf64_aarch64_link_hash_entry *eh;
+	  struct elf_dyn_relocs **pp;
+	  struct elf_dyn_relocs *p;
+
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	  eh = (struct elf64_aarch64_link_hash_entry *) h;
+
+	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
+	    {
+	      if (p->sec == sec)
+		{
+		  /* Everything must go for SEC.  */
+		  *pp = p->next;
+		  break;
+		}
+	    }
+        }
+      else
+	{
+	  Elf_Internal_Sym *isym;
+
+	  /* A local symbol.  */
+	  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+					abfd, r_symndx);
+	  if (isym == NULL)
+	    return FALSE;
+	}
+
+      r_type = ELF64_R_TYPE (rel->r_info);
+      r_type = aarch64_tls_transition (abfd,info, r_type, h ,r_symndx);
+      switch (r_type)
+	{
+	case R_AARCH64_LD64_GOT_LO12_NC:
+	case R_AARCH64_GOT_LD_PREL19:
+	case R_AARCH64_ADR_GOT_PAGE:
+	case R_AARCH64_TLSGD_ADR_PAGE21:
+	case R_AARCH64_TLSGD_ADD_LO12_NC:
+	case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+	case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+	case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+	case R_AARCH64_TLSDESC_ADR_PAGE:
+	case R_AARCH64_TLSDESC_ADD_LO12_NC:
+	case R_AARCH64_TLSDESC_LD64_LO12_NC:
+          if (h != NULL)
+	    {
+	      if (h->got.refcount > 0)
+		h->got.refcount -= 1;
+	    }
+	  else if (local_got_refcounts != NULL)
+	    {
+	      if (local_got_refcounts[r_symndx] > 0)
+		local_got_refcounts[r_symndx] -= 1;
+	    }
+	  break;
+
+	case R_AARCH64_ADR_PREL_PG_HI21_NC:
+	case R_AARCH64_ADR_PREL_PG_HI21:
+	case R_AARCH64_ADR_PREL_LO21:
+	  if (h != NULL && info->executable)
+	    {
+	      if (h->plt.refcount > 0)
+		h->plt.refcount -= 1;
+	    }
+	  break;
+
+	case R_AARCH64_CALL26:
+	case R_AARCH64_JUMP26:
+          /* If this is a local symbol then we resolve it
+             directly without creating a PLT entry.  */
+	  if (h == NULL)
+	    continue;
+
+	  if (h->plt.refcount > 0)
+	    h->plt.refcount -= 1;
+	  break;
+
+	case R_AARCH64_ABS64:
+	  if (h != NULL && info->executable)
+	    {
+	      if (h->plt.refcount > 0)
+		h->plt.refcount -= 1;
+	    }
+	  break;
+        
+	default:
+	  break;
+	}
+    }
+
   return TRUE;
 }
 
@@ -7049,7 +7180,7 @@ const struct elf_size_info elf64_aarch64_size_info =
   elf64_aarch64_size_info
 
 #define elf_backend_can_refcount       1
-#define elf_backend_can_gc_sections    0
+#define elf_backend_can_gc_sections    1
 #define elf_backend_plt_readonly       1
 #define elf_backend_want_got_plt       1
 #define elf_backend_want_plt_sym       0
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index 4cd671d..4b88093 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -1,7 +1,5 @@
 # Support routines for LD testsuite.
-#   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-#    2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-#    Free Software Foundation, Inc.
+#   Copyright 1994-2013 Free Software Foundation, Inc.
 #
 # This file is part of the GNU Binutils.
 #
@@ -1518,22 +1516,21 @@ proc check_gc_sections_available { } {
     if {![info exists gc_sections_available_saved]} {
 	# Some targets don't support gc-sections despite whatever's
 	# advertised by ld's options.
-	if {[istarget aarch64*-*-*]
-	     || [istarget arc-*-*]
-	     || [istarget d30v-*-*]
-	     || [istarget dlx-*-*]
-	     || [istarget i960-*-*]
-	     || [istarget or32-*-*]
-	     || [istarget pj*-*-*]
-	     || [istarget alpha-*-*]
-	     || [istarget hppa*64-*-*]
-	     || [istarget i370-*-*]
-	     || [istarget i860-*-*]
-	     || [istarget ia64-*-*]
-	     || [istarget mep-*-*]
-	     || [istarget mn10200-*-*]
-	     || [istarget *-*-cygwin]
-	     || [istarget *-*-mingw*] } {
+	if {   [istarget arc-*-*]
+	    || [istarget d30v-*-*]
+	    || [istarget dlx-*-*]
+	    || [istarget i960-*-*]
+	    || [istarget or32-*-*]
+	    || [istarget pj*-*-*]
+	    || [istarget alpha-*-*]
+	    || [istarget hppa*64-*-*]
+	    || [istarget i370-*-*]
+	    || [istarget i860-*-*]
+	    || [istarget ia64-*-*]
+	    || [istarget mep-*-*]
+	    || [istarget mn10200-*-*]
+	    || [istarget *-*-cygwin]
+	    || [istarget *-*-mingw*] } {
 	    set gc_sections_available_saved 0
 	    return 0
 	}