Home | History | Annotate | Download | only in Hexagon
      1 //===- HexagonRelocator.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 "HexagonRelocator.h"
     10 #include "HexagonRelocationFunctions.h"
     11 #include "HexagonEncodings.h"
     12 #include <llvm/ADT/Twine.h>
     13 #include <llvm/Support/DataTypes.h>
     14 #include <llvm/Support/ELF.h>
     15 
     16 #include <mcld/LD/ELFFileFormat.h>
     17 #include <mcld/LD/LDSymbol.h>
     18 #include <mcld/Support/MsgHandling.h>
     19 
     20 using namespace mcld;
     21 
     22 //===--------------------------------------------------------------------===//
     23 // Relocation Helper Functions
     24 //===--------------------------------------------------------------------===//
     25 /// helper_DynRel - Get an relocation entry in .rela.dyn
     26 static Relocation &helper_DynRel_init(ResolveInfo *pSym,
     27                                       Fragment &pFrag,
     28                                       uint64_t pOffset,
     29                                       Relocator::Type pType,
     30                                       HexagonRelocator &pParent) {
     31   HexagonLDBackend &ld_backend = pParent.getTarget();
     32   Relocation &rela_entry = *ld_backend.getRelaDyn().create();
     33   rela_entry.setType(pType);
     34   rela_entry.targetRef().assign(pFrag, pOffset);
     35   if (pType == llvm::ELF::R_HEX_RELATIVE || NULL == pSym)
     36     rela_entry.setSymInfo(0);
     37   else
     38     rela_entry.setSymInfo(pSym);
     39 
     40   return rela_entry;
     41 }
     42 
     43 /// helper_use_relative_reloc - Check if symbol can use relocation
     44 /// R_HEX_RELATIVE
     45 static bool helper_use_relative_reloc(const ResolveInfo &pSym,
     46                                       const HexagonRelocator &pFactory) {
     47   // if symbol is dynamic or undefine or preemptible
     48   if (pSym.isDyn() || pSym.isUndef() ||
     49       pFactory.getTarget().isSymbolPreemptible(pSym))
     50     return false;
     51   return true;
     52 }
     53 
     54 static HexagonGOTEntry &helper_GOT_init(Relocation &pReloc,
     55                                         bool pHasRel,
     56                                         HexagonRelocator &pParent) {
     57   // rsym - The relocation target symbol
     58   ResolveInfo *rsym = pReloc.symInfo();
     59   HexagonLDBackend &ld_backend = pParent.getTarget();
     60   assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
     61 
     62   HexagonGOTEntry *got_entry = ld_backend.getGOT().create();
     63   pParent.getSymGOTMap().record(*rsym, *got_entry);
     64 
     65   if (!pHasRel) {
     66     // No corresponding dynamic relocation, initialize to the symbol value.
     67     got_entry->setValue(HexagonRelocator::SymVal);
     68   }
     69   else {
     70     // Initialize got_entry content and the corresponding dynamic relocation.
     71     if (helper_use_relative_reloc(*rsym, pParent)) {
     72       helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_RELATIVE,
     73                                                                        pParent);
     74       got_entry->setValue(HexagonRelocator::SymVal);
     75     }
     76     else {
     77       helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_GLOB_DAT,
     78                                                                        pParent);
     79       got_entry->setValue(0);
     80     }
     81   }
     82   return *got_entry;
     83 }
     84 
     85 static Relocator::Address helper_get_GOT_address(ResolveInfo &pSym,
     86                                                     HexagonRelocator &pParent) {
     87   HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(pSym);
     88   assert(NULL != got_entry);
     89   return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
     90 }
     91 
     92 static PLTEntryBase &helper_PLT_init(Relocation &pReloc,
     93                                      HexagonRelocator &pParent) {
     94   // rsym - The relocation target symbol
     95   ResolveInfo *rsym = pReloc.symInfo();
     96   HexagonLDBackend &ld_backend = pParent.getTarget();
     97   assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
     98 
     99   PLTEntryBase *plt_entry = ld_backend.getPLT().create();
    100   pParent.getSymPLTMap().record(*rsym, *plt_entry);
    101 
    102   assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
    103          "PLT entry not exist, but DynRel entry exist!");
    104   HexagonGOTEntry *gotplt_entry = ld_backend.getGOTPLT().create();
    105   pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
    106   // init the corresponding rel entry in .rela.plt
    107   Relocation &rela_entry = *ld_backend.getRelaPLT().create();
    108   rela_entry.setType(llvm::ELF::R_HEX_JMP_SLOT);
    109   rela_entry.targetRef().assign(*gotplt_entry);
    110   rela_entry.setSymInfo(rsym);
    111 
    112   return *plt_entry;
    113 }
    114 
    115 static Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
    116                                                     HexagonRelocator &pParent) {
    117   PLTEntryBase *plt_entry = pParent.getSymPLTMap().lookUp(pSym);
    118   assert(NULL != plt_entry);
    119   return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
    120 }
    121 
    122 //===--------------------------------------------------------------------===//
    123 // Relocation Functions and Tables
    124 //===--------------------------------------------------------------------===//
    125 DECL_HEXAGON_APPLY_RELOC_FUNCS
    126 
    127 /// the prototype of applying function
    128 typedef Relocator::Result (*ApplyFunctionType)(Relocation &pReloc,
    129                                                HexagonRelocator &pParent);
    130 
    131 // the table entry of applying functions
    132 struct ApplyFunctionTriple {
    133   ApplyFunctionType func;
    134   unsigned int type;
    135   const char *name;
    136 };
    137 
    138 // declare the table of applying functions
    139 static const ApplyFunctionTriple ApplyFunctions[] = {
    140   DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS
    141 };
    142 
    143 static uint32_t findBitMask(uint32_t insn, Instruction *encodings,
    144                             int32_t numInsns) {
    145   for (int32_t i = 0; i < numInsns; i++) {
    146     if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex))
    147       continue;
    148 
    149     if (((insn & 0xc000) != 0) && (encodings[i].isDuplex))
    150       continue;
    151 
    152     if (((encodings[i].insnMask) & insn) == encodings[i].insnCmpMask)
    153       return encodings[i].insnBitMask;
    154   }
    155   assert(0);
    156   // Should not be here, but add a return for -Werror=return-type
    157   // error: control reaches end of non-void function
    158   return -1;
    159 }
    160 
    161 #define FINDBITMASK(INSN)                                                      \
    162   findBitMask((uint32_t) INSN, insn_encodings,                                 \
    163               sizeof(insn_encodings) / sizeof(Instruction))
    164 
    165 //===--------------------------------------------------------------------===//
    166 // HexagonRelocator
    167 //===--------------------------------------------------------------------===//
    168 HexagonRelocator::HexagonRelocator(HexagonLDBackend &pParent,
    169                                    const LinkerConfig &pConfig)
    170     : Relocator(pConfig), m_Target(pParent) {}
    171 
    172 HexagonRelocator::~HexagonRelocator() {}
    173 
    174 Relocator::Result HexagonRelocator::applyRelocation(Relocation &pRelocation) {
    175   Relocation::Type type = pRelocation.type();
    176 
    177   if (type > 85) { // 86-255 relocs do not exists for Hexagon
    178     return Relocator::Unknown;
    179   }
    180 
    181   // apply the relocation
    182   return ApplyFunctions[type].func(pRelocation, *this);
    183 }
    184 
    185 const char *HexagonRelocator::getName(Relocation::Type pType) const {
    186   return ApplyFunctions[pType].name;
    187 }
    188 
    189 Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const {
    190   return 32;
    191 }
    192 
    193 void HexagonRelocator::scanRelocation(Relocation &pReloc, IRBuilder &pLinker,
    194                                       Module &pModule, LDSection &pSection, Input &pInput) {
    195   if (LinkerConfig::Object == config().codeGenType())
    196     return;
    197 
    198   // rsym - The relocation target symbol
    199   ResolveInfo *rsym = pReloc.symInfo();
    200   assert(NULL != rsym &&
    201          "ResolveInfo of relocation not set while scanRelocation");
    202 
    203   if (config().isCodeStatic())
    204     return;
    205 
    206   assert(NULL != pSection.getLink());
    207   if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
    208     return;
    209 
    210   if (rsym->isLocal()) // rsym is local
    211     scanLocalReloc(pReloc, pLinker, pModule, pSection);
    212   else // rsym is external
    213     scanGlobalReloc(pReloc, pLinker, pModule, pSection);
    214 
    215   // check if we should issue undefined reference for the relocation target
    216   // symbol
    217   if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
    218     issueUndefRef(pReloc, pSection, pInput);
    219 }
    220 
    221 void HexagonRelocator::addCopyReloc(ResolveInfo &pSym,
    222                                     HexagonLDBackend &pTarget) {
    223   Relocation &rel_entry = *pTarget.getRelaDyn().create();
    224   rel_entry.setType(pTarget.getCopyRelType());
    225   assert(pSym.outSymbol()->hasFragRef());
    226   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
    227   rel_entry.setSymInfo(&pSym);
    228 }
    229 
    230 void HexagonRelocator::scanLocalReloc(Relocation &pReloc, IRBuilder &pBuilder,
    231                                       Module &pModule, LDSection &pSection) {
    232   // rsym - The relocation target symbol
    233   ResolveInfo *rsym = pReloc.symInfo();
    234 
    235   switch (pReloc.type()) {
    236 
    237   case llvm::ELF::R_HEX_LO16:
    238   case llvm::ELF::R_HEX_HI16:
    239   case llvm::ELF::R_HEX_16:
    240   case llvm::ELF::R_HEX_8:
    241   case llvm::ELF::R_HEX_32_6_X:
    242   case llvm::ELF::R_HEX_16_X:
    243   case llvm::ELF::R_HEX_12_X:
    244   case llvm::ELF::R_HEX_11_X:
    245   case llvm::ELF::R_HEX_10_X:
    246   case llvm::ELF::R_HEX_9_X:
    247   case llvm::ELF::R_HEX_8_X:
    248   case llvm::ELF::R_HEX_7_X:
    249   case llvm::ELF::R_HEX_6_X:
    250     assert(!(rsym->reserved() & ReserveRel) &&
    251            "Cannot apply this relocation for read only section");
    252     return;
    253 
    254   case llvm::ELF::R_HEX_32:
    255     // If buiding PIC object (shared library or PIC executable),
    256     // a dynamic relocations with RELATIVE type to this location is needed.
    257     // Reserve an entry in .rel.dyn
    258     if (config().isCodeIndep()) {
    259       Relocation &reloc = helper_DynRel_init(rsym,
    260                                              *pReloc.targetRef().frag(),
    261                                              pReloc.targetRef().offset(),
    262                                              llvm::ELF::R_HEX_RELATIVE,
    263                                              *this);
    264       // we need to set up the relocation addend at apply relocation, record the
    265       // relocation
    266       getRelRelMap().record(pReloc, reloc);
    267 
    268       // set Rel bit
    269       rsym->setReserved(rsym->reserved() | ReserveRel);
    270       getTarget().checkAndSetHasTextRel(*pSection.getLink());
    271     }
    272     return;
    273 
    274   default:
    275     return;
    276   }
    277 }
    278 
    279 void HexagonRelocator::scanGlobalReloc(Relocation &pReloc, IRBuilder &pBuilder,
    280                                        Module &pModule, LDSection &pSection) {
    281   // rsym - The relocation target symbol
    282   ResolveInfo *rsym = pReloc.symInfo();
    283   HexagonLDBackend &ld_backend = getTarget();
    284 
    285   switch (pReloc.type()) {
    286   case llvm::ELF::R_HEX_LO16:
    287   case llvm::ELF::R_HEX_HI16:
    288   case llvm::ELF::R_HEX_16:
    289   case llvm::ELF::R_HEX_8:
    290   case llvm::ELF::R_HEX_32_6_X:
    291   case llvm::ELF::R_HEX_16_X:
    292   case llvm::ELF::R_HEX_12_X:
    293   case llvm::ELF::R_HEX_11_X:
    294   case llvm::ELF::R_HEX_10_X:
    295   case llvm::ELF::R_HEX_9_X:
    296   case llvm::ELF::R_HEX_8_X:
    297   case llvm::ELF::R_HEX_7_X:
    298   case llvm::ELF::R_HEX_6_X:
    299     assert(!(rsym->reserved() & ReserveRel) &&
    300            "Cannot apply this relocation for read only section");
    301     return;
    302 
    303   case llvm::ELF::R_HEX_32:
    304     if (ld_backend.symbolNeedsPLT(*rsym)) {
    305       //create PLT for this symbol if it does not have.
    306       if (!(rsym->reserved() & ReservePLT)) {
    307         helper_PLT_init(pReloc, *this);
    308         rsym->setReserved(rsym->reserved() | ReservePLT);
    309       }
    310     }
    311 
    312     if (ld_backend.symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
    313                                      true)) {
    314       if (ld_backend.symbolNeedsCopyReloc(pReloc, *rsym)) {
    315         LDSymbol &cpy_sym =
    316             defineSymbolforCopyReloc(pBuilder, *rsym, ld_backend);
    317         addCopyReloc(*cpy_sym.resolveInfo(), ld_backend);
    318       }
    319       else {
    320         Relocation &reloc = helper_DynRel_init(rsym,
    321                                                *pReloc.targetRef().frag(),
    322                                                pReloc.targetRef().offset(),
    323                                                llvm::ELF::R_HEX_RELATIVE,
    324                                                *this);
    325         // we need to set up the relocation addend at apply relocation, record the
    326         // relocation
    327         getRelRelMap().record(pReloc, reloc);
    328         rsym->setReserved(rsym->reserved() | ReserveRel);
    329         ld_backend.checkAndSetHasTextRel(*pSection.getLink());
    330       }
    331     }
    332     return;
    333 
    334   case llvm::ELF::R_HEX_GOTREL_LO16:
    335   case llvm::ELF::R_HEX_GOTREL_HI16:
    336   case llvm::ELF::R_HEX_GOTREL_32:
    337   case llvm::ELF::R_HEX_GOTREL_32_6_X:
    338   case llvm::ELF::R_HEX_GOTREL_16_X:
    339   case llvm::ELF::R_HEX_GOTREL_11_X:
    340     // This assumes that GOT exists
    341     return;
    342 
    343   case llvm::ELF::R_HEX_GOT_LO16:
    344   case llvm::ELF::R_HEX_GOT_HI16:
    345   case llvm::ELF::R_HEX_GOT_32:
    346   case llvm::ELF::R_HEX_GOT_16:
    347   case llvm::ELF::R_HEX_GOT_32_6_X:
    348   case llvm::ELF::R_HEX_GOT_16_X:
    349   case llvm::ELF::R_HEX_GOT_11_X:
    350     // Symbol needs GOT entry, reserve entry in .got
    351     // return if we already create GOT for this symbol
    352     if (rsym->reserved() & ReserveGOT)
    353       return;
    354     // If the GOT is used in statically linked binaries,
    355     // the GOT entry is enough and no relocation is needed.
    356     if (config().isCodeStatic())
    357       helper_GOT_init(pReloc, false, *this);
    358     else
    359       helper_GOT_init(pReloc, true, *this);
    360     // set GOT bit
    361     rsym->setReserved(rsym->reserved() | ReserveGOT);
    362     return;
    363 
    364   case llvm::ELF::R_HEX_B22_PCREL:
    365   case llvm::ELF::R_HEX_B15_PCREL:
    366   case llvm::ELF::R_HEX_B7_PCREL:
    367   case llvm::ELF::R_HEX_B13_PCREL:
    368   case llvm::ELF::R_HEX_B9_PCREL:
    369   case llvm::ELF::R_HEX_B32_PCREL_X:
    370   case llvm::ELF::R_HEX_B22_PCREL_X:
    371   case llvm::ELF::R_HEX_B15_PCREL_X:
    372   case llvm::ELF::R_HEX_B13_PCREL_X:
    373   case llvm::ELF::R_HEX_B9_PCREL_X:
    374   case llvm::ELF::R_HEX_B7_PCREL_X:
    375   case llvm::ELF::R_HEX_32_PCREL:
    376   case llvm::ELF::R_HEX_6_PCREL_X:
    377   case llvm::ELF::R_HEX_PLT_B22_PCREL:
    378     if (rsym->reserved() & ReservePLT)
    379       return;
    380     if (ld_backend.symbolNeedsPLT(*rsym) ||
    381         pReloc.type() == llvm::ELF::R_HEX_PLT_B22_PCREL) {
    382       helper_PLT_init(pReloc, *this);
    383       rsym->setReserved(rsym->reserved() | ReservePLT);
    384     }
    385     return;
    386 
    387   default:
    388     break;
    389 
    390   } // end of switch
    391 }
    392 
    393 /// defineSymbolforCopyReloc
    394 /// For a symbol needing copy relocation, define a copy symbol in the BSS
    395 /// section and all other reference to this symbol should refer to this
    396 /// copy.
    397 /// @note This is executed at `scan relocation' stage.
    398 LDSymbol &HexagonRelocator::defineSymbolforCopyReloc(
    399     IRBuilder &pBuilder, const ResolveInfo &pSym, HexagonLDBackend &pTarget) {
    400   // get or create corresponding BSS LDSection
    401   LDSection *bss_sect_hdr = NULL;
    402   ELFFileFormat *file_format = pTarget.getOutputFormat();
    403   if (ResolveInfo::ThreadLocal == pSym.type())
    404     bss_sect_hdr = &file_format->getTBSS();
    405   else
    406     bss_sect_hdr = &file_format->getBSS();
    407 
    408   // get or create corresponding BSS SectionData
    409   assert(NULL != bss_sect_hdr);
    410   SectionData *bss_section = NULL;
    411   if (bss_sect_hdr->hasSectionData())
    412     bss_section = bss_sect_hdr->getSectionData();
    413   else
    414     bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
    415 
    416   // Determine the alignment by the symbol value
    417   // FIXME: here we use the largest alignment
    418   uint32_t addralign = config().targets().bitclass() / 8;
    419 
    420   // allocate space in BSS for the copy symbol
    421   Fragment *frag = new FillFragment(0x0, 1, pSym.size());
    422   uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_section, addralign);
    423   bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
    424 
    425   // change symbol binding to Global if it's a weak symbol
    426   ResolveInfo::Binding binding = (ResolveInfo::Binding) pSym.binding();
    427   if (binding == ResolveInfo::Weak)
    428     binding = ResolveInfo::Global;
    429 
    430   // Define the copy symbol in the bss section and resolve it
    431   LDSymbol *cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    432       pSym.name(), (ResolveInfo::Type) pSym.type(), ResolveInfo::Define,
    433       binding, pSym.size(), // size
    434       0x0,                  // value
    435       FragmentRef::Create(*frag, 0x0), (ResolveInfo::Visibility) pSym.other());
    436 
    437   // output all other alias symbols if any
    438   Module &pModule = pBuilder.getModule();
    439   Module::AliasList *alias_list = pModule.getAliasList(pSym);
    440   if (NULL != alias_list) {
    441     Module::alias_iterator it, it_e = alias_list->end();
    442     for (it = alias_list->begin(); it != it_e; ++it) {
    443       const ResolveInfo *alias = *it;
    444       if (alias != &pSym && alias->isDyn()) {
    445         pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    446             alias->name(), (ResolveInfo::Type) alias->type(),
    447             ResolveInfo::Define, binding, alias->size(), // size
    448             0x0,                                         // value
    449             FragmentRef::Create(*frag, 0x0),
    450             (ResolveInfo::Visibility) alias->other());
    451       }
    452     }
    453   }
    454 
    455   return *cpy_sym;
    456 }
    457 
    458 void HexagonRelocator::partialScanRelocation(Relocation &pReloc,
    459                                              Module &pModule,
    460                                              const LDSection &pSection) {
    461   pReloc.updateAddend();
    462   // if we meet a section symbol
    463   if (pReloc.symInfo()->type() == ResolveInfo::Section) {
    464     LDSymbol *input_sym = pReloc.symInfo()->outSymbol();
    465 
    466     // 1. update the relocation target offset
    467     assert(input_sym->hasFragRef());
    468     // 2. get the output LDSection which the symbol defined in
    469     const LDSection &out_sect =
    470         input_sym->fragRef()->frag()->getParent()->getSection();
    471     ResolveInfo *sym_info =
    472         pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
    473     // set relocation target symbol to the output section symbol's resolveInfo
    474     pReloc.setSymInfo(sym_info);
    475   }
    476 }
    477 
    478 //=========================================//
    479 // Each relocation function implementation //
    480 //=========================================//
    481 
    482 // R_HEX_NONE
    483 Relocator::Result none(Relocation &pReloc, HexagonRelocator &pParent) {
    484   return Relocator::OK;
    485 }
    486 
    487 //R_HEX_32 and its class of relocations use only addend and symbol value
    488 // S + A : result is unsigned truncate.
    489 // Exception: R_HEX_32_6_X : unsigned verify
    490 Relocator::Result applyAbs(Relocation &pReloc) {
    491   Relocator::Address S = pReloc.symValue();
    492   Relocator::DWord A = pReloc.addend();
    493   uint32_t result = (uint32_t)(S + A);
    494   uint32_t bitMask = 0;
    495   uint32_t effectiveBits = 0;
    496   uint32_t alignment = 1;
    497   uint32_t shift = 0;
    498 
    499   switch (pReloc.type()) {
    500   case llvm::ELF::R_HEX_LO16:
    501     bitMask = 0x00c03fff;
    502     break;
    503 
    504   case llvm::ELF::R_HEX_HI16:
    505     shift = 16;
    506     bitMask = 0x00c03fff;
    507     break;
    508 
    509   case llvm::ELF::R_HEX_32:
    510     bitMask = 0xffffffff;
    511     break;
    512 
    513   case llvm::ELF::R_HEX_16:
    514     bitMask = 0x0000ffff;
    515     alignment = 2;
    516     break;
    517 
    518   case llvm::ELF::R_HEX_8:
    519     bitMask = 0x000000ff;
    520     alignment = 1;
    521     break;
    522 
    523   case llvm::ELF::R_HEX_12_X:
    524     bitMask = 0x000007e0;
    525     break;
    526 
    527   case llvm::ELF::R_HEX_32_6_X:
    528     bitMask = 0xfff3fff;
    529     shift = 6;
    530     effectiveBits = 26;
    531     break;
    532 
    533   case llvm::ELF::R_HEX_16_X:
    534   case llvm::ELF::R_HEX_11_X:
    535   case llvm::ELF::R_HEX_10_X:
    536   case llvm::ELF::R_HEX_9_X:
    537   case llvm::ELF::R_HEX_8_X:
    538   case llvm::ELF::R_HEX_7_X:
    539   case llvm::ELF::R_HEX_6_X:
    540     bitMask = FINDBITMASK(pReloc.target());
    541     break;
    542 
    543   default:
    544     // show proper error
    545     fatal(diag::unsupported_relocation) << (int)
    546         pReloc.type() << "mclinker (at) googlegroups.com";
    547 
    548   }
    549 
    550   if ((shift != 0) && (result % alignment != 0))
    551     return Relocator::BadReloc;
    552 
    553   result >>= shift;
    554 
    555   if (effectiveBits) {
    556     uint32_t range = 1 << effectiveBits;
    557     if (result > (range - 1))
    558       return Relocator::Overflow;
    559   }
    560 
    561   pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
    562   return Relocator::OK;
    563 }
    564 
    565 //R_HEX_B22_PCREL and its class of relocations, use
    566 // S + A - P : result is signed verify.
    567 // Exception: R_HEX_B32_PCREL_X : signed truncate
    568 // Another Exception: R_HEX_6_PCREL_X is unsigned truncate
    569 Relocator::Result applyRel(Relocation &pReloc, int64_t pResult) {
    570   uint32_t bitMask = 0;
    571   uint32_t effectiveBits = 0;
    572   uint32_t alignment = 1;
    573   uint32_t result;
    574   uint32_t shift = 0;
    575 
    576   switch (pReloc.type()) {
    577   case llvm::ELF::R_HEX_B22_PCREL:
    578     bitMask = 0x01ff3ffe;
    579     effectiveBits = 22;
    580     alignment = 4;
    581     shift = 2;
    582     break;
    583 
    584   case llvm::ELF::R_HEX_B15_PCREL:
    585     bitMask = 0x00df20fe;
    586     effectiveBits = 15;
    587     alignment = 4;
    588     shift = 2;
    589     break;
    590 
    591   case llvm::ELF::R_HEX_B7_PCREL:
    592     bitMask = 0x00001f18;
    593     effectiveBits = 7;
    594     alignment = 4;
    595     shift = 2;
    596     break;
    597 
    598   case llvm::ELF::R_HEX_B13_PCREL:
    599     bitMask = 0x00202ffe;
    600     effectiveBits = 13;
    601     alignment = 4;
    602     shift = 2;
    603     break;
    604 
    605   case llvm::ELF::R_HEX_B9_PCREL:
    606     bitMask = 0x003000fe;
    607     effectiveBits = 9;
    608     alignment = 4;
    609     shift = 2;
    610     break;
    611 
    612   case llvm::ELF::R_HEX_B32_PCREL_X:
    613     bitMask = 0xfff3fff;
    614     shift = 6;
    615     break;
    616 
    617   case llvm::ELF::R_HEX_B22_PCREL_X:
    618     bitMask = 0x01ff3ffe;
    619     effectiveBits = 22;
    620     pResult &= 0x3f;
    621     break;
    622 
    623   case llvm::ELF::R_HEX_B15_PCREL_X:
    624     bitMask = 0x00df20fe;
    625     effectiveBits = 15;
    626     pResult &= 0x3f;
    627     break;
    628 
    629   case llvm::ELF::R_HEX_B13_PCREL_X:
    630     bitMask = 0x00202ffe;
    631     effectiveBits = 13;
    632     pResult &= 0x3f;
    633     break;
    634 
    635   case llvm::ELF::R_HEX_B9_PCREL_X:
    636     bitMask = 0x003000fe;
    637     effectiveBits = 9;
    638     pResult &= 0x3f;
    639     break;
    640 
    641   case llvm::ELF::R_HEX_B7_PCREL_X:
    642     bitMask = 0x00001f18;
    643     effectiveBits = 7;
    644     pResult &= 0x3f;
    645     break;
    646 
    647   case llvm::ELF::R_HEX_32_PCREL:
    648     bitMask = 0xffffffff;
    649     effectiveBits = 32;
    650     break;
    651 
    652   case llvm::ELF::R_HEX_6_PCREL_X:
    653     // This is unique since it has a unsigned operand and its truncated
    654     bitMask = FINDBITMASK(pReloc.target());
    655     result = pReloc.addend() + pReloc.symValue() - pReloc.place();
    656     pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
    657     return Relocator::OK;
    658 
    659   default:
    660     // show proper error
    661     fatal(diag::unsupported_relocation) << (int)
    662         pReloc.type() << "mclinker (at) googlegroups.com";
    663   }
    664 
    665   if ((shift != 0) && (pResult % alignment != 0))
    666     return Relocator::BadReloc;
    667 
    668   pResult >>= shift;
    669 
    670   if (effectiveBits) {
    671     int64_t range = 1LL << (effectiveBits - 1);
    672     if ((pResult > (range - 1)) || (pResult < -range))
    673       return Relocator::Overflow;
    674   }
    675 
    676   pReloc.target() |= (uint32_t) ApplyMask<int32_t>(bitMask, pResult);
    677   return Relocator::OK;
    678 }
    679 
    680 Relocator::Result relocAbs(Relocation &pReloc, HexagonRelocator &pParent) {
    681   ResolveInfo *rsym = pReloc.symInfo();
    682   Relocator::Address S = pReloc.symValue();
    683   Relocator::DWord A = pReloc.addend();
    684 
    685   Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc);
    686   bool has_dyn_rel = (NULL != rel_entry);
    687 
    688   // if the flag of target section is not ALLOC, we eprform only static
    689   // relocation.
    690   if (0 == (llvm::ELF::SHF_ALLOC &
    691             pReloc.targetRef().frag()->getParent()->getSection().flag())) {
    692     return applyAbs(pReloc);
    693   }
    694 
    695   // a local symbol with .rela type relocation
    696   if (rsym->isLocal() && has_dyn_rel) {
    697     rel_entry->setAddend(S + A);
    698     return Relocator::OK;
    699   }
    700 
    701   if (!rsym->isLocal()) {
    702     if (rsym->reserved() & HexagonRelocator::ReservePLT) {
    703       S = helper_get_PLT_address(*rsym, pParent);
    704     }
    705 
    706     if (has_dyn_rel) {
    707       if (llvm::ELF::R_HEX_32 == pReloc.type() &&
    708           helper_use_relative_reloc(*rsym, pParent)) {
    709         rel_entry->setAddend(S + A);
    710       } else {
    711         rel_entry->setAddend(A);
    712         return Relocator::OK;
    713       }
    714     }
    715   }
    716 
    717   return applyAbs(pReloc);
    718 }
    719 
    720 Relocator::Result relocPCREL(Relocation &pReloc, HexagonRelocator &pParent) {
    721   ResolveInfo *rsym = pReloc.symInfo();
    722   int64_t result;
    723 
    724   Relocator::Address S = pReloc.symValue();
    725   Relocator::DWord A = pReloc.addend();
    726   Relocator::DWord P = pReloc.place();
    727 
    728   FragmentRef &target_fragref = pReloc.targetRef();
    729   Fragment *target_frag = target_fragref.frag();
    730   LDSection &target_sect = target_frag->getParent()->getSection();
    731 
    732   result = (int64_t)(S + A - P);
    733 
    734   // for relocs inside non ALLOC, just apply
    735   if (0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
    736     return applyRel(pReloc, result);
    737   }
    738 
    739   if (!rsym->isLocal()) {
    740     if (rsym->reserved() & HexagonRelocator::ReservePLT) {
    741       S = helper_get_PLT_address(*rsym, pParent);
    742       result = (int64_t)(S + A - P);
    743       applyRel(pReloc, result);
    744       return Relocator::OK;
    745     }
    746   }
    747 
    748   return applyRel(pReloc, result);
    749 }
    750 
    751 // R_HEX_GPREL16_0 and its class : Unsigned Verify
    752 Relocator::Result relocGPREL(Relocation &pReloc, HexagonRelocator &pParent) {
    753   Relocator::Address S = pReloc.symValue();
    754   Relocator::DWord A = pReloc.addend();
    755   Relocator::DWord GP = pParent.getTarget().getGP();
    756 
    757   uint32_t result = (uint32_t)(S + A - GP);
    758   uint32_t shift = 0;
    759   uint32_t alignment = 1;
    760 
    761   switch (pReloc.type()) {
    762   case llvm::ELF::R_HEX_GPREL16_0:
    763     break;
    764 
    765   case llvm::ELF::R_HEX_GPREL16_1:
    766     shift = 1;
    767     alignment = 2;
    768     break;
    769 
    770   case llvm::ELF::R_HEX_GPREL16_2:
    771     shift = 2;
    772     alignment = 4;
    773     break;
    774 
    775   case llvm::ELF::R_HEX_GPREL16_3:
    776     shift = 3;
    777     alignment = 8;
    778     break;
    779 
    780   default:
    781     // show proper error
    782     fatal(diag::unsupported_relocation) << (int)
    783         pReloc.type() << "mclinker (at) googlegroups.com";
    784   }
    785 
    786   uint32_t range = 1 << 16;
    787   uint32_t bitMask = FINDBITMASK(pReloc.target());
    788 
    789   if ((shift != 0) && (result % alignment != 0))
    790     return Relocator::BadReloc;
    791 
    792   result >>= shift;
    793 
    794   if (result < range - 1) {
    795     pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
    796     return Relocator::OK;
    797   }
    798   return Relocator::Overflow;
    799 }
    800 
    801 // R_HEX_PLT_B22_PCREL: PLT(S) + A - P
    802 Relocator::Result relocPLTB22PCREL(Relocation &pReloc,
    803                                    HexagonRelocator &pParent) {
    804   // PLT_S depends on if there is a PLT entry.
    805   Relocator::Address PLT_S;
    806   if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT))
    807     PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
    808   else
    809     PLT_S = pReloc.symValue();
    810   Relocator::Address P = pReloc.place();
    811   uint32_t bitMask = FINDBITMASK(pReloc.target());
    812   uint32_t result = (PLT_S + pReloc.addend() - P) >> 2;
    813   pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
    814   return Relocator::OK;
    815 }
    816 
    817 //R_HEX_GOT_LO16 and its class : (G) Signed Truncate
    818 //Exception: R_HEX_GOT_16(_X): signed verify
    819 // Exception: R_HEX_GOT_11_X : unsigned truncate
    820 Relocator::Result relocGOT(Relocation &pReloc, HexagonRelocator &pParent) {
    821   if (!(pReloc.symInfo()->reserved() & HexagonRelocator::ReserveGOT)) {
    822     return Relocator::BadReloc;
    823   }
    824 
    825   // set got entry value if needed
    826   HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
    827   assert(NULL != got_entry);
    828   if (HexagonRelocator::SymVal == got_entry->getValue())
    829     got_entry->setValue(pReloc.symValue());
    830 
    831   Relocator::Address GOT_S =
    832                              helper_get_GOT_address(*pReloc.symInfo(), pParent);
    833   Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
    834   int32_t result = (int32_t)(GOT_S - GOT);
    835   uint32_t effectiveBits = 0;
    836   uint32_t alignment = 1;
    837   uint32_t bitMask = 0;
    838   uint32_t result_u;
    839   uint32_t shift = 0;
    840 
    841   switch (pReloc.type()) {
    842   case llvm::ELF::R_HEX_GOT_LO16:
    843     bitMask = 0x00c03fff;
    844     break;
    845 
    846   case llvm::ELF::R_HEX_GOT_HI16:
    847     bitMask = 0x00c03fff;
    848     shift = 16;
    849     alignment = 4;
    850     break;
    851 
    852   case llvm::ELF::R_HEX_GOT_32:
    853     bitMask = 0xffffffff;
    854     break;
    855 
    856   case llvm::ELF::R_HEX_GOT_16:
    857     bitMask = FINDBITMASK(pReloc.target());
    858     effectiveBits = 16;
    859     break;
    860 
    861   case llvm::ELF::R_HEX_GOT_32_6_X:
    862     bitMask = 0xfff3fff;
    863     shift = 6;
    864     break;
    865 
    866   case llvm::ELF::R_HEX_GOT_16_X:
    867     bitMask = FINDBITMASK(pReloc.target());
    868     effectiveBits = 6;
    869     break;
    870 
    871   case llvm::ELF::R_HEX_GOT_11_X:
    872     bitMask = FINDBITMASK(pReloc.target());
    873     result_u = GOT_S - GOT;
    874     pReloc.target() |= ApplyMask<uint32_t>(bitMask, result_u);
    875     return Relocator::OK;
    876 
    877   default:
    878     // show proper error
    879     fatal(diag::unsupported_relocation) << (int)
    880         pReloc.type() << "mclinker (at) googlegroups.com";
    881   }
    882 
    883   if ((shift != 0) && (result % alignment != 0))
    884     return Relocator::BadReloc;
    885 
    886   result >>= shift;
    887 
    888   if (effectiveBits) {
    889     int32_t range = 1 << (effectiveBits - 1);
    890     if ((result > range - 1) || (result < -range))
    891       return Relocator::Overflow;
    892   }
    893   pReloc.target() |= ApplyMask<int32_t>(bitMask, result);
    894   return Relocator::OK;
    895 }
    896 
    897 // R_HEX_GOTREL_LO16: and its class of relocs
    898 // (S + A - GOT) : Signed Truncate
    899 Relocator::Result relocGOTREL(Relocation &pReloc, HexagonRelocator &pParent) {
    900   Relocator::Address S = pReloc.symValue();
    901   Relocator::DWord A = pReloc.addend();
    902   Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
    903 
    904   uint32_t bitMask = 0;
    905   uint32_t alignment = 1;
    906   uint32_t shift = 0;
    907 
    908   uint32_t result = (uint32_t)(S + A - GOT);
    909 
    910   switch (pReloc.type()) {
    911   case llvm::ELF::R_HEX_GOTREL_LO16:
    912     bitMask = 0x00c03fff;
    913     break;
    914 
    915   case llvm::ELF::R_HEX_GOTREL_HI16:
    916     bitMask = 0x00c03fff;
    917     shift = 16;
    918     alignment = 4;
    919     break;
    920 
    921   case llvm::ELF::R_HEX_GOTREL_32:
    922     bitMask = 0xffffffff;
    923     break;
    924 
    925   case llvm::ELF::R_HEX_GOTREL_32_6_X:
    926     bitMask = 0x0fff3fff;
    927     shift = 6;
    928     break;
    929 
    930   case llvm::ELF::R_HEX_GOTREL_16_X:
    931   case llvm::ELF::R_HEX_GOTREL_11_X:
    932     bitMask = FINDBITMASK(pReloc.target());
    933     break;
    934 
    935   default:
    936     // show proper error
    937     fatal(diag::unsupported_relocation) << (int)
    938         pReloc.type() << "mclinker (at) googlegroups.com";
    939   }
    940 
    941   if (result % alignment != 0)
    942     return Relocator::BadReloc;
    943 
    944   result >>= shift;
    945 
    946   pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
    947   return Relocator::OK;
    948 }
    949 
    950 Relocator::Result unsupport(Relocation &pReloc, HexagonRelocator &pParent) {
    951   return Relocator::Unsupport;
    952 }
    953