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