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