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
AArch64GOT(LDSection & pSection)25 AArch64GOT::AArch64GOT(LDSection& pSection)
26     : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) {
27 }
28 
~AArch64GOT()29 AArch64GOT::~AArch64GOT() {
30 }
31 
createGOT0()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 
hasGOT1() const38 bool AArch64GOT::hasGOT1() const {
39   return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
40 }
41 
createGOT()42 AArch64GOTEntry* AArch64GOT::createGOT() {
43   AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
44   m_GOT.push_back(entry);
45   return entry;
46 }
47 
createGOTPLT()48 AArch64GOTEntry* AArch64GOT::createGOTPLT() {
49   AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
50   m_GOTPLT.push_back(entry);
51   return entry;
52 }
53 
finalizeSectionSize()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 
applyGOT0(uint64_t pAddress)96 void AArch64GOT::applyGOT0(uint64_t pAddress) {
97   llvm::cast<AArch64GOTEntry>(*(m_SectionData->getFragmentList().begin()))
98       .setValue(pAddress);
99 }
100 
applyGOTPLT(uint64_t pPLTBase)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 
emit(MemoryRegion & pRegion)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