ARMLDBackend.h revision 87f34658dec9097d987d254a990ea7f311bfc95f
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 MCLD_ARM_LDBACKEND_H
10#define MCLD_ARM_LDBACKEND_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  Relocator* getRelocator();
59
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
129private:
130  void defineGOTSymbol(IRBuilder& pBuilder);
131
132  /// maxBranchOffset
133  /// FIXME: if we can handle arm attributes, we may refine this!
134  uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; }
135
136  /// mayRelax - Backends should override this function if they need relaxation
137  bool mayRelax() { return true; }
138
139  /// doRelax - Backend can orevride this function to add its relaxation
140  /// implementation. Return true if the output (e.g., .text) is "relaxed"
141  /// (i.e. layout is changed), and set pFinished to true if everything is fit,
142  /// otherwise set it to false.
143  bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
144
145  /// initTargetStubs
146  bool initTargetStubs();
147
148  /// getRelEntrySize - the size in BYTE of rel type relocation
149  size_t getRelEntrySize()
150  { return 8; }
151
152  /// getRelEntrySize - the size in BYTE of rela type relocation
153  size_t getRelaEntrySize()
154  { assert(0 && "ARM backend with Rela type relocation\n"); return 12; }
155
156  /// doCreateProgramHdrs - backend can implement this function to create the
157  /// target-dependent segments
158  virtual void doCreateProgramHdrs(Module& pModule);
159
160private:
161  Relocator* m_pRelocator;
162
163  ARMGOT* m_pGOT;
164  ARMPLT* m_pPLT;
165  /// m_RelDyn - dynamic relocation table of .rel.dyn
166  OutputRelocSection* m_pRelDyn;
167  /// m_RelPLT - dynamic relocation table of .rel.plt
168  OutputRelocSection* m_pRelPLT;
169
170  /// m_pAttrData - attribute data in public ("aeabi") attribute subsection
171  ARMELFAttributeData* m_pAttrData;
172
173  ARMELFDynamic* m_pDynamic;
174  LDSymbol* m_pGOTSymbol;
175  LDSymbol* m_pEXIDXStart;
176  LDSymbol* m_pEXIDXEnd;
177
178  //     variable name           :  ELF
179  LDSection* m_pEXIDX;           // .ARM.exidx
180  LDSection* m_pEXTAB;           // .ARM.extab
181  LDSection* m_pAttributes;      // .ARM.attributes
182//  LDSection* m_pPreemptMap;      // .ARM.preemptmap
183//  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
184//  LDSection* m_pOverlayTable;    // .ARM.overlay_table
185};
186} // namespace of mcld
187
188#endif
189
190