summaryrefslogtreecommitdiff
path: root/gold/powerpc.cc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-08-01 17:43:29 +0930
committerAlan Modra <amodra@gmail.com>2019-08-02 18:22:42 +0930
commit6a010cf67a96adcaf80c74f926df6b42ce13e7df (patch)
treec420914e864baabfd4275178df6301b3d4b2f148 /gold/powerpc.cc
parent97c0a07968a7c64e1de96abff8937d089f09b3e7 (diff)
downloadbinutils-gdb-6a010cf67a96adcaf80c74f926df6b42ce13e7df.tar.gz
[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.cc16
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: