1 //===- AArch64LDBackend.cpp -----------------------------------------------===//
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 #include "AArch64.h"
10 #include "AArch64ELFDynamic.h"
11 #include "AArch64GNUInfo.h"
12 #include "AArch64LDBackend.h"
13 #include "AArch64Relocator.h"
14 
15 #include <cstring>
16 
17 #include <llvm/ADT/Triple.h>
18 #include <llvm/ADT/Twine.h>
19 #include <llvm/Support/ELF.h>
20 #include <llvm/Support/Casting.h>
21 
22 #include <mcld/IRBuilder.h>
23 #include <mcld/LinkerConfig.h>
24 #include <mcld/Fragment/FillFragment.h>
25 #include <mcld/Fragment/AlignFragment.h>
26 #include <mcld/Fragment/RegionFragment.h>
27 #include <mcld/Fragment/Stub.h>
28 #include <mcld/Fragment/NullFragment.h>
29 #include <mcld/Support/MemoryRegion.h>
30 #include <mcld/Support/MemoryArea.h>
31 #include <mcld/Support/MsgHandling.h>
32 #include <mcld/Support/TargetRegistry.h>
33 #include <mcld/LD/BranchIslandFactory.h>
34 #include <mcld/LD/StubFactory.h>
35 #include <mcld/LD/LDContext.h>
36 #include <mcld/LD/ELFFileFormat.h>
37 #include <mcld/LD/ELFSegmentFactory.h>
38 #include <mcld/LD/ELFSegment.h>
39 #include <mcld/Target/ELFAttribute.h>
40 #include <mcld/Target/GNUInfo.h>
41 #include <mcld/Object/ObjectBuilder.h>
42 
43 using namespace mcld;
44 
45 //===----------------------------------------------------------------------===//
46 // AArch64GNULDBackend
47 //===----------------------------------------------------------------------===//
AArch64GNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)48 AArch64GNULDBackend::AArch64GNULDBackend(const LinkerConfig& pConfig,
49                                          GNUInfo* pInfo)
50   : GNULDBackend(pConfig, pInfo),
51     m_pRelocator(NULL),
52     m_pGOT(NULL),
53     m_pGOTPLT(NULL),
54     m_pPLT(NULL),
55     m_pRelaDyn(NULL),
56     m_pRelaPLT(NULL),
57     // m_pAttrData(NULL),
58     m_pDynamic(NULL),
59     m_pGOTSymbol(NULL)
60     // m_pAttributes(NULL)
61 {
62 }
63 
~AArch64GNULDBackend()64 AArch64GNULDBackend::~AArch64GNULDBackend()
65 {
66   if (m_pRelocator != NULL)
67     delete m_pRelocator;
68   if (m_pGOT == m_pGOTPLT) {
69     if (m_pGOT != NULL)
70       delete m_pGOT;
71   } else {
72     if (m_pGOT != NULL)
73       delete m_pGOT;
74     if (m_pGOTPLT != NULL)
75       delete m_pGOTPLT;
76   }
77   if (m_pPLT != NULL)
78     delete m_pPLT;
79   if (m_pRelaDyn != NULL)
80     delete m_pRelaDyn;
81   if (m_pRelaPLT != NULL)
82     delete m_pRelaPLT;
83   if (m_pDynamic != NULL)
84     delete m_pDynamic;
85 }
86 
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)87 void AArch64GNULDBackend::initTargetSections(Module& pModule,
88                                              ObjectBuilder& pBuilder)
89 {
90   // TODO
91 
92   if (LinkerConfig::Object != config().codeGenType()) {
93     ELFFileFormat* file_format = getOutputFormat();
94 
95     // initialize .got
96     LDSection& got = file_format->getGOT();
97     m_pGOT = new AArch64GOT(got);
98     if (config().options().hasNow()) {
99       // when -z now is given, there will be only one .got section (contains
100       // both GOTPLT and normal GOT entries), create GOT0 for .got section and
101       // set m_pGOTPLT to the same .got
102       m_pGOT->createGOT0();
103       m_pGOTPLT = m_pGOT;
104     }
105     else {
106       // Otherwise, got should be seperated to two sections, .got and .got.plt
107       // initialize .got.plt
108       LDSection& gotplt = file_format->getGOTPLT();
109       m_pGOTPLT = new AArch64GOT(gotplt);
110       m_pGOTPLT->createGOT0();
111     }
112 
113     // initialize .plt
114     LDSection& plt = file_format->getPLT();
115     m_pPLT = new AArch64PLT(plt, *m_pGOTPLT);
116 
117     // initialize .rela.plt
118     LDSection& relaplt = file_format->getRelaPlt();
119     relaplt.setLink(&plt);
120     m_pRelaPLT = new OutputRelocSection(pModule, relaplt);
121 
122     // initialize .rela.dyn
123     LDSection& reladyn = file_format->getRelaDyn();
124     m_pRelaDyn = new OutputRelocSection(pModule, reladyn);
125   }
126 }
127 
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)128 void AArch64GNULDBackend::initTargetSymbols(IRBuilder& pBuilder,
129                                             Module& pModule)
130 {
131   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
132   // same name in input
133   if (LinkerConfig::Object != config().codeGenType()) {
134     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
135                                                   "_GLOBAL_OFFSET_TABLE_",
136                                                   ResolveInfo::Object,
137                                                   ResolveInfo::Define,
138                                                   ResolveInfo::Local,
139                                                   0x0,  // size
140                                                   0x0,  // value
141                                                   FragmentRef::Null(),
142                                                   ResolveInfo::Hidden);
143   }
144   // TODO
145 }
146 
initRelocator()147 bool AArch64GNULDBackend::initRelocator()
148 {
149   if (NULL == m_pRelocator) {
150     m_pRelocator = new AArch64Relocator(*this, config());
151   }
152   return true;
153 }
154 
getRelocator() const155 const Relocator* AArch64GNULDBackend::getRelocator() const
156 {
157   assert(NULL != m_pRelocator);
158   return m_pRelocator;
159 }
160 
getRelocator()161 Relocator* AArch64GNULDBackend::getRelocator()
162 {
163   assert(NULL != m_pRelocator);
164   return m_pRelocator;
165 }
166 
defineGOTSymbol(IRBuilder & pBuilder)167 void AArch64GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
168 {
169   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
170   if (m_pGOTSymbol != NULL) {
171     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
172                      "_GLOBAL_OFFSET_TABLE_",
173                      ResolveInfo::Object,
174                      ResolveInfo::Define,
175                      ResolveInfo::Local,
176                      0x0, // size
177                      0x0, // value
178                      FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
179                      ResolveInfo::Hidden);
180   }
181   else {
182     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
183                      "_GLOBAL_OFFSET_TABLE_",
184                      ResolveInfo::Object,
185                      ResolveInfo::Define,
186                      ResolveInfo::Local,
187                      0x0, // size
188                      0x0, // value
189                      FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
190                      ResolveInfo::Hidden);
191   }
192 }
193 
doPreLayout(IRBuilder & pBuilder)194 void AArch64GNULDBackend::doPreLayout(IRBuilder& pBuilder)
195 {
196   // initialize .dynamic data
197   if (!config().isCodeStatic() && NULL == m_pDynamic)
198     m_pDynamic = new AArch64ELFDynamic(*this, config());
199 
200   if (LinkerConfig::Object != config().codeGenType()) {
201     // set .got size
202     if (config().options().hasNow()) {
203       // when building shared object, the GOTPLT section is must
204       if (LinkerConfig::DynObj == config().codeGenType() ||
205           m_pGOT->hasGOT1() ||
206           NULL != m_pGOTSymbol) {
207         m_pGOT->finalizeSectionSize();
208         defineGOTSymbol(pBuilder);
209       }
210     }
211     else {
212       // when building shared object, the GOTPLT section is must
213       if (LinkerConfig::DynObj == config().codeGenType() ||
214           m_pGOTPLT->hasGOT1() ||
215           NULL != m_pGOTSymbol) {
216         m_pGOTPLT->finalizeSectionSize();
217         defineGOTSymbol(pBuilder);
218       }
219       if (m_pGOT->hasGOT1())
220         m_pGOT->finalizeSectionSize();
221     }
222 
223     // set .plt size
224     if (m_pPLT->hasPLT1())
225       m_pPLT->finalizeSectionSize();
226 
227     ELFFileFormat* file_format = getOutputFormat();
228     // set .rela.dyn size
229     if (!m_pRelaDyn->empty()) {
230       assert(!config().isCodeStatic() &&
231             "static linkage should not result in a dynamic relocation section");
232       file_format->getRelaDyn().setSize(
233                                 m_pRelaDyn->numOfRelocs() * getRelaEntrySize());
234     }
235 
236     // set .rela.plt size
237     if (!m_pRelaPLT->empty()) {
238       assert(!config().isCodeStatic() &&
239             "static linkage should not result in a dynamic relocation section");
240       file_format->getRelaPlt().setSize(
241                                 m_pRelaPLT->numOfRelocs() * getRelaEntrySize());
242     }
243   }
244 }
245 
doPostLayout(Module & pModule,IRBuilder & pBuilder)246 void AArch64GNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
247 {
248   const ELFFileFormat *file_format = getOutputFormat();
249 
250   // apply PLT
251   if (file_format->hasPLT()) {
252     assert(NULL != m_pPLT);
253     m_pPLT->applyPLT0();
254     m_pPLT->applyPLT1();
255   }
256 
257   // apply GOTPLT
258   if ((config().options().hasNow() && file_format->hasGOT()) ||
259        file_format->hasGOTPLT()) {
260     assert(NULL != m_pGOTPLT);
261     if (LinkerConfig::DynObj == config().codeGenType())
262       m_pGOTPLT->applyGOT0(file_format->getDynamic().addr());
263     else {
264       // executable file and object file? should fill with zero.
265       m_pGOTPLT->applyGOT0(0);
266     }
267   }
268 }
269 
dynamic()270 AArch64ELFDynamic& AArch64GNULDBackend::dynamic()
271 {
272   assert(NULL != m_pDynamic);
273   return *m_pDynamic;
274 }
275 
dynamic() const276 const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const
277 {
278   assert(NULL != m_pDynamic);
279   return *m_pDynamic;
280 }
281 
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const282 uint64_t AArch64GNULDBackend::emitSectionData(const LDSection& pSection,
283                                               MemoryRegion& pRegion) const
284 {
285   assert(pRegion.size() && "Size of MemoryRegion is zero!");
286 
287   const ELFFileFormat* file_format = getOutputFormat();
288 
289   if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
290     uint64_t result = m_pPLT->emit(pRegion);
291     return result;
292   }
293 
294   if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
295     uint64_t result = m_pGOT->emit(pRegion);
296     return result;
297   }
298 
299   if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
300     uint64_t result = m_pGOT->emit(pRegion);
301     return result;
302   }
303 
304   // TODO
305   return pRegion.size();
306 }
307 
308 unsigned int
getTargetSectionOrder(const LDSection & pSectHdr) const309 AArch64GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
310 {
311   const ELFFileFormat* file_format = getOutputFormat();
312 
313   if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
314     if (config().options().hasNow())
315       return SHO_RELRO;
316     return SHO_RELRO_LAST;
317   }
318 
319   if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
320     return SHO_NON_RELRO_FIRST;
321 
322   if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
323     return SHO_PLT;
324 
325   return SHO_UNDEFINED;
326 }
327 
doRelax(Module & pModule,IRBuilder & pBuilder,bool & pFinished)328 bool AArch64GNULDBackend::doRelax(Module& pModule,
329                                   IRBuilder& pBuilder,
330                                   bool& pFinished)
331 {
332   // TODO
333   return false;
334 }
335 
initTargetStubs()336 bool AArch64GNULDBackend::initTargetStubs()
337 {
338   // TODO
339   return true;
340 }
341 
doCreateProgramHdrs(Module & pModule)342 void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule)
343 {
344   // TODO
345 }
346 
finalizeTargetSymbols()347 bool AArch64GNULDBackend::finalizeTargetSymbols()
348 {
349   // TODO
350   return true;
351 }
352 
mergeSection(Module & pModule,const Input & pInput,LDSection & pSection)353 bool AArch64GNULDBackend::mergeSection(Module& pModule,
354                                        const Input& pInput,
355                                        LDSection& pSection)
356 {
357   // TODO
358   return true;
359 }
360 
readSection(Input & pInput,SectionData & pSD)361 bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD)
362 {
363   // TODO
364   return true;
365 }
366 
getGOT()367 AArch64GOT& AArch64GNULDBackend::getGOT()
368 {
369   assert(NULL != m_pGOT && "GOT section not exist");
370   return *m_pGOT;
371 }
372 
getGOT() const373 const AArch64GOT& AArch64GNULDBackend::getGOT() const
374 {
375   assert(NULL != m_pGOT && "GOT section not exist");
376   return *m_pGOT;
377 }
378 
getGOTPLT()379 AArch64GOT& AArch64GNULDBackend::getGOTPLT()
380 {
381   assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
382   return *m_pGOTPLT;
383 }
384 
getGOTPLT() const385 const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const
386 {
387   assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
388   return *m_pGOTPLT;
389 }
390 
getPLT()391 AArch64PLT& AArch64GNULDBackend::getPLT()
392 {
393   assert(NULL != m_pPLT && "PLT section not exist");
394   return *m_pPLT;
395 }
396 
getPLT() const397 const AArch64PLT& AArch64GNULDBackend::getPLT() const
398 {
399   assert(NULL != m_pPLT && "PLT section not exist");
400   return *m_pPLT;
401 }
402 
getRelaDyn()403 OutputRelocSection& AArch64GNULDBackend::getRelaDyn()
404 {
405   assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
406   return *m_pRelaDyn;
407 }
408 
getRelaDyn() const409 const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const
410 {
411   assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
412   return *m_pRelaDyn;
413 }
414 
getRelaPLT()415 OutputRelocSection& AArch64GNULDBackend::getRelaPLT()
416 {
417   assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
418   return *m_pRelaPLT;
419 }
420 
getRelaPLT() const421 const OutputRelocSection& AArch64GNULDBackend::getRelaPLT() const
422 {
423   assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
424   return *m_pRelaPLT;
425 }
426 
427 namespace mcld {
428 
429 //===----------------------------------------------------------------------===//
430 //  createAArch64LDBackend - the help funtion to create corresponding
431 //  AArch64LDBackend
432 //===----------------------------------------------------------------------===//
createAArch64LDBackend(const LinkerConfig & pConfig)433 TargetLDBackend* createAArch64LDBackend(const LinkerConfig& pConfig)
434 {
435   if (pConfig.targets().triple().isOSDarwin()) {
436     assert(0 && "MachO linker is not supported yet");
437     /**
438     return new AArch64MachOLDBackend(createAArch64MachOArchiveReader,
439                                      createAArch64MachOObjectReader,
440                                      createAArch64MachOObjectWriter);
441     **/
442   }
443   if (pConfig.targets().triple().isOSWindows()) {
444     assert(0 && "COFF linker is not supported yet");
445     /**
446     return new AArch64COFFLDBackend(createAArch64COFFArchiveReader,
447                                     createAArch64COFFObjectReader,
448                                     createAArch64COFFObjectWriter);
449     **/
450   }
451   return new AArch64GNULDBackend(pConfig,
452      new AArch64GNUInfo(pConfig.targets().triple()));
453 }
454 
455 } // namespace of mcld
456 
457 //===----------------------------------------------------------------------===//
458 // Force static initialization.
459 //===----------------------------------------------------------------------===//
MCLDInitializeAArch64LDBackend()460 extern "C" void MCLDInitializeAArch64LDBackend() {
461   // Register the linker backend
462   mcld::TargetRegistry::RegisterTargetLDBackend(TheAArch64Target,
463                                                 createAArch64LDBackend);
464 }
465 
466