X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf64-aarch64.c;h=aef472f2e8bc017e376756e1a7626c8371b249c0;hb=036c3acbab525e5125bf2d1f98cb041ed95e21d5;hp=629907403c18ba05a39c1a341e06cac0345b1eb9;hpb=a06ea96464a2928865beb2ac6f12deb0464bfcd7;p=binutils-gdb.git diff --git a/bfd/elf64-aarch64.c b/bfd/elf64-aarch64.c index 629907403c1..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. @@ -908,7 +908,23 @@ static reloc_howto_type elf64_aarch64_howto_table[] = EMPTY_HOWTO (306), EMPTY_HOWTO (307), EMPTY_HOWTO (308), - EMPTY_HOWTO (309), + + /* Set a load-literal immediate field to bits + 0x1FFFFC of G(S)-P */ + HOWTO (R_AARCH64_GOT_LD_PREL19, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte,1 = short,2 = long) */ + 19, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AARCH64_GOT_LD_PREL19", /* name */ + FALSE, /* partial_inplace */ + 0xffffe0, /* src_mask */ + 0xffffe0, /* dst_mask */ + TRUE), /* pcrel_offset */ + EMPTY_HOWTO (310), /* Get to the page for the GOT entry for the symbol @@ -1060,7 +1076,7 @@ static reloc_howto_type elf64_aarch64_tls_howto_table[] = FALSE), /* pcrel_offset */ HOWTO (R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 21, /* bitsize */ FALSE, /* pc_relative */ @@ -1074,7 +1090,7 @@ static reloc_howto_type elf64_aarch64_tls_howto_table[] = FALSE), /* pcrel_offset */ HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G2, /* type */ - 8, /* rightshift */ + 32, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ @@ -1088,7 +1104,7 @@ static reloc_howto_type elf64_aarch64_tls_howto_table[] = FALSE), /* pcrel_offset */ HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G1, /* type */ - 4, /* rightshift */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ @@ -1102,7 +1118,7 @@ static reloc_howto_type elf64_aarch64_tls_howto_table[] = FALSE), /* pcrel_offset */ HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, /* type */ - 4, /* rightshift */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ @@ -1144,7 +1160,7 @@ static reloc_howto_type elf64_aarch64_tls_howto_table[] = FALSE), /* pcrel_offset */ HOWTO (R_AARCH64_TLSLE_ADD_TPREL_HI12, /* type */ - 3, /* rightshift */ + 12, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ @@ -1189,7 +1205,7 @@ static reloc_howto_type elf64_aarch64_tls_howto_table[] = static reloc_howto_type elf64_aarch64_tlsdesc_howto_table[] = { HOWTO (R_AARCH64_TLSDESC_LD64_PREL19, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 21, /* bitsize */ TRUE, /* pc_relative */ @@ -1263,7 +1279,7 @@ static reloc_howto_type elf64_aarch64_tlsdesc_howto_table[] = FALSE), /* pcrel_offset */ HOWTO (R_AARCH64_TLSDESC_OFF_G1, /* type */ - 4, /* rightshift */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ @@ -1427,6 +1443,7 @@ static const struct elf64_aarch64_reloc_map elf64_aarch64_reloc_map[] = {BFD_RELOC_AARCH64_CALL26, R_AARCH64_CALL26}, /* Relocations for PIC. */ + {BFD_RELOC_AARCH64_GOT_LD_PREL19, R_AARCH64_GOT_LD_PREL19}, {BFD_RELOC_AARCH64_ADR_GOT_PAGE, R_AARCH64_ADR_GOT_PAGE}, {BFD_RELOC_AARCH64_LD64_GOT_LO12_NC, R_AARCH64_LD64_GOT_LO12_NC}, @@ -1499,11 +1516,47 @@ elf64_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, return NULL; } +/* Support for core dump NOTE sections. */ + +static bfd_boolean +elf64_aarch64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +{ + int offset; + size_t size; + + switch (note->descsz) + { + default: + return FALSE; + + case 408: /* sizeof(struct elf_prstatus) on Linux/arm64. */ + /* pr_cursig */ + elf_tdata (abfd)->core->signal + = bfd_get_16 (abfd, note->descdata + 12); + + /* pr_pid */ + elf_tdata (abfd)->core->lwpid + = bfd_get_32 (abfd, note->descdata + 32); + + /* pr_reg */ + offset = 112; + size = 272; + + break; + } + + /* Make a ".reg/999" section. */ + return _bfd_elfcore_make_pseudosection (abfd, ".reg", + size, note->descpos + offset); +} + #define TARGET_LITTLE_SYM bfd_elf64_littleaarch64_vec #define TARGET_LITTLE_NAME "elf64-littleaarch64" #define TARGET_BIG_SYM bfd_elf64_bigaarch64_vec #define TARGET_BIG_NAME "elf64-bigaarch64" +#define elf_backend_grok_prstatus elf64_aarch64_grok_prstatus + typedef unsigned long int insn32; /* The linker script knows the section names for placement. @@ -2040,7 +2093,7 @@ elf64_aarch64_link_hash_table_create (bfd *abfd) struct elf64_aarch64_link_hash_table *ret; bfd_size_type amt = sizeof (struct elf64_aarch64_link_hash_table); - ret = bfd_malloc (amt); + ret = bfd_zmalloc (amt); if (ret == NULL) return NULL; @@ -2052,23 +2105,9 @@ elf64_aarch64_link_hash_table_create (bfd *abfd) return NULL; } - ret->sdynbss = NULL; - ret->srelbss = NULL; - ret->plt_header_size = PLT_ENTRY_SIZE; ret->plt_entry_size = PLT_SMALL_ENTRY_SIZE; - - ret->sym_cache.abfd = NULL; ret->obfd = abfd; - - ret->stub_bfd = NULL; - ret->add_stub_section = NULL; - ret->layout_sections_again = NULL; - ret->stub_group = NULL; - ret->bfd_count = 0; - ret->top_index = 0; - ret->input_list = NULL; - ret->tlsdesc_plt = 0; ret->dt_tlsdesc_got = (bfd_vma) - 1; if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc, @@ -2090,7 +2129,7 @@ elf64_aarch64_hash_table_free (struct bfd_link_hash_table *hash) = (struct elf64_aarch64_link_hash_table *) hash; bfd_hash_table_free (&ret->stub_hash_table); - _bfd_generic_link_hash_table_free (hash); + _bfd_elf_link_hash_table_free (hash); } static bfd_vma @@ -2143,6 +2182,10 @@ aarch64_resolve_relocation (unsigned int r_type, bfd_vma place, bfd_vma value, value = PG (value + addend) - PG (place); break; + case R_AARCH64_GOT_LD_PREL19: + value = value + addend - place; + break; + case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_TLSDESC_ADR_PAGE: case R_AARCH64_TLSGD_ADR_PAGE21: @@ -3362,6 +3405,7 @@ bfd_elf_aarch64_put_addend (bfd *abfd, break; case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_GOT_LD_PREL19: if (old_addend & ((1 << howto->rightshift) - 1)) return bfd_reloc_overflow; contents = reencode_ld_lit_ofs_19 (contents, addend); @@ -3570,6 +3614,7 @@ aarch64_reloc_got_type (unsigned int r_type) { case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_GOT_LD_PREL19: return GOT_NORMAL; case R_AARCH64_TLSGD_ADR_PAGE21: @@ -3992,6 +4037,7 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto, case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_GOT_LD_PREL19: if (globals->root.sgot == NULL) BFD_ASSERT (h != NULL); @@ -4030,7 +4076,7 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto, case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: case R_AARCH64_TLSLE_MOVW_TPREL_G2: value = aarch64_resolve_relocation (r_type, place, value, - - tpoff_base (info), weak_undef_p); + signed_addend - tpoff_base (info), weak_undef_p); *unresolved_reloc_p = FALSE; break; @@ -4260,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; @@ -4284,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 @@ -4823,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; } @@ -4965,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; @@ -4977,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++) @@ -4996,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 { @@ -5015,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. */ @@ -5116,6 +5284,7 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, /* RR: We probably want to keep a consistency check that there are no dangling GOT_PAGE relocs. */ 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: @@ -5201,6 +5370,7 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, 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 this reloc is in a read-only section, we might @@ -5381,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)) { @@ -6590,7 +6762,7 @@ elf64_aarch64_finish_dynamic_symbol (bfd *output_bfd, /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. SYM may be NULL for local symbols. */ if (sym != NULL - && (strcmp (h->root.root.string, "_DYNAMIC") == 0 + && (h == elf_hash_table (info)->hdynamic || h == elf_hash_table (info)->hgot)) sym->st_shndx = SHN_ABS; @@ -7001,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 @@ -7009,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"