From 972d8a18db78974f59e1a6b1dc02f7e5b7d226d2 Mon Sep 17 00:00:00 2001 From: Han Shen Date: Mon, 28 Aug 2017 16:36:45 -0700 Subject: [PATCH] 2017-08-28 James Clarke gold/ChangeLog: PR gold/21868 * aarch64.cc (AArch64_relobj::try_fix_erratum_843419_optimized): Add extra view offset argument to function. (AArch64_relobj::fix_errata_and_relocate_erratum_stubs): Add extra view offset set to the output offset when the view has is_input_output_view set, since it has not already been included. Pass this to try_fix_erratum_843419_optimized. --- gold/aarch64.cc | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 2194a21de2a..a72e2c31b2a 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -1864,7 +1864,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 +1980,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 +1989,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 +2040,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 + view_offset + (stub_table->address() - pview.address)); // Next erratum stub. ++p; @@ -2042,7 +2059,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 +2069,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 +2089,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)) -- 2.30.2