• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 {
35 public:
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 
85 protected:
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 
95 private:
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 
175 private:
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  */
202 class Mips32GOT : public MipsGOT
203 {
204 public:
205   Mips32GOT(LDSection& pSection);
206 
207 private:
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  */
221 class Mips64GOT : public MipsGOT
222 {
223 public:
224   Mips64GOT(LDSection& pSection);
225 
226 private:
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