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