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