2009-11-09 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::fake_relnum_for_stubs): New constant. (arm_symbol_value): Remove. (Arm_relocate_functions::arm_branch_common, Arm_relocate_functions::abs8, Arm_relocate_functions::thm_abs5, Arm_relocate_functions::abs12, Arm_relocate_functions::abs16, Arm_relocate_functions::abs32, Arm_relocate_functions::rel32, Arm_relocate_functions::thm_call, Arm_relocate_functions::plt32, Arm_relocate_functions::call, Arm_relocate_functions::jump24, Arm_relocate_functions::prel31, Arm_relocate_functions::mov_abs_nc, Arm_relocate_functions::movt_abs, Arm_relocate_functions::movw_abs_nc, Arm_relocate_functions::thm_mobw_abs_nc, Arm_relocate_functions::thm_mov_abs, Arm_relocate_functions::movw_prel_nc, Arm_relocate_functions::thm_movt_abs, Arm_relocate_functions::movt_prel, Arm_relocate_functions::thm_movw_prel_nc, Arm_relocate_functions::thm_movt_prel): Adjust callers of the above. (Target_arm::Relocate::relocate): Only decompose address into two parts if relocation type uses the thumb-bit and pass the actual bit instead of a flag indicating that the thumb-bit is used. Adjust calls to methods in Arm_relocate_functions for this change.
This commit is contained in:
parent
57ca8ac797
commit
2daedcd627
2 changed files with 128 additions and 86 deletions
|
@ -1,3 +1,27 @@
|
||||||
|
2009-11-09 Doug Kwan <dougkwan@google.com>
|
||||||
|
|
||||||
|
* arm.cc (Target_arm::fake_relnum_for_stubs): New constant.
|
||||||
|
(arm_symbol_value): Remove.
|
||||||
|
(Arm_relocate_functions::arm_branch_common,
|
||||||
|
Arm_relocate_functions::abs8, Arm_relocate_functions::thm_abs5,
|
||||||
|
Arm_relocate_functions::abs12, Arm_relocate_functions::abs16,
|
||||||
|
Arm_relocate_functions::abs32, Arm_relocate_functions::rel32,
|
||||||
|
Arm_relocate_functions::thm_call, Arm_relocate_functions::plt32,
|
||||||
|
Arm_relocate_functions::call, Arm_relocate_functions::jump24,
|
||||||
|
Arm_relocate_functions::prel31, Arm_relocate_functions::mov_abs_nc,
|
||||||
|
Arm_relocate_functions::movt_abs, Arm_relocate_functions::movw_abs_nc,
|
||||||
|
Arm_relocate_functions::thm_mobw_abs_nc,
|
||||||
|
Arm_relocate_functions::thm_mov_abs,
|
||||||
|
Arm_relocate_functions::movw_prel_nc,
|
||||||
|
Arm_relocate_functions::thm_movt_abs,
|
||||||
|
Arm_relocate_functions::movt_prel,
|
||||||
|
Arm_relocate_functions::thm_movw_prel_nc,
|
||||||
|
Arm_relocate_functions::thm_movt_prel): Adjust callers of the above.
|
||||||
|
(Target_arm::Relocate::relocate): Only decompose address into two
|
||||||
|
parts if relocation type uses the thumb-bit and pass the actual
|
||||||
|
bit instead of a flag indicating that the thumb-bit is used. Adjust
|
||||||
|
calls to methods in Arm_relocate_functions for this change.
|
||||||
|
|
||||||
2009-11-08 Ian Lance Taylor <ian@airs.com>
|
2009-11-08 Ian Lance Taylor <ian@airs.com>
|
||||||
|
|
||||||
PR 10925
|
PR 10925
|
||||||
|
|
190
gold/arm.cc
190
gold/arm.cc
|
@ -1140,6 +1140,9 @@ class Target_arm : public Sized_target<32, big_endian>
|
||||||
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian>
|
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian>
|
||||||
Reloc_section;
|
Reloc_section;
|
||||||
|
|
||||||
|
// When were are relocating a stub, we pass this as the relocation number.
|
||||||
|
static const size_t fake_relnum_for_stubs = static_cast<size_t>(-1);
|
||||||
|
|
||||||
Target_arm()
|
Target_arm()
|
||||||
: Sized_target<32, big_endian>(&arm_info),
|
: Sized_target<32, big_endian>(&arm_info),
|
||||||
got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
|
got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
|
||||||
|
@ -1653,27 +1656,6 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
typedef Relocate_functions<32, big_endian> Base;
|
typedef Relocate_functions<32, big_endian> Base;
|
||||||
typedef Arm_relocate_functions<big_endian> This;
|
typedef Arm_relocate_functions<big_endian> This;
|
||||||
|
|
||||||
// Get an symbol value of *PSYMVAL with an ADDEND. This is a wrapper
|
|
||||||
// to Symbol_value::value(). If HAS_THUMB_BIT is true, that LSB is used
|
|
||||||
// to distinguish ARM and THUMB functions and it is treated specially.
|
|
||||||
static inline Symbol_value<32>::Value
|
|
||||||
arm_symbol_value (const Sized_relobj<32, big_endian> *object,
|
|
||||||
const Symbol_value<32>* psymval,
|
|
||||||
Symbol_value<32>::Value addend,
|
|
||||||
bool has_thumb_bit)
|
|
||||||
{
|
|
||||||
typedef Symbol_value<32>::Value Valtype;
|
|
||||||
|
|
||||||
if (has_thumb_bit)
|
|
||||||
{
|
|
||||||
Valtype raw = psymval->value(object, 0);
|
|
||||||
Valtype thumb_bit = raw & 1;
|
|
||||||
return ((raw & ~((Valtype) 1)) + addend) | thumb_bit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return psymval->value(object, addend);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encoding of imm16 argument for movt and movw ARM instructions
|
// Encoding of imm16 argument for movt and movw ARM instructions
|
||||||
// from ARM ARM:
|
// from ARM ARM:
|
||||||
//
|
//
|
||||||
|
@ -1755,7 +1737,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
|
@ -1788,8 +1770,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
|
|
||||||
Valtype addend = utils::sign_extend<26>(val << 2);
|
Valtype addend = utils::sign_extend<26>(val << 2);
|
||||||
Valtype x = (This::arm_symbol_value(object, psymval, addend, has_thumb_bit)
|
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
|
||||||
- address);
|
|
||||||
|
|
||||||
// If target has thumb bit set, we need to either turn the BL
|
// If target has thumb bit set, we need to either turn the BL
|
||||||
// into a BLX (for ARMv5 or above) or generate a stub.
|
// into a BLX (for ARMv5 or above) or generate a stub.
|
||||||
|
@ -1823,7 +1804,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
|
||||||
Reltype addend = utils::sign_extend<8>(val);
|
Reltype addend = utils::sign_extend<8>(val);
|
||||||
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
|
Reltype x = psymval->value(object, addend);
|
||||||
val = utils::bit_select(val, x, 0xffU);
|
val = utils::bit_select(val, x, 0xffU);
|
||||||
elfcpp::Swap<8, big_endian>::writeval(wv, val);
|
elfcpp::Swap<8, big_endian>::writeval(wv, val);
|
||||||
return (utils::has_signed_unsigned_overflow<8>(x)
|
return (utils::has_signed_unsigned_overflow<8>(x)
|
||||||
|
@ -1842,7 +1823,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
|
||||||
Reltype addend = (val & 0x7e0U) >> 6;
|
Reltype addend = (val & 0x7e0U) >> 6;
|
||||||
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
|
Reltype x = psymval->value(object, addend);
|
||||||
val = utils::bit_select(val, x << 6, 0x7e0U);
|
val = utils::bit_select(val, x << 6, 0x7e0U);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv, val);
|
elfcpp::Swap<16, big_endian>::writeval(wv, val);
|
||||||
return (utils::has_overflow<5>(x)
|
return (utils::has_overflow<5>(x)
|
||||||
|
@ -1861,7 +1842,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Reltype addend = val & 0x0fffU;
|
Reltype addend = val & 0x0fffU;
|
||||||
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
|
Reltype x = psymval->value(object, addend);
|
||||||
val = utils::bit_select(val, x, 0x0fffU);
|
val = utils::bit_select(val, x, 0x0fffU);
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
||||||
return (utils::has_overflow<12>(x)
|
return (utils::has_overflow<12>(x)
|
||||||
|
@ -1880,7 +1861,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
|
||||||
Reltype addend = utils::sign_extend<16>(val);
|
Reltype addend = utils::sign_extend<16>(val);
|
||||||
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
|
Reltype x = psymval->value(object, addend);
|
||||||
val = utils::bit_select(val, x, 0xffffU);
|
val = utils::bit_select(val, x, 0xffffU);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv, val);
|
elfcpp::Swap<16, big_endian>::writeval(wv, val);
|
||||||
return (utils::has_signed_unsigned_overflow<16>(x)
|
return (utils::has_signed_unsigned_overflow<16>(x)
|
||||||
|
@ -1893,12 +1874,12 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
abs32(unsigned char *view,
|
abs32(unsigned char *view,
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype x = This::arm_symbol_value(object, psymval, addend, has_thumb_bit);
|
Valtype x = psymval->value(object, addend) | thumb_bit;
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, x);
|
elfcpp::Swap<32, big_endian>::writeval(wv, x);
|
||||||
return This::STATUS_OKAY;
|
return This::STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
@ -1909,13 +1890,12 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype x = (This::arm_symbol_value(object, psymval, addend, has_thumb_bit)
|
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
|
||||||
- address);
|
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, x);
|
elfcpp::Swap<32, big_endian>::writeval(wv, x);
|
||||||
return This::STATUS_OKAY;
|
return This::STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
@ -1926,7 +1906,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
// A thumb call consists of two instructions.
|
// A thumb call consists of two instructions.
|
||||||
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
|
||||||
|
@ -1938,8 +1918,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
gold_assert((lo & 0xf800) == 0xf800);
|
gold_assert((lo & 0xf800) == 0xf800);
|
||||||
Reltype addend = utils::sign_extend<23>(((hi & 0x7ff) << 12)
|
Reltype addend = utils::sign_extend<23>(((hi & 0x7ff) << 12)
|
||||||
| ((lo & 0x7ff) << 1));
|
| ((lo & 0x7ff) << 1));
|
||||||
Reltype x = (This::arm_symbol_value(object, psymval, addend, has_thumb_bit)
|
Reltype x = (psymval->value(object, addend) | thumb_bit) - address;
|
||||||
- address);
|
|
||||||
|
|
||||||
// If target has no thumb bit set, we need to either turn the BL
|
// If target has no thumb bit set, we need to either turn the BL
|
||||||
// into a BLX (for ARMv5 or above) or generate a stub.
|
// into a BLX (for ARMv5 or above) or generate a stub.
|
||||||
|
@ -2001,10 +1980,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
return arm_branch_common<elfcpp::R_ARM_PLT32>(view, object, psymval,
|
return arm_branch_common<elfcpp::R_ARM_PLT32>(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// R_ARM_CALL: (S + A) | T - P
|
// R_ARM_CALL: (S + A) | T - P
|
||||||
|
@ -2013,10 +1992,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
return arm_branch_common<elfcpp::R_ARM_CALL>(view, object, psymval,
|
return arm_branch_common<elfcpp::R_ARM_CALL>(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// R_ARM_JUMP24: (S + A) | T - P
|
// R_ARM_JUMP24: (S + A) | T - P
|
||||||
|
@ -2025,10 +2004,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
return arm_branch_common<elfcpp::R_ARM_JUMP24>(view, object, psymval,
|
return arm_branch_common<elfcpp::R_ARM_JUMP24>(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// R_ARM_PREL: (S + A) | T - P
|
// R_ARM_PREL: (S + A) | T - P
|
||||||
|
@ -2037,14 +2016,13 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype addend = utils::sign_extend<31>(val);
|
Valtype addend = utils::sign_extend<31>(val);
|
||||||
Valtype x = (This::arm_symbol_value(object, psymval, addend, has_thumb_bit)
|
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
|
||||||
- address);
|
|
||||||
val = utils::bit_select(val, x, 0x7fffffffU);
|
val = utils::bit_select(val, x, 0x7fffffffU);
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
||||||
return (utils::has_overflow<31>(x) ?
|
return (utils::has_overflow<31>(x) ?
|
||||||
|
@ -2056,13 +2034,13 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
movw_abs_nc(unsigned char *view,
|
movw_abs_nc(unsigned char *view,
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
||||||
Valtype x = This::arm_symbol_value(object, psymval, addend, has_thumb_bit);
|
Valtype x = psymval->value(object, addend) | thumb_bit;
|
||||||
val = This::insert_val_arm_movw_movt(val, x);
|
val = This::insert_val_arm_movw_movt(val, x);
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
||||||
return This::STATUS_OKAY;
|
return This::STATUS_OKAY;
|
||||||
|
@ -2078,7 +2056,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
||||||
Valtype x = This::arm_symbol_value(object, psymval, addend, 0) >> 16;
|
Valtype x = psymval->value(object, addend) >> 16;
|
||||||
val = This::insert_val_arm_movw_movt(val, x);
|
val = This::insert_val_arm_movw_movt(val, x);
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
||||||
return This::STATUS_OKAY;
|
return This::STATUS_OKAY;
|
||||||
|
@ -2089,7 +2067,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
thm_movw_abs_nc(unsigned char *view,
|
thm_movw_abs_nc(unsigned char *view,
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
|
||||||
|
@ -2097,7 +2075,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Reltype val = ((elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
Reltype val = ((elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
||||||
| elfcpp::Swap<16, big_endian>::readval(wv + 1));
|
| elfcpp::Swap<16, big_endian>::readval(wv + 1));
|
||||||
Reltype addend = extract_thumb_movw_movt_addend(val);
|
Reltype addend = extract_thumb_movw_movt_addend(val);
|
||||||
Reltype x = This::arm_symbol_value(object, psymval, addend, has_thumb_bit);
|
Reltype x = psymval->value(object, addend) | thumb_bit;
|
||||||
val = This::insert_val_thumb_movw_movt(val, x);
|
val = This::insert_val_thumb_movw_movt(val, x);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
||||||
|
@ -2116,7 +2094,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Reltype val = ((elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
Reltype val = ((elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
||||||
| elfcpp::Swap<16, big_endian>::readval(wv + 1));
|
| elfcpp::Swap<16, big_endian>::readval(wv + 1));
|
||||||
Reltype addend = This::extract_thumb_movw_movt_addend(val);
|
Reltype addend = This::extract_thumb_movw_movt_addend(val);
|
||||||
Reltype x = This::arm_symbol_value(object, psymval, addend, 0) >> 16;
|
Reltype x = psymval->value(object, addend) >> 16;
|
||||||
val = This::insert_val_thumb_movw_movt(val, x);
|
val = This::insert_val_thumb_movw_movt(val, x);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
||||||
|
@ -2129,14 +2107,13 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
||||||
Valtype x = (This::arm_symbol_value(object, psymval, addend, has_thumb_bit)
|
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
|
||||||
- address);
|
|
||||||
val = This::insert_val_arm_movw_movt(val, x);
|
val = This::insert_val_arm_movw_movt(val, x);
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
||||||
return This::STATUS_OKAY;
|
return This::STATUS_OKAY;
|
||||||
|
@ -2153,8 +2130,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||||
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
|
||||||
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
Valtype addend = This::extract_arm_movw_movt_addend(val);
|
||||||
Valtype x = (This::arm_symbol_value(object, psymval, addend, 0)
|
Valtype x = (psymval->value(object, addend) - address) >> 16;
|
||||||
- address) >> 16;
|
|
||||||
val = This::insert_val_arm_movw_movt(val, x);
|
val = This::insert_val_arm_movw_movt(val, x);
|
||||||
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
elfcpp::Swap<32, big_endian>::writeval(wv, val);
|
||||||
return This::STATUS_OKAY;
|
return This::STATUS_OKAY;
|
||||||
|
@ -2166,7 +2142,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
const Sized_relobj<32, big_endian>* object,
|
const Sized_relobj<32, big_endian>* object,
|
||||||
const Symbol_value<32>* psymval,
|
const Symbol_value<32>* psymval,
|
||||||
Arm_address address,
|
Arm_address address,
|
||||||
bool has_thumb_bit)
|
Arm_address thumb_bit)
|
||||||
{
|
{
|
||||||
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
|
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
|
||||||
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
|
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
|
||||||
|
@ -2174,8 +2150,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Reltype val = (elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
Reltype val = (elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
||||||
| elfcpp::Swap<16, big_endian>::readval(wv + 1);
|
| elfcpp::Swap<16, big_endian>::readval(wv + 1);
|
||||||
Reltype addend = This::extract_thumb_movw_movt_addend(val);
|
Reltype addend = This::extract_thumb_movw_movt_addend(val);
|
||||||
Reltype x = (This::arm_symbol_value(object, psymval, addend, has_thumb_bit)
|
Reltype x = (psymval->value(object, addend) | thumb_bit) - address;
|
||||||
- address);
|
|
||||||
val = This::insert_val_thumb_movw_movt(val, x);
|
val = This::insert_val_thumb_movw_movt(val, x);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
||||||
|
@ -2195,8 +2170,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
|
||||||
Reltype val = (elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
Reltype val = (elfcpp::Swap<16, big_endian>::readval(wv) << 16)
|
||||||
| elfcpp::Swap<16, big_endian>::readval(wv + 1);
|
| elfcpp::Swap<16, big_endian>::readval(wv + 1);
|
||||||
Reltype addend = This::extract_thumb_movw_movt_addend(val);
|
Reltype addend = This::extract_thumb_movw_movt_addend(val);
|
||||||
Reltype x = (This::arm_symbol_value(object, psymval, addend, 0)
|
Reltype x = (psymval->value(object, addend) - address) >> 16;
|
||||||
- address) >> 16;
|
|
||||||
val = This::insert_val_thumb_movw_movt(val, x);
|
val = This::insert_val_thumb_movw_movt(val, x);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
|
||||||
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
|
||||||
|
@ -4424,24 +4398,68 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
|
|
||||||
r_type = get_real_reloc_type(r_type);
|
r_type = get_real_reloc_type(r_type);
|
||||||
|
|
||||||
// If this the symbol may be a Thumb function, set thumb bit to 1.
|
const Arm_relobj<big_endian>* object =
|
||||||
bool has_thumb_bit = ((gsym != NULL)
|
Arm_relobj<big_endian>::as_arm_relobj(relinfo->object);
|
||||||
&& (gsym->type() == elfcpp::STT_FUNC
|
|
||||||
|| gsym->type() == elfcpp::STT_ARM_TFUNC));
|
|
||||||
|
|
||||||
// Pick the value to use for symbols defined in shared objects.
|
// If the final branch target of a relocation is THUMB instruction, this
|
||||||
|
// is 1. Otherwise it is 0.
|
||||||
|
Arm_address thumb_bit = 0;
|
||||||
Symbol_value<32> symval;
|
Symbol_value<32> symval;
|
||||||
if (gsym != NULL
|
if (relnum != Target_arm<big_endian>::fake_relnum_for_stubs)
|
||||||
&& gsym->use_plt_offset(reloc_is_non_pic(r_type)))
|
|
||||||
{
|
{
|
||||||
symval.set_output_value(target->plt_section()->address()
|
if (gsym != NULL)
|
||||||
+ gsym->plt_offset());
|
{
|
||||||
psymval = &symval;
|
// This is a global symbol. Determine if we use PLT and if the
|
||||||
has_thumb_bit = 0;
|
// final target is THUMB.
|
||||||
|
if (gsym->use_plt_offset(reloc_is_non_pic(r_type)))
|
||||||
|
{
|
||||||
|
// This uses a PLT, change the symbol value.
|
||||||
|
symval.set_output_value(target->plt_section()->address()
|
||||||
|
+ gsym->plt_offset());
|
||||||
|
psymval = &symval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set thumb bit if symbol:
|
||||||
|
// -Has type STT_ARM_TFUNC or
|
||||||
|
// -Has type STT_FUNC, is defined and with LSB in value set.
|
||||||
|
thumb_bit =
|
||||||
|
(((gsym->type() == elfcpp::STT_ARM_TFUNC)
|
||||||
|
|| (gsym->type() == elfcpp::STT_FUNC
|
||||||
|
&& !gsym->is_undefined()
|
||||||
|
&& ((psymval->value(object, 0) & 1) != 0)))
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is a local symbol. Determine if the final target is THUMB.
|
||||||
|
// We saved this information when all the local symbols were read.
|
||||||
|
elfcpp::Elf_types<32>::Elf_WXword r_info = rel.get_r_info();
|
||||||
|
unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info);
|
||||||
|
thumb_bit = object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is a fake relocation synthesized for a stub. It does not have
|
||||||
|
// a real symbol. We just look at the LSB of the symbol value to
|
||||||
|
// determine if the target is THUMB or not.
|
||||||
|
thumb_bit = ((psymval->value(object, 0) & 1) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sized_relobj<32, big_endian>* object = relinfo->object;
|
// Strip LSB if this points to a THUMB target.
|
||||||
|
if (thumb_bit != 0
|
||||||
|
&& Target_arm<big_endian>::reloc_uses_thumb_bit(r_type)
|
||||||
|
&& ((psymval->value(object, 0) & 1) != 0))
|
||||||
|
{
|
||||||
|
Arm_address stripped_value =
|
||||||
|
psymval->value(object, 0) & ~static_cast<Arm_address>(1);
|
||||||
|
symval.set_output_value(stripped_value);
|
||||||
|
psymval = &symval;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the GOT offset if needed.
|
// Get the GOT offset if needed.
|
||||||
// The GOT pointer points to the end of the GOT section.
|
// The GOT pointer points to the end of the GOT section.
|
||||||
// We need to subtract the size of the GOT section to get
|
// We need to subtract the size of the GOT section to get
|
||||||
|
@ -4501,7 +4519,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
|
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
|
||||||
output_section))
|
output_section))
|
||||||
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
|
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
|
||||||
has_thumb_bit);
|
thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_ABS32_NOI:
|
case elfcpp::R_ARM_ABS32_NOI:
|
||||||
|
@ -4517,7 +4535,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
output_section))
|
output_section))
|
||||||
reloc_status = Arm_relocate_functions::movw_abs_nc(view, object,
|
reloc_status = Arm_relocate_functions::movw_abs_nc(view, object,
|
||||||
psymval,
|
psymval,
|
||||||
has_thumb_bit);
|
thumb_bit);
|
||||||
else
|
else
|
||||||
gold_error(_("relocation R_ARM_MOVW_ABS_NC cannot be used when making"
|
gold_error(_("relocation R_ARM_MOVW_ABS_NC cannot be used when making"
|
||||||
"a shared object; recompile with -fPIC"));
|
"a shared object; recompile with -fPIC"));
|
||||||
|
@ -4537,7 +4555,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
output_section))
|
output_section))
|
||||||
reloc_status = Arm_relocate_functions::thm_movw_abs_nc(view, object,
|
reloc_status = Arm_relocate_functions::thm_movw_abs_nc(view, object,
|
||||||
psymval,
|
psymval,
|
||||||
has_thumb_bit);
|
thumb_bit);
|
||||||
else
|
else
|
||||||
gold_error(_("relocation R_ARM_THM_MOVW_ABS_NC cannot be used when"
|
gold_error(_("relocation R_ARM_THM_MOVW_ABS_NC cannot be used when"
|
||||||
"making a shared object; recompile with -fPIC"));
|
"making a shared object; recompile with -fPIC"));
|
||||||
|
@ -4556,7 +4574,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
case elfcpp::R_ARM_MOVW_PREL_NC:
|
case elfcpp::R_ARM_MOVW_PREL_NC:
|
||||||
reloc_status = Arm_relocate_functions::movw_prel_nc(view, object,
|
reloc_status = Arm_relocate_functions::movw_prel_nc(view, object,
|
||||||
psymval, address,
|
psymval, address,
|
||||||
has_thumb_bit);
|
thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_MOVT_PREL:
|
case elfcpp::R_ARM_MOVT_PREL:
|
||||||
|
@ -4567,7 +4585,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
case elfcpp::R_ARM_THM_MOVW_PREL_NC:
|
case elfcpp::R_ARM_THM_MOVW_PREL_NC:
|
||||||
reloc_status = Arm_relocate_functions::thm_movw_prel_nc(view, object,
|
reloc_status = Arm_relocate_functions::thm_movw_prel_nc(view, object,
|
||||||
psymval, address,
|
psymval, address,
|
||||||
has_thumb_bit);
|
thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_THM_MOVT_PREL:
|
case elfcpp::R_ARM_THM_MOVT_PREL:
|
||||||
|
@ -4577,7 +4595,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
|
|
||||||
case elfcpp::R_ARM_REL32:
|
case elfcpp::R_ARM_REL32:
|
||||||
reloc_status = Arm_relocate_functions::rel32(view, object, psymval,
|
reloc_status = Arm_relocate_functions::rel32(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_THM_ABS5:
|
case elfcpp::R_ARM_THM_ABS5:
|
||||||
|
@ -4588,7 +4606,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
|
|
||||||
case elfcpp::R_ARM_THM_CALL:
|
case elfcpp::R_ARM_THM_CALL:
|
||||||
reloc_status = Arm_relocate_functions::thm_call(view, object, psymval,
|
reloc_status = Arm_relocate_functions::thm_call(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_GOTOFF32:
|
case elfcpp::R_ARM_GOTOFF32:
|
||||||
|
@ -4596,7 +4614,7 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
Arm_address got_origin;
|
Arm_address got_origin;
|
||||||
got_origin = target->got_plt_section()->address();
|
got_origin = target->got_plt_section()->address();
|
||||||
reloc_status = Arm_relocate_functions::rel32(view, object, psymval,
|
reloc_status = Arm_relocate_functions::rel32(view, object, psymval,
|
||||||
got_origin, has_thumb_bit);
|
got_origin, thumb_bit);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4674,22 +4692,22 @@ Target_arm<big_endian>::Relocate::relocate(
|
||||||
&& !gsym->is_from_dynobj()
|
&& !gsym->is_from_dynobj()
|
||||||
&& !gsym->is_preemptible()));
|
&& !gsym->is_preemptible()));
|
||||||
reloc_status = Arm_relocate_functions::plt32(view, object, psymval,
|
reloc_status = Arm_relocate_functions::plt32(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_CALL:
|
case elfcpp::R_ARM_CALL:
|
||||||
reloc_status = Arm_relocate_functions::call(view, object, psymval,
|
reloc_status = Arm_relocate_functions::call(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_JUMP24:
|
case elfcpp::R_ARM_JUMP24:
|
||||||
reloc_status = Arm_relocate_functions::jump24(view, object, psymval,
|
reloc_status = Arm_relocate_functions::jump24(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_PREL31:
|
case elfcpp::R_ARM_PREL31:
|
||||||
reloc_status = Arm_relocate_functions::prel31(view, object, psymval,
|
reloc_status = Arm_relocate_functions::prel31(view, object, psymval,
|
||||||
address, has_thumb_bit);
|
address, thumb_bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_ARM_TARGET1:
|
case elfcpp::R_ARM_TARGET1:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue