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