MipsGOT.h revision 533eae20118036f425f27bf0536ef0ccbb090b65
1//===- MipsGOT.h ----------------------------------------------------------===//
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#ifndef TARGET_MIPS_MIPSGOT_H
10#define TARGET_MIPS_MIPSGOT_H
11#include <map>
12#include <vector>
13
14
15#include <mcld/ADT/SizeTraits.h>
16#include <mcld/Target/GOT.h>
17#include <mcld/Fragment/Relocation.h>
18#include <mcld/Support/MemoryRegion.h>
19#include <llvm/ADT/DenseMap.h>
20#include <llvm/ADT/DenseSet.h>
21#include <set>
22
23namespace mcld {
24
25class Input;
26class LDSection;
27class LDSymbol;
28class OutputRelocSection;
29
30/** \class MipsGOT
31 *  \brief Mips Global Offset Table.
32 */
33class MipsGOT : public GOT
34{
35public:
36  MipsGOT(LDSection& pSection);
37
38  /// Assign value to the GOT entry.
39  virtual void setEntryValue(Fragment* entry, uint64_t pValue) = 0;
40
41  /// Emit the global offset table.
42  virtual uint64_t emit(MemoryRegion& pRegion) = 0;
43
44  /// Address of _gp_disp symbol.
45  uint64_t getGPDispAddress() const;
46
47  void initializeScan(const Input& pInput);
48  void finalizeScan(const Input& pInput);
49
50  bool reserveLocalEntry(ResolveInfo& pInfo, int reloc,
51                         Relocation::DWord pAddend);
52  bool reserveGlobalEntry(ResolveInfo& pInfo);
53
54  size_t getLocalNum() const;   ///< number of local symbols in primary GOT
55  size_t getGlobalNum() const;  ///< total number of global symbols
56
57  bool isPrimaryGOTConsumed();
58
59  Fragment* consumeLocal();
60  Fragment* consumeGlobal();
61
62  uint64_t getGPAddr(const Input& pInput) const;
63  uint64_t getGPRelOffset(const Input& pInput, const Fragment& pEntry) const;
64
65  void recordGlobalEntry(const ResolveInfo* pInfo, Fragment* pEntry);
66  Fragment* lookupGlobalEntry(const ResolveInfo* pInfo);
67
68  void recordLocalEntry(const ResolveInfo* pInfo,
69                        Relocation::DWord pAddend,
70                        Fragment* pEntry);
71  Fragment* lookupLocalEntry(const ResolveInfo* pInfo,
72                             Relocation::DWord pAddend);
73
74  /// hasGOT1 - return if this got section has any GOT1 entry
75  bool hasGOT1() const;
76
77  bool hasMultipleGOT() const;
78
79  /// Create GOT entries and reserve dynrel entries.
80  void finalizeScanning(OutputRelocSection& pRelDyn);
81
82  /// Compare two symbols to define order in the .dynsym.
83  bool dynSymOrderCompare(const LDSymbol* pX, const LDSymbol* pY) const;
84
85protected:
86  /// Create GOT entry.
87  virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent) = 0;
88
89  /// Size of GOT entry.
90  virtual size_t getEntrySize() const = 0;
91
92  /// Reserve GOT header entries.
93  virtual void reserveHeader() = 0;
94
95private:
96  /** \class GOTMultipart
97   *  \brief GOTMultipart counts local and global entries in the GOT.
98   */
99  struct GOTMultipart
100  {
101    GOTMultipart(size_t local = 0, size_t global = 0);
102
103    typedef llvm::DenseSet<const Input*> InputSetType;
104
105    size_t m_LocalNum;  ///< number of reserved local entries
106    size_t m_GlobalNum; ///< number of reserved global entries
107
108    size_t m_ConsumedLocal;       ///< consumed local entries
109    size_t m_ConsumedGlobal;      ///< consumed global entries
110
111    Fragment* m_pLastLocal;   ///< the last consumed local entry
112    Fragment* m_pLastGlobal;  ///< the last consumed global entry
113
114    InputSetType m_Inputs;
115
116    bool isConsumed() const;
117
118    void consumeLocal();
119    void consumeGlobal();
120  };
121
122  /** \class LocalEntry
123   *  \brief LocalEntry local GOT entry descriptor.
124   */
125  struct LocalEntry
126  {
127    const ResolveInfo* m_pInfo;
128    Relocation::DWord  m_Addend;
129    bool               m_IsGot16;
130
131    LocalEntry(const ResolveInfo* pInfo,
132               Relocation::DWord addend, bool isGot16);
133
134    bool operator<(const LocalEntry &O) const;
135  };
136
137  typedef std::vector<GOTMultipart> MultipartListType;
138
139  // Set of global symbols.
140  typedef llvm::DenseSet<const ResolveInfo*> SymbolSetType;
141  // Map of symbols. If value is true, the symbol is referenced
142  // in the current input only. If value is false, the symbol
143  // is referenced in the other modules merged to the current GOT.
144  typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolUniqueMapType;
145
146  // Set of local symbols.
147  typedef std::set<LocalEntry> LocalSymbolSetType;
148
149  MultipartListType m_MultipartList;  ///< list of GOT's descriptors
150  const Input* m_pInput;              ///< current input
151
152  // Global symbols merged to the current GOT
153  // except symbols from the current input.
154  SymbolSetType m_MergedGlobalSymbols;
155  // Global symbols from the current input.
156  SymbolUniqueMapType m_InputGlobalSymbols;
157  // Local symbols merged to the current GOT
158  // except symbols from the current input.
159  LocalSymbolSetType m_MergedLocalSymbols;
160  // Local symbols from the current input.
161  LocalSymbolSetType m_InputLocalSymbols;
162
163  size_t m_CurrentGOTPart;
164
165  typedef llvm::DenseMap<const LDSymbol*, unsigned> SymbolOrderMapType;
166  SymbolOrderMapType m_SymbolOrderMap;
167
168  void initGOTList();
169
170  void changeInput();
171  bool isGOTFull() const;
172  void split();
173  void reserve(size_t pNum);
174
175private:
176  struct GotEntryKey
177  {
178    size_t m_GOTPage;
179    const ResolveInfo* m_pInfo;
180    Relocation::DWord m_Addend;
181
182    bool operator<(const GotEntryKey& key) const
183    {
184      if (m_GOTPage != key.m_GOTPage)
185        return m_GOTPage < key.m_GOTPage;
186
187      if (m_pInfo != key.m_pInfo)
188        return m_pInfo < key.m_pInfo;
189
190      return m_Addend < key.m_Addend;
191    }
192  };
193
194  typedef std::map<GotEntryKey, Fragment*> GotEntryMapType;
195  GotEntryMapType m_GotLocalEntriesMap;
196  GotEntryMapType m_GotGlobalEntriesMap;
197};
198
199/** \class Mips32GOT
200 *  \brief Mips 32-bit Global Offset Table.
201 */
202class Mips32GOT : public MipsGOT
203{
204public:
205  Mips32GOT(LDSection& pSection);
206
207private:
208  typedef GOT::Entry<4> Mips32GOTEntry;
209
210  // MipsGOT
211  virtual void setEntryValue(Fragment* entry, uint64_t pValue);
212  virtual uint64_t emit(MemoryRegion& pRegion);
213  virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent);
214  virtual size_t getEntrySize() const;
215  virtual void reserveHeader();
216};
217
218/** \class Mips64GOT
219 *  \brief Mips 64-bit Global Offset Table.
220 */
221class Mips64GOT : public MipsGOT
222{
223public:
224  Mips64GOT(LDSection& pSection);
225
226private:
227  typedef GOT::Entry<8> Mips64GOTEntry;
228
229  // MipsGOT
230  virtual void setEntryValue(Fragment* entry, uint64_t pValue);
231  virtual uint64_t emit(MemoryRegion& pRegion);
232  virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent);
233  virtual size_t getEntrySize() const;
234  virtual void reserveHeader();
235};
236
237} // namespace of mcld
238
239#endif
240
241