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