• 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 <new>
12 
13 #include <llvm/Support/Casting.h>
14 
15 #include <mcld/LD/LDFileFormat.h>
16 #include <mcld/Support/MemoryRegion.h>
17 #include <mcld/Support/MsgHandling.h>
18 
19 namespace {
20   const size_t ARMGOTEntrySize = 4;
21 } // end of anonymous namespace
22 
23 using namespace mcld;
24 
25 //===----------------------------------------------------------------------===//
26 // ARMGOT
ARMGOT(LDSection & pSection,SectionData & pSectionData)27 ARMGOT::ARMGOT(LDSection& pSection, SectionData& pSectionData)
28              : GOT(pSection, pSectionData, ARMGOTEntrySize),
29                m_NormalGOTIterator(), m_GOTPLTIterator(),
30                m_GOTPLTBegin(), m_GOTPLTEnd()
31 {
32   GOTEntry* Entry = 0;
33 
34   // Create GOT0 entries.
35   for (int i = 0; i < 3; i++) {
36     Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
37                                         &m_SectionData);
38 
39     if (!Entry)
40       fatal(diag::fail_allocate_memory_got);
41 
42     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
43   }
44 
45   // Skip GOT0 entries.
46   iterator it = m_SectionData.begin();
47 
48   for (int i = 1; i < ARMGOT0Num; ++i) {
49     assert((it != m_SectionData.end()) && "Generation of GOT0 entries is incomplete!");
50     ++it;
51   }
52 
53   m_NormalGOTIterator = it;
54   m_GOTPLTIterator = it;
55 
56   m_GOTPLTBegin = it;
57   m_GOTPLTEnd = it;
58 }
59 
~ARMGOT()60 ARMGOT::~ARMGOT()
61 {
62 }
63 
reserveEntry(size_t pNum)64 void ARMGOT::reserveEntry(size_t pNum)
65 {
66   GOTEntry* Entry = 0;
67 
68   for (size_t i = 0; i < pNum; i++) {
69     Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
70                                         &m_SectionData);
71 
72     if (!Entry)
73       fatal(diag::fail_allocate_memory_got);
74 
75     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
76   }
77 }
78 
reserveGOTPLTEntry()79 void ARMGOT::reserveGOTPLTEntry()
80 {
81     GOTEntry* got_entry = 0;
82 
83     got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
84 
85     if (!got_entry)
86       fatal(diag::fail_allocate_memory_got);
87 
88     m_Section.setSize(m_Section.size() + getEntrySize());
89 
90     ++m_GOTPLTEnd;
91     ++m_NormalGOTIterator;
92 }
93 
getEntry(const ResolveInfo & pInfo,bool & pExist)94 GOTEntry* ARMGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
95 {
96   GOTEntry *&Entry = m_NormalGOTMap[&pInfo];
97   pExist = 1;
98 
99   if (!Entry) {
100     pExist = 0;
101 
102     ++m_NormalGOTIterator;
103     assert(m_NormalGOTIterator != m_SectionData.getFragmentList().end()
104            && "The number of GOT Entries and ResolveInfo doesn't match!");
105 
106     Entry = llvm::cast<GOTEntry>(&(*m_NormalGOTIterator));
107   }
108 
109   return Entry;
110 }
111 
applyGOT0(uint64_t pAddress)112 void ARMGOT::applyGOT0(uint64_t pAddress)
113 {
114   llvm::cast<GOTEntry>
115     (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
116 }
117 
applyAllGOTPLT(uint64_t pPLTBase)118 void ARMGOT::applyAllGOTPLT(uint64_t pPLTBase)
119 {
120   iterator begin = getGOTPLTBegin();
121   iterator end = getGOTPLTEnd();
122 
123   for (;begin != end ;++begin)
124     llvm::cast<GOTEntry>(*begin).setContent(pPLTBase);
125 }
126 
lookupGOTPLTMap(const ResolveInfo & pSymbol)127 GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
128 {
129   return m_GOTPLTMap[&pSymbol];
130 }
131 
begin()132 ARMGOT::iterator ARMGOT::begin()
133 {
134   return m_SectionData.getFragmentList().begin();
135 }
136 
begin() const137 ARMGOT::const_iterator ARMGOT::begin() const
138 {
139   return m_SectionData.getFragmentList().begin();
140 }
141 
end()142 ARMGOT::iterator ARMGOT::end()
143 {
144   return m_SectionData.getFragmentList().end();
145 }
146 
end() const147 ARMGOT::const_iterator ARMGOT::end() const
148 {
149   return m_SectionData.getFragmentList().end();
150 }
151 
getNextGOTPLTEntry()152 ARMGOT::iterator ARMGOT::getNextGOTPLTEntry()
153 {
154   return ++m_GOTPLTIterator;
155 }
156 
getGOTPLTBegin()157 ARMGOT::iterator ARMGOT::getGOTPLTBegin()
158 {
159   // Move to the first GOTPLT entry from last GOT0 entry.
160   iterator begin = m_GOTPLTBegin;
161   return ++begin;
162 }
163 
getGOTPLTEnd()164 const ARMGOT::iterator ARMGOT::getGOTPLTEnd()
165 {
166   // Move to end or the first normal GOT entry from the last GOTPLT entry.
167   iterator end = m_GOTPLTEnd;
168   return ++end;
169 }
170 
emit(MemoryRegion & pRegion)171 uint64_t ARMGOT::emit(MemoryRegion& pRegion)
172 {
173   uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
174 
175   GOTEntry* got = 0;
176   unsigned int entry_size = getEntrySize();
177   uint64_t result = 0x0;
178   for (iterator it = begin(), ie = end();
179        it != ie; ++it, ++buffer) {
180       got = &(llvm::cast<GOTEntry>((*it)));
181       *buffer = static_cast<uint32_t>(got->getContent());
182       result += entry_size;
183   }
184   return result;
185 }
186 
187