15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ARMRelocationFactory.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 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLDInfo.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h> 16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMRelocationFactory.h" 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMRelocationFunctions.h" 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 2567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_ARM_APPLY_RELOC_FUNCS 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaotypedef RelocationFactory::Result (*ApplyFunctionType)( 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao Relocation& pReloc, 3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const MCLDInfo& pLDInfo, 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ARMRelocationFactory& pParent); 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_ARM_APPLY_RELOC_FUNC_PTRS 4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMRelocationFactory 4967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::ARMRelocationFactory(size_t pNum, 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMGNULDBackend& pParent) 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : RelocationFactory(pNum), 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent) { 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::~ARMRelocationFactory() 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result 6167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoARMRelocationFactory::applyRelocation(Relocation& pRelocation, 6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const MCLDInfo& pLDInfo) 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (type > 130) { // 131-255 doesn't noted in ARM spec 66affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::unknown_relocation) << (int)type 67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << pRelocation.symInfo()->name(); 6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return RelocationFactory::Unknown; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[type].func(pRelocation, pLDInfo, *this); 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const 7567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// non-member functions 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic RelocationFactory::DWord getThumbBit(const Relocation& pReloc) 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Set thumb bit if 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord thumbBit = 86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) && 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (pReloc.symInfo()->type() == ResolveInfo::Function) && 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((pReloc.symValue() & 0x1) != 0))? 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1:0; 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return thumbBit; 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation helper function // 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Using uint64_t to make sure those complicate operations won't cause 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// undefined behavior. 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width) 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(pOri_width <= 64); 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint64_t sign_bit = 1 << (pOri_width - 1); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return (pVal ^ sign_bit) - sign_bit; 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Reverse sign bit, then subtract sign bit. 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask) 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return (pA & ~pMask) | (pB & pMask) ; 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check if symbol can use relocation R_ARM_RELATIVE 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym, 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ARMRelocationFactory& pFactory) 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol is dynamic or undefine or preemptible 124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pSym.isDyn() || 125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pSym.isUndef() || 126affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pFactory.getTarget().isSymbolPreemptible(pSym, 127affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pLDInfo, 128affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pLDInfo.output())) 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMGNULDBackend& ld_backend = pParent.getTarget(); 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist); 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!exist) { 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & ARMGNULDBackend::ReserveGOT) { 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // No corresponding dynamic relocation, initialize to the symbol value. 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(pReloc.symValue()); 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else if (rsym->reserved() & ARMGNULDBackend::GOTRel) { 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize corresponding dynamic relocation. 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, true, exist); 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(!exist && "GOT entry not exist, but DynRel entry exist!"); 156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if ( rsym->isLocal() || 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize got entry to target symbol address 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(pReloc.symValue()); 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_ARM_RELATIVE); 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(0); 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize got entry to 0 for corresponding dynamic relocation. 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(0); 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT); 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym); 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef().assign(got_entry); 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 172cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return got_entry; 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent) 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getTarget().getGOT().getSection().addr(); 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_GOT(Relocation& pReloc, 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent); 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry); 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoPLTEntry& helper_get_PLT_and_init(Relocation& pReloc, 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMGNULDBackend& ld_backend = pParent.getTarget(); 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist); 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!exist) { 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this PLT entry, we should initialize it. 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& gotplt_entry = 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist); 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize corresponding dynamic relocation. 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelPLT().getEntry(*rsym, true, exist); 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(!exist && "PLT entry not exist, but DynRel entry exist!"); 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT); 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef().assign(gotplt_entry); 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym); 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 219cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_plt); 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return plt_entry; 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent) 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getTarget().getPLT().getSection().addr(); 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_PLT(Relocation& pReloc, 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry); 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Get an relocation entry in .rel.dyn and set its type to pType, 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo() 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Type pType, 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMGNULDBackend& ld_backend = pParent.getTarget(); 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, false, exist); 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(pType); 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pType == llvm::ELF::R_ARM_RELATIVE) 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(0); 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym); 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_extract_movw_movt_addend(ARMRelocationFactory::DWord pTarget) 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // imm16: [19-16][11-0] 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU), 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 16); 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_insert_val_movw_movt_inst(ARMRelocationFactory::DWord pTarget, 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord pImm) 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // imm16: [19-16][11-0] 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget &= 0xfff0f000U; 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget |= pImm & 0x0fffU; 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget |= (pImm & 0xf000U) << 4; 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pTarget; 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget) 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Consider the endianness problem, get the target data value from lower 288affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // and upper 16 bits 289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord val = 290affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) | 291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(reinterpret_cast<uint16_t*>(&pTarget) + 1); 292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // imm16: [19-16][26][14-12][7-0] 294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return helper_sign_extend((((val >> 4) & 0xf000U) | 295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ((val >> 15) & 0x0800U) | 296affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ((val >> 4) & 0x0700U) | 297affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (val & 0x00ffU)), 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 16); 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget, 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord pImm) 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 305affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord val; 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // imm16: [19-16][26][14-12][7-0] 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget &= 0xfbf08f00U; 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget |= (pImm & 0xf000U) << 4; 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget |= (pImm & 0x0800U) << 15; 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget |= (pImm & 0x0700U) << 4; 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pTarget |= (pImm & 0x00ffU); 312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Consider the endianness problem, write back data from lower and 314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // upper 16 bits 315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang val = (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) | 316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(reinterpret_cast<uint16_t*>(&pTarget) + 1); 317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return val; 3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_thumb32_branch_offset(ARMRelocationFactory::DWord pUpper16, 3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord pLower16) 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord s = (pUpper16 & (1U << 10)) >> 10, // 26 bit 3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao u = pUpper16 & 0x3ffU, // 25-16 3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao l = pLower16 & 0x7ffU, // 10-0 3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao j1 = (pLower16 & (1U << 13)) >> 13, // 13 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao j2 = (pLower16 & (1U << 11)) >> 11; // 11 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord i1 = j1 ^ s? 0: 1, 3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao i2 = j2 ^ s? 0: 1; 3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // [31-25][24][23][22][21-12][11-1][0] 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // 0 s i1 i2 u l 0 3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) | 3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (u << 12) | (l << 1), 3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 25); 3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_thumb32_branch_upper(ARMRelocationFactory::DWord pUpper16, 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord pOffset) 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t sign = ((pOffset & 0x80000000U) >> 31); 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10); 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_thumb32_branch_lower(ARMRelocationFactory::DWord pLower16, 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord pOffset) 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t sign = ((pOffset & 0x80000000U) >> 31); 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ((pLower16 & ~0x2fffU) | 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((((pOffset >> 23) & 1) ^ !sign) << 13) | 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((((pOffset >> 22) & 1) ^ !sign) << 11) | 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ((pOffset >> 1) & 0x7ffU)); 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Return true if overflow 3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_check_signed_overflow(ARMRelocationFactory::DWord pValue, 3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned bits) 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t signed_val = static_cast<int32_t>(pValue); 3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t max = (1 << (bits - 1)) - 1; 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t min = -(1 << (bits - 1)); 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (signed_val > max || signed_val < min) { 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation // 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_NONE 3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result none(Relocation& pReloc, 3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_ABS32: (S + A) | T 3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result abs32(Relocation& pReloc, 3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord S = pReloc.symValue(); 3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 396affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 397affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 398affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 399affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 400affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 401affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 402affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 403affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A) | T; 404affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK; 405affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 406affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 407affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // A local symbol may need REL Type dynamic relocation 408affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->isLocal() && (rsym->reserved() & ARMGNULDBackend::ReserveRel)) { 4095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent); 4105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (S + A) | T ; 4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 413affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 414affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 415affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 416affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 4175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 4185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0 ; // PLT is not thumb 4195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (S + A) | T; 4205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we generate a dynamic relocation (except R_ARM_RELATIVE) 4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // for a place, we should not perform static relocation on it 4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // in order to keep the addend store in the place correct. 424affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ARMGNULDBackend::ReserveRel) { 425affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { 4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent); 4275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pReloc.type(), pParent); 4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 435affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 4365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 4375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (S + A) | T; 4385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_REL32: ((S + A) | T) - P 4425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result rel32(Relocation& pReloc, 4435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 4445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 4455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 4475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 4485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 4495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = ((pReloc.symValue() + A) | T) 4505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao - pReloc.place(pParent.getLayout()); 4515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_BASE_PREL: B(S) + A - P 4555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result base_prel(Relocation& pReloc, 4565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 4575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 4585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 4605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 4615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout()); 4625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG 4665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result gotoff32(Relocation& pReloc, 4675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 4695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 4735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 4745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = ((S + A) | T) - GOT_ORG; 4765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG 4805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result got_brel(Relocation& pReloc, 4815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 4825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 484affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(pReloc.symInfo()->reserved() & 485affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) { 4865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::BadReloc; 4875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent); 4895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 4905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 4915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 4925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - GOT_ORG; 4935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 4945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_PREL: GOT(S) + A - P 4975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result got_prel(Relocation& pReloc, 4985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 4995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 501affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(pReloc.symInfo()->reserved() & 502affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) { 5035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::BadReloc; 5045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent); 5065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout()); 5085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 5095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - P; 5105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 5115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_PLT32: ((S + A) | T) - P 5145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_JUMP24: ((S + A) | T) - P 5155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_CALL: ((S + A) | T) - P 5165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result call(Relocation& pReloc, 5175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 5185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 5195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 520affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // TODO: Some issue have not been considered: 521affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // 1. Add stub when switching mode or jump target too far 522affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // 2. We assume the blx is available 5235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If target is undefined weak symbol, we only need to jump to the 525affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // next instruction unless it has PLT entry. Rewrite instruction 526affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // to NOP. 527affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pReloc.symInfo()->isWeak() && 528affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.symInfo()->isUndef() && 529affc150dc44fab1911775a49636d0ce85333b634Zonr Chang !pReloc.symInfo()->isDyn() && 5305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) { 5315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // change target to NOP : mov r0, r0 5325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000; 5335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 5345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 536affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::Address S; // S depends on PLT exists or not. 5375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 5385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 5395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) 5405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao + pReloc.addend(); 5415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout()); 5425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = pReloc.symValue(); 544affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) { 5455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0; // PLT is not thumb. 5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 549affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the jump target is thumb instruction, switch mode is needed, rewrite 550affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // the instruction to BLX 551affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (T != 0) { 552affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // cannot rewrite R_ARM_JUMP24 instruction to blx 553affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert((pReloc.type() != llvm::ELF::R_ARM_JUMP24)&& 554affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Invalid instruction to rewrite to blx for switching mode."); 555affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (pReloc.target() & 0xffffff) | 556affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 0xfa000000 | 557affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (((S + A - P) & 2) << 23); 5585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 559affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 560affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord X = ((S + A) | T) - P; 5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Check X is 24bit sign int. If not, we should use stub or PLT before apply. 56267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (helper_check_signed_overflow(X, 26)) 56367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ARMRelocationFactory::Overflow; 5645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Make sure the Imm is 0. Result Mask. 5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2); 5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_CALL: ((S + A) | T) - P 570affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_JUMP24: (((S + A) | T) - P) 5715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_call(Relocation& pReloc, 5725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 5735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 5745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 5755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If target is undefined weak symbol, we only need to jump to the 576affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // next instruction unless it has PLT entry. Rewrite instruction 577affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // to NOP. 578affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pReloc.symInfo()->isWeak() && 579affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.symInfo()->isUndef() && 580affc150dc44fab1911775a49636d0ce85333b634Zonr Chang !pReloc.symInfo()->isDyn() && 5815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) { 5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (0xe000U << 16) | 0xbf00U; 5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 5845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 586affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // get lower and upper 16 bit instructions from relocation targetData 587affc150dc44fab1911775a49636d0ce85333b634Zonr Chang uint16_t upper16 = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 588affc150dc44fab1911775a49636d0ce85333b634Zonr Chang uint16_t lower16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 5895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 5915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16, 5925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao lower16); 5935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout()); 5945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S; 5955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol has plt 597affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) { 5985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 5995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0; // PLT is not thumb. 6005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 601affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 602affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = pReloc.symValue(); 603affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 6045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 605affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = S + A; 6065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 607affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // FIXME: check if we can use BLX instruction (check from .ARM.attribute 608affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // CPU ARCH TAG, which should be ARMv5 or above) 609affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 610affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the jump target is not thumb, switch mode is needed, rewrite 611affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // instruction to BLX 612affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (T == 0) { 613affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // for BLX, select bit 1 from relocation base address to jump target 614affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // address 615affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_bit_select(S, P, 0x2); 616affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // rewrite instruction to BLX 617affc150dc44fab1911775a49636d0ce85333b634Zonr Chang lower16 &= ~0x1000U; 618affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 619affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 620affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // otherwise, the instruction should be BL 621affc150dc44fab1911775a49636d0ce85333b634Zonr Chang lower16 |= 0x1000U; 622affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 623affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 624affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord X = (S | T) - P; 625affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 626affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // TODO: check if we need stub when building non-shared object, 627affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // overflow or switch-mode. 6285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // FIXME: Check bit size is 24(thumb2) or 22? 630affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_check_signed_overflow(X, 25)) { 6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::Overflow; 6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 6335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao upper16 = helper_thumb32_branch_upper(upper16, X); 6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao lower16 = helper_thumb32_branch_lower(lower16, X); 6365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 637affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16; 638affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16; 6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 640affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK; 6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_ABS_NC: (S + A) | T 6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc, 6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 6485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 6545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 655affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 65667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao *(pReloc.targetRef().frag())); 657affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 65867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao // If the flag of target section is not ALLOC, we will not scan this 65967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao // relocation but perform static relocation. (e.g., applying .debug section) 660affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 661affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 662affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 663affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 664affc150dc44fab1911775a49636d0ce85333b634Zonr Chang T = 0 ; // PLT is not thumb 665affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 6665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 667affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 6685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 66967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao X = (S + A) | T; 67067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst( 67167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao pReloc.target() + pReloc.addend(), X); 67267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ARMRelocationFactory::OK; 6735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P 6765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc, 6775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 6785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 6795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 6805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 6815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 6825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 6835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 6845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 6855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 6865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = ((S + A) | T) - P; 6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_check_signed_overflow(X, 16)) { 6905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::Overflow; 6915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 6925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 6935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 6945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 6955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_ABS: S + A 6985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movt_abs(Relocation& pReloc, 6995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 7005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 7015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 7035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 7045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 7055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 7065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 7075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 708affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 709affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 710affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 711affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 712affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 713affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 714affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 715affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 716affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 717affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 7185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = S + A; 7215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 7225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 7245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 7255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_PREL: S + A - P 7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movt_prel(Relocation& pReloc, 7295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 7305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 7315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 7335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 7345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 7355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 7365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 7375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = S + A - P; 7395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 7405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 7425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 7435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_ABS_NC: (S + A) | T 7465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc, 7475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 7485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 7495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 7515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 7525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 7535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 7545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 7555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 7565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 757affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 758affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 759affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 760affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 761affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 762affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 763affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 764affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 765affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 766affc150dc44fab1911775a49636d0ce85333b634Zonr Chang T = 0; // PLT is not thumb 767affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 7685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = (S + A) | T; 770affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 771affc150dc44fab1911775a49636d0ce85333b634Zonr Chang X); 772affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK; 7735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P 7765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc, 7775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 7785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 7795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 7815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 7825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 7835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 7845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 7855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 7865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = ((S + A) | T) - P; 7885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // check 16-bit overflow 790affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 791affc150dc44fab1911775a49636d0ce85333b634Zonr Chang X); 792affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK; 793affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 794affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 795affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S) 796affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S) 797affc150dc44fab1911775a49636d0ce85333b634Zonr ChangARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc, 798affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const MCLDInfo& pLDInfo, 799affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory& pParent) 800affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 801affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::Address S = pReloc.symValue(); 802affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord T = getThumbBit(pReloc); 803affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 804affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord A = 805affc150dc44fab1911775a49636d0ce85333b634Zonr Chang helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 806affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ARMRelocationFactory::DWord X; 807affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 808affc150dc44fab1911775a49636d0ce85333b634Zonr Chang X = ((S + A) | T) - P; 809affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 810affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // check 16-bit overflow 811affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 812affc150dc44fab1911775a49636d0ce85333b634Zonr Chang X); 813affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK; 8145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_ABS: S + A 8175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc, 8185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 8195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 8205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 8225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 8235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 8245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 8255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 8265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 827affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 828affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 829affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 830affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 831affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 832affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 833affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // use plt 834affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 835affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 836affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 8375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 838affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 8395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = S + A; 8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // check 16-bit overflow 8435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_check_signed_overflow(X, 16)) { 8445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::Overflow; 8455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 8465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 8475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X); 8485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 8495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_PREL: S + A - P 853affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVT_BREL: S + A - B(S) 8545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc, 8555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 8565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S = pReloc.symValue(); 8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = 8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 8625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X; 8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X = S + A - P; 8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X >>= 16; 866affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 8675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X); 868affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK; 8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_PREL31: (S + A) | T 8725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result prel31(Relocation& pReloc, 8735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 8745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 8755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord target = pReloc.target(); 8775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord T = getThumbBit(pReloc); 8785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) + 8795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.addend(); 8805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::Address S; 8815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = pReloc.symValue(); 8835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol has plt 884affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if ( pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) { 8855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 8865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao T = 0; // PLT is not thumb. 8875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory::DWord X = (S + A) | T ; 8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = helper_bit_select(target, X, 0x7fffffffU); 891affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_check_signed_overflow(X, 31)) 8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::Overflow; 8935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::OK; 8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_GD32: GOT(S) + A - P 8975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_IE32: GOT(S) + A - P 8985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_LE32: S + A - tp 8995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result tls(Relocation& pReloc, 9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 9015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 9025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 9035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::Unsupport; 9045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result unsupport(Relocation& pReloc, 9075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ARMRelocationFactory& pParent) 9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 9105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ARMRelocationFactory::Unsupport; 9115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 912