diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-09-18 00:45:53 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-09-18 00:45:53 +0000 |
commit | 5e445df679225ddbcd707c65ebb1c05af08536fc (patch) | |
tree | 7283197a7726757184987a298669d1a2cff95e68 /gold/arm.cc | |
parent | eb4fd9dd881d958e72120ad58c0d2de0d3b1a91e (diff) | |
download | gdb-5e445df679225ddbcd707c65ebb1c05af08536fc.zip gdb-5e445df679225ddbcd707c65ebb1c05af08536fc.tar.gz gdb-5e445df679225ddbcd707c65ebb1c05af08536fc.tar.bz2 |
* arm.cc (has_signed_unsigned_overflow): New function.
(Arm_relocate_functions::abs8): New function.
(Target_arm::Scan::local): Handle R_ARM_ABS8.
(Target_arm::Scan::global): Likewise.
(Target_arm::relocate::relocate): Likewise.
(Target_arm::Relocatable_size_for_reloc::get_size_for_reloc):
Likewise.
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index 0e4a3eb..6fc71a7 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -117,6 +117,23 @@ namespace utils return as_signed > max || as_signed < min; } + // Detects overflow of an NO_BITS integer stored in a uint32_t when it + // fits in the given number of bits as either a signed or unsigned value. + // For example, has_signed_unsigned_overflow<8> would check + // -128 <= bits <= 255 + template<int no_bits> + static inline bool + has_signed_unsigned_overflow(uint32_t bits) + { + gold_assert(no_bits >= 2 && no_bits <= 32); + if (no_bits == 32) + return false; + int32_t max = static_cast<int32_t>((1U << no_bits) - 1); + int32_t min = -(1 << (no_bits - 1)); + int32_t as_signed = static_cast<int32_t>(bits); + return as_signed > max || as_signed < min; + } + // Select bits from A and B using bits in MASK. For each n in [0..31], // the n-th bit in the result is chosen from the n-th bits of A and B. // A zero selects A and a one selects B. @@ -555,6 +572,26 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian> } public: + + // R_ARM_ABS8: S + A + static inline typename This::Status + abs8(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, bool has_thumb_bit) + { + typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<8, big_endian>::readval(wv); + Reltype addend = utils::sign_extend<8>(val); + Reltype x = This::arm_symbol_value(object, psymval, addend, has_thumb_bit); + val = utils::bit_select(val, x, 0xffU); + elfcpp::Swap<8, big_endian>::writeval(wv, val); + return (utils::has_signed_unsigned_overflow<8>(x) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + // R_ARM_ABS32: (S + A) | T static inline typename This::Status abs32(unsigned char *view, @@ -1074,6 +1111,15 @@ Target_arm<big_endian>::Scan::local(const General_options&, case elfcpp::R_ARM_NONE: break; + case elfcpp::R_ARM_ABS8: + if (parameters->options().output_is_position_independent()) + { + // FIXME: Create a dynamic relocation for this location. + gold_error(_("%s: gold bug: need dynamic ABS8 reloc"), + object->name().c_str()); + } + break; + case elfcpp::R_ARM_ABS32: // If building a shared library (or a position-independent // executable), we need to create a dynamic relocation for @@ -1187,6 +1233,16 @@ Target_arm<big_endian>::Scan::global(const General_options&, case elfcpp::R_ARM_NONE: break; + case elfcpp::R_ARM_ABS8: + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) + { + // FIXME: Create a dynamic relocation for this location. + gold_error(_("%s: gold bug: need dynamic ABS8 reloc for %s"), + object->name().c_str(), gsym->demangled_name().c_str()); + } + break; + case elfcpp::R_ARM_ABS32: { // Make a dynamic relocation if necessary. @@ -1595,6 +1651,13 @@ Target_arm<big_endian>::Relocate::relocate( case elfcpp::R_ARM_NONE: break; + case elfcpp::R_ARM_ABS8: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::abs8(view, object, psymval, + has_thumb_bit); + break; + case elfcpp::R_ARM_ABS32: if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true, output_section)) @@ -1764,6 +1827,9 @@ Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc( case elfcpp::R_ARM_NONE: return 0; + case elfcpp::R_ARM_ABS8: + return 1; + case elfcpp::R_ARM_ABS32: case elfcpp::R_ARM_REL32: case elfcpp::R_ARM_THM_CALL: |