• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- X86LDBackend.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 X86_LDBACKEND_H
10 #define X86_LDBACKEND_H
11 
12 #include "X86ELFDynamic.h"
13 #include "X86GOT.h"
14 #include "X86GOTPLT.h"
15 #include "X86PLT.h"
16 #include <mcld/LD/LDSection.h>
17 #include <mcld/Target/GNULDBackend.h>
18 #include <mcld/Target/OutputRelocSection.h>
19 
20 namespace mcld {
21 
22 class LinkerConfig;
23 class GNUInfo;
24 
25 //===----------------------------------------------------------------------===//
26 /// X86GNULDBackend - linker backend of X86 target of GNU ELF format
27 ///
28 class X86GNULDBackend : public GNULDBackend
29 {
30 public:
31   /** \enum ReservedEntryType
32    *  \brief The reserved entry type of reserved space in ResolveInfo.
33    *
34    *  This is used for sacnRelocation to record what kinds of entries are
35    *  reserved for this resolved symbol
36    *
37    *  In X86, there are three kinds of entries, GOT, PLT, and dynamic reloction.
38    *  GOT may needs a corresponding relocation to relocate itself, so we
39    *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
40    *  symbol, there might be two kinds of entries reserved for different location.
41    *  For example, reference to the same symbol, one may use GOT and the other may
42    *  use dynamic relocation.
43    *
44    *  bit:  3       2      1     0
45    *   | PLT | GOTRel | GOT | Rel |
46    *
47    *  value    Name         - Description
48    *
49    *  0000     None         - no reserved entry
50    *  0001     ReserveRel   - reserve an dynamic relocation entry
51    *  0010     ReserveGOT   - reserve an GOT entry
52    *  0011     GOTandRel    - For different relocation, we've reserved GOT and
53    *                          Rel for different location.
54    *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
55    *                          relocation entry which relocate this GOT entry
56    *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
57    *                          and relocation entry for different location.
58    *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
59    *                          Dynamic relocation entries
60    *  1001     PLTandRel    - For different relocation, we've reserved PLT and
61    *                          Rel for different location.
62    */
63   enum ReservedEntryType {
64     None         = 0,
65     ReserveRel   = 1,
66     ReserveGOT   = 2,
67     GOTandRel    = 3,
68     GOTRel       = 4,
69     GOTRelandRel = 5,
70     ReservePLT   = 8,
71     PLTandRel    = 9
72   };
73 
74 public:
75   X86GNULDBackend(const LinkerConfig& pConfig,
76 		  GNUInfo* pInfo,
77 		  Relocation::Type pCopyRel);
78 
79   ~X86GNULDBackend();
80 
81   uint32_t machine() const;
82 
83   X86PLT& getPLT();
84 
85   const X86PLT& getPLT() const;
86 
87   /// preLayout - Backend can do any needed modification before layout
88   void doPreLayout(IRBuilder& pBuilder);
89 
90   /// postLayout -Backend can do any needed modification after layout
91   void doPostLayout(Module& pModule, IRBuilder& pBuilder);
92 
93   /// dynamic - the dynamic section of the target machine.
94   /// Use co-variant return type to return its own dynamic section.
95   X86ELFDynamic& dynamic();
96 
97   /// dynamic - the dynamic section of the target machine.
98   /// Use co-variant return type to return its own dynamic section.
99   const X86ELFDynamic& dynamic() const;
100 
101   /// emitSectionData - write out the section data into the memory region.
102   /// When writers get a LDSection whose kind is LDFileFormat::Target, writers
103   /// call back target backend to emit the data.
104   ///
105   /// Backends handle the target-special tables (plt, gp,...) by themselves.
106   /// Backend can put the data of the tables in MCSectionData directly
107   ///  - LDSection.getSectionData can get the section data.
108   /// Or, backend can put the data into special data structure
109   ///  - backend can maintain its own map<LDSection, table> to get the table
110   /// from given LDSection.
111   ///
112   /// @param pSection - the given LDSection
113   /// @param pLayout - for comouting the size of fragment
114   /// @param pRegion - the region to write out data
115   /// @return the size of the table in the file.
116   uint64_t emitSectionData(const LDSection& pSection,
117                            MemoryRegion& pRegion) const;
118 
119   /// initRelocator - create and initialize Relocator.
120   virtual bool initRelocator() = 0;
121 
122   /// getRelocator - return relocator.
123   Relocator* getRelocator();
124 
125   virtual void initTargetSections(Module& pModule, ObjectBuilder& pBuilder) = 0;
126 
127   void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
128 
129   /// scanRelocation - determine the empty entries are needed or not and create
130   /// the empty entries if needed.
131   /// For X86, following entries are check to create:
132   /// - GOT entry (for .got and .got.plt sections)
133   /// - PLT entry (for .plt section)
134   /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
135   void scanRelocation(Relocation& pReloc,
136                       IRBuilder& pBuilder,
137                       Module& pModule,
138                       LDSection& pSection);
139 
140   OutputRelocSection& getRelDyn();
141 
142   const OutputRelocSection& getRelDyn() const;
143 
144   OutputRelocSection& getRelPLT();
145 
146   const OutputRelocSection& getRelPLT() const;
147 
148   /// getTargetSectionOrder - compute the layout order of X86 target sections
149   unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
150 
151   /// finalizeTargetSymbols - finalize the symbol value
152   bool finalizeTargetSymbols();
153 
154   /// getPointerRel - get pointer relocation type.
getPointerRel()155   Relocation::Type getPointerRel()
156   { return m_PointerRel; }
157 
158 private:
159   virtual void scanLocalReloc(Relocation& pReloc,
160 			      IRBuilder& pBuilder,
161 			      Module& pModule,
162 			      LDSection& pSection) = 0;
163 
164   virtual void scanGlobalReloc(Relocation& pReloc,
165 			       IRBuilder& pBuilder,
166 			       Module& pModule,
167 			       LDSection& pSection) = 0;
168 
169 protected:
170   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
171   /// @param pSym - A resolved copy symbol that defined in BSS section
172   void addCopyReloc(ResolveInfo& pSym);
173 
174   /// defineSymbolforCopyReloc - allocate a space in BSS section and
175   /// and force define the copy of pSym to BSS section
176   /// @return the output LDSymbol of the copy symbol
177   LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker,
178                                      const ResolveInfo& pSym);
179 
180   void defineGOTSymbol(IRBuilder& pBuilder, Fragment&);
181 
182 protected:
183   /// getRelEntrySize - the size in BYTE of rel type relocation
getRelEntrySize()184   size_t getRelEntrySize()
185   { return m_RelEntrySize; }
186 
187   /// getRelEntrySize - the size in BYTE of rela type relocation
getRelaEntrySize()188   size_t getRelaEntrySize()
189   { return m_RelaEntrySize; }
190 
191 private:
192   /// doCreateProgramHdrs - backend can implement this function to create the
193   /// target-dependent segments
194   void doCreateProgramHdrs(Module& pModule);
195 
196   virtual void setGOTSectionSize(IRBuilder& pBuilder) = 0;
197 
198   virtual uint64_t emitGOTSectionData(MemoryRegion& pRegion) const = 0;
199 
200   virtual uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion,
201 					 const ELFFileFormat* FileFormat) const = 0;
202 
203   virtual void setRelDynSize() = 0;
204   virtual void setRelPLTSize() = 0;
205 
206 protected:
207   Relocator* m_pRelocator;
208   X86PLT* m_pPLT;
209   /// m_RelDyn - dynamic relocation table of .rel.dyn
210   OutputRelocSection* m_pRelDyn;
211   /// m_RelPLT - dynamic relocation table of .rel.plt
212   OutputRelocSection* m_pRelPLT;
213 
214   X86ELFDynamic* m_pDynamic;
215   LDSymbol* m_pGOTSymbol;
216 
217   size_t m_RelEntrySize;
218   size_t m_RelaEntrySize;
219 
220   Relocation::Type m_CopyRel;
221   Relocation::Type m_PointerRel;
222 };
223 
224 //
225 //===----------------------------------------------------------------------===//
226 /// X86_32GNULDBackend - linker backend of X86-32 target of GNU ELF format
227 ///
228 class X86_32GNULDBackend : public X86GNULDBackend
229 {
230 public:
231   X86_32GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
232 
233   ~X86_32GNULDBackend();
234 
235   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
236 
237   X86_32GOT& getGOT();
238 
239   const X86_32GOT& getGOT() const;
240 
241   X86_32GOTPLT& getGOTPLT();
242 
243   const X86_32GOTPLT& getGOTPLT() const;
244 
245   X86_32GOTEntry& getTLSModuleID();
246 
247 private:
248   void scanLocalReloc(Relocation& pReloc,
249                       IRBuilder& pBuilder,
250                       Module& pModule,
251                       LDSection& pSection);
252 
253   void scanGlobalReloc(Relocation& pReloc,
254                        IRBuilder& pBuilder,
255                        Module& pModule,
256                        LDSection& pSection);
257 
258   /// initRelocator - create and initialize Relocator.
259   bool initRelocator();
260 
261   /// -----  tls optimization  ----- ///
262   /// convert R_386_TLS_IE to R_386_TLS_LE
263   void convertTLSIEtoLE(Relocation& pReloc, LDSection& pSection);
264 
265   void setGOTSectionSize(IRBuilder& pBuilder);
266 
267   uint64_t emitGOTSectionData(MemoryRegion& pRegion) const;
268 
269   uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion,
270 				 const ELFFileFormat* FileFormat) const;
271 
272   void setRelDynSize();
273   void setRelPLTSize();
274 
275 private:
276   X86_32GOT* m_pGOT;
277   X86_32GOTPLT* m_pGOTPLT;
278 };
279 
280 //
281 //===----------------------------------------------------------------------===//
282 /// X86_64GNULDBackend - linker backend of X86-64 target of GNU ELF format
283 ///
284 class X86_64GNULDBackend : public X86GNULDBackend
285 {
286 public:
287   X86_64GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
288 
289   ~X86_64GNULDBackend();
290 
291   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
292 
293   X86_64GOT& getGOT();
294 
295   const X86_64GOT& getGOT() const;
296 
297   X86_64GOTPLT& getGOTPLT();
298 
299   const X86_64GOTPLT& getGOTPLT() const;
300 
301 private:
302   void scanLocalReloc(Relocation& pReloc,
303                       IRBuilder& pBuilder,
304                       Module& pModule,
305                       LDSection& pSection);
306 
307   void scanGlobalReloc(Relocation& pReloc,
308                        IRBuilder& pBuilder,
309                        Module& pModule,
310                        LDSection& pSection);
311 
312   /// initRelocator - create and initialize Relocator.
313   bool initRelocator();
314 
315   void setGOTSectionSize(IRBuilder& pBuilder);
316 
317   uint64_t emitGOTSectionData(MemoryRegion& pRegion) const;
318 
319   uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion,
320 				 const ELFFileFormat* FileFormat) const;
321 
322   void setRelDynSize();
323   void setRelPLTSize();
324 
325 private:
326   X86_64GOT* m_pGOT;
327   X86_64GOTPLT* m_pGOTPLT;
328 };
329 } // namespace of mcld
330 
331 #endif
332 
333