AArch64LDBackend.cpp revision 0dea6bc96bb52346737966839ac68644f7939f58
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
43using namespace mcld;
44
45//===----------------------------------------------------------------------===//
46// AArch64GNULDBackend
47//===----------------------------------------------------------------------===//
48AArch64GNULDBackend::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
64AArch64GNULDBackend::~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
87void 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
128void 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
147bool AArch64GNULDBackend::initRelocator()
148{
149  if (NULL == m_pRelocator) {
150    m_pRelocator = new AArch64Relocator(*this, config());
151  }
152  return true;
153}
154
155const Relocator* AArch64GNULDBackend::getRelocator() const
156{
157  assert(NULL != m_pRelocator);
158  return m_pRelocator;
159}
160
161Relocator* AArch64GNULDBackend::getRelocator()
162{
163  assert(NULL != m_pRelocator);
164  return m_pRelocator;
165}
166
167void 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
194void 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
246void 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
270AArch64ELFDynamic& AArch64GNULDBackend::dynamic()
271{
272  assert(NULL != m_pDynamic);
273  return *m_pDynamic;
274}
275
276const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const
277{
278  assert(NULL != m_pDynamic);
279  return *m_pDynamic;
280}
281
282uint64_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
308unsigned int
309AArch64GNULDBackend::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
328bool AArch64GNULDBackend::doRelax(Module& pModule,
329                                  IRBuilder& pBuilder,
330                                  bool& pFinished)
331{
332  // TODO
333  return false;
334}
335
336bool AArch64GNULDBackend::initTargetStubs()
337{
338  // TODO
339  return true;
340}
341
342void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule)
343{
344  // TODO
345}
346
347bool AArch64GNULDBackend::finalizeTargetSymbols()
348{
349  // TODO
350  return true;
351}
352
353bool AArch64GNULDBackend::mergeSection(Module& pModule,
354                                       const Input& pInput,
355                                       LDSection& pSection)
356{
357  // TODO
358  return true;
359}
360
361bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD)
362{
363  // TODO
364  return true;
365}
366
367AArch64GOT& AArch64GNULDBackend::getGOT()
368{
369  assert(NULL != m_pGOT && "GOT section not exist");
370  return *m_pGOT;
371}
372
373const AArch64GOT& AArch64GNULDBackend::getGOT() const
374{
375  assert(NULL != m_pGOT && "GOT section not exist");
376  return *m_pGOT;
377}
378
379AArch64GOT& AArch64GNULDBackend::getGOTPLT()
380{
381  assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
382  return *m_pGOTPLT;
383}
384
385const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const
386{
387  assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
388  return *m_pGOTPLT;
389}
390
391AArch64PLT& AArch64GNULDBackend::getPLT()
392{
393  assert(NULL != m_pPLT && "PLT section not exist");
394  return *m_pPLT;
395}
396
397const AArch64PLT& AArch64GNULDBackend::getPLT() const
398{
399  assert(NULL != m_pPLT && "PLT section not exist");
400  return *m_pPLT;
401}
402
403OutputRelocSection& AArch64GNULDBackend::getRelaDyn()
404{
405  assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
406  return *m_pRelaDyn;
407}
408
409const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const
410{
411  assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
412  return *m_pRelaDyn;
413}
414
415OutputRelocSection& AArch64GNULDBackend::getRelaPLT()
416{
417  assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
418  return *m_pRelaPLT;
419}
420
421const OutputRelocSection& AArch64GNULDBackend::getRelaPLT() const
422{
423  assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
424  return *m_pRelaPLT;
425}
426
427namespace mcld {
428
429//===----------------------------------------------------------------------===//
430//  createAArch64LDBackend - the help funtion to create corresponding
431//  AArch64LDBackend
432//===----------------------------------------------------------------------===//
433TargetLDBackend* 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//===----------------------------------------------------------------------===//
460extern "C" void MCLDInitializeAArch64LDBackend() {
461  // Register the linker backend
462  mcld::TargetRegistry::RegisterTargetLDBackend(TheAArch64Target,
463                                                createAArch64LDBackend);
464}
465
466