Home | History | Annotate | Download | only in Mips
      1 //===- MipsGOT.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 
     10 #include <llvm/Support/ErrorHandling.h>
     11 #include <mcld/LD/ResolveInfo.h>
     12 #include <mcld/Support/MemoryRegion.h>
     13 #include "MipsGOT.h"
     14 
     15 namespace {
     16   const size_t MipsGOTEntrySize = 4;
     17   const size_t MipsGOT0Num = 1;
     18 }
     19 
     20 using namespace mcld;
     21 
     22 //===----------------------------------------------------------------------===//
     23 // MipsGOT
     24 MipsGOT::MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
     25   : GOT(pSection, pSectionData, MipsGOTEntrySize),
     26     m_pLocalNum(0)
     27 {
     28   // Create GOT0 entries.
     29   for (size_t i = 0; i < MipsGOT0Num; ++i) {
     30     GOTEntry* entry =
     31       new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
     32 
     33     if (NULL == entry)
     34       llvm::report_fatal_error("Allocating GOT0 entries failed!");
     35 
     36     m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
     37   }
     38 
     39   // Skip GOT0 entries.
     40   iterator it = m_SectionData.begin();
     41   iterator ie = m_SectionData.end();
     42 
     43   for (size_t i = 1; i < MipsGOT0Num; ++i) {
     44     if (it == ie)
     45       llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
     46 
     47     ++it;
     48   }
     49 
     50   m_LocalGOTIterator = it;
     51   m_GlobalGOTIterator = it;
     52   m_pLocalNum = MipsGOT0Num;
     53 }
     54 
     55 MipsGOT::iterator MipsGOT::begin()
     56 {
     57   return m_SectionData.getFragmentList().begin();
     58 }
     59 
     60 MipsGOT::iterator MipsGOT::end()
     61 {
     62   return m_SectionData.getFragmentList().end();
     63 }
     64 
     65 MipsGOT::const_iterator MipsGOT::begin() const
     66 {
     67   return m_SectionData.getFragmentList().begin();
     68 }
     69 
     70 MipsGOT::const_iterator MipsGOT::end() const
     71 {
     72   return m_SectionData.getFragmentList().end();
     73 }
     74 
     75 uint64_t MipsGOT::emit(MemoryRegion& pRegion)
     76 {
     77   uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
     78 
     79   size_t entry_size = getEntrySize();
     80 
     81   uint64_t result = 0;
     82   for (iterator it = begin(), ie = end();
     83        it != ie; ++it, ++buffer) {
     84     GOTEntry* got = &(llvm::cast<GOTEntry>((*it)));
     85     *buffer = static_cast<uint32_t>(got->getContent());
     86     result += entry_size;
     87   }
     88   return result;
     89 }
     90 
     91 void MipsGOT::reserveEntry(size_t pNum)
     92 {
     93   for (size_t i = 0; i < pNum; ++i) {
     94     GOTEntry* entry =
     95       new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
     96 
     97     if (NULL == entry)
     98       llvm::report_fatal_error("Allocating new GOTEntry failed");
     99 
    100     m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
    101   }
    102 }
    103 
    104 void MipsGOT::reserveLocalEntry()
    105 {
    106   reserveEntry(1);
    107   ++m_pLocalNum;
    108 
    109   // Move global entries iterator forward.
    110   // We need to put global GOT entries after all local ones.
    111   ++m_GlobalGOTIterator;
    112 }
    113 
    114 void MipsGOT::reserveGlobalEntry()
    115 {
    116   reserveEntry(1);
    117 }
    118 
    119 GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
    120 {
    121   GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
    122 
    123   pExist = NULL != entry;
    124 
    125   if (!pExist) {
    126     iterator& it = pInfo.isLocal() ? m_LocalGOTIterator : m_GlobalGOTIterator;
    127 
    128     ++it;
    129 
    130     assert(it != m_SectionData.getFragmentList().end() &&
    131            "The number of GOT Entries and ResolveInfo doesn't match");
    132 
    133     entry = llvm::cast<GOTEntry>(&(*it));
    134   }
    135 
    136   return entry;
    137 }
    138 
    139 size_t MipsGOT::getTotalNum() const
    140 {
    141   return m_SectionData.getFragmentList().size();
    142 }
    143 
    144 size_t MipsGOT::getLocalNum() const
    145 {
    146   return m_pLocalNum;
    147 }
    148