Fix typo in comment.
[deliverable/binutils-gdb.git] / gold / i386.cc
CommitLineData
14bfc3f5
ILT
1// i386.cc -- i386 target support for gold.
2
3#include "gold.h"
4#include "elfcpp.h"
92e059d8 5#include "reloc.h"
61ba1cf9
ILT
6#include "i386.h"
7#include "object.h"
92e059d8
ILT
8#include "layout.h"
9#include "output.h"
14bfc3f5 10#include "target.h"
61ba1cf9 11#include "target-reloc.h"
14bfc3f5
ILT
12#include "target-select.h"
13
14namespace
15{
16
17using namespace gold;
18
19// The i386 target class.
20
21class Target_i386 : public Sized_target<32, false>
22{
23 public:
24 Target_i386()
75f65a3e 25 : Sized_target<32, false>(&i386_info)
14bfc3f5 26 { }
75f65a3e 27
92e059d8 28 // Scan the relocations to look for symbol adjustments.
61ba1cf9 29 void
92e059d8
ILT
30 scan_relocs(const General_options& options,
31 Symbol_table* symtab,
32 Sized_object<32, false>* object,
33 unsigned int sh_type,
34 const unsigned char* prelocs,
35 size_t reloc_count,
36 size_t local_symbol_count,
37 const unsigned char* plocal_symbols,
38 Symbol** global_symbols);
61ba1cf9 39
92e059d8
ILT
40 // Relocate a section.
41 void
42 relocate_section(const Relocate_info<32, false>*,
43 unsigned int sh_type,
44 const unsigned char* prelocs,
45 size_t reloc_count,
46 unsigned char* view,
47 elfcpp::Elf_types<32>::Elf_Addr view_address,
48 off_t view_size);
49
50 private:
51 // The class which scans relocations.
52 struct Scan
61ba1cf9
ILT
53 {
54 inline void
92e059d8
ILT
55 local(const General_options& options, Sized_object<32, false>* object,
56 const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
57 const elfcpp::Sym<32, false>& lsym);
61ba1cf9 58
92e059d8
ILT
59 inline void
60 global(const General_options& options, Sized_object<32, false>* object,
61 const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
62 Symbol* gsym);
61ba1cf9
ILT
63 };
64
92e059d8
ILT
65 // The class which implements relocation.
66 class Relocate
67 {
68 public:
69 // Do a relocation.
70 static inline void
71 relocate(const Relocate_info<32, false>*, size_t relnum,
72 const elfcpp::Rel<32, false>&,
73 unsigned int r_type, Sized_symbol<32>*,
74 elfcpp::Elf_types<32>::Elf_Addr,
75 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
76 off_t);
77
78 private:
79 // Do a TLS relocation.
80 static inline void
81 relocate_tls(const Relocate_info<32, false>*, size_t relnum,
82 const elfcpp::Rel<32, false>&,
83 unsigned int r_type, Sized_symbol<32>*,
84 elfcpp::Elf_types<32>::Elf_Addr,
85 unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, off_t);
86
87 // Do a TLS Initial-Exec to Local-Exec transition.
88 static inline void
89 tls_ie_to_le(const Relocate_info<32, false>*, size_t relnum,
90 Output_segment* tls_segment,
91 const elfcpp::Rel<32, false>&, unsigned int r_type,
92 elfcpp::Elf_types<32>::Elf_Addr value,
93 unsigned char* view,
94 off_t view_size);
95
96 // Check the range for a TLS relocation.
97 static inline void
98 check_range(const Relocate_info<32, false>*, size_t relnum,
99 const elfcpp::Rel<32, false>&, off_t, off_t);
100
101 // Check the validity of a TLS relocation. This is like assert.
102 static inline void
103 check_tls(const Relocate_info<32, false>*, size_t relnum,
104 const elfcpp::Rel<32, false>&, bool);
105 };
106
107 // Adjust TLS relocation type based on the options and whether this
108 // is a local symbol.
109 static unsigned int
110 optimize_tls_reloc(const General_options*, bool is_local, int r_type);
111
112 // Information about this specific target which we pass to the
113 // general Target structure.
75f65a3e
ILT
114 static const Target::Target_info i386_info;
115};
116
117const Target::Target_info Target_i386::i386_info =
118{
61ba1cf9
ILT
119 32, // size
120 false, // is_big_endian
121 elfcpp::EM_386, // machine_code
122 false, // has_make_symbol
123 false, // has_resolve,
124 0x08048000, // text_segment_address,
125 0x1000, // abi_pagesize
126 0x1000 // common_pagesize
14bfc3f5
ILT
127};
128
92e059d8
ILT
129// Optimize the TLS relocation type based on what we know about the
130// symbol. IS_LOCAL is true if this symbol can be resolved entirely
131// locally--i.e., does not have to be in the dynamic symbol table.
132
133unsigned int
134Target_i386::optimize_tls_reloc(const General_options* options, bool is_local,
135 int r_type)
136{
137 // If we are generating a shared library, then we can't do anything
138 // in the linker.
139 if (options->is_shared())
140 return r_type;
141
142 switch (r_type)
143 {
144 case elfcpp::R_386_TLS_GD:
145 case elfcpp::R_386_TLS_GOTDESC:
146 case elfcpp::R_386_TLS_DESC_CALL:
147 // These are Global-Dynamic which permits fully general TLS
148 // access. Since we know that we are generating an executable,
149 // we can convert this to Initial-Exec. If we also know that
150 // this is a local symbol, we can further switch to Local-Exec.
151 if (is_local)
152 return elfcpp::R_386_TLS_LE_32;
153 return elfcpp::R_386_TLS_IE_32;
154
155 case elfcpp::R_386_TLS_LDM:
156 // This is Local-Dynamic, which refers to a local symbol in the
157 // dynamic TLS block. Since we know that we generating an
158 // executable, we can switch to Local-Exec.
159 return elfcpp::R_386_TLS_LE_32;
160
161 case elfcpp::R_386_TLS_LDO_32:
162 // Another type of Local-Dynamic relocation.
163 return elfcpp::R_386_TLS_LE;
164
165 case elfcpp::R_386_TLS_IE:
166 case elfcpp::R_386_TLS_GOTIE:
167 case elfcpp::R_386_TLS_IE_32:
168 // These are Initial-Exec relocs which get the thread offset
169 // from the GOT. If we know that we are linking against the
170 // local symbol, we can switch to Local-Exec, which links the
171 // thread offset into the instruction.
172 if (is_local)
173 return elfcpp::R_386_TLS_LE_32;
174 return r_type;
175
176 case elfcpp::R_386_TLS_LE:
177 case elfcpp::R_386_TLS_LE_32:
178 // When we already have Local-Exec, there is nothing further we
179 // can do.
180 return r_type;
181
182 default:
183 abort();
184 }
185}
186
187// Scan a relocation for a local symbol.
188
189inline void
190Target_i386::Scan::local(const General_options& options,
191 Sized_object<32, false>* object,
192 const elfcpp::Rel<32, false>&, unsigned int r_type,
193 const elfcpp::Sym<32, false>&)
194{
195 switch (r_type)
196 {
197 case elfcpp::R_386_NONE:
198 case elfcpp::R_386_GNU_VTINHERIT:
199 case elfcpp::R_386_GNU_VTENTRY:
200 break;
201
202 case elfcpp::R_386_32:
203 case elfcpp::R_386_16:
204 case elfcpp::R_386_8:
205 // FIXME: If we are generating a shared object we need to copy
206 // this relocation into the object.
207 break;
208
209 case elfcpp::R_386_PC32:
210 case elfcpp::R_386_PC16:
211 case elfcpp::R_386_PC8:
212 break;
213
214 case elfcpp::R_386_COPY:
215 case elfcpp::R_386_GLOB_DAT:
216 case elfcpp::R_386_JUMP_SLOT:
217 case elfcpp::R_386_RELATIVE:
218 case elfcpp::R_386_TLS_TPOFF:
219 case elfcpp::R_386_TLS_DTPMOD32:
220 case elfcpp::R_386_TLS_DTPOFF32:
221 case elfcpp::R_386_TLS_TPOFF32:
222 case elfcpp::R_386_TLS_DESC:
223 fprintf(stderr, _("%s: %s: unexpected reloc %u in object file\n"),
224 program_name, object->name().c_str(), r_type);
225 gold_exit(false);
226 break;
227
228 case elfcpp::R_386_TLS_IE:
229 case elfcpp::R_386_TLS_GOTIE:
230 case elfcpp::R_386_TLS_LE:
231 case elfcpp::R_386_TLS_GD:
232 case elfcpp::R_386_TLS_LDM:
233 case elfcpp::R_386_TLS_LDO_32:
234 case elfcpp::R_386_TLS_IE_32:
235 case elfcpp::R_386_TLS_LE_32:
236 case elfcpp::R_386_TLS_GOTDESC:
237 case elfcpp::R_386_TLS_DESC_CALL:
238 r_type = Target_i386::optimize_tls_reloc(&options, true, r_type);
239 switch (r_type)
240 {
241 case elfcpp::R_386_TLS_LE:
242 case elfcpp::R_386_TLS_LE_32:
243 // FIXME: If generating a shared object, we need to copy
244 // this relocation into the object.
245 break;
246
247 case elfcpp::R_386_TLS_IE:
248 case elfcpp::R_386_TLS_GOTIE:
249 case elfcpp::R_386_TLS_GD:
250 case elfcpp::R_386_TLS_LDM:
251 case elfcpp::R_386_TLS_LDO_32:
252 case elfcpp::R_386_TLS_IE_32:
253 case elfcpp::R_386_TLS_GOTDESC:
254 case elfcpp::R_386_TLS_DESC_CALL:
255 fprintf(stderr,
256 _("%s: %s: unsupported reloc %u against local symbol\n"),
257 program_name, object->name().c_str(), r_type);
258 break;
259 }
260 break;
261
262 case elfcpp::R_386_GOT32:
263 case elfcpp::R_386_PLT32:
264 case elfcpp::R_386_GOTOFF:
265 case elfcpp::R_386_GOTPC:
266 case elfcpp::R_386_32PLT:
267 case elfcpp::R_386_TLS_GD_32:
268 case elfcpp::R_386_TLS_GD_PUSH:
269 case elfcpp::R_386_TLS_GD_CALL:
270 case elfcpp::R_386_TLS_GD_POP:
271 case elfcpp::R_386_TLS_LDM_32:
272 case elfcpp::R_386_TLS_LDM_PUSH:
273 case elfcpp::R_386_TLS_LDM_CALL:
274 case elfcpp::R_386_TLS_LDM_POP:
275 case elfcpp::R_386_USED_BY_INTEL_200:
276 default:
277 fprintf(stderr, _("%s: %s: unsupported reloc %u against local symbol\n"),
278 program_name, object->name().c_str(), r_type);
279 break;
280 }
281}
282
283// Scan a relocation for a global symbol.
284
285inline void
286Target_i386::Scan::global(const General_options& options,
287 Sized_object<32, false>* object,
288 const elfcpp::Rel<32, false>&, unsigned int r_type,
289 Symbol* gsym)
290{
291 switch (r_type)
292 {
293 case elfcpp::R_386_NONE:
294 case elfcpp::R_386_GNU_VTINHERIT:
295 case elfcpp::R_386_GNU_VTENTRY:
296 break;
297
298 case elfcpp::R_386_32:
299 case elfcpp::R_386_PC32:
300 case elfcpp::R_386_16:
301 case elfcpp::R_386_PC16:
302 case elfcpp::R_386_8:
303 case elfcpp::R_386_PC8:
304 // FIXME: If we are generating a shared object we may need to
305 // copy this relocation into the object. If this symbol is
306 // defined in a shared object, we may need to copy this
307 // relocation in order to avoid a COPY relocation.
308 break;
309
310 case elfcpp::R_386_COPY:
311 case elfcpp::R_386_GLOB_DAT:
312 case elfcpp::R_386_JUMP_SLOT:
313 case elfcpp::R_386_RELATIVE:
314 case elfcpp::R_386_TLS_TPOFF:
315 case elfcpp::R_386_TLS_DTPMOD32:
316 case elfcpp::R_386_TLS_DTPOFF32:
317 case elfcpp::R_386_TLS_TPOFF32:
318 case elfcpp::R_386_TLS_DESC:
319 fprintf(stderr, _("%s: %s: unexpected reloc %u in object file\n"),
320 program_name, object->name().c_str(), r_type);
321 gold_exit(false);
322 break;
323
324 case elfcpp::R_386_TLS_IE:
325 case elfcpp::R_386_TLS_GOTIE:
326 case elfcpp::R_386_TLS_LE:
327 case elfcpp::R_386_TLS_GD:
328 case elfcpp::R_386_TLS_LDM:
329 case elfcpp::R_386_TLS_LDO_32:
330 case elfcpp::R_386_TLS_IE_32:
331 case elfcpp::R_386_TLS_LE_32:
332 case elfcpp::R_386_TLS_GOTDESC:
333 case elfcpp::R_386_TLS_DESC_CALL:
334 r_type = Target_i386::optimize_tls_reloc(&options,
335 !gsym->in_dynsym(),
336 r_type);
337 switch (r_type)
338 {
339 case elfcpp::R_386_TLS_LE:
340 case elfcpp::R_386_TLS_LE_32:
341 // FIXME: If generating a shared object, we need to copy
342 // this relocation into the object.
343 break;
344
345 case elfcpp::R_386_TLS_IE:
346 case elfcpp::R_386_TLS_GOTIE:
347 case elfcpp::R_386_TLS_GD:
348 case elfcpp::R_386_TLS_LDM:
349 case elfcpp::R_386_TLS_LDO_32:
350 case elfcpp::R_386_TLS_IE_32:
351 case elfcpp::R_386_TLS_GOTDESC:
352 case elfcpp::R_386_TLS_DESC_CALL:
353 fprintf(stderr,
354 _("%s: %s: unsupported reloc %u against global symbol %s\n"),
355 program_name, object->name().c_str(), r_type, gsym->name());
356 break;
357 }
358 break;
359
360 case elfcpp::R_386_GOT32:
361 case elfcpp::R_386_PLT32:
362 case elfcpp::R_386_GOTOFF:
363 case elfcpp::R_386_GOTPC:
364 case elfcpp::R_386_32PLT:
365 case elfcpp::R_386_TLS_GD_32:
366 case elfcpp::R_386_TLS_GD_PUSH:
367 case elfcpp::R_386_TLS_GD_CALL:
368 case elfcpp::R_386_TLS_GD_POP:
369 case elfcpp::R_386_TLS_LDM_32:
370 case elfcpp::R_386_TLS_LDM_PUSH:
371 case elfcpp::R_386_TLS_LDM_CALL:
372 case elfcpp::R_386_TLS_LDM_POP:
373 case elfcpp::R_386_USED_BY_INTEL_200:
374 default:
375 fprintf(stderr,
376 _("%s: %s: unsupported reloc %u against global symbol %s\n"),
377 program_name, object->name().c_str(), r_type, gsym->name());
378 break;
379 }
380}
381
382// Scan relocations for a section.
383
384void
385Target_i386::scan_relocs(const General_options& options,
386 Symbol_table* symtab,
387 Sized_object<32, false>* object,
388 unsigned int sh_type,
389 const unsigned char* prelocs,
390 size_t reloc_count,
391 size_t local_symbol_count,
392 const unsigned char* plocal_symbols,
393 Symbol** global_symbols)
394{
395 if (sh_type == elfcpp::SHT_RELA)
396 {
397 fprintf(stderr, _("%s: %s: unsupported RELA reloc section\n"),
398 program_name, object->name().c_str());
399 gold_exit(false);
400 }
401
402 gold::scan_relocs<32, false, elfcpp::SHT_REL, Target_i386::Scan>(
403 options,
404 symtab,
405 object,
406 prelocs,
407 reloc_count,
408 local_symbol_count,
409 plocal_symbols,
410 global_symbols);
411}
412
61ba1cf9
ILT
413// Perform a relocation.
414
415inline void
92e059d8
ILT
416Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
417 size_t relnum,
418 const elfcpp::Rel<32, false>& rel,
419 unsigned int r_type,
420 Sized_symbol<32>* gsym,
421 elfcpp::Elf_types<32>::Elf_Addr value,
422 unsigned char* view,
423 elfcpp::Elf_types<32>::Elf_Addr address,
424 off_t view_size)
61ba1cf9
ILT
425{
426 switch (r_type)
427 {
428 case elfcpp::R_386_NONE:
92e059d8
ILT
429 case elfcpp::R_386_GNU_VTINHERIT:
430 case elfcpp::R_386_GNU_VTENTRY:
61ba1cf9
ILT
431 break;
432
433 case elfcpp::R_386_32:
92e059d8 434 Relocate_functions<32, false>::rel32(view, value);
61ba1cf9
ILT
435 break;
436
437 case elfcpp::R_386_PC32:
92e059d8
ILT
438 Relocate_functions<32, false>::pcrel32(view, value, address);
439 break;
440
441 case elfcpp::R_386_16:
442 Relocate_functions<32, false>::rel16(view, value);
443 break;
444
445 case elfcpp::R_386_PC16:
446 Relocate_functions<32, false>::pcrel16(view, value, address);
61ba1cf9
ILT
447 break;
448
92e059d8
ILT
449 case elfcpp::R_386_8:
450 Relocate_functions<32, false>::rel8(view, value);
451 break;
452
453 case elfcpp::R_386_PC8:
454 Relocate_functions<32, false>::pcrel8(view, value, address);
455 break;
456
457 case elfcpp::R_386_COPY:
458 case elfcpp::R_386_GLOB_DAT:
459 case elfcpp::R_386_JUMP_SLOT:
460 case elfcpp::R_386_RELATIVE:
461 case elfcpp::R_386_TLS_TPOFF:
462 case elfcpp::R_386_TLS_DTPMOD32:
463 case elfcpp::R_386_TLS_DTPOFF32:
464 case elfcpp::R_386_TLS_TPOFF32:
465 case elfcpp::R_386_TLS_DESC:
466 fprintf(stderr, _("%s: %s: unexpected reloc %u in object file\n"),
467 program_name,
468 relinfo->location(relnum, rel.get_r_offset()).c_str(),
469 r_type);
470 gold_exit(false);
471 break;
472
473 case elfcpp::R_386_TLS_IE:
474 case elfcpp::R_386_TLS_GOTIE:
475 case elfcpp::R_386_TLS_LE:
476 case elfcpp::R_386_TLS_GD:
477 case elfcpp::R_386_TLS_LDM:
478 case elfcpp::R_386_TLS_LDO_32:
479 case elfcpp::R_386_TLS_IE_32:
480 case elfcpp::R_386_TLS_LE_32:
481 case elfcpp::R_386_TLS_GOTDESC:
482 case elfcpp::R_386_TLS_DESC_CALL:
483 Target_i386::Relocate::relocate_tls(relinfo, relnum, rel, r_type,
484 gsym, value, view, address,
485 view_size);
486 break;
487
488 case elfcpp::R_386_GOT32:
489 case elfcpp::R_386_PLT32:
490 case elfcpp::R_386_GOTOFF:
491 case elfcpp::R_386_GOTPC:
492 case elfcpp::R_386_32PLT:
493 case elfcpp::R_386_TLS_GD_32:
494 case elfcpp::R_386_TLS_GD_PUSH:
495 case elfcpp::R_386_TLS_GD_CALL:
496 case elfcpp::R_386_TLS_GD_POP:
497 case elfcpp::R_386_TLS_LDM_32:
498 case elfcpp::R_386_TLS_LDM_PUSH:
499 case elfcpp::R_386_TLS_LDM_CALL:
500 case elfcpp::R_386_TLS_LDM_POP:
501 case elfcpp::R_386_USED_BY_INTEL_200:
61ba1cf9
ILT
502 default:
503 fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
92e059d8
ILT
504 program_name,
505 relinfo->location(relnum, rel.get_r_offset()).c_str(),
506 r_type);
61ba1cf9 507 // gold_exit(false);
92e059d8
ILT
508 break;
509 }
510}
511
512// Perform a TLS relocation.
513
514inline void
515Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
516 size_t relnum,
517 const elfcpp::Rel<32, false>& rel,
518 unsigned int r_type,
519 Sized_symbol<32>* gsym,
520 elfcpp::Elf_types<32>::Elf_Addr value,
521 unsigned char* view,
522 elfcpp::Elf_types<32>::Elf_Addr,
523 off_t view_size)
524{
525 Output_segment* tls_segment = relinfo->layout->tls_segment();
526 if (tls_segment == NULL)
527 {
528 fprintf(stderr, _("%s: %s: TLS reloc but no TLS segment\n"),
529 program_name,
530 relinfo->location(relnum, rel.get_r_offset()).c_str());
531 gold_exit(false);
532 }
533
534 const bool is_local = gsym == NULL || !gsym->in_dynsym();
535 const unsigned int opt_r_type =
536 Target_i386::optimize_tls_reloc(relinfo->options, is_local, r_type);
537 switch (r_type)
538 {
539 case elfcpp::R_386_TLS_LE_32:
540 value = tls_segment->vaddr() + tls_segment->memsz() - value;
541 Relocate_functions<32, false>::rel32(view, value);
542 break;
543
544 case elfcpp::R_386_TLS_LE:
545 value = value - (tls_segment->vaddr() + tls_segment->memsz());
546 Relocate_functions<32, false>::rel32(view, value);
547 break;
548
549 case elfcpp::R_386_TLS_IE:
550 case elfcpp::R_386_TLS_GOTIE:
551 case elfcpp::R_386_TLS_IE_32:
552 if (opt_r_type == elfcpp::R_386_TLS_LE_32)
553 {
554 Target_i386::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
555 rel, r_type, value, view,
556 view_size);
557 break;
558 }
559 fprintf(stderr, _("%s: %s: unsupported reloc type %u\n"),
560 program_name,
561 relinfo->location(relnum, rel.get_r_offset()).c_str(),
562 r_type);
563 // gold_exit(false);
564 break;
565
566 case elfcpp::R_386_TLS_GD:
567 case elfcpp::R_386_TLS_LDM:
568 case elfcpp::R_386_TLS_LDO_32:
569 case elfcpp::R_386_TLS_GOTDESC:
570 case elfcpp::R_386_TLS_DESC_CALL:
571 fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
572 program_name,
573 relinfo->location(relnum, rel.get_r_offset()).c_str(),
574 r_type);
575 // gold_exit(false);
576 break;
577 }
578}
579
580// Do a relocation in which we convert a TLS Initial-Exec to a
581// Local-Exec.
582
583inline void
584Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
585 size_t relnum,
586 Output_segment* tls_segment,
587 const elfcpp::Rel<32, false>& rel,
588 unsigned int r_type,
589 elfcpp::Elf_types<32>::Elf_Addr value,
590 unsigned char* view,
591 off_t view_size)
592{
593 // We have to actually change the instructions, which means that we
594 // need to examine the opcodes to figure out which instruction we
595 // are looking at.
596 if (r_type == elfcpp::R_386_TLS_IE)
597 {
598 // movl %gs:XX,%eax ==> movl $YY,%eax
599 // movl %gs:XX,%reg ==> movl $YY,%reg
600 // addl %gs:XX,%reg ==> addl $YY,%reg
601 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -1);
602 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 4);
603
604 unsigned char op1 = view[-1];
605 if (op1 == 0xa1)
606 {
607 // movl XX,%eax ==> movl $YY,%eax
608 view[-1] = 0xb8;
609 }
610 else
611 {
612 Target_i386::Relocate::check_range(relinfo, relnum, rel,
613 view_size, -2);
614
615 unsigned char op2 = view[-2];
616 if (op2 == 0x8b)
617 {
618 // movl XX,%reg ==> movl $YY,%reg
619 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
620 (op1 & 0xc7) == 0x05);
621 view[-2] = 0xc7;
622 view[-1] = 0xc0 | ((op1 >> 3) & 7);
623 }
624 else if (op2 == 0x03)
625 {
626 // addl XX,%reg ==> addl $YY,%reg
627 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
628 (op1 & 0xc7) == 0x05);
629 view[-2] = 0x81;
630 view[-1] = 0xc0 | ((op1 >> 3) & 7);
631 }
632 else
633 Target_i386::Relocate::check_tls(relinfo, relnum, rel, 0);
634 }
635 }
636 else
637 {
638 // subl %gs:XX(%reg1),%reg2 ==> subl $YY,%reg2
639 // movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2
640 // addl %gs:XX(%reg1),%reg2 ==> addl $YY,$reg2
641 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -2);
642 Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 4);
643
644 unsigned char op1 = view[-1];
645 unsigned char op2 = view[-2];
646 Target_i386::Relocate::check_tls(relinfo, relnum, rel,
647 (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
648 if (op2 == 0x8b)
649 {
650 // movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2
651 view[-2] = 0xc7;
652 view[-1] = 0xc0 | ((op1 >> 3) & 7);
653 }
654 else if (op2 == 0x2b)
655 {
656 // subl %gs:XX(%reg1),%reg2 ==> subl $YY,%reg2
657 view[-2] = 0x81;
658 view[-1] = 0xe8 | ((op1 >> 3) & 7);
659 }
660 else if (op2 == 0x03)
661 {
662 // addl %gs:XX(%reg1),%reg2 ==> addl $YY,$reg2
663 view[-2] = 0x81;
664 view[-1] = 0xc0 | ((op1 >> 3) & 7);
665 }
666 else
667 Target_i386::Relocate::check_tls(relinfo, relnum, rel, 0);
668 }
669
670 if (r_type == elfcpp::R_386_TLS_IE_32)
671 value = tls_segment->vaddr() + tls_segment->memsz() - value;
672 else // elfcpp::R_386_TLS_IE, elfcpp::R_386_TLS_GOTIE
673 value = value - (tls_segment->vaddr() + tls_segment->memsz());
674
675 Relocate_functions<32, false>::rel32(view, value);
676}
677
678// Check the range for a TLS relocation.
679
680inline void
681Target_i386::Relocate::check_range(const Relocate_info<32, false>* relinfo,
682 size_t relnum,
683 const elfcpp::Rel<32, false>& rel,
684 off_t view_size, off_t off)
685{
686 off_t offset = rel.get_r_offset() + off;
687 if (offset < 0 || offset > view_size)
688 {
689 fprintf(stderr, _("%s: %s: TLS relocation out of range\n"),
690 program_name,
691 relinfo->location(relnum, rel.get_r_offset()).c_str());
692 gold_exit(false);
693 }
694}
695
696// Check the validity of a TLS relocation. This is like assert.
697
698inline void
699Target_i386::Relocate::check_tls(const Relocate_info<32, false>* relinfo,
700 size_t relnum,
701 const elfcpp::Rel<32, false>& rel,
702 bool valid)
703{
704 if (!valid)
705 {
706 fprintf(stderr,
707 _("%s: %s: TLS relocation against invalid instruction\n"),
708 program_name,
709 relinfo->location(relnum, rel.get_r_offset()).c_str());
710 gold_exit(false);
61ba1cf9
ILT
711 }
712}
713
714// Relocate section data.
715
716void
92e059d8 717Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
61ba1cf9
ILT
718 unsigned int sh_type,
719 const unsigned char* prelocs,
720 size_t reloc_count,
61ba1cf9
ILT
721 unsigned char* view,
722 elfcpp::Elf_types<32>::Elf_Addr address,
723 off_t view_size)
724{
92e059d8 725 assert(sh_type == elfcpp::SHT_REL);
61ba1cf9
ILT
726
727 gold::relocate_section<32, false, elfcpp::SHT_REL, Target_i386::Relocate>(
92e059d8 728 relinfo,
61ba1cf9
ILT
729 prelocs,
730 reloc_count,
61ba1cf9
ILT
731 view,
732 address,
733 view_size);
734}
735
736// The i386 target.
737
738Target_i386 target_i386;
739
14bfc3f5
ILT
740// The selector for i386 object files.
741
742class Target_selector_i386 : public Target_selector
743{
744public:
745 Target_selector_i386()
746 : Target_selector(elfcpp::EM_386, 32, false)
747 { }
748
749 Target*
750 recognize(int machine, int osabi, int abiversion) const;
751};
752
753// Recognize an i386 object file when we already know that the machine
754// number is EM_386.
755
756Target*
757Target_selector_i386::recognize(int, int, int) const
758{
61ba1cf9 759 return &target_i386;
14bfc3f5
ILT
760}
761
762Target_selector_i386 target_selector_i386;
763
764} // End anonymous namespace.
This page took 0.076316 seconds and 4 git commands to generate.