MipsLDBackend.h revision 37b74a387bb3993387029859c2d9d051c41c724e
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 MemoryArea;
21class MipsGNUInfo;
22class OutputRelocSection;
23class SectionMap;
24
25/** \class MipsGNULDBackend
26 *  \brief Base linker backend of Mips target of GNU ELF format.
27 */
28class 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
107  LDSymbol* getGOTSymbol() { return m_pGOTSymbol; }
108  const LDSymbol* getGOTSymbol() const { return m_pGOTSymbol; }
109
110  LDSymbol* getGpDispSymbol() { return m_pGpDispSymbol; }
111  const LDSymbol* getGpDispSymbol() const { return m_pGpDispSymbol; }
112
113  SymbolListType& getGlobalGOTSyms() { return m_GlobalGOTSyms; }
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
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 */
240class 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 */
256class 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