From e9bbb53879cdf1e21e8d37e11741a44a0f917f60 Mon Sep 17 00:00:00 2001 From: Doug Kwan Date: Sat, 31 Oct 2009 02:59:36 +0000 Subject: [PATCH] 2009-10-30 Doug Kwan * arm.cc (Stub_addend_reader): New struct template definition and partial specializations. (Stub_addend_reader::operator()): New method definition for a partially specialized template. --- gold/ChangeLog | 7 +++ gold/arm.cc | 116 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index a89b6ef58a3..4952be1185c 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,10 @@ +2009-10-30 Doug Kwan + + * arm.cc (Stub_addend_reader): New struct template definition + and partial specializations. + (Stub_addend_reader::operator()): New method definition for a + partially specialized template. + 2009-10-30 Doug Kwan * arm.cc (Arm_relobj::processor_specific_flags): New method diff --git a/gold/arm.cc b/gold/arm.cc index 210ccf73912..420769f962e 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 +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::Reloc& /* reloc */) const + { gold_unreachable(); } +}; + +// Specialized Stub_addend_reader for SHT_REL type relocation sections. + +template +struct Stub_addend_reader +{ + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int, + const unsigned char*, + const typename Reloc_types::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 +struct Stub_addend_reader +{ + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int, + const unsigned char*, + const typename Reloc_types::Reloc& reloc) const; +}; + // Utilities for manipulating integers of up to 32-bits namespace utils @@ -2989,7 +3034,7 @@ Arm_output_section::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::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 +elfcpp::Elf_types<32>::Elf_Swxword +Stub_addend_reader::operator()( + unsigned int r_type, + const unsigned char* view, + const typename Reloc_types::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(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(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(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 -- 2.30.2