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 "ARMGNUInfo.h"
     11 #include "ARMELFAttributeData.h"
     12 #include "ARMELFDynamic.h"
     13 #include "ARMLDBackend.h"
     14 #include "ARMRelocator.h"
     15 #include "ARMToARMStub.h"
     16 #include "ARMToTHMStub.h"
     17 #include "THMToTHMStub.h"
     18 #include "THMToARMStub.h"
     19 
     20 #include <mcld/IRBuilder.h>
     21 #include <mcld/LinkerConfig.h>
     22 #include <mcld/Fragment/FillFragment.h>
     23 #include <mcld/Fragment/AlignFragment.h>
     24 #include <mcld/Fragment/RegionFragment.h>
     25 #include <mcld/Fragment/Stub.h>
     26 #include <mcld/Fragment/NullFragment.h>
     27 #include <mcld/Support/MemoryRegion.h>
     28 #include <mcld/Support/MemoryArea.h>
     29 #include <mcld/Support/MsgHandling.h>
     30 #include <mcld/Support/TargetRegistry.h>
     31 #include <mcld/LD/BranchIslandFactory.h>
     32 #include <mcld/LD/StubFactory.h>
     33 #include <mcld/LD/LDContext.h>
     34 #include <mcld/LD/ELFFileFormat.h>
     35 #include <mcld/LD/ELFSegmentFactory.h>
     36 #include <mcld/LD/ELFSegment.h>
     37 #include <mcld/Target/ELFAttribute.h>
     38 #include <mcld/Target/GNUInfo.h>
     39 #include <mcld/Object/ObjectBuilder.h>
     40 
     41 #include <llvm/ADT/StringRef.h>
     42 #include <llvm/ADT/Triple.h>
     43 #include <llvm/ADT/Twine.h>
     44 #include <llvm/Support/ELF.h>
     45 #include <llvm/Support/Casting.h>
     46 
     47 #include <cstring>
     48 
     49 using namespace mcld;
     50 
     51 //===----------------------------------------------------------------------===//
     52 // ARMGNULDBackend
     53 //===----------------------------------------------------------------------===//
     54 ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo)
     55   : GNULDBackend(pConfig, pInfo),
     56     m_pRelocator(NULL),
     57     m_pGOT(NULL),
     58     m_pPLT(NULL),
     59     m_pRelDyn(NULL),
     60     m_pRelPLT(NULL),
     61     m_pAttrData(NULL),
     62     m_pDynamic(NULL),
     63     m_pGOTSymbol(NULL),
     64     m_pEXIDXStart(NULL),
     65     m_pEXIDXEnd(NULL),
     66     m_pEXIDX(NULL),
     67     m_pEXTAB(NULL),
     68     m_pAttributes(NULL) {
     69 }
     70 
     71 ARMGNULDBackend::~ARMGNULDBackend()
     72 {
     73   delete m_pRelocator;
     74   delete m_pGOT;
     75   delete m_pPLT;
     76   delete m_pRelDyn;
     77   delete m_pRelPLT;
     78   delete m_pDynamic;
     79   delete m_pAttrData;
     80 }
     81 
     82 void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
     83 {
     84  // FIXME: Currently we set exidx and extab to "Exception" and directly emit
     85  // them from input
     86   m_pEXIDX        = pBuilder.CreateSection(".ARM.exidx",
     87                                            LDFileFormat::Target,
     88                                            llvm::ELF::SHT_ARM_EXIDX,
     89                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
     90                                            config().targets().bitclass() / 8);
     91   m_pEXTAB        = pBuilder.CreateSection(".ARM.extab",
     92                                            LDFileFormat::Target,
     93                                            llvm::ELF::SHT_PROGBITS,
     94                                            llvm::ELF::SHF_ALLOC,
     95                                            0x1);
     96   m_pAttributes   = pBuilder.CreateSection(".ARM.attributes",
     97                                            LDFileFormat::Target,
     98                                            llvm::ELF::SHT_ARM_ATTRIBUTES,
     99                                            0x0,
    100                                            0x1);
    101 
    102   // initialize "aeabi" attributes subsection
    103   m_pAttrData = new ARMELFAttributeData();
    104   attribute().registerAttributeData(*m_pAttrData);
    105 
    106   if (LinkerConfig::Object != config().codeGenType()) {
    107     ELFFileFormat* file_format = getOutputFormat();
    108 
    109     // initialize .got
    110     LDSection& got = file_format->getGOT();
    111     m_pGOT = new ARMGOT(got);
    112 
    113     // initialize .plt
    114     LDSection& plt = file_format->getPLT();
    115     m_pPLT = new ARMPLT(plt, *m_pGOT);
    116 
    117     // initialize .rel.plt
    118     LDSection& relplt = file_format->getRelPlt();
    119     relplt.setLink(&plt);
    120     // create SectionData and ARMRelDynSection
    121     m_pRelPLT = new OutputRelocSection(pModule, relplt);
    122 
    123     // initialize .rel.dyn
    124     LDSection& reldyn = file_format->getRelDyn();
    125     m_pRelDyn = new OutputRelocSection(pModule, reldyn);
    126   }
    127 }
    128 
    129 void ARMGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
    130 {
    131   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
    132   // same name in input
    133   if (LinkerConfig::Object != config().codeGenType()) {
    134     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    135                                                   "_GLOBAL_OFFSET_TABLE_",
    136                                                   ResolveInfo::Object,
    137                                                   ResolveInfo::Define,
    138                                                   ResolveInfo::Local,
    139                                                   0x0,  // size
    140                                                   0x0,  // value
    141                                                   FragmentRef::Null(),
    142                                                   ResolveInfo::Hidden);
    143   }
    144   if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
    145     FragmentRef* exidx_start =
    146       FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
    147     FragmentRef* exidx_end =
    148       FragmentRef::Create(m_pEXIDX->getSectionData()->front(),
    149                           m_pEXIDX->size());
    150     m_pEXIDXStart =
    151       pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    152                                                     "__exidx_start",
    153                                                     ResolveInfo::Object,
    154                                                     ResolveInfo::Define,
    155                                                     ResolveInfo::Local,
    156                                                     0x0, // size
    157                                                     0x0, // value
    158                                                     exidx_start, // FragRef
    159                                                     ResolveInfo::Default);
    160 
    161     m_pEXIDXEnd =
    162       pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    163                                                     "__exidx_end",
    164                                                     ResolveInfo::Object,
    165                                                     ResolveInfo::Define,
    166                                                     ResolveInfo::Local,
    167                                                     0x0, // size
    168                                                     0x0, // value
    169                                                     exidx_end, // FragRef
    170                                                     ResolveInfo::Default);
    171     // change __exidx_start/_end to local dynamic category
    172     if (NULL != m_pEXIDXStart)
    173       pModule.getSymbolTable().changeToDynamic(*m_pEXIDXStart);
    174     if (NULL != m_pEXIDXEnd)
    175       pModule.getSymbolTable().changeToDynamic(*m_pEXIDXEnd);
    176   } else {
    177     m_pEXIDXStart =
    178       pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    179                                                     "__exidx_start",
    180                                                     ResolveInfo::NoType,
    181                                                     ResolveInfo::Define,
    182                                                     ResolveInfo::Absolute,
    183                                                     0x0, // size
    184                                                     0x0, // value
    185                                                     FragmentRef::Null(),
    186                                                     ResolveInfo::Default);
    187 
    188     m_pEXIDXEnd =
    189       pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    190                                                     "__exidx_end",
    191                                                     ResolveInfo::NoType,
    192                                                     ResolveInfo::Define,
    193                                                     ResolveInfo::Absolute,
    194                                                     0x0, // size
    195                                                     0x0, // value
    196                                                     FragmentRef::Null(),
    197                                                     ResolveInfo::Default);
    198   }
    199 }
    200 
    201 bool ARMGNULDBackend::initRelocator()
    202 {
    203   if (NULL == m_pRelocator) {
    204     m_pRelocator = new ARMRelocator(*this, config());
    205   }
    206   return true;
    207 }
    208 
    209 const Relocator* ARMGNULDBackend::getRelocator() const
    210 {
    211   assert(NULL != m_pRelocator);
    212   return m_pRelocator;
    213 }
    214 
    215 Relocator* ARMGNULDBackend::getRelocator()
    216 {
    217   assert(NULL != m_pRelocator);
    218   return m_pRelocator;
    219 }
    220 
    221 void ARMGNULDBackend::doPreLayout(IRBuilder& pBuilder)
    222 {
    223   // initialize .dynamic data
    224   if (!config().isCodeStatic() && NULL == m_pDynamic)
    225     m_pDynamic = new ARMELFDynamic(*this, config());
    226 
    227   // set attribute section size
    228   m_pAttributes->setSize(attribute().sizeOutput());
    229 
    230   // set .got size
    231   // when building shared object, the .got section is must
    232   if (LinkerConfig::Object != config().codeGenType()) {
    233     if (LinkerConfig::DynObj == config().codeGenType() ||
    234         m_pGOT->hasGOT1() ||
    235         NULL != m_pGOTSymbol) {
    236       m_pGOT->finalizeSectionSize();
    237       defineGOTSymbol(pBuilder);
    238     }
    239 
    240     // set .plt size
    241     if (m_pPLT->hasPLT1())
    242       m_pPLT->finalizeSectionSize();
    243 
    244     ELFFileFormat* file_format = getOutputFormat();
    245     // set .rel.dyn size
    246     if (!m_pRelDyn->empty()) {
    247       assert(!config().isCodeStatic() &&
    248             "static linkage should not result in a dynamic relocation section");
    249       file_format->getRelDyn().setSize(
    250                                   m_pRelDyn->numOfRelocs() * getRelEntrySize());
    251     }
    252 
    253     // set .rel.plt size
    254     if (!m_pRelPLT->empty()) {
    255       assert(!config().isCodeStatic() &&
    256             "static linkage should not result in a dynamic relocation section");
    257       file_format->getRelPlt().setSize(
    258                                   m_pRelPLT->numOfRelocs() * getRelEntrySize());
    259     }
    260   }
    261 }
    262 
    263 void ARMGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
    264 {
    265   const ELFFileFormat *file_format = getOutputFormat();
    266 
    267   // apply PLT
    268   if (file_format->hasPLT()) {
    269     // Since we already have the size of LDSection PLT, m_pPLT should not be
    270     // NULL.
    271     assert(NULL != m_pPLT);
    272     m_pPLT->applyPLT0();
    273     m_pPLT->applyPLT1();
    274   }
    275 
    276   // apply GOT
    277   if (file_format->hasGOT()) {
    278     // Since we already have the size of GOT, m_pGOT should not be NULL.
    279     assert(NULL != m_pGOT);
    280     if (LinkerConfig::DynObj == config().codeGenType())
    281       m_pGOT->applyGOT0(file_format->getDynamic().addr());
    282     else {
    283       // executable file and object file? should fill with zero.
    284       m_pGOT->applyGOT0(0);
    285     }
    286   }
    287 }
    288 
    289 /// dynamic - the dynamic section of the target machine.
    290 /// Use co-variant return type to return its own dynamic section.
    291 ARMELFDynamic& ARMGNULDBackend::dynamic()
    292 {
    293   assert(NULL != m_pDynamic);
    294   return *m_pDynamic;
    295 }
    296 
    297 /// dynamic - the dynamic section of the target machine.
    298 /// Use co-variant return type to return its own dynamic section.
    299 const ARMELFDynamic& ARMGNULDBackend::dynamic() const
    300 {
    301   assert(NULL != m_pDynamic);
    302   return *m_pDynamic;
    303 }
    304 
    305 void ARMGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
    306 {
    307   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
    308   if (m_pGOTSymbol != NULL) {
    309     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
    310                      "_GLOBAL_OFFSET_TABLE_",
    311                      ResolveInfo::Object,
    312                      ResolveInfo::Define,
    313                      ResolveInfo::Local,
    314                      0x0, // size
    315                      0x0, // value
    316                      FragmentRef::Create(*(m_pGOT->begin()), 0x0),
    317                      ResolveInfo::Hidden);
    318   }
    319   else {
    320     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    321                      "_GLOBAL_OFFSET_TABLE_",
    322                      ResolveInfo::Object,
    323                      ResolveInfo::Define,
    324                      ResolveInfo::Local,
    325                      0x0, // size
    326                      0x0, // value
    327                      FragmentRef::Create(*(m_pGOT->begin()), 0x0),
    328                      ResolveInfo::Hidden);
    329   }
    330 
    331 }
    332 
    333 uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
    334                                           MemoryRegion& pRegion) const
    335 {
    336   assert(pRegion.size() && "Size of MemoryRegion is zero!");
    337 
    338   const ELFFileFormat* file_format = getOutputFormat();
    339 
    340   if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
    341     uint64_t result = m_pPLT->emit(pRegion);
    342     return result;
    343   }
    344 
    345   if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
    346     uint64_t result = m_pGOT->emit(pRegion);
    347     return result;
    348   }
    349 
    350   if (&pSection == m_pAttributes) {
    351     return attribute().emit(pRegion);
    352   }
    353 
    354   // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
    355   // directly from the input file.
    356   const SectionData* sect_data = pSection.getSectionData();
    357   SectionData::const_iterator frag_iter, frag_end = sect_data->end();
    358   uint8_t* out_offset = pRegion.begin();
    359   for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
    360     size_t size = frag_iter->size();
    361     switch(frag_iter->getKind()) {
    362       case Fragment::Fillment: {
    363         const FillFragment& fill_frag =
    364           llvm::cast<FillFragment>(*frag_iter);
    365         if (0 == fill_frag.getValueSize()) {
    366           // virtual fillment, ignore it.
    367           break;
    368         }
    369 
    370         memset(out_offset, fill_frag.getValue(), fill_frag.size());
    371         break;
    372       }
    373       case Fragment::Region: {
    374         const RegionFragment& region_frag =
    375           llvm::cast<RegionFragment>(*frag_iter);
    376         const char* start = region_frag.getRegion().begin();
    377         memcpy(out_offset, start, size);
    378         break;
    379       }
    380       case Fragment::Alignment: {
    381         const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
    382         uint64_t count = size / align_frag.getValueSize();
    383         switch (align_frag.getValueSize()) {
    384           case 1u:
    385             std::memset(out_offset, align_frag.getValue(), count);
    386             break;
    387           default:
    388             llvm::report_fatal_error(
    389               "unsupported value size for align fragment emission yet.\n");
    390             break;
    391         } // end switch
    392         break;
    393       }
    394       case Fragment::Null: {
    395         assert(0x0 == size);
    396         break;
    397       }
    398       default:
    399         llvm::report_fatal_error("unsupported fragment type.\n");
    400         break;
    401     } // end switch
    402     out_offset += size;
    403   } // end for
    404   return pRegion.size();
    405 }
    406 
    407 /// finalizeSymbol - finalize the symbol value
    408 bool ARMGNULDBackend::finalizeTargetSymbols()
    409 {
    410   return true;
    411 }
    412 
    413 bool ARMGNULDBackend::mergeSection(Module& pModule,
    414                                    const Input& pInput,
    415                                    LDSection& pSection)
    416 {
    417   switch (pSection.type()) {
    418     case llvm::ELF::SHT_ARM_ATTRIBUTES: {
    419       return attribute().merge(pInput, pSection);
    420     }
    421     case llvm::ELF::SHT_ARM_EXIDX: {
    422       assert(NULL != pSection.getLink());
    423       if (LDFileFormat::Ignore == pSection.getLink()->kind()) {
    424         // if the target section of the .ARM.exidx is Ignore, then it should be
    425         // ignored as well
    426         pSection.setKind(LDFileFormat::Ignore);
    427         return true;
    428       }
    429     }
    430     /** fall through **/
    431     default: {
    432       ObjectBuilder builder(pModule);
    433       builder.MergeSection(pInput, pSection);
    434       return true;
    435     }
    436   } // end of switch
    437   return true;
    438 }
    439 
    440 void ARMGNULDBackend::setUpReachedSectionsForGC(const Module& pModule,
    441             GarbageCollection::SectionReachedListMap& pSectReachedListMap) const
    442 {
    443   // traverse all the input relocations to find the relocation sections applying
    444   // .ARM.exidx sections
    445   Module::const_obj_iterator input, inEnd = pModule.obj_end();
    446   for (input = pModule.obj_begin(); input != inEnd; ++input) {
    447     LDContext::const_sect_iterator rs,
    448                                    rsEnd = (*input)->context()->relocSectEnd();
    449     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
    450       // bypass the discarded relocation section
    451       // 1. its section kind is changed to Ignore. (The target section is a
    452       // discarded group section.)
    453       // 2. it has no reloc data. (All symbols in the input relocs are in the
    454       // discarded group sections)
    455       LDSection* reloc_sect = *rs;
    456       LDSection* apply_sect = reloc_sect->getLink();
    457       if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
    458           (!reloc_sect->hasRelocData()))
    459         continue;
    460 
    461       if (llvm::ELF::SHT_ARM_EXIDX == apply_sect->type()) {
    462         // 1. set up the reference according to relocations
    463         bool add_first = false;
    464         GarbageCollection::SectionListTy* reached_sects = NULL;
    465         RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
    466         for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd;
    467                                                                    ++reloc_it) {
    468           Relocation* reloc = llvm::cast<Relocation>(reloc_it);
    469           ResolveInfo* sym = reloc->symInfo();
    470           // only the target symbols defined in the input fragments can make the
    471           // reference
    472           if (NULL == sym)
    473             continue;
    474           if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
    475             continue;
    476 
    477           // only the target symbols defined in the concerned sections can make
    478           // the reference
    479           const LDSection* target_sect =
    480                 &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
    481           if (target_sect->kind() != LDFileFormat::TEXT &&
    482               target_sect->kind() != LDFileFormat::DATA &&
    483               target_sect->kind() != LDFileFormat::BSS)
    484             continue;
    485 
    486           // setup the reached list, if we first add the element to reached list
    487           // of this section, create an entry in ReachedSections map
    488           if (!add_first) {
    489             reached_sects = &pSectReachedListMap.getReachedList(*apply_sect);
    490             add_first = true;
    491           }
    492           reached_sects->insert(target_sect);
    493         }
    494         reached_sects = NULL;
    495         add_first = false;
    496         // 2. set up the reference from XXX to .ARM.exidx.XXX
    497         assert(apply_sect->getLink() != NULL);
    498         pSectReachedListMap.addReference(*apply_sect->getLink(), *apply_sect);
    499       }
    500     }
    501   }
    502 }
    503 
    504 bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD)
    505 {
    506   Fragment* frag = NULL;
    507   uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
    508   uint32_t size = pSD.getSection().size();
    509 
    510   llvm::StringRef region = pInput.memArea()->request(offset, size);
    511   if (region.size() == 0) {
    512     // If the input section's size is zero, we got a NULL region.
    513     // use a virtual fill fragment
    514     frag = new FillFragment(0x0, 0, 0);
    515   }
    516   else {
    517     frag = new RegionFragment(region);
    518   }
    519 
    520   ObjectBuilder::AppendFragment(*frag, pSD);
    521   return true;
    522 }
    523 
    524 ARMGOT& ARMGNULDBackend::getGOT()
    525 {
    526   assert(NULL != m_pGOT && "GOT section not exist");
    527   return *m_pGOT;
    528 }
    529 
    530 const ARMGOT& ARMGNULDBackend::getGOT() const
    531 {
    532   assert(NULL != m_pGOT && "GOT section not exist");
    533   return *m_pGOT;
    534 }
    535 
    536 ARMPLT& ARMGNULDBackend::getPLT()
    537 {
    538   assert(NULL != m_pPLT && "PLT section not exist");
    539   return *m_pPLT;
    540 }
    541 
    542 const ARMPLT& ARMGNULDBackend::getPLT() const
    543 {
    544   assert(NULL != m_pPLT && "PLT section not exist");
    545   return *m_pPLT;
    546 }
    547 
    548 OutputRelocSection& ARMGNULDBackend::getRelDyn()
    549 {
    550   assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
    551   return *m_pRelDyn;
    552 }
    553 
    554 const OutputRelocSection& ARMGNULDBackend::getRelDyn() const
    555 {
    556   assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
    557   return *m_pRelDyn;
    558 }
    559 
    560 OutputRelocSection& ARMGNULDBackend::getRelPLT()
    561 {
    562   assert(NULL != m_pRelPLT && ".rel.plt section not exist");
    563   return *m_pRelPLT;
    564 }
    565 
    566 const OutputRelocSection& ARMGNULDBackend::getRelPLT() const
    567 {
    568   assert(NULL != m_pRelPLT && ".rel.plt section not exist");
    569   return *m_pRelPLT;
    570 }
    571 
    572 ARMELFAttributeData& ARMGNULDBackend::getAttributeData()
    573 {
    574   assert(NULL != m_pAttrData && ".ARM.attributes section not exist");
    575   return *m_pAttrData;
    576 }
    577 
    578 const ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const
    579 {
    580   assert(NULL != m_pAttrData && ".ARM.attributes section not exist");
    581   return *m_pAttrData;
    582 }
    583 
    584 unsigned int
    585 ARMGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
    586 {
    587   const ELFFileFormat* file_format = getOutputFormat();
    588 
    589   if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
    590     if (config().options().hasNow())
    591       return SHO_RELRO_LAST;
    592     return SHO_DATA;
    593   }
    594 
    595   if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
    596     return SHO_PLT;
    597 
    598   if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
    599     // put ARM.exidx and ARM.extab in the same order of .eh_frame
    600     return SHO_EXCEPTION;
    601   }
    602 
    603   return SHO_UNDEFINED;
    604 }
    605 
    606 /// doRelax
    607 bool
    608 ARMGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished)
    609 {
    610   assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
    611 
    612   bool isRelaxed = false;
    613   ELFFileFormat* file_format = getOutputFormat();
    614   // check branch relocs and create the related stubs if needed
    615   Module::obj_iterator input, inEnd = pModule.obj_end();
    616   for (input = pModule.obj_begin(); input != inEnd; ++input) {
    617     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    618     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
    619       if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
    620         continue;
    621       RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
    622       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
    623         Relocation* relocation = llvm::cast<Relocation>(reloc);
    624 
    625         switch (relocation->type()) {
    626           case llvm::ELF::R_ARM_PC24:
    627           case llvm::ELF::R_ARM_CALL:
    628           case llvm::ELF::R_ARM_JUMP24:
    629           case llvm::ELF::R_ARM_PLT32:
    630           case llvm::ELF::R_ARM_THM_CALL:
    631           case llvm::ELF::R_ARM_THM_XPC22:
    632           case llvm::ELF::R_ARM_THM_JUMP24:
    633           case llvm::ELF::R_ARM_THM_JUMP19: {
    634             // calculate the possible symbol value
    635             uint64_t sym_value = 0x0;
    636             LDSymbol* symbol = relocation->symInfo()->outSymbol();
    637             if (symbol->hasFragRef()) {
    638               uint64_t value = symbol->fragRef()->getOutputOffset();
    639               uint64_t addr =
    640                 symbol->fragRef()->frag()->getParent()->getSection().addr();
    641               sym_value = addr + value;
    642             }
    643             if (relocation->symInfo()->isGlobal() &&
    644                 (relocation->symInfo()->reserved() & ARMRelocator::ReservePLT) != 0x0) {
    645               // FIXME: we need to find out the address of the specific plt entry
    646               assert(file_format->hasPLT());
    647               sym_value = file_format->getPLT().addr();
    648             }
    649 
    650             Stub* stub = getStubFactory()->create(*relocation, // relocation
    651                                                   sym_value, // symbol value
    652                                                   pBuilder,
    653                                                   *getBRIslandFactory());
    654             if (NULL != stub) {
    655               switch (config().options().getStripSymbolMode()) {
    656                 case GeneralOptions::StripAllSymbols:
    657                 case GeneralOptions::StripLocals:
    658                   break;
    659                 default: {
    660                   // a stub symbol should be local
    661                   assert(NULL != stub->symInfo() && stub->symInfo()->isLocal());
    662                   LDSection& symtab = file_format->getSymTab();
    663                   LDSection& strtab = file_format->getStrTab();
    664 
    665                   // increase the size of .symtab and .strtab if needed
    666                   if (config().targets().is32Bits())
    667                     symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
    668                   else
    669                     symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym));
    670                   symtab.setInfo(symtab.getInfo() + 1);
    671                   strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
    672                 }
    673               } // end of switch
    674               isRelaxed = true;
    675             }
    676             break;
    677           }
    678           case llvm::ELF::R_ARM_V4BX:
    679             /* FIXME: bypass R_ARM_V4BX relocation now */
    680             break;
    681           default:
    682             break;
    683         } // end of switch
    684 
    685       } // for all relocations
    686     } // for all relocation section
    687   } // for all inputs
    688 
    689   // find the first fragment w/ invalid offset due to stub insertion
    690   Fragment* invalid = NULL;
    691   pFinished = true;
    692   for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
    693        island_end = getBRIslandFactory()->end(); island != island_end; ++island) {
    694     if ((*island).end() == file_format->getText().getSectionData()->end())
    695       break;
    696 
    697     Fragment* exit = (*island).end();
    698     if (((*island).offset() + (*island).size()) > exit->getOffset()) {
    699       invalid = exit;
    700       pFinished = false;
    701       break;
    702     }
    703   }
    704 
    705   // reset the offset of invalid fragments
    706   while (NULL != invalid) {
    707     invalid->setOffset(invalid->getPrevNode()->getOffset() +
    708                        invalid->getPrevNode()->size());
    709     invalid = invalid->getNextNode();
    710   }
    711 
    712   // reset the size of .text
    713   if (isRelaxed) {
    714     file_format->getText().setSize(
    715       file_format->getText().getSectionData()->back().getOffset() +
    716       file_format->getText().getSectionData()->back().size());
    717   }
    718   return isRelaxed;
    719 }
    720 
    721 /// initTargetStubs
    722 bool ARMGNULDBackend::initTargetStubs()
    723 {
    724   if (NULL != getStubFactory()) {
    725     getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep()));
    726     getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep()));
    727     getStubFactory()->addPrototype(
    728         new THMToTHMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
    729     getStubFactory()->addPrototype(
    730         new THMToARMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
    731     return true;
    732   }
    733   return false;
    734 }
    735 
    736 /// maxFwdBranchOffset
    737 int64_t ARMGNULDBackend::maxFwdBranchOffset()
    738 {
    739   if (m_pAttrData->usingThumb2()) {
    740     return THM2_MAX_FWD_BRANCH_OFFSET;
    741   } else {
    742     return THM_MAX_FWD_BRANCH_OFFSET;
    743   }
    744 }
    745 
    746 /// maxBwdBranchOffset
    747 int64_t ARMGNULDBackend::maxBwdBranchOffset()
    748 {
    749   if (m_pAttrData->usingThumb2()) {
    750     return THM2_MAX_BWD_BRANCH_OFFSET;
    751   } else {
    752     return THM_MAX_BWD_BRANCH_OFFSET;
    753   }
    754 }
    755 
    756 /// doCreateProgramHdrs - backend can implement this function to create the
    757 /// target-dependent segments
    758 void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule)
    759 {
    760    if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
    761      // make PT_ARM_EXIDX
    762      ELFSegment* exidx_seg = elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX,
    763                                                        llvm::ELF::PF_R);
    764      exidx_seg->append(m_pEXIDX);
    765    }
    766 }
    767 
    768 /// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
    769 /// function pointer access
    770 bool
    771 ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess(const LDSection& pSection)
    772     const
    773 {
    774   llvm::StringRef name(pSection.name());
    775   return !name.startswith(".ARM.exidx") &&
    776          !name.startswith(".ARM.extab") &&
    777          GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection);
    778 }
    779 
    780 
    781 namespace mcld {
    782 
    783 //===----------------------------------------------------------------------===//
    784 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
    785 ///
    786 TargetLDBackend* createARMLDBackend(const LinkerConfig& pConfig)
    787 {
    788   if (pConfig.targets().triple().isOSDarwin()) {
    789     assert(0 && "MachO linker is not supported yet");
    790     /**
    791     return new ARMMachOLDBackend(createARMMachOArchiveReader,
    792                                createARMMachOObjectReader,
    793                                createARMMachOObjectWriter);
    794     **/
    795   }
    796   if (pConfig.targets().triple().isOSWindows()) {
    797     assert(0 && "COFF linker is not supported yet");
    798     /**
    799     return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
    800                                createARMCOFFObjectReader,
    801                                createARMCOFFObjectWriter);
    802     **/
    803   }
    804   return new ARMGNULDBackend(pConfig, new ARMGNUInfo(pConfig.targets().triple()));
    805 }
    806 
    807 } // namespace of mcld
    808 
    809 //===----------------------------------------------------------------------===//
    810 // Force static initialization.
    811 //===----------------------------------------------------------------------===//
    812 extern "C" void MCLDInitializeARMLDBackend() {
    813   // Register the linker backend
    814   mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
    815   mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend);
    816 }
    817 
    818