[GOLD] PowerPC relocation signed overflow check
authorAlan Modra <amodra@gmail.com>
Thu, 1 Aug 2019 08:13:29 +0000 (17:43 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 2 Aug 2019 08:52:42 +0000 (18:22 +0930)
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.

gold/ChangeLog
gold/powerpc.cc

index 754d0e3eb202e09f9f0b5993654411a8462bdbf6..b2961d72f21bc7e35c1ce0cd336c98c753bf671e 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-02  Alan Modra  <amodra@gmail.com>
+
+       * powerpc.cc (Powerpc_relocate_functions::rela, rela_ua): Perform
+       signed right shift for signed overflow check.
+
 2019-07-29  Martin Liska  <mliska@suse.cz>
 
        PR 24768
index 688f7243d328120fcd6f05919ed8d02be6049770..67c3061bb3ee5c0413c16638afed81a5aa2d9c51 100644 (file)
@@ -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: