diff options
Diffstat (limited to 'gold/i386.cc')
-rw-r--r-- | gold/i386.cc | 342 |
1 files changed, 2 insertions, 340 deletions
diff --git a/gold/i386.cc b/gold/i386.cc index d7d8f87..f9ae4ad 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -39,7 +39,6 @@ #include "target-select.h" #include "tls.h" #include "freebsd.h" -#include "nacl.h" #include "gc.h" namespace @@ -4046,8 +4045,7 @@ Target_i386::do_calls_non_split(Relobj* object, unsigned int shndx, *to = "__morestack_non_split"; } -// The selector for i386 object files. Note this is never instantiated -// directly. It's only used in Target_selector_i386_nacl, below. +// The selector for i386 object files. class Target_selector_i386 : public Target_selector_freebsd { @@ -4063,343 +4061,7 @@ public: { return new Target_i386(); } }; -// NaCl variant. It uses different PLT contents. - -class Output_data_plt_i386_nacl : public Output_data_plt_i386 -{ - public: - Output_data_plt_i386_nacl(Layout* layout, - Output_data_got_plt_i386* got_plt, - Output_data_space* got_irelative) - : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative) - { } - - 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, plt_eh_frame_cie, plt_eh_frame_cie_size, - plt_eh_frame_fde, plt_eh_frame_fde_size); - } - - // The size of an entry in the PLT. - static const int plt_entry_size = 64; - - // 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]; -}; - -class Output_data_plt_i386_nacl_exec : public Output_data_plt_i386_nacl -{ -public: - Output_data_plt_i386_nacl_exec(Layout* layout, - Output_data_got_plt_i386* got_plt, - Output_data_space* got_irelative) - : Output_data_plt_i386_nacl(layout, got_plt, got_irelative) - { } - - protected: - virtual void - do_fill_first_plt_entry(unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr got_address); - - virtual unsigned int - do_fill_plt_entry(unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr got_address, - unsigned int got_offset, - unsigned int plt_offset, - unsigned int plt_rel_offset); - - private: - // The first entry in the PLT for an executable. - 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]; -}; - -class Output_data_plt_i386_nacl_dyn : public Output_data_plt_i386_nacl -{ - public: - Output_data_plt_i386_nacl_dyn(Layout* layout, - Output_data_got_plt_i386* got_plt, - Output_data_space* got_irelative) - : Output_data_plt_i386_nacl(layout, got_plt, got_irelative) - { } - - protected: - virtual void - do_fill_first_plt_entry(unsigned char* pov, elfcpp::Elf_types<32>::Elf_Addr); - - virtual unsigned int - do_fill_plt_entry(unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr, - unsigned int got_offset, - unsigned int plt_offset, - unsigned int plt_rel_offset); - - private: - // The first entry in the PLT for a shared object. - static const unsigned char first_plt_entry[plt_entry_size]; - - // Other entries in the PLT for a shared object. - static const unsigned char plt_entry[plt_entry_size]; -}; - -class Target_i386_nacl : public Target_i386 -{ - public: - Target_i386_nacl() - : Target_i386(&i386_nacl_info) - { } - - protected: - virtual Output_data_plt_i386* - do_make_data_plt(Layout* layout, - Output_data_got_plt_i386* got_plt, - Output_data_space* got_irelative, - bool dyn) - { - if (dyn) - return new Output_data_plt_i386_nacl_dyn(layout, got_plt, got_irelative); - else - return new Output_data_plt_i386_nacl_exec(layout, got_plt, got_irelative); - } - - virtual std::string - do_code_fill(section_size_type length) const; - - private: - static const Target::Target_info i386_nacl_info; -}; - -const Target::Target_info Target_i386_nacl::i386_nacl_info = -{ - 32, // size - false, // is_big_endian - elfcpp::EM_386, // 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-32.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 - NULL, // attributes_section - NULL, // attributes_vendor - "_start", // entry_symbol_name - 32, // hash_entry_size - elfcpp::SHT_PROGBITS, // unwind_section_type -}; - -#define NACLMASK 0xe0 // 32-byte alignment mask - -const unsigned char -Output_data_plt_i386_nacl_exec::first_plt_entry[plt_entry_size] = -{ - 0xff, 0x35, // pushl contents of memory address - 0, 0, 0, 0, // replaced with address of .got + 4 - 0x8b, 0x0d, // movl contents of address, %ecx - 0, 0, 0, 0, // replaced with address of .got + 8 - 0x83, 0xe1, NACLMASK, // andl $NACLMASK, %ecx - 0xff, 0xe1, // jmp *%ecx - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90 -}; - -void -Output_data_plt_i386_nacl_exec::do_fill_first_plt_entry( - unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr got_address) -{ - memcpy(pov, first_plt_entry, plt_entry_size); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4); - elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8); -} - -// The first entry in the PLT for a shared object. - -const unsigned char -Output_data_plt_i386_nacl_dyn::first_plt_entry[plt_entry_size] = -{ - 0xff, 0xb3, 4, 0, 0, 0, // pushl 4(%ebx) - 0x8b, 0x4b, 0x08, // mov 0x8(%ebx), %ecx - 0x83, 0xe1, NACLMASK, // andl $NACLMASK, %ecx - 0xff, 0xe1, // jmp *%ecx - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90, // nops - 0x90, 0x90, 0x90, 0x90, 0x90 // nops -}; - -void -Output_data_plt_i386_nacl_dyn::do_fill_first_plt_entry( - unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr) -{ - memcpy(pov, first_plt_entry, plt_entry_size); -} - -// Subsequent entries in the PLT for an executable. - -const unsigned char -Output_data_plt_i386_nacl_exec::plt_entry[plt_entry_size] = -{ - 0x8b, 0x0d, // movl contents of address, %ecx */ - 0, 0, 0, 0, // replaced with address of symbol in .got - 0x83, 0xe1, NACLMASK, // andl $NACLMASK, %ecx - 0xff, 0xe1, // jmp *%ecx - - // Pad to the next 32-byte boundary with nop instructions. - 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - - // Lazy GOT entries point here (32-byte aligned). - 0x68, // pushl immediate - 0, 0, 0, 0, // replaced with offset into relocation table - 0xe9, // jmp relative - 0, 0, 0, 0, // replaced with offset to start of .plt - - // Pad to the next 32-byte boundary with nop instructions. - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90 -}; - -unsigned int -Output_data_plt_i386_nacl_exec::do_fill_plt_entry( - unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr got_address, - unsigned int got_offset, - unsigned int plt_offset, - unsigned int plt_rel_offset) -{ - memcpy(pov, plt_entry, plt_entry_size); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, - got_address + got_offset); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_rel_offset); - elfcpp::Swap<32, false>::writeval(pov + 38, - (plt_offset + 38 + 4)); - return 32; -} - -// Subsequent entries in the PLT for a shared object. - -const unsigned char -Output_data_plt_i386_nacl_dyn::plt_entry[plt_entry_size] = -{ - 0x8b, 0x8b, // movl offset(%ebx), %ecx - 0, 0, 0, 0, // replaced with offset of symbol in .got - 0x83, 0xe1, 0xe0, // andl $NACLMASK, %ecx - 0xff, 0xe1, // jmp *%ecx - - // Pad to the next 32-byte boundary with nop instructions. - 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - - // Lazy GOT entries point here (32-byte aligned). - 0x68, // pushl immediate - 0, 0, 0, 0, // replaced with offset into relocation table. - 0xe9, // jmp relative - 0, 0, 0, 0, // replaced with offset to start of .plt. - - // Pad to the next 32-byte boundary with nop instructions. - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90 -}; - -unsigned int -Output_data_plt_i386_nacl_dyn::do_fill_plt_entry( - unsigned char* pov, - elfcpp::Elf_types<32>::Elf_Addr, - unsigned int got_offset, - unsigned int plt_offset, - unsigned int plt_rel_offset) -{ - memcpy(pov, plt_entry, plt_entry_size); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset); - elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_rel_offset); - elfcpp::Swap<32, false>::writeval(pov + 38, - (plt_offset + 38 + 4)); - return 32; -} - -const unsigned char -Output_data_plt_i386_nacl::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, 8, // DW_CFA_def_cfa_offset: 8. - elfcpp::DW_CFA_advance_loc + 6, // Advance 6 to __PLT__ + 6. - elfcpp::DW_CFA_def_cfa_offset, 12, // DW_CFA_def_cfa_offset: 12. - 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_breg4, 4, // Push %esp + 4. - elfcpp::DW_OP_breg8, 0, // Push %eip. - elfcpp::DW_OP_const1u, 63, // Push 0x3f. - elfcpp::DW_OP_and, // & (%eip & 0x3f). - elfcpp::DW_OP_const1u, 37, // Push 0x25. - elfcpp::DW_OP_ge, // >= ((%eip & 0x3f) >= 0x25) - elfcpp::DW_OP_lit2, // Push 2. - elfcpp::DW_OP_shl, // << (((%eip & 0x3f) >= 0x25) << 2) - elfcpp::DW_OP_plus, // + ((((%eip&0x3f)>=0x25)<<2)+%esp+4 - 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. -std::string -Target_i386_nacl::do_code_fill(section_size_type length) const -{ - return std::string(length, static_cast<char>(0x90)); -} - -// The selector for i386-nacl object files. - -class Target_selector_i386_nacl - : public Target_selector_nacl<Target_selector_i386, Target_i386_nacl> -{ - public: - Target_selector_i386_nacl() - : Target_selector_nacl<Target_selector_i386, - Target_i386_nacl>("x86-32", - "elf32-i386-nacl", - "elf_i386_nacl") - { } -}; - -Target_selector_i386_nacl target_selector_i386; +Target_selector_i386 target_selector_i386; // IAMCU variant. It uses EM_IAMCU, not EM_386. |