aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2016-02-06 22:42:16 -0800
committerCary Coutant <ccoutant@gmail.com>2016-02-07 07:49:34 -0800
commit7c8b700c92444fca9ee81ab3844baadac0bdd4e3 (patch)
treed58a0a87a7878950547245d45b60ad134caad93e
parent30914ca8c030eedc4a7e1f1acc878211639cc1ca (diff)
downloadgdb-7c8b700c92444fca9ee81ab3844baadac0bdd4e3.zip
gdb-7c8b700c92444fca9ee81ab3844baadac0bdd4e3.tar.gz
gdb-7c8b700c92444fca9ee81ab3844baadac0bdd4e3.tar.bz2
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.
-rw-r--r--gold/ChangeLog5
-rw-r--r--gold/x86_64.cc13
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);