AArch64LDBackend.cpp revision 533eae20118036f425f27bf0536ef0ccbb090b65
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
155Relocator* AArch64GNULDBackend::getRelocator()
156{
157  assert(NULL != m_pRelocator);
158  return m_pRelocator;
159}
160
161void AArch64GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
162{
163  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
164  if (m_pGOTSymbol != NULL) {
165    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
166                     "_GLOBAL_OFFSET_TABLE_",
167                     ResolveInfo::Object,
168                     ResolveInfo::Define,
169                     ResolveInfo::Local,
170                     0x0, // size
171                     0x0, // value
172                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
173                     ResolveInfo::Hidden);
174  }
175  else {
176    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
177                     "_GLOBAL_OFFSET_TABLE_",
178                     ResolveInfo::Object,
179                     ResolveInfo::Define,
180                     ResolveInfo::Local,
181                     0x0, // size
182                     0x0, // value
183                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
184                     ResolveInfo::Hidden);
185  }
186}
187
188void AArch64GNULDBackend::doPreLayout(IRBuilder& pBuilder)
189{
190  // initialize .dynamic data
191  if (!config().isCodeStatic() && NULL == m_pDynamic)
192    m_pDynamic = new AArch64ELFDynamic(*this, config());
193
194  if (LinkerConfig::Object != config().codeGenType()) {
195    // set .got size
196    if (config().options().hasNow()) {
197      // when building shared object, the GOTPLT section is must
198      if (LinkerConfig::DynObj == config().codeGenType() ||
199          m_pGOT->hasGOT1() ||
200          NULL != m_pGOTSymbol) {
201        m_pGOT->finalizeSectionSize();
202        defineGOTSymbol(pBuilder);
203      }
204    }
205    else {
206      // when building shared object, the GOTPLT section is must
207      if (LinkerConfig::DynObj == config().codeGenType() ||
208          m_pGOTPLT->hasGOT1() ||
209          NULL != m_pGOTSymbol) {
210        m_pGOTPLT->finalizeSectionSize();
211        defineGOTSymbol(pBuilder);
212      }
213      if (m_pGOT->hasGOT1())
214        m_pGOT->finalizeSectionSize();
215    }
216
217    // set .plt size
218    if (m_pPLT->hasPLT1())
219      m_pPLT->finalizeSectionSize();
220
221    ELFFileFormat* file_format = getOutputFormat();
222    // set .rela.dyn size
223    if (!m_pRelaDyn->empty()) {
224      assert(!config().isCodeStatic() &&
225            "static linkage should not result in a dynamic relocation section");
226      file_format->getRelaDyn().setSize(
227                                m_pRelaDyn->numOfRelocs() * getRelaEntrySize());
228    }
229
230    // set .rela.plt size
231    if (!m_pRelaPLT->empty()) {
232      assert(!config().isCodeStatic() &&
233            "static linkage should not result in a dynamic relocation section");
234      file_format->getRelaPlt().setSize(
235                                m_pRelaPLT->numOfRelocs() * getRelaEntrySize());
236    }
237  }
238}
239
240void AArch64GNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
241{
242  const ELFFileFormat *file_format = getOutputFormat();
243
244  // apply PLT
245  if (file_format->hasPLT()) {
246    assert(NULL != m_pPLT);
247    m_pPLT->applyPLT0();
248    m_pPLT->applyPLT1();
249  }
250
251  // apply GOTPLT
252  if ((config().options().hasNow() && file_format->hasGOT()) ||
253       file_format->hasGOTPLT()) {
254    assert(NULL != m_pGOTPLT);
255    if (LinkerConfig::DynObj == config().codeGenType())
256      m_pGOTPLT->applyGOT0(file_format->getDynamic().addr());
257    else {
258      // executable file and object file? should fill with zero.
259      m_pGOTPLT->applyGOT0(0);
260    }
261  }
262}
263
264AArch64ELFDynamic& AArch64GNULDBackend::dynamic()
265{
266  assert(NULL != m_pDynamic);
267  return *m_pDynamic;
268}
269
270const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const
271{
272  assert(NULL != m_pDynamic);
273  return *m_pDynamic;
274}
275
276uint64_t AArch64GNULDBackend::emitSectionData(const LDSection& pSection,
277                                              MemoryRegion& pRegion) const
278{
279  assert(pRegion.size() && "Size of MemoryRegion is zero!");
280
281  const ELFFileFormat* file_format = getOutputFormat();
282
283  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
284    uint64_t result = m_pPLT->emit(pRegion);
285    return result;
286  }
287
288  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
289    uint64_t result = m_pGOT->emit(pRegion);
290    return result;
291  }
292
293  if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
294    uint64_t result = m_pGOT->emit(pRegion);
295    return result;
296  }
297
298  // TODO
299  return pRegion.size();
300}
301
302unsigned int
303AArch64GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
304{
305  const ELFFileFormat* file_format = getOutputFormat();
306
307  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
308    if (config().options().hasNow())
309      return SHO_RELRO;
310    return SHO_RELRO_LAST;
311  }
312
313  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
314    return SHO_NON_RELRO_FIRST;
315
316  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
317    return SHO_PLT;
318
319  return SHO_UNDEFINED;
320}
321
322bool AArch64GNULDBackend::doRelax(Module& pModule,
323                                  IRBuilder& pBuilder,
324                                  bool& pFinished)
325{
326  // TODO
327  return false;
328}
329
330bool AArch64GNULDBackend::initTargetStubs()
331{
332  // TODO
333  return true;
334}
335
336void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule)
337{
338  // TODO
339}
340
341bool AArch64GNULDBackend::finalizeTargetSymbols()
342{
343  // TODO
344  return true;
345}
346
347bool AArch64GNULDBackend::mergeSection(Module& pModule,
348                                       const Input& pInput,
349                                       LDSection& pSection)
350{
351  // TODO
352  return true;
353}
354
355bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD)
356{
357  // TODO
358  return true;
359}
360
361AArch64GOT& AArch64GNULDBackend::getGOT()
362{
363  assert(NULL != m_pGOT && "GOT section not exist");
364  return *m_pGOT;
365}
366
367const AArch64GOT& AArch64GNULDBackend::getGOT() const
368{
369  assert(NULL != m_pGOT && "GOT section not exist");
370  return *m_pGOT;
371}
372
373AArch64GOT& AArch64GNULDBackend::getGOTPLT()
374{
375  assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
376  return *m_pGOTPLT;
377}
378
379const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const
380{
381  assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
382  return *m_pGOTPLT;
383}
384
385AArch64PLT& AArch64GNULDBackend::getPLT()
386{
387  assert(NULL != m_pPLT && "PLT section not exist");
388  return *m_pPLT;
389}
390
391const AArch64PLT& AArch64GNULDBackend::getPLT() const
392{
393  assert(NULL != m_pPLT && "PLT section not exist");
394  return *m_pPLT;
395}
396
397OutputRelocSection& AArch64GNULDBackend::getRelaDyn()
398{
399  assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
400  return *m_pRelaDyn;
401}
402
403const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const
404{
405  assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
406  return *m_pRelaDyn;
407}
408
409OutputRelocSection& AArch64GNULDBackend::getRelaPLT()
410{
411  assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
412  return *m_pRelaPLT;
413}
414
415const OutputRelocSection& AArch64GNULDBackend::getRelaPLT() const
416{
417  assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
418  return *m_pRelaPLT;
419}
420
421namespace mcld {
422
423//===----------------------------------------------------------------------===//
424//  createAArch64LDBackend - the help funtion to create corresponding
425//  AArch64LDBackend
426//===----------------------------------------------------------------------===//
427TargetLDBackend* createAArch64LDBackend(const LinkerConfig& pConfig)
428{
429  if (pConfig.targets().triple().isOSDarwin()) {
430    assert(0 && "MachO linker is not supported yet");
431    /**
432    return new AArch64MachOLDBackend(createAArch64MachOArchiveReader,
433                                     createAArch64MachOObjectReader,
434                                     createAArch64MachOObjectWriter);
435    **/
436  }
437  if (pConfig.targets().triple().isOSWindows()) {
438    assert(0 && "COFF linker is not supported yet");
439    /**
440    return new AArch64COFFLDBackend(createAArch64COFFArchiveReader,
441                                    createAArch64COFFObjectReader,
442                                    createAArch64COFFObjectWriter);
443    **/
444  }
445  return new AArch64GNULDBackend(pConfig,
446     new AArch64GNUInfo(pConfig.targets().triple()));
447}
448
449} // namespace of mcld
450
451//===----------------------------------------------------------------------===//
452// Force static initialization.
453//===----------------------------------------------------------------------===//
454extern "C" void MCLDInitializeAArch64LDBackend() {
455  // Register the linker backend
456  mcld::TargetRegistry::RegisterTargetLDBackend(TheAArch64Target,
457                                                createAArch64LDBackend);
458}
459
460