diff options
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r-- | gold/x86_64.cc | 379 |
1 files changed, 3 insertions, 376 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 5c6157d..f23330e 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -39,7 +39,6 @@ #include "target-select.h" #include "tls.h" #include "freebsd.h" -#include "nacl.h" #include "gc.h" #include "icf.h" @@ -5792,8 +5791,7 @@ Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx, *to = "__morestack_non_split"; } -// The selector for x86_64 object files. Note this is never instantiated -// directly. It's only used in Target_selector_x86_64_nacl, below. +// The selector for x86_64 object files. template<int size> class Target_selector_x86_64 : public Target_selector_freebsd @@ -5815,378 +5813,7 @@ public: }; -// NaCl variant. It uses different PLT contents. - -template<int size> -class Output_data_plt_x86_64_nacl : public Output_data_plt_x86_64<size> -{ - public: - Output_data_plt_x86_64_nacl(Layout* layout, - Output_data_got<64, false>* got, - Output_data_got_plt_x86_64* got_plt, - Output_data_space* got_irelative) - : Output_data_plt_x86_64<size>(layout, plt_entry_size, - got, got_plt, got_irelative) - { } - - Output_data_plt_x86_64_nacl(Layout* layout, - Output_data_got<64, false>* got, - Output_data_got_plt_x86_64* got_plt, - Output_data_space* got_irelative, - unsigned int plt_count) - : Output_data_plt_x86_64<size>(layout, plt_entry_size, - got, got_plt, got_irelative, - plt_count) - { } - - protected: - virtual unsigned int - do_get_plt_entry_size() const - { return plt_entry_size; } - - virtual void - do_add_eh_frame(Layout* layout) - { - layout->add_eh_frame_for_plt(this, - this->plt_eh_frame_cie, - this->plt_eh_frame_cie_size, - plt_eh_frame_fde, - plt_eh_frame_fde_size); - } - - virtual void - do_fill_first_plt_entry(unsigned char* pov, - typename elfcpp::Elf_types<size>::Elf_Addr got_addr, - typename elfcpp::Elf_types<size>::Elf_Addr plt_addr); - - virtual unsigned int - do_fill_plt_entry(unsigned char* pov, - typename elfcpp::Elf_types<size>::Elf_Addr got_address, - typename elfcpp::Elf_types<size>::Elf_Addr plt_address, - unsigned int got_offset, - unsigned int plt_offset, - unsigned int plt_index); - - virtual void - do_fill_tlsdesc_entry(unsigned char* pov, - typename elfcpp::Elf_types<size>::Elf_Addr got_address, - typename elfcpp::Elf_types<size>::Elf_Addr plt_address, - typename elfcpp::Elf_types<size>::Elf_Addr got_base, - unsigned int tlsdesc_got_offset, - unsigned int plt_offset); - - private: - // The size of an entry in the PLT. - static const int plt_entry_size = 64; - - // The first entry in the PLT. - static const unsigned char first_plt_entry[plt_entry_size]; - - // Other entries in the PLT for an executable. - static const unsigned char plt_entry[plt_entry_size]; - - // The reserved TLSDESC entry in the PLT for an executable. - static const unsigned char tlsdesc_plt_entry[plt_entry_size]; - - // The .eh_frame unwind information for the PLT. - static const int plt_eh_frame_fde_size = 32; - static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size]; -}; - -template<int size> -class Target_x86_64_nacl : public Target_x86_64<size> -{ - public: - Target_x86_64_nacl() - : Target_x86_64<size>(&x86_64_nacl_info) - { } - - virtual Output_data_plt_x86_64<size>* - do_make_data_plt(Layout* layout, - Output_data_got<64, false>* got, - Output_data_got_plt_x86_64* got_plt, - Output_data_space* got_irelative) - { - return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt, - got_irelative); - } - - virtual Output_data_plt_x86_64<size>* - do_make_data_plt(Layout* layout, - Output_data_got<64, false>* got, - Output_data_got_plt_x86_64* got_plt, - Output_data_space* got_irelative, - unsigned int plt_count) - { - return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt, - got_irelative, - plt_count); - } - - virtual std::string - do_code_fill(section_size_type length) const; - - private: - static const Target::Target_info x86_64_nacl_info; -}; - -template<> -const Target::Target_info Target_x86_64_nacl<64>::x86_64_nacl_info = -{ - 64, // size - false, // is_big_endian - elfcpp::EM_X86_64, // machine_code - false, // has_make_symbol - false, // has_resolve - true, // has_code_fill - true, // is_default_stack_executable - true, // can_icf_inline_merge_sections - '\0', // wrap_char - "/lib64/ld-nacl-x86-64.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_X86_64_LCOMMON, // large_common_shndx - 0, // small_common_section_flags - elfcpp::SHF_X86_64_LARGE, // large_common_section_flags - NULL, // attributes_section - NULL, // attributes_vendor - "_start", // entry_symbol_name - 32, // hash_entry_size - elfcpp::SHT_X86_64_UNWIND, // unwind_section_type -}; - -template<> -const Target::Target_info Target_x86_64_nacl<32>::x86_64_nacl_info = -{ - 32, // size - false, // is_big_endian - elfcpp::EM_X86_64, // machine_code - false, // has_make_symbol - false, // has_resolve - true, // has_code_fill - true, // is_default_stack_executable - true, // can_icf_inline_merge_sections - '\0', // wrap_char - "/lib/ld-nacl-x86-64.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_X86_64_LCOMMON, // large_common_shndx - 0, // small_common_section_flags - elfcpp::SHF_X86_64_LARGE, // large_common_section_flags - NULL, // attributes_section - NULL, // attributes_vendor - "_start", // entry_symbol_name - 32, // hash_entry_size - elfcpp::SHT_X86_64_UNWIND, // unwind_section_type -}; - -#define NACLMASK 0xe0 // 32-byte alignment mask. - -// The first entry in the PLT. - -template<int size> -const unsigned char -Output_data_plt_x86_64_nacl<size>::first_plt_entry[plt_entry_size] = -{ - 0xff, 0x35, // pushq contents of memory address - 0, 0, 0, 0, // replaced with address of .got + 8 - 0x4c, 0x8b, 0x1d, // mov GOT+16(%rip), %r11 - 0, 0, 0, 0, // replaced with address of .got + 16 - 0x41, 0x83, 0xe3, NACLMASK, // and $-32, %r11d - 0x4d, 0x01, 0xfb, // add %r15, %r11 - 0x41, 0xff, 0xe3, // jmpq *%r11 - - // 9-byte nop sequence to pad out to the next 32-byte boundary. - 0x66, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw 0x0(%rax,%rax,1) - - // 32 bytes of nop to pad out to the standard size - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) - 0x66, // excess data32 prefix - 0x90 // nop -}; - -template<int size> -void -Output_data_plt_x86_64_nacl<size>::do_fill_first_plt_entry( - unsigned char* pov, - typename elfcpp::Elf_types<size>::Elf_Addr got_address, - typename elfcpp::Elf_types<size>::Elf_Addr plt_address) -{ - memcpy(pov, first_plt_entry, plt_entry_size); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, - (got_address + 8 - - (plt_address + 2 + 4))); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 9, - (got_address + 16 - - (plt_address + 9 + 4))); -} - -// Subsequent entries in the PLT. - -template<int size> -const unsigned char -Output_data_plt_x86_64_nacl<size>::plt_entry[plt_entry_size] = -{ - 0x4c, 0x8b, 0x1d, // mov name@GOTPCREL(%rip),%r11 - 0, 0, 0, 0, // replaced with address of symbol in .got - 0x41, 0x83, 0xe3, NACLMASK, // and $-32, %r11d - 0x4d, 0x01, 0xfb, // add %r15, %r11 - 0x41, 0xff, 0xe3, // jmpq *%r11 - - // 15-byte nop sequence to pad out to the next 32-byte boundary. - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) - - // Lazy GOT entries point here (32-byte aligned). - 0x68, // pushq immediate - 0, 0, 0, 0, // replaced with index into relocation table - 0xe9, // jmp relative - 0, 0, 0, 0, // replaced with offset to start of .plt0 - - // 22 bytes of nop to pad out to the standard size. - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) - 0x0f, 0x1f, 0x80, 0, 0, 0, 0, // nopl 0x0(%rax) -}; - -template<int size> -unsigned int -Output_data_plt_x86_64_nacl<size>::do_fill_plt_entry( - unsigned char* pov, - typename elfcpp::Elf_types<size>::Elf_Addr got_address, - typename elfcpp::Elf_types<size>::Elf_Addr plt_address, - unsigned int got_offset, - unsigned int plt_offset, - unsigned int plt_index) -{ - memcpy(pov, plt_entry, plt_entry_size); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 3, - (got_address + got_offset - - (plt_address + plt_offset - + 3 + 4))); - - elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_index); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 38, - - (plt_offset + 38 + 4)); - - return 32; -} - -// The reserved TLSDESC entry in the PLT. - -template<int size> -const unsigned char -Output_data_plt_x86_64_nacl<size>::tlsdesc_plt_entry[plt_entry_size] = -{ - 0xff, 0x35, // pushq x(%rip) - 0, 0, 0, 0, // replaced with address of linkmap GOT entry (at PLTGOT + 8) - 0x4c, 0x8b, 0x1d, // mov y(%rip),%r11 - 0, 0, 0, 0, // replaced with offset of reserved TLSDESC_GOT entry - 0x41, 0x83, 0xe3, NACLMASK, // and $-32, %r11d - 0x4d, 0x01, 0xfb, // add %r15, %r11 - 0x41, 0xff, 0xe3, // jmpq *%r11 - - // 41 bytes of nop to pad out to the standard size. - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) - 0x66, 0x66, // excess data32 prefixes - 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1) -}; - -template<int size> -void -Output_data_plt_x86_64_nacl<size>::do_fill_tlsdesc_entry( - unsigned char* pov, - typename elfcpp::Elf_types<size>::Elf_Addr got_address, - typename elfcpp::Elf_types<size>::Elf_Addr plt_address, - typename elfcpp::Elf_types<size>::Elf_Addr got_base, - unsigned int tlsdesc_got_offset, - unsigned int plt_offset) -{ - memcpy(pov, tlsdesc_plt_entry, plt_entry_size); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, - (got_address + 8 - - (plt_address + plt_offset - + 2 + 4))); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 9, - (got_base - + tlsdesc_got_offset - - (plt_address + plt_offset - + 9 + 4))); -} - -// The .eh_frame unwind information for the PLT. - -template<int size> -const unsigned char -Output_data_plt_x86_64_nacl<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] = -{ - 0, 0, 0, 0, // Replaced with offset to .plt. - 0, 0, 0, 0, // Replaced with size of .plt. - 0, // Augmentation size. - elfcpp::DW_CFA_def_cfa_offset, 16, // DW_CFA_def_cfa_offset: 16. - elfcpp::DW_CFA_advance_loc + 6, // Advance 6 to __PLT__ + 6. - elfcpp::DW_CFA_def_cfa_offset, 24, // DW_CFA_def_cfa_offset: 24. - elfcpp::DW_CFA_advance_loc + 58, // Advance 58 to __PLT__ + 64. - elfcpp::DW_CFA_def_cfa_expression, // DW_CFA_def_cfa_expression. - 13, // Block length. - elfcpp::DW_OP_breg7, 8, // Push %rsp + 8. - elfcpp::DW_OP_breg16, 0, // Push %rip. - elfcpp::DW_OP_const1u, 63, // Push 0x3f. - elfcpp::DW_OP_and, // & (%rip & 0x3f). - elfcpp::DW_OP_const1u, 37, // Push 0x25. - elfcpp::DW_OP_ge, // >= ((%rip & 0x3f) >= 0x25) - elfcpp::DW_OP_lit3, // Push 3. - elfcpp::DW_OP_shl, // << (((%rip & 0x3f) >= 0x25) << 3) - elfcpp::DW_OP_plus, // + ((((%rip&0x3f)>=0x25)<<3)+%rsp+8 - elfcpp::DW_CFA_nop, // Align to 32 bytes. - elfcpp::DW_CFA_nop -}; - -// Return a string used to fill a code section with nops. -// For NaCl, long NOPs are only valid if they do not cross -// bundle alignment boundaries, so keep it simple with one-byte NOPs. -template<int size> -std::string -Target_x86_64_nacl<size>::do_code_fill(section_size_type length) const -{ - return std::string(length, static_cast<char>(0x90)); -} - -// The selector for x86_64-nacl object files. - -template<int size> -class Target_selector_x86_64_nacl - : public Target_selector_nacl<Target_selector_x86_64<size>, - Target_x86_64_nacl<size> > -{ - public: - Target_selector_x86_64_nacl() - : Target_selector_nacl<Target_selector_x86_64<size>, - Target_x86_64_nacl<size> >("x86-64", - size == 64 - ? "elf64-x86-64-nacl" - : "elf32-x86-64-nacl", - size == 64 - ? "elf_x86_64_nacl" - : "elf32_x86_64_nacl") - { } -}; - -Target_selector_x86_64_nacl<64> target_selector_x86_64; -Target_selector_x86_64_nacl<32> target_selector_x32; +Target_selector_x86_64<64> target_selector_x86_64; +Target_selector_x86_64<32> target_selector_x32; } // End anonymous namespace. |