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