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
18 namespace {
19 const size_t MipsGOTEntrySize = 4;
20 const size_t MipsGOT0Num = 1;
21 }
22
23 using namespace mcld;
24
25 //===----------------------------------------------------------------------===//
26 // MipsGOT
MipsGOT(LDSection & pSection,SectionData & pSectionData)27 MipsGOT::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
begin()57 MipsGOT::iterator MipsGOT::begin()
58 {
59 return m_SectionData.getFragmentList().begin();
60 }
61
end()62 MipsGOT::iterator MipsGOT::end()
63 {
64 return m_SectionData.getFragmentList().end();
65 }
66
begin() const67 MipsGOT::const_iterator MipsGOT::begin() const
68 {
69 return m_SectionData.getFragmentList().begin();
70 }
71
end() const72 MipsGOT::const_iterator MipsGOT::end() const
73 {
74 return m_SectionData.getFragmentList().end();
75 }
76
emit(MemoryRegion & pRegion)77 uint64_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
reserveEntry(size_t pNum)93 void 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
reserveLocalEntry()106 void 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
reserveGlobalEntry()116 void MipsGOT::reserveGlobalEntry()
117 {
118 reserveEntry(1);
119 }
120
getEntry(const ResolveInfo & pInfo,bool & pExist)121 GOTEntry* 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
getTotalNum() const151 size_t MipsGOT::getTotalNum() const
152 {
153 return m_SectionData.getFragmentList().size();
154 }
155
getLocalNum() const156 size_t MipsGOT::getLocalNum() const
157 {
158 return m_pLocalNum;
159 }
160
161