diff options
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 230 |
1 files changed, 3 insertions, 227 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index 7d80d85..82782a6 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -51,7 +51,6 @@ #include "gc.h" #include "attributes.h" #include "arm-reloc-property.h" -#include "nacl.h" namespace { @@ -12865,8 +12864,7 @@ Target_arm<big_endian>::apply_cortex_a8_workaround( elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn); } -// Target selector for ARM. Note this is never instantiated directly. -// It's only used in Target_selector_arm_nacl, below. +// Target selector for ARM. template<bool big_endian> class Target_selector_arm : public Target_selector @@ -13002,229 +13000,7 @@ Target_arm<big_endian>::do_define_standard_symbols( } } -// NaCl variant. It uses different PLT contents. - -template<bool big_endian> -class Output_data_plt_arm_nacl; - -template<bool big_endian> -class Target_arm_nacl : public Target_arm<big_endian> -{ - public: - Target_arm_nacl() - : Target_arm<big_endian>(&arm_nacl_info) - { } - - protected: - virtual Output_data_plt_arm<big_endian>* - do_make_data_plt( - Layout* layout, - Arm_output_data_got<big_endian>* got, - Output_data_space* got_plt, - Output_data_space* got_irelative) - { return new Output_data_plt_arm_nacl<big_endian>( - layout, got, got_plt, got_irelative); } - - private: - static const Target::Target_info arm_nacl_info; -}; - -template<bool big_endian> -const Target::Target_info Target_arm_nacl<big_endian>::arm_nacl_info = -{ - 32, // size - big_endian, // is_big_endian - elfcpp::EM_ARM, // machine_code - false, // has_make_symbol - false, // has_resolve - false, // has_code_fill - true, // is_default_stack_executable - false, // can_icf_inline_merge_sections - '\0', // wrap_char - "/lib/ld-nacl-arm.so.1", // dynamic_linker - 0x20000, // default_text_segment_address - 0x10000, // abi_pagesize (overridable by -z max-page-size) - 0x10000, // common_pagesize (overridable by -z common-page-size) - true, // isolate_execinstr - 0x10000000, // rosegment_gap - elfcpp::SHN_UNDEF, // small_common_shndx - elfcpp::SHN_UNDEF, // large_common_shndx - 0, // small_common_section_flags - 0, // large_common_section_flags - ".ARM.attributes", // attributes_section - "aeabi", // attributes_vendor - "_start", // entry_symbol_name - 32, // hash_entry_size - elfcpp::SHT_PROGBITS, // unwind_section_type -}; - -template<bool big_endian> -class Output_data_plt_arm_nacl : public Output_data_plt_arm<big_endian> -{ - public: - Output_data_plt_arm_nacl( - Layout* layout, - Arm_output_data_got<big_endian>* got, - Output_data_space* got_plt, - Output_data_space* got_irelative) - : Output_data_plt_arm<big_endian>(layout, 16, got, got_plt, got_irelative) - { } - - protected: - // Return the offset of the first non-reserved PLT entry. - virtual unsigned int - do_first_plt_entry_offset() const - { return sizeof(first_plt_entry); } - - // Return the size of a PLT entry. - virtual unsigned int - do_get_plt_entry_size() const - { return sizeof(plt_entry); } - - virtual void - do_fill_first_plt_entry(unsigned char* pov, - Arm_address got_address, - Arm_address plt_address); - - virtual void - do_fill_plt_entry(unsigned char* pov, - Arm_address got_address, - Arm_address plt_address, - unsigned int got_offset, - unsigned int plt_offset); - - private: - inline uint32_t arm_movw_immediate(uint32_t value) - { - return (value & 0x00000fff) | ((value & 0x0000f000) << 4); - } - - inline uint32_t arm_movt_immediate(uint32_t value) - { - return ((value & 0x0fff0000) >> 16) | ((value & 0xf0000000) >> 12); - } - - // Template for the first PLT entry. - static const uint32_t first_plt_entry[16]; - - // Template for subsequent PLT entries. - static const uint32_t plt_entry[4]; -}; - -// The first entry in the PLT. -template<bool big_endian> -const uint32_t Output_data_plt_arm_nacl<big_endian>::first_plt_entry[16] = -{ - // First bundle: - 0xe300c000, // movw ip, #:lower16:&GOT[2]-.+8 - 0xe340c000, // movt ip, #:upper16:&GOT[2]-.+8 - 0xe08cc00f, // add ip, ip, pc - 0xe52dc008, // str ip, [sp, #-8]! - // Second bundle: - 0xe3ccc103, // bic ip, ip, #0xc0000000 - 0xe59cc000, // ldr ip, [ip] - 0xe3ccc13f, // bic ip, ip, #0xc000000f - 0xe12fff1c, // bx ip - // Third bundle: - 0xe320f000, // nop - 0xe320f000, // nop - 0xe320f000, // nop - // .Lplt_tail: - 0xe50dc004, // str ip, [sp, #-4] - // Fourth bundle: - 0xe3ccc103, // bic ip, ip, #0xc0000000 - 0xe59cc000, // ldr ip, [ip] - 0xe3ccc13f, // bic ip, ip, #0xc000000f - 0xe12fff1c, // bx ip -}; - -template<bool big_endian> -void -Output_data_plt_arm_nacl<big_endian>::do_fill_first_plt_entry( - unsigned char* pov, - Arm_address got_address, - Arm_address plt_address) -{ - // Write first PLT entry. All but first two words are constants. - const size_t num_first_plt_words = (sizeof(first_plt_entry) - / sizeof(first_plt_entry[0])); - - int32_t got_displacement = got_address + 8 - (plt_address + 16); - - elfcpp::Swap<32, big_endian>::writeval - (pov + 0, first_plt_entry[0] | arm_movw_immediate (got_displacement)); - elfcpp::Swap<32, big_endian>::writeval - (pov + 4, first_plt_entry[1] | arm_movt_immediate (got_displacement)); - - for (size_t i = 2; i < num_first_plt_words; ++i) - elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]); -} - -// Subsequent entries in the PLT. - -template<bool big_endian> -const uint32_t Output_data_plt_arm_nacl<big_endian>::plt_entry[4] = -{ - 0xe300c000, // movw ip, #:lower16:&GOT[n]-.+8 - 0xe340c000, // movt ip, #:upper16:&GOT[n]-.+8 - 0xe08cc00f, // add ip, ip, pc - 0xea000000, // b .Lplt_tail -}; - -template<bool big_endian> -void -Output_data_plt_arm_nacl<big_endian>::do_fill_plt_entry( - unsigned char* pov, - Arm_address got_address, - Arm_address plt_address, - unsigned int got_offset, - unsigned int plt_offset) -{ - // Calculate the displacement between the PLT slot and the - // common tail that's part of the special initial PLT slot. - int32_t tail_displacement = (plt_address + (11 * sizeof(uint32_t)) - - (plt_address + plt_offset - + sizeof(plt_entry) + sizeof(uint32_t))); - gold_assert((tail_displacement & 3) == 0); - tail_displacement >>= 2; - - gold_assert ((tail_displacement & 0xff000000) == 0 - || (-tail_displacement & 0xff000000) == 0); - - // Calculate the displacement between the PLT slot and the entry - // in the GOT. The offset accounts for the value produced by - // adding to pc in the penultimate instruction of the PLT stub. - const int32_t got_displacement = (got_address + got_offset - - (plt_address + sizeof(plt_entry))); - - elfcpp::Swap<32, big_endian>::writeval - (pov + 0, plt_entry[0] | arm_movw_immediate (got_displacement)); - elfcpp::Swap<32, big_endian>::writeval - (pov + 4, plt_entry[1] | arm_movt_immediate (got_displacement)); - elfcpp::Swap<32, big_endian>::writeval - (pov + 8, plt_entry[2]); - elfcpp::Swap<32, big_endian>::writeval - (pov + 12, plt_entry[3] | (tail_displacement & 0x00ffffff)); -} - -// Target selectors. - -template<bool big_endian> -class Target_selector_arm_nacl - : public Target_selector_nacl<Target_selector_arm<big_endian>, - Target_arm_nacl<big_endian> > -{ - public: - Target_selector_arm_nacl() - : Target_selector_nacl<Target_selector_arm<big_endian>, - Target_arm_nacl<big_endian> >( - "arm", - big_endian ? "elf32-bigarm-nacl" : "elf32-littlearm-nacl", - big_endian ? "armelfb_nacl" : "armelf_nacl") - { } -}; - -Target_selector_arm_nacl<false> target_selector_arm; -Target_selector_arm_nacl<true> target_selector_armbe; +Target_selector_arm<false> target_selector_arm; +Target_selector_arm<true> target_selector_armbe; } // End anonymous namespace. |