Add support for V_4B so we can properly reject it.
[deliverable/binutils-gdb.git] / gold / aarch64.cc
index 2194a21de2af74d09a2c45a02b390720bea144a2..5e702dbfd7710ef614da536ef35fe3c58b6cbba0 100644 (file)
@@ -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<big_endian>::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<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 +1992,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 +2001,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 +2052,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 + (stub_table->address() - pview.address));
 
           // Next erratum stub.
          ++p;
@@ -2042,7 +2071,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 +2081,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 +2101,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))
@@ -2284,6 +2316,19 @@ AArch64_relobj<size, big_endian>::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<Erratum_stub_set_iter, Erratum_stub_set_iter>
+         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
This page took 0.028365 seconds and 4 git commands to generate.