Home | History | Annotate | Download | only in ARM
      1 //===- ARMRelocator.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 
     10 #include <mcld/LinkerConfig.h>
     11 #include <mcld/IRBuilder.h>
     12 #include <llvm/ADT/Twine.h>
     13 #include <llvm/Support/DataTypes.h>
     14 #include <llvm/Support/ELF.h>
     15 #include <llvm/Support/Host.h>
     16 #include <mcld/Support/MsgHandling.h>
     17 #include <mcld/LD/LDSymbol.h>
     18 #include <mcld/Object/ObjectBuilder.h>
     19 #include "ARMRelocator.h"
     20 #include "ARMRelocationFunctions.h"
     21 
     22 using namespace mcld;
     23 
     24 //===--------------------------------------------------------------------===//
     25 // Relocation Functions and Tables
     26 //===--------------------------------------------------------------------===//
     27 DECL_ARM_APPLY_RELOC_FUNCS
     28 
     29 /// the prototype of applying function
     30 typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
     31                                                ARMRelocator& pParent);
     32 
     33 // the table entry of applying functions
     34 struct ApplyFunctionTriple
     35 {
     36   ApplyFunctionType func;
     37   unsigned int type;
     38   const char* name;
     39 };
     40 
     41 // declare the table of applying functions
     42 static const ApplyFunctionTriple ApplyFunctions[] = {
     43   DECL_ARM_APPLY_RELOC_FUNC_PTRS
     44 };
     45 
     46 //===--------------------------------------------------------------------===//
     47 // ARMRelocator
     48 //===--------------------------------------------------------------------===//
     49 ARMRelocator::ARMRelocator(ARMGNULDBackend& pParent,
     50                            const LinkerConfig& pConfig)
     51   : Relocator(pConfig),
     52     m_Target(pParent) {
     53 }
     54 
     55 ARMRelocator::~ARMRelocator()
     56 {
     57 }
     58 
     59 Relocator::Result
     60 ARMRelocator::applyRelocation(Relocation& pRelocation)
     61 {
     62   Relocation::Type type = pRelocation.type();
     63   if (type > 130) { // 131-255 doesn't noted in ARM spec
     64     return Relocator::Unknown;
     65   }
     66 
     67   return ApplyFunctions[type].func(pRelocation, *this);
     68 }
     69 
     70 const char* ARMRelocator::getName(Relocator::Type pType) const
     71 {
     72   return ApplyFunctions[pType].name;
     73 }
     74 
     75 Relocator::Size ARMRelocator::getSize(Relocation::Type pType) const
     76 {
     77   return 32;
     78 }
     79 
     80 void ARMRelocator::addCopyReloc(ResolveInfo& pSym)
     81 {
     82   Relocation& rel_entry = *getTarget().getRelDyn().consumeEntry();
     83   rel_entry.setType(llvm::ELF::R_ARM_COPY);
     84   assert(pSym.outSymbol()->hasFragRef());
     85   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
     86   rel_entry.setSymInfo(&pSym);
     87 }
     88 
     89 /// defineSymbolForCopyReloc
     90 /// For a symbol needing copy relocation, define a copy symbol in the BSS
     91 /// section and all other reference to this symbol should refer to this
     92 /// copy.
     93 /// This is executed at scan relocation stage.
     94 LDSymbol&
     95 ARMRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
     96                                        const ResolveInfo& pSym)
     97 {
     98   // get or create corresponding BSS LDSection
     99   LDSection* bss_sect_hdr = NULL;
    100   ELFFileFormat* file_format = getTarget().getOutputFormat();
    101   if (ResolveInfo::ThreadLocal == pSym.type())
    102     bss_sect_hdr = &file_format->getTBSS();
    103   else
    104     bss_sect_hdr = &file_format->getBSS();
    105 
    106   // get or create corresponding BSS SectionData
    107   SectionData* bss_data = NULL;
    108   if (bss_sect_hdr->hasSectionData())
    109     bss_data = bss_sect_hdr->getSectionData();
    110   else
    111     bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
    112 
    113   // Determine the alignment by the symbol value
    114   // FIXME: here we use the largest alignment
    115   uint32_t addralign = config().targets().bitclass() / 8;
    116 
    117   // allocate space in BSS for the copy symbol
    118   Fragment* frag = new FillFragment(0x0, 1, pSym.size());
    119   uint64_t size = ObjectBuilder::AppendFragment(*frag,
    120                                                 *bss_data,
    121                                                 addralign);
    122   bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
    123 
    124   // change symbol binding to Global if it's a weak symbol
    125   ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
    126   if (binding == ResolveInfo::Weak)
    127     binding = ResolveInfo::Global;
    128 
    129   // Define the copy symbol in the bss section and resolve it
    130   LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    131                       pSym.name(),
    132                       (ResolveInfo::Type)pSym.type(),
    133                       ResolveInfo::Define,
    134                       binding,
    135                       pSym.size(),  // size
    136                       0x0,          // value
    137                       FragmentRef::Create(*frag, 0x0),
    138                       (ResolveInfo::Visibility)pSym.other());
    139 
    140   return *cpy_sym;
    141 }
    142 
    143 /// checkValidReloc - When we attempt to generate a dynamic relocation for
    144 /// ouput file, check if the relocation is supported by dynamic linker.
    145 void ARMRelocator::checkValidReloc(Relocation& pReloc) const
    146 {
    147   // If not PIC object, no relocation type is invalid
    148   if (!config().isCodeIndep())
    149     return;
    150 
    151   switch(pReloc.type()) {
    152     case llvm::ELF::R_ARM_RELATIVE:
    153     case llvm::ELF::R_ARM_COPY:
    154     case llvm::ELF::R_ARM_GLOB_DAT:
    155     case llvm::ELF::R_ARM_JUMP_SLOT:
    156     case llvm::ELF::R_ARM_ABS32:
    157     case llvm::ELF::R_ARM_ABS32_NOI:
    158     case llvm::ELF::R_ARM_PC24:
    159     case llvm::ELF::R_ARM_TLS_DTPMOD32:
    160     case llvm::ELF::R_ARM_TLS_DTPOFF32:
    161     case llvm::ELF::R_ARM_TLS_TPOFF32:
    162       break;
    163 
    164     default:
    165       error(diag::non_pic_relocation) << (int)pReloc.type()
    166                                       << pReloc.symInfo()->name();
    167       break;
    168   }
    169 }
    170 
    171 void
    172 ARMRelocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection)
    173 {
    174   // rsym - The relocation target symbol
    175   ResolveInfo* rsym = pReloc.symInfo();
    176 
    177   switch(pReloc.type()){
    178 
    179     // Set R_ARM_TARGET1 to R_ARM_ABS32
    180     // Ref: GNU gold 1.11 arm.cc, line 9892
    181     // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
    182     // or --target1-rel
    183     case llvm::ELF::R_ARM_TARGET1:
    184        pReloc.setType(llvm::ELF::R_ARM_ABS32);
    185     case llvm::ELF::R_ARM_ABS32:
    186     case llvm::ELF::R_ARM_ABS32_NOI: {
    187       // If buiding PIC object (shared library or PIC executable),
    188       // a dynamic relocations with RELATIVE type to this location is needed.
    189       // Reserve an entry in .rel.dyn
    190       if (config().isCodeIndep()) {
    191         getTarget().getRelDyn().reserveEntry();
    192         // set Rel bit
    193         rsym->setReserved(rsym->reserved() | ReserveRel);
    194         getTarget().checkAndSetHasTextRel(*pSection.getLink());
    195       }
    196       return;
    197     }
    198 
    199     case llvm::ELF::R_ARM_ABS16:
    200     case llvm::ELF::R_ARM_ABS12:
    201     case llvm::ELF::R_ARM_THM_ABS5:
    202     case llvm::ELF::R_ARM_ABS8:
    203     case llvm::ELF::R_ARM_BASE_ABS:
    204     case llvm::ELF::R_ARM_MOVW_ABS_NC:
    205     case llvm::ELF::R_ARM_MOVT_ABS:
    206     case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
    207     case llvm::ELF::R_ARM_THM_MOVT_ABS: {
    208       // PIC code should not contain these kinds of relocation
    209       if (config().isCodeIndep()) {
    210         error(diag::non_pic_relocation) << (int)pReloc.type()
    211                                         << pReloc.symInfo()->name();
    212       }
    213       return;
    214     }
    215     case llvm::ELF::R_ARM_GOTOFF32:
    216     case llvm::ELF::R_ARM_GOTOFF12: {
    217       // FIXME: A GOT section is needed
    218       return;
    219     }
    220 
    221     // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
    222     // Ref: GNU gold 1.11 arm.cc, line 9892
    223     // FIXME: R_ARM_TARGET2 should be set by option --target2
    224     case llvm::ELF::R_ARM_TARGET2:
    225       pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
    226     case llvm::ELF::R_ARM_GOT_BREL:
    227     case llvm::ELF::R_ARM_GOT_PREL: {
    228       // A GOT entry is needed for these relocation type.
    229       // return if we already create GOT for this symbol
    230       if (rsym->reserved() & (ReserveGOT | GOTRel))
    231         return;
    232       getTarget().getGOT().reserveGOT();
    233       // If building PIC object, a dynamic relocation with
    234       // type RELATIVE is needed to relocate this GOT entry.
    235       // Reserve an entry in .rel.dyn
    236       if (config().isCodeIndep()) {
    237         // create .rel.dyn section if not exist
    238         getTarget().getRelDyn().reserveEntry();
    239         // set GOTRel bit
    240         rsym->setReserved(rsym->reserved() | 0x4u);
    241         return;
    242       }
    243       // set GOT bit
    244       rsym->setReserved(rsym->reserved() | 0x2u);
    245       return;
    246     }
    247 
    248     case llvm::ELF::R_ARM_BASE_PREL: {
    249       // FIXME: Currently we only support R_ARM_BASE_PREL against
    250       // symbol _GLOBAL_OFFSET_TABLE_
    251       if (rsym != getTarget().getGOTSymbol()->resolveInfo())
    252         fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
    253                                      << "mclinker (at) googlegroups.com";
    254       return;
    255     }
    256     case llvm::ELF::R_ARM_COPY:
    257     case llvm::ELF::R_ARM_GLOB_DAT:
    258     case llvm::ELF::R_ARM_JUMP_SLOT:
    259     case llvm::ELF::R_ARM_RELATIVE: {
    260       // These are relocation type for dynamic linker, shold not
    261       // appear in object file.
    262       fatal(diag::dynamic_relocation) << (int)pReloc.type();
    263       break;
    264     }
    265     default: {
    266       break;
    267     }
    268   } // end switch
    269 }
    270 
    271 void ARMRelocator::scanGlobalReloc(Relocation& pReloc,
    272                                    IRBuilder& pBuilder,
    273                                    const LDSection& pSection)
    274 {
    275   // rsym - The relocation target symbol
    276   ResolveInfo* rsym = pReloc.symInfo();
    277 
    278   switch(pReloc.type()) {
    279 
    280     // Set R_ARM_TARGET1 to R_ARM_ABS32
    281     // Ref: GNU gold 1.11 arm.cc, line 9892
    282     // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
    283     // or --target1-rel
    284     case llvm::ELF::R_ARM_TARGET1:
    285       pReloc.setType(llvm::ELF::R_ARM_ABS32);
    286     case llvm::ELF::R_ARM_ABS32:
    287     case llvm::ELF::R_ARM_ABS16:
    288     case llvm::ELF::R_ARM_ABS12:
    289     case llvm::ELF::R_ARM_THM_ABS5:
    290     case llvm::ELF::R_ARM_ABS8:
    291     case llvm::ELF::R_ARM_BASE_ABS:
    292     case llvm::ELF::R_ARM_MOVW_ABS_NC:
    293     case llvm::ELF::R_ARM_MOVT_ABS:
    294     case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
    295     case llvm::ELF::R_ARM_THM_MOVT_ABS:
    296     case llvm::ELF::R_ARM_ABS32_NOI: {
    297       // Absolute relocation type, symbol may needs PLT entry or
    298       // dynamic relocation entry
    299       if (getTarget().symbolNeedsPLT(*rsym)) {
    300         // create plt for this symbol if it does not have one
    301         if (!(rsym->reserved() & ReservePLT)){
    302           // Symbol needs PLT entry, we need to reserve a PLT entry
    303           // and the corresponding GOT and dynamic relocation entry
    304           // in .got and .rel.plt. (GOT entry will be reserved simultaneously
    305           // when calling ARMPLT->reserveEntry())
    306           getTarget().getPLT().reserveEntry();
    307           getTarget().getRelPLT().reserveEntry();
    308           // set PLT bit
    309           rsym->setReserved(rsym->reserved() | ReservePLT);
    310         }
    311       }
    312 
    313       if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
    314         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
    315         getTarget().getRelDyn().reserveEntry();
    316         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
    317           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
    318           addCopyReloc(*cpy_sym.resolveInfo());
    319         }
    320         else {
    321           checkValidReloc(pReloc);
    322           // set Rel bit
    323           rsym->setReserved(rsym->reserved() | ReserveRel);
    324           getTarget().checkAndSetHasTextRel(*pSection.getLink());
    325         }
    326       }
    327       return;
    328     }
    329 
    330     case llvm::ELF::R_ARM_GOTOFF32:
    331     case llvm::ELF::R_ARM_GOTOFF12: {
    332       // FIXME: A GOT section is needed
    333       return;
    334     }
    335 
    336     case llvm::ELF::R_ARM_BASE_PREL:
    337     case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
    338     case llvm::ELF::R_ARM_THM_MOVW_BREL:
    339     case llvm::ELF::R_ARM_THM_MOVT_BREL:
    340       // FIXME: Currently we only support these relocations against
    341       // symbol _GLOBAL_OFFSET_TABLE_
    342       if (rsym != getTarget().getGOTSymbol()->resolveInfo()) {
    343         fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
    344                                      << "mclinker (at) googlegroups.com";
    345       }
    346     case llvm::ELF::R_ARM_REL32:
    347     case llvm::ELF::R_ARM_LDR_PC_G0:
    348     case llvm::ELF::R_ARM_SBREL32:
    349     case llvm::ELF::R_ARM_THM_PC8:
    350     case llvm::ELF::R_ARM_MOVW_PREL_NC:
    351     case llvm::ELF::R_ARM_MOVT_PREL:
    352     case llvm::ELF::R_ARM_THM_MOVW_PREL_NC:
    353     case llvm::ELF::R_ARM_THM_MOVT_PREL:
    354     case llvm::ELF::R_ARM_THM_ALU_PREL_11_0:
    355     case llvm::ELF::R_ARM_THM_PC12:
    356     case llvm::ELF::R_ARM_REL32_NOI:
    357     case llvm::ELF::R_ARM_ALU_PC_G0_NC:
    358     case llvm::ELF::R_ARM_ALU_PC_G0:
    359     case llvm::ELF::R_ARM_ALU_PC_G1_NC:
    360     case llvm::ELF::R_ARM_ALU_PC_G1:
    361     case llvm::ELF::R_ARM_ALU_PC_G2:
    362     case llvm::ELF::R_ARM_LDR_PC_G1:
    363     case llvm::ELF::R_ARM_LDR_PC_G2:
    364     case llvm::ELF::R_ARM_LDRS_PC_G0:
    365     case llvm::ELF::R_ARM_LDRS_PC_G1:
    366     case llvm::ELF::R_ARM_LDRS_PC_G2:
    367     case llvm::ELF::R_ARM_LDC_PC_G0:
    368     case llvm::ELF::R_ARM_LDC_PC_G1:
    369     case llvm::ELF::R_ARM_LDC_PC_G2:
    370     case llvm::ELF::R_ARM_ALU_SB_G0_NC:
    371     case llvm::ELF::R_ARM_ALU_SB_G0:
    372     case llvm::ELF::R_ARM_ALU_SB_G1_NC:
    373     case llvm::ELF::R_ARM_ALU_SB_G1:
    374     case llvm::ELF::R_ARM_ALU_SB_G2:
    375     case llvm::ELF::R_ARM_LDR_SB_G0:
    376     case llvm::ELF::R_ARM_LDR_SB_G1:
    377     case llvm::ELF::R_ARM_LDR_SB_G2:
    378     case llvm::ELF::R_ARM_LDRS_SB_G0:
    379     case llvm::ELF::R_ARM_LDRS_SB_G1:
    380     case llvm::ELF::R_ARM_LDRS_SB_G2:
    381     case llvm::ELF::R_ARM_LDC_SB_G0:
    382     case llvm::ELF::R_ARM_LDC_SB_G1:
    383     case llvm::ELF::R_ARM_LDC_SB_G2:
    384     case llvm::ELF::R_ARM_MOVW_BREL_NC:
    385     case llvm::ELF::R_ARM_MOVT_BREL:
    386     case llvm::ELF::R_ARM_MOVW_BREL: {
    387       // Relative addressing relocation, may needs dynamic relocation
    388       if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
    389         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
    390         getTarget().getRelDyn().reserveEntry();
    391         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
    392           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
    393           addCopyReloc(*cpy_sym.resolveInfo());
    394         }
    395         else {
    396           checkValidReloc(pReloc);
    397           // set Rel bit
    398           rsym->setReserved(rsym->reserved() | ReserveRel);
    399           getTarget().checkAndSetHasTextRel(*pSection.getLink());
    400         }
    401       }
    402       return;
    403     }
    404 
    405     case llvm::ELF::R_ARM_PC24:
    406     case llvm::ELF::R_ARM_THM_CALL:
    407     case llvm::ELF::R_ARM_PLT32:
    408     case llvm::ELF::R_ARM_CALL:
    409     case llvm::ELF::R_ARM_JUMP24:
    410     case llvm::ELF::R_ARM_THM_JUMP24:
    411     case llvm::ELF::R_ARM_SBREL31:
    412     case llvm::ELF::R_ARM_PREL31:
    413     case llvm::ELF::R_ARM_THM_JUMP19:
    414     case llvm::ELF::R_ARM_THM_JUMP6:
    415     case llvm::ELF::R_ARM_THM_JUMP11:
    416     case llvm::ELF::R_ARM_THM_JUMP8: {
    417       // These are branch relocation (except PREL31)
    418       // A PLT entry is needed when building shared library
    419 
    420       // return if we already create plt for this symbol
    421       if (rsym->reserved() & ReservePLT)
    422         return;
    423 
    424       // if the symbol's value can be decided at link time, then no need plt
    425       if (getTarget().symbolFinalValueIsKnown(*rsym))
    426         return;
    427 
    428       // if symbol is defined in the ouput file and it's not
    429       // preemptible, no need plt
    430       if (rsym->isDefine() && !rsym->isDyn() &&
    431           !getTarget().isSymbolPreemptible(*rsym)) {
    432         return;
    433       }
    434 
    435       // Symbol needs PLT entry, we need to reserve a PLT entry
    436       // and the corresponding GOT and dynamic relocation entry
    437       // in .got and .rel.plt. (GOT entry will be reserved simultaneously
    438       // when calling ARMPLT->reserveEntry())
    439       getTarget().getPLT().reserveEntry();
    440       getTarget().getRelPLT().reserveEntry();
    441       // set PLT bit
    442       rsym->setReserved(rsym->reserved() | ReservePLT);
    443       return;
    444     }
    445 
    446     // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
    447     // Ref: GNU gold 1.11 arm.cc, line 9892
    448     // FIXME: R_ARM_TARGET2 should be set by option --target2
    449     case llvm::ELF::R_ARM_TARGET2:
    450       pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
    451     case llvm::ELF::R_ARM_GOT_BREL:
    452     case llvm::ELF::R_ARM_GOT_ABS:
    453     case llvm::ELF::R_ARM_GOT_PREL: {
    454       // Symbol needs GOT entry, reserve entry in .got
    455       // return if we already create GOT for this symbol
    456       if (rsym->reserved() & (ReserveGOT | GOTRel))
    457         return;
    458       getTarget().getGOT().reserveGOT();
    459       // if the symbol cannot be fully resolved at link time, then we need a
    460       // dynamic relocation
    461       if (!getTarget().symbolFinalValueIsKnown(*rsym)) {
    462         getTarget().getRelDyn().reserveEntry();
    463         // set GOTRel bit
    464         rsym->setReserved(rsym->reserved() | GOTRel);
    465         return;
    466       }
    467       // set GOT bit
    468       rsym->setReserved(rsym->reserved() | ReserveGOT);
    469       return;
    470     }
    471 
    472     case llvm::ELF::R_ARM_COPY:
    473     case llvm::ELF::R_ARM_GLOB_DAT:
    474     case llvm::ELF::R_ARM_JUMP_SLOT:
    475     case llvm::ELF::R_ARM_RELATIVE: {
    476       // These are relocation type for dynamic linker, shold not
    477       // appear in object file.
    478       fatal(diag::dynamic_relocation) << (int)pReloc.type();
    479       break;
    480     }
    481     default: {
    482       break;
    483     }
    484   } // end switch
    485 }
    486 
    487 void ARMRelocator::scanRelocation(Relocation& pReloc,
    488                                   IRBuilder& pBuilder,
    489                                   Module& pModule,
    490                                   LDSection& pSection)
    491 {
    492   // rsym - The relocation target symbol
    493   ResolveInfo* rsym = pReloc.symInfo();
    494   assert(NULL != rsym &&
    495          "ResolveInfo of relocation not set while scanRelocation");
    496 
    497   pReloc.updateAddend();
    498   assert(NULL != pSection.getLink());
    499   if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
    500     return;
    501 
    502   // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
    503   // entries should be created.
    504   // FIXME: Below judgements concern nothing about TLS related relocation
    505 
    506   // rsym is local
    507   if (rsym->isLocal())
    508     scanLocalReloc(pReloc, pSection);
    509 
    510   // rsym is external
    511   else
    512     scanGlobalReloc(pReloc, pBuilder, pSection);
    513 
    514   // check if we shoule issue undefined reference for the relocation target
    515   // symbol
    516   if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
    517     fatal(diag::undefined_reference) << rsym->name();
    518 }
    519 
    520 //===--------------------------------------------------------------------===//
    521 // non-member functions
    522 //===--------------------------------------------------------------------===//
    523 static Relocator::DWord getThumbBit(const Relocation& pReloc)
    524 {
    525   // Set thumb bit if
    526   // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
    527   Relocator::DWord thumbBit =
    528        ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
    529         (pReloc.symInfo()->type() == ResolveInfo::Function) &&
    530         ((pReloc.symValue() & 0x1) != 0))?
    531         1:0;
    532   return thumbBit;
    533 }
    534 
    535 //=========================================//
    536 // Relocation helper function              //
    537 //=========================================//
    538 
    539 // Using uint64_t to make sure those complicate operations won't cause
    540 // undefined behavior.
    541 static
    542 uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
    543 {
    544   assert(pOri_width <= 64);
    545   if (pOri_width == 64)
    546     return pVal;
    547   uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width);
    548   pVal &= mask;
    549   // Reverse sign bit, then subtract sign bit.
    550   uint64_t sign_bit = 1 << (pOri_width - 1);
    551   return (pVal ^ sign_bit) - sign_bit;
    552 }
    553 
    554 static
    555 uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
    556 {
    557   return (pA & ~pMask) | (pB & pMask) ;
    558 }
    559 
    560 // Check if symbol can use relocation R_ARM_RELATIVE
    561 static bool
    562 helper_use_relative_reloc(const ResolveInfo& pSym,
    563                           const ARMRelocator& pFactory)
    564 {
    565   // if symbol is dynamic or undefine or preemptible
    566   if (pSym.isDyn() ||
    567       pSym.isUndef() ||
    568       pFactory.getTarget().isSymbolPreemptible(pSym))
    569     return false;
    570   return true;
    571 }
    572 
    573 // Strip LSB (THUMB bit) if "S" is a THUMB target.
    574 static inline void helper_clear_thumb_bit(ARMRelocator::DWord& pValue)
    575 {
    576   pValue &= (~0x1);
    577 }
    578 
    579 static
    580 ARMGOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
    581                                      ARMRelocator& pParent)
    582 {
    583   // rsym - The relocation target symbol
    584   ResolveInfo* rsym = pReloc.symInfo();
    585   ARMGNULDBackend& ld_backend = pParent.getTarget();
    586 
    587   ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
    588   if (NULL == got_entry) {
    589     got_entry = ld_backend.getGOT().consumeGOT();
    590     pParent.getSymGOTMap().record(*rsym, *got_entry);
    591     // If we first get this GOT entry, we should initialize it.
    592     if (rsym->reserved() & ARMRelocator::ReserveGOT) {
    593       // No corresponding dynamic relocation, initialize to the symbol value.
    594       got_entry->setValue(pReloc.symValue());
    595     }
    596     else if (rsym->reserved() & ARMRelocator::GOTRel) {
    597 
    598       // Initialize corresponding dynamic relocation.
    599       Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
    600       if ( rsym->isLocal() ||
    601           helper_use_relative_reloc(*rsym, pParent)) {
    602         // Initialize got entry to target symbol address
    603         got_entry->setValue(pReloc.symValue());
    604         rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
    605         rel_entry.setSymInfo(0);
    606       }
    607       else {
    608         // Initialize got entry to 0 for corresponding dynamic relocation.
    609         got_entry->setValue(0);
    610         rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
    611         rel_entry.setSymInfo(rsym);
    612       }
    613       rel_entry.targetRef().assign(*got_entry);
    614     }
    615     else {
    616       fatal(diag::reserve_entry_number_mismatch_got);
    617     }
    618   }
    619   return *got_entry;
    620 }
    621 
    622 static
    623 ARMRelocator::Address helper_GOT_ORG(ARMRelocator& pParent)
    624 {
    625   return pParent.getTarget().getGOT().addr();
    626 }
    627 
    628 
    629 static
    630 ARMRelocator::Address helper_GOT(Relocation& pReloc, ARMRelocator& pParent)
    631 {
    632   ARMGOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
    633   return helper_GOT_ORG(pParent) + got_entry.getOffset();
    634 }
    635 
    636 
    637 static
    638 ARMPLT1& helper_get_PLT_and_init(Relocation& pReloc, ARMRelocator& pParent)
    639 {
    640   // rsym - The relocation target symbol
    641   ResolveInfo* rsym = pReloc.symInfo();
    642   ARMGNULDBackend& ld_backend = pParent.getTarget();
    643 
    644   ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
    645   if (NULL != plt_entry)
    646     return *plt_entry;
    647 
    648   plt_entry = ld_backend.getPLT().consume();
    649   pParent.getSymPLTMap().record(*rsym, *plt_entry);
    650 
    651   // If we first get this PLT entry, we should initialize it.
    652   if (rsym->reserved() & ARMRelocator::ReservePLT) {
    653     ARMGOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
    654     assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
    655     gotplt_entry = ld_backend.getGOT().consumeGOTPLT();
    656     pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
    657 
    658     // Initialize corresponding dynamic relocation.
    659     Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
    660     rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
    661     rel_entry.targetRef().assign(*gotplt_entry);
    662     rel_entry.setSymInfo(rsym);
    663   }
    664   else {
    665     fatal(diag::reserve_entry_number_mismatch_plt);
    666   }
    667 
    668   return *plt_entry;
    669 }
    670 
    671 static
    672 ARMRelocator::Address helper_PLT_ORG(ARMRelocator& pParent)
    673 {
    674   return pParent.getTarget().getPLT().addr();
    675 }
    676 
    677 
    678 static
    679 ARMRelocator::Address helper_PLT(Relocation& pReloc, ARMRelocator& pParent)
    680 {
    681   ARMPLT1& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
    682   return helper_PLT_ORG(pParent) + plt_entry.getOffset();
    683 }
    684 
    685 // Get an relocation entry in .rel.dyn and set its type to pType,
    686 // its FragmentRef to pReloc->targetFrag() and its ResolveInfo to
    687 // pReloc->symInfo()
    688 static
    689 void helper_DynRel(Relocation& pReloc,
    690                    ARMRelocator::Type pType,
    691                    ARMRelocator& pParent)
    692 {
    693   // rsym - The relocation target symbol
    694   ResolveInfo* rsym = pReloc.symInfo();
    695   ARMGNULDBackend& ld_backend = pParent.getTarget();
    696 
    697   Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
    698   rel_entry.setType(pType);
    699   rel_entry.targetRef() = pReloc.targetRef();
    700 
    701   if (pType == llvm::ELF::R_ARM_RELATIVE)
    702     rel_entry.setSymInfo(0);
    703   else
    704     rel_entry.setSymInfo(rsym);
    705 }
    706 
    707 static ARMRelocator::DWord
    708 helper_extract_movw_movt_addend(ARMRelocator::DWord pTarget)
    709 {
    710   // imm16: [19-16][11-0]
    711   return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
    712                             16);
    713 }
    714 
    715 static ARMRelocator::DWord
    716 helper_insert_val_movw_movt_inst(ARMRelocator::DWord pTarget,
    717                                  ARMRelocator::DWord pImm)
    718 {
    719   // imm16: [19-16][11-0]
    720   pTarget &= 0xfff0f000U;
    721   pTarget |= pImm & 0x0fffU;
    722   pTarget |= (pImm & 0xf000U) << 4;
    723   return pTarget;
    724 }
    725 
    726 static ARMRelocator::DWord
    727 helper_extract_thumb_movw_movt_addend(ARMRelocator::DWord pValue)
    728 {
    729   // imm16: [19-16][26][14-12][7-0]
    730   return helper_sign_extend((((pValue >> 4) & 0xf000U) |
    731                              ((pValue >> 15) & 0x0800U) |
    732                              ((pValue >> 4) & 0x0700U) |
    733                              (pValue& 0x00ffU)),
    734                             16);
    735 }
    736 
    737 static ARMRelocator::DWord
    738 helper_insert_val_thumb_movw_movt_inst(ARMRelocator::DWord pValue,
    739                                        ARMRelocator::DWord pImm)
    740 {
    741   // imm16: [19-16][26][14-12][7-0]
    742   pValue &= 0xfbf08f00U;
    743   pValue |= (pImm & 0xf000U) << 4;
    744   pValue |= (pImm & 0x0800U) << 15;
    745   pValue |= (pImm & 0x0700U) << 4;
    746   pValue |= (pImm & 0x00ffU);
    747   return pValue;
    748 }
    749 
    750 static ARMRelocator::DWord
    751 helper_thumb32_branch_offset(ARMRelocator::DWord pUpper16,
    752                              ARMRelocator::DWord pLower16)
    753 {
    754   ARMRelocator::DWord s = (pUpper16 & (1U << 10)) >> 10,        // 26 bit
    755                            u  = pUpper16 & 0x3ffU,              // 25-16
    756                            l  = pLower16 & 0x7ffU,              // 10-0
    757                            j1 = (pLower16 & (1U << 13)) >> 13,  // 13
    758                            j2 = (pLower16 & (1U << 11)) >> 11;  // 11
    759   ARMRelocator::DWord i1 = j1 ^ s? 0: 1,
    760                               i2 = j2 ^ s? 0: 1;
    761 
    762   // [31-25][24][23][22][21-12][11-1][0]
    763   //      0   s  i1  i2      u     l  0
    764   return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
    765                             (u << 12) | (l << 1),
    766                             25);
    767 }
    768 
    769 static ARMRelocator::DWord
    770 helper_thumb32_branch_upper(ARMRelocator::DWord pUpper16,
    771                             ARMRelocator::DWord pOffset)
    772 {
    773   uint32_t sign = ((pOffset & 0x80000000U) >> 31);
    774   return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
    775 }
    776 
    777 static ARMRelocator::DWord
    778 helper_thumb32_branch_lower(ARMRelocator::DWord pLower16,
    779                             ARMRelocator::DWord pOffset)
    780 {
    781   uint32_t sign = ((pOffset & 0x80000000U) >> 31);
    782   return ((pLower16 & ~0x2fffU) |
    783           ((((pOffset >> 23) & 1) ^ !sign) << 13) |
    784           ((((pOffset >> 22) & 1) ^ !sign) << 11) |
    785           ((pOffset >> 1) & 0x7ffU));
    786 }
    787 
    788 // Return true if overflow
    789 static bool
    790 helper_check_signed_overflow(ARMRelocator::DWord pValue,
    791                              unsigned bits)
    792 {
    793   int32_t signed_val = static_cast<int32_t>(pValue);
    794   int32_t max = (1 << (bits - 1)) - 1;
    795   int32_t min = -(1 << (bits - 1));
    796   if (signed_val > max || signed_val < min) {
    797     return true;
    798   } else {
    799     return false;
    800   }
    801 }
    802 
    803 
    804 //=========================================//
    805 // Each relocation function implementation //
    806 //=========================================//
    807 
    808 // R_ARM_NONE
    809 ARMRelocator::Result none(Relocation& pReloc, ARMRelocator& pParent)
    810 {
    811   return ARMRelocator::OK;
    812 }
    813 
    814 // R_ARM_ABS32: (S + A) | T
    815 ARMRelocator::Result abs32(Relocation& pReloc, ARMRelocator& pParent)
    816 {
    817   ResolveInfo* rsym = pReloc.symInfo();
    818   ARMRelocator::DWord T = getThumbBit(pReloc);
    819   ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
    820   ARMRelocator::DWord S = pReloc.symValue();
    821   if (T != 0x0)
    822     helper_clear_thumb_bit(S);
    823 
    824   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
    825 
    826   // If the flag of target section is not ALLOC, we will not scan this relocation
    827   // but perform static relocation. (e.g., applying .debug section)
    828   if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
    829     pReloc.target() = (S + A) | T;
    830     return ARMRelocator::OK;
    831   }
    832 
    833   // A local symbol may need REL Type dynamic relocation
    834   if (rsym->isLocal() && (rsym->reserved() & ARMRelocator::ReserveRel)) {
    835     helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
    836     pReloc.target() = (S + A) | T ;
    837     return ARMRelocator::OK;
    838   }
    839 
    840   // An external symbol may need PLT and dynamic relocation
    841   if (!rsym->isLocal()) {
    842     if (rsym->reserved() & ARMRelocator::ReservePLT) {
    843       S = helper_PLT(pReloc, pParent);
    844       T = 0 ; // PLT is not thumb
    845     }
    846     // If we generate a dynamic relocation (except R_ARM_RELATIVE)
    847     // for a place, we should not perform static relocation on it
    848     // in order to keep the addend store in the place correct.
    849     if (rsym->reserved() & ARMRelocator::ReserveRel) {
    850       if (helper_use_relative_reloc(*rsym, pParent)) {
    851         helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
    852       }
    853       else {
    854         helper_DynRel(pReloc, pReloc.type(), pParent);
    855         return ARMRelocator::OK;
    856       }
    857     }
    858   }
    859 
    860 
    861   // perform static relocation
    862   pReloc.target() = (S + A) | T;
    863   return ARMRelocator::OK;
    864 }
    865 
    866 // R_ARM_REL32: ((S + A) | T) - P
    867 ARMRelocator::Result rel32(Relocation& pReloc, ARMRelocator& pParent)
    868 {
    869   // perform static relocation
    870   ARMRelocator::Address S = pReloc.symValue();
    871   ARMRelocator::DWord   T = getThumbBit(pReloc);
    872   ARMRelocator::DWord   A = pReloc.target() + pReloc.addend();
    873   if (T != 0x0)
    874     helper_clear_thumb_bit(S);
    875 
    876   // An external symbol may need PLT (this reloc is from stub)
    877   if (!pReloc.symInfo()->isLocal()) {
    878     if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
    879       S = helper_PLT(pReloc, pParent);
    880       T = 0;  // PLT is not thumb.
    881     }
    882   }
    883 
    884   // perform relocation
    885   pReloc.target() = ((S + A) | T) - pReloc.place();
    886 
    887   return ARMRelocator::OK;
    888 }
    889 
    890 // R_ARM_BASE_PREL: B(S) + A - P
    891 ARMRelocator::Result base_prel(Relocation& pReloc, ARMRelocator& pParent)
    892 {
    893   // perform static relocation
    894   ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
    895   pReloc.target() = pReloc.symValue() + A - pReloc.place();
    896   return ARMRelocator::OK;
    897 }
    898 
    899 // R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
    900 ARMRelocator::Result gotoff32(Relocation& pReloc, ARMRelocator& pParent)
    901 {
    902   ARMRelocator::DWord T = getThumbBit(pReloc);
    903   ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
    904   ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent);
    905   ARMRelocator::Address S = pReloc.symValue();
    906   if (T != 0x0)
    907     helper_clear_thumb_bit(S);
    908 
    909   pReloc.target() = ((S + A) | T) - GOT_ORG;
    910   return ARMRelocator::OK;
    911 }
    912 
    913 // R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
    914 ARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent)
    915 {
    916   if (!(pReloc.symInfo()->reserved() &
    917       (ARMRelocator::ReserveGOT | ARMRelocator::GOTRel))) {
    918     return ARMRelocator::BadReloc;
    919   }
    920   ARMRelocator::Address GOT_S   = helper_GOT(pReloc, pParent);
    921   ARMRelocator::DWord   A       = pReloc.target() + pReloc.addend();
    922   ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent);
    923   // Apply relocation.
    924   pReloc.target() = GOT_S + A - GOT_ORG;
    925   return ARMRelocator::OK;
    926 }
    927 
    928 // R_ARM_GOT_PREL: GOT(S) + A - P
    929 ARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent)
    930 {
    931   if (!(pReloc.symInfo()->reserved() &
    932       (ARMRelocator::ReserveGOT | ARMRelocator::GOTRel))) {
    933     return ARMRelocator::BadReloc;
    934   }
    935   ARMRelocator::Address GOT_S   = helper_GOT(pReloc, pParent);
    936   ARMRelocator::DWord   A       = pReloc.target() + pReloc.addend();
    937   ARMRelocator::Address P = pReloc.place();
    938 
    939   // Apply relocation.
    940   pReloc.target() = GOT_S + A - P;
    941   return ARMRelocator::OK;
    942 }
    943 
    944 // R_ARM_THM_JUMP11: S + A - P
    945 ARMRelocator::Result thm_jump11(Relocation& pReloc, ARMRelocator& pParent)
    946 {
    947   ARMRelocator::DWord P = pReloc.place();
    948   ARMRelocator::DWord A =
    949                        helper_sign_extend((pReloc.target() & 0x07ff) << 1, 11) +
    950                        pReloc.addend();
    951   // S depends on PLT exists or not
    952   ARMRelocator::Address S = pReloc.symValue();
    953   if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)
    954     S = helper_PLT(pReloc, pParent);
    955 
    956   ARMRelocator::DWord X = S + A - P;
    957   if (helper_check_signed_overflow(X, 11))
    958     return ARMRelocator::Overflow;
    959   //                    Make sure the Imm is 0.          Result Mask.
    960   pReloc.target() = (pReloc.target() & 0xFFFFF800u) | ((X & 0x0FFEu) >> 1);
    961   return ARMRelocator::OK;
    962 }
    963 
    964 // R_ARM_PC24: ((S + A) | T) - P
    965 // R_ARM_PLT32: ((S + A) | T) - P
    966 // R_ARM_JUMP24: ((S + A) | T) - P
    967 // R_ARM_CALL: ((S + A) | T) - P
    968 ARMRelocator::Result call(Relocation& pReloc, ARMRelocator& pParent)
    969 {
    970   // If target is undefined weak symbol, we only need to jump to the
    971   // next instruction unless it has PLT entry. Rewrite instruction
    972   // to NOP.
    973   if (pReloc.symInfo()->isWeak() &&
    974       pReloc.symInfo()->isUndef() &&
    975       !pReloc.symInfo()->isDyn() &&
    976       !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) {
    977     // change target to NOP : mov r0, r0
    978     pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
    979     return ARMRelocator::OK;
    980   }
    981 
    982   ARMRelocator::DWord   T = getThumbBit(pReloc);
    983   ARMRelocator::DWord   A =
    984     helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) +
    985     pReloc.addend();
    986   ARMRelocator::Address P = pReloc.place();
    987   ARMRelocator::Address S = pReloc.symValue();
    988   if (T != 0x0)
    989     helper_clear_thumb_bit(S);
    990 
    991   // S depends on PLT exists or not
    992   if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
    993     S = helper_PLT(pReloc, pParent);
    994     T = 0;  // PLT is not thumb.
    995   }
    996 
    997   // At this moment (after relaxation), if the jump target is thumb instruction,
    998   // switch mode is needed, rewrite the instruction to BLX
    999   // FIXME: check if we can use BLX instruction (check from .ARM.attribute
   1000   // CPU ARCH TAG, which should be ARMv5 or above)
   1001   if (T != 0) {
   1002     // cannot rewrite to blx for R_ARM_JUMP24
   1003     if (pReloc.type() == llvm::ELF::R_ARM_JUMP24)
   1004       return ARMRelocator::BadReloc;
   1005     if (pReloc.type() == llvm::ELF::R_ARM_PC24)
   1006       return ARMRelocator::BadReloc;
   1007 
   1008     pReloc.target() = (pReloc.target() & 0xffffff) |
   1009                       0xfa000000 |
   1010                       (((S + A - P) & 2) << 23);
   1011   }
   1012 
   1013   ARMRelocator::DWord X = ((S + A) | T) - P;
   1014   // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
   1015   if (helper_check_signed_overflow(X, 26))
   1016     return ARMRelocator::Overflow;
   1017   //                    Make sure the Imm is 0.          Result Mask.
   1018   pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
   1019   return ARMRelocator::OK;
   1020 }
   1021 
   1022 // R_ARM_THM_CALL: ((S + A) | T) - P
   1023 // R_ARM_THM_JUMP24: ((S + A) | T) - P
   1024 ARMRelocator::Result thm_call(Relocation& pReloc, ARMRelocator& pParent)
   1025 {
   1026   // If target is undefined weak symbol, we only need to jump to the
   1027   // next instruction unless it has PLT entry. Rewrite instruction
   1028   // to NOP.
   1029   if (pReloc.symInfo()->isWeak() &&
   1030       pReloc.symInfo()->isUndef() &&
   1031       !pReloc.symInfo()->isDyn() &&
   1032       !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) {
   1033     pReloc.target() = (0xe000U << 16) | 0xbf00U;
   1034     return ARMRelocator::OK;
   1035   }
   1036 
   1037   // get lower and upper 16 bit instructions from relocation targetData
   1038   uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
   1039   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
   1040 
   1041   ARMRelocator::DWord T = getThumbBit(pReloc);
   1042   ARMRelocator::DWord A = helper_thumb32_branch_offset(upper_inst,
   1043                                                                lower_inst);
   1044   ARMRelocator::Address P = pReloc.place();
   1045   ARMRelocator::Address S;
   1046 
   1047   // if symbol has plt
   1048   if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
   1049     S = helper_PLT(pReloc, pParent);
   1050     T = 0;  // PLT is not thumb.
   1051   }
   1052   else {
   1053     S = pReloc.symValue();
   1054     if (T != 0x0)
   1055       helper_clear_thumb_bit(S);
   1056   }
   1057 
   1058   S = S + A;
   1059 
   1060   // At this moment (after relaxation), if the jump target is arm
   1061   // instruction, switch mode is needed, rewrite the instruction to BLX
   1062   // FIXME: check if we can use BLX instruction (check from .ARM.attribute
   1063   // CPU ARCH TAG, which should be ARMv5 or above)
   1064   if (T == 0) {
   1065     // cannot rewrite to blx for R_ARM_THM_JUMP24
   1066     if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24)
   1067       return ARMRelocator::BadReloc;
   1068 
   1069     // for BLX, select bit 1 from relocation base address to jump target
   1070     // address
   1071     S = helper_bit_select(S, P, 0x2);
   1072     // rewrite instruction to BLX
   1073     lower_inst &= ~0x1000U;
   1074   }
   1075   else {
   1076     // otherwise, the instruction should be BL
   1077     lower_inst |= 0x1000U;
   1078   }
   1079 
   1080   ARMRelocator::DWord X = (S | T) - P;
   1081 
   1082   // FIXME: Check bit size is 24(thumb2) or 22?
   1083   if (helper_check_signed_overflow(X, 25)) {
   1084     return ARMRelocator::Overflow;
   1085   }
   1086 
   1087   upper_inst = helper_thumb32_branch_upper(upper_inst, X);
   1088   lower_inst = helper_thumb32_branch_lower(lower_inst, X);
   1089 
   1090   *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
   1091   *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
   1092 
   1093   return ARMRelocator::OK;
   1094 }
   1095 
   1096 // R_ARM_MOVW_ABS_NC: (S + A) | T
   1097 ARMRelocator::Result movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
   1098 {
   1099   ResolveInfo* rsym = pReloc.symInfo();
   1100   ARMRelocator::Address S = pReloc.symValue();
   1101   ARMRelocator::DWord T = getThumbBit(pReloc);
   1102   ARMRelocator::DWord A =
   1103       helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   1104   if (T != 0x0)
   1105     helper_clear_thumb_bit(S);
   1106 
   1107   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
   1108 
   1109   // If the flag of target section is not ALLOC, we will not scan this
   1110   // relocation but perform static relocation. (e.g., applying .debug section)
   1111   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
   1112     // use plt
   1113     if (rsym->reserved() & ARMRelocator::ReservePLT) {
   1114       S = helper_PLT(pReloc, pParent);
   1115       T = 0 ; // PLT is not thumb
   1116     }
   1117   }
   1118 
   1119   // perform static relocation
   1120   ARMRelocator::DWord X = (S + A) | T;
   1121   pReloc.target() = helper_insert_val_movw_movt_inst(
   1122                                          pReloc.target() + pReloc.addend(), X);
   1123   return ARMRelocator::OK;
   1124 }
   1125 
   1126 // R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
   1127 ARMRelocator::Result movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
   1128 {
   1129   ARMRelocator::Address S = pReloc.symValue();
   1130   ARMRelocator::DWord T = getThumbBit(pReloc);
   1131   ARMRelocator::DWord P = pReloc.place();
   1132   ARMRelocator::DWord A =
   1133       helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   1134   if (T != 0x0)
   1135     helper_clear_thumb_bit(S);
   1136   ARMRelocator::DWord X = ((S + A) | T) - P;
   1137 
   1138   if (helper_check_signed_overflow(X, 16)) {
   1139     return ARMRelocator::Overflow;
   1140   } else {
   1141     pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
   1142     return ARMRelocator::OK;
   1143   }
   1144 }
   1145 
   1146 // R_ARM_MOVT_ABS: S + A
   1147 ARMRelocator::Result movt_abs(Relocation& pReloc, ARMRelocator& pParent)
   1148 {
   1149   ResolveInfo* rsym = pReloc.symInfo();
   1150   ARMRelocator::Address S = pReloc.symValue();
   1151   ARMRelocator::DWord A =
   1152     helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   1153 
   1154   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
   1155 
   1156   // If the flag of target section is not ALLOC, we will not scan this relocation
   1157   // but perform static relocation. (e.g., applying .debug section)
   1158   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
   1159     // use plt
   1160     if (rsym->reserved() & ARMRelocator::ReservePLT) {
   1161       S = helper_PLT(pReloc, pParent);
   1162     }
   1163   }
   1164 
   1165   ARMRelocator::DWord X = S + A;
   1166   X >>= 16;
   1167   // perform static relocation
   1168   pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
   1169   return ARMRelocator::OK;
   1170 }
   1171 
   1172 // R_ARM_MOVT_PREL: S + A - P
   1173 ARMRelocator::Result movt_prel(Relocation& pReloc, ARMRelocator& pParent)
   1174 {
   1175   ARMRelocator::Address S = pReloc.symValue();
   1176   ARMRelocator::DWord P = pReloc.place();
   1177   ARMRelocator::DWord A =
   1178              helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   1179   ARMRelocator::DWord X = S + A - P;
   1180   X >>= 16;
   1181 
   1182   pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
   1183   return ARMRelocator::OK;
   1184 }
   1185 
   1186 // R_ARM_THM_MOVW_ABS_NC: (S + A) | T
   1187 ARMRelocator::Result thm_movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
   1188 {
   1189   ResolveInfo* rsym = pReloc.symInfo();
   1190   ARMRelocator::Address S = pReloc.symValue();
   1191   ARMRelocator::DWord T = getThumbBit(pReloc);
   1192   if (T != 0x0)
   1193     helper_clear_thumb_bit(S);
   1194 
   1195   // get lower and upper 16 bit instructions from relocation targetData
   1196   uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
   1197   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
   1198   ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
   1199   ARMRelocator::DWord A =
   1200                    helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   1201 
   1202   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
   1203   // If the flag of target section is not ALLOC, we will not scan this relocation
   1204   // but perform static relocation. (e.g., applying .debug section)
   1205   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
   1206     // use plt
   1207     if (rsym->reserved() & ARMRelocator::ReservePLT) {
   1208       S = helper_PLT(pReloc, pParent);
   1209       T = 0; // PLT is not thumb
   1210     }
   1211   }
   1212   ARMRelocator::DWord X = (S + A) | T;
   1213 
   1214   val = helper_insert_val_thumb_movw_movt_inst(val, X);
   1215   *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
   1216   *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
   1217 
   1218   return ARMRelocator::OK;
   1219 }
   1220 
   1221 // R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
   1222 ARMRelocator::Result thm_movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
   1223 {
   1224   ARMRelocator::Address S = pReloc.symValue();
   1225   ARMRelocator::DWord T = getThumbBit(pReloc);
   1226   ARMRelocator::DWord P = pReloc.place();
   1227   if (T != 0x0)
   1228     helper_clear_thumb_bit(S);
   1229 
   1230   // get lower and upper 16 bit instructions from relocation targetData
   1231   uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
   1232   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
   1233   ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
   1234   ARMRelocator::DWord A =
   1235                    helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   1236   ARMRelocator::DWord X = ((S + A) | T) - P;
   1237 
   1238   val = helper_insert_val_thumb_movw_movt_inst(val, X);
   1239   *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
   1240   *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
   1241 
   1242   return ARMRelocator::OK;
   1243 }
   1244 
   1245 // R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
   1246 // R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
   1247 ARMRelocator::Result thm_movw_brel(Relocation& pReloc, ARMRelocator& pParent)
   1248 {
   1249   ARMRelocator::Address S = pReloc.symValue();
   1250   ARMRelocator::DWord T = getThumbBit(pReloc);
   1251   ARMRelocator::DWord P = pReloc.place();
   1252   if (T != 0x0)
   1253     helper_clear_thumb_bit(S);
   1254 
   1255   // get lower and upper 16 bit instructions from relocation targetData
   1256   uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
   1257   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
   1258   ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
   1259   ARMRelocator::DWord A =
   1260                    helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   1261 
   1262   ARMRelocator::DWord X = ((S + A) | T) - P;
   1263 
   1264   val = helper_insert_val_thumb_movw_movt_inst(val, X);
   1265   *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
   1266   *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
   1267 
   1268   return ARMRelocator::OK;
   1269 }
   1270 
   1271 // R_ARM_THM_MOVT_ABS: S + A
   1272 ARMRelocator::Result thm_movt_abs(Relocation& pReloc, ARMRelocator& pParent)
   1273 {
   1274   ResolveInfo* rsym = pReloc.symInfo();
   1275   ARMRelocator::Address S = pReloc.symValue();
   1276 
   1277   // get lower and upper 16 bit instructions from relocation targetData
   1278   uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
   1279   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
   1280   ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
   1281   ARMRelocator::DWord A =
   1282                    helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   1283 
   1284   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
   1285   // If the flag of target section is not ALLOC, we will not scan this
   1286   // relocation but perform static relocation. (e.g., applying .debug section)
   1287   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
   1288     // use plt
   1289     if (rsym->reserved() & ARMRelocator::ReservePLT) {
   1290       S = helper_PLT(pReloc, pParent);
   1291     }
   1292   }
   1293 
   1294   ARMRelocator::DWord X = S + A;
   1295   X >>= 16;
   1296 
   1297   // check 16-bit overflow
   1298   if (helper_check_signed_overflow(X, 16))
   1299     return ARMRelocator::Overflow;
   1300   val = helper_insert_val_thumb_movw_movt_inst(val, X);
   1301   *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
   1302   *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
   1303   return ARMRelocator::OK;
   1304 
   1305 }
   1306 
   1307 // R_ARM_THM_MOVT_PREL: S + A - P
   1308 // R_ARM_THM_MOVT_BREL: S + A - B(S)
   1309 ARMRelocator::Result thm_movt_prel(Relocation& pReloc, ARMRelocator& pParent)
   1310 {
   1311   ARMRelocator::Address S = pReloc.symValue();
   1312   ARMRelocator::DWord P = pReloc.place();
   1313 
   1314   // get lower and upper 16 bit instructions from relocation targetData
   1315   uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
   1316   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
   1317   ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
   1318   ARMRelocator::DWord A =
   1319                    helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   1320   ARMRelocator::DWord X = S + A - P;
   1321   X >>= 16;
   1322 
   1323   val = helper_insert_val_thumb_movw_movt_inst(val, X);
   1324   *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
   1325   *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
   1326 
   1327   return ARMRelocator::OK;
   1328 }
   1329 
   1330 // R_ARM_PREL31: ((S + A) | T) - P
   1331 ARMRelocator::Result prel31(Relocation& pReloc, ARMRelocator& pParent)
   1332 {
   1333   ARMRelocator::DWord target = pReloc.target();
   1334   ARMRelocator::DWord T = getThumbBit(pReloc);
   1335   ARMRelocator::DWord A = helper_sign_extend(target, 31) + pReloc.addend();
   1336   ARMRelocator::DWord P = pReloc.place();
   1337   ARMRelocator::Address S = pReloc.symValue();
   1338   if (T != 0x0)
   1339     helper_clear_thumb_bit(S);
   1340 
   1341   // if symbol has plt
   1342   if ( pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
   1343     S = helper_PLT(pReloc, pParent);
   1344     T = 0;  // PLT is not thumb.
   1345   }
   1346 
   1347   ARMRelocator::DWord X = ((S + A) | T) - P;
   1348   pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
   1349   if (helper_check_signed_overflow(X, 31))
   1350     return ARMRelocator::Overflow;
   1351   return ARMRelocator::OK;
   1352 }
   1353 
   1354 // R_ARM_TLS_GD32: GOT(S) + A - P
   1355 // R_ARM_TLS_IE32: GOT(S) + A - P
   1356 // R_ARM_TLS_LE32: S + A - tp
   1357 ARMRelocator::Result tls(Relocation& pReloc, ARMRelocator& pParent)
   1358 {
   1359   return ARMRelocator::Unsupport;
   1360 }
   1361 
   1362 ARMRelocator::Result unsupport(Relocation& pReloc, ARMRelocator& pParent)
   1363 {
   1364   return ARMRelocator::Unsupport;
   1365 }
   1366