• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- MipsLDBackend.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_MIPSLDBACKEND_H
10 #define TARGET_MIPS_MIPSLDBACKEND_H
11 #include <mcld/Target/GNULDBackend.h>
12 #include "MipsELFDynamic.h"
13 #include "MipsGOT.h"
14 #include "MipsGOTPLT.h"
15 #include "MipsPLT.h"
16 
17 namespace mcld {
18 
19 class LinkerConfig;
20 class OutputRelocSection;
21 class SectionMap;
22 class MemoryArea;
23 class MipsGNUInfo;
24 
25 /** \class MipsGNULDBackend
26  *  \brief Base linker backend of Mips target of GNU ELF format.
27  */
28 class MipsGNULDBackend : public GNULDBackend
29 {
30 public:
31   typedef std::vector<LDSymbol*> SymbolListType;
32 
33 public:
34   MipsGNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
35   ~MipsGNULDBackend();
36 
37   bool needsLA25Stub(Relocation::Type pType, const mcld::ResolveInfo* pSym);
38 
39   void addNonPICBranchSym(ResolveInfo* rsym);
40   bool hasNonPICBranch(const ResolveInfo* rsym) const;
41 
42 public:
43   /// initTargetSections - initialize target dependent sections in output
44   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
45 
46   /// initTargetSymbols - initialize target dependent symbols in output.
47   void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
48 
49   /// getRelocator - return relocator.
50   const Relocator* getRelocator() const;
51   Relocator* getRelocator();
52 
53   /// preLayout - Backend can do any needed modification before layout
54   void doPreLayout(IRBuilder& pBuilder);
55 
56   /// postLayout - Backend can do any needed modification after layout
57   void doPostLayout(Module& pModule, IRBuilder& pBuilder);
58 
59   /// dynamic - the dynamic section of the target machine.
60   /// Use co-variant return type to return its own dynamic section.
61   MipsELFDynamic& dynamic();
62 
63   /// dynamic - the dynamic section of the target machine.
64   /// Use co-variant return type to return its own dynamic section.
65   const MipsELFDynamic& dynamic() const;
66 
67   /// emitSectionData - write out the section data into the memory region.
68   /// When writers get a LDSection whose kind is LDFileFormat::Target, writers
69   /// call back target backend to emit the data.
70   ///
71   /// Backends handle the target-special tables (plt, gp,...) by themselves.
72   /// Backend can put the data of the tables in SectionData directly
73   ///  - LDSection.getSectionData can get the section data.
74   /// Or, backend can put the data into special data structure
75   ///  - backend can maintain its own map<LDSection, table> to get the table
76   /// from given LDSection.
77   ///
78   /// @param pSection - the given LDSection
79   /// @param pRegion - the region to write out data
80   /// @return the size of the table in the file.
81   uint64_t emitSectionData(const LDSection& pSection,
82                            MemoryRegion& pRegion) const;
83 
84   /// hasEntryInStrTab - symbol has an entry in a .strtab
85   bool hasEntryInStrTab(const LDSymbol& pSym) const;
86 
87   /// orderSymbolTable - order symbol table before emitting
88   void orderSymbolTable(Module& pModule);
89 
90   /// readSection - read a target dependent section.
91   bool readSection(Input& pInput, SectionData& pSD);
92 
93   MipsGOT& getGOT();
94   const MipsGOT& getGOT() const;
95 
96   MipsPLT& getPLT();
97   const MipsPLT& getPLT() const;
98 
99   MipsGOTPLT& getGOTPLT();
100   const MipsGOTPLT& getGOTPLT() const;
101 
102   OutputRelocSection& getRelPLT();
103   const OutputRelocSection& getRelPLT() const;
104 
105   OutputRelocSection& getRelDyn();
106   const OutputRelocSection& getRelDyn() const;
107 
getGOTSymbol()108   LDSymbol*             getGOTSymbol()           { return m_pGOTSymbol;    }
getGOTSymbol()109   const LDSymbol*       getGOTSymbol() const     { return m_pGOTSymbol;    }
110 
getGpDispSymbol()111   LDSymbol*             getGpDispSymbol()        { return m_pGpDispSymbol; }
getGpDispSymbol()112   const LDSymbol*       getGpDispSymbol() const  { return m_pGpDispSymbol; }
113 
getGlobalGOTSyms()114   SymbolListType&       getGlobalGOTSyms()       { return m_GlobalGOTSyms; }
getGlobalGOTSyms()115   const SymbolListType& getGlobalGOTSyms() const { return m_GlobalGOTSyms; }
116 
117   /// getTargetSectionOrder - compute the layout order of ARM target sections
118   unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
119 
120   /// finalizeSymbol - finalize the symbol value
121   bool finalizeTargetSymbols();
122 
123   /// allocateCommonSymbols - allocate common symbols in the corresponding
124   /// sections.
125   bool allocateCommonSymbols(Module& pModule);
126 
127   /// getGP0 - the gp value used to create the relocatable objects
128   /// in the specified input.
129   uint64_t getGP0(const Input& pInput) const;
130 
131 private:
132   void defineGOTSymbol(IRBuilder& pBuilder);
133   void defineGOTPLTSymbol(IRBuilder& pBuilder);
134 
135   bool relaxRelocation(IRBuilder& pBuilder, Relocation& pRel);
136 
137   /// emitSymbol32 - emit an ELF32 symbol, override parent's function
138   void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
139                     LDSymbol& pSymbol,
140                     char* pStrtab,
141                     size_t pStrtabsize,
142                     size_t pSymtabIdx);
143 
144   /// doCreateProgramHdrs - backend can implement this function to create the
145   /// target-dependent segments
146   void doCreateProgramHdrs(Module& pModule);
147 
148   /// mayRelax - Backends should override this function if they need relaxation
mayRelax()149   bool mayRelax() { return true; }
150 
151   /// doRelax - Backend can orevride this function to add its relaxation
152   /// implementation. Return true if the output (e.g., .text) is "relaxed"
153   /// (i.e. layout is changed), and set pFinished to true if everything is fit,
154   /// otherwise set it to false.
155   bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
156 
157   /// initTargetStubs
158   bool initTargetStubs();
159 
160   /// readRelocation - read ELF32_Rel entry
161   bool readRelocation(const llvm::ELF::Elf32_Rel& pRel,
162                       Relocation::Type& pType,
163                       uint32_t& pSymIdx,
164                       uint32_t& pOffset) const;
165 
166   /// readRelocation - read ELF32_Rela entry
167   bool readRelocation(const llvm::ELF::Elf32_Rela& pRel,
168                       Relocation::Type& pType,
169                       uint32_t& pSymIdx,
170                       uint32_t& pOffset,
171                       int32_t& pAddend) const;
172 
173   /// readRelocation - read ELF64_Rel entry
174   bool readRelocation(const llvm::ELF::Elf64_Rel& pRel,
175                       Relocation::Type& pType,
176                       uint32_t& pSymIdx,
177                       uint64_t& pOffset) const;
178 
179   /// readRel - read ELF64_Rela entry
180   bool readRelocation(const llvm::ELF::Elf64_Rela& pRel,
181                       Relocation::Type& pType,
182                       uint32_t& pSymIdx,
183                       uint64_t& pOffset,
184                       int64_t& pAddend) const;
185 
186   /// emitRelocation - write data to the ELF32_Rel entry
187   void emitRelocation(llvm::ELF::Elf32_Rel& pRel,
188                       Relocation::Type pType,
189                       uint32_t pSymIdx,
190                       uint32_t pOffset) const;
191 
192   /// emitRelocation - write data to the ELF32_Rela entry
193   void emitRelocation(llvm::ELF::Elf32_Rela& pRel,
194                       Relocation::Type pType,
195                       uint32_t pSymIdx,
196                       uint32_t pOffset,
197                       int32_t pAddend) const;
198 
199   /// emitRelocation - write data to the ELF64_Rel entry
200   void emitRelocation(llvm::ELF::Elf64_Rel& pRel,
201                       Relocation::Type pType,
202                       uint32_t pSymIdx,
203                       uint64_t pOffset) const;
204 
205   /// emitRelocation - write data to the ELF64_Rela entry
206   void emitRelocation(llvm::ELF::Elf64_Rela& pRel,
207                       Relocation::Type pType,
208                       uint32_t pSymIdx,
209                       uint64_t pOffset,
210                       int64_t pAddend) const;
211 
212 private:
213   typedef llvm::DenseSet<const ResolveInfo*> ResolveInfoSetType;
214   typedef llvm::DenseMap<const Input*, llvm::ELF::Elf64_Addr> GP0MapType;
215 
216 protected:
217   Relocator* m_pRelocator;
218   MipsGOT* m_pGOT;                      // .got
219   MipsPLT* m_pPLT;                      // .plt
220   MipsGOTPLT* m_pGOTPLT;                // .got.plt
221 
222 private:
223   MipsGNUInfo& m_pInfo;
224 
225   OutputRelocSection* m_pRelPlt;        // .rel.plt
226   OutputRelocSection* m_pRelDyn;        // .rel.dyn
227 
228   MipsELFDynamic* m_pDynamic;
229   LDSymbol* m_pGOTSymbol;
230   LDSymbol* m_pPLTSymbol;
231   LDSymbol* m_pGpDispSymbol;
232 
233   SymbolListType m_GlobalGOTSyms;
234   ResolveInfoSetType m_HasNonPICBranchSyms;
235   GP0MapType m_GP0Map;
236 };
237 
238 /** \class Mips32GNULDBackend
239  *  \brief Base linker backend of Mips 32-bit target of GNU ELF format.
240  */
241 class Mips32GNULDBackend : public MipsGNULDBackend
242 {
243 public:
244   Mips32GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
245 
246 private:
247   // MipsGNULDBackend
248 
249   bool initRelocator();
250   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
251   size_t getRelEntrySize();
252   size_t getRelaEntrySize();
253 };
254 
255 /** \class Mips64GNULDBackend
256  *  \brief Base linker backend of Mips 64-bit target of GNU ELF format.
257  */
258 class Mips64GNULDBackend : public MipsGNULDBackend
259 {
260 public:
261   Mips64GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
262 
263 private:
264   // MipsGNULDBackend
265 
266   bool initRelocator();
267   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
268   size_t getRelEntrySize();
269   size_t getRelaEntrySize();
270 };
271 
272 } // namespace of mcld
273 
274 #endif
275