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 1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h" 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "AArch64Relocator.h" 1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "AArch64RelocationFunctions.h" 1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "AArch64RelocationHelpers.h" 20551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 21551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/ADT/Twine.h> 22551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/DataTypes.h> 23551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/ELF.h> 24551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/Host.h> 25551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 2637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace 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 { 3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines public: 40551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionEntry() {} 41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ApplyFunctionEntry(ApplyFunctionType pFunc, 42551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const char* pName, 43551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines size_t pSize = 0) 4437b74a387bb3993387029859c2d9d051c41c724eStephen 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[] = { 5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines DECL_AARCH64_APPLY_RELOC_FUNC_PTRS(ApplyFunctionMap::value_type, 5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines ApplyFunctionEntry)}; 54551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// declare the table of applying functions 56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic ApplyFunctionMap ApplyFunctions(ApplyFunctionList, 5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines ApplyFunctionList + 5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines sizeof(ApplyFunctionList) / 5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines sizeof(ApplyFunctionList[0])); 60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// AArch64Relocator 63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::AArch64Relocator(AArch64GNULDBackend& pParent, 65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines const LinkerConfig& pConfig) 6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines : Relocator(pConfig), m_Target(pParent) { 67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 68551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 6937b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64Relocator::~AArch64Relocator() { 70551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 7237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result AArch64Relocator::applyRelocation(Relocation& pRelocation) { 73551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation::Type type = pRelocation.type(); 74b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // valid types are 0x0, 0x100-1032, and R_AARCH64_REWRITE_INSN 75b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if ((type < 0x100 || type > 1032) && 76b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines (type != 0x0) && 77b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines (type != R_AARCH64_REWRITE_INSN)) { 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 8437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* AArch64Relocator::getName(Relocator::Type pType) const { 85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(ApplyFunctions.find(pType) != ApplyFunctions.end()); 86551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return ApplyFunctions[pType].name; 87551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 8937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Size AArch64Relocator::getSize(Relocation::Type pType) const { 90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return ApplyFunctions[pType].size; 91551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 92551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 9337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64Relocator::addCopyReloc(ResolveInfo& pSym) { 94551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& rel_entry = *getTarget().getRelaDyn().create(); 95a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines rel_entry.setType(llvm::ELF::R_AARCH64_COPY); 96551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(pSym.outSymbol()->hasFragRef()); 97551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 98551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rel_entry.setSymInfo(&pSym); 99551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 101551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// defineSymbolForCopyReloc 102551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS 103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// section and all other reference to this symbol should refer to this 104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// copy. 105551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// This is executed at scan relocation stage. 106551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesLDSymbol& AArch64Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines const ResolveInfo& pSym) { 108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // get or create corresponding BSS LDSection 109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection* bss_sect_hdr = NULL; 110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ELFFileFormat* file_format = getTarget().getOutputFormat(); 111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (ResolveInfo::ThreadLocal == pSym.type()) 112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_sect_hdr = &file_format->getTBSS(); 113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_sect_hdr = &file_format->getBSS(); 115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // get or create corresponding BSS SectionData 117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines SectionData* bss_data = NULL; 118551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (bss_sect_hdr->hasSectionData()) 119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_data = bss_sect_hdr->getSectionData(); 120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr); 122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 123551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Determine the alignment by the symbol value 124551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // FIXME: here we use the largest alignment 125551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint32_t addralign = config().targets().bitclass() / 8; 126551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // allocate space in BSS for the copy symbol 128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_data, addralign); 130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 131551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 132551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // change symbol binding to Global if it's a weak symbol 133551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 134551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (binding == ResolveInfo::Weak) 135551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines binding = ResolveInfo::Global; 136551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Define the copy symbol in the bss section and resolve it 138551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines pSym.name(), 14037b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Type)pSym.type(), 14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines ResolveInfo::Define, 14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines binding, 14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pSym.size(), // size 14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines 0x0, // value 14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines FragmentRef::Create(*frag, 0x0), 14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Visibility)pSym.other()); 147551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 148551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return *cpy_sym; 149551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 150551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 15137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64Relocator::scanLocalReloc(Relocation& pReloc, 15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines const LDSection& pSection) { 153551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym - The relocation target symbol 154551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 156551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS64: 157551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If buiding PIC object (shared library or PIC executable), 158551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 159551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Reserve an entry in .rel.dyn 160551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (config().isCodeIndep()) { 161551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set Rel bit 162551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 163551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 164551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set up the dyn rel directly 165551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 166551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *pReloc.targetRef().frag(), 167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.targetRef().offset(), 168a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines llvm::ELF::R_AARCH64_RELATIVE, 169551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *this); 170551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 171551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 172551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 173551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 174551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS32: 175551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS16: 176551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If buiding PIC object (shared library or PIC executable), 177551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 178551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Reserve an entry in .rel.dyn 179551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (config().isCodeIndep()) { 180551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set up the dyn rel directly 181551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines *pReloc.targetRef().frag(), 18337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.targetRef().offset(), 18437b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.type(), 18537b74a387bb3993387029859c2d9d051c41c724eStephen Hines *this); 186551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 187551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set Rel bit 188551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 189551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 190551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 191551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 192551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 193551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 194551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 195551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs GOT entry, reserve entry in .got 196551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // return if we already create GOT for this symbol 197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & ReserveGOT) 198551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 199551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If building PIC object, a dynamic relocation with 200551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // type RELATIVE is needed to relocate this GOT entry. 201551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (config().isCodeIndep()) 20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_GOT_init(pReloc, true, *this); 203551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_GOT_init(pReloc, false, *this); 205551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set GOT bit 206551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 207551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 210551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines default: 211551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 212551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 213551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 214551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 215551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanGlobalReloc(Relocation& pReloc, 216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines IRBuilder& pBuilder, 21737b74a387bb3993387029859c2d9d051c41c724eStephen Hines const LDSection& pSection) { 218551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym - The relocation target symbol 219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 22037b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS64: 222551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS32: 223551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ABS16: 224551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 225551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // dynamic relocation entry 226551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 227551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create plt for this symbol if it does not have one 22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 229551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need a PLT entry 230551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 231551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 232551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 233551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 234551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 235551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 236551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 237551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 23837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget() 23937b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), true)) { 241551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // symbol needs dynamic relocation entry, set up the dynrel entry 242551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 243551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 244551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 24537b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 246551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set Rel bit and the dyn rel 247551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 248551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 249551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() && 250551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_use_relative_reloc(*rsym, *this)) { 25104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Relocation& reloc = 25204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines helper_DynRela_init(rsym, 25304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines *pReloc.targetRef().frag(), 25404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines pReloc.targetRef().offset(), 25504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines llvm::ELF::R_AARCH64_RELATIVE, 25604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines *this); 257551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 25837b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 259551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation& reloc = helper_DynRela_init(rsym, 260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *pReloc.targetRef().frag(), 261551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.targetRef().offset(), 262551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.type(), 263551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines *this); 264551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getRelRelMap().record(pReloc, reloc); 265551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 266551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 267551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 268551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 269551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 270551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_PREL64: 271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_PREL32: 272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_PREL16: 273551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && 274551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 275551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create plt for this symbol if it does not have one 27637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 277551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need a PLT entry 278551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 279551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 280551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 281551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 282551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 283551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 284551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 285551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 286551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Only PC relative relocation against dynamic symbol needs a 287551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // dynamic relocation. Only dynamic copy relocation is allowed 288551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and PC relative relocation will be resolved to the local copy. 289551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // All other dynamic relocations may lead to run-time relocation 290551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // overflow. 291551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().isDynamicSymbol(*rsym) && 29237b74a387bb3993387029859c2d9d051c41c724eStephen Hines getTarget() 29337b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), false) && 295551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 296551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 297551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 298551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 299551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 300551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 301551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_CONDBR19: 302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_JUMP26: 303551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_CALL26: { 304551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // return if we already create plt for this symbol 305551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & ReservePLT) 306551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 307551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 308551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if the symbol's value can be decided at link time, then no need plt 309551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 310551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 311551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 312551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if symbol is defined in the ouput file and it's not 313551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // preemptible, no need plt 314551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 31537b74a387bb3993387029859c2d9d051c41c724eStephen Hines !getTarget().isSymbolPreemptible(*rsym)) { 316551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 317551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 318551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 319551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 320551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 321551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 322551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 323551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 324551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 325551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 326551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 328a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines case llvm::ELF::R_AARCH64_ADR_PREL_LO21: 329551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21: 330a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 33137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget() 33237b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 33337b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), false)) { 334551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 335551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 336551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 337551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 338551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 339551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 340551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create plt for this symbol if it does not have one 34137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 342551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs PLT entry, we need a PLT entry 343551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // and the corresponding GOT and dynamic relocation entry 344551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in .got and .rel.plt. 345551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_PLT_init(pReloc, *this); 346551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set PLT bit 347551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 348551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 349551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 350551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 351551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 352551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 353551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 354551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Symbol needs GOT entry, reserve entry in .got 355551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // return if we already create GOT for this symbol 356551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & ReserveGOT) 357551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 358551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if the symbol cannot be fully resolved at link time, then we need a 359551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // dynamic relocation 360551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!getTarget().symbolFinalValueIsKnown(*rsym)) 361551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_GOT_init(pReloc, true, *this); 362551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 363551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_GOT_init(pReloc, false, *this); 364551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // set GOT bit 365551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 366551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 367551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 368551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 369551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines default: 370551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines break; 371551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 372551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 373551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 374551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanRelocation(Relocation& pReloc, 375551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines IRBuilder& pBuilder, 376551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Module& pModule, 377551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection& pSection, 37837b74a387bb3993387029859c2d9d051c41c724eStephen Hines Input& pInput) { 379551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 38037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(rsym != NULL && 381551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines "ResolveInfo of relocation not set while scanRelocation"); 382551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 38337b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pSection.getLink() != NULL); 38437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0) 385551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return; 386551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 387551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 388551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // entries should be created. 389551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // FIXME: Below judgements concern nothing about TLS related relocation 390551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 391551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym is local 392551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isLocal()) 393551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines scanLocalReloc(pReloc, pSection); 394551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // rsym is external 395551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 396551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines scanGlobalReloc(pReloc, pBuilder, pSection); 397551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 398551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // check if we shoule issue undefined reference for the relocation target 399551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // symbol 400551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 401551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines issueUndefRef(pReloc, pSection, pInput); 402551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 403551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 404b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesbool 405b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesAArch64Relocator::mayHaveFunctionPointerAccess(const Relocation& pReloc) const { 406b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines switch (pReloc.type()) { 407b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21: 408b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21_NC: 409b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_AARCH64_ADD_ABS_LO12_NC: 410b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 411b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 412b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return true; 413b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 414b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines default: { 415b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pReloc.symInfo()->isLocal()) { 416b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // Do not fold any local symbols if building a shared object. 417b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return (config().codeGenType() == LinkerConfig::DynObj); 418b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else { 419b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // Do not fold any none global defualt symbols if building a shared 420b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // object. 421b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return ((config().codeGenType() == LinkerConfig::DynObj) && 422b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines (pReloc.symInfo()->visibility() != ResolveInfo::Default)); 423b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 424b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 425b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 426b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return false; 427b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 428b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 42937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t AArch64Relocator::getDebugStringOffset(Relocation& pReloc) const { 43037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.type() != llvm::ELF::R_AARCH64_ABS32) 43137b74a387bb3993387029859c2d9d051c41c724eStephen Hines error(diag::unsupport_reloc_for_debug_string) 43237b74a387bb3993387029859c2d9d051c41c724eStephen Hines << getName(pReloc.type()) << "mclinker@googlegroups.com"; 43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines 43437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->type() == ResolveInfo::Section) 435fda4bbd63841e8ae3418637b24b7416f6bf56ca6Stephen McGroarty return pReloc.target() + pReloc.addend(); 43637b74a387bb3993387029859c2d9d051c41c724eStephen Hines else 43737b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pReloc.symInfo()->outSymbol()->fragRef()->offset() + 43837b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() + pReloc.addend(); 43937b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 44037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 44137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64Relocator::applyDebugStringOffset(Relocation& pReloc, 44237b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint32_t pOffset) { 44337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = pOffset; 44437b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines 446551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 447551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// Each relocation function implementation 448551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===// 449551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 450551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_NONE 45137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result none(Relocation& pReloc, AArch64Relocator& pParent) { 452551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 453551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 454551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 45537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result unsupported(Relocation& pReloc, AArch64Relocator& pParent) { 45637b74a387bb3993387029859c2d9d051c41c724eStephen Hines return Relocator::Unsupported; 457551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 458551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 459551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS64: S + A 460551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS32: S + A 461551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS16: S + A 46237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result abs(Relocation& pReloc, AArch64Relocator& pParent) { 463551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 464551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 465551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord S = pReloc.symValue(); 466551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 46737b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool has_dyn_rel = (dyn_rel != NULL); 468551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 469551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 470551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If the flag of target section is not ALLOC, we will not scan this 471551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 472551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 473551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = S + A; 474551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 475551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 476551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // A local symbol may need RELATIVE Type dynamic relocation 477551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->isLocal() && has_dyn_rel) { 478551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rel->setAddend(S + A); 479551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 480551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 481551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // An external symbol may need PLT and dynamic relocation 482551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!rsym->isLocal()) { 483551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 484551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 485551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 486551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If we generate a dynamic relocation (except R_AARCH64_64_RELATIVE) 487551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // for a place, we should not perform static relocation on it 488551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // in order to keep the addend store in the place correct. 489551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (has_dyn_rel) { 490551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() && 491a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines llvm::ELF::R_AARCH64_RELATIVE == dyn_rel->type()) { 492551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rel->setAddend(S + A); 49337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 494551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rel->setAddend(A); 495551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 496551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 497551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 498551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 499551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 500551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // perform static relocation 501551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = S + A; 502551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 503551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 504551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 505551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL64: S + A - P 506551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL32: S + A - P 507551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL16: S + A - P 50837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result rel(Relocation& pReloc, AArch64Relocator& pParent) { 509551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 510551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 51137b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.addend(); 51237b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord P = pReloc.place(); 513551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 514551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type()) 51537b74a387bb3993387029859c2d9d051c41c724eStephen Hines A += pReloc.target() & get_mask(pParent.getSize(pReloc.type())); 516551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines else 517551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines A += pReloc.target(); 518551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 519551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 520551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If the flag of target section is not ALLOC, we will not scan this 521551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 522551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 523551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if plt entry exists, the S value is the plt entry address 524551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!rsym->isLocal()) { 525551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 526551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 527551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 528551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 529551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 530551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 531551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 532551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = X; 533551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 534551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type() && 535551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines helper_check_signed_overflow(X, pParent.getSize(pReloc.type()))) 536551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 537551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 538551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 539551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 540551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADD_ABS_LO12_NC: S + A 54137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result add_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) { 542551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address value = 0x0; 543551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 54437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.addend(); 545551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 546551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines value = helper_get_page_offset(S + A); 547551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_add_imm(pReloc.target(), value); 548551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 549551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 550551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 551551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 552a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// R_AARCH64_ADR_PREL_LO21: S + A - P 553a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen HinesRelocator::Result adr_prel_lo21(Relocation& pReloc, AArch64Relocator& pParent) { 554a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 555a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Relocator::Address S = pReloc.symValue(); 556a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // if plt entry exists, the S value is the plt entry address 557a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 558a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 559a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 560a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Relocator::DWord A = pReloc.addend(); 561a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Relocator::DWord P = pReloc.place(); 562a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Relocator::DWord X = S + A - P; 563a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 564a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines pReloc.target() = helper_reencode_adr_imm(pReloc.target(), X); 565a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 566a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines return Relocator::OK; 567a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} 568a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 569551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21: ((PG(S + A) - PG(P)) >> 12) 570551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21_NC: ((PG(S + A) - PG(P)) >> 12) 57137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result adr_prel_pg_hi21(Relocation& pReloc, 57237b74a387bb3993387029859c2d9d051c41c724eStephen Hines AArch64Relocator& pParent) { 573551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 574551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 575551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // if plt entry exists, the S value is the plt entry address 576551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (rsym->reserved() & AArch64Relocator::ReservePLT) { 577551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*rsym, pParent); 578551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 579551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 58037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord P = pReloc.place(); 58137b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord X = 58237b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_get_page_address(S + A) - helper_get_page_address(P); 583551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 584551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12)); 585551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 586551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 587551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 588551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 589551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CALL26: S + A - P 590551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_JUMP26: S + A - P 59137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result call(Relocation& pReloc, AArch64Relocator& pParent) { 592551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If target is undefined weak symbol, we only need to jump to the 593551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // next instruction unless it has PLT entry. Rewrite instruction 594551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // to NOP. 59537b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() && 596551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !pReloc.symInfo()->isDyn() && 597551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) { 598551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // change target to NOP 599551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = 0xd503201f; 600551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 601551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 602551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 603551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 60437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.addend(); 605551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 606551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 607551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // S depends on PLT exists or not 608551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT) 609551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 610551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 611551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 612551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // TODO: check overflow.. 613551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 614551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_branch_offset_26(pReloc.target(), X >> 2); 615551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 616551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 617551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 618551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 619551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CONDBR19: S + A - P 62037b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result condbr(Relocation& pReloc, AArch64Relocator& pParent) { 621551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // If target is undefined weak symbol, we only need to jump to the 622551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // next instruction unless it has PLT entry. Rewrite instruction 623551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // to NOP. 62437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() && 625551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !pReloc.symInfo()->isDyn() && 626551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) { 627551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // change target to NOP 628551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = 0xd503201f; 629551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 630551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 631551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 632551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 63337b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.addend(); 634551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 635551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 636551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // S depends on PLT exists or not 637551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT) 638551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 639551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 640551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = S + A - P; 641551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // TODO: check overflow.. 642551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 643551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_cond_branch_ofs_19(pReloc.target(), X >> 2); 644551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 645551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 646551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 647551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 648551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_GOT_PAGE: Page(G(GDAT(S+A))) - Page(P) 64937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result adr_got_page(Relocation& pReloc, AArch64Relocator& pParent) { 650551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) { 651551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 652551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 653551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 654551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 655551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 656551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord X = 65837b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_get_page_address(GOT_S + A) - helper_get_page_address(P); 659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 660551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12)); 661551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 662551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup got entry value if needed 663551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 66437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (got_entry != NULL && AArch64Relocator::SymVal == got_entry->getValue()) 665551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines got_entry->setValue(pReloc.symValue()); 666551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup relocation addend if needed 667551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc); 66837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((dyn_rela != NULL) && (AArch64Relocator::SymVal == dyn_rela->addend())) { 669551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rela->setAddend(pReloc.symValue()); 670551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 671551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 672551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 673551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 674551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LD64_GOT_LO12_NC: G(GDAT(S+A)) 67537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result ld64_got_lo12(Relocation& pReloc, AArch64Relocator& pParent) { 676551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) { 677551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 678551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 679551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 680551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 681551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = helper_get_page_offset(GOT_S + A); 683551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 684551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3)); 685551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 686551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup got entry value if needed 687551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 68837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (got_entry != NULL && AArch64Relocator::SymVal == got_entry->getValue()) 689551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines got_entry->setValue(pReloc.symValue()); 690551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 691551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // setup relocation addend if needed 692551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc); 69337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((dyn_rela != NULL) && (AArch64Relocator::SymVal == dyn_rela->addend())) { 694551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines dyn_rela->setAddend(pReloc.symValue()); 695551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 696551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 697551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 698551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 699551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 700551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST8_ABS_LO12_NC: S + A 701551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST16_ABS_LO12_NC: S + A 702551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST32_ABS_LO12_NC: S + A 703551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST64_ABS_LO12_NC: S + A 704551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST128_ABS_LO12_NC: S + A 70537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result ldst_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) { 706551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 707551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord A = pReloc.addend(); 708551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::DWord X = helper_get_page_offset(S + A); 709551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 71037b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 71137b74a387bb3993387029859c2d9d051c41c724eStephen Hines case llvm::ELF::R_AARCH64_LDST8_ABS_LO12_NC: 71237b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), X); 71337b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 71437b74a387bb3993387029859c2d9d051c41c724eStephen Hines case llvm::ELF::R_AARCH64_LDST16_ABS_LO12_NC: 71537b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 1)); 71637b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines case llvm::ELF::R_AARCH64_LDST32_ABS_LO12_NC: 71837b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 2)); 71937b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 72037b74a387bb3993387029859c2d9d051c41c724eStephen Hines case llvm::ELF::R_AARCH64_LDST64_ABS_LO12_NC: 72137b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3)); 72237b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 72337b74a387bb3993387029859c2d9d051c41c724eStephen Hines case llvm::ELF::R_AARCH64_LDST128_ABS_LO12_NC: 72437b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 4)); 72537b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 726551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines default: 72737b74a387bb3993387029859c2d9d051c41c724eStephen Hines break; 728551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines } 729551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 730551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines} 731551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines 73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 733