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