1 //===- ARMLDBackend.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 <llvm/ADT/Triple.h>
10 #include <llvm/ADT/Twine.h>
11 #include <llvm/Support/ELF.h>
12 #include <llvm/Support/ErrorHandling.h>
13
14 #include <mcld/LD/SectionMap.h>
15 #include <mcld/MC/MCLDInfo.h>
16 #include <mcld/MC/MCLDOutput.h>
17 #include <mcld/MC/MCLinker.h>
18 #include <mcld/MC/MCRegionFragment.h>
19 #include <mcld/Support/MemoryRegion.h>
20 #include <mcld/Support/TargetRegistry.h>
21
22 #include <cstring>
23
24 #include "ARM.h"
25 #include "ARMELFDynamic.h"
26 #include "ARMLDBackend.h"
27 #include "ARMRelocationFactory.h"
28
29 using namespace mcld;
30
ARMGNULDBackend()31 ARMGNULDBackend::ARMGNULDBackend()
32 : m_pRelocFactory(NULL),
33 m_pGOT(NULL),
34 m_pPLT(NULL),
35 m_pRelDyn(NULL),
36 m_pRelPLT(NULL),
37 m_pDynamic(NULL),
38 m_pEXIDX(NULL),
39 m_pEXTAB(NULL),
40 m_pAttributes(NULL) {
41 }
42
~ARMGNULDBackend()43 ARMGNULDBackend::~ARMGNULDBackend()
44 {
45 if (m_pRelocFactory)
46 delete m_pRelocFactory;
47 if(m_pGOT)
48 delete m_pGOT;
49 if(m_pPLT)
50 delete m_pPLT;
51 if(m_pRelDyn)
52 delete m_pRelDyn;
53 if(m_pRelPLT)
54 delete m_pRelPLT;
55 if(m_pDynamic)
56 delete m_pDynamic;
57 }
58
initRelocFactory(const MCLinker & pLinker)59 bool ARMGNULDBackend::initRelocFactory(const MCLinker& pLinker)
60 {
61 if (NULL == m_pRelocFactory) {
62 m_pRelocFactory = new ARMRelocationFactory(1024, *this);
63 m_pRelocFactory->setLayout(pLinker.getLayout());
64 }
65 return true;
66 }
67
getRelocFactory()68 RelocationFactory* ARMGNULDBackend::getRelocFactory()
69 {
70 assert(NULL != m_pRelocFactory);
71 return m_pRelocFactory;
72 }
73
initTargetSectionMap(SectionMap & pSectionMap)74 bool ARMGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
75 {
76 if (!pSectionMap.push_back(".ARM.exidx", ".ARM.exidx") ||
77 !pSectionMap.push_back(".ARM.extab", ".ARM.extab") ||
78 !pSectionMap.push_back(".ARM.attributes", ".ARM.attributes"))
79 return false;
80 return true;
81 }
82
initTargetSections(MCLinker & pLinker)83 void ARMGNULDBackend::initTargetSections(MCLinker& pLinker)
84 {
85 // FIXME: Currently we set exidx and extab to "Exception" and directly emit
86 // them from input
87 m_pEXIDX = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
88 LDFileFormat::Exception,
89 llvm::ELF::SHT_ARM_EXIDX,
90 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
91 bitclass() / 8);
92 m_pEXTAB = &pLinker.getOrCreateOutputSectHdr(".ARM.extab",
93 LDFileFormat::Exception,
94 llvm::ELF::SHT_PROGBITS,
95 llvm::ELF::SHF_ALLOC,
96 0x1);
97 m_pAttributes = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes",
98 LDFileFormat::Target,
99 llvm::ELF::SHT_ARM_ATTRIBUTES,
100 0x0,
101 0x1);
102 }
103
initTargetSymbols(MCLinker & pLinker)104 void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker)
105 {
106 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
107 // same name in input
108 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
109 "_GLOBAL_OFFSET_TABLE_",
110 false,
111 ResolveInfo::Object,
112 ResolveInfo::Define,
113 ResolveInfo::Local,
114 0x0, // size
115 0x0, // value
116 NULL, // FragRef
117 ResolveInfo::Hidden);
118 }
119
doPreLayout(const Output & pOutput,const MCLDInfo & pInfo,MCLinker & pLinker)120 void ARMGNULDBackend::doPreLayout(const Output& pOutput,
121 const MCLDInfo& pInfo,
122 MCLinker& pLinker)
123 {
124 // when building shared object, the .got section is must.
125 if(pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
126 createARMGOT(pLinker, pOutput);
127 }
128 }
129
doPostLayout(const Output & pOutput,const MCLDInfo & pInfo,MCLinker & pLinker)130 void ARMGNULDBackend::doPostLayout(const Output& pOutput,
131 const MCLDInfo& pInfo,
132 MCLinker& pLinker)
133 {
134 // emit program headers
135 if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
136 emitProgramHdrs(pLinker.getLDInfo().output());
137
138 ELFFileFormat *file_format = getOutputFormat(pOutput);
139
140 // apply PLT
141 if (file_format->hasPLT()) {
142 // Since we already have the size of LDSection PLT, m_pPLT should not be
143 // NULL.
144 assert(NULL != m_pPLT);
145 m_pPLT->applyPLT0();
146 m_pPLT->applyPLT1();
147 }
148
149 // apply GOT
150 if (file_format->hasGOT()) {
151 // Since we already have the size of GOT, m_pGOT should not be NULL.
152 assert(NULL != m_pGOT);
153 if (pOutput.type() == Output::DynObj)
154 m_pGOT->applyGOT0(file_format->getDynamic().addr());
155 else {
156 // executable file and object file? should fill with zero.
157 m_pGOT->applyGOT0(0);
158 }
159 }
160 }
161
162 /// dynamic - the dynamic section of the target machine.
163 /// Use co-variant return type to return its own dynamic section.
dynamic()164 ARMELFDynamic& ARMGNULDBackend::dynamic()
165 {
166 if (NULL == m_pDynamic)
167 m_pDynamic = new ARMELFDynamic(*this);
168
169 return *m_pDynamic;
170 }
171
172 /// dynamic - the dynamic section of the target machine.
173 /// Use co-variant return type to return its own dynamic section.
dynamic() const174 const ARMELFDynamic& ARMGNULDBackend::dynamic() const
175 {
176 assert( NULL != m_pDynamic);
177 return *m_pDynamic;
178 }
179
isPIC(const MCLDInfo & pLDInfo,const Output & pOutput) const180 bool ARMGNULDBackend::isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const
181 {
182 return (pOutput.type() == Output::DynObj);
183 }
184
createARMGOT(MCLinker & pLinker,const Output & pOutput)185 void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
186 {
187 // get .got LDSection and create MCSectionData
188 ELFFileFormat* file_format = getOutputFormat(pOutput);
189
190 LDSection& got = file_format->getGOT();
191 m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got));
192
193 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
194 if( m_pGOTSymbol != NULL ) {
195 pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
196 "_GLOBAL_OFFSET_TABLE_",
197 false,
198 ResolveInfo::Object,
199 ResolveInfo::Define,
200 ResolveInfo::Local,
201 0x0, // size
202 0x0, // value
203 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
204 ResolveInfo::Hidden);
205 }
206 else {
207 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
208 "_GLOBAL_OFFSET_TABLE_",
209 false,
210 ResolveInfo::Object,
211 ResolveInfo::Define,
212 ResolveInfo::Local,
213 0x0, // size
214 0x0, // value
215 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
216 ResolveInfo::Hidden);
217 }
218
219 }
220
createARMPLTandRelPLT(MCLinker & pLinker,const Output & pOutput)221 void ARMGNULDBackend::createARMPLTandRelPLT(MCLinker& pLinker,
222 const Output& pOutput)
223 {
224 ELFFileFormat* file_format = getOutputFormat(pOutput);
225
226 // get .plt and .rel.plt LDSection
227 LDSection& plt = file_format->getPLT();
228 LDSection& relplt = file_format->getRelPlt();
229 // create MCSectionData and ARMPLT
230 m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT);
231 // set info of .rel.plt to .plt
232 relplt.setLink(&plt);
233 // create MCSectionData and ARMRelDynSection
234 m_pRelPLT = new OutputRelocSection(relplt,
235 pLinker.getOrCreateSectData(relplt),
236 8);
237 }
238
createARMRelDyn(MCLinker & pLinker,const Output & pOutput)239 void ARMGNULDBackend::createARMRelDyn(MCLinker& pLinker,
240 const Output& pOutput)
241 {
242 ELFFileFormat* file_format = getOutputFormat(pOutput);
243
244 // get .rel.dyn LDSection and create MCSectionData
245 LDSection& reldyn = file_format->getRelDyn();
246 // create MCSectionData and ARMRelDynSection
247 m_pRelDyn = new OutputRelocSection(reldyn,
248 pLinker.getOrCreateSectData(reldyn),
249 8);
250 }
251
getOutputFormat(const Output & pOutput) const252 ELFFileFormat* ARMGNULDBackend::getOutputFormat(const Output& pOutput) const
253 {
254 switch (pOutput.type()) {
255 case Output::DynObj:
256 return getDynObjFileFormat();
257 case Output::Exec:
258 return getExecFileFormat();
259 // FIXME: We do not support building .o now
260 case Output::Object:
261 default:
262 llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
263 llvm::Twine(pOutput.type()));
264 return NULL;
265 }
266 }
267
isSymbolNeedsPLT(const ResolveInfo & pSym,const MCLDInfo & pLDInfo,const Output & pOutput) const268 bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
269 const MCLDInfo& pLDInfo,
270 const Output& pOutput) const
271 {
272 return (Output::DynObj == pOutput.type() &&
273 ResolveInfo::Function == pSym.type() &&
274 (pSym.isDyn() || pSym.isUndef() ||
275 isSymbolPreemptible(pSym, pLDInfo, pOutput)));
276 }
277
isSymbolNeedsDynRel(const ResolveInfo & pSym,const Output & pOutput,bool isAbsReloc) const278 bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
279 const Output& pOutput,
280 bool isAbsReloc) const
281 {
282 if(pSym.isUndef() && (Output::Exec == pOutput.type()))
283 return false;
284 if(pSym.isAbsolute())
285 return false;
286 if(Output::DynObj == pOutput.type() && isAbsReloc)
287 return true;
288 if(pSym.isDyn() || pSym.isUndef())
289 return true;
290
291 return false;
292 }
293
isSymbolPreemptible(const ResolveInfo & pSym,const MCLDInfo & pLDInfo,const Output & pOutput) const294 bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
295 const MCLDInfo& pLDInfo,
296 const Output& pOutput) const
297 {
298 if(pSym.other() != ResolveInfo::Default)
299 return false;
300
301 if(Output::DynObj != pOutput.type())
302 return false;
303
304 if(pLDInfo.options().Bsymbolic())
305 return false;
306
307 return true;
308 }
309
310 /// checkValidReloc - When we attempt to generate a dynamic relocation for
311 /// ouput file, check if the relocation is supported by dynamic linker.
checkValidReloc(Relocation & pReloc,const MCLDInfo & pLDInfo,const Output & pOutput) const312 void ARMGNULDBackend::checkValidReloc(Relocation& pReloc,
313 const MCLDInfo& pLDInfo,
314 const Output& pOutput) const
315 {
316 // If not building a PIC object, no relocation type is invalid
317 if (!isPIC(pLDInfo, pOutput))
318 return;
319
320 switch(pReloc.type()) {
321 case llvm::ELF::R_ARM_RELATIVE:
322 case llvm::ELF::R_ARM_COPY:
323 case llvm::ELF::R_ARM_GLOB_DAT:
324 case llvm::ELF::R_ARM_JUMP_SLOT:
325 case llvm::ELF::R_ARM_ABS32:
326 case llvm::ELF::R_ARM_ABS32_NOI:
327 case llvm::ELF::R_ARM_PC24:
328 case llvm::ELF::R_ARM_TLS_DTPMOD32:
329 case llvm::ELF::R_ARM_TLS_DTPOFF32:
330 case llvm::ELF::R_ARM_TLS_TPOFF32:
331 break;
332
333 default:
334 llvm::report_fatal_error(llvm::Twine("Attempt to generate unsupported") +
335 llvm::Twine(" relocation type ") +
336 llvm::Twine((int)pReloc.type()) +
337 llvm::Twine(" for symbol '") +
338 llvm::Twine(pReloc.symInfo()->name()) +
339 llvm::Twine("', recompile with -fPIC")
340 );
341 break;
342 }
343 }
344
updateAddend(Relocation & pReloc,const LDSymbol & pInputSym,const Layout & pLayout) const345 void ARMGNULDBackend::updateAddend(Relocation& pReloc,
346 const LDSymbol& pInputSym,
347 const Layout& pLayout) const
348 {
349 // Update value keep in addend if we meet a section symbol
350 if(pReloc.symInfo()->type() == ResolveInfo::Section) {
351 pReloc.setAddend(pLayout.getOutputOffset(
352 *pInputSym.fragRef()) + pReloc.addend());
353 }
354 }
355
scanLocalReloc(Relocation & pReloc,const LDSymbol & pInputSym,MCLinker & pLinker,const MCLDInfo & pLDInfo,const Output & pOutput)356 void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc,
357 const LDSymbol& pInputSym,
358 MCLinker& pLinker,
359 const MCLDInfo& pLDInfo,
360 const Output& pOutput)
361 {
362 // rsym - The relocation target symbol
363 ResolveInfo* rsym = pReloc.symInfo();
364
365 updateAddend(pReloc, pInputSym, pLinker.getLayout());
366
367 switch(pReloc.type()){
368
369 // Set R_ARM_TARGET1 to R_ARM_ABS32
370 // Ref: GNU gold 1.11 arm.cc, line 9892
371 case llvm::ELF::R_ARM_TARGET1:
372 pReloc.setType(llvm::ELF::R_ARM_ABS32);
373 case llvm::ELF::R_ARM_ABS32:
374 case llvm::ELF::R_ARM_ABS32_NOI: {
375 // If buiding PIC object (shared library or PIC executable),
376 // a dynamic relocations with RELATIVE type to this location is needed.
377 // Reserve an entry in .rel.dyn
378 if(isPIC(pLDInfo, pOutput)) {
379 // create .rel.dyn section if not exist
380 if(NULL == m_pRelDyn)
381 createARMRelDyn(pLinker, pOutput);
382 m_pRelDyn->reserveEntry(*m_pRelocFactory);
383 // set Rel bit
384 rsym->setReserved(rsym->reserved() | 0x1u);
385 }
386 return;
387 }
388
389 case llvm::ELF::R_ARM_ABS16:
390 case llvm::ELF::R_ARM_ABS12:
391 case llvm::ELF::R_ARM_THM_ABS5:
392 case llvm::ELF::R_ARM_ABS8:
393 case llvm::ELF::R_ARM_BASE_ABS:
394 case llvm::ELF::R_ARM_MOVW_ABS_NC:
395 case llvm::ELF::R_ARM_MOVT_ABS:
396 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
397 case llvm::ELF::R_ARM_THM_MOVT_ABS: {
398 // Update value keep in relocation place if we meet a section symbol
399 if(rsym->type() == ResolveInfo::Section) {
400 pReloc.target() = pLinker.getLayout().getOutputOffset(
401 *pInputSym.fragRef()) + pReloc.target();
402 }
403
404 // If building PIC object (shared library or PIC executable),
405 // a dynamic relocation for this location is needed.
406 // Reserve an entry in .rel.dyn
407 if(isPIC(pLDInfo, pOutput)) {
408 checkValidReloc(pReloc, pLDInfo, pOutput);
409 // create .rel.dyn section if not exist
410 if(NULL == m_pRelDyn)
411 createARMRelDyn(pLinker, pOutput);
412 m_pRelDyn->reserveEntry(*m_pRelocFactory);
413 // set Rel bit
414 rsym->setReserved(rsym->reserved() | 0x1u);
415 }
416 return;
417 }
418 case llvm::ELF::R_ARM_GOTOFF32:
419 case llvm::ELF::R_ARM_GOTOFF12: {
420 // A GOT section is needed
421 if(NULL == m_pGOT)
422 createARMGOT(pLinker, pOutput);
423 return;
424 }
425
426 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
427 // Ref: GNU gold 1.11 arm.cc, line 9892
428 case llvm::ELF::R_ARM_TARGET2:
429 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
430 case llvm::ELF::R_ARM_GOT_BREL:
431 case llvm::ELF::R_ARM_GOT_PREL: {
432 // A GOT entry is needed for these relocation type.
433 // return if we already create GOT for this symbol
434 if(rsym->reserved() & 0x6u)
435 return;
436 if(NULL == m_pGOT)
437 createARMGOT(pLinker, pOutput);
438 m_pGOT->reserveEntry();
439 // If building PIC object, a dynamic relocation with
440 // type RELATIVE is needed to relocate this GOT entry.
441 // Reserve an entry in .rel.dyn
442 if(isPIC(pLDInfo, pOutput)) {
443 // create .rel.dyn section if not exist
444 if(NULL == m_pRelDyn)
445 createARMRelDyn(pLinker, pOutput);
446 m_pRelDyn->reserveEntry(*m_pRelocFactory);
447 // set GOTRel bit
448 rsym->setReserved(rsym->reserved() | 0x4u);
449 return;
450 }
451 // set GOT bit
452 rsym->setReserved(rsym->reserved() | 0x2u);
453 return;
454 }
455
456 case llvm::ELF::R_ARM_BASE_PREL: {
457 // FIXME: Currently we only support R_ARM_BASE_PREL against
458 // symbol _GLOBAL_OFFSET_TABLE_
459 if(rsym != m_pGOTSymbol->resolveInfo()) {
460 llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
461 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
462 llvm::Twine(rsym->name()) +
463 llvm::Twine(".'"));
464 }
465 return;
466 }
467 case llvm::ELF::R_ARM_COPY:
468 case llvm::ELF::R_ARM_GLOB_DAT:
469 case llvm::ELF::R_ARM_JUMP_SLOT:
470 case llvm::ELF::R_ARM_RELATIVE: {
471 // These are relocation type for dynamic linker, shold not
472 // appear in object file.
473 llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
474 llvm::Twine((int)pReloc.type()) +
475 llvm::Twine(" in object file"));
476 break;
477 }
478 default: {
479 break;
480 }
481 } // end switch
482 }
483
scanGlobalReloc(Relocation & pReloc,const LDSymbol & pInputSym,MCLinker & pLinker,const MCLDInfo & pLDInfo,const Output & pOutput)484 void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc,
485 const LDSymbol& pInputSym,
486 MCLinker& pLinker,
487 const MCLDInfo& pLDInfo,
488 const Output& pOutput)
489 {
490 // rsym - The relocation target symbol
491 ResolveInfo* rsym = pReloc.symInfo();
492
493 switch(pReloc.type()) {
494
495 // Set R_ARM_TARGET1 to R_ARM_ABS32
496 // Ref: GNU gold 1.11 arm.cc, line 9892
497 case llvm::ELF::R_ARM_TARGET1:
498 pReloc.setType(llvm::ELF::R_ARM_ABS32);
499 case llvm::ELF::R_ARM_ABS32:
500 case llvm::ELF::R_ARM_ABS16:
501 case llvm::ELF::R_ARM_ABS12:
502 case llvm::ELF::R_ARM_THM_ABS5:
503 case llvm::ELF::R_ARM_ABS8:
504 case llvm::ELF::R_ARM_BASE_ABS:
505 case llvm::ELF::R_ARM_MOVW_ABS_NC:
506 case llvm::ELF::R_ARM_MOVT_ABS:
507 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
508 case llvm::ELF::R_ARM_THM_MOVT_ABS:
509 case llvm::ELF::R_ARM_ABS32_NOI: {
510 // Absolute relocation type, symbol may needs PLT entry or
511 // dynamic relocation entry
512 if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
513 // create plt for this symbol if it does not have one
514 if(!(rsym->reserved() & 0x8u)){
515 // Create .got section if it doesn't exist
516 if(NULL == m_pGOT)
517 createARMGOT(pLinker, pOutput);
518 // create .plt and .rel.plt if not exist
519 if(NULL == m_pPLT)
520 createARMPLTandRelPLT(pLinker, pOutput);
521 // Symbol needs PLT entry, we need to reserve a PLT entry
522 // and the corresponding GOT and dynamic relocation entry
523 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
524 // when calling ARMPLT->reserveEntry())
525 m_pPLT->reserveEntry();
526 m_pRelPLT->reserveEntry(*m_pRelocFactory);
527 // set PLT bit
528 rsym->setReserved(rsym->reserved() | 0x8u);
529 }
530 }
531
532 if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
533 checkValidReloc(pReloc, pLDInfo, pOutput);
534 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
535 // create .rel.dyn section if not exist
536 if(NULL == m_pRelDyn)
537 createARMRelDyn(pLinker, pOutput);
538 m_pRelDyn->reserveEntry(*m_pRelocFactory);
539 // set Rel bit
540 rsym->setReserved(rsym->reserved() | 0x1u);
541 }
542 return;
543 }
544
545 case llvm::ELF::R_ARM_GOTOFF32:
546 case llvm::ELF::R_ARM_GOTOFF12: {
547 // A GOT section is needed
548 if(NULL == m_pGOT)
549 createARMGOT(pLinker, pOutput);
550 return;
551 }
552
553 case llvm::ELF::R_ARM_BASE_PREL:
554 // FIXME: Currently we only support R_ARM_BASE_PREL against
555 // symbol _GLOBAL_OFFSET_TABLE_
556 if(rsym != m_pGOTSymbol->resolveInfo()) {
557 llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
558 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
559 llvm::Twine(rsym->name()) +
560 llvm::Twine(".'"));
561 }
562 case llvm::ELF::R_ARM_REL32:
563 case llvm::ELF::R_ARM_LDR_PC_G0:
564 case llvm::ELF::R_ARM_SBREL32:
565 case llvm::ELF::R_ARM_THM_PC8:
566 case llvm::ELF::R_ARM_MOVW_PREL_NC:
567 case llvm::ELF::R_ARM_MOVT_PREL:
568 case llvm::ELF::R_ARM_THM_MOVW_PREL_NC:
569 case llvm::ELF::R_ARM_THM_MOVT_PREL:
570 case llvm::ELF::R_ARM_THM_ALU_PREL_11_0:
571 case llvm::ELF::R_ARM_THM_PC12:
572 case llvm::ELF::R_ARM_REL32_NOI:
573 case llvm::ELF::R_ARM_ALU_PC_G0_NC:
574 case llvm::ELF::R_ARM_ALU_PC_G0:
575 case llvm::ELF::R_ARM_ALU_PC_G1_NC:
576 case llvm::ELF::R_ARM_ALU_PC_G1:
577 case llvm::ELF::R_ARM_ALU_PC_G2:
578 case llvm::ELF::R_ARM_LDR_PC_G1:
579 case llvm::ELF::R_ARM_LDR_PC_G2:
580 case llvm::ELF::R_ARM_LDRS_PC_G0:
581 case llvm::ELF::R_ARM_LDRS_PC_G1:
582 case llvm::ELF::R_ARM_LDRS_PC_G2:
583 case llvm::ELF::R_ARM_LDC_PC_G0:
584 case llvm::ELF::R_ARM_LDC_PC_G1:
585 case llvm::ELF::R_ARM_LDC_PC_G2:
586 case llvm::ELF::R_ARM_ALU_SB_G0_NC:
587 case llvm::ELF::R_ARM_ALU_SB_G0:
588 case llvm::ELF::R_ARM_ALU_SB_G1_NC:
589 case llvm::ELF::R_ARM_ALU_SB_G1:
590 case llvm::ELF::R_ARM_ALU_SB_G2:
591 case llvm::ELF::R_ARM_LDR_SB_G0:
592 case llvm::ELF::R_ARM_LDR_SB_G1:
593 case llvm::ELF::R_ARM_LDR_SB_G2:
594 case llvm::ELF::R_ARM_LDRS_SB_G0:
595 case llvm::ELF::R_ARM_LDRS_SB_G1:
596 case llvm::ELF::R_ARM_LDRS_SB_G2:
597 case llvm::ELF::R_ARM_LDC_SB_G0:
598 case llvm::ELF::R_ARM_LDC_SB_G1:
599 case llvm::ELF::R_ARM_LDC_SB_G2:
600 case llvm::ELF::R_ARM_MOVW_BREL_NC:
601 case llvm::ELF::R_ARM_MOVT_BREL:
602 case llvm::ELF::R_ARM_MOVW_BREL:
603 case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
604 case llvm::ELF::R_ARM_THM_MOVT_BREL:
605 case llvm::ELF::R_ARM_THM_MOVW_BREL: {
606 // Relative addressing relocation, may needs dynamic relocation
607 if(isSymbolNeedsDynRel(*rsym, pOutput, false)) {
608 checkValidReloc(pReloc, pLDInfo, pOutput);
609 // create .rel.dyn section if not exist
610 if(NULL == m_pRelDyn)
611 createARMRelDyn(pLinker, pOutput);
612 m_pRelDyn->reserveEntry(*m_pRelocFactory);
613 // set Rel bit
614 rsym->setReserved(rsym->reserved() | 0x1u);
615 }
616 return;
617 }
618
619 case llvm::ELF::R_ARM_THM_CALL:
620 case llvm::ELF::R_ARM_PLT32:
621 case llvm::ELF::R_ARM_CALL:
622 case llvm::ELF::R_ARM_JUMP24:
623 case llvm::ELF::R_ARM_THM_JUMP24:
624 case llvm::ELF::R_ARM_SBREL31:
625 case llvm::ELF::R_ARM_PREL31:
626 case llvm::ELF::R_ARM_THM_JUMP19:
627 case llvm::ELF::R_ARM_THM_JUMP6:
628 case llvm::ELF::R_ARM_THM_JUMP11:
629 case llvm::ELF::R_ARM_THM_JUMP8: {
630 // These are branch relocation (except PREL31)
631 // A PLT entry is needed when building shared library
632
633 // return if we already create plt for this symbol
634 if(rsym->reserved() & 0x8u)
635 return;
636
637 // if symbol is defined in the ouput file and it's not
638 // preemptible, no need plt
639 if(rsym->isDefine() && !rsym->isDyn() &&
640 !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
641 return;
642 }
643
644 // Create .got section if it doesn't exist
645 if(NULL == m_pGOT)
646 createARMGOT(pLinker, pOutput);
647
648 // create .plt and .rel.plt if not exist
649 if(NULL == m_pPLT)
650 createARMPLTandRelPLT(pLinker, pOutput);
651 // Symbol needs PLT entry, we need to reserve a PLT entry
652 // and the corresponding GOT and dynamic relocation entry
653 // in .got and .rel.plt. (GOT entry will be reserved simultaneously
654 // when calling ARMPLT->reserveEntry())
655 m_pPLT->reserveEntry();
656 m_pRelPLT->reserveEntry(*m_pRelocFactory);
657 // set PLT bit
658 rsym->setReserved(rsym->reserved() | 0x8u);
659 return;
660 }
661
662 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
663 // Ref: GNU gold 1.11 arm.cc, line 9892
664 case llvm::ELF::R_ARM_TARGET2:
665 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
666 case llvm::ELF::R_ARM_GOT_BREL:
667 case llvm::ELF::R_ARM_GOT_ABS:
668 case llvm::ELF::R_ARM_GOT_PREL: {
669 // Symbol needs GOT entry, reserve entry in .got
670 // return if we already create GOT for this symbol
671 if(rsym->reserved() & 0x6u)
672 return;
673 if(NULL == m_pGOT)
674 createARMGOT(pLinker, pOutput);
675 m_pGOT->reserveEntry();
676 // If building shared object or the symbol is undefined, a dynamic
677 // relocation is needed to relocate this GOT entry. Reserve an
678 // entry in .rel.dyn
679 if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
680 // create .rel.dyn section if not exist
681 if(NULL == m_pRelDyn)
682 createARMRelDyn(pLinker, pOutput);
683 m_pRelDyn->reserveEntry(*m_pRelocFactory);
684 // set GOTRel bit
685 rsym->setReserved(rsym->reserved() | 0x4u);
686 return;
687 }
688 // set GOT bit
689 rsym->setReserved(rsym->reserved() | 0x2u);
690 return;
691 }
692
693 case llvm::ELF::R_ARM_COPY:
694 case llvm::ELF::R_ARM_GLOB_DAT:
695 case llvm::ELF::R_ARM_JUMP_SLOT:
696 case llvm::ELF::R_ARM_RELATIVE: {
697 // These are relocation type for dynamic linker, shold not
698 // appear in object file.
699 llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
700 llvm::Twine((int)pReloc.type()) +
701 llvm::Twine(" in object file"));
702 break;
703 }
704 default: {
705 break;
706 }
707 } // end switch
708 }
709
scanRelocation(Relocation & pReloc,const LDSymbol & pInputSym,MCLinker & pLinker,const MCLDInfo & pLDInfo,const Output & pOutput)710 void ARMGNULDBackend::scanRelocation(Relocation& pReloc,
711 const LDSymbol& pInputSym,
712 MCLinker& pLinker,
713 const MCLDInfo& pLDInfo,
714 const Output& pOutput)
715 {
716 // rsym - The relocation target symbol
717 ResolveInfo* rsym = pReloc.symInfo();
718 assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
719
720 // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
721 // entries should be created.
722 // FIXME: Below judgements concern only .so is generated as output
723 // FIXME: Below judgements concern nothing about TLS related relocation
724
725 // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
726 // is needed
727 if(NULL == m_pGOT && NULL != m_pGOTSymbol) {
728 if(rsym == m_pGOTSymbol->resolveInfo()) {
729 createARMGOT(pLinker, pOutput);
730 }
731 }
732
733 // rsym is local
734 if(rsym->isLocal())
735 scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
736
737 // rsym is external
738 else
739 scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
740
741 }
742
emitSectionData(const Output & pOutput,const LDSection & pSection,const MCLDInfo & pInfo,MemoryRegion & pRegion) const743 uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
744 const LDSection& pSection,
745 const MCLDInfo& pInfo,
746 MemoryRegion& pRegion) const
747 {
748 assert(pRegion.size() && "Size of MemoryRegion is zero!");
749
750 ELFFileFormat* file_format = getOutputFormat(pOutput);
751
752 if (&pSection == m_pAttributes) {
753 // FIXME: Currently Emitting .ARM.attributes directly from the input file.
754 const llvm::MCSectionData* sect_data = pSection.getSectionData();
755 assert(sect_data &&
756 "Emit .ARM.attribute failed, MCSectionData doesn't exist!");
757
758 uint8_t* start =
759 llvm::cast<MCRegionFragment>(
760 sect_data->getFragmentList().front()).getRegion().start();
761
762 memcpy(pRegion.start(), start, pRegion.size());
763 return pRegion.size();
764 }
765
766 if (&pSection == &(file_format->getPLT())) {
767 assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
768 uint64_t result = m_pPLT->emit(pRegion);
769 return result;
770 }
771
772 if (&pSection == &(file_format->getGOT())) {
773 assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
774 uint64_t result = m_pGOT->emit(pRegion);
775 return result;
776 }
777
778 llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
779 pSection.name() +
780 llvm::Twine("'.\n"));
781 return 0x0;
782 }
783
784 /// finalizeSymbol - finalize the symbol value
785 /// If the symbol's reserved field is not zero, MCLinker will call back this
786 /// function to ask the final value of the symbol
finalizeSymbol(LDSymbol & pSymbol) const787 bool ARMGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
788 {
789 return false;
790 }
791
792 /// allocateCommonSymbols - allocate common symbols in the corresponding
793 /// sections.
794 /// @refer Google gold linker: common.cc: 214
795 bool
allocateCommonSymbols(const MCLDInfo & pInfo,MCLinker & pLinker) const796 ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
797 {
798 SymbolCategory& symbol_list = pLinker.getOutputSymbols();
799
800 if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
801 return true;
802
803 // addralign := max value of all common symbols
804 uint64_t addralign = 0x0;
805
806 // Due to the visibility, some common symbols may be forcefully local.
807 SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
808 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
809 if (ResolveInfo::Common == (*com_sym)->desc()) {
810 if ((*com_sym)->value() > addralign)
811 addralign = (*com_sym)->value();
812 }
813 }
814
815 // global common symbols.
816 com_end = symbol_list.commonEnd();
817 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
818 if ((*com_sym)->value() > addralign)
819 addralign = (*com_sym)->value();
820 }
821
822 // FIXME: If the order of common symbols is defined, then sort common symbols
823 // com_sym = symbol_list.commonBegin();
824 // std::sort(com_sym, com_end, some kind of order);
825
826 // get or create corresponding BSS LDSection
827 LDSection* bss_sect_hdr = NULL;
828 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
829 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
830 ".tbss",
831 LDFileFormat::BSS,
832 llvm::ELF::SHT_NOBITS,
833 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
834 }
835 else {
836 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
837 LDFileFormat::BSS,
838 llvm::ELF::SHT_NOBITS,
839 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
840 }
841
842 // get or create corresponding BSS MCSectionData
843 assert(NULL != bss_sect_hdr);
844 llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
845
846 // allocate all common symbols
847 uint64_t offset = bss_sect_hdr->size();
848
849 // allocate all local common symbols
850 com_end = symbol_list.localEnd();
851 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
852 if (ResolveInfo::Common == (*com_sym)->desc()) {
853 // We have to reset the description of the symbol here. When doing
854 // incremental linking, the output relocatable object may have common
855 // symbols. Therefore, we can not treat common symbols as normal symbols
856 // when emitting the regular name pools. We must change the symbols'
857 // description here.
858 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
859 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
860 (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
861 uint64_t size = pLinker.getLayout().appendFragment(*frag,
862 bss_section,
863 (*com_sym)->value());
864 offset += size;
865 }
866 }
867
868 // allocate all global common symbols
869 com_end = symbol_list.commonEnd();
870 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
871 // We have to reset the description of the symbol here. When doing
872 // incremental linking, the output relocatable object may have common
873 // symbols. Therefore, we can not treat common symbols as normal symbols
874 // when emitting the regular name pools. We must change the symbols'
875 // description here.
876 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
877 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
878 (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
879 uint64_t size = pLinker.getLayout().appendFragment(*frag,
880 bss_section,
881 (*com_sym)->value());
882 offset += size;
883 }
884
885 bss_sect_hdr->setSize(offset);
886 symbol_list.changeCommonsToGlobal();
887 return true;
888 }
889
readSection(Input & pInput,MCLinker & pLinker,LDSection & pInputSectHdr)890 bool ARMGNULDBackend::readSection(Input& pInput,
891 MCLinker& pLinker,
892 LDSection& pInputSectHdr)
893 {
894 LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
895 pInputSectHdr.kind(),
896 pInputSectHdr.type(),
897 pInputSectHdr.flag());
898 // FIXME: (Luba)
899 // Handle ARM attributes in the right way.
900 // In current milestone, MCLinker goes through the shortcut.
901 // It reads input's ARM attributes and copies the first ARM attributes
902 // into the output file. The correct way is merge these sections, not
903 // just copy.
904 if ((0 == out_sect.name().compare(".ARM.attributes")) &&
905 (0 != out_sect.size()))
906 return true;
907
908 MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(),
909 pInputSectHdr.size());
910
911 llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
912
913 new MCRegionFragment(*region, §_data);
914
915 out_sect.setSize(out_sect.size() + pInputSectHdr.size());
916 return true;
917 }
918
getGOT()919 ARMGOT& ARMGNULDBackend::getGOT()
920 {
921 assert(NULL != m_pGOT && "GOT section not exist");
922 return *m_pGOT;
923 }
924
getGOT() const925 const ARMGOT& ARMGNULDBackend::getGOT() const
926 {
927 assert(NULL != m_pGOT && "GOT section not exist");
928 return *m_pGOT;
929 }
930
getPLT()931 ARMPLT& ARMGNULDBackend::getPLT()
932 {
933 assert(NULL != m_pPLT && "PLT section not exist");
934 return *m_pPLT;
935 }
936
getPLT() const937 const ARMPLT& ARMGNULDBackend::getPLT() const
938 {
939 assert(NULL != m_pPLT && "PLT section not exist");
940 return *m_pPLT;
941 }
942
getRelDyn()943 OutputRelocSection& ARMGNULDBackend::getRelDyn()
944 {
945 assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
946 return *m_pRelDyn;
947 }
948
getRelDyn() const949 const OutputRelocSection& ARMGNULDBackend::getRelDyn() const
950 {
951 assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
952 return *m_pRelDyn;
953 }
954
getRelPLT()955 OutputRelocSection& ARMGNULDBackend::getRelPLT()
956 {
957 assert(NULL != m_pRelPLT && ".rel.plt section not exist");
958 return *m_pRelPLT;
959 }
960
getRelPLT() const961 const OutputRelocSection& ARMGNULDBackend::getRelPLT() const
962 {
963 assert(NULL != m_pRelPLT && ".rel.plt section not exist");
964 return *m_pRelPLT;
965 }
966
967 unsigned int
getTargetSectionOrder(const Output & pOutput,const LDSection & pSectHdr) const968 ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput,
969 const LDSection& pSectHdr) const
970 {
971 ELFFileFormat* file_format = getOutputFormat(pOutput);
972
973 if (&pSectHdr == &file_format->getGOT())
974 return SHO_DATA;
975
976 if (&pSectHdr == &file_format->getPLT())
977 return SHO_PLT;
978
979 return SHO_UNDEFINED;
980 }
981
982 namespace mcld {
983
984 //===----------------------------------------------------------------------===//
985 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
986 ///
createARMLDBackend(const llvm::Target & pTarget,const std::string & pTriple)987 TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
988 const std::string& pTriple)
989 {
990 Triple theTriple(pTriple);
991 if (theTriple.isOSDarwin()) {
992 assert(0 && "MachO linker is not supported yet");
993 /**
994 return new ARMMachOLDBackend(createARMMachOArchiveReader,
995 createARMMachOObjectReader,
996 createARMMachOObjectWriter);
997 **/
998 }
999 if (theTriple.isOSWindows()) {
1000 assert(0 && "COFF linker is not supported yet");
1001 /**
1002 return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
1003 createARMCOFFObjectReader,
1004 createARMCOFFObjectWriter);
1005 **/
1006 }
1007 return new ARMGNULDBackend();
1008 }
1009
1010 } // namespace of mcld
1011
1012 //=============================
1013 // Force static initialization.
LLVMInitializeARMLDBackend()1014 extern "C" void LLVMInitializeARMLDBackend() {
1015 // Register the linker backend
1016 mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
1017 }
1018