X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-aarch64.c;h=aef472f2e8bc017e376756e1a7626c8371b249c0;hb=036c3acbab525e5125bf2d1f98cb041ed95e21d5;hp=4b8fe435237903fc8a17258df95c59d80f8cdec7;hpb=9f7c3e5e99a620b68f6b2d0f3b17329e40b8d781;p=binutils-gdb.git diff --git a/bfd/elf64-aarch64.c b/bfd/elf64-aarch64.c index 4b8fe435237..aef472f2e8b 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. @@ -1531,11 +1531,11 @@ elf64_aarch64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) case 408: /* sizeof(struct elf_prstatus) on Linux/arm64. */ /* pr_cursig */ - elf_tdata (abfd)->core_signal + elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ - elf_tdata (abfd)->core_lwpid + elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32); /* pr_reg */ @@ -4306,6 +4306,14 @@ elf64_aarch64_relocate_section (bfd *output_bfd, bfd_reloc.howto = elf64_aarch64_howto_from_type (r_type); howto = bfd_reloc.howto; + if (howto == NULL) + { + (*_bfd_error_handler) + (_("%B: unrecognized relocation (0x%x) in section `%A'"), + input_bfd, input_section, r_type); + return FALSE; + } + h = NULL; sym = NULL; sec = NULL; @@ -4330,12 +4338,6 @@ elf64_aarch64_relocate_section (bfd *output_bfd, return FALSE; } - if (r_type >= R_AARCH64_dyn_max) - { - bfd_set_error (bfd_error_bad_value); - return FALSE; - } - relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); } else @@ -4869,12 +4871,142 @@ elf64_aarch64_print_private_bfd_data (bfd *abfd, void *ptr) /* Update the got entry reference counts for the section being removed. */ static bfd_boolean -elf64_aarch64_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info ATTRIBUTE_UNUSED, - asection *sec ATTRIBUTE_UNUSED, - const Elf_Internal_Rela * - relocs ATTRIBUTE_UNUSED) +elf64_aarch64_gc_sweep_hook (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela * relocs) { + struct elf64_aarch64_link_hash_table *htab; + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + struct elf_aarch64_local_symbol *locals; + 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); + + locals = elf64_aarch64_locals (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 (locals != NULL) + { + if (locals[r_symndx].got_refcount > 0) + locals[r_symndx].got_refcount -= 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; } @@ -5011,8 +5143,6 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, struct elf64_aarch64_link_hash_table *htab; - unsigned long nsyms; - if (info->relocatable) return TRUE; @@ -5023,7 +5153,6 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, symtab_hdr = &elf_symtab_hdr (abfd); sym_hashes = elf_sym_hashes (abfd); - nsyms = NUM_SHDR_ENTRIES (symtab_hdr); rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -5042,18 +5171,7 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, return FALSE; } - if (r_symndx >= nsyms - /* PR 9934: It is possible to have relocations that do not - refer to symbols, thus it is also possible to have an - object file containing relocations but no symbol table. */ - && (r_symndx > 0 || nsyms > 0)) - { - (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd, - r_symndx); - return FALSE; - } - - if (nsyms == 0 || r_symndx < symtab_hdr->sh_info) + if (r_symndx < symtab_hdr->sh_info) h = NULL; else { @@ -5061,6 +5179,10 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *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; + + /* PR15323, ref flags aren't set for references in the same + object. */ + h->root.non_ir_ref = 1; } /* Could be done earlier, if h were already available. */ @@ -5429,7 +5551,9 @@ elf64_aarch64_post_process_headers (bfd *abfd, } static enum elf_reloc_type_class -elf64_aarch64_reloc_type_class (const Elf_Internal_Rela *rela) +elf64_aarch64_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela) { switch ((int) ELF64_R_TYPE (rela->r_info)) { @@ -7049,7 +7173,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 @@ -7057,6 +7181,7 @@ const struct elf_size_info elf64_aarch64_size_info = #define elf_backend_may_use_rela_p 1 #define elf_backend_default_use_rela_p 1 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3) +#define elf_backend_default_execstack 0 #undef elf_backend_obj_attrs_section #define elf_backend_obj_attrs_section ".ARM.attributes"