diff options
author | Doug Kwan <dougkwan@google.com> | 2009-10-31 02:59:36 +0000 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2009-10-31 02:59:36 +0000 |
commit | e9bbb53879cdf1e21e8d37e11741a44a0f917f60 (patch) | |
tree | f61a7a9b3360dc0cef8aa62a63ccf1daef17164b /gold/arm.cc | |
parent | 0081696c26d7f38d499c684773099c1c7ccd24a2 (diff) | |
download | gdb-e9bbb53879cdf1e21e8d37e11741a44a0f917f60.zip gdb-e9bbb53879cdf1e21e8d37e11741a44a0f917f60.tar.gz gdb-e9bbb53879cdf1e21e8d37e11741a44a0f917f60.tar.bz2 |
2009-10-30 Doug Kwan <dougkwan@google.com>
* arm.cc (Stub_addend_reader): New struct template definition
and partial specializations.
(Stub_addend_reader::operator()): New method definition for a
partially specialized template.
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index 210ccf7..420769f 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -1029,6 +1029,51 @@ class Arm_dynobj : public Sized_dynobj<32, big_endian> elfcpp::Elf_Word processor_specific_flags_; }; +// Functor to read reloc addends during stub generation. + +template<int sh_type, bool big_endian> +struct Stub_addend_reader +{ + // Return the addend for a relocation of a particular type. Depending + // on whether this is a REL or RELA relocation, read the addend from a + // view or from a Reloc object. + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int /* r_type */, + const unsigned char* /* view */, + const typename Reloc_types<sh_type, + 32, big_endian>::Reloc& /* reloc */) const + { gold_unreachable(); } +}; + +// Specialized Stub_addend_reader for SHT_REL type relocation sections. + +template<bool big_endian> +struct Stub_addend_reader<elfcpp::SHT_REL, big_endian> +{ + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int, + const unsigned char*, + const typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc&) const; +}; + +// Specialized Stub_addend_reader for RELA type relocation sections. +// We currently do not handle RELA type relocation sections but it is trivial +// to implement the addend reader. This is provided for completeness and to +// make it easier to add support for RELA relocation sections in the future. + +template<bool big_endian> +struct Stub_addend_reader<elfcpp::SHT_RELA, big_endian> +{ + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int, + const unsigned char*, + const typename Reloc_types<elfcpp::SHT_RELA, 32, + big_endian>::Reloc& reloc) const; +}; + // Utilities for manipulating integers of up to 32-bits namespace utils @@ -2989,7 +3034,7 @@ Arm_output_section<big_endian>::group_sections( section_begin_offset + p->data_size(); // Check to see if we should group the previously seens sections. - switch(state) + switch (state) { case NO_GROUP: break; @@ -3367,6 +3412,75 @@ Arm_dynobj<big_endian>::do_read_symbols(Read_symbols_data* sd) this->processor_specific_flags_ = ehdr.get_e_flags(); } +// Stub_addend_reader methods. + +// Read the addend of a REL relocation of type R_TYPE at VIEW. + +template<bool big_endian> +elfcpp::Elf_types<32>::Elf_Swxword +Stub_addend_reader<elfcpp::SHT_REL, big_endian>::operator()( + unsigned int r_type, + const unsigned char* view, + const typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc&) const +{ + switch (r_type) + { + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_PLT32: + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + return utils::sign_extend<26>(val << 2); + } + + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_THM_XPC22: + { + // Fetch the addend. We use the Thumb-2 encoding (backwards + // compatible with Thumb-1) involving the J1 and J2 bits. + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view); + Valtype upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + Valtype lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + + uint32_t s = (upper_insn & (1 << 10)) >> 10; + uint32_t upper = upper_insn & 0x3ff; + uint32_t lower = lower_insn & 0x7ff; + uint32_t j1 = (lower_insn & (1 << 13)) >> 13; + uint32_t j2 = (lower_insn & (1 << 11)) >> 11; + uint32_t i1 = j1 ^ s ? 0 : 1; + uint32_t i2 = j2 ^ s ? 0 : 1; + + return utils::sign_extend<25>((s << 24) | (i1 << 23) | (i2 << 22) + | (upper << 12) | (lower << 1)); + } + + case elfcpp::R_ARM_THM_JUMP19: + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view); + Valtype upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + Valtype lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + + // Reconstruct the top three bits and squish the two 11 bit pieces + // together. + uint32_t S = (upper_insn & 0x0400) >> 10; + uint32_t J1 = (lower_insn & 0x2000) >> 13; + uint32_t J2 = (lower_insn & 0x0800) >> 11; + uint32_t upper = + (S << 8) | (J2 << 7) | (J1 << 6) | (upper_insn & 0x003f); + uint32_t lower = (lower_insn & 0x07ff); + return utils::sign_extend<23>((upper << 12) | (lower << 1)); + } + + default: + gold_unreachable(); + } +} + // A class to handle the PLT data. template<bool big_endian> |