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