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/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 //===--------------------------------------------------------------------===//
     50 X86Relocator::X86Relocator(const LinkerConfig& pConfig)
     51   : Relocator(pConfig) {
     52 }
     53 
     54 X86Relocator::~X86Relocator()
     55 {
     56 }
     57 
     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 
     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.
    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 //===--------------------------------------------------------------------===//
    176 X86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent,
    177                                  const LinkerConfig& pConfig)
    178   : X86Relocator(pConfig), m_Target(pParent) {
    179 }
    180 
    181 Relocator::Result
    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 
    194 const char* X86_32Relocator::getName(Relocation::Type pType) const
    195 {
    196   return X86_32ApplyFunctions[pType].name;
    197 }
    198 
    199 Relocator::Size X86_32Relocator::getSize(Relocation::Type pType) const
    200 {
    201   return X86_32ApplyFunctions[pType].size;;
    202 }
    203 
    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 (at) googlegroups.com";
    357       break;
    358   } // end switch
    359 }
    360 
    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 (at) googlegroups.com";
    573       break;
    574     }
    575   } // end switch
    576 }
    577 
    578 // Create a GOT entry for the TLS module index
    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
    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
    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
    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
    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
    730 X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
    731 {
    732   return pParent.getTarget().getGOTPLT().addr();
    733 }
    734 
    735 
    736 static
    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
    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
    781 X86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent)
    782 {
    783   return pParent.getTarget().getPLT().addr();
    784 }
    785 
    786 
    787 static
    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
    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
    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
    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
    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
    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
    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
    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:
    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
   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
   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
   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
   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
   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 
   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 //===--------------------------------------------------------------------===//
   1175 X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent,
   1176                                  const LinkerConfig& pConfig)
   1177   : X86Relocator(pConfig), m_Target(pParent) {
   1178 }
   1179 
   1180 Relocator::Result
   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 
   1193 const char* X86_64Relocator::getName(Relocation::Type pType) const
   1194 {
   1195   return X86_64ApplyFunctions[pType].name;
   1196 }
   1197 
   1198 Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const
   1199 {
   1200   return X86_64ApplyFunctions[pType].size;
   1201 }
   1202 
   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 (at) googlegroups.com";
   1263       break;
   1264   } // end switch
   1265 }
   1266 
   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 (at) 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
   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
   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
   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
   1490 X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
   1491 {
   1492   return pParent.getTarget().getGOT().addr();
   1493 }
   1494 
   1495 static
   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
   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
   1537 X86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent)
   1538 {
   1539   return pParent.getTarget().getPLT().addr();
   1540 }
   1541 
   1542 static
   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
   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
   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
   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
   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
   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
   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 
   1723 X86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent)
   1724 {
   1725   return X86Relocator::Unsupport;
   1726 }
   1727