ARMLDBackend.h revision cfcb22478ca64c308df58f9abe6fa2dedb213c16
1//===- ARMLDBackend.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_ARM_ARMLDBACKEND_H_
10#define TARGET_ARM_ARMLDBACKEND_H_
11
12#include "ARMELFDynamic.h"
13#include "ARMException.h"
14#include "ARMGOT.h"
15#include "ARMPLT.h"
16#include "mcld/LD/LDSection.h"
17#include "mcld/Target/GNULDBackend.h"
18#include "mcld/Target/OutputRelocSection.h"
19
20#include <memory>
21
22namespace mcld {
23
24class ARMELFAttributeData;
25class GNUInfo;
26class LinkerConfig;
27
28//===----------------------------------------------------------------------===//
29/// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
30///
31class ARMGNULDBackend : public GNULDBackend {
32 public:
33  // max branch offsets for ARM, THUMB, and THUMB2
34  static const int32_t ARM_MAX_FWD_BRANCH_OFFSET = ((((1 << 23) - 1) << 2) + 8);
35  static const int32_t ARM_MAX_BWD_BRANCH_OFFSET = ((-((1 << 23) << 2)) + 8);
36  static const int32_t THM_MAX_FWD_BRANCH_OFFSET = ((1 << 22) - 2 + 4);
37  static const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4);
38  static const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4);
39  static const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
40
41 public:
42  ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
43  ~ARMGNULDBackend();
44
45 public:
46  typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList;
47
48 public:
49  /// initTargetSections - initialize target dependent sections in output.
50  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
51
52  /// initTargetSymbols - initialize target dependent symbols in output.
53  void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
54
55  /// initRelocator - create and initialize Relocator.
56  bool initRelocator();
57
58  /// getRelocator - return relocator.
59  const Relocator* getRelocator() const;
60  Relocator* getRelocator();
61
62  /// doPreLayout - Backend can do any needed modification before layout
63  void doPreLayout(IRBuilder& pBuilder);
64
65  /// doPostLayout -Backend can do any needed modification after layout
66  void doPostLayout(Module& pModule, IRBuilder& pBuilder);
67
68  /// dynamic - the dynamic section of the target machine.
69  /// Use co-variant return type to return its own dynamic section.
70  ARMELFDynamic& dynamic();
71
72  /// dynamic - the dynamic section of the target machine.
73  /// Use co-variant return type to return its own dynamic section.
74  const ARMELFDynamic& dynamic() const;
75
76  /// emitSectionData - write out the section data into the memory region.
77  /// When writers get a LDSection whose kind is LDFileFormat::Target, writers
78  /// call back target backend to emit the data.
79  ///
80  /// Backends handle the target-special tables (plt, gp,...) by themselves.
81  /// Backend can put the data of the tables in SectionData directly
82  ///  - LDSection.getSectionData can get the section data.
83  /// Or, backend can put the data into special data structure
84  ///  - backend can maintain its own map<LDSection, table> to get the table
85  /// from given LDSection.
86  ///
87  /// @param pSection - the given LDSection
88  /// @param pConfig - all options in the command line.
89  /// @param pRegion - the region to write out data
90  /// @return the size of the table in the file.
91  uint64_t emitSectionData(const LDSection& pSection,
92                           MemoryRegion& pRegion) const;
93
94  ARMGOT& getGOT();
95  const ARMGOT& getGOT() const;
96
97  ARMPLT& getPLT();
98  const ARMPLT& getPLT() const;
99
100  OutputRelocSection& getRelDyn();
101  const OutputRelocSection& getRelDyn() const;
102
103  OutputRelocSection& getRelPLT();
104  const OutputRelocSection& getRelPLT() const;
105
106  ARMELFAttributeData& getAttributeData();
107  const ARMELFAttributeData& getAttributeData() const;
108
109  LDSymbol* getGOTSymbol() { return m_pGOTSymbol; }
110  const LDSymbol* getGOTSymbol() const { return m_pGOTSymbol; }
111
112  /// getTargetSectionOrder - compute the layout order of ARM target sections
113  unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
114
115  /// finalizeTargetSymbols - finalize the symbol value
116  bool finalizeTargetSymbols();
117
118  /// preMergeSections - hooks to be executed before merging sections
119  virtual void preMergeSections(Module& pModule);
120
121  /// postMergeSections - hooks to be executed after merging sections
122  virtual void postMergeSections(Module& pModule);
123
124  /// mergeSection - merge target dependent sections
125  bool mergeSection(Module& pModule, const Input& pInput, LDSection& pSection);
126
127  /// setUpReachedSectionsForGC - set the reference from section XXX to
128  /// .ARM.exidx.XXX to make sure GC correctly handle section exidx
129  void setUpReachedSectionsForGC(
130      const Module& pModule,
131      GarbageCollection::SectionReachedListMap& pSectReachedListMap) const;
132
133  /// readSection - read target dependent sections
134  bool readSection(Input& pInput, SectionData& pSD);
135
136  /// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
137  /// function pointer access
138  bool mayHaveUnsafeFunctionPointerAccess(const LDSection& pSection) const;
139
140 private:
141  void defineGOTSymbol(IRBuilder& pBuilder);
142
143  /// maxFwdBranchOffset
144  int64_t maxFwdBranchOffset() const;
145  /// maxBwdBranchOffset
146  int64_t maxBwdBranchOffset() const;
147
148  /// mayRelax - Backends should override this function if they need relaxation
149  bool mayRelax() { return true; }
150
151  /// relax - the relaxation pass
152  virtual bool relax(Module& pModule, IRBuilder& pBuilder);
153
154  /// doRelax - Backend can orevride this function to add its relaxation
155  /// implementation. Return true if the output (e.g., .text) is "relaxed"
156  /// (i.e. layout is changed), and set pFinished to true if everything is fit,
157  /// otherwise set it to false.
158  bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
159
160  /// initTargetStubs
161  bool initTargetStubs();
162
163  /// getRelEntrySize - the size in BYTE of rel type relocation
164  size_t getRelEntrySize() { return 8; }
165
166  /// getRelEntrySize - the size in BYTE of rela type relocation
167  size_t getRelaEntrySize() {
168    assert(0 && "ARM backend with Rela type relocation\n");
169    return 12;
170  }
171
172  /// doCreateProgramHdrs - backend can implement this function to create the
173  /// target-dependent segments
174  virtual void doCreateProgramHdrs(Module& pModule);
175
176  /// rewriteExceptionSection - rewrite the output .ARM.exidx section.
177  void rewriteARMExIdxSection(Module& pModule);
178
179 private:
180  Relocator* m_pRelocator;
181
182  ARMGOT* m_pGOT;
183  ARMPLT* m_pPLT;
184  /// m_RelDyn - dynamic relocation table of .rel.dyn
185  OutputRelocSection* m_pRelDyn;
186  /// m_RelPLT - dynamic relocation table of .rel.plt
187  OutputRelocSection* m_pRelPLT;
188
189  /// m_pAttrData - attribute data in public ("aeabi") attribute subsection
190  ARMELFAttributeData* m_pAttrData;
191
192  ARMELFDynamic* m_pDynamic;
193  LDSymbol* m_pGOTSymbol;
194  LDSymbol* m_pEXIDXStart;
195  LDSymbol* m_pEXIDXEnd;
196
197  //     variable name           :  ELF
198  LDSection* m_pEXIDX;       // .ARM.exidx
199  LDSection* m_pEXTAB;       // .ARM.extab
200  LDSection* m_pAttributes;  // .ARM.attributes
201  //  LDSection* m_pPreemptMap;      // .ARM.preemptmap
202  //  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
203  //  LDSection* m_pOverlayTable;    // .ARM.overlay_table
204
205  // m_pExData - exception handling section data structures
206  std::unique_ptr<ARMExData> m_pExData;
207};
208
209}  // namespace mcld
210
211#endif  // TARGET_ARM_ARMLDBACKEND_H_
212