1551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===- AArch64Relocator.cpp ----------------------------------------------===// 2551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// 3551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// The MCLinker Project 4551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// 5551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// This file is distributed under the University of Illinois Open Source 6551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// License. See LICENSE.TXT for details. 7551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// 8551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 9551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 10551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/LinkerConfig.h> 11551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/IRBuilder.h> 12551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/Support/MsgHandling.h> 13551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/LD/LDSymbol.h> 14551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/LD/ELFFileFormat.h> 15551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/Object/ObjectBuilder.h> 16551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 17551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/ADT/Twine.h> 18551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/DataTypes.h> 19551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/ELF.h> 20551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/Host.h> 21551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 22551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64Relocator.h" 23551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64RelocationFunctions.h" 24551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64RelocationHelpers.h" 25551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 26551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesusing namespace mcld; 27551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 28551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 29551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// Relocation Functions and Tables 30551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 31551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesDECL_AARCH64_APPLY_RELOC_FUNCS 32551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 33551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// the prototype of applying function 34551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinestypedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc, 35551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64Relocator& pParent); 36551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 37551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// the table entry of applying functions 38551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesclass ApplyFunctionEntry { 39551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinespublic: 40551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionEntry() {} 41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionEntry(ApplyFunctionType pFunc, 42551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const char* pName, 43551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines size_t pSize = 0) 44551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines : func(pFunc), name(pName), size(pSize) { } 45551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionType func; 46551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const char* name; 47551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines size_t size; 48551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}; 49551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinestypedef std::map<Relocator::Type, ApplyFunctionEntry> ApplyFunctionMap; 50551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic const ApplyFunctionMap::value_type ApplyFunctionList[] = { 52551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines DECL_AARCH64_APPLY_RELOC_FUNC_PTRS(ApplyFunctionMap::value_type, 53551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionEntry) 54551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}; 55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// declare the table of applying functions 57551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic ApplyFunctionMap ApplyFunctions(ApplyFunctionList, 58551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionList + sizeof(ApplyFunctionList)/sizeof(ApplyFunctionList[0])); 59551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// AArch64Relocator 62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::AArch64Relocator(AArch64GNULDBackend& pParent, 64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const LinkerConfig& pConfig) 65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines : Relocator(pConfig), 66551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines m_Target(pParent) { 67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 68551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 69551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::~AArch64Relocator() 70551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 72551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 73551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result AArch64Relocator::applyRelocation(Relocation& pRelocation) 74551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 75551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation::Type type = pRelocation.type(); 76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // valid types are 0x0, 0x100-0x239 77551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if ((type < 0x100 || type > 0x239) && (type != 0x0)) { 78551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Unknown; 79551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 80551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(ApplyFunctions.find(type) != ApplyFunctions.end()); 81551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return ApplyFunctions[type].func(pRelocation, *this); 82551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 84551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesconst char* AArch64Relocator::getName(Relocator::Type pType) const 85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 86551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(ApplyFunctions.find(pType) != ApplyFunctions.end()); 87551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return ApplyFunctions[pType].name; 88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 89551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Size AArch64Relocator::getSize(Relocation::Type pType) const 91551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 92551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return ApplyFunctions[pType].size; 93551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 94551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 95551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::addCopyReloc(ResolveInfo& pSym) 96551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 97551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& rel_entry = *getTarget().getRelaDyn().create(); 98551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rel_entry.setType(R_AARCH64_COPY); 99551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(pSym.outSymbol()->hasFragRef()); 100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 101551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rel_entry.setSymInfo(&pSym); 102551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// defineSymbolForCopyReloc 105551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS 106551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// section and all other reference to this symbol should refer to this 107551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// copy. 108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// This is executed at scan relocation stage. 109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesLDSymbol& AArch64Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const ResolveInfo& pSym) 111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // get or create corresponding BSS LDSection 113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection* bss_sect_hdr = NULL; 114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ELFFileFormat* file_format = getTarget().getOutputFormat(); 115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (ResolveInfo::ThreadLocal == pSym.type()) 116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_sect_hdr = &file_format->getTBSS(); 117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 118551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_sect_hdr = &file_format->getBSS(); 119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // get or create corresponding BSS SectionData 121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData* bss_data = NULL; 122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (bss_sect_hdr->hasSectionData()) 123551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_data = bss_sect_hdr->getSectionData(); 124551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 125551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr); 126551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Determine the alignment by the symbol value 128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // FIXME: here we use the largest alignment 129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint32_t addralign = config().targets().bitclass() / 8; 130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 131551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // allocate space in BSS for the copy symbol 132551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 133551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_data, addralign); 134551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 135551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 136551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // change symbol binding to Global if it's a weak symbol 137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 138551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (binding == ResolveInfo::Weak) 139551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines binding = ResolveInfo::Global; 140551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 141551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Define the copy symbol in the bss section and resolve it 142551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 143551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pSym.name(), 144551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (ResolveInfo::Type)pSym.type(), 145551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo::Define, 146551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines binding, 147551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pSym.size(), // size 148551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 0x0, // value 149551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines FragmentRef::Create(*frag, 0x0), 150551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (ResolveInfo::Visibility)pSym.other()); 151551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 152551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return *cpy_sym; 153551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 154551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 155551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid 156551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection) 157551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 158551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym - The relocation target symbol 159551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 160551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines switch(pReloc.type()) { 161551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS64: 162551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If buiding PIC object (shared library or PIC executable), 163551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 164551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Reserve an entry in .rel.dyn 165551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (config().isCodeIndep()) { 166551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set Rel bit 167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 168551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 169551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set up the dyn rel directly 170551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 171551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *pReloc.targetRef().frag(), 172551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.targetRef().offset(), 173551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines R_AARCH64_RELATIVE, 174551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *this); 175551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 176551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 177551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 178551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 179551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS32: 180551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS16: 181551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If buiding PIC object (shared library or PIC executable), 182551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 183551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Reserve an entry in .rel.dyn 184551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (config().isCodeIndep()) { 185551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set up the dyn rel directly 186551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 187551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *pReloc.targetRef().frag(), 188551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.targetRef().offset(), pReloc.type(), *this); 189551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 190551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set Rel bit 191551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 192551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 193551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 194551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 195551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 196551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 198551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs GOT entry, reserve entry in .got 199551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // return if we already create GOT for this symbol 200551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & ReserveGOT) 201551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 202551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If building PIC object, a dynamic relocation with 203551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // type RELATIVE is needed to relocate this GOT entry. 204551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (config().isCodeIndep()) 205551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_GOT_init(pReloc, true, *this); 206551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 207551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_GOT_init(pReloc, false, *this); 208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set GOT bit 209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 210551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 211551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 212551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 213551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines default: 214551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 215551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 217551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 218551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanGlobalReloc(Relocation& pReloc, 219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines IRBuilder& pBuilder, 220551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const LDSection& pSection) 221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 222551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym - The relocation target symbol 223551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 224551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines switch(pReloc.type()) { 225551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS64: 226551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS32: 227551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS16: 228551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 229551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // dynamic relocation entry 230551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 231551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create plt for this symbol if it does not have one 232551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 233551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need a PLT entry 234551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 235551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 236551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 237551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 238551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 239551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 240551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 241551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 242551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 243551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines true)) { 244551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // symbol needs dynamic relocation entry, set up the dynrel entry 245551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 246551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 247551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 248551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 249551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else { 250551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set Rel bit and the dyn rel 251551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 252551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 253551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() && 254551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_use_relative_reloc(*rsym, *this)) { 255551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 256551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *pReloc.targetRef().frag(), 257551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.targetRef().offset(), 258551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines R_AARCH64_RELATIVE, 259551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *this); 260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 261551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 262551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else { 263551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 264551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *pReloc.targetRef().frag(), 265551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.targetRef().offset(), 266551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.type(), 267551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *this); 268551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 269551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 270551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 273551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 274551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_PREL64: 275551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_PREL32: 276551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_PREL16: 277551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && 278551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 279551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create plt for this symbol if it does not have one 280551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 281551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need a PLT entry 282551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 283551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 284551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 285551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 286551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 287551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 288551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 289551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 290551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Only PC relative relocation against dynamic symbol needs a 291551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // dynamic relocation. Only dynamic copy relocation is allowed 292551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and PC relative relocation will be resolved to the local copy. 293551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // All other dynamic relocations may lead to run-time relocation 294551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // overflow. 295551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().isDynamicSymbol(*rsym) && 296551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().symbolNeedsDynRel(*rsym, 297551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (rsym->reserved() & ReservePLT), 298551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines false) && 299551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 300551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 301551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 303551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 304551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 305551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_CONDBR19: 306551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_JUMP26: 307551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_CALL26: { 308551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // return if we already create plt for this symbol 309551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & ReservePLT) 310551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 311551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 312551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if the symbol's value can be decided at link time, then no need plt 313551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 314551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 315551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 316551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if symbol is defined in the ouput file and it's not 317551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // preemptible, no need plt 318551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 319551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !getTarget().isSymbolPreemptible(*rsym)) { 320551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 321551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 322551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 323551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 324551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 325551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 326551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 328551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 329551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 330551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 331551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 332551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21: 333551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case R_AARCH64_ADR_PREL_PG_HI21_NC: 334551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, 335551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (rsym->reserved() & ReservePLT), 336551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines false)) { 337551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 338551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 339551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 340551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 341551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 342551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 343551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create plt for this symbol if it does not have one 344551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 345551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need a PLT entry 346551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 347551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 348551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 349551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 350551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 351551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 352551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 353551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 354551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 355551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 356551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 357551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs GOT entry, reserve entry in .got 358551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // return if we already create GOT for this symbol 359551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & ReserveGOT) 360551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 361551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if the symbol cannot be fully resolved at link time, then we need a 362551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // dynamic relocation 363551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!getTarget().symbolFinalValueIsKnown(*rsym)) 364551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_GOT_init(pReloc, true, *this); 365551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 366551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_GOT_init(pReloc, false, *this); 367551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set GOT bit 368551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 369551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 370551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 371551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 372551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines default: 373551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 374551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 375551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 376551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 377551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanRelocation(Relocation& pReloc, 378551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines IRBuilder& pBuilder, 379551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Module& pModule, 380551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection& pSection, 381551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Input& pInput) 382551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 383551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 384551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(NULL != rsym && 385551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines "ResolveInfo of relocation not set while scanRelocation"); 386551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 387551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(NULL != pSection.getLink()); 388551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 389551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 390551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 391551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 392551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // entries should be created. 393551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // FIXME: Below judgements concern nothing about TLS related relocation 394551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 395551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym is local 396551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isLocal()) 397551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines scanLocalReloc(pReloc, pSection); 398551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym is external 399551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 400551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines scanGlobalReloc(pReloc, pBuilder, pSection); 401551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 402551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // check if we shoule issue undefined reference for the relocation target 403551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // symbol 404551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 405551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines issueUndefRef(pReloc, pSection, pInput); 406551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 407551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 408551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 409551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// Each relocation function implementation 410551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 411551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 412551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_NONE 413551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result none(Relocation& pReloc, AArch64Relocator& pParent) 414551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 415551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 416551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 417551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 418551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result unsupport(Relocation& pReloc, AArch64Relocator& pParent) 419551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 420551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Unsupport; 421551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 422551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 423551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS64: S + A 424551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS32: S + A 425551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS16: S + A 426551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result abs(Relocation& pReloc, AArch64Relocator& pParent) 427551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 428551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 429551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 430551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord S = pReloc.symValue(); 431551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 432551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bool has_dyn_rel = (NULL != dyn_rel); 433551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 434551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 435551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If the flag of target section is not ALLOC, we will not scan this 436551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 437551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 438551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = S + A; 439551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 440551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 441551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // A local symbol may need RELATIVE Type dynamic relocation 442551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isLocal() && has_dyn_rel) { 443551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rel->setAddend(S + A); 444551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 445551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 446551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // An external symbol may need PLT and dynamic relocation 447551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!rsym->isLocal()) { 448551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 449551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 450551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 451551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If we generate a dynamic relocation (except R_AARCH64_64_RELATIVE) 452551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // for a place, we should not perform static relocation on it 453551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in order to keep the addend store in the place correct. 454551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (has_dyn_rel) { 455551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() && 456551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines R_AARCH64_RELATIVE == dyn_rel->type()) { 457551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rel->setAddend(S + A); 458551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 459551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else { 460551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rel->setAddend(A); 461551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 462551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 463551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 464551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 465551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 466551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // perform static relocation 467551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = S + A; 468551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 469551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 470551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 471551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL64: S + A - P 472551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL32: S + A - P 473551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL16: S + A - P 474551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result rel(Relocation& pReloc, AArch64Relocator& pParent) 475551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 476551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 477551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 478551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 479551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place(); 480551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 481551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type()) 482551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines A += pReloc.target() & get_mask(pParent.getSize(pReloc.type())); 483551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 484551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines A += pReloc.target(); 485551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 486551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 487551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If the flag of target section is not ALLOC, we will not scan this 488551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 489551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 490551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if plt entry exists, the S value is the plt entry address 491551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!rsym->isLocal()) { 492551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 493551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 494551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 495551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 496551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 497551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 498551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 499551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = X; 500551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 501551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type() && 502551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_check_signed_overflow(X, pParent.getSize(pReloc.type()))) 503551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 504551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 505551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 506551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 507551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADD_ABS_LO12_NC: S + A 508551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result add_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) 509551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 510551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address value = 0x0; 511551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 512551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 513551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 514551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines value = helper_get_page_offset(S + A); 515551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_add_imm(pReloc.target(), value); 516551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 517551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 518551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 519551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 520551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21: ((PG(S + A) - PG(P)) >> 12) 521551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21_NC: ((PG(S + A) - PG(P)) >> 12) 522551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result 523551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesadr_prel_pg_hi21(Relocation& pReloc, AArch64Relocator& pParent) 524551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 525551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 526551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 527551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if plt entry exists, the S value is the plt entry address 528551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 529551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 530551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 531551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 532551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord P = pReloc.place() ; 533551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = helper_get_page_address(S + A) - 534551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_get_page_address(P); 535551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 536551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12)); 537551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 538551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 539551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 540551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 541551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CALL26: S + A - P 542551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_JUMP26: S + A - P 543551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result call(Relocation& pReloc, AArch64Relocator& pParent) 544551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 545551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If target is undefined weak symbol, we only need to jump to the 546551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // next instruction unless it has PLT entry. Rewrite instruction 547551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // to NOP. 548551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (pReloc.symInfo()->isWeak() && 549551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.symInfo()->isUndef() && 550551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !pReloc.symInfo()->isDyn() && 551551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) { 552551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // change target to NOP 553551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = 0xd503201f; 554551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 555551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 556551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 557551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 558551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 559551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 560551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 561551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // S depends on PLT exists or not 562551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT) 563551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 564551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 565551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 566551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // TODO: check overflow.. 567551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 568551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_branch_offset_26(pReloc.target(), X >> 2); 569551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 570551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 571551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 572551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 573551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CONDBR19: S + A - P 574551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result condbr(Relocation& pReloc, AArch64Relocator& pParent) 575551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 576551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If target is undefined weak symbol, we only need to jump to the 577551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // next instruction unless it has PLT entry. Rewrite instruction 578551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // to NOP. 579551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (pReloc.symInfo()->isWeak() && 580551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.symInfo()->isUndef() && 581551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !pReloc.symInfo()->isDyn() && 582551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) { 583551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // change target to NOP 584551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = 0xd503201f; 585551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 586551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 587551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 588551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 589551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 590551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 591551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 592551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // S depends on PLT exists or not 593551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT) 594551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 595551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 596551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 597551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // TODO: check overflow.. 598551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 599551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_cond_branch_ofs_19(pReloc.target(), X >> 2); 600551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 601551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 602551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 603551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 604551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_GOT_PAGE: Page(G(GDAT(S+A))) - Page(P) 605551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result adr_got_page(Relocation& pReloc, AArch64Relocator& pParent) 606551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 607551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) { 608551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 609551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 610551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 611551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 612551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 613551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 614551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = helper_get_page_address(GOT_S + A) - 615551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_get_page_address(P); 616551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 617551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12)); 618551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 619551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup got entry value if needed 620551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 621551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (NULL != got_entry && AArch64Relocator::SymVal == got_entry->getValue()) 622551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines got_entry->setValue(pReloc.symValue()); 623551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup relocation addend if needed 624551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc); 625551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if ((NULL != dyn_rela) && (AArch64Relocator::SymVal == dyn_rela->addend())) { 626551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rela->setAddend(pReloc.symValue()); 627551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 628551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 629551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 630551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 631551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LD64_GOT_LO12_NC: G(GDAT(S+A)) 632551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result ld64_got_lo12(Relocation& pReloc, AArch64Relocator& pParent) 633551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 634551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) { 635551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 636551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 637551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 638551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 639551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 640551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = helper_get_page_offset(GOT_S + A); 641551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 642551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3)); 643551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 644551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup got entry value if needed 645551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 646551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (NULL != got_entry && AArch64Relocator::SymVal == got_entry->getValue()) 647551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines got_entry->setValue(pReloc.symValue()); 648551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 649551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup relocation addend if needed 650551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc); 651551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if ((NULL != dyn_rela) && (AArch64Relocator::SymVal == dyn_rela->addend())) { 652551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rela->setAddend(pReloc.symValue()); 653551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 654551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 655551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 656551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 657551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 658551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST8_ABS_LO12_NC: S + A 659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST16_ABS_LO12_NC: S + A 660551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST32_ABS_LO12_NC: S + A 661551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST64_ABS_LO12_NC: S + A 662551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST128_ABS_LO12_NC: S + A 663551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result ldst_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) 664551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{ 665551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 666551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 667551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = helper_get_page_offset(S + A); 668551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 669551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines switch(pReloc.type()) { 670551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LDST8_ABS_LO12_NC: 671551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), X); 672551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 673551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LDST16_ABS_LO12_NC: 674551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 675551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (X >> 1)); 676551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 677551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LDST32_ABS_LO12_NC: 678551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 679551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (X >> 2)); 680551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 681551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LDST64_ABS_LO12_NC: 682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 683551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (X >> 3)); 684551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 685551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LDST128_ABS_LO12_NC: 686551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 687551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines (X >> 4)); 688551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 689551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines default: 690551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 691551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 692551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 693551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 694551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 695