MipsLDBackend.h revision f33f6de54db174aa679a4b6d1e040d37e95541c0
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 MIPS_LDBACKEND_H
10#define MIPS_LDBACKEND_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  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
130private:
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
211private:
212  typedef llvm::DenseSet<const ResolveInfo*> ResolveInfoSetType;
213  typedef llvm::DenseMap<const Input*, llvm::ELF::Elf64_Addr> GP0MapType;
214
215protected:
216  Relocator* m_pRelocator;
217  MipsGOT* m_pGOT;                      // .got
218  MipsPLT* m_pPLT;                      // .plt
219  MipsGOTPLT* m_pGOTPLT;                // .got.plt
220
221private:
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{
242public:
243  Mips32GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
244
245private:
246  // MipsGNULDBackend
247
248  bool initRelocator();
249  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
250  size_t getRelEntrySize();
251  size_t getRelaEntrySize();
252};
253
254/** \class Mips64GNULDBackend
255 *  \brief Base linker backend of Mips 64-bit target of GNU ELF format.
256 */
257class Mips64GNULDBackend : public MipsGNULDBackend
258{
259public:
260  Mips64GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
261
262private:
263  // MipsGNULDBackend
264
265  bool initRelocator();
266  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
267  size_t getRelEntrySize();
268  size_t getRelaEntrySize();
269};
270
271} // namespace of mcld
272
273#endif
274