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