1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- ARMRelocator.cpp ----------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LinkerConfig.h> 11f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/IRBuilder.h> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h> 16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 17f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LD/LDSymbol.h> 1887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/ELFFileFormat.h> 19f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Object/ObjectBuilder.h> 20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "ARMRelocator.h" 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMRelocationFunctions.h" 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//=========================================// 2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Relocation helper function // 2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//=========================================// 2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic Relocator::DWord getThumbBit(const Relocation& pReloc) 2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Set thumb bit if 3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set 3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord thumbBit = 3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) && 3487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (pReloc.symInfo()->type() == ResolveInfo::Function) && 3587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((pReloc.symValue() & 0x1) != 0))? 3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1:0; 3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return thumbBit; 3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Using uint64_t to make sure those complicate operations won't cause 4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// undefined behavior. 4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width) 4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(pOri_width <= 64); 4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pOri_width == 64) 4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pVal; 4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width); 5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pVal &= mask; 5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Reverse sign bit, then subtract sign bit. 5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t sign_bit = 1 << (pOri_width - 1); 5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return (pVal ^ sign_bit) - sign_bit; 5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask) 5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return (pA & ~pMask) | (pB & pMask) ; 6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Check if symbol can use relocation R_ARM_RELATIVE 6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic bool 6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hineshelper_use_relative_reloc(const ResolveInfo& pSym, 6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const ARMRelocator& pFactory) 6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // if symbol is dynamic or undefine or preemptible 6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pSym.isDyn() || 6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pSym.isUndef() || 7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pFactory.getTarget().isSymbolPreemptible(pSym)) 7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Strip LSB (THUMB bit) if "S" is a THUMB target. 76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic inline void helper_clear_thumb_bit(Relocator::DWord& pValue) 7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pValue &= (~0x1); 7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 82551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Address helper_get_GOT_address(ResolveInfo& pSym, 83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ARMRelocator& pParent) 8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(pSym); 8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(NULL != got_entry); 8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 9187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMGOTEntry& helper_GOT_init(Relocation& pReloc, 9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool pHasRel, 9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMRelocator& pParent) 9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGNULDBackend& ld_backend = pParent.getTarget(); 9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(NULL == pParent.getSymGOTMap().lookUp(*rsym)); 9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGOTEntry* got_entry = ld_backend.getGOT().createGOT(); 10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymGOTMap().record(*rsym, *got_entry); 10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // If we first get this GOT entry, we should initialize it. 10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!pHasRel) { 10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // No corresponding dynamic relocation, initialize to the symbol value. 10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(ARMRelocator::SymVal); 10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else { 10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Initialize corresponding dynamic relocation. 10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().create(); 11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->isLocal() || helper_use_relative_reloc(*rsym, pParent)) { 11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Initialize got entry to target symbol address 11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(ARMRelocator::SymVal); 11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(llvm::ELF::R_ARM_RELATIVE); 11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(NULL); 11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else { 11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Initialize got entry to 0 for corresponding dynamic relocation. 11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0); 11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT); 12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(rsym); 12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef().assign(*got_entry); 12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *got_entry; 12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 12687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Address helper_GOT_ORG(ARMRelocator& pParent) 12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getGOT().addr(); 13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 134551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Address helper_get_PLT_address(ResolveInfo& pSym, 135551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ARMRelocator& pParent) 13687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 13787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 13887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(NULL != plt_entry); 13987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 14087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 14187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 14287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 14387f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMPLT1& helper_PLT_init(Relocation& pReloc, ARMRelocator& pParent) 14487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 14687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 14787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGNULDBackend& ld_backend = pParent.getTarget(); 14887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(NULL == pParent.getSymPLTMap().lookUp(*rsym)); 14987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 15087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // initialize the plt and the corresponding gotplt and dyn relocation 15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMPLT1* plt_entry = ld_backend.getPLT().create(); 15287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymPLTMap().record(*rsym, *plt_entry); 15387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) && 15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines "PLT entry not exist, but DynRel entry exist!"); 15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGOTEntry* gotplt_entry = ld_backend.getGOT().createGOTPLT(); 15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 15887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 15987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelPLT().create(); 16087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT); 16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef().assign(*gotplt_entry); 16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(rsym); 16387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *plt_entry; 16587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 16687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Get an relocation entry in .rel.dyn and set its type to pType, 16887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to 16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// pReloc->symInfo() 17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic 17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid helper_DynRel_init(Relocation& pReloc, 172551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Type pType, 17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMRelocator& pParent) 17487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 17587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 17787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGNULDBackend& ld_backend = pParent.getTarget(); 17887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 17987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().create(); 18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(pType); 18187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef() = pReloc.targetRef(); 18287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 18387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pType == llvm::ELF::R_ARM_RELATIVE) 18487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(NULL); 18587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(rsym); 18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 18887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 189551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 190551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_extract_movw_movt_addend(Relocator::DWord pTarget) 19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // imm16: [19-16][11-0] 19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU), 19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16); 19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 198551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_insert_val_movw_movt_inst(Relocator::DWord pTarget, 199551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pImm) 20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 20187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // imm16: [19-16][11-0] 20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pTarget &= 0xfff0f000U; 20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pTarget |= pImm & 0x0fffU; 20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pTarget |= (pImm & 0xf000U) << 4; 20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pTarget; 20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_extract_thumb_movw_movt_addend(Relocator::DWord pValue) 21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // imm16: [19-16][26][14-12][7-0] 21287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return helper_sign_extend((((pValue >> 4) & 0xf000U) | 21387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((pValue >> 15) & 0x0800U) | 21487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((pValue >> 4) & 0x0700U) | 21587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (pValue& 0x00ffU)), 21687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16); 21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 220551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_insert_val_thumb_movw_movt_inst(Relocator::DWord pValue, 221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pImm) 22287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // imm16: [19-16][26][14-12][7-0] 22487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pValue &= 0xfbf08f00U; 22587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pValue |= (pImm & 0xf000U) << 4; 22687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pValue |= (pImm & 0x0800U) << 15; 22787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pValue |= (pImm & 0x0700U) << 4; 22887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pValue |= (pImm & 0x00ffU); 22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pValue; 23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 23187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 232551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 233551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_branch_offset(Relocator::DWord pUpper16, 234551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pLower16) 23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 236551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord s = (pUpper16 & (1U << 10)) >> 10, // 26 bit 23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines u = pUpper16 & 0x3ffU, // 25-16 23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines l = pLower16 & 0x7ffU, // 10-0 23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines j1 = (pLower16 & (1U << 13)) >> 13, // 13 24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines j2 = (pLower16 & (1U << 11)) >> 11; // 11 241551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord i1 = j1 ^ s? 0: 1, 24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines i2 = j2 ^ s? 0: 1; 24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // [31-25][24][23][22][21-12][11-1][0] 24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // 0 s i1 i2 u l 0 24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) | 24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (u << 12) | (l << 1), 24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 25); 24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 251551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 252551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_branch_upper(Relocator::DWord pUpper16, 253551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pOffset) 25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t sign = ((pOffset & 0x80000000U) >> 31); 25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10); 25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 25887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 259551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_branch_lower(Relocator::DWord pLower16, 261551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pOffset) 26287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 26387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t sign = ((pOffset & 0x80000000U) >> 31); 26487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return ((pLower16 & ~0x2fffU) | 26587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((((pOffset >> 23) & 1) ^ !sign) << 13) | 26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((((pOffset >> 22) & 1) ^ !sign) << 11) | 26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ((pOffset >> 1) & 0x7ffU)); 26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 270551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_cond_branch_offset(Relocator::DWord pUpper16, 272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pLower16) 27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t s = (pUpper16 & 0x0400U) >> 10; 27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t j1 = (pLower16 & 0x2000U) >> 13; 27687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t j2 = (pLower16 & 0x0800U) >> 11; 27787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t lower = (pLower16 & 0x07ffU); 27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t upper = (s << 8) | (j2 << 7) | (j1 << 6) | (pUpper16 & 0x003fU); 27987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return helper_sign_extend((upper << 12) | (lower << 1), 21); 28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 28187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 282551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 283551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_cond_branch_upper(Relocator::DWord pUpper16, 284551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pOffset) 28587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 28687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t sign = ((pOffset & 0x80000000U) >> 31); 28787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return (pUpper16 & 0xfbc0U) | (sign << 10) | ((pOffset & 0x0003f000U) >> 12); 28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 28987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 290551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord 291551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_cond_branch_lower(Relocator::DWord pLower16, 292551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord pOffset) 29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t j2 = (pOffset & 0x00080000U) >> 19; 29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t j1 = (pOffset & 0x00040000U) >> 18; 29687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t lo = (pOffset & 0x00000ffeU) >> 1; 29787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return (pLower16 & 0xd000U) | (j1 << 13) | (j2 << 11) | lo; 29887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 29987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 30087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Return true if overflow 30187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic bool 302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_check_signed_overflow(Relocator::DWord pValue, 30387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines unsigned bits) 30487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 30587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t signed_val = static_cast<int32_t>(pValue); 30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t max = (1 << (bits - 1)) - 1; 30787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t min = -(1 << (bits - 1)); 30887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (signed_val > max || signed_val < min) { 30987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 31087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } else { 31187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 31487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 31587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 31667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 31767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 31867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_ARM_APPLY_RELOC_FUNCS 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 32167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 322d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc, 323d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao ARMRelocator& pParent); 32467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 32567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 32667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 32767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 32867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 32967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 33067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 33167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 33267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 33367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 33467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 33567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_ARM_APPLY_RELOC_FUNC_PTRS 33667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 33767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// ARMRelocator 34067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::ARMRelocator(ARMGNULDBackend& pParent, 342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : Relocator(pConfig), 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent) { 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 347d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::~ARMRelocator() 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 351d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result 352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::applyRelocation(Relocation& pRelocation) 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (type > 130) { // 131-255 doesn't noted in ARM spec 356d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return Relocator::Unknown; 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 35922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return ApplyFunctions[type].func(pRelocation, *this); 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 362d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* ARMRelocator::getName(Relocator::Type pType) const 36367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 36467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 36567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size ARMRelocator::getSize(Relocation::Type pType) const 3686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return 32; 3706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::addCopyReloc(ResolveInfo& pSym) 373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 37487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *getTarget().getRelDyn().create(); 375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setType(llvm::ELF::R_ARM_COPY); 376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(pSym.outSymbol()->hasFragRef()); 377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setSymInfo(&pSym); 379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolForCopyReloc 382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS 383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this 384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy. 385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// This is executed at scan relocation stage. 386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesLDSymbol& 387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const ResolveInfo& pSym) 389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get or create corresponding BSS LDSection 391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection* bss_sect_hdr = NULL; 392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ELFFileFormat* file_format = getTarget().getOutputFormat(); 393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (ResolveInfo::ThreadLocal == pSym.type()) 394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr = &file_format->getTBSS(); 395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr = &file_format->getBSS(); 397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get or create corresponding BSS SectionData 399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines SectionData* bss_data = NULL; 400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (bss_sect_hdr->hasSectionData()) 401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_data = bss_sect_hdr->getSectionData(); 402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr); 404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Determine the alignment by the symbol value 406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: here we use the largest alignment 407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t addralign = config().targets().bitclass() / 8; 408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // allocate space in BSS for the copy symbol 410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t size = ObjectBuilder::AppendFragment(*frag, 412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *bss_data, 413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addralign); 414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // change symbol binding to Global if it's a weak symbol 417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (binding == ResolveInfo::Weak) 419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines binding = ResolveInfo::Global; 420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Define the copy symbol in the bss section and resolve it 422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSym.name(), 424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (ResolveInfo::Type)pSym.type(), 425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Define, 426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines binding, 427f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSym.size(), // size 428f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 0x0, // value 429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines FragmentRef::Create(*frag, 0x0), 430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (ResolveInfo::Visibility)pSym.other()); 431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *cpy_sym; 433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// checkValidReloc - When we attempt to generate a dynamic relocation for 436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// ouput file, check if the relocation is supported by dynamic linker. 437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::checkValidReloc(Relocation& pReloc) const 438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If not PIC object, no relocation type is invalid 440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!config().isCodeIndep()) 441f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()) { 444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_RELATIVE: 445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_COPY: 446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GLOB_DAT: 447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_JUMP_SLOT: 448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS32: 449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS32_NOI: 450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_PC24: 451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TLS_DTPMOD32: 452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TLS_DTPOFF32: 453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TLS_TPOFF32: 454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines error(diag::non_pic_relocation) << (int)pReloc.type() 458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << pReloc.symInfo()->name(); 459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 463a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hinesbool ARMRelocator::mayHaveFunctionPointerAccess(const Relocation& pReloc) const 464a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines{ 465a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines switch (pReloc.type()) { 466a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_PC24: 467a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_THM_CALL: 468a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_PLT32: 469a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_CALL: 470a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_JUMP24: 471a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_THM_JUMP24: 472a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_SBREL31: 473a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_PREL31: 474a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_THM_JUMP19: 475a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_THM_JUMP6: 476a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_THM_JUMP11: 477a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines case llvm::ELF::R_ARM_THM_JUMP8: { 478a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines return false; 479a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines } 480a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines default: { 481a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines return true; 482a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines } 483a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines } 484a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines} 485a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines 486f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid 487f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection) 488f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 489f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 490f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 491f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()){ 493f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 494f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Set R_ARM_TARGET1 to R_ARM_ABS32 495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Ref: GNU gold 1.11 arm.cc, line 9892 496f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: R_ARM_TARGET1 should be set by option --target1-rel 497f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // or --target1-rel 498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TARGET1: 499f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.setType(llvm::ELF::R_ARM_ABS32); 500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS32: 501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS32_NOI: { 502f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If buiding PIC object (shared library or PIC executable), 503f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Reserve an entry in .rel.dyn 505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeIndep()) { 50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this); 507f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 508f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 509f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 510f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 511f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 512f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 513f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 514f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS16: 515f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS12: 516f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_ABS5: 517f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS8: 518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_BASE_ABS: 519f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVW_ABS_NC: 520f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVT_ABS: 521f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 522f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVT_ABS: { 523f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // PIC code should not contain these kinds of relocation 524f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeIndep()) { 525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines error(diag::non_pic_relocation) << (int)pReloc.type() 526f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << pReloc.symInfo()->name(); 527f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 528f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 529f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 530f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOTOFF32: 531f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOTOFF12: { 532f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: A GOT section is needed 533f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 534f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 535f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 536f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Ref: GNU gold 1.11 arm.cc, line 9892 538f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: R_ARM_TARGET2 should be set by option --target2 539f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TARGET2: 540f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 541f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOT_BREL: 542f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOT_PREL: { 543f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A GOT entry is needed for these relocation type. 544f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 54787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 548f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If building PIC object, a dynamic relocation with 549f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // type RELATIVE is needed to relocate this GOT entry. 55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (config().isCodeIndep()) 55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, true, *this); 55287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, false, *this); 554f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 556f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 557f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 558f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 559f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_BASE_PREL: { 560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: Currently we only support R_ARM_BASE_PREL against 561f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol _GLOBAL_OFFSET_TABLE_ 562f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym != getTarget().getGOTSymbol()->resolveInfo()) 563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name() 564f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 565f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 566f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_COPY: 568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GLOB_DAT: 569f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_JUMP_SLOT: 570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_RELATIVE: { 571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // These are relocation type for dynamic linker, shold not 572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // appear in object file. 573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::dynamic_relocation) << (int)pReloc.type(); 574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 575f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 576f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: { 577f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 578f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } // end switch 580f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 582f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::scanGlobalReloc(Relocation& pReloc, 583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LDSection& pSection) 585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 589f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()) { 590f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Set R_ARM_TARGET1 to R_ARM_ABS32 592f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Ref: GNU gold 1.11 arm.cc, line 9892 593f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: R_ARM_TARGET1 should be set by option --target1-rel 594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // or --target1-rel 595f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TARGET1: 596f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.setType(llvm::ELF::R_ARM_ABS32); 597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS32: 598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS16: 599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS12: 600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_ABS5: 601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS8: 602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_BASE_ABS: 603f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVW_ABS_NC: 604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVT_ABS: 605f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 606f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVT_ABS: 607f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ABS32_NOI: { 608f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 609f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation entry 610f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt. 61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 617f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 618f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 619f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 620f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 621f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 62287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (getTarget().symbolNeedsDynRel(*rsym, 62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (rsym->reserved() & ReservePLT), true)) { 624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 627f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 628f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines checkValidReloc(pReloc); 630f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 63187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (helper_use_relative_reloc(*rsym, *this)) 63287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this); 63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 63487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(pReloc, pReloc.type(), *this); 635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 636f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 637f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 638f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 639f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 640f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 641f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 642f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOTOFF32: 643f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOTOFF12: { 644f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: A GOT section is needed 645f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 646f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 647f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 648f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_BASE_PREL: 649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVW_BREL_NC: 650f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVW_BREL: 651f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVT_BREL: 652f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: Currently we only support these relocations against 653f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol _GLOBAL_OFFSET_TABLE_ 654f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym != getTarget().getGOTSymbol()->resolveInfo()) { 655f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name() 656f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 657f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 658f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_REL32: 659f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDR_PC_G0: 660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_SBREL32: 661f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_PC8: 662f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVW_PREL_NC: 663f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVT_PREL: 664f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVW_PREL_NC: 665f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_MOVT_PREL: 666f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_ALU_PREL_11_0: 667f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_PC12: 668f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_REL32_NOI: 669f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_PC_G0_NC: 670f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_PC_G0: 671f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_PC_G1_NC: 672f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_PC_G1: 673f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_PC_G2: 674f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDR_PC_G1: 675f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDR_PC_G2: 676f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDRS_PC_G0: 677f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDRS_PC_G1: 678f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDRS_PC_G2: 679f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDC_PC_G0: 680f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDC_PC_G1: 681f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDC_PC_G2: 682f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_SB_G0_NC: 683f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_SB_G0: 684f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_SB_G1_NC: 685f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_SB_G1: 686f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_ALU_SB_G2: 687f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDR_SB_G0: 688f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDR_SB_G1: 689f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDR_SB_G2: 690f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDRS_SB_G0: 691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDRS_SB_G1: 692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDRS_SB_G2: 693f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDC_SB_G0: 694f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDC_SB_G1: 695f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_LDC_SB_G2: 696f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVW_BREL_NC: 697f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVT_BREL: 698f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_MOVW_BREL: { 699f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Relative addressing relocation, may needs dynamic relocation 70087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 70187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines false)) { 702f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 703f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 704f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 705f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 708f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines checkValidReloc(pReloc); 709f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 71087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines //helper_DynRel_init(pReloc, pReloc.type(), *this); 711f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 713f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 714f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 715f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 716f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 717f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 718f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_PC24: 719f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_CALL: 720f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_PLT32: 721f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_CALL: 722f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_JUMP24: 723f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_JUMP24: 724f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_SBREL31: 725f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_PREL31: 726f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_JUMP19: 727f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_JUMP6: 728f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_JUMP11: 729f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_THM_JUMP8: { 730f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // These are branch relocation (except PREL31) 731f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A PLT entry is needed when building shared library 732f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 733f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create plt for this symbol 734f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ReservePLT) 735f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 736f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 737f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if the symbol's value can be decided at link time, then no need plt 738f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 739f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 740f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 741f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if symbol is defined in the ouput file and it's not 742f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // preemptible, no need plt 743f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 744f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !getTarget().isSymbolPreemptible(*rsym)) { 745f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 746f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 747f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 748f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 749f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 75087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt. 75187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 752f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 753f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 754f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 755f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 756f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 757f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 758f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Ref: GNU gold 1.11 arm.cc, line 9892 759f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: R_ARM_TARGET2 should be set by option --target2 760f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_TARGET2: 761f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 762f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOT_BREL: 763f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOT_ABS: 764f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GOT_PREL: { 765f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 766f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 768f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 769f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if the symbol cannot be fully resolved at link time, then we need a 770f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation 77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!getTarget().symbolFinalValueIsKnown(*rsym)) 77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, true, *this); 77387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, false, *this); 775f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 776f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 777f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 778f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 779f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 780f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_COPY: 781f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_GLOB_DAT: 782f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_JUMP_SLOT: 783f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_ARM_RELATIVE: { 784f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // These are relocation type for dynamic linker, shold not 785f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // appear in object file. 786f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::dynamic_relocation) << (int)pReloc.type(); 787f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 788f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 789f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: { 790f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 791f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 792f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } // end switch 793f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 794f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 795f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::scanRelocation(Relocation& pReloc, 796f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 797f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 79887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& pSection, 79987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Input& pInput) 800f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 801f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 802f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 803f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != rsym && 804f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines "ResolveInfo of relocation not set while scanRelocation"); 805f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 806f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != pSection.getLink()); 807f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 808f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 809f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 810f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 811f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entries should be created. 812f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: Below judgements concern nothing about TLS related relocation 813f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 814f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym is local 815f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isLocal()) 816f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanLocalReloc(pReloc, pSection); 817f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 818f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym is external 819f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 820f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanGlobalReloc(pReloc, pBuilder, pSection); 821f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 822f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // check if we shoule issue undefined reference for the relocation target 823f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol 824f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 82587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines issueUndefRef(pReloc, pSection, pInput); 8265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 8295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation // 8305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 8315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_NONE 833d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result none(Relocation& pReloc, ARMRelocator& pParent) 8345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 835551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_ABS32: (S + A) | T 839d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result abs32(Relocation& pReloc, ARMRelocator& pParent) 8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 842551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 843551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 844551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord S = pReloc.symValue(); 845f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 846f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 8475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 848affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 849affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & 85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().frag()->getParent()->getSection().flag())) { 852affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A) | T; 853551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 854affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 855affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 856affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 857affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 858f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ARMRelocator::ReservePLT) { 85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0 ; // PLT is not thumb 8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we generate a dynamic relocation (except R_ARM_RELATIVE) 8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // for a place, we should not perform static relocation on it 8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // in order to keep the addend store in the place correct. 86587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if ((rsym->reserved() & ARMRelocator::ReserveRel) && 86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (!helper_use_relative_reloc(*rsym, pParent))) 867551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 8715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (S + A) | T; 872551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_REL32: ((S + A) | T) - P 876d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result rel32(Relocation& pReloc, ARMRelocator& pParent) 8775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 879551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 880551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 881551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 88222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // An external symbol may need PLT (this reloc is from a stub/veneer) 88422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!pReloc.symInfo()->isLocal()) { 885f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 88722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao T = 0; // PLT is not thumb. 88822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 88922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 89022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 89187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (T != 0x0) 89287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_clear_thumb_bit(S); 89387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 89422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation 89522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = ((S + A) | T) - pReloc.place(); 89622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 897551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_BASE_PREL: B(S) + A - P 901d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result base_prel(Relocation& pReloc, ARMRelocator& pParent) 9025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 9035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 904551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 90522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = pReloc.symValue() + A - pReloc.place(); 906551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG 910d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result gotoff32(Relocation& pReloc, ARMRelocator& pParent) 9115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 912551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 913551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 914551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 915551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 916f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 917f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 9185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = ((S + A) | T) - GOT_ORG; 920551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG 924d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent) 9255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT)) 927551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 929551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 930551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 931551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 9325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 9335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - GOT_ORG; 93487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // setup got entry value if needed 93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue()) 93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(pReloc.symValue()); 939551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_PREL: GOT(S) + A - P 943d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent) 9445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 94587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT)) { 946551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 9475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 948551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 949551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 950551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 95122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 9535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - P; 95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 95587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // setup got entry value if needed 95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue()) 95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(pReloc.symValue()); 959551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 962a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines// R_ARM_THM_JUMP8: S + A - P 963a790f0a8f3175183bea088389b3e4ae41813e192Stephen HinesARMRelocator::Result thm_jump8(Relocation& pReloc, ARMRelocator& pParent) 964a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines{ 965a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines Relocator::DWord P = pReloc.place(); 966a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines Relocator::DWord A = helper_sign_extend((pReloc.target() & 0x00ff) << 1, 8) + 967a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines pReloc.addend(); 968a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines // S depends on PLT exists or not 969a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines Relocator::Address S = pReloc.symValue(); 970a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) 971a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 972a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines 973a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines Relocator::DWord X = S + A - P; 974a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines if (helper_check_signed_overflow(X, 9)) 975a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines return Relocator::Overflow; 976a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines // Make sure the Imm is 0. Result Mask. 977a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines pReloc.target() = (pReloc.target() & 0xFFFFFF00u) | ((X & 0x01FEu) >> 1); 978a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines return Relocator::OK; 979a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines} 980a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines 981f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_ARM_THM_JUMP11: S + A - P 982f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::Result thm_jump11(Relocation& pReloc, ARMRelocator& pParent) 983f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 984551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 985551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = helper_sign_extend((pReloc.target() & 0x07ff) << 1, 11) + 986f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.addend(); 987f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // S depends on PLT exists or not 988551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 989f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) 99087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 991f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 992551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 993a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines if (helper_check_signed_overflow(X, 12)) 994551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 995f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Make sure the Imm is 0. Result Mask. 996f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.target() = (pReloc.target() & 0xFFFFF800u) | ((X & 0x0FFEu) >> 1); 997551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 998f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 999f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 100087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_ARM_THM_JUMP19: ((S + A) | T) - P 100187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMRelocator::Result thm_jump19(Relocation& pReloc, ARMRelocator& pParent) 100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{ 100387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // get lower and upper 16 bit instructions from relocation targetData 100487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 100587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 100687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1007551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1008551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = helper_thumb32_cond_branch_offset(upper_inst, 100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines lower_inst); 1010551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 1011551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S; 101287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // if symbol has plt 101387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 101487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 101587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines T = 0; // PLT is not thumb. 101687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 101787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else { 101887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = pReloc.symValue(); 101987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (T != 0x0) 102087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_clear_thumb_bit(S); 102187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 102287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 102387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (0x0 == T) { 102487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // FIXME: conditional branch to PLT in THUMB-2 not supported yet 102587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines error(diag::unsupport_cond_branch_reloc) << (int)pReloc.type(); 1026551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 102787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 102887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1029551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = ((S + A) | T) - P; 103087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (helper_check_signed_overflow(X, 21)) 1031551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 103287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 103387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines upper_inst = helper_thumb32_cond_branch_upper(upper_inst, X); 103487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines lower_inst = helper_thumb32_cond_branch_lower(lower_inst, X); 103587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 103687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst; 103787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst; 103887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1039551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 104087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 104187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1042f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_ARM_PC24: ((S + A) | T) - P 10435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_PLT32: ((S + A) | T) - P 10445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_JUMP24: ((S + A) | T) - P 10455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_CALL: ((S + A) | T) - P 1046d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result call(Relocation& pReloc, ARMRelocator& pParent) 10475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If target is undefined weak symbol, we only need to jump to the 1049affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // next instruction unless it has PLT entry. Rewrite instruction 1050affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // to NOP. 1051affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pReloc.symInfo()->isWeak() && 1052affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.symInfo()->isUndef() && 1053affc150dc44fab1911775a49636d0ce85333b634Zonr Chang !pReloc.symInfo()->isDyn() && 1054f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) { 10555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // change target to NOP : mov r0, r0 10565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000; 1057551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 10585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 10595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1060551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1061551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1062f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) + 1063f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.addend(); 1064551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 1065551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1066f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1067f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 10685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1069f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // S depends on PLT exists or not 1070f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 107187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 10725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0; // PLT is not thumb. 10735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 10745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 107522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // At this moment (after relaxation), if the jump target is thumb instruction, 107622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // switch mode is needed, rewrite the instruction to BLX 107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: check if we can use BLX instruction (check from .ARM.attribute 107822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // CPU ARCH TAG, which should be ARMv5 or above) 1079affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (T != 0) { 108022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // cannot rewrite to blx for R_ARM_JUMP24 108122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pReloc.type() == llvm::ELF::R_ARM_JUMP24) 1082551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 1083f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.type() == llvm::ELF::R_ARM_PC24) 1084551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 108522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1086affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (pReloc.target() & 0xffffff) | 1087affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 0xfa000000 | 1088affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (((S + A - P) & 2) << 23); 10895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1090affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1091551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = ((S + A) | T) - P; 10925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Check X is 24bit sign int. If not, we should use stub or PLT before apply. 109367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (helper_check_signed_overflow(X, 26)) 1094551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 10955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Make sure the Imm is 0. Result Mask. 10965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2); 1097551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 10985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_CALL: ((S + A) | T) - P 1101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_ARM_THM_JUMP24: ((S + A) | T) - P 1102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_call(Relocation& pReloc, ARMRelocator& pParent) 11035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 11045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If target is undefined weak symbol, we only need to jump to the 1105affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // next instruction unless it has PLT entry. Rewrite instruction 1106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // to NOP. 1107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pReloc.symInfo()->isWeak() && 1108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.symInfo()->isUndef() && 1109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang !pReloc.symInfo()->isDyn() && 1110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) { 11115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (0xe000U << 16) | 0xbf00U; 1112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 11135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 11145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // get lower and upper 16 bit instructions from relocation targetData 111622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 111722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 11185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = helper_thumb32_branch_offset(upper_inst, lower_inst); 1121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 1122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S; 11235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol has plt 1125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 112687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 11275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0; // PLT is not thumb. 11285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 1130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = pReloc.symValue(); 1131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 1133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 11345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = S + A; 11365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 113722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // At this moment (after relaxation), if the jump target is arm 113822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // instruction, switch mode is needed, rewrite the instruction to BLX 1139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // FIXME: check if we can use BLX instruction (check from .ARM.attribute 1140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // CPU ARCH TAG, which should be ARMv5 or above) 1141affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (T == 0) { 114222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // cannot rewrite to blx for R_ARM_THM_JUMP24 114322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24) 1144551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 114522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // for BLX, select bit 1 from relocation base address to jump target 1147affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // address 1148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_bit_select(S, P, 0x2); 1149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // rewrite instruction to BLX 115022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao lower_inst &= ~0x1000U; 1151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 1153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // otherwise, the instruction should be BL 115422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao lower_inst |= 0x1000U; 1155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1157551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = (S | T) - P; 1158affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 11595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // FIXME: Check bit size is 24(thumb2) or 22? 1160affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_check_signed_overflow(X, 25)) { 1161551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 11625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 11635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 116422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao upper_inst = helper_thumb32_branch_upper(upper_inst, X); 116522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao lower_inst = helper_thumb32_branch_lower(lower_inst, X); 11665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 116722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst; 116822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst; 11695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1170551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 11715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 11725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_ABS_NC: (S + A) | T 1174d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent) 11755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 11765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1177551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1178551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1179551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1180551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 11835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 118422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 118522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 118667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao // If the flag of target section is not ALLOC, we will not scan this 118767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao // relocation but perform static relocation. (e.g., applying .debug section) 118822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 1190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ARMRelocator::ReservePLT) { 119187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 1192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang T = 0 ; // PLT is not thumb 1193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 11945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 11965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 1197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = (S + A) | T; 119867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst( 119967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao pReloc.target() + pReloc.addend(), X); 1200551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 12015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P 1204d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent) 12055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1206551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1207551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 1209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1210551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 1213551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = ((S + A) | T) - P; 12145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_check_signed_overflow(X, 16)) { 1216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 12175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 12185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 1219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 12205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 12215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_ABS: S + A 1224d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movt_abs(Relocation& pReloc, ARMRelocator& pParent) 12255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 12265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1227551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1228551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1229551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 12305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 123122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 123222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1233affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 1234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 123522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 1237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ARMRelocator::ReservePLT) { 123887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 1239affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 12405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 12415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1242551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A; 12435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 12445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 12455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 1246551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 12475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_PREL: S + A - P 1250d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movt_prel(Relocation& pReloc, ARMRelocator& pParent) 12515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1252551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1253551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 1254551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1256551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 12575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 12585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 1260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 12615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_ABS_NC: (S + A) | T 1264d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent) 12655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 12665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1267551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1268551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 127122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 127222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get lower and upper 16 bit instructions from relocation targetData 127322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 127422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1275551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1276551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 12785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 127922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1280affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 1281affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 128222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 1284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ARMRelocator::ReservePLT) { 128587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 1286affc150dc44fab1911775a49636d0ce85333b634Zonr Chang T = 0; // PLT is not thumb 1287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 12885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1289551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = (S + A) | T; 129022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 129122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao val = helper_insert_val_thumb_movw_movt_inst(val, X); 1292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 129422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1295551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 12965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P 1299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent) 13005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1301551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1303551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 1304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 130622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 130722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get lower and upper 16 bit instructions from relocation targetData 130822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 130922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1310551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1311551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1313551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = ((S + A) | T) - P; 13145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 131522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao val = helper_insert_val_thumb_movw_movt_inst(val, X); 1316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 131822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1319551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 1320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 1321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S) 1323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S) 1324d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movw_brel(Relocation& pReloc, ARMRelocator& pParent) 1325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 1326551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1328551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 1329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 133122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 133222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get lower and upper 16 bit instructions from relocation targetData 133322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 133422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1335551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1336551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1338affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1339551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = ((S + A) | T) - P; 1340affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 134122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao val = helper_insert_val_thumb_movw_movt_inst(val, X); 1342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 134422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1345551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 13465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 13475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_ABS: S + A 1349d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movt_abs(Relocation& pReloc, ARMRelocator& pParent) 13505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 13515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1352551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 135322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 135422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get lower and upper 16 bit instructions from relocation targetData 135522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 135622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1357551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1358551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 13605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 136122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If the flag of target section is not ALLOC, we will not scan this 1363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 136422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1365affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 1366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ARMRelocator::ReservePLT) { 136787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 1368affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 13695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1370affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1371551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A; 13725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 13735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // check 16-bit overflow 1375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (helper_check_signed_overflow(X, 16)) 1376551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 1377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines val = helper_insert_val_thumb_movw_movt_inst(val, X); 1378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 1380551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 1381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 13825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 13835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_PREL: S + A - P 1385affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVT_BREL: S + A - B(S) 1386d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movt_prel(Relocation& pReloc, ARMRelocator& pParent) 13875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1388551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1389551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 139022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 139122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get lower and upper 16 bit instructions from relocation targetData 139222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 139322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1394551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1395551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = 1396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1397551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 13985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 139922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 140022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao val = helper_insert_val_thumb_movw_movt_inst(val, X); 1401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 140322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1404551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 14055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 14065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 140722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_ARM_PREL31: ((S + A) | T) - P 1408d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result prel31(Relocation& pReloc, ARMRelocator& pParent) 14095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1410551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord target = pReloc.target(); 1411551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord T = getThumbBit(pReloc); 1412551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = helper_sign_extend(target, 31) + pReloc.addend(); 1413551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 1414551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 1415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (T != 0x0) 1416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_clear_thumb_bit(S); 14175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol has plt 1419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if ( pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 142087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 14215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0; // PLT is not thumb. 14225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 14235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1424551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = ((S + A) | T) - P; 14255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_bit_select(target, X, 0x7fffffffU); 1426affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_check_signed_overflow(X, 31)) 1427551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 1428551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 14295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 14305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_GD32: GOT(S) + A - P 14325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_IE32: GOT(S) + A - P 14335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_LE32: S + A - tp 1434d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result tls(Relocation& pReloc, ARMRelocator& pParent) 14355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1436551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Unsupport; 14375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 14385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1439d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result unsupport(Relocation& pReloc, ARMRelocator& pParent) 14405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1441551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Unsupport; 14425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1443