• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- impl.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 "ARMGOT.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/MemoryRegion.h>
16 #include <mcld/Support/MsgHandling.h>
17 
18 namespace {
19   const unsigned int ARMGOT0Num = 3;
20 } // end of anonymous namespace
21 
22 using namespace mcld;
23 
24 //===----------------------------------------------------------------------===//
25 // ARMGOT
ARMGOT(LDSection & pSection)26 ARMGOT::ARMGOT(LDSection& pSection)
27   : GOT(pSection), m_pLast(NULL)
28 {
29   // Create GOT0 entries.
30   reserve(ARMGOT0Num);
31 
32   // Skip GOT0 entries.
33   for (unsigned int i = 0; i < ARMGOT0Num; ++i) {
34     consume();
35   }
36 }
37 
~ARMGOT()38 ARMGOT::~ARMGOT()
39 {
40 }
41 
hasGOT1() const42 bool ARMGOT::hasGOT1() const
43 {
44   return (m_SectionData->size() > ARMGOT0Num);
45 }
46 
reserve(size_t pNum)47 void ARMGOT::reserve(size_t pNum)
48 {
49   for (size_t i = 0; i < pNum; i++) {
50     new ARMGOTEntry(0, m_SectionData);
51   }
52 }
53 
consume()54 ARMGOTEntry* ARMGOT::consume()
55 {
56   if (NULL == m_pLast) {
57     assert(!empty() && "Consume empty GOT entry!");
58     m_pLast = llvm::cast<ARMGOTEntry>(&m_SectionData->front());
59     return m_pLast;
60   }
61 
62   m_pLast = llvm::cast<ARMGOTEntry>(m_pLast->getNextNode());
63   return m_pLast;
64 }
65 
reserveGOTPLT()66 void ARMGOT::reserveGOTPLT()
67 {
68   ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
69   if (NULL == m_GOTPLT.front) {
70     // GOTPLT is empty
71     if (NULL == m_GOT.front) {
72       // GOT part is also empty. Since entry is the last entry, we can assign
73       // it to GOTPLT directly.
74       m_GOTPLT.front = entry;
75     }
76     else {
77       // GOTn is not empty. Shift GOTn backward by one entry.
78       m_GOTPLT.front = m_GOT.front;
79       m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
80     }
81   }
82   else {
83     // GOTPLT is not empty
84     if (NULL != m_GOT.front)
85       m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
86   }
87 }
88 
reserveGOT()89 void ARMGOT::reserveGOT()
90 {
91   ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
92   if (NULL == m_GOT.front) {
93     // Entry must be the last entry. We can directly assign it to GOT part.
94     m_GOT.front = entry;
95   }
96 }
97 
consumeGOTPLT()98 ARMGOTEntry* ARMGOT::consumeGOTPLT()
99 {
100   assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
101 
102   if (NULL == m_GOTPLT.last_used) {
103     m_GOTPLT.last_used = m_GOTPLT.front;
104   }
105   else {
106     m_GOTPLT.last_used = llvm::cast<ARMGOTEntry>(m_GOTPLT.last_used->getNextNode());
107     assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
108   }
109   return m_GOTPLT.last_used;
110 }
111 
consumeGOT()112 ARMGOTEntry* ARMGOT::consumeGOT()
113 {
114   assert(NULL != m_GOT.front && "Consuming empty GOT section!");
115 
116   if (NULL == m_GOT.last_used) {
117     m_GOT.last_used = m_GOT.front;
118   }
119   else {
120     m_GOT.last_used = llvm::cast<ARMGOTEntry>(m_GOT.last_used->getNextNode());
121     assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
122   }
123   return m_GOT.last_used;
124 }
125 
applyGOT0(uint64_t pAddress)126 void ARMGOT::applyGOT0(uint64_t pAddress)
127 {
128   llvm::cast<ARMGOTEntry>
129     (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
130 }
131 
applyGOTPLT(uint64_t pPLTBase)132 void ARMGOT::applyGOTPLT(uint64_t pPLTBase)
133 {
134   if (NULL == m_GOTPLT.front)
135     return;
136 
137   SectionData::iterator entry(m_GOTPLT.front);
138   SectionData::iterator e_end;
139   if (NULL == m_GOT.front)
140     e_end = m_SectionData->end();
141   else
142     e_end = SectionData::iterator(m_GOT.front);
143 
144   while (entry != e_end) {
145     llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase);
146     ++entry;
147   }
148 }
149 
emit(MemoryRegion & pRegion)150 uint64_t ARMGOT::emit(MemoryRegion& pRegion)
151 {
152   uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
153 
154   ARMGOTEntry* got = NULL;
155   uint64_t result = 0x0;
156   for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
157       got = &(llvm::cast<ARMGOTEntry>((*it)));
158       *buffer = static_cast<uint32_t>(got->getValue());
159       result += ARMGOTEntry::EntrySize;
160   }
161   return result;
162 }
163 
164