Home | History | Annotate | Download | only in Mips
      1 //===- MipsRelocator.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 "MipsRelocator.h"
     10 #include "MipsRelocationFunctions.h"
     11 
     12 #include "mcld/IRBuilder.h"
     13 #include "mcld/LinkerConfig.h"
     14 #include "mcld/Object/ObjectBuilder.h"
     15 #include "mcld/Support/MsgHandling.h"
     16 #include "mcld/Target/OutputRelocSection.h"
     17 #include "mcld/LD/ELFFileFormat.h"
     18 
     19 #include <llvm/ADT/Twine.h>
     20 #include <llvm/Support/ELF.h>
     21 
     22 namespace mcld {
     23 
     24 //===----------------------------------------------------------------------===//
     25 // MipsRelocationInfo
     26 //===----------------------------------------------------------------------===//
     27 class MipsRelocationInfo {
     28  public:
     29   static bool HasSubType(const Relocation& pParent, Relocation::Type pType) {
     30     if (llvm::ELF::R_MIPS_NONE == pType)
     31       return true;
     32 
     33     for (Relocation::Type type = pParent.type();
     34          llvm::ELF::R_MIPS_NONE != (type & 0xff);
     35          type >>= 8) {
     36       if ((type & 0xff) == pType)
     37         return true;
     38     }
     39 
     40     return false;
     41   }
     42 
     43   MipsRelocationInfo(Relocation& pParent, bool pIsRel)
     44       : m_Parent(&pParent),
     45         m_Type(pParent.type()),
     46         m_Addend(pIsRel ? pParent.target() : pParent.addend()),
     47         m_Symbol(pParent.symValue()),
     48         m_Result(pParent.target()) {}
     49 
     50   bool isNone() const { return llvm::ELF::R_MIPS_NONE == type(); }
     51   bool isFirst() const { return type() == (parent().type() & 0xff); }
     52   bool isLast() const { return llvm::ELF::R_MIPS_NONE == (m_Type >> 8); }
     53 
     54   MipsRelocationInfo next() const {
     55     return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result());
     56   }
     57 
     58   const Relocation& parent() const { return *m_Parent; }
     59 
     60   Relocation& parent() { return *m_Parent; }
     61 
     62   Relocation::Type type() const { return m_Type & 0xff; }
     63 
     64   Relocation::DWord A() const { return m_Addend; }
     65 
     66   Relocation::DWord S() const { return m_Symbol; }
     67 
     68   Relocation::DWord P() const { return parent().place(); }
     69 
     70   Relocation::DWord result() const { return m_Result; }
     71 
     72   Relocation::DWord& result() { return m_Result; }
     73 
     74  private:
     75   Relocation* m_Parent;
     76   Relocation::Type m_Type;
     77   Relocation::DWord m_Addend;
     78   Relocation::DWord m_Symbol;
     79   Relocation::DWord m_Result;
     80 
     81   MipsRelocationInfo(Relocation& pParent, Relocation::Type pType,
     82                      Relocation::DWord pResult, Relocation::DWord pAddend)
     83       : m_Parent(&pParent),
     84         m_Type(pType),
     85         m_Addend(pAddend),
     86         m_Symbol(0),
     87         m_Result(pResult) {}
     88 };
     89 
     90 static void helper_PLT_init(MipsRelocationInfo& pReloc,
     91                             MipsRelocator& pParent) {
     92   ResolveInfo* rsym = pReloc.parent().symInfo();
     93   assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL && "PLT entry exists");
     94 
     95   MipsGNULDBackend& backend = pParent.getTarget();
     96   PLTEntryBase* pltEntry = backend.getPLT().create();
     97   pParent.getSymPLTMap().record(*rsym, *pltEntry);
     98 
     99   assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL &&
    100          "PLT entry not exist, but DynRel entry exist!");
    101   Fragment* gotpltEntry = backend.getGOTPLT().create();
    102   pParent.getSymGOTPLTMap().record(*rsym, *gotpltEntry);
    103 
    104   Relocation* relEntry = backend.getRelPLT().create();
    105   relEntry->setType(llvm::ELF::R_MIPS_JUMP_SLOT);
    106   relEntry->targetRef().assign(*gotpltEntry);
    107   relEntry->setSymInfo(rsym);
    108 }
    109 
    110 static Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
    111                                                  MipsRelocator& pParent) {
    112   PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
    113   assert(plt_entry != NULL);
    114   return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
    115 }
    116 
    117 //===----------------------------------------------------------------------===//
    118 // Relocation Functions and Tables
    119 //===----------------------------------------------------------------------===//
    120 DECL_MIPS_APPLY_RELOC_FUNCS
    121 
    122 /// the prototype of applying function
    123 typedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&,
    124                                                MipsRelocator& pParent);
    125 
    126 // the table entry of applying functions
    127 struct ApplyFunctionTriple {
    128   ApplyFunctionType func;
    129   unsigned int type;
    130   const char* name;
    131   unsigned int size;
    132 };
    133 
    134 // declare the table of applying functions
    135 static const ApplyFunctionTriple ApplyFunctions[] = {
    136     DECL_MIPS_APPLY_RELOC_FUNC_PTRS};
    137 
    138 //===----------------------------------------------------------------------===//
    139 // MipsRelocator
    140 //===----------------------------------------------------------------------===//
    141 MipsRelocator::MipsRelocator(MipsGNULDBackend& pParent,
    142                              const LinkerConfig& pConfig)
    143     : Relocator(pConfig),
    144       m_Target(pParent),
    145       m_pApplyingInput(NULL),
    146       m_CurrentLo16Reloc(NULL) {
    147 }
    148 
    149 Relocator::Result MipsRelocator::applyRelocation(Relocation& pReloc) {
    150   // If m_CurrentLo16Reloc is not NULL we are processing
    151   // postponed relocation. Otherwise check relocation type
    152   // and postpone it for later handling.
    153   if (m_CurrentLo16Reloc == NULL && isPostponed(pReloc)) {
    154     postponeRelocation(pReloc);
    155     return OK;
    156   }
    157 
    158   for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone();
    159        info = info.next()) {
    160     if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0]))
    161       return Unknown;
    162 
    163     const ApplyFunctionTriple& triple = ApplyFunctions[info.type()];
    164 
    165     Result res = triple.func(info, *this);
    166     if (OK != res)
    167       return res;
    168 
    169     if (info.isLast()) {
    170       uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size);
    171       pReloc.target() &= ~mask;
    172       pReloc.target() |= info.result() & mask;
    173     }
    174   }
    175 
    176   return OK;
    177 }
    178 
    179 const char* MipsRelocator::getName(Relocation::Type pType) const {
    180   return ApplyFunctions[pType & 0xff].name;
    181 }
    182 
    183 void MipsRelocator::scanRelocation(Relocation& pReloc,
    184                                    IRBuilder& pBuilder,
    185                                    Module& pModule,
    186                                    LDSection& pSection,
    187                                    Input& pInput) {
    188   // rsym - The relocation target symbol
    189   ResolveInfo* rsym = pReloc.symInfo();
    190   assert(rsym != NULL &&
    191          "ResolveInfo of relocation not set while scanRelocation");
    192 
    193   // Skip relocation against _gp_disp
    194   if (getTarget().getGpDispSymbol() != NULL &&
    195       rsym == getTarget().getGpDispSymbol()->resolveInfo())
    196     return;
    197 
    198   assert(pSection.getLink() != NULL);
    199   if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0)
    200     return;
    201 
    202   for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone();
    203        info = info.next()) {
    204     // We test isLocal or if pInputSym is not a dynamic symbol
    205     // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
    206     // Don't put undef symbols into local entries.
    207     if (isLocalReloc(*rsym))
    208       scanLocalReloc(info, pBuilder, pSection);
    209     else
    210       scanGlobalReloc(info, pBuilder, pSection);
    211 
    212     if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo()))
    213       getTarget().addNonPICBranchSym(pReloc.symInfo());
    214   }
    215 
    216   // Check if we should issue undefined reference
    217   // for the relocation target symbol.
    218   if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
    219     issueUndefRef(pReloc, pSection, pInput);
    220 }
    221 
    222 bool MipsRelocator::initializeScan(Input& pInput) {
    223   if (LinkerConfig::Object != config().codeGenType())
    224     getTarget().getGOT().initializeScan(pInput);
    225   return true;
    226 }
    227 
    228 bool MipsRelocator::finalizeScan(Input& pInput) {
    229   if (LinkerConfig::Object != config().codeGenType())
    230     getTarget().getGOT().finalizeScan(pInput);
    231   return true;
    232 }
    233 
    234 bool MipsRelocator::initializeApply(Input& pInput) {
    235   m_pApplyingInput = &pInput;
    236   return true;
    237 }
    238 
    239 bool MipsRelocator::finalizeApply(Input& pInput) {
    240   m_pApplyingInput = NULL;
    241   return true;
    242 }
    243 
    244 void MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc,
    245                                    IRBuilder& pBuilder,
    246                                    const LDSection& pSection) {
    247   ResolveInfo* rsym = pReloc.parent().symInfo();
    248 
    249   switch (pReloc.type()) {
    250     case llvm::ELF::R_MIPS_NONE:
    251     case llvm::ELF::R_MIPS_16:
    252       break;
    253     case llvm::ELF::R_MIPS_32:
    254     case llvm::ELF::R_MIPS_64:
    255       if (pReloc.isFirst() && LinkerConfig::DynObj == config().codeGenType()) {
    256         // TODO: (simon) The gold linker does not create an entry in .rel.dyn
    257         // section if the symbol section flags contains SHF_EXECINSTR.
    258         // 1. Find the reason of this condition.
    259         // 2. Check this condition here.
    260         getTarget().getRelDyn().reserveEntry();
    261         rsym->setReserved(rsym->reserved() | ReserveRel);
    262         getTarget().checkAndSetHasTextRel(*pSection.getLink());
    263       }
    264       break;
    265     case llvm::ELF::R_MIPS_REL32:
    266     case llvm::ELF::R_MIPS_26:
    267     case llvm::ELF::R_MIPS_HI16:
    268     case llvm::ELF::R_MIPS_LO16:
    269     case llvm::ELF::R_MIPS_SHIFT5:
    270     case llvm::ELF::R_MIPS_SHIFT6:
    271     case llvm::ELF::R_MIPS_SUB:
    272     case llvm::ELF::R_MIPS_INSERT_A:
    273     case llvm::ELF::R_MIPS_INSERT_B:
    274     case llvm::ELF::R_MIPS_DELETE:
    275     case llvm::ELF::R_MIPS_HIGHER:
    276     case llvm::ELF::R_MIPS_HIGHEST:
    277     case llvm::ELF::R_MIPS_SCN_DISP:
    278     case llvm::ELF::R_MIPS_REL16:
    279     case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
    280     case llvm::ELF::R_MIPS_PJUMP:
    281     case llvm::ELF::R_MIPS_RELGOT:
    282     case llvm::ELF::R_MIPS_JALR:
    283     case llvm::ELF::R_MIPS_GLOB_DAT:
    284     case llvm::ELF::R_MIPS_COPY:
    285     case llvm::ELF::R_MIPS_JUMP_SLOT:
    286       break;
    287     case llvm::ELF::R_MIPS_GOT16:
    288     case llvm::ELF::R_MIPS_CALL16:
    289     case llvm::ELF::R_MIPS_GOT_HI16:
    290     case llvm::ELF::R_MIPS_CALL_HI16:
    291     case llvm::ELF::R_MIPS_GOT_LO16:
    292     case llvm::ELF::R_MIPS_CALL_LO16:
    293     case llvm::ELF::R_MIPS_GOT_DISP:
    294     case llvm::ELF::R_MIPS_GOT_PAGE:
    295     case llvm::ELF::R_MIPS_GOT_OFST:
    296       if (getTarget()
    297               .getGOT()
    298               .reserveLocalEntry(*rsym, pReloc.type(), pReloc.A())) {
    299         if (getTarget().getGOT().hasMultipleGOT())
    300           getTarget().checkAndSetHasTextRel(*pSection.getLink());
    301       }
    302       break;
    303     case llvm::ELF::R_MIPS_GPREL32:
    304     case llvm::ELF::R_MIPS_GPREL16:
    305     case llvm::ELF::R_MIPS_LITERAL:
    306       break;
    307     case llvm::ELF::R_MIPS_TLS_GD:
    308       getTarget().getGOT().reserveTLSGdEntry(*rsym);
    309       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    310       break;
    311     case llvm::ELF::R_MIPS_TLS_LDM:
    312       getTarget().getGOT().reserveTLSLdmEntry();
    313       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    314       break;
    315     case llvm::ELF::R_MIPS_TLS_GOTTPREL:
    316       getTarget().getGOT().reserveTLSGotEntry(*rsym);
    317       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    318       break;
    319     case llvm::ELF::R_MIPS_TLS_DTPMOD32:
    320     case llvm::ELF::R_MIPS_TLS_DTPREL32:
    321     case llvm::ELF::R_MIPS_TLS_DTPMOD64:
    322     case llvm::ELF::R_MIPS_TLS_DTPREL64:
    323     case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
    324     case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
    325     case llvm::ELF::R_MIPS_TLS_TPREL32:
    326     case llvm::ELF::R_MIPS_TLS_TPREL64:
    327     case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
    328     case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
    329       break;
    330     case llvm::ELF::R_MIPS_PC16:
    331     case llvm::ELF::R_MIPS_PC32:
    332     case llvm::ELF::R_MIPS_PC18_S3:
    333     case llvm::ELF::R_MIPS_PC19_S2:
    334     case llvm::ELF::R_MIPS_PC21_S2:
    335     case llvm::ELF::R_MIPS_PC26_S2:
    336     case llvm::ELF::R_MIPS_PCHI16:
    337     case llvm::ELF::R_MIPS_PCLO16:
    338       break;
    339     default:
    340       fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type())
    341                                       << rsym->name();
    342   }
    343 }
    344 
    345 void MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc,
    346                                     IRBuilder& pBuilder,
    347                                     const LDSection& pSection) {
    348   ResolveInfo* rsym = pReloc.parent().symInfo();
    349   bool hasPLT = rsym->reserved() & ReservePLT;
    350 
    351   switch (pReloc.type()) {
    352     case llvm::ELF::R_MIPS_NONE:
    353     case llvm::ELF::R_MIPS_INSERT_A:
    354     case llvm::ELF::R_MIPS_INSERT_B:
    355     case llvm::ELF::R_MIPS_DELETE:
    356     case llvm::ELF::R_MIPS_TLS_DTPMOD64:
    357     case llvm::ELF::R_MIPS_TLS_DTPREL64:
    358     case llvm::ELF::R_MIPS_REL16:
    359     case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
    360     case llvm::ELF::R_MIPS_PJUMP:
    361     case llvm::ELF::R_MIPS_RELGOT:
    362     case llvm::ELF::R_MIPS_TLS_TPREL64:
    363       break;
    364     case llvm::ELF::R_MIPS_32:
    365     case llvm::ELF::R_MIPS_64:
    366       if (pReloc.isFirst() &&
    367           getTarget().symbolNeedsDynRel(*rsym, hasPLT, true)) {
    368         getTarget().getRelDyn().reserveEntry();
    369         rsym->setReserved(rsym->reserved() | ReserveRel);
    370         getTarget().checkAndSetHasTextRel(*pSection.getLink());
    371         if (!getTarget().symbolFinalValueIsKnown(*rsym))
    372           getTarget().getGOT().reserveGlobalEntry(*rsym);
    373       }
    374       break;
    375     case llvm::ELF::R_MIPS_HI16:
    376     case llvm::ELF::R_MIPS_LO16:
    377       if (getTarget().symbolNeedsDynRel(*rsym, hasPLT, true) ||
    378           getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) {
    379         getTarget().getRelDyn().reserveEntry();
    380         LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym);
    381         addCopyReloc(*cpySym.resolveInfo());
    382       }
    383       break;
    384     case llvm::ELF::R_MIPS_GOT16:
    385     case llvm::ELF::R_MIPS_CALL16:
    386     case llvm::ELF::R_MIPS_GOT_DISP:
    387     case llvm::ELF::R_MIPS_GOT_HI16:
    388     case llvm::ELF::R_MIPS_CALL_HI16:
    389     case llvm::ELF::R_MIPS_GOT_LO16:
    390     case llvm::ELF::R_MIPS_CALL_LO16:
    391     case llvm::ELF::R_MIPS_GOT_PAGE:
    392     case llvm::ELF::R_MIPS_GOT_OFST:
    393       if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
    394         if (getTarget().getGOT().hasMultipleGOT())
    395           getTarget().checkAndSetHasTextRel(*pSection.getLink());
    396       }
    397       break;
    398     case llvm::ELF::R_MIPS_LITERAL:
    399     case llvm::ELF::R_MIPS_GPREL32:
    400       fatal(diag::invalid_global_relocation) << static_cast<int>(pReloc.type())
    401                                              << rsym->name();
    402       break;
    403     case llvm::ELF::R_MIPS_GPREL16:
    404       break;
    405     case llvm::ELF::R_MIPS_26:
    406       // Create a PLT entry if the symbol requires it and does not have it.
    407       if (getTarget().symbolNeedsPLT(*rsym) && !hasPLT) {
    408         helper_PLT_init(pReloc, *this);
    409         rsym->setReserved(rsym->reserved() | ReservePLT);
    410       }
    411       break;
    412     case llvm::ELF::R_MIPS_16:
    413     case llvm::ELF::R_MIPS_SHIFT5:
    414     case llvm::ELF::R_MIPS_SHIFT6:
    415     case llvm::ELF::R_MIPS_SUB:
    416     case llvm::ELF::R_MIPS_HIGHER:
    417     case llvm::ELF::R_MIPS_HIGHEST:
    418     case llvm::ELF::R_MIPS_SCN_DISP:
    419       break;
    420     case llvm::ELF::R_MIPS_TLS_GD:
    421       getTarget().getGOT().reserveTLSGdEntry(*rsym);
    422       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    423       break;
    424     case llvm::ELF::R_MIPS_TLS_LDM:
    425       getTarget().getGOT().reserveTLSLdmEntry();
    426       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    427       break;
    428     case llvm::ELF::R_MIPS_TLS_GOTTPREL:
    429       getTarget().getGOT().reserveTLSGotEntry(*rsym);
    430       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    431       break;
    432     case llvm::ELF::R_MIPS_TLS_DTPREL32:
    433     case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
    434     case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
    435     case llvm::ELF::R_MIPS_TLS_TPREL32:
    436     case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
    437     case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
    438       break;
    439     case llvm::ELF::R_MIPS_REL32:
    440     case llvm::ELF::R_MIPS_JALR:
    441     case llvm::ELF::R_MIPS_PC16:
    442     case llvm::ELF::R_MIPS_PC32:
    443     case llvm::ELF::R_MIPS_PC18_S3:
    444     case llvm::ELF::R_MIPS_PC19_S2:
    445     case llvm::ELF::R_MIPS_PC21_S2:
    446     case llvm::ELF::R_MIPS_PC26_S2:
    447     case llvm::ELF::R_MIPS_PCHI16:
    448     case llvm::ELF::R_MIPS_PCLO16:
    449       break;
    450     case llvm::ELF::R_MIPS_COPY:
    451     case llvm::ELF::R_MIPS_GLOB_DAT:
    452     case llvm::ELF::R_MIPS_JUMP_SLOT:
    453       fatal(diag::dynamic_relocation) << static_cast<int>(pReloc.type());
    454       break;
    455     default:
    456       fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type())
    457                                       << rsym->name();
    458   }
    459 }
    460 
    461 bool MipsRelocator::isPostponed(const Relocation& pReloc) const {
    462   if (isN64ABI())
    463     return false;
    464 
    465   if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16) ||
    466       MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_PCHI16))
    467     return true;
    468 
    469   if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) &&
    470       pReloc.symInfo()->isLocal())
    471     return true;
    472 
    473   return false;
    474 }
    475 
    476 void MipsRelocator::addCopyReloc(ResolveInfo& pSym) {
    477   Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
    478   relEntry.setType(llvm::ELF::R_MIPS_COPY);
    479   assert(pSym.outSymbol()->hasFragRef());
    480   relEntry.targetRef().assign(*pSym.outSymbol()->fragRef());
    481   relEntry.setSymInfo(&pSym);
    482 }
    483 
    484 LDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
    485                                                   const ResolveInfo& pSym) {
    486   // Get or create corresponding BSS LDSection
    487   ELFFileFormat* fileFormat = getTarget().getOutputFormat();
    488   LDSection* bssSectHdr = ResolveInfo::ThreadLocal == pSym.type()
    489                               ? &fileFormat->getTBSS()
    490                               : &fileFormat->getBSS();
    491 
    492   // Get or create corresponding BSS SectionData
    493   SectionData* bssData = bssSectHdr->hasSectionData()
    494                              ? bssSectHdr->getSectionData()
    495                              : IRBuilder::CreateSectionData(*bssSectHdr);
    496 
    497   // Determine the alignment by the symbol value
    498   // FIXME: here we use the largest alignment
    499   uint32_t addrAlign = config().targets().bitclass() / 8;
    500 
    501   // Allocate space in BSS for the copy symbol
    502   Fragment* frag = new FillFragment(0x0, 1, pSym.size());
    503   uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign);
    504   bssSectHdr->setSize(bssSectHdr->size() + size);
    505 
    506   // Change symbol binding to Global if it's a weak symbol
    507   ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
    508   if (binding == ResolveInfo::Weak)
    509     binding = ResolveInfo::Global;
    510 
    511   // Define the copy symbol in the bss section and resolve it
    512   LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    513       pSym.name(),
    514       (ResolveInfo::Type)pSym.type(),
    515       ResolveInfo::Define,
    516       binding,
    517       pSym.size(),  // size
    518       0x0,          // value
    519       FragmentRef::Create(*frag, 0x0),
    520       (ResolveInfo::Visibility)pSym.other());
    521 
    522   // Output all other alias symbols if any
    523   Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym);
    524   if (alias_list == NULL)
    525     return *cpySym;
    526 
    527   for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end();
    528        it != ie;
    529        ++it) {
    530     const ResolveInfo* alias = *it;
    531     if (alias == &pSym || !alias->isDyn())
    532       continue;
    533 
    534     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    535         alias->name(),
    536         (ResolveInfo::Type)alias->type(),
    537         ResolveInfo::Define,
    538         binding,
    539         alias->size(),  // size
    540         0x0,            // value
    541         FragmentRef::Create(*frag, 0x0),
    542         (ResolveInfo::Visibility)alias->other());
    543   }
    544 
    545   return *cpySym;
    546 }
    547 
    548 void MipsRelocator::postponeRelocation(Relocation& pReloc) {
    549   ResolveInfo* rsym = pReloc.symInfo();
    550   m_PostponedRelocs[rsym].insert(&pReloc);
    551 }
    552 
    553 void MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc) {
    554   m_CurrentLo16Reloc = &pLo16Reloc;
    555 
    556   ResolveInfo* rsym = pLo16Reloc.parent().symInfo();
    557 
    558   RelocationSet& relocs = m_PostponedRelocs[rsym];
    559   for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it)
    560     (*it)->apply(*this);
    561 
    562   m_PostponedRelocs.erase(rsym);
    563 
    564   m_CurrentLo16Reloc = NULL;
    565 }
    566 
    567 bool MipsRelocator::isGpDisp(const Relocation& pReloc) const {
    568   return strcmp("_gp_disp", pReloc.symInfo()->name()) == 0;
    569 }
    570 
    571 bool MipsRelocator::isRel() const {
    572   return config().targets().is32Bits();
    573 }
    574 
    575 bool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const {
    576   if (pSym.isUndef())
    577     return false;
    578 
    579   return pSym.isLocal() || !getTarget().isDynamicSymbol(pSym) || !pSym.isDyn();
    580 }
    581 
    582 Relocator::Address MipsRelocator::getGPAddress() {
    583   return getTarget().getGOT().getGPAddr(getApplyingInput());
    584 }
    585 
    586 Relocator::Address MipsRelocator::getTPOffset() {
    587   return getTarget().getTPOffset(getApplyingInput());
    588 }
    589 
    590 Relocator::Address MipsRelocator::getDTPOffset() {
    591   return getTarget().getDTPOffset(getApplyingInput());
    592 }
    593 
    594 Relocator::Address MipsRelocator::getGP0() {
    595   return getTarget().getGP0(getApplyingInput());
    596 }
    597 
    598 Fragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc,
    599                                           Relocation::DWord entryValue) {
    600   // rsym - The relocation target symbol
    601   ResolveInfo* rsym = pReloc.parent().symInfo();
    602   MipsGOT& got = getTarget().getGOT();
    603 
    604   assert(isLocalReloc(*rsym) &&
    605          "Attempt to get a global GOT entry for the local relocation");
    606 
    607   Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue);
    608 
    609   // Found a mapping, then return the mapped entry immediately.
    610   if (got_entry != NULL)
    611     return *got_entry;
    612 
    613   // Not found.
    614   got_entry = got.consumeLocal();
    615 
    616   if (got.isPrimaryGOTConsumed())
    617     setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), NULL);
    618   else
    619     got.setEntryValue(got_entry, entryValue);
    620 
    621   got.recordLocalEntry(rsym, entryValue, got_entry);
    622 
    623   return *got_entry;
    624 }
    625 
    626 Fragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc) {
    627   // rsym - The relocation target symbol
    628   ResolveInfo* rsym = pReloc.parent().symInfo();
    629   MipsGOT& got = getTarget().getGOT();
    630 
    631   assert(!isLocalReloc(*rsym) &&
    632          "Attempt to get a local GOT entry for the global relocation");
    633 
    634   Fragment* got_entry = got.lookupGlobalEntry(rsym);
    635 
    636   // Found a mapping, then return the mapped entry immediately.
    637   if (got_entry != NULL)
    638     return *got_entry;
    639 
    640   // Not found.
    641   got_entry = got.consumeGlobal();
    642 
    643   if (got.isPrimaryGOTConsumed())
    644     setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), rsym);
    645   else
    646     got.setEntryValue(got_entry, pReloc.parent().symValue());
    647 
    648   got.recordGlobalEntry(rsym, got_entry);
    649 
    650   return *got_entry;
    651 }
    652 
    653 Fragment& MipsRelocator::getTLSGOTEntry(MipsRelocationInfo& pReloc) {
    654   // rsym - The relocation target symbol
    655   ResolveInfo* rsym = pReloc.parent().symInfo();
    656   MipsGOT& got = getTarget().getGOT();
    657 
    658   Fragment* modEntry = got.lookupTLSEntry(rsym, pReloc.type());
    659 
    660   // Found a mapping, then return the mapped entry immediately.
    661   if (modEntry != NULL)
    662     return *modEntry;
    663 
    664   // Not found.
    665   modEntry = got.consumeTLS(pReloc.type());
    666   setupTLSDynEntry(*modEntry, rsym, pReloc.type());
    667   got.recordTLSEntry(rsym, modEntry, pReloc.type());
    668 
    669   return *modEntry;
    670 }
    671 
    672 Relocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc) {
    673   ResolveInfo* rsym = pReloc.parent().symInfo();
    674   MipsGOT& got = getTarget().getGOT();
    675 
    676   if (isLocalReloc(*rsym)) {
    677     uint64_t value = pReloc.S();
    678 
    679     if (ResolveInfo::Section == rsym->type())
    680       value += pReloc.A();
    681 
    682     return got.getGPRelOffset(getApplyingInput(),
    683                               getLocalGOTEntry(pReloc, value));
    684   } else {
    685     return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc));
    686   }
    687 }
    688 
    689 Relocator::Address MipsRelocator::getTLSGOTOffset(MipsRelocationInfo& pReloc) {
    690   MipsGOT& got = getTarget().getGOT();
    691   return got.getGPRelOffset(getApplyingInput(), getTLSGOTEntry(pReloc));
    692 }
    693 
    694 void MipsRelocator::createDynRel(MipsRelocationInfo& pReloc) {
    695   Relocator::DWord A = pReloc.A();
    696   Relocator::DWord S = pReloc.S();
    697 
    698   ResolveInfo* rsym = pReloc.parent().symInfo();
    699 
    700   if (getTarget().isDynamicSymbol(*rsym)) {
    701     setupRel32DynEntry(pReloc.parent().targetRef(), rsym);
    702     // Don't add symbol value that will be resolved by the dynamic linker.
    703     pReloc.result() = A;
    704   } else {
    705     setupRel32DynEntry(pReloc.parent().targetRef(), NULL);
    706     pReloc.result() = A + S;
    707   }
    708 
    709   if (!isLocalReloc(*rsym) && !getTarget().symbolFinalValueIsKnown(*rsym))
    710     getGlobalGOTEntry(pReloc);
    711 }
    712 
    713 uint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc) {
    714   if (isN64ABI())
    715     return pHiReloc.A();
    716 
    717   assert(m_CurrentLo16Reloc != NULL &&
    718          "There is no saved R_MIPS_LO16 relocation");
    719 
    720   uint64_t AHI = pHiReloc.A() & 0xFFFF;
    721   uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF;
    722   uint64_t AHL = (AHI << 16) + int16_t(ALO);
    723 
    724   return AHL;
    725 }
    726 
    727 bool MipsRelocator::isN64ABI() const {
    728   return config().targets().is64Bits();
    729 }
    730 
    731 uint32_t MipsRelocator::getDebugStringOffset(Relocation& pReloc) const {
    732   if (pReloc.type() != llvm::ELF::R_MIPS_32)
    733     error(diag::unsupport_reloc_for_debug_string)
    734         << getName(pReloc.type()) << "mclinker (at) googlegroups.com";
    735   if (pReloc.symInfo()->type() == ResolveInfo::Section)
    736     return pReloc.target() + pReloc.addend();
    737   else
    738     return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
    739                pReloc.target() + pReloc.addend();
    740 }
    741 
    742 void MipsRelocator::applyDebugStringOffset(Relocation& pReloc,
    743                                            uint32_t pOffset) {
    744   pReloc.target() = pOffset;
    745 }
    746 
    747 void MipsRelocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym,
    748                                      Relocation::Type pType) {
    749   Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
    750   relEntry.setType(pType);
    751   relEntry.targetRef() = pFragRef;
    752   relEntry.setSymInfo(pSym);
    753 }
    754 
    755 //===----------------------------------------------------------------------===//
    756 // Mips32Relocator
    757 //===----------------------------------------------------------------------===//
    758 Mips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent,
    759                                  const LinkerConfig& pConfig)
    760     : MipsRelocator(pParent, pConfig) {
    761 }
    762 
    763 void Mips32Relocator::setupRel32DynEntry(FragmentRef& pFragRef,
    764                                          ResolveInfo* pSym) {
    765   setupRelDynEntry(pFragRef, pSym, llvm::ELF::R_MIPS_REL32);
    766 }
    767 
    768 void Mips32Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym,
    769                                        Relocation::Type pType) {
    770   pSym = pSym->isLocal() ? nullptr : pSym;
    771   if (pType == llvm::ELF::R_MIPS_TLS_GD) {
    772     FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
    773     setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32);
    774     FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0);
    775     setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL32);
    776   } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) {
    777     FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
    778     setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32);
    779   } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) {
    780     FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
    781     setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL32);
    782   } else {
    783     llvm_unreachable("Unexpected relocation");
    784   }
    785 }
    786 
    787 Relocator::Size Mips32Relocator::getSize(Relocation::Type pType) const {
    788   return ApplyFunctions[pType & 0xff].size;
    789 }
    790 
    791 //===----------------------------------------------------------------------===//
    792 // Mips64Relocator
    793 //===----------------------------------------------------------------------===//
    794 Mips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent,
    795                                  const LinkerConfig& pConfig)
    796     : MipsRelocator(pParent, pConfig) {
    797 }
    798 
    799 void Mips64Relocator::setupRel32DynEntry(FragmentRef& pFragRef,
    800                                          ResolveInfo* pSym) {
    801   Relocation::Type type = llvm::ELF::R_MIPS_REL32 | llvm::ELF::R_MIPS_64 << 8;
    802   setupRelDynEntry(pFragRef, pSym, type);
    803 }
    804 
    805 void Mips64Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym,
    806                                        Relocation::Type pType) {
    807   pSym = pSym->isLocal() ? nullptr : pSym;
    808   if (pType == llvm::ELF::R_MIPS_TLS_GD) {
    809     FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
    810     setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64);
    811     FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0);
    812     setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL64);
    813   } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) {
    814     FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
    815     setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64);
    816   } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) {
    817     FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0);
    818     setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL64);
    819   } else {
    820     llvm_unreachable("Unexpected relocation");
    821   }
    822 }
    823 
    824 Relocator::Size Mips64Relocator::getSize(Relocation::Type pType) const {
    825   if (((pType >> 16) & 0xff) != llvm::ELF::R_MIPS_NONE)
    826     return ApplyFunctions[(pType >> 16) & 0xff].size;
    827   if (((pType >> 8) & 0xff) != llvm::ELF::R_MIPS_NONE)
    828     return ApplyFunctions[(pType >> 8) & 0xff].size;
    829   return ApplyFunctions[pType & 0xff].size;
    830 }
    831 
    832 //=========================================//
    833 // Relocation functions implementation     //
    834 //=========================================//
    835 
    836 // R_MIPS_NONE and those unsupported/deprecated relocation type
    837 static MipsRelocator::Result none(MipsRelocationInfo& pReloc,
    838                                   MipsRelocator& pParent) {
    839   return Relocator::OK;
    840 }
    841 
    842 // R_MIPS_32: S + A
    843 static MipsRelocator::Result abs32(MipsRelocationInfo& pReloc,
    844                                    MipsRelocator& pParent) {
    845   ResolveInfo* rsym = pReloc.parent().symInfo();
    846 
    847   Relocator::DWord A = pReloc.A();
    848   Relocator::DWord S = pReloc.S();
    849 
    850   LDSection& target_sect =
    851       pReloc.parent().targetRef().frag()->getParent()->getSection();
    852 
    853   // If the flag of target section is not ALLOC, we will not scan this
    854   // relocation
    855   // but perform static relocation. (e.g., applying .debug section)
    856   if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
    857     pReloc.result() = S + A;
    858     return Relocator::OK;
    859   }
    860 
    861   if (rsym->reserved() & MipsRelocator::ReserveRel) {
    862     pParent.createDynRel(pReloc);
    863     return Relocator::OK;
    864   }
    865 
    866   pReloc.result() = S + A;
    867 
    868   return Relocator::OK;
    869 }
    870 
    871 // R_MIPS_26:
    872 //   local   : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
    873 //   external: (signextend(A) + S) >> 2
    874 static MipsRelocator::Result rel26(MipsRelocationInfo& pReloc,
    875                                    MipsRelocator& pParent) {
    876   ResolveInfo* rsym = pReloc.parent().symInfo();
    877 
    878   int32_t A = pParent.isN64ABI() ? pReloc.A() : (pReloc.A() & 0x03FFFFFF) << 2;
    879   int32_t P = pReloc.P();
    880   int32_t S = rsym->reserved() & MipsRelocator::ReservePLT
    881                   ? helper_get_PLT_address(*rsym, pParent)
    882                   : pReloc.S();
    883 
    884   if (rsym->isLocal())
    885     pReloc.result() = A | ((P + 4) & 0x3F000000);
    886   else
    887     pReloc.result() = signExtend<28>(A);
    888 
    889   pReloc.result() = (pReloc.result() + S) >> 2;
    890 
    891   return Relocator::OK;
    892 }
    893 
    894 // R_MIPS_HI16:
    895 //   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
    896 //   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
    897 static MipsRelocator::Result hi16(MipsRelocationInfo& pReloc,
    898                                   MipsRelocator& pParent) {
    899   uint64_t AHL = pParent.calcAHL(pReloc);
    900 
    901   if (pParent.isGpDisp(pReloc.parent())) {
    902     int32_t P = pReloc.P();
    903     int32_t GP = pParent.getGPAddress();
    904     pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
    905   } else {
    906     int32_t S = pReloc.S();
    907     if (pParent.isN64ABI())
    908       pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16;
    909     else
    910       pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
    911   }
    912 
    913   return Relocator::OK;
    914 }
    915 
    916 // R_MIPS_LO16:
    917 //   local/external: AHL + S
    918 //   _gp_disp      : AHL + GP - P + 4
    919 static MipsRelocator::Result lo16(MipsRelocationInfo& pReloc,
    920                                   MipsRelocator& pParent) {
    921   // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16
    922   // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16
    923   // addend here.
    924   int32_t AHL = (pReloc.A() & 0xFFFF);
    925 
    926   if (pParent.isGpDisp(pReloc.parent())) {
    927     int32_t P = pReloc.P();
    928     int32_t GP = pParent.getGPAddress();
    929     pReloc.result() = AHL + GP - P + 4;
    930   } else {
    931     int32_t S = pReloc.S();
    932     pReloc.result() = AHL + S;
    933   }
    934 
    935   pParent.applyPostponedRelocations(pReloc);
    936 
    937   return Relocator::OK;
    938 }
    939 
    940 // R_MIPS_GPREL16:
    941 //   external: signextend(A) + S - GP
    942 //   local   : signextend(A) + S + GP0  GP
    943 static MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc,
    944                                      MipsRelocator& pParent) {
    945   // Remember to add the section offset to A.
    946   uint64_t A = pReloc.A();
    947   uint64_t S = pReloc.S();
    948   uint64_t GP0 = pParent.getGP0();
    949   uint64_t GP = pParent.getGPAddress();
    950 
    951   ResolveInfo* rsym = pReloc.parent().symInfo();
    952   if (rsym->isLocal())
    953     pReloc.result() = A + S + GP0 - GP;
    954   else
    955     pReloc.result() = A + S - GP;
    956 
    957   return Relocator::OK;
    958 }
    959 
    960 // R_MIPS_GOT16:
    961 //   local   : G (calculate AHL and put high 16 bit to GOT)
    962 //   external: G
    963 static MipsRelocator::Result got16(MipsRelocationInfo& pReloc,
    964                                    MipsRelocator& pParent) {
    965   if (pReloc.parent().symInfo()->isLocal()) {
    966     int32_t AHL = pParent.calcAHL(pReloc);
    967     int32_t S = pReloc.S();
    968     int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
    969 
    970     MipsGOT& got = pParent.getTarget().getGOT();
    971 
    972     Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res);
    973 
    974     pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
    975   } else {
    976     pReloc.result() = pParent.getGOTOffset(pReloc);
    977   }
    978 
    979   return Relocator::OK;
    980 }
    981 
    982 // R_MIPS_GOTHI16:
    983 //   external: (G - (short)G) >> 16 + A
    984 static MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc,
    985                                      MipsRelocator& pParent) {
    986   Relocator::Address G = pParent.getGOTOffset(pReloc);
    987   int32_t A = pReloc.A();
    988 
    989   pReloc.result() = (G - (int16_t)G) >> (16 + A);
    990 
    991   return Relocator::OK;
    992 }
    993 
    994 // R_MIPS_GOTLO16:
    995 //   external: G & 0xffff
    996 static MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc,
    997                                      MipsRelocator& pParent) {
    998   pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff;
    999 
   1000   return Relocator::OK;
   1001 }
   1002 
   1003 // R_MIPS_SUB:
   1004 //   external/local: S - A
   1005 static MipsRelocator::Result sub(MipsRelocationInfo& pReloc,
   1006                                  MipsRelocator& pParent) {
   1007   uint64_t S = pReloc.S();
   1008   uint64_t A = pReloc.A();
   1009 
   1010   pReloc.result() = S - A;
   1011 
   1012   return Relocator::OK;
   1013 }
   1014 
   1015 // R_MIPS_CALL16: G
   1016 static MipsRelocator::Result call16(MipsRelocationInfo& pReloc,
   1017                                     MipsRelocator& pParent) {
   1018   pReloc.result() = pParent.getGOTOffset(pReloc);
   1019 
   1020   return Relocator::OK;
   1021 }
   1022 
   1023 // R_MIPS_GPREL32: A + S + GP0 - GP
   1024 static MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc,
   1025                                      MipsRelocator& pParent) {
   1026   // Remember to add the section offset to A.
   1027   uint64_t A = pReloc.A();
   1028   uint64_t S = pReloc.S();
   1029   uint64_t GP0 = pParent.getGP0();
   1030   uint64_t GP = pParent.getGPAddress();
   1031 
   1032   pReloc.result() = A + S + GP0 - GP;
   1033 
   1034   return Relocator::OK;
   1035 }
   1036 
   1037 // R_MIPS_64: S + A
   1038 static MipsRelocator::Result abs64(MipsRelocationInfo& pReloc,
   1039                                    MipsRelocator& pParent) {
   1040   // FIXME (simon): Consider to merge with abs32() or use the same function
   1041   // but with another mask size.
   1042   ResolveInfo* rsym = pReloc.parent().symInfo();
   1043 
   1044   Relocator::DWord A = pReloc.A();
   1045   Relocator::DWord S = pReloc.S();
   1046 
   1047   LDSection& target_sect =
   1048       pReloc.parent().targetRef().frag()->getParent()->getSection();
   1049 
   1050   // If the flag of target section is not ALLOC, we will not scan this
   1051   // relocation
   1052   // but perform static relocation. (e.g., applying .debug section)
   1053   if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
   1054     pReloc.result() = S + A;
   1055     return Relocator::OK;
   1056   }
   1057 
   1058   if (rsym->reserved() & MipsRelocator::ReserveRel) {
   1059     pParent.createDynRel(pReloc);
   1060     return Relocator::OK;
   1061   }
   1062 
   1063   pReloc.result() = S + A;
   1064 
   1065   return Relocator::OK;
   1066 }
   1067 
   1068 // R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G
   1069 static MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc,
   1070                                      MipsRelocator& pParent) {
   1071   pReloc.result() = pParent.getGOTOffset(pReloc);
   1072 
   1073   return Relocator::OK;
   1074 }
   1075 
   1076 // R_MIPS_GOT_OFST:
   1077 static MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc,
   1078                                     MipsRelocator& pParent) {
   1079   // FIXME (simon): Needs to be implemented.
   1080   return Relocator::OK;
   1081 }
   1082 
   1083 // R_MIPS_JALR:
   1084 static MipsRelocator::Result jalr(MipsRelocationInfo& pReloc,
   1085                                   MipsRelocator& pParent) {
   1086   return Relocator::OK;
   1087 }
   1088 
   1089 // R_MIPS_PC16
   1090 static MipsRelocator::Result pc16(MipsRelocationInfo& pReloc,
   1091                                   MipsRelocator& pParent) {
   1092   int64_t A = signExtend<18>(pReloc.A() << 2);
   1093   int64_t S = pReloc.S();
   1094   int64_t P = pReloc.P();
   1095   pReloc.result() = (A + S - P) >> 2;
   1096   return Relocator::OK;
   1097 }
   1098 
   1099 // R_MIPS_PC32
   1100 static MipsRelocator::Result pc32(MipsRelocationInfo& pReloc,
   1101                                   MipsRelocator& pParent) {
   1102   int64_t A = pReloc.A();
   1103   int64_t S = pReloc.S();
   1104   int64_t P = pReloc.P();
   1105   pReloc.result() = A + S - P;
   1106   return Relocator::OK;
   1107 }
   1108 
   1109 // R_MIPS_PC18_S3
   1110 static MipsRelocator::Result pc18_s3(MipsRelocationInfo& pReloc,
   1111                                      MipsRelocator& pParent) {
   1112   int64_t A = signExtend<21>(pReloc.A() << 3);
   1113   int64_t S = pReloc.S();
   1114   int64_t P = pReloc.P();
   1115   pReloc.result() = (S + A - ((P | 7) ^ 7)) >> 3;
   1116   return Relocator::OK;
   1117 }
   1118 
   1119 // R_MIPS_PC19_S2
   1120 static MipsRelocator::Result pc19_s2(MipsRelocationInfo& pReloc,
   1121                                      MipsRelocator& pParent) {
   1122   int64_t A = signExtend<21>(pReloc.A() << 2);
   1123   int64_t S = pReloc.S();
   1124   int64_t P = pReloc.P();
   1125   pReloc.result() = (A + S - P) >> 2;
   1126   return Relocator::OK;
   1127 }
   1128 
   1129 // R_MIPS_PC21_S2
   1130 static MipsRelocator::Result pc21_s2(MipsRelocationInfo& pReloc,
   1131                                      MipsRelocator& pParent) {
   1132   int32_t A = signExtend<23>(pReloc.A() << 2);
   1133   int32_t S = pReloc.S();
   1134   int32_t P = pReloc.P();
   1135   pReloc.result() = (A + S - P) >> 2;
   1136   return Relocator::OK;
   1137 }
   1138 
   1139 // R_MIPS_PC26_S2
   1140 static MipsRelocator::Result pc26_s2(MipsRelocationInfo& pReloc,
   1141                                      MipsRelocator& pParent) {
   1142   int64_t A = signExtend<28>(pReloc.A() << 2);
   1143   int64_t S = pReloc.S();
   1144   int64_t P = pReloc.P();
   1145   pReloc.result() = (A + S - P) >> 2;
   1146   return Relocator::OK;
   1147 }
   1148 
   1149 // R_MIPS_PCHI16
   1150 static MipsRelocator::Result pchi16(MipsRelocationInfo& pReloc,
   1151                                     MipsRelocator& pParent) {
   1152   uint64_t AHL = pParent.calcAHL(pReloc);
   1153   int64_t S = pReloc.S();
   1154   int64_t P = pReloc.P();
   1155   pReloc.result() = (S + AHL - P + 0x8000) >> 16;
   1156   return Relocator::OK;
   1157 }
   1158 
   1159 // R_MIPS_PCLO16
   1160 static MipsRelocator::Result pclo16(MipsRelocationInfo& pReloc,
   1161                                     MipsRelocator& pParent) {
   1162   int32_t AHL = pReloc.A() & 0xFFFF;
   1163   int64_t S = pReloc.S();
   1164   int64_t P = pReloc.P();
   1165   pReloc.result() = S + AHL - P;
   1166   pParent.applyPostponedRelocations(pReloc);
   1167   return Relocator::OK;
   1168 }
   1169 
   1170 // R_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_DTPREL_HI16
   1171 //   local/external: (A + S - TP Offset) >> 16
   1172 //   _gp_disp      : (A + GP - P - TP Offset) >> 16
   1173 static MipsRelocator::Result tlshi16(MipsRelocationInfo& pReloc,
   1174                                      MipsRelocator& pParent) {
   1175   uint64_t A = pReloc.A() & 0xFFFF;
   1176   if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_HI16)
   1177     A -= pParent.getTPOffset();
   1178   else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_HI16)
   1179     A -= pParent.getDTPOffset();
   1180   else
   1181     llvm_unreachable("Unexpected relocation");
   1182 
   1183   if (pParent.isGpDisp(pReloc.parent()))
   1184     pReloc.result() = (A + pReloc.S() - pReloc.P() + 0x8000) >> 16;
   1185   else
   1186     pReloc.result() = (A + pReloc.S() + 0x8000) >> 16;
   1187 
   1188   return Relocator::OK;
   1189 }
   1190 
   1191 // R_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_DTPREL_LO16
   1192 //   local/external: A + S - TP Offset
   1193 //   _gp_disp      : A + GP - P + 4 - TP Offset
   1194 static MipsRelocator::Result tlslo16(MipsRelocationInfo& pReloc,
   1195                                      MipsRelocator& pParent) {
   1196   uint64_t A = pReloc.A() & 0xFFFF;
   1197   if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_LO16)
   1198     A -= pParent.getTPOffset();
   1199   else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_LO16)
   1200     A -= pParent.getDTPOffset();
   1201   else
   1202     llvm_unreachable("Unexpected relocation");
   1203 
   1204   if (pParent.isGpDisp(pReloc.parent()))
   1205     pReloc.result() = A + pReloc.S() - pReloc.P() + 4;
   1206   else
   1207     pReloc.result() = A + pReloc.S();
   1208 
   1209   return Relocator::OK;
   1210 }
   1211 
   1212 // R_MIPS_TLS_GD, R_MIPS_TLS_LDM
   1213 static MipsRelocator::Result tlsgot(MipsRelocationInfo& pReloc,
   1214                                     MipsRelocator& pParent) {
   1215   pReloc.result() = pParent.getTLSGOTOffset(pReloc);
   1216   return Relocator::OK;
   1217 }
   1218 
   1219 static MipsRelocator::Result unsupported(MipsRelocationInfo& pReloc,
   1220                                          MipsRelocator& pParent) {
   1221   return Relocator::Unsupported;
   1222 }
   1223 
   1224 }  // namespace mcld
   1225