MipsLDBackend.h revision 0dea6bc96bb52346737966839ac68644f7939f58
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
17namespace mcld {
18
19class LinkerConfig;
20class OutputRelocSection;
21class SectionMap;
22class MemoryArea;
23class MipsGNUInfo;
24
25/** \class MipsGNULDBackend
26 *  \brief Base linker backend of Mips target of GNU ELF format.
27 */
28class MipsGNULDBackend : public GNULDBackend
29{
30public:
31  typedef std::vector<LDSymbol*> SymbolListType;
32
33public:
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
42public:
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
108  LDSymbol*             getGOTSymbol()           { return m_pGOTSymbol;    }
109  const LDSymbol*       getGOTSymbol() const     { return m_pGOTSymbol;    }
110
111  LDSymbol*             getGpDispSymbol()        { return m_pGpDispSymbol; }
112  const LDSymbol*       getGpDispSymbol() const  { return m_pGpDispSymbol; }
113
114  SymbolListType&       getGlobalGOTSyms()       { return m_GlobalGOTSyms; }
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
131private:
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
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
212private:
213  typedef llvm::DenseSet<const ResolveInfo*> ResolveInfoSetType;
214  typedef llvm::DenseMap<const Input*, llvm::ELF::Elf64_Addr> GP0MapType;
215
216protected:
217  Relocator* m_pRelocator;
218  MipsGOT* m_pGOT;                      // .got
219  MipsPLT* m_pPLT;                      // .plt
220  MipsGOTPLT* m_pGOTPLT;                // .got.plt
221
222private:
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 */
241class Mips32GNULDBackend : public MipsGNULDBackend
242{
243public:
244  Mips32GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
245
246private:
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 */
258class Mips64GNULDBackend : public MipsGNULDBackend
259{
260public:
261  Mips64GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
262
263private:
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