• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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