1 //===- X86Relocator.cpp -------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "X86Relocator.h"
10 #include "X86RelocationFunctions.h"
11
12 #include <mcld/LinkerConfig.h>
13 #include <mcld/IRBuilder.h>
14 #include <mcld/Support/MsgHandling.h>
15 #include <mcld/LD/LDSymbol.h>
16 #include <mcld/Object/ObjectBuilder.h>
17
18 #include <llvm/ADT/Twine.h>
19 #include <llvm/Support/DataTypes.h>
20 #include <llvm/Support/ELF.h>
21
22 using namespace mcld;
23
24 //===--------------------------------------------------------------------===//
25 // Relocation Functions and Tables
26 //===--------------------------------------------------------------------===//
27 DECL_X86_32_APPLY_RELOC_FUNCS
28
29 /// the prototype of applying function
30 typedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc,
31 X86_32Relocator& pParent);
32
33 // the table entry of applying functions
34 struct X86_32ApplyFunctionTriple
35 {
36 X86_32ApplyFunctionType func;
37 unsigned int type;
38 const char* name;
39 unsigned int size;
40 };
41
42 // declare the table of applying functions
43 static const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = {
44 DECL_X86_32_APPLY_RELOC_FUNC_PTRS
45 };
46
47 //===--------------------------------------------------------------------===//
48 // X86Relocator
49 //===--------------------------------------------------------------------===//
X86Relocator(const LinkerConfig & pConfig)50 X86Relocator::X86Relocator(const LinkerConfig& pConfig)
51 : Relocator(pConfig) {
52 }
53
~X86Relocator()54 X86Relocator::~X86Relocator()
55 {
56 }
57
scanRelocation(Relocation & pReloc,IRBuilder & pLinker,Module & pModule,LDSection & pSection)58 void X86Relocator::scanRelocation(Relocation& pReloc,
59 IRBuilder& pLinker,
60 Module& pModule,
61 LDSection& pSection)
62 {
63 if (LinkerConfig::Object == config().codeGenType())
64 return;
65 // rsym - The relocation target symbol
66 ResolveInfo* rsym = pReloc.symInfo();
67 assert(NULL != rsym &&
68 "ResolveInfo of relocation not set while scanRelocation");
69
70 pReloc.updateAddend();
71 assert(NULL != pSection.getLink());
72 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
73 return;
74
75 // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
76 // entries should be created.
77 if (rsym->isLocal()) // rsym is local
78 scanLocalReloc(pReloc, pLinker, pModule, pSection);
79 else // rsym is external
80 scanGlobalReloc(pReloc, pLinker, pModule, pSection);
81
82 // check if we should issue undefined reference for the relocation target
83 // symbol
84 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
85 fatal(diag::undefined_reference) << rsym->name();
86 }
87
addCopyReloc(ResolveInfo & pSym,X86GNULDBackend & pTarget)88 void X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget)
89 {
90 Relocation& rel_entry = *pTarget.getRelDyn().consumeEntry();
91 rel_entry.setType(pTarget.getCopyRelType());
92 assert(pSym.outSymbol()->hasFragRef());
93 rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
94 rel_entry.setSymInfo(&pSym);
95 }
96
97 /// defineSymbolforCopyReloc
98 /// For a symbol needing copy relocation, define a copy symbol in the BSS
99 /// section and all other reference to this symbol should refer to this
100 /// copy.
101 /// @note This is executed at `scan relocation' stage.
defineSymbolforCopyReloc(IRBuilder & pBuilder,const ResolveInfo & pSym,X86GNULDBackend & pTarget)102 LDSymbol& X86Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
103 const ResolveInfo& pSym,
104 X86GNULDBackend& pTarget)
105 {
106 // get or create corresponding BSS LDSection
107 LDSection* bss_sect_hdr = NULL;
108 ELFFileFormat* file_format = pTarget.getOutputFormat();
109 if (ResolveInfo::ThreadLocal == pSym.type())
110 bss_sect_hdr = &file_format->getTBSS();
111 else
112 bss_sect_hdr = &file_format->getBSS();
113
114 // get or create corresponding BSS SectionData
115 assert(NULL != bss_sect_hdr);
116 SectionData* bss_section = NULL;
117 if (bss_sect_hdr->hasSectionData())
118 bss_section = bss_sect_hdr->getSectionData();
119 else
120 bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
121
122 // Determine the alignment by the symbol value
123 // FIXME: here we use the largest alignment
124 uint32_t addralign = config().targets().bitclass() / 8;
125
126 // allocate space in BSS for the copy symbol
127 Fragment* frag = new FillFragment(0x0, 1, pSym.size());
128 uint64_t size = ObjectBuilder::AppendFragment(*frag,
129 *bss_section,
130 addralign);
131 bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
132
133 // change symbol binding to Global if it's a weak symbol
134 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
135 if (binding == ResolveInfo::Weak)
136 binding = ResolveInfo::Global;
137
138 // Define the copy symbol in the bss section and resolve it
139 LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
140 pSym.name(),
141 (ResolveInfo::Type)pSym.type(),
142 ResolveInfo::Define,
143 binding,
144 pSym.size(), // size
145 0x0, // value
146 FragmentRef::Create(*frag, 0x0),
147 (ResolveInfo::Visibility)pSym.other());
148
149 // output all other alias symbols if any
150 Module &pModule = pBuilder.getModule();
151 Module::AliasList* alias_list = pModule.getAliasList(pSym);
152 if (NULL!=alias_list) {
153 Module::alias_iterator it, it_e=alias_list->end();
154 for (it=alias_list->begin(); it!=it_e; ++it) {
155 const ResolveInfo* alias = *it;
156 if (alias!=&pSym && alias->isDyn()) {
157 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
158 alias->name(),
159 (ResolveInfo::Type)alias->type(),
160 ResolveInfo::Define,
161 binding,
162 alias->size(), // size
163 0x0, // value
164 FragmentRef::Create(*frag, 0x0),
165 (ResolveInfo::Visibility)alias->other());
166 }
167 }
168 }
169
170 return *cpy_sym;
171 }
172
173 //===--------------------------------------------------------------------===//
174 // X86_32Relocator
175 //===--------------------------------------------------------------------===//
X86_32Relocator(X86_32GNULDBackend & pParent,const LinkerConfig & pConfig)176 X86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent,
177 const LinkerConfig& pConfig)
178 : X86Relocator(pConfig), m_Target(pParent) {
179 }
180
181 Relocator::Result
applyRelocation(Relocation & pRelocation)182 X86_32Relocator::applyRelocation(Relocation& pRelocation)
183 {
184 Relocation::Type type = pRelocation.type();
185
186 if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) {
187 return Unknown;
188 }
189
190 // apply the relocation
191 return X86_32ApplyFunctions[type].func(pRelocation, *this);
192 }
193
getName(Relocation::Type pType) const194 const char* X86_32Relocator::getName(Relocation::Type pType) const
195 {
196 return X86_32ApplyFunctions[pType].name;
197 }
198
getSize(Relocation::Type pType) const199 Relocator::Size X86_32Relocator::getSize(Relocation::Type pType) const
200 {
201 return X86_32ApplyFunctions[pType].size;;
202 }
203
scanLocalReloc(Relocation & pReloc,IRBuilder & pBuilder,Module & pModule,LDSection & pSection)204 void X86_32Relocator::scanLocalReloc(Relocation& pReloc,
205 IRBuilder& pBuilder,
206 Module& pModule,
207 LDSection& pSection)
208 {
209 // rsym - The relocation target symbol
210 ResolveInfo* rsym = pReloc.symInfo();
211
212 switch(pReloc.type()){
213
214 case llvm::ELF::R_386_32:
215 case llvm::ELF::R_386_16:
216 case llvm::ELF::R_386_8:
217 // If buiding PIC object (shared library or PIC executable),
218 // a dynamic relocations with RELATIVE type to this location is needed.
219 // Reserve an entry in .rel.dyn
220 if (config().isCodeIndep()) {
221 getTarget().getRelDyn().reserveEntry();
222 // set Rel bit
223 rsym->setReserved(rsym->reserved() | ReserveRel);
224 getTarget().checkAndSetHasTextRel(*pSection.getLink());
225 }
226 return;
227
228 case llvm::ELF::R_386_PLT32:
229 return;
230
231 case llvm::ELF::R_386_GOTOFF:
232 case llvm::ELF::R_386_GOTPC:
233 // FIXME: A GOT section is needed
234 return;
235
236 case llvm::ELF::R_386_GOT32:
237 // Symbol needs GOT entry, reserve entry in .got
238 // return if we already create GOT for this symbol
239 if (rsym->reserved() & (ReserveGOT | GOTRel))
240 return;
241 // FIXME: check STT_GNU_IFUNC symbol
242 getTarget().getGOT().reserve();
243
244 // If the GOT is used in statically linked binaries,
245 // the GOT entry is enough and no relocation is needed.
246 if (config().isCodeStatic()) {
247 rsym->setReserved(rsym->reserved() | ReserveGOT);
248 return;
249 }
250 // If building shared object or the symbol is undefined, a dynamic
251 // relocation is needed to relocate this GOT entry. Reserve an
252 // entry in .rel.dyn
253 if (LinkerConfig::DynObj ==
254 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
255 getTarget().getRelDyn().reserveEntry();
256 // set GOTRel bit
257 rsym->setReserved(rsym->reserved() | GOTRel);
258 return;
259 }
260 // set GOT bit
261 rsym->setReserved(rsym->reserved() | ReserveGOT);
262 return;
263
264 case llvm::ELF::R_386_PC32:
265 case llvm::ELF::R_386_PC16:
266 case llvm::ELF::R_386_PC8:
267 return;
268
269 case llvm::ELF::R_386_TLS_GD: {
270 // FIXME: no linker optimization for TLS relocation
271 if (rsym->reserved() & GOTRel)
272 return;
273 getTarget().getGOT().reserve(2);
274 // reserve an rel entry
275 getTarget().getRelDyn().reserveEntry();
276 // set GOTRel bit
277 rsym->setReserved(rsym->reserved() | GOTRel);
278 // define the section symbol for .tdata or .tbss
279 // the target symbol of the created dynamic relocation should be the
280 // section symbol of the section which this symbol defined. so we
281 // need to define that section symbol here
282 ELFFileFormat* file_format = getTarget().getOutputFormat();
283 const LDSection* sym_sect =
284 &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
285 if (&file_format->getTData() == sym_sect) {
286 if (!getTarget().hasTDATASymbol())
287 getTarget().setTDATASymbol(*pModule.getSectionSymbolSet().get(*sym_sect));
288 }
289 else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
290 if (!getTarget().hasTBSSSymbol())
291 getTarget().setTBSSSymbol(*pModule.getSectionSymbolSet().get(*sym_sect));
292 }
293 else
294 error(diag::invalid_tls) << rsym->name() << sym_sect->name();
295 return;
296 }
297
298 case llvm::ELF::R_386_TLS_LDM:
299 getTLSModuleID();
300 return;
301
302 case llvm::ELF::R_386_TLS_LDO_32:
303 return;
304
305 case llvm::ELF::R_386_TLS_IE:
306 getTarget().setHasStaticTLS();
307 // if buildint shared object, a RELATIVE dynamic relocation is needed
308 if (LinkerConfig::DynObj == config().codeGenType()) {
309 getTarget().getRelDyn().reserveEntry();
310 rsym->setReserved(rsym->reserved() | ReserveRel);
311 getTarget().checkAndSetHasTextRel(*pSection.getLink());
312 } else {
313 // for local sym, we can convert ie to le if not building shared object
314 convertTLSIEtoLE(pReloc, pSection);
315 return;
316 }
317 if (rsym->reserved() & GOTRel)
318 return;
319 // reserve got and dyn relocation entries for tp-relative offset
320 getTarget().getGOT().reserve();
321 getTarget().getRelDyn().reserveEntry();
322 // set GOTRel bit
323 rsym->setReserved(rsym->reserved() | GOTRel);
324 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
325 return;
326
327 case llvm::ELF::R_386_TLS_GOTIE:
328 getTarget().setHasStaticTLS();
329 if (rsym->reserved() & GOTRel)
330 return;
331 // reserve got and dyn relocation entries for tp-relative offset
332 getTarget().getGOT().reserve();
333 getTarget().getRelDyn().reserveEntry();
334 // set GOTRel bit
335 rsym->setReserved(rsym->reserved() | GOTRel);
336 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
337 return;
338
339 case llvm::ELF::R_386_TLS_LE:
340 case llvm::ELF::R_386_TLS_LE_32:
341 getTarget().setHasStaticTLS();
342 // if buildint shared object, a dynamic relocation is needed
343 if (LinkerConfig::DynObj == config().codeGenType()) {
344 getTarget().getRelDyn().reserveEntry();
345 rsym->setReserved(rsym->reserved() | ReserveRel);
346 getTarget().checkAndSetHasTextRel(*pSection.getLink());
347 // the target symbol of the dynamic relocation is rsym, so we need to
348 // emit it into .dynsym
349 assert(NULL != rsym->outSymbol());
350 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
351 }
352 return;
353
354 default:
355 fatal(diag::unsupported_relocation) << (int)pReloc.type()
356 << "mclinker@googlegroups.com";
357 break;
358 } // end switch
359 }
360
scanGlobalReloc(Relocation & pReloc,IRBuilder & pBuilder,Module & pModule,LDSection & pSection)361 void X86_32Relocator::scanGlobalReloc(Relocation& pReloc,
362 IRBuilder& pBuilder,
363 Module& pModule,
364 LDSection& pSection)
365 {
366 // rsym - The relocation target symbol
367 ResolveInfo* rsym = pReloc.symInfo();
368
369 switch(pReloc.type()) {
370 case llvm::ELF::R_386_32:
371 case llvm::ELF::R_386_16:
372 case llvm::ELF::R_386_8:
373 // Absolute relocation type, symbol may needs PLT entry or
374 // dynamic relocation entry
375 if (getTarget().symbolNeedsPLT(*rsym)) {
376 // create plt for this symbol if it does not have one
377 if (!(rsym->reserved() & ReservePLT)){
378 // Symbol needs PLT entry, we need to reserve a PLT entry
379 // and the corresponding GOT and dynamic relocation entry
380 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
381 // when calling X86PLT->reserveEntry())
382 getTarget().getPLT().reserveEntry();
383 getTarget().getGOTPLT().reserve();
384 getTarget().getRelPLT().reserveEntry();
385 // set PLT bit
386 rsym->setReserved(rsym->reserved() | ReservePLT);
387 }
388 }
389
390 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
391 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
392 getTarget().getRelDyn().reserveEntry();
393 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
394 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
395 addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
396 }
397 else {
398 // set Rel bit
399 rsym->setReserved(rsym->reserved() | ReserveRel);
400 getTarget().checkAndSetHasTextRel(pSection);
401 }
402 }
403 return;
404
405 case llvm::ELF::R_386_GOTOFF:
406 case llvm::ELF::R_386_GOTPC: {
407 // FIXME: A GOT section is needed
408 return;
409 }
410
411 case llvm::ELF::R_386_PLT32:
412 // A PLT entry is needed when building shared library
413
414 // return if we already create plt for this symbol
415 if (rsym->reserved() & ReservePLT)
416 return;
417
418 // if the symbol's value can be decided at link time, then no need plt
419 if (getTarget().symbolFinalValueIsKnown(*rsym))
420 return;
421
422 // if symbol is defined in the ouput file and it's not
423 // preemptible, no need plt
424 if (rsym->isDefine() && !rsym->isDyn() &&
425 !getTarget().isSymbolPreemptible(*rsym)) {
426 return;
427 }
428
429 // Symbol needs PLT entry, we need to reserve a PLT entry
430 // and the corresponding GOT and dynamic relocation entry
431 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
432 // when calling X86PLT->reserveEntry())
433 getTarget().getPLT().reserveEntry();
434 getTarget().getGOTPLT().reserve();
435 getTarget().getRelPLT().reserveEntry();
436 // set PLT bit
437 rsym->setReserved(rsym->reserved() | ReservePLT);
438 return;
439
440 case llvm::ELF::R_386_GOT32:
441 // Symbol needs GOT entry, reserve entry in .got
442 // return if we already create GOT for this symbol
443 if (rsym->reserved() & (ReserveGOT | GOTRel))
444 return;
445 getTarget().getGOT().reserve();
446
447 // If the GOT is used in statically linked binaries,
448 // the GOT entry is enough and no relocation is needed.
449 if (config().isCodeStatic()) {
450 rsym->setReserved(rsym->reserved() | ReserveGOT);
451 return;
452 }
453 // If building shared object or the symbol is undefined, a dynamic
454 // relocation is needed to relocate this GOT entry. Reserve an
455 // entry in .rel.dyn
456 if (LinkerConfig::DynObj ==
457 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
458 getTarget().getRelDyn().reserveEntry();
459 // set GOTRel bit
460 rsym->setReserved(rsym->reserved() | GOTRel);
461 return;
462 }
463 // set GOT bit
464 rsym->setReserved(rsym->reserved() | ReserveGOT);
465 return;
466
467 case llvm::ELF::R_386_PC32:
468 case llvm::ELF::R_386_PC16:
469 case llvm::ELF::R_386_PC8:
470
471 if (getTarget().symbolNeedsPLT(*rsym) &&
472 LinkerConfig::DynObj != config().codeGenType()) {
473 // create plt for this symbol if it does not have one
474 if (!(rsym->reserved() & ReservePLT)){
475 // Symbol needs PLT entry, we need to reserve a PLT entry
476 // and the corresponding GOT and dynamic relocation entry
477 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
478 // when calling X86PLT->reserveEntry())
479 getTarget().getPLT().reserveEntry();
480 getTarget().getGOTPLT().reserve();
481 getTarget().getRelPLT().reserveEntry();
482 // set PLT bit
483 rsym->setReserved(rsym->reserved() | ReservePLT);
484 }
485 }
486
487 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
488 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
489 getTarget().getRelDyn().reserveEntry();
490 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
491 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
492 addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
493 }
494 else {
495 // set Rel bit
496 rsym->setReserved(rsym->reserved() | ReserveRel);
497 getTarget().checkAndSetHasTextRel(pSection);
498 }
499 }
500 return;
501
502 case llvm::ELF::R_386_TLS_GD: {
503 // FIXME: no linker optimization for TLS relocation
504 if (rsym->reserved() & GOTRel)
505 return;
506 // reserve two pairs of got entry and dynamic relocation
507 getTarget().getGOT().reserve(2);
508 getTarget().getRelDyn().reserveEntry(2);
509 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
510 // set GOTRel bit
511 rsym->setReserved(rsym->reserved() | GOTRel);
512 return;
513 }
514
515 case llvm::ELF::R_386_TLS_LDM:
516 getTLSModuleID();
517 return;
518
519 case llvm::ELF::R_386_TLS_LDO_32:
520 return;
521
522 case llvm::ELF::R_386_TLS_IE:
523 getTarget().setHasStaticTLS();
524 // if buildint shared object, a RELATIVE dynamic relocation is needed
525 if (LinkerConfig::DynObj == config().codeGenType()) {
526 getTarget().getRelDyn().reserveEntry();
527 rsym->setReserved(rsym->reserved() | ReserveRel);
528 getTarget().checkAndSetHasTextRel(*pSection.getLink());
529 } else {
530 // for global sym, we can convert ie to le if its final value is known
531 if (getTarget().symbolFinalValueIsKnown(*rsym)) {
532 convertTLSIEtoLE(pReloc, pSection);
533 return;
534 }
535 }
536 if (rsym->reserved() & GOTRel)
537 return;
538 // reserve got and dyn relocation entries for tp-relative offset
539 getTarget().getGOT().reserve();
540 getTarget().getRelDyn().reserveEntry();
541 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
542 // set GOTRel bit
543 rsym->setReserved(rsym->reserved() | GOTRel);
544 return;
545
546 case llvm::ELF::R_386_TLS_GOTIE:
547 getTarget().setHasStaticTLS();
548 if (rsym->reserved() & GOTRel)
549 return;
550 // reserve got and dyn relocation entries for tp-relative offset
551 getTarget().getGOT().reserve();
552 getTarget().getRelDyn().reserveEntry();
553 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
554 // set GOTRel bit
555 rsym->setReserved(rsym->reserved() | GOTRel);
556 return;
557
558 case llvm::ELF::R_386_TLS_LE:
559 case llvm::ELF::R_386_TLS_LE_32:
560 getTarget().setHasStaticTLS();
561 // if buildint shared object, a dynamic relocation is needed
562 if (LinkerConfig::DynObj == config().codeGenType()) {
563 getTarget().getRelDyn().reserveEntry();
564 getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
565 rsym->setReserved(rsym->reserved() | ReserveRel);
566 getTarget().checkAndSetHasTextRel(*pSection.getLink());
567 }
568 return;
569
570 default: {
571 fatal(diag::unsupported_relocation) << (int)pReloc.type()
572 << "mclinker@googlegroups.com";
573 break;
574 }
575 } // end switch
576 }
577
578 // Create a GOT entry for the TLS module index
getTLSModuleID()579 X86_32GOTEntry& X86_32Relocator::getTLSModuleID()
580 {
581 static X86_32GOTEntry* got_entry = NULL;
582 if (NULL != got_entry)
583 return *got_entry;
584
585 // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
586 getTarget().getGOT().reserve(2);
587 got_entry = getTarget().getGOT().consume();
588 getTarget().getGOT().consume()->setValue(0x0);
589
590 getTarget().getRelDyn().reserveEntry();
591 Relocation* rel_entry = getTarget().getRelDyn().consumeEntry();
592 rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
593 rel_entry->targetRef().assign(*got_entry, 0x0);
594 rel_entry->setSymInfo(NULL);
595
596 return *got_entry;
597 }
598
599 /// convert R_386_TLS_IE to R_386_TLS_LE
convertTLSIEtoLE(Relocation & pReloc,LDSection & pSection)600 void X86_32Relocator::convertTLSIEtoLE(Relocation& pReloc,
601 LDSection& pSection)
602 {
603 assert(pReloc.type() == llvm::ELF::R_386_TLS_IE);
604 assert(NULL != pReloc.targetRef().frag());
605
606 // 1. create the fragment references and new relocs
607 uint64_t off = pReloc.targetRef().offset();
608 if (off >= 4)
609 off -= 4;
610 else
611 off = 0;
612
613 FragmentRef* fragref = FragmentRef::Create(*pReloc.targetRef().frag(), off);
614 // TODO: add symbols for R_386_TLS_OPT relocs
615 Relocation* reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT,
616 *fragref,
617 0x0);
618
619 // 2. modify the opcodes to the appropriate ones
620 uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target()));
621 off = pReloc.targetRef().offset() - reloc->targetRef().offset() - 1;
622 if (op[off] == 0xa1) {
623 op[off] = 0xb8;
624 } else {
625 switch (op[off - 1]) {
626 case 0x8b:
627 assert((op[off] & 0xc7) == 0x05);
628 op[off - 1] = 0xc7;
629 op[off] = 0xc0 | ((op[off] >> 3) & 7);
630 break;
631 case 0x03:
632 assert((op[off] & 0xc7) == 0x05);
633 op[off - 1] = 0x81;
634 op[off] = 0xc0 | ((op[off] >> 3) & 7);
635 break;
636 default:
637 assert(0);
638 break;
639 }
640 }
641
642 // 3. insert the new relocs "BEFORE" the original reloc.
643 pSection.getRelocData()->getRelocationList().insert(
644 RelocData::iterator(pReloc), reloc);
645
646 // 4. change the type of the original reloc
647 pReloc.setType(llvm::ELF::R_386_TLS_LE);
648 }
649
650 //===--------------------------------------------------------------------===//
651 // Relocation helper function
652 //===--------------------------------------------------------------------===//
653
654 /// helper_DynRel - Get an relocation entry in .rel.dyn
655 static
helper_DynRel(ResolveInfo * pSym,Fragment & pFrag,uint64_t pOffset,X86Relocator::Type pType,X86_32Relocator & pParent)656 Relocation& helper_DynRel(ResolveInfo* pSym,
657 Fragment& pFrag,
658 uint64_t pOffset,
659 X86Relocator::Type pType,
660 X86_32Relocator& pParent)
661 {
662 X86_32GNULDBackend& ld_backend = pParent.getTarget();
663 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
664 rel_entry.setType(pType);
665 rel_entry.targetRef().assign(pFrag, pOffset);
666 if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym)
667 rel_entry.setSymInfo(0);
668 else
669 rel_entry.setSymInfo(pSym);
670
671 return rel_entry;
672 }
673
674
675 /// helper_use_relative_reloc - Check if symbol can use relocation
676 /// R_386_RELATIVE
677 static bool
helper_use_relative_reloc(const ResolveInfo & pSym,const X86_32Relocator & pFactory)678 helper_use_relative_reloc(const ResolveInfo& pSym,
679 const X86_32Relocator& pFactory)
680
681 {
682 // if symbol is dynamic or undefine or preemptible
683 if (pSym.isDyn() ||
684 pSym.isUndef() ||
685 pFactory.getTarget().isSymbolPreemptible(pSym))
686 return false;
687 return true;
688 }
689
690 static
helper_get_GOT_and_init(Relocation & pReloc,X86_32Relocator & pParent)691 X86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
692 X86_32Relocator& pParent)
693 {
694 // rsym - The relocation target symbol
695 ResolveInfo* rsym = pReloc.symInfo();
696 X86_32GNULDBackend& ld_backend = pParent.getTarget();
697
698 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
699 if (NULL != got_entry)
700 return *got_entry;
701
702 // not found
703 got_entry = ld_backend.getGOT().consume();
704 pParent.getSymGOTMap().record(*rsym, *got_entry);
705
706 // If we first get this GOT entry, we should initialize it.
707 if (rsym->reserved() & X86Relocator::ReserveGOT) {
708 // No corresponding dynamic relocation, initialize to the symbol value.
709 got_entry->setValue(pReloc.symValue());
710 }
711 else if (rsym->reserved() & X86Relocator::GOTRel) {
712 // Initialize got_entry content and the corresponding dynamic relocation.
713 if (helper_use_relative_reloc(*rsym, pParent)) {
714 helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
715 got_entry->setValue(pReloc.symValue());
716 }
717 else {
718 helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
719 got_entry->setValue(0);
720 }
721 }
722 else {
723 fatal(diag::reserve_entry_number_mismatch_got);
724 }
725 return *got_entry;
726 }
727
728
729 static
helper_GOT_ORG(X86_32Relocator & pParent)730 X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
731 {
732 return pParent.getTarget().getGOTPLT().addr();
733 }
734
735
736 static
helper_GOT(Relocation & pReloc,X86_32Relocator & pParent)737 X86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent)
738 {
739 X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
740 X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr();
741 return got_addr + got_entry.getOffset();
742 }
743
744
745 static
helper_get_PLT_and_init(Relocation & pReloc,X86_32Relocator & pParent)746 PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
747 X86_32Relocator& pParent)
748 {
749 // rsym - The relocation target symbol
750 ResolveInfo* rsym = pReloc.symInfo();
751 X86_32GNULDBackend& ld_backend = pParent.getTarget();
752
753 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
754 if (NULL != plt_entry)
755 return *plt_entry;
756
757 // not found
758 plt_entry = ld_backend.getPLT().consume();
759 pParent.getSymPLTMap().record(*rsym, *plt_entry);
760 // If we first get this PLT entry, we should initialize it.
761 if (rsym->reserved() & X86Relocator::ReservePLT) {
762 X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
763 assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
764 gotplt_entry = ld_backend.getGOTPLT().consume();
765 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
766 // init the corresponding rel entry in .rel.plt
767 Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
768 rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
769 rel_entry.targetRef().assign(*gotplt_entry);
770 rel_entry.setSymInfo(rsym);
771 }
772 else {
773 fatal(diag::reserve_entry_number_mismatch_plt);
774 }
775
776 return *plt_entry;
777 }
778
779
780 static
helper_PLT_ORG(X86_32Relocator & pParent)781 X86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent)
782 {
783 return pParent.getTarget().getPLT().addr();
784 }
785
786
787 static
helper_PLT(Relocation & pReloc,X86_32Relocator & pParent)788 X86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent)
789 {
790 PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
791 return helper_PLT_ORG(pParent) + plt_entry.getOffset();
792 }
793
794
795 //=========================================//
796 // Each relocation function implementation //
797 //=========================================//
798
799 // R_386_NONE
none(Relocation & pReloc,X86_32Relocator & pParent)800 X86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent)
801 {
802 return X86Relocator::OK;
803 }
804
805 // R_386_32: S + A
806 // R_386_16
807 // R_386_8
abs(Relocation & pReloc,X86_32Relocator & pParent)808 X86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent)
809 {
810 ResolveInfo* rsym = pReloc.symInfo();
811 Relocator::DWord A = pReloc.target() + pReloc.addend();
812 Relocator::DWord S = pReloc.symValue();
813 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
814 *rsym,
815 (rsym->reserved() & X86Relocator::ReservePLT),
816 true);
817 FragmentRef &target_fragref = pReloc.targetRef();
818 Fragment *target_frag = target_fragref.frag();
819
820 LDSection& target_sect = target_frag->getParent()->getSection();
821 // If the flag of target section is not ALLOC, we will not scan this relocation
822 // but perform static relocation. (e.g., applying .debug section)
823 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
824 pReloc.target() = S + A;
825 return X86Relocator::OK;
826 }
827
828 // A local symbol may need REL Type dynamic relocation
829 if (rsym->isLocal() && has_dyn_rel) {
830 X86Relocator::Type pType = pReloc.type();
831 if (llvm::ELF::R_386_32 == pType)
832 pType = llvm::ELF::R_386_RELATIVE;
833 helper_DynRel(rsym, *target_frag, target_fragref.offset(), pType, pParent);
834 pReloc.target() = S + A;
835 return X86Relocator::OK;
836 }
837
838 // An external symbol may need PLT and dynamic relocation
839 if (!rsym->isLocal()) {
840 if (rsym->reserved() & X86Relocator::ReservePLT) {
841 S = helper_PLT(pReloc, pParent);
842 }
843 // If we generate a dynamic relocation (except R_386_RELATIVE)
844 // for a place, we should not perform static relocation on it
845 // in order to keep the addend store in the place correct.
846 if (has_dyn_rel) {
847 if (llvm::ELF::R_386_32 == pReloc.type() &&
848 helper_use_relative_reloc(*rsym, pParent)) {
849 helper_DynRel(rsym, *target_frag, target_fragref.offset(),
850 llvm::ELF::R_386_RELATIVE, pParent);
851 }
852 else {
853 helper_DynRel(rsym, *target_frag, target_fragref.offset(),
854 pReloc.type(), pParent);
855 return X86Relocator::OK;
856 }
857 }
858 }
859
860 // perform static relocation
861 pReloc.target() = S + A;
862 return X86Relocator::OK;
863 }
864
865 // R_386_PC32: S + A - P
866 // R_386_PC16
867 // R_386_PC8
rel(Relocation & pReloc,X86_32Relocator & pParent)868 X86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent)
869 {
870 ResolveInfo* rsym = pReloc.symInfo();
871 Relocator::DWord A = pReloc.target() + pReloc.addend();
872 Relocator::DWord S = pReloc.symValue();
873 Relocator::DWord P = pReloc.place();
874
875 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
876 // If the flag of target section is not ALLOC, we will not scan this relocation
877 // but perform static relocation. (e.g., applying .debug section)
878 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
879 pReloc.target() = S + A - P;
880 return X86Relocator::OK;
881 }
882
883 // An external symbol may need PLT and dynamic relocation
884 if (!rsym->isLocal()) {
885 if (rsym->reserved() & X86Relocator::ReservePLT) {
886 S = helper_PLT(pReloc, pParent);
887 pReloc.target() = S + A - P;
888 }
889 if (pParent.getTarget().symbolNeedsDynRel(
890 *rsym,
891 (rsym->reserved() & X86Relocator::ReservePLT),
892 false)) {
893 if (helper_use_relative_reloc(*rsym, pParent) ) {
894 helper_DynRel(rsym, *pReloc.targetRef().frag(),
895 pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
896 }
897 else {
898 helper_DynRel(rsym, *pReloc.targetRef().frag(),
899 pReloc.targetRef().offset(), pReloc.type(), pParent);
900 return X86Relocator::OK;
901 }
902 }
903 }
904
905 // perform static relocation
906 pReloc.target() = S + A - P;
907 return X86Relocator::OK;
908 }
909
910 // R_386_GOTOFF: S + A - GOT_ORG
gotoff32(Relocation & pReloc,X86_32Relocator & pParent)911 X86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent)
912 {
913 Relocator::DWord A = pReloc.target() + pReloc.addend();
914 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
915 X86Relocator::Address S = pReloc.symValue();
916
917 pReloc.target() = S + A - GOT_ORG;
918 return X86Relocator::OK;
919 }
920
921 // R_386_GOTPC: GOT_ORG + A - P
gotpc32(Relocation & pReloc,X86_32Relocator & pParent)922 X86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent)
923 {
924 Relocator::DWord A = pReloc.target() + pReloc.addend();
925 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
926 // Apply relocation.
927 pReloc.target() = GOT_ORG + A - pReloc.place();
928 return X86Relocator::OK;
929 }
930
931 // R_386_GOT32: GOT(S) + A - GOT_ORG
got32(Relocation & pReloc,X86_32Relocator & pParent)932 X86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent)
933 {
934 if (!(pReloc.symInfo()->reserved()
935 & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) {
936 return X86Relocator::BadReloc;
937 }
938 X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent);
939 Relocator::DWord A = pReloc.target() + pReloc.addend();
940 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
941 // Apply relocation.
942 pReloc.target() = GOT_S + A - GOT_ORG;
943 return X86Relocator::OK;
944 }
945
946 // R_386_PLT32: PLT(S) + A - P
plt32(Relocation & pReloc,X86_32Relocator & pParent)947 X86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent)
948 {
949 // PLT_S depends on if there is a PLT entry.
950 X86Relocator::Address PLT_S;
951 if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
952 PLT_S = helper_PLT(pReloc, pParent);
953 else
954 PLT_S = pReloc.symValue();
955 Relocator::DWord A = pReloc.target() + pReloc.addend();
956 X86Relocator::Address P = pReloc.place();
957 pReloc.target() = PLT_S + A - P;
958 return X86Relocator::OK;
959 }
960
961 // R_386_TLS_GD:
tls_gd(Relocation & pReloc,X86_32Relocator & pParent)962 X86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent)
963 {
964 // global-dynamic
965 ResolveInfo* rsym = pReloc.symInfo();
966 // must reserve two pairs of got and dynamic relocation
967 if (!(rsym->reserved() & X86Relocator::GOTRel)) {
968 return X86Relocator::BadReloc;
969 }
970
971 X86_32GNULDBackend& ld_backend = pParent.getTarget();
972 ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
973 // setup corresponding got and dynamic relocatio entries:
974 // get first got entry, if there is already a got entry for rsym, then apply
975 // this relocation to the got entry directly. If not, setup the corresponding
976 // got and dyn relocation entries
977 X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
978
979 if (NULL == got_entry1) {
980 // get and init two got entries if not exist
981 got_entry1 = ld_backend.getGOT().consume();
982 pParent.getSymGOTMap().record(*rsym, *got_entry1);
983 X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume();
984 got_entry1->setValue(0x0);
985 got_entry2->setValue(0x0);
986 // setup dyn rel for get_entry1
987 Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
988 llvm::ELF::R_386_TLS_DTPMOD32, pParent);
989 if (rsym->isLocal()) {
990 // for local symbol, set got_entry2 to symbol value
991 got_entry2->setValue(pReloc.symValue());
992
993 // for local tls symbol, add rel entry against the section symbol this
994 // symbol belong to (.tdata or .tbss)
995 const LDSection* sym_sect =
996 &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
997 ResolveInfo* sect_sym = NULL;
998 if (&file_format->getTData() == sym_sect)
999 sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo();
1000 else
1001 sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo();
1002 rel_entry1.setSymInfo(sect_sym);
1003 }
1004 else {
1005 // for non-local symbol, add a pair of rel entries against this symbol
1006 // for those two got entries
1007 helper_DynRel(rsym, *got_entry2, 0x0,
1008 llvm::ELF::R_386_TLS_DTPOFF32, pParent);
1009 }
1010 }
1011
1012 // perform relocation to the first got entry
1013 Relocator::DWord A = pReloc.target() + pReloc.addend();
1014 // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
1015 // .got.plt section)
1016 X86Relocator::Address GOT_OFF =
1017 file_format->getGOT().addr() +
1018 got_entry1->getOffset() -
1019 file_format->getGOTPLT().addr();
1020 pReloc.target() = GOT_OFF + A;
1021 return X86Relocator::OK;
1022 }
1023
1024 // R_386_TLS_LDM
tls_ldm(Relocation & pReloc,X86_32Relocator & pParent)1025 X86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent)
1026 {
1027 // FIXME: no linker optimization for TLS relocation
1028 const X86_32GOTEntry& got_entry = pParent.getTLSModuleID();
1029
1030 // All GOT offsets are relative to the end of the GOT.
1031 X86Relocator::SWord GOT_S = got_entry.getOffset() -
1032 (pParent.getTarget().getGOTPLT().addr() -
1033 pParent.getTarget().getGOT().addr());
1034 Relocator::DWord A = pReloc.target() + pReloc.addend();
1035 pReloc.target() = GOT_S + A;
1036
1037 return X86Relocator::OK;
1038 }
1039
1040 // R_386_TLS_LDO_32
tls_ldo_32(Relocation & pReloc,X86_32Relocator & pParent)1041 X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent)
1042 {
1043 // FIXME: no linker optimization for TLS relocation
1044 Relocator::DWord A = pReloc.target() + pReloc.addend();
1045 X86Relocator::Address S = pReloc.symValue();
1046 pReloc.target() = S + A;
1047 return X86Relocator::OK;
1048 }
1049
1050 // R_X86_TLS_IE
tls_ie(Relocation & pReloc,X86_32Relocator & pParent)1051 X86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent)
1052 {
1053 ResolveInfo* rsym = pReloc.symInfo();
1054 if (!(rsym->reserved() & X86Relocator::GOTRel)) {
1055 return X86Relocator::BadReloc;
1056 }
1057
1058 if (rsym->reserved() & X86Relocator::ReserveRel) {
1059 // when building shared object, set up a RELATIVE dynamic relocation
1060 helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(),
1061 llvm::ELF::R_386_RELATIVE, pParent);
1062 }
1063
1064 // set up the got and dynamic relocation entries if not exist
1065 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
1066 if (NULL == got_entry) {
1067 // set got entry
1068 X86_32GNULDBackend& ld_backend = pParent.getTarget();
1069 got_entry = ld_backend.getGOT().consume();
1070 pParent.getSymGOTMap().record(*rsym, *got_entry);
1071 got_entry->setValue(0x0);
1072 // set relocation entry
1073 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
1074 rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
1075 rel_entry.setSymInfo(rsym);
1076 rel_entry.targetRef().assign(*got_entry);
1077 }
1078
1079 // perform relocation to the absolute address of got_entry
1080 X86Relocator::Address GOT_S =
1081 pParent.getTarget().getGOT().addr() + got_entry->getOffset();
1082
1083 Relocator::DWord A = pReloc.target() + pReloc.addend();
1084 pReloc.target() = GOT_S + A;
1085
1086 return X86Relocator::OK;
1087 }
1088
1089 // R_386_TLS_GOTIE
tls_gotie(Relocation & pReloc,X86_32Relocator & pParent)1090 X86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent)
1091 {
1092 ResolveInfo* rsym = pReloc.symInfo();
1093 if (!(rsym->reserved() & X86Relocator::GOTRel)) {
1094 return X86Relocator::BadReloc;
1095 }
1096
1097 // set up the got and dynamic relocation entries if not exist
1098 X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
1099 if (NULL == got_entry) {
1100 // set got entry
1101 X86_32GNULDBackend& ld_backend = pParent.getTarget();
1102 got_entry = ld_backend.getGOT().consume();
1103 pParent.getSymGOTMap().record(*rsym, *got_entry);
1104 got_entry->setValue(0x0);
1105 // set relocation entry
1106 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
1107 rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
1108 rel_entry.setSymInfo(rsym);
1109 rel_entry.targetRef().assign(*got_entry);
1110 }
1111
1112 // All GOT offsets are relative to the end of the GOT.
1113 X86Relocator::SWord GOT_S = got_entry->getOffset() -
1114 (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
1115 Relocator::DWord A = pReloc.target() + pReloc.addend();
1116 pReloc.target() = GOT_S + A;
1117
1118 return X86Relocator::OK;
1119 }
1120
1121 // R_X86_TLS_LE
tls_le(Relocation & pReloc,X86_32Relocator & pParent)1122 X86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent)
1123 {
1124 ResolveInfo* rsym = pReloc.symInfo();
1125 if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) {
1126 helper_DynRel(rsym,
1127 *pReloc.targetRef().frag(),
1128 pReloc.targetRef().offset(),
1129 llvm::ELF::R_386_TLS_TPOFF,
1130 pParent);
1131 return X86Relocator::OK;
1132 }
1133
1134 // perform static relocation
1135 // get TLS segment
1136 ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
1137 llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
1138 Relocator::DWord A = pReloc.target() + pReloc.addend();
1139 X86Relocator::Address S = pReloc.symValue();
1140 pReloc.target() = S + A - tls_seg->memsz();
1141 return X86Relocator::OK;
1142 }
1143
unsupport(Relocation & pReloc,X86_32Relocator & pParent)1144 X86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent)
1145 {
1146 return X86Relocator::Unsupport;
1147 }
1148
1149 //===--------------------------------------------------------------------===//
1150 // Relocation Functions and Tables
1151 //===--------------------------------------------------------------------===//
1152 DECL_X86_64_APPLY_RELOC_FUNCS
1153
1154 /// the prototype of applying function
1155 typedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc,
1156 X86_64Relocator& pParent);
1157
1158 // the table entry of applying functions
1159 struct X86_64ApplyFunctionTriple
1160 {
1161 X86_64ApplyFunctionType func;
1162 unsigned int type;
1163 const char* name;
1164 unsigned int size;
1165 };
1166
1167 // declare the table of applying functions
1168 static const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = {
1169 DECL_X86_64_APPLY_RELOC_FUNC_PTRS
1170 };
1171
1172 //===--------------------------------------------------------------------===//
1173 // X86_64Relocator
1174 //===--------------------------------------------------------------------===//
X86_64Relocator(X86_64GNULDBackend & pParent,const LinkerConfig & pConfig)1175 X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent,
1176 const LinkerConfig& pConfig)
1177 : X86Relocator(pConfig), m_Target(pParent) {
1178 }
1179
1180 Relocator::Result
applyRelocation(Relocation & pRelocation)1181 X86_64Relocator::applyRelocation(Relocation& pRelocation)
1182 {
1183 Relocation::Type type = pRelocation.type();
1184
1185 if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) {
1186 return Unknown;
1187 }
1188
1189 // apply the relocation
1190 return X86_64ApplyFunctions[type].func(pRelocation, *this);
1191 }
1192
getName(Relocation::Type pType) const1193 const char* X86_64Relocator::getName(Relocation::Type pType) const
1194 {
1195 return X86_64ApplyFunctions[pType].name;
1196 }
1197
getSize(Relocation::Type pType) const1198 Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const
1199 {
1200 return X86_64ApplyFunctions[pType].size;
1201 }
1202
scanLocalReloc(Relocation & pReloc,IRBuilder & pBuilder,Module & pModule,LDSection & pSection)1203 void X86_64Relocator::scanLocalReloc(Relocation& pReloc,
1204 IRBuilder& pBuilder,
1205 Module& pModule,
1206 LDSection& pSection)
1207 {
1208 // rsym - The relocation target symbol
1209 ResolveInfo* rsym = pReloc.symInfo();
1210
1211 switch(pReloc.type()){
1212 case llvm::ELF::R_X86_64_64:
1213 case llvm::ELF::R_X86_64_32:
1214 case llvm::ELF::R_X86_64_16:
1215 case llvm::ELF::R_X86_64_8:
1216 case llvm::ELF::R_X86_64_32S:
1217 // If buiding PIC object (shared library or PIC executable),
1218 // a dynamic relocations with RELATIVE type to this location is needed.
1219 // Reserve an entry in .rela.dyn
1220 if (config().isCodeIndep()) {
1221 getTarget().getRelDyn().reserveEntry();
1222 // set Rel bit
1223 rsym->setReserved(rsym->reserved() | ReserveRel);
1224 getTarget().checkAndSetHasTextRel(*pSection.getLink());
1225 }
1226 return;
1227
1228 case llvm::ELF::R_X86_64_PC32:
1229 case llvm::ELF::R_X86_64_PC16:
1230 case llvm::ELF::R_X86_64_PC8:
1231 return;
1232
1233 case llvm::ELF::R_X86_64_GOTPCREL:
1234 // Symbol needs GOT entry, reserve entry in .got
1235 // return if we already create GOT for this symbol
1236 if (rsym->reserved() & (ReserveGOT | GOTRel))
1237 return;
1238 getTarget().getGOT().reserve();
1239
1240 // If the GOT is used in statically linked binaries,
1241 // the GOT entry is enough and no relocation is needed.
1242 if (config().isCodeStatic()) {
1243 rsym->setReserved(rsym->reserved() | ReserveGOT);
1244 return;
1245 }
1246 // If building shared object or the symbol is undefined, a dynamic
1247 // relocation is needed to relocate this GOT entry. Reserve an
1248 // entry in .rela.dyn
1249 if (LinkerConfig::DynObj ==
1250 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
1251 getTarget().getRelDyn().reserveEntry();
1252 // set GOTRel bit
1253 rsym->setReserved(rsym->reserved() | GOTRel);
1254 return;
1255 }
1256 // set GOT bit
1257 rsym->setReserved(rsym->reserved() | ReserveGOT);
1258 return;
1259
1260 default:
1261 fatal(diag::unsupported_relocation) << (int)pReloc.type()
1262 << "mclinker@googlegroups.com";
1263 break;
1264 } // end switch
1265 }
1266
scanGlobalReloc(Relocation & pReloc,IRBuilder & pBuilder,Module & pModule,LDSection & pSection)1267 void X86_64Relocator::scanGlobalReloc(Relocation& pReloc,
1268 IRBuilder& pBuilder,
1269 Module& pModule,
1270 LDSection& pSection)
1271 {
1272 // rsym - The relocation target symbol
1273 ResolveInfo* rsym = pReloc.symInfo();
1274
1275 switch(pReloc.type()) {
1276 case llvm::ELF::R_X86_64_64:
1277 case llvm::ELF::R_X86_64_32:
1278 case llvm::ELF::R_X86_64_16:
1279 case llvm::ELF::R_X86_64_8:
1280 case llvm::ELF::R_X86_64_32S:
1281 // Absolute relocation type, symbol may needs PLT entry or
1282 // dynamic relocation entry
1283 if (getTarget().symbolNeedsPLT(*rsym)) {
1284 // create plt for this symbol if it does not have one
1285 if (!(rsym->reserved() & ReservePLT)){
1286 // Symbol needs PLT entry, we need to reserve a PLT entry
1287 // and the corresponding GOT and dynamic relocation entry
1288 // in .got and .rela.plt. (GOT entry will be reserved simultaneously
1289 // when calling X86PLT->reserveEntry())
1290 getTarget().getPLT().reserveEntry();
1291 getTarget().getGOTPLT().reserve();
1292 getTarget().getRelPLT().reserveEntry();
1293 // set PLT bit
1294 rsym->setReserved(rsym->reserved() | ReservePLT);
1295 }
1296 }
1297
1298 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
1299 // symbol needs dynamic relocation entry, reserve an entry in .rela.dyn
1300 getTarget().getRelDyn().reserveEntry();
1301 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
1302 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
1303 addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
1304 }
1305 else {
1306 // set Rel bit
1307 rsym->setReserved(rsym->reserved() | ReserveRel);
1308 getTarget().checkAndSetHasTextRel(*pSection.getLink());
1309 }
1310 }
1311 return;
1312
1313 case llvm::ELF::R_X86_64_GOTPCREL:
1314 // Symbol needs GOT entry, reserve entry in .got
1315 // return if we already create GOT for this symbol
1316 if (rsym->reserved() & (ReserveGOT | GOTRel))
1317 return;
1318 getTarget().getGOT().reserve();
1319
1320 // If the GOT is used in statically linked binaries,
1321 // the GOT entry is enough and no relocation is needed.
1322 if (config().isCodeStatic()) {
1323 rsym->setReserved(rsym->reserved() | ReserveGOT);
1324 return;
1325 }
1326 // If building shared object or the symbol is undefined, a dynamic
1327 // relocation is needed to relocate this GOT entry. Reserve an
1328 // entry in .rela.dyn
1329 if (LinkerConfig::DynObj ==
1330 config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
1331 getTarget().getRelDyn().reserveEntry();
1332 // set GOTRel bit
1333 rsym->setReserved(rsym->reserved() | GOTRel);
1334 return;
1335 }
1336 // set GOT bit
1337 rsym->setReserved(rsym->reserved() | ReserveGOT);
1338 return;
1339
1340 case llvm::ELF::R_X86_64_PLT32:
1341 // A PLT entry is needed when building shared library
1342
1343 // return if we already create plt for this symbol
1344 if (rsym->reserved() & ReservePLT)
1345 return;
1346
1347 // if the symbol's value can be decided at link time, then no need plt
1348 if (getTarget().symbolFinalValueIsKnown(*rsym))
1349 return;
1350
1351 // if symbol is defined in the ouput file and it's not
1352 // preemptible, no need plt
1353 if (rsym->isDefine() && !rsym->isDyn() &&
1354 !getTarget().isSymbolPreemptible(*rsym)) {
1355 return;
1356 }
1357
1358 // Symbol needs PLT entry, we need to reserve a PLT entry
1359 // and the corresponding GOT and dynamic relocation entry
1360 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
1361 // when calling X86PLT->reserveEntry())
1362 getTarget().getPLT().reserveEntry();
1363 getTarget().getGOTPLT().reserve();
1364 getTarget().getRelPLT().reserveEntry();
1365 // set PLT bit
1366 rsym->setReserved(rsym->reserved() | ReservePLT);
1367 return;
1368
1369 case llvm::ELF::R_X86_64_PC32:
1370 case llvm::ELF::R_X86_64_PC16:
1371 case llvm::ELF::R_X86_64_PC8:
1372 if (getTarget().symbolNeedsPLT(*rsym) &&
1373 LinkerConfig::DynObj != config().codeGenType()) {
1374 // create plt for this symbol if it does not have one
1375 if (!(rsym->reserved() & ReservePLT)){
1376 // Symbol needs PLT entry, we need to reserve a PLT entry
1377 // and the corresponding GOT and dynamic relocation entry
1378 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
1379 // when calling X86PLT->reserveEntry())
1380 getTarget().getPLT().reserveEntry();
1381 getTarget().getGOTPLT().reserve();
1382 getTarget().getRelPLT().reserveEntry();
1383 // set PLT bit
1384 rsym->setReserved(rsym->reserved() | ReservePLT);
1385 }
1386 }
1387
1388 // Only PC relative relocation against dynamic symbol needs a
1389 // dynamic relocation. Only dynamic copy relocation is allowed
1390 // and PC relative relocation will be resolved to the local copy.
1391 // All other dynamic relocations may lead to run-time relocation
1392 // overflow.
1393 if (getTarget().isDynamicSymbol(*rsym) &&
1394 getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false) &&
1395 getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
1396 getTarget().getRelDyn().reserveEntry();
1397 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
1398 addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
1399 }
1400 return;
1401
1402 default:
1403 fatal(diag::unsupported_relocation) << (int)pReloc.type()
1404 << "mclinker@googlegroups.com";
1405 break;
1406 } // end switch
1407 }
1408
1409 //===--------------------------------------------------------------------===//
1410 // Relocation helper function
1411 //===--------------------------------------------------------------------===//
1412 /// helper_DynRel - Get an relocation entry in .rela.dyn
1413 static
helper_DynRel(ResolveInfo * pSym,Fragment & pFrag,uint64_t pOffset,X86Relocator::Type pType,X86_64Relocator & pParent)1414 Relocation& helper_DynRel(ResolveInfo* pSym,
1415 Fragment& pFrag,
1416 uint64_t pOffset,
1417 X86Relocator::Type pType,
1418 X86_64Relocator& pParent)
1419 {
1420 X86_64GNULDBackend& ld_backend = pParent.getTarget();
1421 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
1422 rel_entry.setType(pType);
1423 rel_entry.targetRef().assign(pFrag, pOffset);
1424 if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym)
1425 rel_entry.setSymInfo(0);
1426 else
1427 rel_entry.setSymInfo(pSym);
1428
1429 return rel_entry;
1430 }
1431
1432
1433 /// helper_use_relative_reloc - Check if symbol can use relocation
1434 /// R_X86_64_RELATIVE
1435 static bool
helper_use_relative_reloc(const ResolveInfo & pSym,const X86_64Relocator & pFactory)1436 helper_use_relative_reloc(const ResolveInfo& pSym,
1437 const X86_64Relocator& pFactory)
1438
1439 {
1440 // if symbol is dynamic or undefine or preemptible
1441 if (pSym.isDyn() ||
1442 pSym.isUndef() ||
1443 pFactory.getTarget().isSymbolPreemptible(pSym))
1444 return false;
1445 return true;
1446 }
1447
1448 static
helper_get_GOT_and_init(Relocation & pReloc,X86_64Relocator & pParent)1449 X86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
1450 X86_64Relocator& pParent)
1451 {
1452 // rsym - The relocation target symbol
1453 ResolveInfo* rsym = pReloc.symInfo();
1454 X86_64GNULDBackend& ld_backend = pParent.getTarget();
1455
1456 X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
1457 if (NULL != got_entry)
1458 return *got_entry;
1459
1460 // not found
1461 got_entry = ld_backend.getGOT().consume();
1462 pParent.getSymGOTMap().record(*rsym, *got_entry);
1463
1464 // If we first get this GOT entry, we should initialize it.
1465 if (rsym->reserved() & X86Relocator::ReserveGOT) {
1466 // No corresponding dynamic relocation, initialize to the symbol value.
1467 got_entry->setValue(pReloc.symValue());
1468 }
1469 else if (rsym->reserved() & X86Relocator::GOTRel) {
1470 // Initialize got_entry content and the corresponding dynamic relocation.
1471 if (helper_use_relative_reloc(*rsym, pParent)) {
1472 Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0,
1473 llvm::ELF::R_X86_64_RELATIVE,
1474 pParent);
1475 rel_entry.setAddend(pReloc.symValue());
1476 }
1477 else {
1478 helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT,
1479 pParent);
1480 }
1481 got_entry->setValue(0);
1482 }
1483 else {
1484 fatal(diag::reserve_entry_number_mismatch_got);
1485 }
1486 return *got_entry;
1487 }
1488
1489 static
helper_GOT_ORG(X86_64Relocator & pParent)1490 X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
1491 {
1492 return pParent.getTarget().getGOT().addr();
1493 }
1494
1495 static
helper_GOT(Relocation & pReloc,X86_64Relocator & pParent)1496 X86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent)
1497 {
1498 X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
1499 return got_entry.getOffset();
1500 }
1501
1502 static
helper_get_PLT_and_init(Relocation & pReloc,X86_64Relocator & pParent)1503 PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
1504 X86_64Relocator& pParent)
1505 {
1506 // rsym - The relocation target symbol
1507 ResolveInfo* rsym = pReloc.symInfo();
1508 X86_64GNULDBackend& ld_backend = pParent.getTarget();
1509
1510 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
1511 if (NULL != plt_entry)
1512 return *plt_entry;
1513
1514 // not found
1515 plt_entry = ld_backend.getPLT().consume();
1516 pParent.getSymPLTMap().record(*rsym, *plt_entry);
1517 // If we first get this PLT entry, we should initialize it.
1518 if (rsym->reserved() & X86Relocator::ReservePLT) {
1519 X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
1520 assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
1521 gotplt_entry = ld_backend.getGOTPLT().consume();
1522 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
1523 // init the corresponding rel entry in .rel.plt
1524 Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
1525 rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
1526 rel_entry.targetRef().assign(*gotplt_entry);
1527 rel_entry.setSymInfo(rsym);
1528 }
1529 else {
1530 fatal(diag::reserve_entry_number_mismatch_plt);
1531 }
1532
1533 return *plt_entry;
1534 }
1535
1536 static
helper_PLT_ORG(X86_64Relocator & pParent)1537 X86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent)
1538 {
1539 return pParent.getTarget().getPLT().addr();
1540 }
1541
1542 static
helper_PLT(Relocation & pReloc,X86_64Relocator & pParent)1543 X86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent)
1544 {
1545 PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
1546 return helper_PLT_ORG(pParent) + plt_entry.getOffset();
1547 }
1548
1549 //
1550 // R_X86_64_NONE
none(Relocation & pReloc,X86_64Relocator & pParent)1551 X86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent)
1552 {
1553 return X86Relocator::OK;
1554 }
1555
1556 // R_X86_64_64: S + A
1557 // R_X86_64_32:
1558 // R_X86_64_16:
1559 // R_X86_64_8
abs(Relocation & pReloc,X86_64Relocator & pParent)1560 X86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent)
1561 {
1562 ResolveInfo* rsym = pReloc.symInfo();
1563 Relocator::DWord A = pReloc.target() + pReloc.addend();
1564 Relocator::DWord S = pReloc.symValue();
1565 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
1566 *rsym,
1567 (rsym->reserved() & X86Relocator::ReservePLT),
1568 true);
1569
1570 FragmentRef &target_fragref = pReloc.targetRef();
1571 Fragment *target_frag = target_fragref.frag();
1572
1573 LDSection& target_sect = target_frag->getParent()->getSection();
1574 // If the flag of target section is not ALLOC, we will not scan this relocation
1575 // but perform static relocation. (e.g., applying .debug section)
1576 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1577 pReloc.target() = S + A;
1578 return X86Relocator::OK;
1579 }
1580
1581 // A local symbol may need RELA Type dynamic relocation
1582 if (rsym->isLocal() && has_dyn_rel) {
1583 X86Relocator::Type pType = pReloc.type();
1584 if (llvm::ELF::R_X86_64_64 == pType)
1585 pType = llvm::ELF::R_X86_64_RELATIVE;
1586 Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
1587 target_fragref.offset(), pType, pParent);
1588 rel_entry.setAddend(S + A);
1589 return X86Relocator::OK;
1590 }
1591
1592 // An external symbol may need PLT and dynamic relocation
1593 if (!rsym->isLocal()) {
1594 if (rsym->reserved() & X86Relocator::ReservePLT) {
1595 S = helper_PLT(pReloc, pParent);
1596 }
1597 // If we generate a dynamic relocation (except R_X86_64_RELATIVE)
1598 // for a place, we should not perform static relocation on it
1599 // in order to keep the addend store in the place correct.
1600 if (has_dyn_rel) {
1601 if (llvm::ELF::R_X86_64_64 == pReloc.type() &&
1602 helper_use_relative_reloc(*rsym, pParent)) {
1603 Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
1604 target_fragref.offset(), llvm::ELF::R_X86_64_RELATIVE, pParent);
1605 rel_entry.setAddend(S + A);
1606 }
1607 else {
1608 Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
1609 target_fragref.offset(), pReloc.type(), pParent);
1610 rel_entry.setAddend(A);
1611 return X86Relocator::OK;
1612 }
1613 }
1614 }
1615
1616 // perform static relocation
1617 pReloc.target() = S + A;
1618 return X86Relocator::OK;
1619 }
1620
1621 // R_X86_64_32S: S + A
signed32(Relocation & pReloc,X86_64Relocator & pParent)1622 X86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent)
1623 {
1624 ResolveInfo* rsym = pReloc.symInfo();
1625 Relocator::DWord A = pReloc.target() + pReloc.addend();
1626 Relocator::DWord S = pReloc.symValue();
1627 bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
1628 *rsym,
1629 (rsym->reserved() & X86Relocator::ReservePLT),
1630 true);
1631
1632 // There should be no dynamic relocations for R_X86_64_32S.
1633 if (has_dyn_rel)
1634 return X86Relocator::BadReloc;
1635
1636 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1637 // If the flag of target section is not ALLOC, we will not scan this relocation
1638 // but perform static relocation. (e.g., applying .debug section)
1639 // An external symbol may need PLT and dynamic relocation
1640 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) &&
1641 !rsym->isLocal() && rsym->reserved() & X86Relocator::ReservePLT)
1642 S = helper_PLT(pReloc, pParent);
1643
1644 #if notyet
1645 // Check 32-bit signed overflow.
1646 Relocator::SWord V = S + A;
1647 if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000))
1648 return X86Relocator::Overflow;
1649 #endif
1650
1651 // perform static relocation
1652 pReloc.target() = S + A;
1653 return X86Relocator::OK;
1654 }
1655
1656 // R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
gotpcrel(Relocation & pReloc,X86_64Relocator & pParent)1657 X86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent)
1658 {
1659 if (!(pReloc.symInfo()->reserved()
1660 & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) {
1661 return X86Relocator::BadReloc;
1662 }
1663 X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent);
1664 Relocator::DWord A = pReloc.target() + pReloc.addend();
1665 X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
1666 // Apply relocation.
1667 pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place();
1668 return X86Relocator::OK;
1669 }
1670
1671 // R_X86_64_PLT32: PLT(S) + A - P
plt32(Relocation & pReloc,X86_64Relocator & pParent)1672 X86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent)
1673 {
1674 // PLT_S depends on if there is a PLT entry.
1675 X86Relocator::Address PLT_S;
1676 if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
1677 PLT_S = helper_PLT(pReloc, pParent);
1678 else
1679 PLT_S = pReloc.symValue();
1680 Relocator::DWord A = pReloc.target() + pReloc.addend();
1681 X86Relocator::Address P = pReloc.place();
1682 pReloc.target() = PLT_S + A - P;
1683 return X86Relocator::OK;
1684 }
1685
1686 // R_X86_64_PC32: S + A - P
1687 // R_X86_64_PC16
1688 // R_X86_64_PC8
rel(Relocation & pReloc,X86_64Relocator & pParent)1689 X86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent)
1690 {
1691 ResolveInfo* rsym = pReloc.symInfo();
1692 Relocator::DWord A = pReloc.target() + pReloc.addend();
1693 Relocator::DWord S = pReloc.symValue();
1694 Relocator::DWord P = pReloc.place();
1695
1696 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1697 // If the flag of target section is not ALLOC, we will not scan this relocation
1698 // but perform static relocation. (e.g., applying .debug section)
1699 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1700 pReloc.target() = S + A - P;
1701 return X86Relocator::OK;
1702 }
1703
1704 // An external symbol may need PLT and dynamic relocation
1705 if (!rsym->isLocal()) {
1706 if (rsym->reserved() & X86Relocator::ReservePLT) {
1707 S = helper_PLT(pReloc, pParent);
1708 pReloc.target() = S + A - P;
1709 }
1710 if (pParent.getTarget().symbolNeedsDynRel(
1711 *rsym,
1712 (rsym->reserved() & X86Relocator::ReservePLT),
1713 false)) {
1714 return X86Relocator::Overflow;
1715 }
1716 }
1717
1718 // perform static relocation
1719 pReloc.target() = S + A - P;
1720 return X86Relocator::OK;
1721 }
1722
unsupport(Relocation & pReloc,X86_64Relocator & pParent)1723 X86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent)
1724 {
1725 return X86Relocator::Unsupport;
1726 }
1727