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/Support/MsgHandling.h>
     13 #include <mcld/LD/LDSymbol.h>
     14 
     15 #include <llvm/ADT/Twine.h>
     16 #include <llvm/Support/DataTypes.h>
     17 #include <llvm/Support/ELF.h>
     18 
     19 using namespace mcld;
     20 
     21 //===--------------------------------------------------------------------===//
     22 // Relocation Functions and Tables
     23 //===--------------------------------------------------------------------===//
     24 DECL_X86_32_APPLY_RELOC_FUNCS
     25 
     26 /// the prototype of applying function
     27 typedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc,
     28 						     X86_32Relocator& pParent);
     29 
     30 // the table entry of applying functions
     31 struct X86_32ApplyFunctionTriple
     32 {
     33   X86_32ApplyFunctionType func;
     34   unsigned int type;
     35   const char* name;
     36   unsigned int size;
     37 };
     38 
     39 // declare the table of applying functions
     40 static const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = {
     41   DECL_X86_32_APPLY_RELOC_FUNC_PTRS
     42 };
     43 
     44 //===--------------------------------------------------------------------===//
     45 // X86Relocator
     46 //===--------------------------------------------------------------------===//
     47 X86Relocator::X86Relocator()
     48   : Relocator() {
     49 }
     50 
     51 X86Relocator::~X86Relocator()
     52 {
     53 }
     54 
     55 //===--------------------------------------------------------------------===//
     56 // X86_32Relocator
     57 //===--------------------------------------------------------------------===//
     58 X86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent)
     59   : X86Relocator(), m_Target(pParent) {
     60 }
     61 
     62 Relocator::Result
     63 X86_32Relocator::applyRelocation(Relocation& pRelocation)
     64 {
     65   Relocation::Type type = pRelocation.type();
     66 
     67   if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) {
     68     return Unknown;
     69   }
     70 
     71   // apply the relocation
     72   return X86_32ApplyFunctions[type].func(pRelocation, *this);
     73 }
     74 
     75 const char* X86_32Relocator::getName(Relocation::Type pType) const
     76 {
     77   return X86_32ApplyFunctions[pType].name;
     78 }
     79 
     80 Relocator::Size X86_32Relocator::getSize(Relocation::Type pType) const
     81 {
     82   return X86_32ApplyFunctions[pType].size;;
     83 }
     84 
     85 //===--------------------------------------------------------------------===//
     86 // Relocation helper function
     87 //===--------------------------------------------------------------------===//
     88 
     89 /// helper_DynRel - Get an relocation entry in .rel.dyn
     90 static
     91 Relocation& helper_DynRel(ResolveInfo* pSym,
     92                           Fragment& pFrag,
     93                           uint64_t pOffset,
     94                           X86Relocator::Type pType,
     95                           X86_32Relocator& pParent)
     96 {
     97   X86_32GNULDBackend& ld_backend = pParent.getTarget();
     98   Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
     99   rel_entry.setType(pType);
    100   rel_entry.targetRef().assign(pFrag, pOffset);
    101   if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym)
    102     rel_entry.setSymInfo(0);
    103   else
    104     rel_entry.setSymInfo(pSym);
    105 
    106   return rel_entry;
    107 }
    108 
    109 
    110 /// helper_use_relative_reloc - Check if symbol can use relocation
    111 /// R_386_RELATIVE
    112 static bool
    113 helper_use_relative_reloc(const ResolveInfo& pSym,
    114                           const X86_32Relocator& pFactory)
    115 
    116 {
    117   // if symbol is dynamic or undefine or preemptible
    118   if (pSym.isDyn() ||
    119       pSym.isUndef() ||
    120       pFactory.getTarget().isSymbolPreemptible(pSym))
    121     return false;
    122   return true;
    123 }
    124 
    125 static
    126 X86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
    127 					X86_32Relocator& pParent)
    128 {
    129   // rsym - The relocation target symbol
    130   ResolveInfo* rsym = pReloc.symInfo();
    131   X86_32GNULDBackend& ld_backend = pParent.getTarget();
    132 
    133   X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
    134   if (NULL != got_entry)
    135     return *got_entry;
    136 
    137   // not found
    138   got_entry = ld_backend.getGOT().consume();
    139   pParent.getSymGOTMap().record(*rsym, *got_entry);
    140 
    141   // If we first get this GOT entry, we should initialize it.
    142   if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
    143     // No corresponding dynamic relocation, initialize to the symbol value.
    144     got_entry->setValue(pReloc.symValue());
    145   }
    146   else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
    147     // Initialize got_entry content and the corresponding dynamic relocation.
    148     if (helper_use_relative_reloc(*rsym, pParent)) {
    149       helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
    150       got_entry->setValue(pReloc.symValue());
    151     }
    152     else {
    153       helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
    154       got_entry->setValue(0);
    155     }
    156   }
    157   else {
    158     fatal(diag::reserve_entry_number_mismatch_got);
    159   }
    160   return *got_entry;
    161 }
    162 
    163 
    164 static
    165 X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
    166 {
    167   return pParent.getTarget().getGOTPLT().addr();
    168 }
    169 
    170 
    171 static
    172 X86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent)
    173 {
    174   X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
    175   X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr();
    176   return got_addr + got_entry.getOffset();
    177 }
    178 
    179 
    180 static
    181 PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
    182 				      X86_32Relocator& pParent)
    183 {
    184   // rsym - The relocation target symbol
    185   ResolveInfo* rsym = pReloc.symInfo();
    186   X86_32GNULDBackend& ld_backend = pParent.getTarget();
    187 
    188   PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
    189   if (NULL != plt_entry)
    190     return *plt_entry;
    191 
    192   // not found
    193   plt_entry = ld_backend.getPLT().consume();
    194   pParent.getSymPLTMap().record(*rsym, *plt_entry);
    195   // If we first get this PLT entry, we should initialize it.
    196   if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
    197     X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
    198     assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
    199     gotplt_entry = ld_backend.getGOTPLT().consume();
    200     pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
    201     // init the corresponding rel entry in .rel.plt
    202     Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
    203     rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
    204     rel_entry.targetRef().assign(*gotplt_entry);
    205     rel_entry.setSymInfo(rsym);
    206   }
    207   else {
    208     fatal(diag::reserve_entry_number_mismatch_plt);
    209   }
    210 
    211   return *plt_entry;
    212 }
    213 
    214 
    215 static
    216 X86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent)
    217 {
    218   return pParent.getTarget().getPLT().addr();
    219 }
    220 
    221 
    222 static
    223 X86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent)
    224 {
    225   PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
    226   return helper_PLT_ORG(pParent) + plt_entry.getOffset();
    227 }
    228 
    229 
    230 //=========================================//
    231 // Each relocation function implementation //
    232 //=========================================//
    233 
    234 // R_386_NONE
    235 X86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent)
    236 {
    237   return X86Relocator::OK;
    238 }
    239 
    240 // R_386_32: S + A
    241 // R_386_16
    242 // R_386_8
    243 X86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent)
    244 {
    245   ResolveInfo* rsym = pReloc.symInfo();
    246   Relocator::DWord A = pReloc.target() + pReloc.addend();
    247   Relocator::DWord S = pReloc.symValue();
    248   bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
    249                               *rsym,
    250                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
    251                               true);
    252 
    253   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
    254   // If the flag of target section is not ALLOC, we will not scan this relocation
    255   // but perform static relocation. (e.g., applying .debug section)
    256   if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
    257     pReloc.target() = S + A;
    258     return X86Relocator::OK;
    259   }
    260 
    261   // A local symbol may need REL Type dynamic relocation
    262   if (rsym->isLocal() && has_dyn_rel) {
    263     if (llvm::ELF::R_386_32 == pReloc.type()) {
    264       helper_DynRel(rsym, *pReloc.targetRef().frag(),
    265                     pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE,
    266                     pParent);
    267     }
    268     else {
    269       // FIXME: check Section symbol
    270       helper_DynRel(rsym, *pReloc.targetRef().frag(),
    271                     pReloc.targetRef().offset(), pReloc.type(), pParent);
    272     }
    273     pReloc.target() = S + A;
    274     return X86Relocator::OK;
    275   }
    276 
    277   // An external symbol may need PLT and dynamic relocation
    278   if (!rsym->isLocal()) {
    279     if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
    280       S = helper_PLT(pReloc, pParent);
    281     }
    282     // If we generate a dynamic relocation (except R_386_RELATIVE)
    283     // for a place, we should not perform static relocation on it
    284     // in order to keep the addend store in the place correct.
    285     if (has_dyn_rel) {
    286       if (llvm::ELF::R_386_32 == pReloc.type() &&
    287           helper_use_relative_reloc(*rsym, pParent)) {
    288         helper_DynRel(rsym, *pReloc.targetRef().frag(),
    289               pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
    290       }
    291       else {
    292         helper_DynRel(rsym, *pReloc.targetRef().frag(),
    293                           pReloc.targetRef().offset(), pReloc.type(), pParent);
    294         return X86Relocator::OK;
    295       }
    296     }
    297   }
    298 
    299   // perform static relocation
    300   pReloc.target() = S + A;
    301   return X86Relocator::OK;
    302 }
    303 
    304 // R_386_PC32: S + A - P
    305 // R_386_PC16
    306 // R_386_PC8
    307 X86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent)
    308 {
    309   ResolveInfo* rsym = pReloc.symInfo();
    310   Relocator::DWord A = pReloc.target() + pReloc.addend();
    311   Relocator::DWord S = pReloc.symValue();
    312   Relocator::DWord P = pReloc.place();
    313 
    314   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
    315   // If the flag of target section is not ALLOC, we will not scan this relocation
    316   // but perform static relocation. (e.g., applying .debug section)
    317   if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
    318     pReloc.target() = S + A - P;
    319     return X86Relocator::OK;
    320   }
    321 
    322   // An external symbol may need PLT and dynamic relocation
    323   if (!rsym->isLocal()) {
    324     if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
    325        S = helper_PLT(pReloc, pParent);
    326        pReloc.target() = S + A - P;
    327     }
    328     if (pParent.getTarget().symbolNeedsDynRel(
    329                               *rsym,
    330                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
    331                               false)) {
    332       if (helper_use_relative_reloc(*rsym, pParent) ) {
    333         helper_DynRel(rsym, *pReloc.targetRef().frag(),
    334               pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
    335       }
    336       else {
    337         helper_DynRel(rsym, *pReloc.targetRef().frag(),
    338                           pReloc.targetRef().offset(), pReloc.type(), pParent);
    339           return X86Relocator::OK;
    340       }
    341     }
    342   }
    343 
    344    // perform static relocation
    345   pReloc.target() = S + A - P;
    346   return X86Relocator::OK;
    347 }
    348 
    349 // R_386_GOTOFF: S + A - GOT_ORG
    350 X86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent)
    351 {
    352   Relocator::DWord      A = pReloc.target() + pReloc.addend();
    353   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
    354   X86Relocator::Address S = pReloc.symValue();
    355 
    356   pReloc.target() = S + A - GOT_ORG;
    357   return X86Relocator::OK;
    358 }
    359 
    360 // R_386_GOTPC: GOT_ORG + A - P
    361 X86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent)
    362 {
    363   Relocator::DWord      A       = pReloc.target() + pReloc.addend();
    364   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
    365   // Apply relocation.
    366   pReloc.target() = GOT_ORG + A - pReloc.place();
    367   return X86Relocator::OK;
    368 }
    369 
    370 // R_386_GOT32: GOT(S) + A - GOT_ORG
    371 X86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent)
    372 {
    373   if (!(pReloc.symInfo()->reserved()
    374        & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
    375     return X86Relocator::BadReloc;
    376   }
    377   X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
    378   Relocator::DWord      A       = pReloc.target() + pReloc.addend();
    379   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
    380   // Apply relocation.
    381   pReloc.target() = GOT_S + A - GOT_ORG;
    382   return X86Relocator::OK;
    383 }
    384 
    385 // R_386_PLT32: PLT(S) + A - P
    386 X86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent)
    387 {
    388   // PLT_S depends on if there is a PLT entry.
    389   X86Relocator::Address PLT_S;
    390   if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
    391     PLT_S = helper_PLT(pReloc, pParent);
    392   else
    393     PLT_S = pReloc.symValue();
    394   Relocator::DWord      A = pReloc.target() + pReloc.addend();
    395   X86Relocator::Address P = pReloc.place();
    396   pReloc.target() = PLT_S + A - P;
    397   return X86Relocator::OK;
    398 }
    399 
    400 // R_386_TLS_GD:
    401 X86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent)
    402 {
    403   // global-dynamic
    404   ResolveInfo* rsym = pReloc.symInfo();
    405   // must reserve two pairs of got and dynamic relocation
    406   if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
    407      return X86Relocator::BadReloc;
    408   }
    409 
    410   X86_32GNULDBackend& ld_backend = pParent.getTarget();
    411   ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
    412   // setup corresponding got and dynamic relocatio entries:
    413   // get first got entry, if there is already a got entry for rsym, then apply
    414   // this relocation to the got entry directly. If not, setup the corresponding
    415   // got and dyn relocation entries
    416   X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
    417 
    418   if (NULL == got_entry1) {
    419     // get and init two got entries if not exist
    420     got_entry1 = ld_backend.getGOT().consume();
    421     pParent.getSymGOTMap().record(*rsym, *got_entry1);
    422     X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume();
    423     got_entry1->setValue(0x0);
    424     got_entry2->setValue(0x0);
    425     // setup dyn rel for get_entry1
    426     Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
    427                                         llvm::ELF::R_386_TLS_DTPMOD32, pParent);
    428     if (rsym->isLocal()) {
    429       // for local symbol, set got_entry2 to symbol value
    430       got_entry2->setValue(pReloc.symValue());
    431 
    432       // for local tls symbol, add rel entry against the section symbol this
    433       // symbol belong to (.tdata or .tbss)
    434       const LDSection* sym_sect =
    435          &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
    436       ResolveInfo* sect_sym = NULL;
    437       if (&file_format->getTData() == sym_sect)
    438         sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo();
    439       else
    440         sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo();
    441       rel_entry1.setSymInfo(sect_sym);
    442     }
    443     else {
    444       // for non-local symbol, add a pair of rel entries against this symbol
    445       // for those two got entries
    446       helper_DynRel(rsym, *got_entry2, 0x0,
    447                                         llvm::ELF::R_386_TLS_DTPOFF32, pParent);
    448     }
    449   }
    450 
    451   // perform relocation to the first got entry
    452   Relocator::DWord A = pReloc.target() + pReloc.addend();
    453   // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
    454   // .got.plt section)
    455   X86Relocator::Address GOT_OFF =
    456      file_format->getGOT().addr() +
    457      got_entry1->getOffset() -
    458      file_format->getGOTPLT().addr();
    459   pReloc.target() = GOT_OFF + A;
    460   return X86Relocator::OK;
    461 }
    462 
    463 // R_386_TLS_LDM
    464 X86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent)
    465 {
    466   // FIXME: no linker optimization for TLS relocation
    467   const X86_32GOTEntry& got_entry = pParent.getTarget().getTLSModuleID();
    468 
    469   // All GOT offsets are relative to the end of the GOT.
    470   X86Relocator::SWord GOT_S = got_entry.getOffset() -
    471                                       (pParent.getTarget().getGOTPLT().addr() -
    472                                        pParent.getTarget().getGOT().addr());
    473   Relocator::DWord A = pReloc.target() + pReloc.addend();
    474   pReloc.target() = GOT_S + A;
    475 
    476   return X86Relocator::OK;
    477 }
    478 
    479 // R_386_TLS_LDO_32
    480 X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent)
    481 {
    482   // FIXME: no linker optimization for TLS relocation
    483   Relocator::DWord A = pReloc.target() + pReloc.addend();
    484   X86Relocator::Address S = pReloc.symValue();
    485   pReloc.target() = S + A;
    486   return X86Relocator::OK;
    487 }
    488 
    489 // R_X86_TLS_IE
    490 X86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent)
    491 {
    492   ResolveInfo* rsym = pReloc.symInfo();
    493   if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
    494      return X86Relocator::BadReloc;
    495   }
    496 
    497   if (rsym->reserved() & X86GNULDBackend::ReserveRel) {
    498     // when building shared object, set up a RELATIVE dynamic relocation
    499     helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(),
    500                                             llvm::ELF::R_386_RELATIVE, pParent);
    501   }
    502 
    503   // set up the got and dynamic relocation entries if not exist
    504   X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
    505   if (NULL == got_entry) {
    506     // set got entry
    507     X86_32GNULDBackend& ld_backend = pParent.getTarget();
    508     got_entry = ld_backend.getGOT().consume();
    509     pParent.getSymGOTMap().record(*rsym, *got_entry);
    510     got_entry->setValue(0x0);
    511     // set relocation entry
    512     Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
    513     rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
    514     rel_entry.setSymInfo(rsym);
    515     rel_entry.targetRef().assign(*got_entry);
    516   }
    517 
    518   // perform relocation to the absolute address of got_entry
    519   X86Relocator::Address GOT_S =
    520                  pParent.getTarget().getGOT().addr() + got_entry->getOffset();
    521 
    522   Relocator::DWord A = pReloc.target() + pReloc.addend();
    523   pReloc.target() = GOT_S + A;
    524 
    525   return X86Relocator::OK;
    526 }
    527 
    528 // R_386_TLS_GOTIE
    529 X86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent)
    530 {
    531   ResolveInfo* rsym = pReloc.symInfo();
    532   if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
    533      return X86Relocator::BadReloc;
    534   }
    535 
    536   // set up the got and dynamic relocation entries if not exist
    537   X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
    538   if (NULL == got_entry) {
    539     // set got entry
    540     X86_32GNULDBackend& ld_backend = pParent.getTarget();
    541     got_entry = ld_backend.getGOT().consume();
    542     pParent.getSymGOTMap().record(*rsym, *got_entry);
    543     got_entry->setValue(0x0);
    544     // set relocation entry
    545     Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
    546     rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
    547     rel_entry.setSymInfo(rsym);
    548     rel_entry.targetRef().assign(*got_entry);
    549   }
    550 
    551   // All GOT offsets are relative to the end of the GOT.
    552   X86Relocator::SWord GOT_S = got_entry->getOffset() -
    553     (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
    554   Relocator::DWord A = pReloc.target() + pReloc.addend();
    555   pReloc.target() = GOT_S + A;
    556 
    557   return X86Relocator::OK;
    558 }
    559 
    560 // R_X86_TLS_LE
    561 X86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent)
    562 {
    563   ResolveInfo* rsym = pReloc.symInfo();
    564   if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) {
    565     helper_DynRel(rsym,
    566                   *pReloc.targetRef().frag(),
    567                   pReloc.targetRef().offset(),
    568                   llvm::ELF::R_386_TLS_TPOFF,
    569                   pParent);
    570     return X86Relocator::OK;
    571   }
    572 
    573   // perform static relocation
    574   // get TLS segment
    575   ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
    576                                        llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
    577   Relocator::DWord A = pReloc.target() + pReloc.addend();
    578   X86Relocator::Address S = pReloc.symValue();
    579   pReloc.target() = S + A - tls_seg->memsz();
    580   return X86Relocator::OK;
    581 }
    582 
    583 X86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent)
    584 {
    585   return X86Relocator::Unsupport;
    586 }
    587 
    588 //===--------------------------------------------------------------------===//
    589 // Relocation Functions and Tables
    590 //===--------------------------------------------------------------------===//
    591 DECL_X86_64_APPLY_RELOC_FUNCS
    592 
    593 /// the prototype of applying function
    594 typedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc,
    595 						     X86_64Relocator& pParent);
    596 
    597 // the table entry of applying functions
    598 struct X86_64ApplyFunctionTriple
    599 {
    600   X86_64ApplyFunctionType func;
    601   unsigned int type;
    602   const char* name;
    603   unsigned int size;
    604 };
    605 
    606 // declare the table of applying functions
    607 static const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = {
    608   DECL_X86_64_APPLY_RELOC_FUNC_PTRS
    609 };
    610 
    611 //===--------------------------------------------------------------------===//
    612 // X86_64Relocator
    613 //===--------------------------------------------------------------------===//
    614 X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent)
    615   : X86Relocator(), m_Target(pParent) {
    616 }
    617 
    618 Relocator::Result
    619 X86_64Relocator::applyRelocation(Relocation& pRelocation)
    620 {
    621   Relocation::Type type = pRelocation.type();
    622 
    623   if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) {
    624     return Unknown;
    625   }
    626 
    627   // apply the relocation
    628   return X86_64ApplyFunctions[type].func(pRelocation, *this);
    629 }
    630 
    631 const char* X86_64Relocator::getName(Relocation::Type pType) const
    632 {
    633   return X86_64ApplyFunctions[pType].name;
    634 }
    635 
    636 Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const
    637 {
    638   return X86_64ApplyFunctions[pType].size;
    639 }
    640 
    641 /// helper_DynRel - Get an relocation entry in .rela.dyn
    642 static
    643 Relocation& helper_DynRel(ResolveInfo* pSym,
    644                           Fragment& pFrag,
    645                           uint64_t pOffset,
    646                           X86Relocator::Type pType,
    647                           X86_64Relocator& pParent)
    648 {
    649   X86_64GNULDBackend& ld_backend = pParent.getTarget();
    650   Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
    651   rel_entry.setType(pType);
    652   rel_entry.targetRef().assign(pFrag, pOffset);
    653   if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym)
    654     rel_entry.setSymInfo(0);
    655   else
    656     rel_entry.setSymInfo(pSym);
    657 
    658   return rel_entry;
    659 }
    660 
    661 
    662 /// helper_use_relative_reloc - Check if symbol can use relocation
    663 /// R_X86_64_RELATIVE
    664 static bool
    665 helper_use_relative_reloc(const ResolveInfo& pSym,
    666                           const X86_64Relocator& pFactory)
    667 
    668 {
    669   // if symbol is dynamic or undefine or preemptible
    670   if (pSym.isDyn() ||
    671       pSym.isUndef() ||
    672       pFactory.getTarget().isSymbolPreemptible(pSym))
    673     return false;
    674   return true;
    675 }
    676 
    677 static
    678 X86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
    679 					X86_64Relocator& pParent)
    680 {
    681   // rsym - The relocation target symbol
    682   ResolveInfo* rsym = pReloc.symInfo();
    683   X86_64GNULDBackend& ld_backend = pParent.getTarget();
    684 
    685   X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
    686   if (NULL != got_entry)
    687     return *got_entry;
    688 
    689   // not found
    690   got_entry = ld_backend.getGOT().consume();
    691   pParent.getSymGOTMap().record(*rsym, *got_entry);
    692 
    693   // If we first get this GOT entry, we should initialize it.
    694   if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
    695     // No corresponding dynamic relocation, initialize to the symbol value.
    696     got_entry->setValue(pReloc.symValue());
    697   }
    698   else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
    699     // Initialize got_entry content and the corresponding dynamic relocation.
    700     if (helper_use_relative_reloc(*rsym, pParent)) {
    701       Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0,
    702 					    llvm::ELF::R_X86_64_RELATIVE,
    703 					    pParent);
    704       rel_entry.setAddend(pReloc.symValue());
    705     }
    706     else {
    707       helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT,
    708 		    pParent);
    709     }
    710     got_entry->setValue(0);
    711   }
    712   else {
    713     fatal(diag::reserve_entry_number_mismatch_got);
    714   }
    715   return *got_entry;
    716 }
    717 
    718 static
    719 X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
    720 {
    721   return pParent.getTarget().getGOT().addr();
    722 }
    723 
    724 static
    725 X86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent)
    726 {
    727   X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
    728   return got_entry.getOffset();
    729 }
    730 
    731 static
    732 PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
    733 				      X86_64Relocator& pParent)
    734 {
    735   // rsym - The relocation target symbol
    736   ResolveInfo* rsym = pReloc.symInfo();
    737   X86_64GNULDBackend& ld_backend = pParent.getTarget();
    738 
    739   PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
    740   if (NULL != plt_entry)
    741     return *plt_entry;
    742 
    743   // not found
    744   plt_entry = ld_backend.getPLT().consume();
    745   pParent.getSymPLTMap().record(*rsym, *plt_entry);
    746   // If we first get this PLT entry, we should initialize it.
    747   if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
    748     X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
    749     assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
    750     gotplt_entry = ld_backend.getGOTPLT().consume();
    751     pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
    752     // init the corresponding rel entry in .rel.plt
    753     Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
    754     rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
    755     rel_entry.targetRef().assign(*gotplt_entry);
    756     rel_entry.setSymInfo(rsym);
    757   }
    758   else {
    759     fatal(diag::reserve_entry_number_mismatch_plt);
    760   }
    761 
    762   return *plt_entry;
    763 }
    764 
    765 static
    766 X86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent)
    767 {
    768   return pParent.getTarget().getPLT().addr();
    769 }
    770 
    771 static
    772 X86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent)
    773 {
    774   PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
    775   return helper_PLT_ORG(pParent) + plt_entry.getOffset();
    776 }
    777 
    778 //
    779 // R_X86_64_NONE
    780 X86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent)
    781 {
    782   return X86Relocator::OK;
    783 }
    784 
    785 // R_X86_64_64: S + A
    786 // R_X86_64_32:
    787 // R_X86_64_16:
    788 // R_X86_64_8
    789 X86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent)
    790 {
    791   ResolveInfo* rsym = pReloc.symInfo();
    792   Relocator::DWord A = pReloc.addend();
    793   Relocator::DWord S = pReloc.symValue();
    794   bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
    795                               *rsym,
    796                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
    797                               true);
    798 
    799   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
    800   // If the flag of target section is not ALLOC, we will not scan this relocation
    801   // but perform static relocation. (e.g., applying .debug section)
    802   if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
    803     pReloc.target() = S + A;
    804     return X86Relocator::OK;
    805   }
    806 
    807   Relocation::Type pointerRel = pParent.getTarget().getPointerRel();
    808 
    809   // A local symbol may need REL Type dynamic relocation
    810   if (rsym->isLocal() && has_dyn_rel) {
    811     if (pointerRel == pReloc.type()) {
    812       Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
    813 					    pReloc.targetRef().offset(),
    814 					    llvm::ELF::R_X86_64_RELATIVE,
    815 					    pParent);
    816       rel_entry.setAddend(S + A);
    817     }
    818     else {
    819       // FIXME: check Section symbol
    820       Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
    821 					    pReloc.targetRef().offset(),
    822 					    pReloc.type(), pParent);
    823       rel_entry.setAddend(S + A);
    824     }
    825     return X86Relocator::OK;
    826   }
    827 
    828   // An external symbol may need PLT and dynamic relocation
    829   if (!rsym->isLocal()) {
    830     // If we generate a dynamic relocation for a place with explicit
    831     // addend, there is no need to perform static relocation on it.
    832     if (has_dyn_rel) {
    833       Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
    834 					    pReloc.targetRef().offset(),
    835 					    llvm::ELF::R_X86_64_RELATIVE,
    836 					    pParent);
    837       // Copy addend.
    838       rel_entry.setAddend(A);
    839       return X86Relocator::OK;
    840     }
    841     else if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
    842       S = helper_PLT(pReloc, pParent);
    843     }
    844   }
    845 
    846   // perform static relocation
    847   pReloc.target() = S + A;
    848   return X86Relocator::OK;
    849 }
    850 
    851 // R_X86_64_32S: S + A
    852 X86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent)
    853 {
    854   ResolveInfo* rsym = pReloc.symInfo();
    855   Relocator::DWord A = pReloc.addend();
    856   Relocator::DWord S = pReloc.symValue();
    857   bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
    858                               *rsym,
    859                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
    860                               true);
    861 
    862   // There should be no dynamic relocations for R_X86_64_32S.
    863   if (has_dyn_rel)
    864     return X86Relocator::BadReloc;
    865 
    866   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
    867   // If the flag of target section is not ALLOC, we will not scan this relocation
    868   // but perform static relocation. (e.g., applying .debug section)
    869   // An external symbol may need PLT and dynamic relocation
    870   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) &&
    871       !rsym->isLocal() && rsym->reserved() & X86GNULDBackend::ReservePLT)
    872     S = helper_PLT(pReloc, pParent);
    873 
    874   // Check 32-bit signed overflow.
    875   Relocator::SWord V = S + A;
    876   if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000))
    877     return X86Relocator::Overflow;
    878 
    879   // perform static relocation
    880   pReloc.target() = S + A;
    881   return X86Relocator::OK;
    882 }
    883 
    884 // R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
    885 X86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent)
    886 {
    887   if (!(pReloc.symInfo()->reserved()
    888        & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
    889     return X86Relocator::BadReloc;
    890   }
    891   X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
    892   Relocator::DWord      A       = pReloc.addend();
    893   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
    894   // Apply relocation.
    895   pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place();
    896   return X86Relocator::OK;
    897 }
    898 
    899 // R_X86_64_PLT32: PLT(S) + A - P
    900 X86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent)
    901 {
    902   // PLT_S depends on if there is a PLT entry.
    903   X86Relocator::Address PLT_S;
    904   if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
    905     PLT_S = helper_PLT(pReloc, pParent);
    906   else
    907     PLT_S = pReloc.symValue();
    908   Relocator::DWord      A = pReloc.addend();
    909   X86Relocator::Address P = pReloc.place();
    910   pReloc.target() = PLT_S + A - P;
    911   return X86Relocator::OK;
    912 }
    913 
    914 // R_X86_64_PC32: S + A - P
    915 // R_X86_64_PC16
    916 // R_X86_64_PC8
    917 X86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent)
    918 {
    919   ResolveInfo* rsym = pReloc.symInfo();
    920   Relocator::DWord A = pReloc.addend();
    921   Relocator::DWord S = pReloc.symValue();
    922   Relocator::DWord P = pReloc.place();
    923 
    924   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
    925   // If the flag of target section is not ALLOC, we will not scan this relocation
    926   // but perform static relocation. (e.g., applying .debug section)
    927   if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
    928     pReloc.target() = S + A - P;
    929     return X86Relocator::OK;
    930   }
    931 
    932   // An external symbol may need PLT and dynamic relocation
    933   if (!rsym->isLocal()) {
    934     if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
    935        S = helper_PLT(pReloc, pParent);
    936        pReloc.target() = S + A - P;
    937     }
    938     if (pParent.getTarget().symbolNeedsDynRel(
    939                               *rsym,
    940                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
    941                               false)) {
    942           return X86Relocator::Overflow;
    943     }
    944   }
    945 
    946    // perform static relocation
    947   pReloc.target() = S + A - P;
    948   return X86Relocator::OK;
    949 }
    950 
    951 X86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent)
    952 {
    953   return X86Relocator::Unsupport;
    954 }
    955