diff options
author | Cary Coutant <ccoutant@gmail.com> | 2016-02-06 22:42:16 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-02-07 07:49:34 -0800 |
commit | 7c8b700c92444fca9ee81ab3844baadac0bdd4e3 (patch) | |
tree | d58a0a87a7878950547245d45b60ad134caad93e | |
parent | 30914ca8c030eedc4a7e1f1acc878211639cc1ca (diff) | |
download | gdb-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/ChangeLog | 5 | ||||
-rw-r--r-- | 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); |