This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Patch for gold internal error while fixing erratum 843419.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=56b06706ebe6bb3decc674b788b6f5b243b8610d

commit 56b06706ebe6bb3decc674b788b6f5b243b8610d
Author: Han Shen <shenhan@google.com>
Date:   Tue Jun 16 15:00:58 2015 -0700

    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  <shenhan@google.com>
    
        * 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.

Diff:
---
 gold/ChangeLog  |  9 +++++++++
 gold/aarch64.cc | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index 7e9997d..4b5b860 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,12 @@
+2015-06-29  Han Shen  <shenhan@google.com>
+
+	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-12  Han Shen  <shenhan@google.com>
 
 	Fix erratum 835769.
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
index 72a65db..e32f003 100644
--- a/gold/aarch64.cc
+++ b/gold/aarch64.cc
@@ -894,6 +894,7 @@ class Erratum_stub : public Stub_base<size, big_endian>
 public:
   typedef AArch64_relobj<size, big_endian> The_aarch64_relobj;
   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
+  typedef AArch64_insn_utilities<big_endian> Insn_utilities;
   typedef typename AArch64_insn_utilities<big_endian>::Insntype Insntype;
 
   static const int STUB_ADDR_ALIGN;
@@ -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
@@ -1417,7 +1450,7 @@ Stub_table<size, big_endian>::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<int size, bool big_endian>
 Erratum_stub<size, big_endian>*
@@ -1518,6 +1551,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;
@@ -1835,13 +1874,17 @@ AArch64_relobj<size, big_endian>::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<Insntype*>(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();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]