Home | History | Annotate | Download | only in Mips
      1 //===- MipsLDBackend.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 "Mips.h"
     10 #include "MipsGNUInfo.h"
     11 #include "MipsELFDynamic.h"
     12 #include "MipsLA25Stub.h"
     13 #include "MipsLDBackend.h"
     14 #include "MipsRelocator.h"
     15 
     16 #include "mcld/IRBuilder.h"
     17 #include "mcld/LinkerConfig.h"
     18 #include "mcld/Module.h"
     19 #include "mcld/Fragment/FillFragment.h"
     20 #include "mcld/LD/BranchIslandFactory.h"
     21 #include "mcld/LD/LDContext.h"
     22 #include "mcld/LD/StubFactory.h"
     23 #include "mcld/LD/ELFFileFormat.h"
     24 #include "mcld/MC/Attribute.h"
     25 #include "mcld/Object/ObjectBuilder.h"
     26 #include "mcld/Support/MemoryRegion.h"
     27 #include "mcld/Support/MemoryArea.h"
     28 #include "mcld/Support/MsgHandling.h"
     29 #include "mcld/Support/TargetRegistry.h"
     30 #include "mcld/Target/OutputRelocSection.h"
     31 
     32 #include <llvm/ADT/Triple.h>
     33 #include <llvm/Support/Casting.h>
     34 #include <llvm/Support/ELF.h>
     35 #include <llvm/Support/Host.h>
     36 
     37 namespace mcld {
     38 
     39 //===----------------------------------------------------------------------===//
     40 // MipsGNULDBackend
     41 //===----------------------------------------------------------------------===//
     42 MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig,
     43                                    MipsGNUInfo* pInfo)
     44     : GNULDBackend(pConfig, pInfo),
     45       m_pRelocator(NULL),
     46       m_pGOT(NULL),
     47       m_pPLT(NULL),
     48       m_pGOTPLT(NULL),
     49       m_pInfo(*pInfo),
     50       m_pRelPlt(NULL),
     51       m_pRelDyn(NULL),
     52       m_pDynamic(NULL),
     53       m_pGOTSymbol(NULL),
     54       m_pPLTSymbol(NULL),
     55       m_pGpDispSymbol(NULL) {
     56 }
     57 
     58 MipsGNULDBackend::~MipsGNULDBackend() {
     59   delete m_pRelocator;
     60   delete m_pPLT;
     61   delete m_pRelPlt;
     62   delete m_pRelDyn;
     63   delete m_pDynamic;
     64 }
     65 
     66 bool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType,
     67                                      const mcld::ResolveInfo* pSym) {
     68   if (config().isCodeIndep())
     69     return false;
     70 
     71   if (llvm::ELF::R_MIPS_26 != pType)
     72     return false;
     73 
     74   if (pSym->isLocal())
     75     return false;
     76 
     77   return true;
     78 }
     79 
     80 void MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym) {
     81   m_HasNonPICBranchSyms.insert(rsym);
     82 }
     83 
     84 bool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const {
     85   return m_HasNonPICBranchSyms.count(rsym);
     86 }
     87 
     88 void MipsGNULDBackend::initTargetSections(Module& pModule,
     89                                           ObjectBuilder& pBuilder) {
     90   if (LinkerConfig::Object == config().codeGenType())
     91     return;
     92 
     93   ELFFileFormat* file_format = getOutputFormat();
     94 
     95   // initialize .rel.plt
     96   LDSection& relplt = file_format->getRelPlt();
     97   m_pRelPlt = new OutputRelocSection(pModule, relplt);
     98 
     99   // initialize .rel.dyn
    100   LDSection& reldyn = file_format->getRelDyn();
    101   m_pRelDyn = new OutputRelocSection(pModule, reldyn);
    102 }
    103 
    104 void MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
    105   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
    106   // same name in input
    107   m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    108       "_GLOBAL_OFFSET_TABLE_",
    109       ResolveInfo::Object,
    110       ResolveInfo::Define,
    111       ResolveInfo::Local,
    112       0x0,                  // size
    113       0x0,                  // value
    114       FragmentRef::Null(),  // FragRef
    115       ResolveInfo::Hidden);
    116 
    117   // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the
    118   // same name in input
    119   m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    120       "_PROCEDURE_LINKAGE_TABLE_",
    121       ResolveInfo::Object,
    122       ResolveInfo::Define,
    123       ResolveInfo::Local,
    124       0x0,                  // size
    125       0x0,                  // value
    126       FragmentRef::Null(),  // FragRef
    127       ResolveInfo::Hidden);
    128 
    129   m_pGpDispSymbol =
    130       pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    131           "_gp_disp",
    132           ResolveInfo::Section,
    133           ResolveInfo::Define,
    134           ResolveInfo::Absolute,
    135           0x0,                  // size
    136           0x0,                  // value
    137           FragmentRef::Null(),  // FragRef
    138           ResolveInfo::Default);
    139 
    140   pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
    141       "_gp",
    142       ResolveInfo::NoType,
    143       ResolveInfo::Define,
    144       ResolveInfo::Absolute,
    145       0x0,                  // size
    146       0x0,                  // value
    147       FragmentRef::Null(),  // FragRef
    148       ResolveInfo::Default);
    149 }
    150 
    151 const Relocator* MipsGNULDBackend::getRelocator() const {
    152   assert(m_pRelocator != NULL);
    153   return m_pRelocator;
    154 }
    155 
    156 Relocator* MipsGNULDBackend::getRelocator() {
    157   assert(m_pRelocator != NULL);
    158   return m_pRelocator;
    159 }
    160 
    161 void MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder) {
    162   // initialize .dynamic data
    163   if (!config().isCodeStatic() && m_pDynamic == NULL)
    164     m_pDynamic = new MipsELFDynamic(*this, config());
    165 
    166   // set .got size
    167   // when building shared object, the .got section is must.
    168   if (LinkerConfig::Object != config().codeGenType()) {
    169     if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
    170         m_pGOTSymbol != NULL) {
    171       m_pGOT->finalizeScanning(*m_pRelDyn);
    172       m_pGOT->finalizeSectionSize();
    173 
    174       defineGOTSymbol(pBuilder);
    175     }
    176 
    177     if (m_pGOTPLT->hasGOT1()) {
    178       m_pGOTPLT->finalizeSectionSize();
    179 
    180       defineGOTPLTSymbol(pBuilder);
    181     }
    182 
    183     if (m_pPLT->hasPLT1())
    184       m_pPLT->finalizeSectionSize();
    185 
    186     ELFFileFormat* file_format = getOutputFormat();
    187 
    188     // set .rel.plt size
    189     if (!m_pRelPlt->empty()) {
    190       assert(
    191           !config().isCodeStatic() &&
    192           "static linkage should not result in a dynamic relocation section");
    193       file_format->getRelPlt().setSize(m_pRelPlt->numOfRelocs() *
    194                                        getRelEntrySize());
    195     }
    196 
    197     // set .rel.dyn size
    198     if (!m_pRelDyn->empty()) {
    199       assert(
    200           !config().isCodeStatic() &&
    201           "static linkage should not result in a dynamic relocation section");
    202       file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
    203                                        getRelEntrySize());
    204     }
    205   }
    206 }
    207 
    208 void MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
    209   const ELFFileFormat* format = getOutputFormat();
    210 
    211   if (format->hasGOTPLT()) {
    212     assert(m_pGOTPLT != NULL && "doPostLayout failed, m_pGOTPLT is NULL!");
    213     m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr());
    214   }
    215 
    216   if (format->hasPLT()) {
    217     assert(m_pPLT != NULL && "doPostLayout failed, m_pPLT is NULL!");
    218     m_pPLT->applyAllPLT(*m_pGOTPLT);
    219   }
    220 
    221   m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0);
    222 
    223   // FIXME: (simon) We need to iterate all input sections
    224   // check that flags are consistent and merge them properly.
    225   uint64_t picFlags = llvm::ELF::EF_MIPS_CPIC;
    226   if (config().targets().triple().isArch64Bit()) {
    227     picFlags |= llvm::ELF::EF_MIPS_PIC;
    228   } else {
    229     if (LinkerConfig::DynObj == config().codeGenType())
    230       picFlags |= llvm::ELF::EF_MIPS_PIC;
    231   }
    232 
    233   m_pInfo.setPICFlags(picFlags);
    234 }
    235 
    236 /// dynamic - the dynamic section of the target machine.
    237 /// Use co-variant return type to return its own dynamic section.
    238 MipsELFDynamic& MipsGNULDBackend::dynamic() {
    239   assert(m_pDynamic != NULL);
    240   return *m_pDynamic;
    241 }
    242 
    243 /// dynamic - the dynamic section of the target machine.
    244 /// Use co-variant return type to return its own dynamic section.
    245 const MipsELFDynamic& MipsGNULDBackend::dynamic() const {
    246   assert(m_pDynamic != NULL);
    247   return *m_pDynamic;
    248 }
    249 
    250 uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
    251                                            MemoryRegion& pRegion) const {
    252   assert(pRegion.size() && "Size of MemoryRegion is zero!");
    253 
    254   const ELFFileFormat* file_format = getOutputFormat();
    255 
    256   if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
    257     return m_pGOT->emit(pRegion);
    258   }
    259 
    260   if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
    261     return m_pPLT->emit(pRegion);
    262   }
    263 
    264   if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
    265     return m_pGOTPLT->emit(pRegion);
    266   }
    267 
    268   fatal(diag::unrecognized_output_sectoin) << pSection.name()
    269                                            << "mclinker (at) googlegroups.com";
    270   return 0;
    271 }
    272 
    273 bool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const {
    274   return ResolveInfo::Section != pSym.type() || m_pGpDispSymbol == &pSym;
    275 }
    276 
    277 namespace {
    278 struct DynsymGOTCompare {
    279   const MipsGOT& m_pGOT;
    280 
    281   explicit DynsymGOTCompare(const MipsGOT& pGOT) : m_pGOT(pGOT) {}
    282 
    283   bool operator()(const LDSymbol* X, const LDSymbol* Y) const {
    284     return m_pGOT.dynSymOrderCompare(X, Y);
    285   }
    286 };
    287 }  // anonymous namespace
    288 
    289 void MipsGNULDBackend::orderSymbolTable(Module& pModule) {
    290   if (config().options().hasGNUHash()) {
    291     // The MIPS ABI and .gnu.hash require .dynsym to be sorted
    292     // in different ways. The MIPS ABI requires a mapping between
    293     // the GOT and the symbol table. At the same time .gnu.hash
    294     // needs symbols to be grouped by hash code.
    295     llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n";
    296   }
    297 
    298   Module::SymbolTable& symbols = pModule.getSymbolTable();
    299 
    300   std::stable_sort(
    301       symbols.dynamicBegin(), symbols.dynamicEnd(), DynsymGOTCompare(*m_pGOT));
    302 }
    303 
    304 }  // namespace mcld
    305 
    306 namespace llvm {
    307 namespace ELF {
    308 // SHT_MIPS_OPTIONS section's block descriptor.
    309 struct Elf_Options {
    310   unsigned char kind;  // Determines interpretation of variable
    311                        // part of descriptor. See ODK_xxx enumeration.
    312   unsigned char size;  // Byte size of descriptor, including this header.
    313   Elf64_Half section;  // Section header index of section affected,
    314                        // or 0 for global options.
    315   Elf64_Word info;     // Kind-specic information.
    316 };
    317 
    318 // Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
    319 struct Elf32_RegInfo {
    320   Elf32_Word ri_gprmask;     // Mask of general purpose registers used.
    321   Elf32_Word ri_cprmask[4];  // Mask of co-processor registers used.
    322   Elf32_Addr ri_gp_value;    // GP register value for this object file.
    323 };
    324 
    325 // Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
    326 struct Elf64_RegInfo {
    327   Elf32_Word ri_gprmask;     // Mask of general purpose registers used.
    328   Elf32_Word ri_pad;         // Padding.
    329   Elf32_Word ri_cprmask[4];  // Mask of co-processor registers used.
    330   Elf64_Addr ri_gp_value;    // GP register value for this object file.
    331 };
    332 
    333 }  // namespace ELF
    334 }  // namespace llvm
    335 
    336 namespace mcld {
    337 
    338 bool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
    339   llvm::StringRef name(pSD.getSection().name());
    340 
    341   if (name.startswith(".sdata")) {
    342     uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
    343     uint64_t size = pSD.getSection().size();
    344 
    345     Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
    346     ObjectBuilder::AppendFragment(*frag, pSD);
    347     return true;
    348   }
    349 
    350   if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
    351     uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
    352     uint32_t size = pSD.getSection().size();
    353 
    354     llvm::StringRef region = pInput.memArea()->request(offset, size);
    355     if (region.size() > 0) {
    356       const llvm::ELF::Elf_Options* optb =
    357           reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
    358       const llvm::ELF::Elf_Options* opte =
    359           reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() +
    360                                                           size);
    361 
    362       for (const llvm::ELF::Elf_Options* opt = optb; opt < opte;
    363            opt += opt->size) {
    364         switch (opt->kind) {
    365           default:
    366             // Nothing to do.
    367             break;
    368           case llvm::ELF::ODK_REGINFO:
    369             if (config().targets().triple().isArch32Bit()) {
    370               const llvm::ELF::Elf32_RegInfo* reg =
    371                   reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
    372               m_GP0Map[&pInput] = reg->ri_gp_value;
    373             } else {
    374               const llvm::ELF::Elf64_RegInfo* reg =
    375                   reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
    376               m_GP0Map[&pInput] = reg->ri_gp_value;
    377             }
    378             break;
    379         }
    380       }
    381     }
    382 
    383     return true;
    384   }
    385 
    386   return GNULDBackend::readSection(pInput, pSD);
    387 }
    388 
    389 MipsGOT& MipsGNULDBackend::getGOT() {
    390   assert(m_pGOT != NULL);
    391   return *m_pGOT;
    392 }
    393 
    394 const MipsGOT& MipsGNULDBackend::getGOT() const {
    395   assert(m_pGOT != NULL);
    396   return *m_pGOT;
    397 }
    398 
    399 MipsPLT& MipsGNULDBackend::getPLT() {
    400   assert(m_pPLT != NULL);
    401   return *m_pPLT;
    402 }
    403 
    404 const MipsPLT& MipsGNULDBackend::getPLT() const {
    405   assert(m_pPLT != NULL);
    406   return *m_pPLT;
    407 }
    408 
    409 MipsGOTPLT& MipsGNULDBackend::getGOTPLT() {
    410   assert(m_pGOTPLT != NULL);
    411   return *m_pGOTPLT;
    412 }
    413 
    414 const MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const {
    415   assert(m_pGOTPLT != NULL);
    416   return *m_pGOTPLT;
    417 }
    418 
    419 OutputRelocSection& MipsGNULDBackend::getRelPLT() {
    420   assert(m_pRelPlt != NULL);
    421   return *m_pRelPlt;
    422 }
    423 
    424 const OutputRelocSection& MipsGNULDBackend::getRelPLT() const {
    425   assert(m_pRelPlt != NULL);
    426   return *m_pRelPlt;
    427 }
    428 
    429 OutputRelocSection& MipsGNULDBackend::getRelDyn() {
    430   assert(m_pRelDyn != NULL);
    431   return *m_pRelDyn;
    432 }
    433 
    434 const OutputRelocSection& MipsGNULDBackend::getRelDyn() const {
    435   assert(m_pRelDyn != NULL);
    436   return *m_pRelDyn;
    437 }
    438 
    439 unsigned int MipsGNULDBackend::getTargetSectionOrder(
    440     const LDSection& pSectHdr) const {
    441   const ELFFileFormat* file_format = getOutputFormat();
    442 
    443   if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
    444     return SHO_DATA;
    445 
    446   if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
    447     return SHO_DATA;
    448 
    449   if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
    450     return SHO_PLT;
    451 
    452   return SHO_UNDEFINED;
    453 }
    454 
    455 /// finalizeSymbol - finalize the symbol value
    456 bool MipsGNULDBackend::finalizeTargetSymbols() {
    457   if (m_pGpDispSymbol != NULL)
    458     m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress());
    459 
    460   return true;
    461 }
    462 
    463 /// allocateCommonSymbols - allocate common symbols in the corresponding
    464 /// sections. This is called at pre-layout stage.
    465 /// FIXME: Mips needs to allocate small common symbol
    466 bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule) {
    467   SymbolCategory& symbol_list = pModule.getSymbolTable();
    468 
    469   if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
    470       symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
    471     return true;
    472 
    473   SymbolCategory::iterator com_sym, com_end;
    474 
    475   // FIXME: If the order of common symbols is defined, then sort common symbols
    476   // std::sort(com_sym, com_end, some kind of order);
    477 
    478   // get corresponding BSS LDSection
    479   ELFFileFormat* file_format = getOutputFormat();
    480   LDSection& bss_sect = file_format->getBSS();
    481   LDSection& tbss_sect = file_format->getTBSS();
    482 
    483   // get or create corresponding BSS SectionData
    484   SectionData* bss_sect_data = NULL;
    485   if (bss_sect.hasSectionData())
    486     bss_sect_data = bss_sect.getSectionData();
    487   else
    488     bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
    489 
    490   SectionData* tbss_sect_data = NULL;
    491   if (tbss_sect.hasSectionData())
    492     tbss_sect_data = tbss_sect.getSectionData();
    493   else
    494     tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
    495 
    496   // remember original BSS size
    497   uint64_t bss_offset = bss_sect.size();
    498   uint64_t tbss_offset = tbss_sect.size();
    499 
    500   // allocate all local common symbols
    501   com_end = symbol_list.localEnd();
    502 
    503   for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
    504     if (ResolveInfo::Common == (*com_sym)->desc()) {
    505       // We have to reset the description of the symbol here. When doing
    506       // incremental linking, the output relocatable object may have common
    507       // symbols. Therefore, we can not treat common symbols as normal symbols
    508       // when emitting the regular name pools. We must change the symbols'
    509       // description here.
    510       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
    511       Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
    512 
    513       if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
    514         // allocate TLS common symbol in tbss section
    515         tbss_offset += ObjectBuilder::AppendFragment(
    516             *frag, *tbss_sect_data, (*com_sym)->value());
    517         ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
    518         (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
    519       } else {
    520         // FIXME: how to identify small and large common symbols?
    521         bss_offset += ObjectBuilder::AppendFragment(
    522             *frag, *bss_sect_data, (*com_sym)->value());
    523         ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
    524         (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
    525       }
    526     }
    527   }
    528 
    529   // allocate all global common symbols
    530   com_end = symbol_list.commonEnd();
    531   for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
    532     // We have to reset the description of the symbol here. When doing
    533     // incremental linking, the output relocatable object may have common
    534     // symbols. Therefore, we can not treat common symbols as normal symbols
    535     // when emitting the regular name pools. We must change the symbols'
    536     // description here.
    537     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
    538     Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
    539 
    540     if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
    541       // allocate TLS common symbol in tbss section
    542       tbss_offset += ObjectBuilder::AppendFragment(
    543           *frag, *tbss_sect_data, (*com_sym)->value());
    544       ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
    545       (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
    546     } else {
    547       // FIXME: how to identify small and large common symbols?
    548       bss_offset += ObjectBuilder::AppendFragment(
    549           *frag, *bss_sect_data, (*com_sym)->value());
    550       ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
    551       (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
    552     }
    553   }
    554 
    555   bss_sect.setSize(bss_offset);
    556   tbss_sect.setSize(tbss_offset);
    557   symbol_list.changeCommonsToGlobal();
    558   return true;
    559 }
    560 
    561 uint64_t MipsGNULDBackend::getGP0(const Input& pInput) const {
    562   return m_GP0Map.lookup(&pInput);
    563 }
    564 
    565 void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
    566   // If we do not reserve any GOT entries, we do not need to re-define GOT
    567   // symbol.
    568   if (!m_pGOT->hasGOT1())
    569     return;
    570 
    571   // define symbol _GLOBAL_OFFSET_TABLE_
    572   if (m_pGOTSymbol != NULL) {
    573     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
    574         "_GLOBAL_OFFSET_TABLE_",
    575         ResolveInfo::Object,
    576         ResolveInfo::Define,
    577         ResolveInfo::Local,
    578         0x0,  // size
    579         0x0,  // value
    580         FragmentRef::Create(*(m_pGOT->begin()), 0x0),
    581         ResolveInfo::Hidden);
    582   } else {
    583     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    584         "_GLOBAL_OFFSET_TABLE_",
    585         ResolveInfo::Object,
    586         ResolveInfo::Define,
    587         ResolveInfo::Local,
    588         0x0,  // size
    589         0x0,  // value
    590         FragmentRef::Create(*(m_pGOT->begin()), 0x0),
    591         ResolveInfo::Hidden);
    592   }
    593 }
    594 
    595 void MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder) {
    596   // define symbol _PROCEDURE_LINKAGE_TABLE_
    597   if (m_pPLTSymbol != NULL) {
    598     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
    599         "_PROCEDURE_LINKAGE_TABLE_",
    600         ResolveInfo::Object,
    601         ResolveInfo::Define,
    602         ResolveInfo::Local,
    603         0x0,  // size
    604         0x0,  // value
    605         FragmentRef::Create(*(m_pPLT->begin()), 0x0),
    606         ResolveInfo::Hidden);
    607   } else {
    608     m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    609         "_PROCEDURE_LINKAGE_TABLE_",
    610         ResolveInfo::Object,
    611         ResolveInfo::Define,
    612         ResolveInfo::Local,
    613         0x0,  // size
    614         0x0,  // value
    615         FragmentRef::Create(*(m_pPLT->begin()), 0x0),
    616         ResolveInfo::Hidden);
    617   }
    618 }
    619 
    620 /// doCreateProgramHdrs - backend can implement this function to create the
    621 /// target-dependent segments
    622 void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule) {
    623   // TODO
    624 }
    625 
    626 bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) {
    627   uint64_t sym_value = 0x0;
    628 
    629   LDSymbol* symbol = pRel.symInfo()->outSymbol();
    630   if (symbol->hasFragRef()) {
    631     uint64_t value = symbol->fragRef()->getOutputOffset();
    632     uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
    633     sym_value = addr + value;
    634   }
    635 
    636   Stub* stub = getStubFactory()->create(
    637       pRel, sym_value, pBuilder, *getBRIslandFactory());
    638 
    639   if (stub == NULL)
    640     return false;
    641 
    642   assert(stub->symInfo() != NULL);
    643   // increase the size of .symtab and .strtab
    644   LDSection& symtab = getOutputFormat()->getSymTab();
    645   LDSection& strtab = getOutputFormat()->getStrTab();
    646   symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
    647   strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
    648 
    649   return true;
    650 }
    651 
    652 bool MipsGNULDBackend::doRelax(Module& pModule,
    653                                IRBuilder& pBuilder,
    654                                bool& pFinished) {
    655   assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
    656 
    657   bool isRelaxed = false;
    658 
    659   for (Module::obj_iterator input = pModule.obj_begin();
    660        input != pModule.obj_end();
    661        ++input) {
    662     LDContext* context = (*input)->context();
    663 
    664     for (LDContext::sect_iterator rs = context->relocSectBegin();
    665          rs != context->relocSectEnd();
    666          ++rs) {
    667       LDSection* sec = *rs;
    668 
    669       if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
    670         continue;
    671 
    672       for (RelocData::iterator reloc = sec->getRelocData()->begin();
    673            reloc != sec->getRelocData()->end();
    674            ++reloc) {
    675         if (llvm::ELF::R_MIPS_26 != reloc->type())
    676           continue;
    677 
    678         if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
    679           isRelaxed = true;
    680       }
    681     }
    682   }
    683 
    684   SectionData* textData = getOutputFormat()->getText().getSectionData();
    685 
    686   // find the first fragment w/ invalid offset due to stub insertion
    687   Fragment* invalid = NULL;
    688   pFinished = true;
    689   for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
    690                                      ie = getBRIslandFactory()->end();
    691        ii != ie;
    692        ++ii) {
    693     BranchIsland& island = *ii;
    694     if (island.end() == textData->end())
    695       break;
    696 
    697     Fragment* exit = island.end();
    698     if ((island.offset() + island.size()) > exit->getOffset()) {
    699       invalid = exit;
    700       pFinished = false;
    701       break;
    702     }
    703   }
    704 
    705   // reset the offset of invalid fragments
    706   while (invalid != NULL) {
    707     invalid->setOffset(invalid->getPrevNode()->getOffset() +
    708                        invalid->getPrevNode()->size());
    709     invalid = invalid->getNextNode();
    710   }
    711 
    712   // reset the size of .text
    713   if (isRelaxed)
    714     getOutputFormat()->getText().setSize(textData->back().getOffset() +
    715                                          textData->back().size());
    716 
    717   return isRelaxed;
    718 }
    719 
    720 bool MipsGNULDBackend::initTargetStubs() {
    721   if (getStubFactory() == NULL)
    722     return false;
    723 
    724   getStubFactory()->addPrototype(new MipsLA25Stub(*this));
    725   return true;
    726 }
    727 
    728 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
    729                                       Relocation::Type& pType,
    730                                       uint32_t& pSymIdx,
    731                                       uint32_t& pOffset) const {
    732   return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
    733 }
    734 
    735 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
    736                                       Relocation::Type& pType,
    737                                       uint32_t& pSymIdx,
    738                                       uint32_t& pOffset,
    739                                       int32_t& pAddend) const {
    740   return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
    741 }
    742 
    743 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
    744                                       Relocation::Type& pType,
    745                                       uint32_t& pSymIdx,
    746                                       uint64_t& pOffset) const {
    747   uint64_t r_info = 0x0;
    748   if (llvm::sys::IsLittleEndianHost) {
    749     pOffset = pRel.r_offset;
    750     r_info = pRel.r_info;
    751   } else {
    752     pOffset = mcld::bswap64(pRel.r_offset);
    753     r_info = mcld::bswap64(pRel.r_info);
    754   }
    755 
    756   // MIPS 64 little endian (we do not support big endian now)
    757   // has a "special" encoding of r_info relocation
    758   // field. Instead of one 64 bit little endian number, it is a little
    759   // endian 32 bit number followed by a 32 bit big endian number.
    760   pType = mcld::bswap32(r_info >> 32);
    761   pSymIdx = r_info & 0xffffffff;
    762   return true;
    763 }
    764 
    765 bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
    766                                       Relocation::Type& pType,
    767                                       uint32_t& pSymIdx,
    768                                       uint64_t& pOffset,
    769                                       int64_t& pAddend) const {
    770   uint64_t r_info = 0x0;
    771   if (llvm::sys::IsLittleEndianHost) {
    772     pOffset = pRel.r_offset;
    773     r_info = pRel.r_info;
    774     pAddend = pRel.r_addend;
    775   } else {
    776     pOffset = mcld::bswap64(pRel.r_offset);
    777     r_info = mcld::bswap64(pRel.r_info);
    778     pAddend = mcld::bswap64(pRel.r_addend);
    779   }
    780 
    781   pType = mcld::bswap32(r_info >> 32);
    782   pSymIdx = r_info & 0xffffffff;
    783   return true;
    784 }
    785 
    786 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
    787                                       Relocation::Type pType,
    788                                       uint32_t pSymIdx,
    789                                       uint32_t pOffset) const {
    790   GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
    791 }
    792 
    793 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
    794                                       Relocation::Type pType,
    795                                       uint32_t pSymIdx,
    796                                       uint32_t pOffset,
    797                                       int32_t pAddend) const {
    798   GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
    799 }
    800 
    801 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
    802                                       Relocation::Type pType,
    803                                       uint32_t pSymIdx,
    804                                       uint64_t pOffset) const {
    805   uint64_t r_info = mcld::bswap32(pType);
    806   r_info <<= 32;
    807   r_info |= pSymIdx;
    808 
    809   pRel.r_info = r_info;
    810   pRel.r_offset = pOffset;
    811 }
    812 
    813 void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
    814                                       Relocation::Type pType,
    815                                       uint32_t pSymIdx,
    816                                       uint64_t pOffset,
    817                                       int64_t pAddend) const {
    818   uint64_t r_info = mcld::bswap32(pType);
    819   r_info <<= 32;
    820   r_info |= pSymIdx;
    821 
    822   pRel.r_info = r_info;
    823   pRel.r_offset = pOffset;
    824   pRel.r_addend = pAddend;
    825 }
    826 
    827 //===----------------------------------------------------------------------===//
    828 // Mips32GNULDBackend
    829 //===----------------------------------------------------------------------===//
    830 Mips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
    831                                        MipsGNUInfo* pInfo)
    832     : MipsGNULDBackend(pConfig, pInfo) {
    833 }
    834 
    835 bool Mips32GNULDBackend::initRelocator() {
    836   if (m_pRelocator == NULL)
    837     m_pRelocator = new Mips32Relocator(*this, config());
    838 
    839   return true;
    840 }
    841 
    842 void Mips32GNULDBackend::initTargetSections(Module& pModule,
    843                                             ObjectBuilder& pBuilder) {
    844   MipsGNULDBackend::initTargetSections(pModule, pBuilder);
    845 
    846   if (LinkerConfig::Object == config().codeGenType())
    847     return;
    848 
    849   ELFFileFormat* fileFormat = getOutputFormat();
    850 
    851   // initialize .got
    852   LDSection& got = fileFormat->getGOT();
    853   m_pGOT = new Mips32GOT(got);
    854 
    855   // initialize .got.plt
    856   LDSection& gotplt = fileFormat->getGOTPLT();
    857   m_pGOTPLT = new MipsGOTPLT(gotplt);
    858 
    859   // initialize .plt
    860   LDSection& plt = fileFormat->getPLT();
    861   m_pPLT = new MipsPLT(plt);
    862 }
    863 
    864 size_t Mips32GNULDBackend::getRelEntrySize() {
    865   return 8;
    866 }
    867 
    868 size_t Mips32GNULDBackend::getRelaEntrySize() {
    869   return 12;
    870 }
    871 
    872 //===----------------------------------------------------------------------===//
    873 // Mips64GNULDBackend
    874 //===----------------------------------------------------------------------===//
    875 Mips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
    876                                        MipsGNUInfo* pInfo)
    877     : MipsGNULDBackend(pConfig, pInfo) {
    878 }
    879 
    880 bool Mips64GNULDBackend::initRelocator() {
    881   if (m_pRelocator == NULL)
    882     m_pRelocator = new Mips64Relocator(*this, config());
    883 
    884   return true;
    885 }
    886 
    887 void Mips64GNULDBackend::initTargetSections(Module& pModule,
    888                                             ObjectBuilder& pBuilder) {
    889   MipsGNULDBackend::initTargetSections(pModule, pBuilder);
    890 
    891   if (LinkerConfig::Object == config().codeGenType())
    892     return;
    893 
    894   ELFFileFormat* fileFormat = getOutputFormat();
    895 
    896   // initialize .got
    897   LDSection& got = fileFormat->getGOT();
    898   m_pGOT = new Mips64GOT(got);
    899 
    900   // initialize .got.plt
    901   LDSection& gotplt = fileFormat->getGOTPLT();
    902   m_pGOTPLT = new MipsGOTPLT(gotplt);
    903 
    904   // initialize .plt
    905   LDSection& plt = fileFormat->getPLT();
    906   m_pPLT = new MipsPLT(plt);
    907 }
    908 
    909 size_t Mips64GNULDBackend::getRelEntrySize() {
    910   return 16;
    911 }
    912 
    913 size_t Mips64GNULDBackend::getRelaEntrySize() {
    914   return 24;
    915 }
    916 
    917 //===----------------------------------------------------------------------===//
    918 /// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
    919 ///
    920 static TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig) {
    921   const llvm::Triple& triple = pConfig.targets().triple();
    922 
    923   if (triple.isOSDarwin()) {
    924     assert(0 && "MachO linker is not supported yet");
    925   }
    926   if (triple.isOSWindows()) {
    927     assert(0 && "COFF linker is not supported yet");
    928   }
    929 
    930   llvm::Triple::ArchType arch = triple.getArch();
    931 
    932   if (llvm::Triple::mips64el == arch)
    933     return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
    934 
    935   assert(arch == llvm::Triple::mipsel);
    936   return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
    937 }
    938 
    939 }  // namespace mcld
    940 
    941 //===----------------------------------------------------------------------===//
    942 // Force static initialization.
    943 //===----------------------------------------------------------------------===//
    944 extern "C" void MCLDInitializeMipsLDBackend() {
    945   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
    946                                                 mcld::createMipsLDBackend);
    947   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
    948                                                 mcld::createMipsLDBackend);
    949 }
    950