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