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