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