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