X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Felfnn-aarch64.c;h=5b8cc4c9701feacd0deb5c998c89d17d97864646;hb=cd702818c6cf25277253b3b5c23f17d2cf7a94df;hp=ee09cd74117c717a399d0de262187b2dff57f5f9;hpb=3da64fe404031c093e8b59565d935fed214e28c1;p=external%2Fbinutils.git diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index ee09cd7..5b8cc4c 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -1,5 +1,5 @@ /* AArch64-specific support for NN-bit ELF. - Copyright (C) 2009-2018 Free Software Foundation, Inc. + Copyright (C) 2009-2019 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of BFD, the Binary File Descriptor library. @@ -139,7 +139,6 @@ #include "bfd.h" #include "libiberty.h" #include "libbfd.h" -#include "bfd_stdint.h" #include "elf-bfd.h" #include "bfdlink.h" #include "objalloc.h" @@ -2436,6 +2435,9 @@ struct elf_aarch64_obj_tdata /* Zero to warn when linking objects with incompatible wchar_t sizes. */ int no_wchar_size_warning; + + /* All GNU_PROPERTY_AARCH64_FEATURE_1_AND properties. */ + uint32_t gnu_and_prop; }; #define elf_aarch64_tdata(bfd) \ @@ -3845,7 +3847,7 @@ _bfd_aarch64_erratum_835769_scan (bfd *input_bfd, static bfd_boolean _bfd_aarch64_adrp_p (uint32_t insn) { - return ((insn & 0x9f000000) == 0x90000000); + return ((insn & AARCH64_ADRP_OP_MASK) == AARCH64_ADRP_OP); } @@ -5077,7 +5079,7 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry, + stub_entry->adrp_offset); insn = bfd_getl32 (contents + stub_entry->adrp_offset); - if ((insn & AARCH64_ADRP_OP_MASK) != AARCH64_ADRP_OP) + if (!_bfd_aarch64_adrp_p (insn)) abort (); bfd_signed_vma imm = @@ -5941,6 +5943,64 @@ bad_ifunc_reloc: # define movz_hw_R0 (0x52c00000) #endif +/* Structure to hold payload for _bfd_aarch64_erratum_843419_clear_stub, + it is used to identify the stub information to reset. */ + +struct erratum_843419_branch_to_stub_clear_data +{ + bfd_vma adrp_offset; + asection *output_section; +}; + +/* Clear the erratum information for GEN_ENTRY if the ADRP_OFFSET and + section inside IN_ARG matches. The clearing is done by setting the + stub_type to none. */ + +static bfd_boolean +_bfd_aarch64_erratum_843419_clear_stub (struct bfd_hash_entry *gen_entry, + void *in_arg) +{ + struct elf_aarch64_stub_hash_entry *stub_entry + = (struct elf_aarch64_stub_hash_entry *) gen_entry; + struct erratum_843419_branch_to_stub_clear_data *data + = (struct erratum_843419_branch_to_stub_clear_data *) in_arg; + + if (stub_entry->target_section != data->output_section + || stub_entry->stub_type != aarch64_stub_erratum_843419_veneer + || stub_entry->adrp_offset != data->adrp_offset) + return TRUE; + + /* Change the stub type instead of removing the entry, removing from the hash + table would be slower and we have already reserved the memory for the entry + so there wouldn't be much gain. Changing the stub also keeps around a + record of what was there before. */ + stub_entry->stub_type = aarch64_stub_none; + + /* We're done and there could have been only one matching stub at that + particular offset, so abort further traversal. */ + return FALSE; +} + +/* TLS Relaxations may relax an adrp sequence that matches the erratum 843419 + sequence. In this case the erratum no longer applies and we need to remove + the entry from the pending stub generation. This clears matching adrp insn + at ADRP_OFFSET in INPUT_SECTION in the stub table defined in GLOBALS. */ + +static void +clear_erratum_843419_entry (struct elf_aarch64_link_hash_table *globals, + bfd_vma adrp_offset, asection *input_section) +{ + if (globals->fix_erratum_843419) + { + struct erratum_843419_branch_to_stub_clear_data data; + data.adrp_offset = adrp_offset; + data.output_section = input_section; + + bfd_hash_traverse (&globals->stub_hash_table, + _bfd_aarch64_erratum_843419_clear_stub, &data); + } +} + /* Handle TLS relaxations. Relaxing is possible for symbols that use R_AARCH64_TLSDESC_ADR_{PAGE, LD64_LO12_NC, ADD_LO12_NC} during a static link. @@ -5951,8 +6011,9 @@ bad_ifunc_reloc: static bfd_reloc_status_type elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, - bfd *input_bfd, bfd_byte *contents, - Elf_Internal_Rela *rel, struct elf_link_hash_entry *h) + bfd *input_bfd, asection *input_section, + bfd_byte *contents, Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h) { bfd_boolean is_local = h == NULL; unsigned int r_type = ELFNN_R_TYPE (rel->r_info); @@ -5973,6 +6034,9 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, Where R is x for LP64, and w for ILP32. */ bfd_putl32 (movz_R0, contents + rel->r_offset); + /* We have relaxed the adrp into a mov, we may have to clear any + pending erratum fixes. */ + clear_erratum_843419_entry (globals, rel->r_offset, input_section); return bfd_reloc_continue; } else @@ -6263,6 +6327,9 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, { insn = bfd_getl32 (contents + rel->r_offset); bfd_putl32 (movz_R0 | (insn & 0x1f), contents + rel->r_offset); + /* We have relaxed the adrp into a mov, we may have to clear any + pending erratum fixes. */ + clear_erratum_843419_entry (globals, rel->r_offset, input_section); } return bfd_reloc_continue; @@ -6487,7 +6554,8 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, howto = elfNN_aarch64_howto_from_bfd_reloc (bfd_r_type); BFD_ASSERT (howto != NULL); r_type = howto->type; - r = elfNN_aarch64_tls_relax (globals, input_bfd, contents, rel, h); + r = elfNN_aarch64_tls_relax (globals, input_bfd, input_section, + contents, rel, h); unresolved_reloc = 0; } else @@ -7565,9 +7633,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: { unsigned got_type; unsigned old_got_type; @@ -8077,6 +8142,8 @@ aarch64_map_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr)) return FALSE; break; + case aarch64_stub_none: + break; default: abort (); @@ -9551,6 +9618,32 @@ elfNN_aarch64_backend_symbol_processing (bfd *abfd, asymbol *sym) sym->flags |= BSF_KEEP; } +/* Implement elf_backend_setup_gnu_properties for AArch64. It serves as a + wrapper function for _bfd_aarch64_elf_link_setup_gnu_properties to account + for the effect of GNU properties of the output_bfd. */ +static bfd * +elfNN_aarch64_link_setup_gnu_properties (struct bfd_link_info *info) +{ + uint32_t prop = elf_aarch64_tdata (info->output_bfd)->gnu_and_prop; + bfd *pbfd = _bfd_aarch64_elf_link_setup_gnu_properties (info, &prop); + elf_aarch64_tdata (info->output_bfd)->gnu_and_prop = prop; + return pbfd; +} + +/* Implement elf_backend_merge_gnu_properties for AArch64. It serves as a + wrapper function for _bfd_aarch64_elf_merge_gnu_properties to account + for the effect of GNU properties of the output_bfd. */ +static bfd_boolean +elfNN_aarch64_merge_gnu_properties (struct bfd_link_info *info, + bfd *abfd, + elf_property *aprop, + elf_property *bprop) +{ + uint32_t prop + = elf_aarch64_tdata (info->output_bfd)->gnu_and_prop; + return _bfd_aarch64_elf_merge_gnu_properties (info, abfd, aprop, + bprop, prop); +} /* We use this so we can override certain functions (though currently we don't). */ @@ -9690,6 +9783,12 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_symbol_processing \ elfNN_aarch64_backend_symbol_processing +#define elf_backend_setup_gnu_properties \ + elfNN_aarch64_link_setup_gnu_properties + +#define elf_backend_merge_gnu_properties \ + elfNN_aarch64_merge_gnu_properties + #define elf_backend_can_refcount 1 #define elf_backend_can_gc_sections 1 #define elf_backend_plt_readonly 1