• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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