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