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
AArch64GOT(LDSection & pSection)25 AArch64GOT::AArch64GOT(LDSection& pSection)
26 : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL)
27 {
28 }
29
~AArch64GOT()30 AArch64GOT::~AArch64GOT()
31 {
32 }
33
createGOT0()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
hasGOT1() const41 bool AArch64GOT::hasGOT1() const
42 {
43 return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
44 }
45
createGOT()46 AArch64GOTEntry* AArch64GOT::createGOT()
47 {
48 AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
49 m_GOT.push_back(entry);
50 return entry;
51 }
52
createGOTPLT()53 AArch64GOTEntry* AArch64GOT::createGOTPLT()
54 {
55 AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
56 m_GOTPLT.push_back(entry);
57 return entry;
58 }
59
finalizeSectionSize()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
applyGOT0(uint64_t pAddress)104 void AArch64GOT::applyGOT0(uint64_t pAddress)
105 {
106 llvm::cast<AArch64GOTEntry>
107 (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
108 }
109
applyGOTPLT(uint64_t pPLTBase)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
emit(MemoryRegion & pRegion)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