Home | History | Annotate | Download | only in ARM
      1 //===- impl.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 "ARMGOT.h"
     10 #include <mcld/LD/LDFileFormat.h>
     11 #include <mcld/Support/MemoryRegion.h>
     12 #include <llvm/Support/ErrorHandling.h>
     13 #include <new>
     14 
     15 namespace {
     16   const size_t ARMGOTEntrySize = 4;
     17 } // end of anonymous namespace
     18 
     19 using namespace mcld;
     20 
     21 //===----------------------------------------------------------------------===//
     22 // ARMGOT
     23 ARMGOT::ARMGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
     24              : GOT(pSection, pSectionData, ARMGOTEntrySize),
     25                m_NormalGOTIterator(), m_GOTPLTIterator(),
     26                m_GOTPLTBegin(), m_GOTPLTEnd()
     27 {
     28   GOTEntry* Entry = 0;
     29 
     30   // Create GOT0 entries.
     31   for (int i = 0; i < 3; i++) {
     32     Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
     33                                         &m_SectionData);
     34 
     35     if (!Entry)
     36       llvm::report_fatal_error("Allocating GOT0 entries failed!");
     37 
     38     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
     39   }
     40 
     41   // Skip GOT0 entries.
     42   iterator it = m_SectionData.begin();
     43   iterator ie = m_SectionData.end();
     44 
     45   for (int i = 1; i < ARMGOT0Num; ++i) {
     46     if (it == ie)
     47       llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
     48 
     49     ++it;
     50   }
     51 
     52   m_NormalGOTIterator = it;
     53   m_GOTPLTIterator = it;
     54 
     55   m_GOTPLTBegin = it;
     56   m_GOTPLTEnd = it;
     57 }
     58 
     59 ARMGOT::~ARMGOT()
     60 {
     61 }
     62 
     63 void ARMGOT::reserveEntry(size_t pNum)
     64 {
     65   GOTEntry* Entry = 0;
     66 
     67   for (size_t i = 0; i < pNum; i++) {
     68     Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
     69                                         &m_SectionData);
     70 
     71     if (!Entry)
     72       llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
     73 
     74     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
     75   }
     76 }
     77 
     78 void ARMGOT::reserveGOTPLTEntry()
     79 {
     80     GOTEntry* got_entry = 0;
     81 
     82     got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
     83 
     84     if (!got_entry)
     85       llvm::report_fatal_error("Allocating new memory for GOT failed!");
     86 
     87     m_Section.setSize(m_Section.size() + getEntrySize());
     88 
     89     ++m_GOTPLTEnd;
     90     ++m_NormalGOTIterator;
     91 }
     92 
     93 GOTEntry* ARMGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
     94 {
     95   GOTEntry *&Entry = m_NormalGOTMap[&pInfo];
     96   pExist = 1;
     97 
     98   if (!Entry) {
     99     pExist = 0;
    100 
    101     ++m_NormalGOTIterator;
    102     assert(m_NormalGOTIterator != m_SectionData.getFragmentList().end()
    103            && "The number of GOT Entries and ResolveInfo doesn't match!");
    104 
    105     Entry = llvm::cast<GOTEntry>(&(*m_NormalGOTIterator));
    106   }
    107 
    108   return Entry;
    109 }
    110 
    111 void ARMGOT::applyGOT0(uint64_t pAddress)
    112 {
    113   llvm::cast<GOTEntry>
    114     (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
    115 }
    116 
    117 void ARMGOT::applyAllGOTPLT(uint64_t pPLTBase)
    118 {
    119   iterator begin = getGOTPLTBegin();
    120   iterator end = getGOTPLTEnd();
    121 
    122   for (;begin != end ;++begin)
    123     llvm::cast<GOTEntry>(*begin).setContent(pPLTBase);
    124 }
    125 
    126 GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
    127 {
    128   return m_GOTPLTMap[&pSymbol];
    129 }
    130 
    131 ARMGOT::iterator ARMGOT::begin()
    132 {
    133   return m_SectionData.getFragmentList().begin();
    134 }
    135 
    136 ARMGOT::const_iterator ARMGOT::begin() const
    137 {
    138   return m_SectionData.getFragmentList().begin();
    139 }
    140 
    141 ARMGOT::iterator ARMGOT::end()
    142 {
    143   return m_SectionData.getFragmentList().end();
    144 }
    145 
    146 ARMGOT::const_iterator ARMGOT::end() const
    147 {
    148   return m_SectionData.getFragmentList().end();
    149 }
    150 
    151 ARMGOT::iterator ARMGOT::getNextGOTPLTEntry()
    152 {
    153   return ++m_GOTPLTIterator;
    154 }
    155 
    156 ARMGOT::iterator ARMGOT::getGOTPLTBegin()
    157 {
    158   // Move to the first GOTPLT entry from last GOT0 entry.
    159   iterator begin = m_GOTPLTBegin;
    160   return ++begin;
    161 }
    162 
    163 const ARMGOT::iterator ARMGOT::getGOTPLTEnd()
    164 {
    165   // Move to end or the first normal GOT entry from the last GOTPLT entry.
    166   iterator end = m_GOTPLTEnd;
    167   return ++end;
    168 }
    169 
    170 uint64_t ARMGOT::emit(MemoryRegion& pRegion)
    171 {
    172   uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
    173 
    174   GOTEntry* got = 0;
    175   unsigned int entry_size = getEntrySize();
    176   uint64_t result = 0x0;
    177   for (iterator it = begin(), ie = end();
    178        it != ie; ++it, ++buffer) {
    179       got = &(llvm::cast<GOTEntry>((*it)));
    180       *buffer = static_cast<uint32_t>(got->getContent());
    181       result += entry_size;
    182   }
    183   return result;
    184 }
    185