summaryrefslogtreecommitdiff
path: root/gold/aarch64.cc
diff options
context:
space:
mode:
authorPeter Smith <peter.smith@linaro.org>2017-11-30 15:07:26 -0800
committerCary Coutant <ccoutant@gmail.com>2017-11-30 15:08:21 -0800
commitfd6798fa2d6f0374d45449c4212869da93623b1e (patch)
tree82f8c3c3510c64b2d673a473c20ac16d78a09127 /gold/aarch64.cc
parente0feb133429709603eeeb382c1ebb6edd0a886aa (diff)
downloadbinutils-gdb-fd6798fa2d6f0374d45449c4212869da93623b1e.tar.gz
Fix internal error in fix_errata on aarch64.
The addresses of erratum stubs can be changed by relaxation passes, and need to be updated. gold/ PR gold/20765 * aarch64.cc (Aarch64_relobj::update_erratum_address): New method. (AArch64_relobj::scan_errata): Update addresses in stub table after relaxation pass.
Diffstat (limited to 'gold/aarch64.cc')
-rw-r--r--gold/aarch64.cc25
1 files changed, 25 insertions, 0 deletions
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
index 04da01d51fa..5e702dbfd77 100644
--- a/gold/aarch64.cc
+++ b/gold/aarch64.cc
@@ -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).
@@ -2304,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);