2006-11-29 Paul Brook <paul@codesourcery.com>
[deliverable/binutils-gdb.git] / gold / i386.cc
CommitLineData
14bfc3f5
ILT
1// i386.cc -- i386 target support for gold.
2
3#include "gold.h"
ead1e424
ILT
4
5#include <cstring>
6
14bfc3f5 7#include "elfcpp.h"
92e059d8 8#include "reloc.h"
61ba1cf9
ILT
9#include "i386.h"
10#include "object.h"
ead1e424 11#include "symtab.h"
92e059d8
ILT
12#include "layout.h"
13#include "output.h"
14bfc3f5 14#include "target.h"
61ba1cf9 15#include "target-reloc.h"
14bfc3f5
ILT
16#include "target-select.h"
17
18namespace
19{
20
21using namespace gold;
22
23// The i386 target class.
24
25class Target_i386 : public Sized_target<32, false>
26{
27 public:
28 Target_i386()
ead1e424
ILT
29 : Sized_target<32, false>(&i386_info),
30 got_(NULL)
14bfc3f5 31 { }
75f65a3e 32
92e059d8 33 // Scan the relocations to look for symbol adjustments.
61ba1cf9 34 void
92e059d8
ILT
35 scan_relocs(const General_options& options,
36 Symbol_table* symtab,
ead1e424 37 Layout* layout,
f6ce93d6 38 Sized_relobj<32, false>* object,
92e059d8
ILT
39 unsigned int sh_type,
40 const unsigned char* prelocs,
41 size_t reloc_count,
42 size_t local_symbol_count,
43 const unsigned char* plocal_symbols,
44 Symbol** global_symbols);
61ba1cf9 45
92e059d8
ILT
46 // Relocate a section.
47 void
48 relocate_section(const Relocate_info<32, false>*,
49 unsigned int sh_type,
50 const unsigned char* prelocs,
51 size_t reloc_count,
52 unsigned char* view,
53 elfcpp::Elf_types<32>::Elf_Addr view_address,
54 off_t view_size);
55
56 private:
57 // The class which scans relocations.
58 struct Scan
61ba1cf9
ILT
59 {
60 inline void
ead1e424
ILT
61 local(const General_options& options, Symbol_table* symtab,
62 Layout* layout, Target_i386* target,
f6ce93d6 63 Sized_relobj<32, false>* object,
92e059d8
ILT
64 const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
65 const elfcpp::Sym<32, false>& lsym);
61ba1cf9 66
92e059d8 67 inline void
ead1e424
ILT
68 global(const General_options& options, Symbol_table* symtab,
69 Layout* layout, Target_i386* target,
f6ce93d6 70 Sized_relobj<32, false>* object,
92e059d8
ILT
71 const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
72 Symbol* gsym);
61ba1cf9
ILT
73 };
74
92e059d8
ILT
75 // The class which implements relocation.
76 class Relocate
77 {
78 public:
ead1e424
ILT
79 Relocate()
80 : skip_call_tls_get_addr_(false)
81 { }
82
83 ~Relocate()
84 {
85 if (this->skip_call_tls_get_addr_)
86 {
87 // FIXME: This needs to specify the location somehow.
88 fprintf(stderr, _("%s: missing expected TLS relocation\n"),
89 program_name);
90 gold_exit(false);
91 }
92 }
93
94 // Do a relocation. Return false if the caller should not issue
95 // any warnings about this relocation.
96 inline bool
97 relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum,
92e059d8 98 const elfcpp::Rel<32, false>&,
c06b7b0b 99 unsigned int r_type, const Sized_symbol<32>*,
92e059d8
ILT
100 elfcpp::Elf_types<32>::Elf_Addr,
101 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
102 off_t);
103
104 private:
105 // Do a TLS relocation.
ead1e424 106 inline void
92e059d8
ILT
107 relocate_tls(const Relocate_info<32, false>*, size_t relnum,
108 const elfcpp::Rel<32, false>&,
c06b7b0b 109 unsigned int r_type, const Sized_symbol<32>*,
92e059d8
ILT
110 elfcpp::Elf_types<32>::Elf_Addr,
111 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, off_t);
112
113 // Do a TLS Initial-Exec to Local-Exec transition.
114 static inline void
115 tls_ie_to_le(const Relocate_info<32, false>*, size_t relnum,
116 Output_segment* tls_segment,
117 const elfcpp::Rel<32, false>&, unsigned int r_type,
118 elfcpp::Elf_types<32>::Elf_Addr value,
119 unsigned char* view,
120 off_t view_size);
121
ead1e424
ILT
122 // Do a TLS Global-Dynamic to Local-Exec transition.
123 inline void
124 tls_gd_to_le(const Relocate_info<32, false>*, size_t relnum,
125 Output_segment* tls_segment,
126 const elfcpp::Rel<32, false>&, unsigned int r_type,
127 elfcpp::Elf_types<32>::Elf_Addr value,
128 unsigned char* view,
129 off_t view_size);
130
92e059d8
ILT
131 // Check the range for a TLS relocation.
132 static inline void
133 check_range(const Relocate_info<32, false>*, size_t relnum,
134 const elfcpp::Rel<32, false>&, off_t, off_t);
135
136 // Check the validity of a TLS relocation. This is like assert.
137 static inline void
138 check_tls(const Relocate_info<32, false>*, size_t relnum,
139 const elfcpp::Rel<32, false>&, bool);
ead1e424
ILT
140
141 // This is set if we should skip the next reloc, which should be a
142 // PLT32 reloc against ___tls_get_addr.
143 bool skip_call_tls_get_addr_;
92e059d8
ILT
144 };
145
146 // Adjust TLS relocation type based on the options and whether this
147 // is a local symbol.
148 static unsigned int
149 optimize_tls_reloc(const General_options*, bool is_local, int r_type);
150
ead1e424 151 // Get the GOT section, creating it if necessary.
dbe717ef 152 Output_data_got<32, false>*
ead1e424
ILT
153 got_section(Symbol_table*, Layout*);
154
92e059d8
ILT
155 // Information about this specific target which we pass to the
156 // general Target structure.
75f65a3e 157 static const Target::Target_info i386_info;
ead1e424
ILT
158
159 // The GOT section.
dbe717ef 160 Output_data_got<32, false>* got_;
75f65a3e
ILT
161};
162
163const Target::Target_info Target_i386::i386_info =
164{
61ba1cf9
ILT
165 32, // size
166 false, // is_big_endian
167 elfcpp::EM_386, // machine_code
168 false, // has_make_symbol
dbe717ef
ILT
169 false, // has_resolve
170 "/usr/lib/libc.so.1", // dynamic_linker
171 0x08048000, // text_segment_address
61ba1cf9
ILT
172 0x1000, // abi_pagesize
173 0x1000 // common_pagesize
14bfc3f5
ILT
174};
175
ead1e424
ILT
176// Get the GOT section, creating it if necessary.
177
dbe717ef 178Output_data_got<32, false>*
ead1e424
ILT
179Target_i386::got_section(Symbol_table* symtab, Layout* layout)
180{
181 if (this->got_ == NULL)
182 {
dbe717ef 183 this->got_ = new Output_data_got<32, false>();
ead1e424
ILT
184
185 assert(symtab != NULL && layout != NULL);
186 layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
187 elfcpp::SHF_ALLOC, this->got_);
188
189 // The first three entries are reserved.
190 this->got_->add_constant(0);
191 this->got_->add_constant(0);
192 this->got_->add_constant(0);
193
194 // Define _GLOBAL_OFFSET_TABLE_ at the start of the section.
195 symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_", this->got_,
196 0, 0, elfcpp::STT_OBJECT,
197 elfcpp::STB_GLOBAL,
198 elfcpp::STV_HIDDEN, 0,
199 false, false);
200 }
201 return this->got_;
202}
203
92e059d8
ILT
204// Optimize the TLS relocation type based on what we know about the
205// symbol. IS_LOCAL is true if this symbol can be resolved entirely
206// locally--i.e., does not have to be in the dynamic symbol table.
207
208unsigned int
209Target_i386::optimize_tls_reloc(const General_options* options, bool is_local,
210 int r_type)
211{
212 // If we are generating a shared library, then we can't do anything
213 // in the linker.
214 if (options->is_shared())
215 return r_type;
216
217 switch (r_type)
218 {
219 case elfcpp::R_386_TLS_GD:
220 case elfcpp::R_386_TLS_GOTDESC:
221 case elfcpp::R_386_TLS_DESC_CALL:
222 // These are Global-Dynamic which permits fully general TLS
223 // access. Since we know that we are generating an executable,
224 // we can convert this to Initial-Exec. If we also know that
225 // this is a local symbol, we can further switch to Local-Exec.
226 if (is_local)
227 return elfcpp::R_386_TLS_LE_32;
228 return elfcpp::R_386_TLS_IE_32;
229
230 case elfcpp::R_386_TLS_LDM:
231 // This is Local-Dynamic, which refers to a local symbol in the
232 // dynamic TLS block. Since we know that we generating an
233 // executable, we can switch to Local-Exec.
234 return elfcpp::R_386_TLS_LE_32;
235
236 case elfcpp::R_386_TLS_LDO_32:
237 // Another type of Local-Dynamic relocation.
238 return elfcpp::R_386_TLS_LE;
239
240 case elfcpp::R_386_TLS_IE:
241 case elfcpp::R_386_TLS_GOTIE:
242 case elfcpp::R_386_TLS_IE_32:
243 // These are Initial-Exec relocs which get the thread offset
244 // from the GOT. If we know that we are linking against the
245 // local symbol, we can switch to Local-Exec, which links the
246 // thread offset into the instruction.
247 if (is_local)
248 return elfcpp::R_386_TLS_LE_32;
249 return r_type;
250
251 case elfcpp::R_386_TLS_LE:
252 case elfcpp::R_386_TLS_LE_32:
253 // When we already have Local-Exec, there is nothing further we
254 // can do.
255 return r_type;
256
257 default:
258 abort();
259 }
260}
261
262// Scan a relocation for a local symbol.
263
264inline void
265Target_i386::Scan::local(const General_options& options,
ead1e424
ILT
266 Symbol_table* symtab,
267 Layout* layout,
268 Target_i386* target,
f6ce93d6 269 Sized_relobj<32, false>* object,
92e059d8
ILT
270 const elfcpp::Rel<32, false>&, unsigned int r_type,
271 const elfcpp::Sym<32, false>&)
272{
273 switch (r_type)
274 {
275 case elfcpp::R_386_NONE:
276 case elfcpp::R_386_GNU_VTINHERIT:
277 case elfcpp::R_386_GNU_VTENTRY:
278 break;
279
280 case elfcpp::R_386_32:
281 case elfcpp::R_386_16:
282 case elfcpp::R_386_8:
283 // FIXME: If we are generating a shared object we need to copy
284 // this relocation into the object.
285 break;
286
287 case elfcpp::R_386_PC32:
288 case elfcpp::R_386_PC16:
289 case elfcpp::R_386_PC8:
290 break;
291
ead1e424
ILT
292 case elfcpp::R_386_GOTOFF:
293 case elfcpp::R_386_GOTPC:
294 // We need a GOT section.
295 target->got_section(symtab, layout);
296 break;
297
92e059d8
ILT
298 case elfcpp::R_386_COPY:
299 case elfcpp::R_386_GLOB_DAT:
300 case elfcpp::R_386_JUMP_SLOT:
301 case elfcpp::R_386_RELATIVE:
302 case elfcpp::R_386_TLS_TPOFF:
303 case elfcpp::R_386_TLS_DTPMOD32:
304 case elfcpp::R_386_TLS_DTPOFF32:
305 case elfcpp::R_386_TLS_TPOFF32:
306 case elfcpp::R_386_TLS_DESC:
307 fprintf(stderr, _("%s: %s: unexpected reloc %u in object file\n"),
308 program_name, object->name().c_str(), r_type);
309 gold_exit(false);
310 break;
311
312 case elfcpp::R_386_TLS_IE:
313 case elfcpp::R_386_TLS_GOTIE:
314 case elfcpp::R_386_TLS_LE:
315 case elfcpp::R_386_TLS_GD:
316 case elfcpp::R_386_TLS_LDM:
317 case elfcpp::R_386_TLS_LDO_32:
318 case elfcpp::R_386_TLS_IE_32:
319 case elfcpp::R_386_TLS_LE_32:
320 case elfcpp::R_386_TLS_GOTDESC:
321 case elfcpp::R_386_TLS_DESC_CALL:
322 r_type = Target_i386::optimize_tls_reloc(&options, true, r_type);
323 switch (r_type)
324 {
325 case elfcpp::R_386_TLS_LE:
326 case elfcpp::R_386_TLS_LE_32:
327 // FIXME: If generating a shared object, we need to copy
328 // this relocation into the object.
329 break;
330
331 case elfcpp::R_386_TLS_IE:
332 case elfcpp::R_386_TLS_GOTIE:
333 case elfcpp::R_386_TLS_GD:
334 case elfcpp::R_386_TLS_LDM:
335 case elfcpp::R_386_TLS_LDO_32:
336 case elfcpp::R_386_TLS_IE_32:
337 case elfcpp::R_386_TLS_GOTDESC:
338 case elfcpp::R_386_TLS_DESC_CALL:
339 fprintf(stderr,
340 _("%s: %s: unsupported reloc %u against local symbol\n"),
341 program_name, object->name().c_str(), r_type);
342 break;
343 }
344 break;
345
346 case elfcpp::R_386_GOT32:
347 case elfcpp::R_386_PLT32:
92e059d8
ILT
348 case elfcpp::R_386_32PLT:
349 case elfcpp::R_386_TLS_GD_32:
350 case elfcpp::R_386_TLS_GD_PUSH:
351 case elfcpp::R_386_TLS_GD_CALL:
352 case elfcpp::R_386_TLS_GD_POP:
353 case elfcpp::R_386_TLS_LDM_32:
354 case elfcpp::R_386_TLS_LDM_PUSH:
355 case elfcpp::R_386_TLS_LDM_CALL:
356 case elfcpp::R_386_TLS_LDM_POP:
357 case elfcpp::R_386_USED_BY_INTEL_200:
358 default:
359 fprintf(stderr, _("%s: %s: unsupported reloc %u against local symbol\n"),
360 program_name, object->name().c_str(), r_type);
361 break;
362 }
363}
364
365// Scan a relocation for a global symbol.
366
367inline void
368Target_i386::Scan::global(const General_options& options,
ead1e424
ILT
369 Symbol_table* symtab,
370 Layout* layout,
371 Target_i386* target,
f6ce93d6 372 Sized_relobj<32, false>* object,
92e059d8
ILT
373 const elfcpp::Rel<32, false>&, unsigned int r_type,
374 Symbol* gsym)
375{
376 switch (r_type)
377 {
378 case elfcpp::R_386_NONE:
379 case elfcpp::R_386_GNU_VTINHERIT:
380 case elfcpp::R_386_GNU_VTENTRY:
381 break;
382
383 case elfcpp::R_386_32:
384 case elfcpp::R_386_PC32:
385 case elfcpp::R_386_16:
386 case elfcpp::R_386_PC16:
387 case elfcpp::R_386_8:
388 case elfcpp::R_386_PC8:
389 // FIXME: If we are generating a shared object we may need to
390 // copy this relocation into the object. If this symbol is
391 // defined in a shared object, we may need to copy this
392 // relocation in order to avoid a COPY relocation.
393 break;
394
ead1e424
ILT
395 case elfcpp::R_386_GOT32:
396 // The symbol requires a GOT entry.
dbe717ef 397 if (target->got_section(symtab, layout)->add_global(gsym))
ead1e424 398 {
ead1e424
ILT
399 // If this symbol is not resolved locally, we need to add a
400 // dynamic relocation for it.
401 if (!gsym->is_resolved_locally())
402 abort();
403 }
404 break;
405
406 case elfcpp::R_386_PLT32:
407 // If the symbol is resolved locally, this is just a PC32 reloc.
408 if (gsym->is_resolved_locally())
409 break;
410 fprintf(stderr,
411 _("%s: %s: unsupported reloc %u against global symbol %s\n"),
412 program_name, object->name().c_str(), r_type, gsym->name());
413 break;
414
415 case elfcpp::R_386_GOTOFF:
416 case elfcpp::R_386_GOTPC:
417 // We need a GOT section.
418 target->got_section(symtab, layout);
419 break;
420
92e059d8
ILT
421 case elfcpp::R_386_COPY:
422 case elfcpp::R_386_GLOB_DAT:
423 case elfcpp::R_386_JUMP_SLOT:
424 case elfcpp::R_386_RELATIVE:
425 case elfcpp::R_386_TLS_TPOFF:
426 case elfcpp::R_386_TLS_DTPMOD32:
427 case elfcpp::R_386_TLS_DTPOFF32:
428 case elfcpp::R_386_TLS_TPOFF32:
429 case elfcpp::R_386_TLS_DESC:
430 fprintf(stderr, _("%s: %s: unexpected reloc %u in object file\n"),
431 program_name, object->name().c_str(), r_type);
432 gold_exit(false);
433 break;
434
435 case elfcpp::R_386_TLS_IE:
436 case elfcpp::R_386_TLS_GOTIE:
437 case elfcpp::R_386_TLS_LE:
438 case elfcpp::R_386_TLS_GD:
439 case elfcpp::R_386_TLS_LDM:
440 case elfcpp::R_386_TLS_LDO_32:
441 case elfcpp::R_386_TLS_IE_32:
442 case elfcpp::R_386_TLS_LE_32:
443 case elfcpp::R_386_TLS_GOTDESC:
444 case elfcpp::R_386_TLS_DESC_CALL:
445 r_type = Target_i386::optimize_tls_reloc(&options,
ead1e424 446 gsym->is_resolved_locally(),
92e059d8
ILT
447 r_type);
448 switch (r_type)
449 {
450 case elfcpp::R_386_TLS_LE:
451 case elfcpp::R_386_TLS_LE_32:
452 // FIXME: If generating a shared object, we need to copy
453 // this relocation into the object.
454 break;
455
456 case elfcpp::R_386_TLS_IE:
457 case elfcpp::R_386_TLS_GOTIE:
458 case elfcpp::R_386_TLS_GD:
459 case elfcpp::R_386_TLS_LDM:
460 case elfcpp::R_386_TLS_LDO_32:
461 case elfcpp::R_386_TLS_IE_32:
462 case elfcpp::R_386_TLS_GOTDESC:
463 case elfcpp::R_386_TLS_DESC_CALL:
464 fprintf(stderr,
465 _("%s: %s: unsupported reloc %u against global symbol %s\n"),
466 program_name, object->name().c_str(), r_type, gsym->name());
467 break;
468 }
469 break;
470
92e059d8
ILT
471 case elfcpp::R_386_32PLT:
472 case elfcpp::R_386_TLS_GD_32:
473 case elfcpp::R_386_TLS_GD_PUSH:
474 case elfcpp::R_386_TLS_GD_CALL:
475 case elfcpp::R_386_TLS_GD_POP:
476 case elfcpp::R_386_TLS_LDM_32:
477 case elfcpp::R_386_TLS_LDM_PUSH:
478 case elfcpp::R_386_TLS_LDM_CALL:
479 case elfcpp::R_386_TLS_LDM_POP:
480 case elfcpp::R_386_USED_BY_INTEL_200:
481 default:
482 fprintf(stderr,
483 _("%s: %s: unsupported reloc %u against global symbol %s\n"),
484 program_name, object->name().c_str(), r_type, gsym->name());
485 break;
486 }
487}
488
489// Scan relocations for a section.
490
491void
492Target_i386::scan_relocs(const General_options& options,
493 Symbol_table* symtab,
ead1e424 494 Layout* layout,
f6ce93d6 495 Sized_relobj<32, false>* object,
92e059d8
ILT
496 unsigned int sh_type,
497 const unsigned char* prelocs,
498 size_t reloc_count,
499 size_t local_symbol_count,
500 const unsigned char* plocal_symbols,
501 Symbol** global_symbols)
502{
503 if (sh_type == elfcpp::SHT_RELA)
504 {
505 fprintf(stderr, _("%s: %s: unsupported RELA reloc section\n"),
506 program_name, object->name().c_str());
507 gold_exit(false);
508 }
509
ead1e424
ILT
510 gold::scan_relocs<32, false, Target_i386, elfcpp::SHT_REL,
511 Target_i386::Scan>(
92e059d8
ILT
512 options,
513 symtab,
ead1e424
ILT
514 layout,
515 this,
92e059d8
ILT
516 object,
517 prelocs,
518 reloc_count,
519 local_symbol_count,
520 plocal_symbols,
521 global_symbols);
522}
523
61ba1cf9
ILT
524// Perform a relocation.
525
ead1e424 526inline bool
92e059d8 527Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
ead1e424 528 Target_i386* target,
92e059d8
ILT
529 size_t relnum,
530 const elfcpp::Rel<32, false>& rel,
531 unsigned int r_type,
c06b7b0b 532 const Sized_symbol<32>* gsym,
92e059d8
ILT
533 elfcpp::Elf_types<32>::Elf_Addr value,
534 unsigned char* view,
535 elfcpp::Elf_types<32>::Elf_Addr address,
536 off_t view_size)
61ba1cf9 537{
ead1e424
ILT
538 if (this->skip_call_tls_get_addr_)
539 {
540 if (r_type != elfcpp::R_386_PLT32
541 || gsym == NULL
542 || strcmp(gsym->name(), "___tls_get_addr") != 0)
543 {
544 fprintf(stderr, _("%s: %s: missing expected TLS relocation\n"),
545 program_name,
546 relinfo->location(relnum, rel.get_r_offset()).c_str());
547 gold_exit(false);
548 }
549
550 this->skip_call_tls_get_addr_ = false;
551
552 return false;
553 }
554
61ba1cf9
ILT
555 switch (r_type)
556 {
557 case elfcpp::R_386_NONE:
92e059d8
ILT
558 case elfcpp::R_386_GNU_VTINHERIT:
559 case elfcpp::R_386_GNU_VTENTRY:
61ba1cf9
ILT
560 break;
561
562 case elfcpp::R_386_32:
92e059d8 563 Relocate_functions<32, false>::rel32(view, value);
61ba1cf9
ILT
564 break;
565
566 case elfcpp::R_386_PC32:
92e059d8
ILT
567 Relocate_functions<32, false>::pcrel32(view, value, address);
568 break;
569
570 case elfcpp::R_386_16:
571 Relocate_functions<32, false>::rel16(view, value);
572 break;
573
574 case elfcpp::R_386_PC16:
575 Relocate_functions<32, false>::pcrel16(view, value, address);
61ba1cf9
ILT
576 break;
577
92e059d8
ILT
578 case elfcpp::R_386_8:
579 Relocate_functions<32, false>::rel8(view, value);
580 break;
581
582 case elfcpp::R_386_PC8:
583 Relocate_functions<32, false>::pcrel8(view, value, address);
584 break;
585
ead1e424
ILT
586 case elfcpp::R_386_PLT32:
587 if (gsym->is_resolved_locally())
588 Relocate_functions<32, false>::pcrel32(view, value, address);
589 else
590 fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
591 program_name,
592 relinfo->location(relnum, rel.get_r_offset()).c_str(),
593 r_type);
594 break;
595
596 case elfcpp::R_386_GOT32:
597 // Local GOT offsets not yet supported.
598 assert(gsym);
599 assert(gsym->has_got_offset());
600 value = gsym->got_offset();
601 Relocate_functions<32, false>::rel32(view, value);
602 break;
603
604 case elfcpp::R_386_GOTOFF:
605 value -= target->got_section(NULL, NULL)->address();
606 Relocate_functions<32, false>::rel32(view, value);
607 break;
608
609 case elfcpp::R_386_GOTPC:
610 value = target->got_section(NULL, NULL)->address();
611 Relocate_functions<32, false>::pcrel32(view, value, address);
612 break;
613
92e059d8
ILT
614 case elfcpp::R_386_COPY:
615 case elfcpp::R_386_GLOB_DAT:
616 case elfcpp::R_386_JUMP_SLOT:
617 case elfcpp::R_386_RELATIVE:
618 case elfcpp::R_386_TLS_TPOFF:
619 case elfcpp::R_386_TLS_DTPMOD32:
620 case elfcpp::R_386_TLS_DTPOFF32:
621 case elfcpp::R_386_TLS_TPOFF32:
622 case elfcpp::R_386_TLS_DESC:
623 fprintf(stderr, _("%s: %s: unexpected reloc %u in object file\n"),
624 program_name,
625 relinfo->location(relnum, rel.get_r_offset()).c_str(),
626 r_type);
627 gold_exit(false);
628 break;
629
630 case elfcpp::R_386_TLS_IE:
631 case elfcpp::R_386_TLS_GOTIE:
632 case elfcpp::R_386_TLS_LE:
633 case elfcpp::R_386_TLS_GD:
634 case elfcpp::R_386_TLS_LDM:
635 case elfcpp::R_386_TLS_LDO_32:
636 case elfcpp::R_386_TLS_IE_32:
637 case elfcpp::R_386_TLS_LE_32:
638 case elfcpp::R_386_TLS_GOTDESC:
639 case elfcpp::R_386_TLS_DESC_CALL:
ead1e424
ILT
640 this->relocate_tls(relinfo, relnum, rel, r_type, gsym, value, view,
641 address, view_size);
92e059d8
ILT
642 break;
643
92e059d8
ILT
644 case elfcpp::R_386_32PLT:
645 case elfcpp::R_386_TLS_GD_32:
646 case elfcpp::R_386_TLS_GD_PUSH:
647 case elfcpp::R_386_TLS_GD_CALL:
648 case elfcpp::R_386_TLS_GD_POP:
649 case elfcpp::R_386_TLS_LDM_32:
650 case elfcpp::R_386_TLS_LDM_PUSH:
651 case elfcpp::R_386_TLS_LDM_CALL:
652 case elfcpp::R_386_TLS_LDM_POP:
653 case elfcpp::R_386_USED_BY_INTEL_200:
61ba1cf9
ILT
654 default:
655 fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
92e059d8
ILT
656 program_name,
657 relinfo->location(relnum, rel.get_r_offset()).c_str(),
658 r_type);
61ba1cf9 659 // gold_exit(false);
92e059d8
ILT
660 break;
661 }
ead1e424
ILT
662
663 return true;
92e059d8
ILT
664}
665
666// Perform a TLS relocation.
667
668inline void
669Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
670 size_t relnum,
671 const elfcpp::Rel<32, false>& rel,
672 unsigned int r_type,
c06b7b0b 673 const Sized_symbol<32>* gsym,
92e059d8
ILT
674 elfcpp::Elf_types<32>::Elf_Addr value,
675 unsigned char* view,
676 elfcpp::Elf_types<32>::Elf_Addr,
677 off_t view_size)
678{
679 Output_segment* tls_segment = relinfo->layout->tls_segment();
680 if (tls_segment == NULL)
681 {
682 fprintf(stderr, _("%s: %s: TLS reloc but no TLS segment\n"),
683 program_name,
684 relinfo->location(relnum, rel.get_r_offset()).c_str());
685 gold_exit(false);
686 }
687
ead1e424 688 const bool is_local = gsym == NULL || gsym->is_resolved_locally();
92e059d8
ILT
689 const unsigned int opt_r_type =
690 Target_i386::optimize_tls_reloc(relinfo->options, is_local, r_type);
691 switch (r_type)
692 {
693 case elfcpp::R_386_TLS_LE_32:
694 value = tls_segment->vaddr() + tls_segment->memsz() - value;
695 Relocate_functions<32, false>::rel32(view, value);
696 break;
697
698 case elfcpp::R_386_TLS_LE:
699 value = value - (tls_segment->vaddr() + tls_segment->memsz());
700 Relocate_functions<32, false>::rel32(view, value);
701 break;
702
703 case elfcpp::R_386_TLS_IE:
704 case elfcpp::R_386_TLS_GOTIE:
705 case elfcpp::R_386_TLS_IE_32:
706 if (opt_r_type == elfcpp::R_386_TLS_LE_32)
707 {
708 Target_i386::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
709 rel, r_type, value, view,
710 view_size);
711 break;
712 }
713 fprintf(stderr, _("%s: %s: unsupported reloc type %u\n"),
714 program_name,
715 relinfo->location(relnum, rel.get_r_offset()).c_str(),
716 r_type);
717 // gold_exit(false);
718 break;
719
720 case elfcpp::R_386_TLS_GD:
ead1e424
ILT
721 if (opt_r_type == elfcpp::R_386_TLS_LE_32)
722 {
723 this->tls_gd_to_le(relinfo, relnum, tls_segment,
724 rel, r_type, value, view,
725 view_size);
726 break;
727 }
728 fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
729 program_name,
730 relinfo->location(relnum, rel.get_r_offset()).c_str(),
731 r_type);
732 // gold_exit(false);
733 break;
734
92e059d8
ILT
735 case elfcpp::R_386_TLS_LDM:
736 case elfcpp::R_386_TLS_LDO_32:
737 case elfcpp::R_386_TLS_GOTDESC:
738 case elfcpp::R_386_TLS_DESC_CALL:
739 fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
740 program_name,
741 relinfo->location(relnum, rel.get_r_offset()).c_str(),
742 r_type);
743 // gold_exit(false);
744 break;
745 }
746}
747
748// Do a relocation in which we convert a TLS Initial-Exec to a
749// Local-Exec.
750
751inline void
752Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
753 size_t relnum,
754 Output_segment* tls_segment,
755 const elfcpp::Rel<32, false>& rel,
756 unsigned int r_type,
757 elfcpp::Elf_types<32>::Elf_Addr value,
758 unsigned char* view,
759 off_t view_size)
760{
761 // We have to actually change the instructions, which means that we
762 // need to examine the opcodes to figure out which instruction we
763 // are looking at.
764 if (r_type == elfcpp::R_386_TLS_IE)
765 {
766 // movl %gs:XX,%eax ==> movl $YY,%eax
767 // movl %gs:XX,%reg ==> movl $YY,%reg
768 // addl %gs:XX,%reg ==> addl $YY,%reg
769 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -1);
770 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 4);
771
772 unsigned char op1 = view[-1];
773 if (op1 == 0xa1)
774 {
775 // movl XX,%eax ==> movl $YY,%eax
776 view[-1] = 0xb8;
777 }
778 else
779 {
780 Target_i386::Relocate::check_range(relinfo, relnum, rel,
781 view_size, -2);
782
783 unsigned char op2 = view[-2];
784 if (op2 == 0x8b)
785 {
786 // movl XX,%reg ==> movl $YY,%reg
787 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
788 (op1 & 0xc7) == 0x05);
789 view[-2] = 0xc7;
790 view[-1] = 0xc0 | ((op1 >> 3) & 7);
791 }
792 else if (op2 == 0x03)
793 {
794 // addl XX,%reg ==> addl $YY,%reg
795 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
796 (op1 & 0xc7) == 0x05);
797 view[-2] = 0x81;
798 view[-1] = 0xc0 | ((op1 >> 3) & 7);
799 }
800 else
801 Target_i386::Relocate::check_tls(relinfo, relnum, rel, 0);
802 }
803 }
804 else
805 {
806 // subl %gs:XX(%reg1),%reg2 ==> subl $YY,%reg2
807 // movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2
808 // addl %gs:XX(%reg1),%reg2 ==> addl $YY,$reg2
809 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -2);
810 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 4);
811
812 unsigned char op1 = view[-1];
813 unsigned char op2 = view[-2];
814 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
815 (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
816 if (op2 == 0x8b)
817 {
818 // movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2
819 view[-2] = 0xc7;
820 view[-1] = 0xc0 | ((op1 >> 3) & 7);
821 }
822 else if (op2 == 0x2b)
823 {
824 // subl %gs:XX(%reg1),%reg2 ==> subl $YY,%reg2
825 view[-2] = 0x81;
826 view[-1] = 0xe8 | ((op1 >> 3) & 7);
827 }
828 else if (op2 == 0x03)
829 {
830 // addl %gs:XX(%reg1),%reg2 ==> addl $YY,$reg2
831 view[-2] = 0x81;
832 view[-1] = 0xc0 | ((op1 >> 3) & 7);
833 }
834 else
835 Target_i386::Relocate::check_tls(relinfo, relnum, rel, 0);
836 }
837
ead1e424
ILT
838 value = tls_segment->vaddr() + tls_segment->memsz() - value;
839 if (r_type == elfcpp::R_386_TLS_IE || r_type == elfcpp::R_386_TLS_GOTIE)
840 value = - value;
92e059d8
ILT
841
842 Relocate_functions<32, false>::rel32(view, value);
843}
844
ead1e424
ILT
845// Do a relocation in which we convert a TLS Global-Dynamic to a
846// Local-Exec.
847
848inline void
849Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo,
850 size_t relnum,
851 Output_segment* tls_segment,
852 const elfcpp::Rel<32, false>& rel,
853 unsigned int,
854 elfcpp::Elf_types<32>::Elf_Addr value,
855 unsigned char* view,
856 off_t view_size)
857{
858 // leal foo(,%reg,1),%eax; call ___tls_get_addr
859 // ==> movl %gs,0,%eax; subl $foo@tpoff,%eax
860 // leal foo(%reg),%eax; call ___tls_get_addr
861 // ==> movl %gs:0,%eax; subl $foo@tpoff,%eax
862
863 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -2);
864 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 9);
865
866 unsigned char op1 = view[-1];
867 unsigned char op2 = view[-2];
868
869 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
870 op2 == 0x8d || op2 == 0x04);
871 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
872 view[4] == 0xe8);
873
874 int roff = 5;
875
876 if (op2 == 0x04)
877 {
878 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -3);
879 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
880 view[-3] == 0x8d);
881 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
882 ((op1 & 0xc7) == 0x05
883 && op1 != (4 << 3)));
884 memcpy(view - 3, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
885 }
886 else
887 {
888 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
889 (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
890 if (rel.get_r_offset() + 9 < view_size && view[9] == 0x90)
891 {
892 // There is a trailing nop. Use the size byte subl.
893 memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
894 roff = 6;
895 }
896 else
897 {
898 // Use the five byte subl.
899 memcpy(view - 2, "\x65\xa1\0\0\0\0\x2d\0\0\0", 11);
900 }
901 }
902
903 value = tls_segment->vaddr() + tls_segment->memsz() - value;
904 Relocate_functions<32, false>::rel32(view + roff, value);
905
906 // The next reloc should be a PLT32 reloc against __tls_get_addr.
907 // We can skip it.
908 this->skip_call_tls_get_addr_ = true;
909}
910
92e059d8
ILT
911// Check the range for a TLS relocation.
912
913inline void
914Target_i386::Relocate::check_range(const Relocate_info<32, false>* relinfo,
915 size_t relnum,
916 const elfcpp::Rel<32, false>& rel,
917 off_t view_size, off_t off)
918{
919 off_t offset = rel.get_r_offset() + off;
920 if (offset < 0 || offset > view_size)
921 {
922 fprintf(stderr, _("%s: %s: TLS relocation out of range\n"),
923 program_name,
924 relinfo->location(relnum, rel.get_r_offset()).c_str());
925 gold_exit(false);
926 }
927}
928
929// Check the validity of a TLS relocation. This is like assert.
930
931inline void
932Target_i386::Relocate::check_tls(const Relocate_info<32, false>* relinfo,
933 size_t relnum,
934 const elfcpp::Rel<32, false>& rel,
935 bool valid)
936{
937 if (!valid)
938 {
939 fprintf(stderr,
940 _("%s: %s: TLS relocation against invalid instruction\n"),
941 program_name,
942 relinfo->location(relnum, rel.get_r_offset()).c_str());
943 gold_exit(false);
61ba1cf9
ILT
944 }
945}
946
947// Relocate section data.
948
949void
92e059d8 950Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
61ba1cf9
ILT
951 unsigned int sh_type,
952 const unsigned char* prelocs,
953 size_t reloc_count,
61ba1cf9
ILT
954 unsigned char* view,
955 elfcpp::Elf_types<32>::Elf_Addr address,
956 off_t view_size)
957{
92e059d8 958 assert(sh_type == elfcpp::SHT_REL);
61ba1cf9 959
ead1e424
ILT
960 gold::relocate_section<32, false, Target_i386, elfcpp::SHT_REL,
961 Target_i386::Relocate>(
92e059d8 962 relinfo,
ead1e424 963 this,
61ba1cf9
ILT
964 prelocs,
965 reloc_count,
61ba1cf9
ILT
966 view,
967 address,
968 view_size);
969}
970
14bfc3f5
ILT
971// The selector for i386 object files.
972
973class Target_selector_i386 : public Target_selector
974{
975public:
976 Target_selector_i386()
977 : Target_selector(elfcpp::EM_386, 32, false)
978 { }
979
980 Target*
ead1e424
ILT
981 recognize(int machine, int osabi, int abiversion);
982
983 private:
984 Target_i386* target_;
14bfc3f5
ILT
985};
986
987// Recognize an i386 object file when we already know that the machine
988// number is EM_386.
989
990Target*
ead1e424 991Target_selector_i386::recognize(int, int, int)
14bfc3f5 992{
ead1e424
ILT
993 if (this->target_ == NULL)
994 this->target_ = new Target_i386();
995 return this->target_;
14bfc3f5
ILT
996}
997
998Target_selector_i386 target_selector_i386;
999
1000} // End anonymous namespace.
This page took 0.071382 seconds and 4 git commands to generate.