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