From a48d0c12f893a922692492829f04189d9f216172 Mon Sep 17 00:00:00 2001 From: Han Shen Date: Wed, 10 Jun 2015 09:50:22 -0700 Subject: [PATCH] Patch for erratum-843419 (2 of 2 - fix erratum occurrences). Now fixing for 843419 is fully functional. The first part of the erratum fix CL is here - https://sourceware.org/ml/binutils/2015-04/msg00229.html gold/ChangeLog 2015-06-10 Han Shen * aarch64.cc(global enum): New constants representing stub types. (Stub_template): New POD struct. (Stub_template_repertoire): New class. (Stub_base): New class. (Erratum_stub): New class. (Reloc_stub): Refactored to be a subclass of Stub_base. (Reloc_stub::Stub_type): Removed. (Reloc_stub::offset): Moved to Stub_base. (Reloc_stub::set_offset): Moved to Stub_base. (Reloc_stub::destination_address): Moved to Stub_base. (Reloc_stub::set_destination_address): Moved to Stub_base. (Reloc_stub::reset_destination_address): Moved to Stub_base. (Reloc_stub::stub_type): Renamed and moved to Stub_base. (Reloc_stub::stub_size): Renamed and moved to Stub_base. (Reloc_stub::stub_insns): Renamed and moved to Stub_base. (Reloc_stub::write): Moved to Stub_base. (Reloc_stub::invalid_offset): Moved to Stub_base. (Reloc_stub::invalid_address): Moved to Stub_base. (Reloc_stub::stub_type_): Renamed and moved to Stub_base. (Reloc_stub::stub_insns_): Moved to Stub_base. (Reloc_stub::offset_): Moved to Stub_base. (Reloc_stub::destination_address_): Moved to Stub_base. (Stub_table::The_aarch64_relobj): New typedef. (Stub_table::The_erratum_stub): New typedef. (Stub_table::The_erratum_stub_less): New typedef. (Stub_table::The_erratum_stub_set): New typedef. (Stub_table::The_erratum_stub_set_iter): New typedef. (Stub_table::empty): Added emptiness testing for erratum stubs. (Stub_table::add_erratum_stub): New method to add an erratum stub. (Stub_table::find_erratum_stub): New method. (Stub_table::find_erratum_stubs_for_input_section): New method. (Stub_table::erratum_stub_address): New method. (Stub_table::update_date_size_changed_p): Modified to handle erratum stubs. (Stub_table::do_addralign): Modified to handle erratum stubs. (Stub_table::erratum_stubs_): New member. (Stub_table::erratum_stub_size_): New member. (Stub_table::relocate_stubs): Modified to handle erratum stubs. (Stub_table::do_write): Modified to handle erratum stubs. (AArch64_relobj::The_erratum_stub): New typedef. (AArch64_relobj::Erratum_stub_set_iter): New typedef. (AArch64_relobj::fix_errata): New method. (Target_aarch64::The_reloc_stub_type): Removed. (Target_aarch64::The_erratum_stub): New typede. (AArch64_relocate_functions::construct_b): New method. --- gold/ChangeLog | 53 +++ gold/aarch64.cc | 833 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 710 insertions(+), 176 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 0ec1c2718c8..97a03b4b8a0 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,56 @@ +2015-06-10 Han Shen + Patch for erratum-843419 (2 of 2 - fix erratum occurrences). + + Now fixing for 843419 is fully functional. + + The first part of the erratum fix CL is here - + https://sourceware.org/ml/binutils/2015-04/msg00229.html + + * aarch64.cc(global enum): New constants representing stub types. + (Stub_template): New POD struct. + (Stub_template_repertoire): New class. + (Stub_base): New class. + (Erratum_stub): New class. + (Reloc_stub): Refactored to be a subclass of Stub_base. + (Reloc_stub::Stub_type): Removed. + (Reloc_stub::offset): Moved to Stub_base. + (Reloc_stub::set_offset): Moved to Stub_base. + (Reloc_stub::destination_address): Moved to Stub_base. + (Reloc_stub::set_destination_address): Moved to Stub_base. + (Reloc_stub::reset_destination_address): Moved to Stub_base. + (Reloc_stub::stub_type): Renamed and moved to Stub_base. + (Reloc_stub::stub_size): Renamed and moved to Stub_base. + (Reloc_stub::stub_insns): Renamed and moved to Stub_base. + (Reloc_stub::write): Moved to Stub_base. + (Reloc_stub::invalid_offset): Moved to Stub_base. + (Reloc_stub::invalid_address): Moved to Stub_base. + (Reloc_stub::stub_type_): Renamed and moved to Stub_base. + (Reloc_stub::stub_insns_): Moved to Stub_base. + (Reloc_stub::offset_): Moved to Stub_base. + (Reloc_stub::destination_address_): Moved to Stub_base. + (Stub_table::The_aarch64_relobj): New typedef. + (Stub_table::The_erratum_stub): New typedef. + (Stub_table::The_erratum_stub_less): New typedef. + (Stub_table::The_erratum_stub_set): New typedef. + (Stub_table::The_erratum_stub_set_iter): New typedef. + (Stub_table::empty): Added emptiness testing for erratum stubs. + (Stub_table::add_erratum_stub): New method to add an erratum stub. + (Stub_table::find_erratum_stub): New method. + (Stub_table::find_erratum_stubs_for_input_section): New method. + (Stub_table::erratum_stub_address): New method. + (Stub_table::update_date_size_changed_p): Modified to handle erratum stubs. + (Stub_table::do_addralign): Modified to handle erratum stubs. + (Stub_table::erratum_stubs_): New member. + (Stub_table::erratum_stub_size_): New member. + (Stub_table::relocate_stubs): Modified to handle erratum stubs. + (Stub_table::do_write): Modified to handle erratum stubs. + (AArch64_relobj::The_erratum_stub): New typedef. + (AArch64_relobj::Erratum_stub_set_iter): New typedef. + (AArch64_relobj::fix_errata): New method. + (Target_aarch64::The_reloc_stub_type): Removed. + (Target_aarch64::The_erratum_stub): New typede. + (AArch64_relocate_functions::construct_b): New method. + 2015-06-08 Nick Clifton * po/fr.po: New French Translation. diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 27457760a15..130fcc2cba0 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -24,6 +24,7 @@ #include #include +#include #include "elfcpp.h" #include "dwarf.h" @@ -576,91 +577,177 @@ template class AArch64_output_section; -// Reloc stub class. - template -class Reloc_stub +class AArch64_relobj; + + +// Stub type enum constants. + +enum { - public: - typedef Reloc_stub This; - typedef typename elfcpp::Elf_types::Elf_Addr AArch64_address; + ST_NONE = 0, - // Do not change the value of the enums, they are used to index into - // stub_insns array. - typedef enum - { - ST_NONE = 0, + // Using adrp/add pair, 4 insns (including alignment) without mem access, + // the fastest stub. This has a limited jump distance, which is tested by + // aarch64_valid_for_adrp_p. + ST_ADRP_BRANCH = 1, - // Using adrp/add pair, 4 insns (including alignment) without mem access, - // the fastest stub. This has a limited jump distance, which is tested by - // aarch64_valid_for_adrp_p. - ST_ADRP_BRANCH = 1, + // Using ldr-absolute-address/br-register, 4 insns with 1 mem access, + // unlimited in jump distance. + ST_LONG_BRANCH_ABS = 2, - // Using ldr-absolute-address/br-register, 4 insns with 1 mem access, - // unlimited in jump distance. - ST_LONG_BRANCH_ABS = 2, + // Using ldr/calculate-pcrel/jump, 8 insns (including alignment) with 1 + // mem access, slowest one. Only used in position independent executables. + ST_LONG_BRANCH_PCREL = 3, - // Using ldr/calculate-pcrel/jump, 8 insns (including alignment) with 1 mem - // access, slowest one. Only used in position independent executables. - ST_LONG_BRANCH_PCREL = 3, + // Stub for erratum 843419 handling. + ST_E_843419 = 4, - } Stub_type; + // Number of total stub types. + ST_NUMBER = 5 +}; - // Branch range. This is used to calculate the section group size, as well as - // determine whether a stub is needed. - static const int MAX_BRANCH_OFFSET = ((1 << 25) - 1) << 2; - static const int MIN_BRANCH_OFFSET = -((1 << 25) << 2); - // Constant used to determine if an offset fits in the adrp instruction - // encoding. - static const int MAX_ADRP_IMM = (1 << 20) - 1; - static const int MIN_ADRP_IMM = -(1 << 20); +// Struct that wraps insns for a particular stub. All stub templates are +// created/initialized as constants by Stub_template_repertoire. - static const int BYTES_PER_INSN = 4; - static const int STUB_ADDR_ALIGN = 4; +template +struct Stub_template +{ + const typename AArch64_insn_utilities::Insntype* insns; + const int insn_num; +}; - // Determine whether the offset fits in the jump/branch instruction. - static bool - aarch64_valid_branch_offset_p(int64_t offset) - { return offset >= MIN_BRANCH_OFFSET && offset <= MAX_BRANCH_OFFSET; } - // Determine whether the offset fits in the adrp immediate field. - static bool - aarch64_valid_for_adrp_p(AArch64_address location, AArch64_address dest) +// Simple singleton class that creates/initializes/stores all types of stub +// templates. + +template +class Stub_template_repertoire +{ +public: + typedef typename AArch64_insn_utilities::Insntype Insntype; + + // Single static method to get stub template for a given stub type. + static const Stub_template* + get_stub_template(int type) { - typedef AArch64_relocate_functions Reloc; - int64_t adrp_imm = (Reloc::Page(dest) - Reloc::Page(location)) >> 12; - return adrp_imm >= MIN_ADRP_IMM && adrp_imm <= MAX_ADRP_IMM; + static Stub_template_repertoire singleton; + return singleton.stub_templates_[type]; } - // Determine the stub type for a certain relocation or ST_NONE, if no stub is - // needed. - static Stub_type - stub_type_for_reloc(unsigned int r_type, AArch64_address address, - AArch64_address target); - - Reloc_stub(Stub_type stub_type) - : stub_type_(stub_type), offset_(invalid_offset), - destination_address_(invalid_address) +private: + // Constructor - creates/initializes all stub templates. + Stub_template_repertoire(); + ~Stub_template_repertoire() { } - ~Reloc_stub() - { } + // Disallowing copy ctor and copy assignment operator. + Stub_template_repertoire(Stub_template_repertoire&); + Stub_template_repertoire& operator=(Stub_template_repertoire&); - // Return offset of code stub from beginning of its containing stub table. - section_offset_type - offset() const + // Data that stores all insn templates. + const Stub_template* stub_templates_[ST_NUMBER]; +}; // End of "class Stub_template_repertoire". + + +// Constructor - creates/initilizes all stub templates. + +template +Stub_template_repertoire::Stub_template_repertoire() +{ + // Insn array definitions. + const static Insntype ST_NONE_INSNS[] = {}; + + const static Insntype ST_ADRP_BRANCH_INSNS[] = + { + 0x90000010, /* adrp ip0, X */ + /* ADR_PREL_PG_HI21(X) */ + 0x91000210, /* add ip0, ip0, :lo12:X */ + /* ADD_ABS_LO12_NC(X) */ + 0xd61f0200, /* br ip0 */ + 0x00000000, /* alignment padding */ + }; + + const static Insntype ST_LONG_BRANCH_ABS_INSNS[] = + { + 0x58000050, /* ldr ip0, 0x8 */ + 0xd61f0200, /* br ip0 */ + 0x00000000, /* address field */ + 0x00000000, /* address fields */ + }; + + const static Insntype ST_LONG_BRANCH_PCREL_INSNS[] = + { + 0x58000090, /* ldr ip0, 0x10 */ + 0x10000011, /* adr ip1, #0 */ + 0x8b110210, /* add ip0, ip0, ip1 */ + 0xd61f0200, /* br ip0 */ + 0x00000000, /* address field */ + 0x00000000, /* address field */ + 0x00000000, /* alignment padding */ + 0x00000000, /* alignment padding */ + }; + + const static Insntype ST_E_843419_INSNS[] = + { + 0x00000000, /* Placeholder for erratum insn. */ + 0x14000000, /* b