MipsGOT.cpp revision affc150dc44fab1911775a49636d0ce85333b634
1//===- MipsGOT.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
10#include <mcld/LD/ResolveInfo.h>
11#include <mcld/Support/MemoryRegion.h>
12#include <mcld/Support/MsgHandling.h>
13#include "MipsGOT.h"
14
15namespace {
16  const size_t MipsGOTEntrySize = 4;
17  const size_t MipsGOT0Num = 1;
18}
19
20using namespace mcld;
21
22//===----------------------------------------------------------------------===//
23// MipsGOT
24MipsGOT::MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
25  : GOT(pSection, pSectionData, MipsGOTEntrySize),
26    m_pLocalNum(0)
27{
28  // Create GOT0 entries.
29  for (size_t i = 0; i < MipsGOT0Num; ++i) {
30    GOTEntry* entry =
31      new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
32
33    if (NULL == entry)
34      fatal(diag::fail_allocate_memory) << "GOT0";
35
36    m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
37  }
38
39  // Skip GOT0 entries.
40  iterator it = m_SectionData.begin();
41  iterator ie = m_SectionData.end();
42
43  for (size_t i = 1; i < MipsGOT0Num; ++i) {
44    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
45
46    ++it;
47  }
48
49  m_LocalGOTIterator = it;
50  m_GlobalGOTIterator = it;
51  m_pLocalNum = MipsGOT0Num;
52}
53
54MipsGOT::iterator MipsGOT::begin()
55{
56  return m_SectionData.getFragmentList().begin();
57}
58
59MipsGOT::iterator MipsGOT::end()
60{
61  return m_SectionData.getFragmentList().end();
62}
63
64MipsGOT::const_iterator MipsGOT::begin() const
65{
66  return m_SectionData.getFragmentList().begin();
67}
68
69MipsGOT::const_iterator MipsGOT::end() const
70{
71  return m_SectionData.getFragmentList().end();
72}
73
74uint64_t MipsGOT::emit(MemoryRegion& pRegion)
75{
76  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
77
78  size_t entry_size = getEntrySize();
79
80  uint64_t result = 0;
81  for (iterator it = begin(), ie = end();
82       it != ie; ++it, ++buffer) {
83    GOTEntry* got = &(llvm::cast<GOTEntry>((*it)));
84    *buffer = static_cast<uint32_t>(got->getContent());
85    result += entry_size;
86  }
87  return result;
88}
89
90void MipsGOT::reserveEntry(size_t pNum)
91{
92  for (size_t i = 0; i < pNum; ++i) {
93    GOTEntry* entry =
94      new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
95
96    if (NULL == entry)
97      fatal(diag::fail_allocate_memory) << "GOTEntry";
98
99    m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
100  }
101}
102
103void MipsGOT::reserveLocalEntry()
104{
105  reserveEntry(1);
106  ++m_pLocalNum;
107
108  // Move global entries iterator forward.
109  // We need to put global GOT entries after all local ones.
110  ++m_GlobalGOTIterator;
111}
112
113void MipsGOT::reserveGlobalEntry()
114{
115  reserveEntry(1);
116}
117
118GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
119{
120  if (isLocal(&pInfo) && pInfo.type() == ResolveInfo::Section) {
121    pExist = false;
122    iterator& it = m_LocalGOTIterator;
123    ++it;
124    assert(it != m_SectionData.getFragmentList().end() &&
125           "The number of GOT Entries and ResolveInfo doesn't match");
126    GOTEntry* entry = llvm::cast<GOTEntry>(&(*it));
127    return entry;
128  }
129
130  GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
131
132  pExist = NULL != entry;
133
134  if (!pExist) {
135    iterator& it = isLocal(&pInfo)  ? m_LocalGOTIterator : m_GlobalGOTIterator;
136
137    ++it;
138
139    assert(it != m_SectionData.getFragmentList().end() &&
140           "The number of GOT Entries and ResolveInfo doesn't match");
141
142    entry = llvm::cast<GOTEntry>(&(*it));
143  }
144
145  return entry;
146}
147
148size_t MipsGOT::getTotalNum() const
149{
150  return m_SectionData.getFragmentList().size();
151}
152
153size_t MipsGOT::getLocalNum() const
154{
155  return m_pLocalNum;
156}
157
158