X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Faarch64.cc;h=5e702dbfd7710ef614da536ef35fe3c58b6cbba0;hb=a3b3345ae62503982698171bcfce0afe23bd8a31;hp=2194a21de2af74d09a2c45a02b390720bea144a2;hpb=cefdd1cd64f3b67aba1b219547b8f895c22d48ed;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 2194a21de2..5e702dbfd7 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -1031,6 +1031,18 @@ public: set_erratum_address(AArch64_address addr) { this->erratum_address_ = addr; } + // Later relaxation passes of may alter the recorded erratum and destination + // address. Given an up to date output section address of shidx_ in + // relobj_ we can derive the erratum_address and destination address. + void + update_erratum_address(AArch64_address output_section_addr) + { + const int BPI = AArch64_insn_utilities::BYTES_PER_INSN; + AArch64_address updated_addr = output_section_addr + this->sh_offset_; + this->set_erratum_address(updated_addr); + this->set_destination_address(updated_addr + BPI); + } + // Comparator used to group Erratum_stubs in a set by (obj, shndx, // sh_offset). We do not include 'type' in the calculation, because there is // at most one stub type at (obj, shndx, sh_offset). @@ -1052,13 +1064,13 @@ public: void invalidate_erratum_stub() { - gold_assert(this->relobj_ != NULL); - this->relobj_ = NULL; + gold_assert(this->erratum_insn_ != invalid_insn); + this->erratum_insn_ = invalid_insn; } bool is_invalidated_erratum_stub() - { return this->relobj_ == NULL; } + { return this->erratum_insn_ == invalid_insn; } protected: virtual void @@ -1864,7 +1876,7 @@ class AArch64_relobj : public Sized_relobj_file // applied. bool try_fix_erratum_843419_optimized( - The_erratum_stub*, + The_erratum_stub*, AArch64_address, typename Sized_relobj_file::View_size&); // Whether a section needs to be scanned for relocation stubs. @@ -1980,6 +1992,7 @@ AArch64_relobj::fix_errata_and_relocate_erratum_stubs( { typedef typename elfcpp::Swap<32,big_endian>::Valtype Insntype; unsigned int shnum = this->shnum(); + const Relobj::Output_sections& out_sections(this->output_sections()); for (unsigned int i = 1; i < shnum; ++i) { The_stub_table* stub_table = this->stub_table(i); @@ -1988,33 +2001,48 @@ AArch64_relobj::fix_errata_and_relocate_erratum_stubs( std::pair ipair(stub_table->find_erratum_stubs_for_input_section(this, i)); Erratum_stub_set_iter p = ipair.first, end = ipair.second; + typename Sized_relobj_file::View_size& + pview((*pviews)[i]); + AArch64_address view_offset = 0; + if (pview.is_input_output_view) + { + // In this case, write_sections has not added the output offset to + // the view's address, so we must do so. Currently this only happens + // for a relaxed section. + unsigned int index = this->adjust_shndx(i); + const Output_relaxed_input_section* poris = + out_sections[index]->find_relaxed_input_section(this, index); + gold_assert(poris != NULL); + view_offset = poris->address() - pview.address; + } + while (p != end) { The_erratum_stub* stub = *p; - typename Sized_relobj_file::View_size& - pview((*pviews)[i]); // Double check data before fix. - gold_assert(pview.address + stub->sh_offset() + gold_assert(pview.address + view_offset + stub->sh_offset() == stub->erratum_address()); // Update previously recorded erratum insn with relocated // version. Insntype* ip = - reinterpret_cast(pview.view + stub->sh_offset()); + reinterpret_cast( + pview.view + view_offset + stub->sh_offset()); Insntype insn_to_fix = ip[0]; stub->update_erratum_insn(insn_to_fix); // First try to see if erratum is 843419 and if it can be fixed // without using branch-to-stub. - if (!try_fix_erratum_843419_optimized(stub, pview)) + if (!try_fix_erratum_843419_optimized(stub, view_offset, pview)) { // Replace the erratum insn with a branch-to-stub. AArch64_address stub_address = stub_table->erratum_stub_address(stub); unsigned int b_offset = stub_address - stub->erratum_address(); AArch64_relocate_functions::construct_b( - pview.view + stub->sh_offset(), b_offset & 0xfffffff); + pview.view + view_offset + stub->sh_offset(), + b_offset & 0xfffffff); } // Erratum fix is done (or skipped), continue to relocate erratum @@ -2024,7 +2052,8 @@ AArch64_relobj::fix_errata_and_relocate_erratum_stubs( // erratum stub, ignoring the fact the erratum could never be // executed. stub_table->relocate_erratum_stub( - stub, pview.view + (stub_table->address() - pview.address)); + stub, + pview.view + (stub_table->address() - pview.address)); // Next erratum stub. ++p; @@ -2042,7 +2071,7 @@ AArch64_relobj::fix_errata_and_relocate_erratum_stubs( template bool AArch64_relobj::try_fix_erratum_843419_optimized( - The_erratum_stub* stub, + The_erratum_stub* stub, AArch64_address view_offset, typename Sized_relobj_file::View_size& pview) { if (stub->type() != ST_E_843419) @@ -2052,9 +2081,11 @@ AArch64_relobj::try_fix_erratum_843419_optimized( typedef typename elfcpp::Swap<32,big_endian>::Valtype Insntype; E843419_stub* e843419_stub = reinterpret_cast*>(stub); - AArch64_address pc = pview.address + e843419_stub->adrp_sh_offset(); + AArch64_address pc = + pview.address + view_offset + e843419_stub->adrp_sh_offset(); unsigned int adrp_offset = e843419_stub->adrp_sh_offset (); - Insntype* adrp_view = reinterpret_cast(pview.view + adrp_offset); + Insntype* adrp_view = + reinterpret_cast(pview.view + view_offset + adrp_offset); Insntype adrp_insn = adrp_view[0]; // If the instruction at adrp_sh_offset is "mrs R, tpidr_el0", it may come @@ -2070,8 +2101,9 @@ AArch64_relobj::try_fix_erratum_843419_optimized( // return true. if (!Insn_utilities::is_adrp(adrp_insn) && adrp_offset) { - Insntype* prev_view - = reinterpret_cast(pview.view + adrp_offset - 4); + Insntype* prev_view = + reinterpret_cast( + pview.view + view_offset + adrp_offset - 4); Insntype prev_insn = prev_view[0]; if (Insn_utilities::is_mrs_tpidr_el0(prev_insn)) @@ -2284,6 +2316,19 @@ AArch64_relobj::scan_errata( output_address = poris->address(); } + // Update the addresses in previously generated erratum stubs. Unlike when + // we scan relocations for stubs, if section addresses have changed due to + // other relaxations we are unlikely to scan the same erratum instances + // again. + The_stub_table* stub_table = this->stub_table(shndx); + if (stub_table) + { + std::pair + ipair(stub_table->find_erratum_stubs_for_input_section(this, shndx)); + for (Erratum_stub_set_iter p = ipair.first; p != ipair.second; ++p) + (*p)->update_erratum_address(output_address); + } + section_size_type input_view_size = 0; const unsigned char* input_view = this->section_contents(shndx, &input_view_size, false); @@ -3503,7 +3548,7 @@ const Target::Target_info Target_aarch64<64, false>::aarch64_info = false, // has_make_symbol false, // has_resolve false, // has_code_fill - true, // is_default_stack_executable + false, // is_default_stack_executable true, // can_icf_inline_merge_sections '\0', // wrap_char "/lib/ld.so.1", // program interpreter @@ -3531,7 +3576,7 @@ const Target::Target_info Target_aarch64<32, false>::aarch64_info = false, // has_make_symbol false, // has_resolve false, // has_code_fill - true, // is_default_stack_executable + false, // is_default_stack_executable false, // can_icf_inline_merge_sections '\0', // wrap_char "/lib/ld.so.1", // program interpreter @@ -3559,7 +3604,7 @@ const Target::Target_info Target_aarch64<64, true>::aarch64_info = false, // has_make_symbol false, // has_resolve false, // has_code_fill - true, // is_default_stack_executable + false, // is_default_stack_executable true, // can_icf_inline_merge_sections '\0', // wrap_char "/lib/ld.so.1", // program interpreter @@ -3587,7 +3632,7 @@ const Target::Target_info Target_aarch64<32, true>::aarch64_info = false, // has_make_symbol false, // has_resolve false, // has_code_fill - true, // is_default_stack_executable + false, // is_default_stack_executable false, // can_icf_inline_merge_sections '\0', // wrap_char "/lib/ld.so.1", // program interpreter