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