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