This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix incorrect x32 overflow checking for refs to weak undef symbols.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7c8b700c92444fca9ee81ab3844baadac0bdd4e3

commit 7c8b700c92444fca9ee81ab3844baadac0bdd4e3
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Sat Feb 6 22:42:16 2016 -0800

    Fix incorrect x32 overflow checking for refs to weak undef symbols.
    
    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.

Diff:
---
 gold/ChangeLog |  5 +++++
 gold/x86_64.cc | 13 +++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index e114198..d824511 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,10 @@
 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
 	* reloc.h (Limits): New class.
 	(Bits::has_overflow32): Use min/max values from Limits.
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 494b312..b0780af 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]