• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 namespace mcld {
20 
21 class LinkerConfig;
22 class GNUInfo;
23 class SectionMap;
24 
25 //===----------------------------------------------------------------------===//
26 /// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
27 ///
28 class ARMGNULDBackend : public GNULDBackend
29 {
30 public:
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 
40 public:
41   ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
42   ~ARMGNULDBackend();
43 
44 public:
45   typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList;
46 
47   /** \enum ReservedEntryType
48    *  \brief The reserved entry type of reserved space in ResolveInfo.
49    *
50    *  This is used for sacnRelocation to record what kinds of entries are
51    *  reserved for this resolved symbol
52    *
53    *  In ARM, there are three kinds of entries, GOT, PLT, and dynamic reloction.
54    *  GOT may needs a corresponding relocation to relocate itself, so we
55    *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
56    *  symbol, there might be two kinds of entries reserved for different location.
57    *  For example, reference to the same symbol, one may use GOT and the other may
58    *  use dynamic relocation.
59    *
60    *  bit:  3       2      1     0
61    *   | PLT | GOTRel | GOT | Rel |
62    *
63    *  value    Name         - Description
64    *
65    *  0000     None         - no reserved entry
66    *  0001     ReserveRel   - reserve an dynamic relocation entry
67    *  0010     ReserveGOT   - reserve an GOT entry
68    *  0011     GOTandRel    - For different relocation, we've reserved GOT and
69    *                          Rel for different location.
70    *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
71    *                          relocation entry which relocate this GOT entry
72    *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
73    *                          and relocation entry for different location.
74    *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
75    *                          Dynamic relocation entries
76    *  1001     PLTandRel    - For different relocation, we've reserved PLT and
77    *                          Rel for different location.
78    */
79   enum ReservedEntryType {
80     None         = 0,
81     ReserveRel   = 1,
82     ReserveGOT   = 2,
83     GOTandRel    = 3,
84     GOTRel       = 4,
85     GOTRelandRel = 5,
86     ReservePLT   = 8,
87     PLTandRel    = 9
88   };
89 
90 public:
91   /// initTargetSections - initialize target dependent sections in output.
92   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
93 
94   /// initTargetSymbols - initialize target dependent symbols in output.
95   void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
96 
97   /// initRelocator - create and initialize Relocator.
98   bool initRelocator();
99 
100   /// getRelocator - return relocator.
101   Relocator* getRelocator();
102 
103   /// scanRelocation - determine the empty entries are needed or not and create
104   /// the empty entries if needed.
105   /// For ARM, following entries are check to create:
106   /// - GOT entry (for .got section)
107   /// - PLT entry (for .plt section)
108   /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
109   void scanRelocation(Relocation& pReloc,
110                       IRBuilder& pBuilder,
111                       Module& pModule,
112                       LDSection& pSection);
113 
114   /// doPreLayout - Backend can do any needed modification before layout
115   void doPreLayout(IRBuilder& pBuilder);
116 
117   /// doPostLayout -Backend can do any needed modification after layout
118   void doPostLayout(Module& pModule, IRBuilder& pBuilder);
119 
120   /// dynamic - the dynamic section of the target machine.
121   /// Use co-variant return type to return its own dynamic section.
122   ARMELFDynamic& dynamic();
123 
124   /// dynamic - the dynamic section of the target machine.
125   /// Use co-variant return type to return its own dynamic section.
126   const ARMELFDynamic& dynamic() const;
127 
128 
129   /// emitSectionData - write out the section data into the memory region.
130   /// When writers get a LDSection whose kind is LDFileFormat::Target, writers
131   /// call back target backend to emit the data.
132   ///
133   /// Backends handle the target-special tables (plt, gp,...) by themselves.
134   /// Backend can put the data of the tables in SectionData directly
135   ///  - LDSection.getSectionData can get the section data.
136   /// Or, backend can put the data into special data structure
137   ///  - backend can maintain its own map<LDSection, table> to get the table
138   /// from given LDSection.
139   ///
140   /// @param pSection - the given LDSection
141   /// @param pConfig - all options in the command line.
142   /// @param pRegion - the region to write out data
143   /// @return the size of the table in the file.
144   uint64_t emitSectionData(const LDSection& pSection,
145                            MemoryRegion& pRegion) const;
146 
147   ARMGOT& getGOT();
148 
149   const ARMGOT& getGOT() const;
150 
151   ARMPLT& getPLT();
152 
153   const ARMPLT& getPLT() const;
154 
155   OutputRelocSection& getRelDyn();
156 
157   const OutputRelocSection& getRelDyn() const;
158 
159   OutputRelocSection& getRelPLT();
160 
161   const OutputRelocSection& getRelPLT() const;
162 
163   /// getTargetSectionOrder - compute the layout order of ARM target sections
164   unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
165 
166   /// finalizeTargetSymbols - finalize the symbol value
167   bool finalizeTargetSymbols();
168 
169   /// mergeSection - merge target dependent sections
170   bool mergeSection(Module& pModule, LDSection& pSection);
171 
172   /// readSection - read target dependent sections
173   bool readSection(Input& pInput, SectionData& pSD);
174 
175 private:
176   void scanLocalReloc(Relocation& pReloc, const LDSection& pSection);
177 
178   void scanGlobalReloc(Relocation& pReloc,
179                        IRBuilder& pBuilder,
180                        const LDSection& pSection);
181 
182   void checkValidReloc(Relocation& pReloc) const;
183 
184   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
185   /// @param pSym - A resolved copy symbol that defined in BSS section
186   void addCopyReloc(ResolveInfo& pSym);
187 
188   /// defineSymbolforCopyReloc - allocate a space in BSS section and
189   /// and force define the copy of pSym to BSS section
190   /// @return the output LDSymbol of the copy symbol
191   LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker,
192                                      const ResolveInfo& pSym);
193 
194   void defineGOTSymbol(IRBuilder& pBuilder);
195 
196   /// maxBranchOffset
197   /// FIXME: if we can handle arm attributes, we may refine this!
maxBranchOffset()198   uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; }
199 
200   /// mayRelax - Backends should override this function if they need relaxation
mayRelax()201   bool mayRelax() { return true; }
202 
203   /// doRelax - Backend can orevride this function to add its relaxation
204   /// implementation. Return true if the output (e.g., .text) is "relaxed"
205   /// (i.e. layout is changed), and set pFinished to true if everything is fit,
206   /// otherwise set it to false.
207   bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
208 
209   /// initTargetStubs
210   bool initTargetStubs();
211 
212   /// getRelEntrySize - the size in BYTE of rel type relocation
getRelEntrySize()213   size_t getRelEntrySize()
214   { return 8; }
215 
216   /// getRelEntrySize - the size in BYTE of rela type relocation
getRelaEntrySize()217   size_t getRelaEntrySize()
218   { assert(0 && "ARM backend with Rela type relocation\n"); return 12; }
219 
220   /// doCreateProgramHdrs - backend can implement this function to create the
221   /// target-dependent segments
222   virtual void doCreateProgramHdrs(Module& pModule);
223 
224 private:
225   Relocator* m_pRelocator;
226 
227   ARMGOT* m_pGOT;
228   ARMPLT* m_pPLT;
229   /// m_RelDyn - dynamic relocation table of .rel.dyn
230   OutputRelocSection* m_pRelDyn;
231   /// m_RelPLT - dynamic relocation table of .rel.plt
232   OutputRelocSection* m_pRelPLT;
233 
234   ARMELFDynamic* m_pDynamic;
235   LDSymbol* m_pGOTSymbol;
236   LDSymbol* m_pEXIDXStart;
237   LDSymbol* m_pEXIDXEnd;
238 
239   //     variable name           :  ELF
240   LDSection* m_pEXIDX;           // .ARM.exidx
241   LDSection* m_pEXTAB;           // .ARM.extab
242   LDSection* m_pAttributes;      // .ARM.attributes
243 //  LDSection* m_pPreemptMap;      // .ARM.preemptmap
244 //  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
245 //  LDSection* m_pOverlayTable;    // .ARM.overlay_table
246 };
247 } // namespace of mcld
248 
249 #endif
250 
251