From ec8f12bcfe31bcd5020c48c28c7b5247e3749647 Mon Sep 17 00:00:00 2001 From: Han Shen Date: Tue, 16 Jun 2015 15:00:58 -0700 Subject: Patch for gold internal error while fixing erratum 843419. The crash reason is that the insn to be moved to stub may be a relocation spot, so instead of placing the origin insn (that is insn before-relocation) to the stub, I have to place the relocated one. Note the relocation involved is non-pc-relative, so it is safe to move the relocated insn. gold/ChangeLog: 2015-06-29 Han Shen * AArch64.cc (Erratum_stub::Insn_utilities): New typedef. (Erratum_stub::update_erratum_insn): New method. (Stub_table::relocate_stubs): Modified to place relocated insn. (AArch64_relobj::fix_errata): Modified gold_assert. Change-Id: I9d90ac6e569bbbab086f877c7446dc6f9ea96247 (cherry picked from commit 56b06706ebe6bb3decc674b788b6f5b243b8610d) --- binutils-2.25/gold/ChangeLog | 9 ++++++++ binutils-2.25/gold/aarch64.cc | 51 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/binutils-2.25/gold/ChangeLog b/binutils-2.25/gold/ChangeLog index fd3415ec..babb95ef 100644 --- a/binutils-2.25/gold/ChangeLog +++ b/binutils-2.25/gold/ChangeLog @@ -1,3 +1,12 @@ +2015-06-29 Han Shen + + Patch for erratum 843419 internal error. + + * AArch64.cc (Erratum_stub::Insn_utilities): New typedef. + (Erratum_stub::update_erratum_insn): New method. + (Stub_table::relocate_stubs): Modified to place relocated insn. + (AArch64_relobj::fix_errata): Modified gold_assert. + 2015-06-16 Yiran Wang * resolve.cc disable the warning of a hidden symbol matches a reference to be resolved diff --git a/binutils-2.25/gold/aarch64.cc b/binutils-2.25/gold/aarch64.cc index e8f5e1fa..7fc18f65 100644 --- a/binutils-2.25/gold/aarch64.cc +++ b/binutils-2.25/gold/aarch64.cc @@ -894,6 +894,7 @@ class Erratum_stub : public Stub_base public: typedef AArch64_relobj The_aarch64_relobj; typedef typename elfcpp::Elf_types::Elf_Addr AArch64_address; + typedef AArch64_insn_utilities Insn_utilities; typedef typename AArch64_insn_utilities::Insntype Insntype; static const int STUB_ADDR_ALIGN = 4; @@ -938,6 +939,38 @@ public: set_erratum_insn(Insntype insn) { this->erratum_insn_ = insn; } + // For 843419, the erratum insn is ld/st xt, [xn, #uimm], which may be a + // relocation spot, in this case, the erratum_insn_ recorded at scanning phase + // is no longer the one we want to write out to the stub, update erratum_insn_ + // with relocated version. Also note that in this case xn must not be "PC", so + // it is safe to move the erratum insn from the origin place to the stub. For + // 835769, the erratum insn is multiply-accumulate insn, which could not be a + // relocation spot (assertion added though). + void + update_erratum_insn(Insntype insn) + { + gold_assert(this->erratum_insn_ != this->invalid_insn); + switch (this->type()) + { + case ST_E_843419: + gold_assert(Insn_utilities::aarch64_ldst_uimm(insn)); + gold_assert(Insn_utilities::aarch64_ldst_uimm(this->erratum_insn())); + gold_assert(Insn_utilities::aarch64_rd(insn) == + Insn_utilities::aarch64_rd(this->erratum_insn())); + gold_assert(Insn_utilities::aarch64_rn(insn) == + Insn_utilities::aarch64_rn(this->erratum_insn())); + // Update plain ld/st insn with relocated insn. + this->erratum_insn_ = insn; + break; + case ST_E_835769: + gold_assert(insn == this->erratum_insn()); + break; + default: + gold_unreachable(); + } + } + + // Return the address where an erratum must be done. AArch64_address erratum_address() const @@ -1413,7 +1446,7 @@ Stub_table::add_erratum_stub(The_erratum_stub* stub) } -// Find if such erratum exists for givein (obj, shndx, sh_offset). +// Find if such erratum exists for given (obj, shndx, sh_offset). template Erratum_stub* @@ -1514,6 +1547,12 @@ relocate_stubs(const The_relocate_info* relinfo, { case ST_E_843419: case ST_E_835769: + // The 1st insn of the erratum could be a relocation spot, + // in this case we need to fix it with + // "(*i)->erratum_insn()". + elfcpp::Swap<32, big_endian>::writeval( + view + (stub_address - this->address()), + (*i)->erratum_insn()); // For the erratum, the 2nd insn is a b-insn to be patched // (relocated). stub_b_insn_address = stub_address + 1 * BPI; @@ -1831,13 +1870,17 @@ AArch64_relobj::fix_errata( pview((*pviews)[i]); // Double check data before fix. + gold_assert(pview.address + stub->sh_offset() + == stub->erratum_address()); + + // Update previously recorded erratum insn with relocated + // version. Insntype* ip = reinterpret_cast(pview.view + stub->sh_offset()); Insntype insn_to_fix = ip[0]; - gold_assert(insn_to_fix == stub->erratum_insn()); - gold_assert(pview.address + stub->sh_offset() - == stub->erratum_address()); + stub->update_erratum_insn(insn_to_fix); + // 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(); -- cgit v1.2.3