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