Home | History | Annotate | Download | only in ARM
      1 //===- ARMGOT.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 
     11 #include "mcld/LD/LDSection.h"
     12 #include "mcld/LD/LDFileFormat.h"
     13 #include "mcld/Support/MsgHandling.h"
     14 
     15 #include <llvm/Support/Casting.h>
     16 
     17 namespace {
     18 const unsigned int ARMGOT0Num = 3;
     19 }  // end of anonymous namespace
     20 
     21 namespace mcld {
     22 
     23 //===----------------------------------------------------------------------===//
     24 // ARMGOT
     25 ARMGOT::ARMGOT(LDSection& pSection)
     26     : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) {
     27   // create GOT0, and put them into m_SectionData immediately
     28   for (unsigned int i = 0; i < ARMGOT0Num; ++i)
     29     new ARMGOTEntry(0, m_SectionData);
     30 }
     31 
     32 ARMGOT::~ARMGOT() {
     33 }
     34 
     35 bool ARMGOT::hasGOT1() const {
     36   return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
     37 }
     38 
     39 ARMGOTEntry* ARMGOT::createGOT() {
     40   ARMGOTEntry* entry = new ARMGOTEntry(0, NULL);
     41   m_GOT.push_back(entry);
     42   return entry;
     43 }
     44 
     45 ARMGOTEntry* ARMGOT::createGOTPLT() {
     46   ARMGOTEntry* entry = new ARMGOTEntry(0, NULL);
     47   m_GOTPLT.push_back(entry);
     48   return entry;
     49 }
     50 
     51 void ARMGOT::finalizeSectionSize() {
     52   uint32_t offset = 0;
     53   SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList();
     54   // setup GOT0 offset
     55   SectionData::iterator frag, fragEnd = m_SectionData->end();
     56   for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
     57     frag->setOffset(offset);
     58     offset += frag->size();
     59   }
     60 
     61   // push GOTPLT into the SectionData and setup the offset
     62   if (!m_GOTPLT.empty()) {
     63     m_pGOTPLTFront = m_GOTPLT.front();
     64     entry_iterator it, end = m_GOTPLT.end();
     65     for (it = m_GOTPLT.begin(); it != end; ++it) {
     66       ARMGOTEntry* entry = *it;
     67       frag_list.push_back(entry);
     68       entry->setParent(m_SectionData);
     69       entry->setOffset(offset);
     70       offset += entry->size();
     71     }
     72   }
     73   m_GOTPLT.clear();
     74 
     75   // push GOT into the SectionData and setup the offset
     76   if (!m_GOT.empty()) {
     77     m_pGOTFront = m_GOT.front();
     78     entry_iterator it, end = m_GOT.end();
     79     for (it = m_GOT.begin(); it != end; ++it) {
     80       ARMGOTEntry* entry = *it;
     81       frag_list.push_back(entry);
     82       entry->setParent(m_SectionData);
     83       entry->setOffset(offset);
     84       offset += entry->size();
     85     }
     86   }
     87   m_GOT.clear();
     88 
     89   // set section size
     90   m_Section.setSize(offset);
     91 }
     92 
     93 void ARMGOT::applyGOT0(uint64_t pAddress) {
     94   llvm::cast<ARMGOTEntry>(*(m_SectionData->getFragmentList().begin()))
     95       .setValue(pAddress);
     96 }
     97 
     98 void ARMGOT::applyGOTPLT(uint64_t pPLTBase) {
     99   if (m_pGOTPLTFront == NULL)
    100     return;
    101 
    102   SectionData::iterator entry(m_pGOTPLTFront);
    103   SectionData::iterator e_end;
    104   if (m_pGOTFront == NULL)
    105     e_end = m_SectionData->end();
    106   else
    107     e_end = SectionData::iterator(m_pGOTFront);
    108 
    109   while (entry != e_end) {
    110     llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase);
    111     ++entry;
    112   }
    113 }
    114 
    115 uint64_t ARMGOT::emit(MemoryRegion& pRegion) {
    116   uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
    117 
    118   ARMGOTEntry* got = NULL;
    119   uint64_t result = 0x0;
    120   for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
    121     got = &(llvm::cast<ARMGOTEntry>((*it)));
    122     *buffer = static_cast<uint32_t>(got->getValue());
    123     result += ARMGOTEntry::EntrySize;
    124   }
    125   return result;
    126 }
    127 
    128 }  // namespace mcld
    129