summaryrefslogtreecommitdiff
path: root/gold/powerpc.cc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-10-09 10:59:33 +1030
committerAlan Modra <amodra@gmail.com>2020-10-09 23:23:27 +1030
commit4290b0ab2b65db23afc9bd8177885bfd91911c0c (patch)
tree1a61e6787591d50752f0b9e9dec57be28f3ac421 /gold/powerpc.cc
parent32930e4edbc06bc6f10c435dbcc63131715df678 (diff)
downloadbinutils-gdb-4290b0ab2b65db23afc9bd8177885bfd91911c0c.tar.gz
[GOLD] internal error in relocate, at powerpc.cc:10473
GOT relocations can refer directly to a function in a fixed position executable, unlike ADDR64 which needs a global entry stub, or branch relocs, which need PLT stubs. * powerpc.cc (is_got_reloc): New function. (Target_powerpc::Relocate::relocate): Use it here, exclude GOT relocs when looking for stubs.
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r--gold/powerpc.cc22
1 files changed, 15 insertions, 7 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index adbc120c14a..f9eb4f98bda 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -1884,6 +1884,19 @@ is_plt16_reloc(unsigned int r_type)
|| (size == 64 && r_type == elfcpp::R_PPC64_PLT16_LO_DS));
}
+// GOT_TYPE_STANDARD (ie. not TLS) GOT relocs
+inline bool
+is_got_reloc(unsigned int r_type)
+{
+ return (r_type == elfcpp::R_POWERPC_GOT16
+ || r_type == elfcpp::R_POWERPC_GOT16_LO
+ || r_type == elfcpp::R_POWERPC_GOT16_HI
+ || r_type == elfcpp::R_POWERPC_GOT16_HA
+ || r_type == elfcpp::R_PPC64_GOT16_DS
+ || r_type == elfcpp::R_PPC64_GOT16_LO_DS
+ || r_type == elfcpp::R_PPC64_GOT_PCREL34);
+}
+
// If INSN is an opcode that may be used with an @tls operand, return
// the transformed insn for TLS optimisation, otherwise return 0. If
// REG is non-zero only match an insn with RB or RA equal to REG.
@@ -10381,6 +10394,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
? gsym->use_plt_offset(Scan::get_reference_flags(r_type, target))
: object->local_has_plt_offset(r_sym));
if (has_plt_offset
+ && !is_got_reloc(r_type)
&& !is_plt16_reloc<size>(r_type)
&& r_type != elfcpp::R_PPC64_PLT_PCREL34
&& r_type != elfcpp::R_PPC64_PLT_PCREL34_NOTOC
@@ -10523,13 +10537,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
elfcpp::Swap<32, big_endian>::writeval(iview + 1, pnop & 0xffffffff);
r_type = elfcpp::R_POWERPC_NONE;
}
- else if (r_type == elfcpp::R_POWERPC_GOT16
- || r_type == elfcpp::R_POWERPC_GOT16_LO
- || r_type == elfcpp::R_POWERPC_GOT16_HI
- || r_type == elfcpp::R_POWERPC_GOT16_HA
- || r_type == elfcpp::R_PPC64_GOT16_DS
- || r_type == elfcpp::R_PPC64_GOT16_LO_DS
- || r_type == elfcpp::R_PPC64_GOT_PCREL34)
+ else if (is_got_reloc(r_type))
{
if (gsym != NULL)
{