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