15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MipsGOT.cpp --------------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
11f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <llvm/Support/ELF.h>
12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/ResolveInfo.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
16f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Target/OutputRelocSection.h>
17f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
18f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include "MipsGOT.h"
19f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include "MipsRelocator.h"
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace {
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const size_t MipsGOT0Num = 1;
23f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  const size_t MipsGOTGpOffset = 0x7FF0;
24f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  const size_t MipsGOTSize = MipsGOTGpOffset + 0x7FFF;
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
30f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// MipsGOTEntry
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
32f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsGOTEntry::MipsGOTEntry(uint64_t pContent, SectionData* pParent)
33f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines   : GOT::Entry<4>(pContent, pParent)
34f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{}
35f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// MipsGOT::GOTMultipart
38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
39f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsGOT::GOTMultipart::GOTMultipart(size_t local, size_t global)
40f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : m_LocalNum(local),
41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_GlobalNum(global),
42f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_ConsumedLocal(0),
43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_ConsumedGlobal(0),
44f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pLastLocal(NULL),
45f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pLastGlobal(NULL)
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::GOTMultipart::isConsumed() const
50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_LocalNum == m_ConsumedLocal &&
52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         m_GlobalNum == m_ConsumedGlobal;
53f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
55f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::GOTMultipart::consumeLocal()
56f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
57f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(m_ConsumedLocal < m_LocalNum &&
58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         "Consumed too many local GOT entries");
59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ++m_ConsumedLocal;
60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pLastLocal = llvm::cast<MipsGOTEntry>(m_pLastLocal->getNextNode());
61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::GOTMultipart::consumeGlobal()
64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(m_ConsumedGlobal < m_GlobalNum &&
66f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         "Consumed too many global GOT entries");
67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ++m_ConsumedGlobal;
68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_pLastGlobal = llvm::cast<MipsGOTEntry>(m_pLastGlobal->getNextNode());
69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// MipsGOT
73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===----------------------------------------------------------------------===//
74f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsGOT::MipsGOT(LDSection& pSection)
75f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : GOT(pSection),
76f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pInput(NULL),
77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_CurrentGOTPart(0)
78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesSizeTraits<32>::Address MipsGOT::getGPDispAddress() const
82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return addr() + MipsGOTGpOffset;
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
86d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid MipsGOT::reserve(size_t pNum)
87d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
88d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  for (size_t i = 0; i < pNum; i++) {
89d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    new MipsGOTEntry(0, m_SectionData);
90d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  }
91d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
92d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::hasGOT1() const
94d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return !m_MultipartList.empty();
96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
97d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::hasMultipleGOT() const
99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_MultipartList.size() > 1;
101d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::finalizeScanning(OutputRelocSection& pRelDyn)
104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (MultipartListType::iterator it = m_MultipartList.begin();
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       it != m_MultipartList.end(); ++it) {
107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    reserve(MipsGOT0Num);
108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    it->m_pLastLocal = llvm::cast<MipsGOTEntry>(&m_SectionData->back());
109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    reserve(it->m_LocalNum);
110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    it->m_pLastGlobal = llvm::cast<MipsGOTEntry>(&m_SectionData->back());
111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    reserve(it->m_GlobalNum);
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (it == m_MultipartList.begin())
114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve entries in the second part of the primary GOT.
115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // These entries correspond to the global symbols in all
116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // non-primary GOTs.
117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      reserve(getGlobalNum() - it->m_GlobalNum);
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    else {
119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve reldyn entries for R_MIPS_REL32 relocations
120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // for all global entries of secondary GOTs.
121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: (simon) Do not count local entries for non-pic.
122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      size_t count = it->m_GlobalNum + it->m_LocalNum;
123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      for (size_t i = 0; i < count; ++i)
124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pRelDyn.reserveEntry();
125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::dynSymOrderCompare(const LDSymbol* pX, const LDSymbol* pY) const
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SymbolOrderMapType::const_iterator itX = m_SymbolOrderMap.find(pX);
132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SymbolOrderMapType::const_iterator itY = m_SymbolOrderMap.find(pY);
133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (itX != m_SymbolOrderMap.end() && itY != m_SymbolOrderMap.end())
135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return itX->second < itY->second;
136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return itX == m_SymbolOrderMap.end() && itY != m_SymbolOrderMap.end();
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t MipsGOT::emit(MemoryRegion& pRegion)
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t result = 0;
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (iterator it = begin(), ie = end();
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       it != ie; ++it, ++buffer) {
147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    MipsGOTEntry* got = &(llvm::cast<MipsGOTEntry>((*it)));
148d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    *buffer = static_cast<uint32_t>(got->getValue());
149d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    result += got->size();
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::initGOTList()
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_SymbolOrderMap.clear();
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.clear();
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.push_back(GOTMultipart());
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.back().m_Inputs.insert(m_pInput);
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MergedGlobalSymbols.clear();
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_InputGlobalSymbols.clear();
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MergedLocalSymbols.clear();
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_InputLocalSymbols.clear();
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::changeInput()
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.back().m_Inputs.insert(m_pInput);
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (SymbolSetType::iterator it = m_InputLocalSymbols.begin(),
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               end = m_InputLocalSymbols.end();
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       it != end; ++it)
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_MergedLocalSymbols.insert(*it);
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_InputLocalSymbols.clear();
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (SymbolUniqueMapType::iterator it = m_InputGlobalSymbols.begin(),
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     end = m_InputGlobalSymbols.end();
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       it != end; ++it)
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_MergedGlobalSymbols.insert(it->first);
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_InputGlobalSymbols.clear();
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::isGOTFull() const
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint64_t gotCount = MipsGOT0Num +
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      m_MultipartList.back().m_LocalNum +
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      m_MultipartList.back().m_GlobalNum;
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  gotCount += 1;
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return (gotCount * mcld::MipsGOTEntry::EntrySize) > MipsGOTSize;
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::split()
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MergedLocalSymbols.clear();
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MergedGlobalSymbols.clear();
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  size_t uniqueCount = 0;
205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (SymbolUniqueMapType::const_iterator it = m_InputGlobalSymbols.begin(),
206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                           end = m_InputGlobalSymbols.end();
207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       it != end; ++it) {
208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (it->second)
209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      ++uniqueCount;
210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.back().m_LocalNum -= m_InputLocalSymbols.size();
213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.back().m_GlobalNum -= uniqueCount;
214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.back().m_Inputs.erase(m_pInput);
215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.push_back(GOTMultipart(m_InputLocalSymbols.size(),
217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                         m_InputGlobalSymbols.size()));
218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList.back().m_Inputs.insert(m_pInput);
219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::initializeScan(const Input& pInput)
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (m_pInput == NULL) {
224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pInput = &pInput;
225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    initGOTList();
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else {
228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pInput = &pInput;
229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    changeInput();
230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::finalizeScan(const Input& pInput)
234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::reserveLocalEntry(ResolveInfo& pInfo)
238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pInfo.type() != ResolveInfo::Section) {
240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (m_InputLocalSymbols.count(&pInfo))
241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return false;
242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (m_MergedLocalSymbols.count(&pInfo)) {
244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      m_InputLocalSymbols.insert(&pInfo);
245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return false;
246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (isGOTFull())
250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    split();
251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pInfo.type() != ResolveInfo::Section)
253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_InputLocalSymbols.insert(&pInfo);
254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ++m_MultipartList.back().m_LocalNum;
256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::reserveGlobalEntry(ResolveInfo& pInfo)
260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (m_InputGlobalSymbols.count(&pInfo))
262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (m_MergedGlobalSymbols.count(&pInfo)) {
265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_InputGlobalSymbols[&pInfo] = false;
266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return false;
267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (isGOTFull())
270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    split();
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_InputGlobalSymbols[&pInfo] = true;
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ++m_MultipartList.back().m_GlobalNum;
274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!(pInfo.reserved() & MipsRelocator::ReserveGot)) {
276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_SymbolOrderMap[pInfo.outSymbol()] = m_SymbolOrderMap.size();
277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pInfo.setReserved(pInfo.reserved() | MipsRelocator::ReserveGot);
278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return true;
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGOT::isPrimaryGOTConsumed()
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_CurrentGOTPart > 0;
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
288d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGOTEntry* MipsGOT::consumeLocal()
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(m_CurrentGOTPart < m_MultipartList.size() && "GOT number is out of range!");
291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (m_MultipartList[m_CurrentGOTPart].isConsumed())
293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    ++m_CurrentGOTPart;
294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList[m_CurrentGOTPart].consumeLocal();
296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_MultipartList[m_CurrentGOTPart].m_pLastLocal;
29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
300d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGOTEntry* MipsGOT::consumeGlobal()
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(m_CurrentGOTPart < m_MultipartList.size() && "GOT number is out of range!");
303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (m_MultipartList[m_CurrentGOTPart].isConsumed())
305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    ++m_CurrentGOTPart;
306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_MultipartList[m_CurrentGOTPart].consumeGlobal();
308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_MultipartList[m_CurrentGOTPart].m_pLastGlobal;
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesSizeTraits<32>::Address MipsGOT::getGPAddr(const Input& pInput) const
3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint64_t gotSize = 0;
315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (MultipartListType::const_iterator it = m_MultipartList.begin();
316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                         it != m_MultipartList.end(); ++it) {
317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (it->m_Inputs.count(&pInput))
318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    gotSize += (MipsGOT0Num + it->m_LocalNum + it->m_GlobalNum);
321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (it == m_MultipartList.begin())
322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      gotSize += getGlobalNum() - it->m_GlobalNum;
323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return addr() + gotSize * MipsGOTEntry::EntrySize + MipsGOTGpOffset;
326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesSizeTraits<32>::Offset MipsGOT::getGPRelOffset(const Input& pInput,
329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                               const MipsGOTEntry& pEntry) const
330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SizeTraits<32>::Address gpAddr = getGPAddr(pInput);
332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return addr() + pEntry.getOffset() - gpAddr;
333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGOT::recordEntry(const ResolveInfo* pInfo, MipsGOTEntry* pEntry)
336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  GotEntryKey key;
338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  key.m_GOTPage = m_CurrentGOTPart;
339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  key.m_pInfo = pInfo;
340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  m_GotEntriesMap[key] = pEntry;
341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsGOTEntry* MipsGOT::lookupEntry(const ResolveInfo* pInfo)
344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
345f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  GotEntryKey key;
346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  key.m_GOTPage= m_CurrentGOTPart;
347f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  key.m_pInfo = pInfo;
348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  GotEntryMapType::iterator it = m_GotEntriesMap.find(key);
349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (it == m_GotEntriesMap.end())
351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return NULL;
352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return it->second;
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t MipsGOT::getLocalNum() const
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(!m_MultipartList.empty() && "GOT is empty!");
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_MultipartList[0].m_LocalNum + MipsGOT0Num;
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
361affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinessize_t MipsGOT::getGlobalNum() const
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return m_SymbolOrderMap.size();
365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
366