Fix incorrect x32 overflow checking for refs to weak undef symbols.
authorCary Coutant <ccoutant@gmail.com>
Sun, 7 Feb 2016 06:42:16 +0000 (22:42 -0800)
committerCary Coutant <ccoutant@gmail.com>
Sun, 7 Feb 2016 15:49:34 +0000 (07:49 -0800)
On x32, a pc-relative reference to an undef weak symbol (value 0)
with a negative addend (typically -4) generates a spurious overflow
error because Symbol_value::value() returns a 32-bit negative number
as an unsigned number, which gets zero-extended before subtracting
the PC value. This patch fixes the problem by special-casing the
negative addend, and adding it to the value after widening it to
64 bits. Symbol_value::value() does not need the addend if it's
negative, since it is only important when processing section
symbols for merge sections, where a positive addend provides the
input section offset of the merged constant.

gold/
* x86_64.cc (X86_64_relocate_functions::pcrela32_check): Fix x32
overflow checking when symbol value + addend < 0.

gold/ChangeLog
gold/x86_64.cc

index e11419847fcc8308b524497d7a5de78a29236e27..d824511082d4fe7cbd096d7424d521eb493aa1ae 100644 (file)
@@ -1,3 +1,8 @@
+2016-02-06  Cary Coutant  <ccoutant@gmail.com>
+
+       * x86_64.cc (X86_64_relocate_functions::pcrela32_check): Fix x32
+       overflow checking when symbol value + addend < 0.
+
 2016-02-06  Cary Coutant  <ccoutant@gmail.com>
 
        PR gold/19577
index 494b312d5169a6ace41e5871266c8a15c4a03a0e..b0780af10019a7300e5243b7edeefe4cc0fdd0c7 100644 (file)
@@ -3385,8 +3385,17 @@ class X86_64_relocate_functions : public Relocate_functions<size, false>
   {
     typedef typename elfcpp::Swap<32, false>::Valtype Valtype;
     Valtype* wv = reinterpret_cast<Valtype*>(view);
-    typename elfcpp::Elf_types<64>::Elf_Addr value =
-       psymval->value(object, addend) - address;
+    typename elfcpp::Elf_types<64>::Elf_Addr value;
+    if (addend >= 0)
+      value = psymval->value(object, addend);
+    else
+      {
+       // For negative addends, get the symbol value without
+       // the addend, then add the addend using 64-bit arithmetic.
+       value = psymval->value(object, 0);
+       value += addend;
+      }
+    value -= address;
     elfcpp::Swap<32, false>::writeval(wv, value);
     return (Bits<32>::has_overflow(value)
            ? Base::RELOC_OVERFLOW : Base::RELOC_OK);