Commit | Line | Data |
---|---|---|
14bfc3f5 ILT |
1 | // i386.cc -- i386 target support for gold. |
2 | ||
3 | #include "gold.h" | |
4 | #include "elfcpp.h" | |
61ba1cf9 ILT |
5 | #include "i386.h" |
6 | #include "object.h" | |
14bfc3f5 | 7 | #include "target.h" |
61ba1cf9 | 8 | #include "target-reloc.h" |
14bfc3f5 ILT |
9 | #include "target-select.h" |
10 | ||
11 | namespace | |
12 | { | |
13 | ||
14 | using namespace gold; | |
15 | ||
16 | // The i386 target class. | |
17 | ||
18 | class Target_i386 : public Sized_target<32, false> | |
19 | { | |
20 | public: | |
21 | Target_i386() | |
75f65a3e | 22 | : Sized_target<32, false>(&i386_info) |
14bfc3f5 | 23 | { } |
75f65a3e | 24 | |
61ba1cf9 ILT |
25 | void |
26 | relocate_section(const Symbol_table* symtab, | |
27 | Sized_object<32, false>*, | |
28 | unsigned int, | |
29 | const unsigned char*, | |
30 | size_t, | |
31 | unsigned int, | |
32 | const elfcpp::Elf_types<32>::Elf_Addr*, | |
33 | Symbol**, | |
34 | unsigned char*, | |
35 | elfcpp::Elf_types<32>::Elf_Addr, | |
36 | off_t); | |
37 | ||
38 | // The class which implements relocation. | |
39 | struct Relocate | |
40 | { | |
41 | inline void | |
42 | operator()(Sized_object<32, false>*, const elfcpp::Rel<32, false>&, | |
43 | unsigned int r_type, Sized_symbol<32>*, | |
44 | elfcpp::Elf_types<32>::Elf_Addr, | |
45 | unsigned char*, elfcpp::Elf_types<32>::Elf_Addr); | |
46 | ||
47 | }; | |
48 | ||
75f65a3e ILT |
49 | private: |
50 | static const Target::Target_info i386_info; | |
51 | }; | |
52 | ||
53 | const Target::Target_info Target_i386::i386_info = | |
54 | { | |
61ba1cf9 ILT |
55 | 32, // size |
56 | false, // is_big_endian | |
57 | elfcpp::EM_386, // machine_code | |
58 | false, // has_make_symbol | |
59 | false, // has_resolve, | |
60 | 0x08048000, // text_segment_address, | |
61 | 0x1000, // abi_pagesize | |
62 | 0x1000 // common_pagesize | |
14bfc3f5 ILT |
63 | }; |
64 | ||
61ba1cf9 ILT |
65 | // Perform a relocation. |
66 | ||
67 | inline void | |
68 | Target_i386::Relocate::operator()(Sized_object<32, false>* object, | |
69 | const elfcpp::Rel<32, false>&, | |
70 | unsigned int r_type, | |
71 | Sized_symbol<32>*, | |
72 | elfcpp::Elf_types<32>::Elf_Addr value, | |
73 | unsigned char* view, | |
74 | elfcpp::Elf_types<32>::Elf_Addr address) | |
75 | { | |
76 | switch (r_type) | |
77 | { | |
78 | case elfcpp::R_386_NONE: | |
79 | break; | |
80 | ||
81 | case elfcpp::R_386_32: | |
82 | { | |
83 | elfcpp::Elf_Word* wv = reinterpret_cast<elfcpp::Elf_Word*>(view); | |
84 | unsigned int x = elfcpp::read_elf_word<false>(wv); | |
85 | elfcpp::write_elf_word<false>(wv, x + value); | |
86 | } | |
87 | break; | |
88 | ||
89 | case elfcpp::R_386_PC32: | |
90 | { | |
91 | elfcpp::Elf_Word* wv = reinterpret_cast<elfcpp::Elf_Word*>(view); | |
92 | unsigned int x = elfcpp::read_elf_word<false>(wv); | |
93 | elfcpp::write_elf_word<false>(wv, x + value - address); | |
94 | } | |
95 | break; | |
96 | ||
97 | default: | |
98 | fprintf(stderr, _("%s: %s: unsupported reloc %u\n"), | |
99 | program_name, object->name().c_str(), r_type); | |
100 | // gold_exit(false); | |
101 | } | |
102 | } | |
103 | ||
104 | // Relocate section data. | |
105 | ||
106 | void | |
107 | Target_i386::relocate_section(const Symbol_table* symtab, | |
108 | Sized_object<32, false>* object, | |
109 | unsigned int sh_type, | |
110 | const unsigned char* prelocs, | |
111 | size_t reloc_count, | |
112 | unsigned int local_count, | |
113 | const elfcpp::Elf_types<32>::Elf_Addr* values, | |
114 | Symbol** global_syms, | |
115 | unsigned char* view, | |
116 | elfcpp::Elf_types<32>::Elf_Addr address, | |
117 | off_t view_size) | |
118 | { | |
119 | if (sh_type == elfcpp::SHT_RELA) | |
120 | { | |
121 | fprintf(stderr, _("%s: %s: unsupported RELA reloc section\n"), | |
122 | program_name, object->name().c_str()); | |
123 | gold_exit(false); | |
124 | } | |
125 | ||
126 | gold::relocate_section<32, false, elfcpp::SHT_REL, Target_i386::Relocate>( | |
127 | symtab, | |
128 | object, | |
129 | prelocs, | |
130 | reloc_count, | |
131 | local_count, | |
132 | values, | |
133 | global_syms, | |
134 | view, | |
135 | address, | |
136 | view_size); | |
137 | } | |
138 | ||
139 | // The i386 target. | |
140 | ||
141 | Target_i386 target_i386; | |
142 | ||
14bfc3f5 ILT |
143 | // The selector for i386 object files. |
144 | ||
145 | class Target_selector_i386 : public Target_selector | |
146 | { | |
147 | public: | |
148 | Target_selector_i386() | |
149 | : Target_selector(elfcpp::EM_386, 32, false) | |
150 | { } | |
151 | ||
152 | Target* | |
153 | recognize(int machine, int osabi, int abiversion) const; | |
154 | }; | |
155 | ||
156 | // Recognize an i386 object file when we already know that the machine | |
157 | // number is EM_386. | |
158 | ||
159 | Target* | |
160 | Target_selector_i386::recognize(int, int, int) const | |
161 | { | |
61ba1cf9 | 162 | return &target_i386; |
14bfc3f5 ILT |
163 | } |
164 | ||
165 | Target_selector_i386 target_selector_i386; | |
166 | ||
167 | } // End anonymous namespace. |