Index: binutils-2.23.1/bfd/elf64-aarch64.c =================================================================== --- binutils-2.23.1.orig/bfd/elf64-aarch64.c +++ binutils-2.23.1/bfd/elf64-aarch64.c @@ -4823,6 +4823,138 @@ elf64_aarch64_gc_sweep_hook (bfd *abfd A 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_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; } @@ -6994,7 +7127,7 @@ const struct elf_size_info elf64_aarch64 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 Index: binutils-2.23.1/ld/testsuite/lib/ld-lib.exp =================================================================== --- binutils-2.23.1.orig/ld/testsuite/lib/ld-lib.exp +++ binutils-2.23.1/ld/testsuite/lib/ld-lib.exp @@ -1500,8 +1500,7 @@ 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-*-*] + if {[istarget arc-*-*] || [istarget d30v-*-*] || [istarget dlx-*-*] || [istarget i960-*-*]