diff options
author | Alan Modra <amodra@gmail.com> | 2019-08-01 17:43:29 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-08-02 18:22:42 +0930 |
commit | 6a010cf67a96adcaf80c74f926df6b42ce13e7df (patch) | |
tree | c420914e864baabfd4275178df6301b3d4b2f148 /gold/powerpc.cc | |
parent | PR24871, readelf segv in dump_ia64_unwind (diff) | |
download | binutils-gdb-6a010cf67a96adcaf80c74f926df6b42ce13e7df.tar.gz binutils-gdb-6a010cf67a96adcaf80c74f926df6b42ce13e7df.tar.bz2 binutils-gdb-6a010cf67a96adcaf80c74f926df6b42ce13e7df.zip |
[GOLD] PowerPC relocation signed overflow check
Relocations with right shifts were calculating wrong overflow status.
Since the addr34 split-field reloc is implemented as an 18-bit high
part with value shifted right by 16 and a 16-bit low part, most of the
pc-relative relocs were affected.
* powerpc.cc (Powerpc_relocate_functions::rela, rela_ua): Perform
signed right shift for signed overflow check.
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r-- | gold/powerpc.cc | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 688f7243d32..67c3061bb3e 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1996,11 +1996,15 @@ private: typedef typename elfcpp::Swap<fieldsize, big_endian>::Valtype Valtype; Valtype* wv = reinterpret_cast<Valtype*>(view); Valtype val = elfcpp::Swap<fieldsize, big_endian>::readval(wv); - Valtype reloc = value >> right_shift; + if (overflow == CHECK_SIGNED) + value = static_cast<SignedAddress>(value) >> right_shift; + else + value = value >> right_shift; + Valtype reloc = value; val &= ~dst_mask; reloc &= dst_mask; elfcpp::Swap<fieldsize, big_endian>::writeval(wv, val | reloc); - return overflowed<valsize>(value >> right_shift, overflow); + return overflowed<valsize>(value, overflow); } // Do a simple RELA relocation, unaligned. @@ -2023,11 +2027,15 @@ private: typedef typename elfcpp::Swap_unaligned<fieldsize, big_endian>::Valtype Valtype; Valtype val = elfcpp::Swap<fieldsize, big_endian>::readval(view); - Valtype reloc = value >> right_shift; + if (overflow == CHECK_SIGNED) + value = static_cast<SignedAddress>(value) >> right_shift; + else + value = value >> right_shift; + Valtype reloc = value; val &= ~dst_mask; reloc &= dst_mask; elfcpp::Swap_unaligned<fieldsize, big_endian>::writeval(view, val | reloc); - return overflowed<valsize>(value >> right_shift, overflow); + return overflowed<valsize>(value, overflow); } public: |