diff options
Diffstat (limited to 'gold/i386.cc')
-rw-r--r-- | gold/i386.cc | 122 |
1 files changed, 114 insertions, 8 deletions
diff --git a/gold/i386.cc b/gold/i386.cc index 21dd57a..32ee881 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -2,7 +2,10 @@ #include "gold.h" #include "elfcpp.h" +#include "i386.h" +#include "object.h" #include "target.h" +#include "target-reloc.h" #include "target-select.h" namespace @@ -19,21 +22,124 @@ class Target_i386 : public Sized_target<32, false> : Sized_target<32, false>(&i386_info) { } + void + relocate_section(const Symbol_table* symtab, + Sized_object<32, false>*, + unsigned int, + const unsigned char*, + size_t, + unsigned int, + const elfcpp::Elf_types<32>::Elf_Addr*, + Symbol**, + unsigned char*, + elfcpp::Elf_types<32>::Elf_Addr, + off_t); + + // The class which implements relocation. + struct Relocate + { + inline void + operator()(Sized_object<32, false>*, const elfcpp::Rel<32, false>&, + unsigned int r_type, Sized_symbol<32>*, + elfcpp::Elf_types<32>::Elf_Addr, + unsigned char*, elfcpp::Elf_types<32>::Elf_Addr); + + }; + private: static const Target::Target_info i386_info; }; const Target::Target_info Target_i386::i386_info = { - 32, // size - false, // is_big_endian - false, // has_make_symbol - false, // has_resolve, - 0x08048000, // text_segment_address, - 0x1000, // abi_pagesize - 0x1000 // common_pagesize + 32, // size + false, // is_big_endian + elfcpp::EM_386, // machine_code + false, // has_make_symbol + false, // has_resolve, + 0x08048000, // text_segment_address, + 0x1000, // abi_pagesize + 0x1000 // common_pagesize }; +// Perform a relocation. + +inline void +Target_i386::Relocate::operator()(Sized_object<32, false>* object, + const elfcpp::Rel<32, false>&, + unsigned int r_type, + Sized_symbol<32>*, + elfcpp::Elf_types<32>::Elf_Addr value, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr address) +{ + switch (r_type) + { + case elfcpp::R_386_NONE: + break; + + case elfcpp::R_386_32: + { + elfcpp::Elf_Word* wv = reinterpret_cast<elfcpp::Elf_Word*>(view); + unsigned int x = elfcpp::read_elf_word<false>(wv); + elfcpp::write_elf_word<false>(wv, x + value); + } + break; + + case elfcpp::R_386_PC32: + { + elfcpp::Elf_Word* wv = reinterpret_cast<elfcpp::Elf_Word*>(view); + unsigned int x = elfcpp::read_elf_word<false>(wv); + elfcpp::write_elf_word<false>(wv, x + value - address); + } + break; + + default: + fprintf(stderr, _("%s: %s: unsupported reloc %u\n"), + program_name, object->name().c_str(), r_type); + // gold_exit(false); + } +} + +// Relocate section data. + +void +Target_i386::relocate_section(const Symbol_table* symtab, + Sized_object<32, false>* object, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + unsigned int local_count, + const elfcpp::Elf_types<32>::Elf_Addr* values, + Symbol** global_syms, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr address, + off_t view_size) +{ + if (sh_type == elfcpp::SHT_RELA) + { + fprintf(stderr, _("%s: %s: unsupported RELA reloc section\n"), + program_name, object->name().c_str()); + gold_exit(false); + } + + gold::relocate_section<32, false, elfcpp::SHT_REL, Target_i386::Relocate>( + symtab, + object, + prelocs, + reloc_count, + local_count, + values, + global_syms, + view, + address, + view_size); +} + +// The i386 target. + +Target_i386 target_i386; + // The selector for i386 object files. class Target_selector_i386 : public Target_selector @@ -53,7 +159,7 @@ public: Target* Target_selector_i386::recognize(int, int, int) const { - return new Target_i386(); + return &target_i386; } Target_selector_i386 target_selector_i386; |