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