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 "ARMGOT.h"
14#include "ARMPLT.h"
15#include <mcld/LD/LDSection.h>
16#include <mcld/Target/GNULDBackend.h>
17#include <mcld/Target/OutputRelocSection.h>
18
19namespace mcld {
20
21class ARMELFAttributeData;
22class LinkerConfig;
23class GNUInfo;
24
25//===----------------------------------------------------------------------===//
26/// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
27///
28class ARMGNULDBackend : public GNULDBackend
29{
30public:
31  // max branch offsets for ARM, THUMB, and THUMB2
32  // @ref gold/arm.cc:99
33  static const int32_t ARM_MAX_FWD_BRANCH_OFFSET = ((((1 << 23) - 1) << 2) + 8);
34  static const int32_t ARM_MAX_BWD_BRANCH_OFFSET = ((-((1 << 23) << 2)) + 8);
35  static const int32_t THM_MAX_FWD_BRANCH_OFFSET = ((1 << 22) -2 + 4);
36  static const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4);
37  static const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4);
38  static const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
39
40public:
41  ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
42  ~ARMGNULDBackend();
43
44public:
45  typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList;
46
47public:
48  /// initTargetSections - initialize target dependent sections in output.
49  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
50
51  /// initTargetSymbols - initialize target dependent symbols in output.
52  void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
53
54  /// initRelocator - create and initialize Relocator.
55  bool initRelocator();
56
57  /// getRelocator - return relocator.
58  const Relocator* getRelocator() const;
59  Relocator* getRelocator();
60
61  /// doPreLayout - Backend can do any needed modification before layout
62  void doPreLayout(IRBuilder& pBuilder);
63
64  /// doPostLayout -Backend can do any needed modification after layout
65  void doPostLayout(Module& pModule, IRBuilder& pBuilder);
66
67  /// dynamic - the dynamic section of the target machine.
68  /// Use co-variant return type to return its own dynamic section.
69  ARMELFDynamic& dynamic();
70
71  /// dynamic - the dynamic section of the target machine.
72  /// Use co-variant return type to return its own dynamic section.
73  const ARMELFDynamic& dynamic() const;
74
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  /// mergeSection - merge target dependent sections
119  bool mergeSection(Module& pModule, const Input& pInput, LDSection& pSection);
120
121  /// setUpReachedSectionsForGC - set the reference from section XXX to
122  /// .ARM.exidx.XXX to make sure GC correctly handle section exidx
123  void setUpReachedSectionsForGC(const Module& pModule,
124           GarbageCollection::SectionReachedListMap& pSectReachedListMap) const;
125
126  /// readSection - read target dependent sections
127  bool readSection(Input& pInput, SectionData& pSD);
128
129  /// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
130  /// function pointer access
131  bool mayHaveUnsafeFunctionPointerAccess(const LDSection& pSection) const;
132
133private:
134  void defineGOTSymbol(IRBuilder& pBuilder);
135
136  /// maxFwdBranchOffset
137  int64_t maxFwdBranchOffset();
138  /// maxBwdBranchOffset
139  int64_t maxBwdBranchOffset();
140
141  /// mayRelax - Backends should override this function if they need relaxation
142  bool mayRelax() { return true; }
143
144  /// doRelax - Backend can orevride this function to add its relaxation
145  /// implementation. Return true if the output (e.g., .text) is "relaxed"
146  /// (i.e. layout is changed), and set pFinished to true if everything is fit,
147  /// otherwise set it to false.
148  bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
149
150  /// initTargetStubs
151  bool initTargetStubs();
152
153  /// getRelEntrySize - the size in BYTE of rel type relocation
154  size_t getRelEntrySize()
155  { return 8; }
156
157  /// getRelEntrySize - the size in BYTE of rela type relocation
158  size_t getRelaEntrySize()
159  { assert(0 && "ARM backend with Rela type relocation\n"); return 12; }
160
161  /// doCreateProgramHdrs - backend can implement this function to create the
162  /// target-dependent segments
163  virtual void doCreateProgramHdrs(Module& pModule);
164
165private:
166  Relocator* m_pRelocator;
167
168  ARMGOT* m_pGOT;
169  ARMPLT* m_pPLT;
170  /// m_RelDyn - dynamic relocation table of .rel.dyn
171  OutputRelocSection* m_pRelDyn;
172  /// m_RelPLT - dynamic relocation table of .rel.plt
173  OutputRelocSection* m_pRelPLT;
174
175  /// m_pAttrData - attribute data in public ("aeabi") attribute subsection
176  ARMELFAttributeData* m_pAttrData;
177
178  ARMELFDynamic* m_pDynamic;
179  LDSymbol* m_pGOTSymbol;
180  LDSymbol* m_pEXIDXStart;
181  LDSymbol* m_pEXIDXEnd;
182
183  //     variable name           :  ELF
184  LDSection* m_pEXIDX;           // .ARM.exidx
185  LDSection* m_pEXTAB;           // .ARM.extab
186  LDSection* m_pAttributes;      // .ARM.attributes
187//  LDSection* m_pPreemptMap;      // .ARM.preemptmap
188//  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
189//  LDSection* m_pOverlayTable;    // .ARM.overlay_table
190};
191} // namespace of mcld
192
193#endif
194
195