ARMLDBackend.h revision f7ac0f19a1c8d0ad14bcf6456ce368b830fea886
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 LinkerConfig;
22class GNUInfo;
23class SectionMap;
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  LDSymbol* getGOTSymbol()             { return m_pGOTSymbol; }
107  const LDSymbol* getGOTSymbol() const { return m_pGOTSymbol; }
108
109  /// getTargetSectionOrder - compute the layout order of ARM target sections
110  unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
111
112  /// finalizeTargetSymbols - finalize the symbol value
113  bool finalizeTargetSymbols();
114
115  /// mergeSection - merge target dependent sections
116  bool mergeSection(Module& pModule, LDSection& pSection);
117
118  /// readSection - read target dependent sections
119  bool readSection(Input& pInput, SectionData& pSD);
120
121private:
122  void defineGOTSymbol(IRBuilder& pBuilder);
123
124  /// maxBranchOffset
125  /// FIXME: if we can handle arm attributes, we may refine this!
126  uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; }
127
128  /// mayRelax - Backends should override this function if they need relaxation
129  bool mayRelax() { return true; }
130
131  /// doRelax - Backend can orevride this function to add its relaxation
132  /// implementation. Return true if the output (e.g., .text) is "relaxed"
133  /// (i.e. layout is changed), and set pFinished to true if everything is fit,
134  /// otherwise set it to false.
135  bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
136
137  /// initTargetStubs
138  bool initTargetStubs();
139
140  /// getRelEntrySize - the size in BYTE of rel type relocation
141  size_t getRelEntrySize()
142  { return 8; }
143
144  /// getRelEntrySize - the size in BYTE of rela type relocation
145  size_t getRelaEntrySize()
146  { assert(0 && "ARM backend with Rela type relocation\n"); return 12; }
147
148  /// doCreateProgramHdrs - backend can implement this function to create the
149  /// target-dependent segments
150  virtual void doCreateProgramHdrs(Module& pModule);
151
152private:
153  Relocator* m_pRelocator;
154
155  ARMGOT* m_pGOT;
156  ARMPLT* m_pPLT;
157  /// m_RelDyn - dynamic relocation table of .rel.dyn
158  OutputRelocSection* m_pRelDyn;
159  /// m_RelPLT - dynamic relocation table of .rel.plt
160  OutputRelocSection* m_pRelPLT;
161
162  ARMELFDynamic* m_pDynamic;
163  LDSymbol* m_pGOTSymbol;
164  LDSymbol* m_pEXIDXStart;
165  LDSymbol* m_pEXIDXEnd;
166
167  //     variable name           :  ELF
168  LDSection* m_pEXIDX;           // .ARM.exidx
169  LDSection* m_pEXTAB;           // .ARM.extab
170  LDSection* m_pAttributes;      // .ARM.attributes
171//  LDSection* m_pPreemptMap;      // .ARM.preemptmap
172//  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
173//  LDSection* m_pOverlayTable;    // .ARM.overlay_table
174};
175} // namespace of mcld
176
177#endif
178
179