diff options
author | Han Shen <shenhan@google.com> | 2017-08-28 16:36:45 -0700 |
---|---|---|
committer | Han Shen <shenhan@google.com> | 2017-08-28 16:40:51 -0700 |
commit | 972d8a18db78974f59e1a6b1dc02f7e5b7d226d2 (patch) | |
tree | 7f51463d653c96c19bc2e654e02de830063a6c20 /gold | |
parent | 0fb0a7677827aea3e7ca1fdb2dfd1ccbdf6c2f71 (diff) | |
download | fsf-binutils-gdb-972d8a18db78974f59e1a6b1dc02f7e5b7d226d2.zip fsf-binutils-gdb-972d8a18db78974f59e1a6b1dc02f7e5b7d226d2.tar.gz fsf-binutils-gdb-972d8a18db78974f59e1a6b1dc02f7e5b7d226d2.tar.bz2 |
2017-08-28 James Clarke <jrtc27@jrtc27.com>
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.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/aarch64.cc | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 2194a21..a72e2c3 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -1864,7 +1864,7 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian> // applied. bool try_fix_erratum_843419_optimized( - The_erratum_stub*, + The_erratum_stub*, AArch64_address, typename Sized_relobj_file<size, big_endian>::View_size&); // Whether a section needs to be scanned for relocation stubs. @@ -1980,6 +1980,7 @@ AArch64_relobj<size, big_endian>::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<size, big_endian>::fix_errata_and_relocate_erratum_stubs( std::pair<Erratum_stub_set_iter, Erratum_stub_set_iter> 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<size, big_endian>::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<size, big_endian>::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<Insntype*>(pview.view + stub->sh_offset()); + reinterpret_cast<Insntype*>( + 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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::fix_errata_and_relocate_erratum_stubs( template<int size, bool big_endian> bool AArch64_relobj<size, big_endian>::try_fix_erratum_843419_optimized( - The_erratum_stub* stub, + The_erratum_stub* stub, AArch64_address view_offset, typename Sized_relobj_file<size, big_endian>::View_size& pview) { if (stub->type() != ST_E_843419) @@ -2052,9 +2069,11 @@ AArch64_relobj<size, big_endian>::try_fix_erratum_843419_optimized( typedef typename elfcpp::Swap<32,big_endian>::Valtype Insntype; E843419_stub<size, big_endian>* e843419_stub = reinterpret_cast<E843419_stub<size, big_endian>*>(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<Insntype*>(pview.view + adrp_offset); + Insntype* adrp_view = + reinterpret_cast<Insntype*>(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<size, big_endian>::try_fix_erratum_843419_optimized( // return true. if (!Insn_utilities::is_adrp(adrp_insn) && adrp_offset) { - Insntype* prev_view - = reinterpret_cast<Insntype*>(pview.view + adrp_offset - 4); + Insntype* prev_view = + reinterpret_cast<Insntype*>( + pview.view + view_offset + adrp_offset - 4); Insntype prev_insn = prev_view[0]; if (Insn_utilities::is_mrs_tpidr_el0(prev_insn)) |