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