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