ARMLDBackend.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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
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 (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
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::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
104void 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
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  // 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.
164ARMELFDynamic& 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.
174const ARMELFDynamic& ARMGNULDBackend::dynamic() const
175{
176  assert( NULL != m_pDynamic);
177  return *m_pDynamic;
178}
179
180bool ARMGNULDBackend::isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const
181{
182  return (pOutput.type() == Output::DynObj);
183}
184
185void 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
221void 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
239void 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
252ELFFileFormat* 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
268bool 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
278bool 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
294bool 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.
312void 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
345void 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
356void 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
484void 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
710void 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
743uint64_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
787bool 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
795bool
796ARMGNULDBackend::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
890bool 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
919ARMGOT& ARMGNULDBackend::getGOT()
920{
921  assert(NULL != m_pGOT && "GOT section not exist");
922  return *m_pGOT;
923}
924
925const ARMGOT& ARMGNULDBackend::getGOT() const
926{
927  assert(NULL != m_pGOT && "GOT section not exist");
928  return *m_pGOT;
929}
930
931ARMPLT& ARMGNULDBackend::getPLT()
932{
933  assert(NULL != m_pPLT && "PLT section not exist");
934  return *m_pPLT;
935}
936
937const ARMPLT& ARMGNULDBackend::getPLT() const
938{
939  assert(NULL != m_pPLT && "PLT section not exist");
940  return *m_pPLT;
941}
942
943OutputRelocSection& ARMGNULDBackend::getRelDyn()
944{
945  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
946  return *m_pRelDyn;
947}
948
949const OutputRelocSection& ARMGNULDBackend::getRelDyn() const
950{
951  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
952  return *m_pRelDyn;
953}
954
955OutputRelocSection& ARMGNULDBackend::getRelPLT()
956{
957  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
958  return *m_pRelPLT;
959}
960
961const OutputRelocSection& ARMGNULDBackend::getRelPLT() const
962{
963  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
964  return *m_pRelPLT;
965}
966
967unsigned int
968ARMGNULDBackend::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
982namespace mcld {
983
984//===----------------------------------------------------------------------===//
985/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
986///
987TargetLDBackend* 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.
1014extern "C" void LLVMInitializeARMLDBackend() {
1015  // Register the linker backend
1016  mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
1017}
1018
1019