• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &sect_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