10b57cec5SDimitry Andric //===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implementation of ELF support for the MC-JIT runtime dynamic linker. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "RuntimeDyldELF.h" 140b57cec5SDimitry Andric #include "RuntimeDyldCheckerImpl.h" 150b57cec5SDimitry Andric #include "Targets/RuntimeDyldELFMips.h" 160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 180b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 190b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 200b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 210b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 220b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 2306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric using namespace llvm::object; 270b57cec5SDimitry Andric using namespace llvm::support::endian; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric #define DEBUG_TYPE "dyld" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric static void or32le(void *P, int32_t V) { write32le(P, read32le(P) | V); } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric static void or32AArch64Imm(void *L, uint64_t Imm) { 340b57cec5SDimitry Andric or32le(L, (Imm & 0xFFF) << 10); 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric template <class T> static void write(bool isBE, void *P, T V) { 385f757f3fSDimitry Andric isBE ? write<T, llvm::endianness::big>(P, V) 395f757f3fSDimitry Andric : write<T, llvm::endianness::little>(P, V); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric static void write32AArch64Addr(void *L, uint64_t Imm) { 430b57cec5SDimitry Andric uint32_t ImmLo = (Imm & 0x3) << 29; 440b57cec5SDimitry Andric uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; 450b57cec5SDimitry Andric uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); 460b57cec5SDimitry Andric write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric // Return the bits [Start, End] from Val shifted Start bits. 500b57cec5SDimitry Andric // For instance, getBits(0xF0, 4, 8) returns 0xF. 510b57cec5SDimitry Andric static uint64_t getBits(uint64_t Val, int Start, int End) { 520b57cec5SDimitry Andric uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1; 530b57cec5SDimitry Andric return (Val >> Start) & Mask; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric namespace { 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { 590b57cec5SDimitry Andric LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric typedef typename ELFT::uint addr_type; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric DyldELFObject(ELFObjectFile<ELFT> &&Obj); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric public: 660b57cec5SDimitry Andric static Expected<std::unique_ptr<DyldELFObject>> 670b57cec5SDimitry Andric create(MemoryBufferRef Wrapper); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric // Methods for type inquiry through isa, cast and dyn_cast 740b57cec5SDimitry Andric static bool classof(const Binary *v) { 750b57cec5SDimitry Andric return (isa<ELFObjectFile<ELFT>>(v) && 760b57cec5SDimitry Andric classof(cast<ELFObjectFile<ELFT>>(v))); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric static bool classof(const ELFObjectFile<ELFT> *v) { 790b57cec5SDimitry Andric return v->isDyldType(); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric }; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric // The MemoryBuffer passed into this constructor is just a wrapper around the 860b57cec5SDimitry Andric // actual memory. Ultimately, the Binary parent class will take ownership of 870b57cec5SDimitry Andric // this MemoryBuffer object but not the underlying memory. 880b57cec5SDimitry Andric template <class ELFT> 890b57cec5SDimitry Andric DyldELFObject<ELFT>::DyldELFObject(ELFObjectFile<ELFT> &&Obj) 900b57cec5SDimitry Andric : ELFObjectFile<ELFT>(std::move(Obj)) { 910b57cec5SDimitry Andric this->isDyldELFObject = true; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric template <class ELFT> 950b57cec5SDimitry Andric Expected<std::unique_ptr<DyldELFObject<ELFT>>> 960b57cec5SDimitry Andric DyldELFObject<ELFT>::create(MemoryBufferRef Wrapper) { 970b57cec5SDimitry Andric auto Obj = ELFObjectFile<ELFT>::create(Wrapper); 980b57cec5SDimitry Andric if (auto E = Obj.takeError()) 990b57cec5SDimitry Andric return std::move(E); 1000b57cec5SDimitry Andric std::unique_ptr<DyldELFObject<ELFT>> Ret( 1010b57cec5SDimitry Andric new DyldELFObject<ELFT>(std::move(*Obj))); 1020b57cec5SDimitry Andric return std::move(Ret); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric template <class ELFT> 1060b57cec5SDimitry Andric void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec, 1070b57cec5SDimitry Andric uint64_t Addr) { 1080b57cec5SDimitry Andric DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); 1090b57cec5SDimitry Andric Elf_Shdr *shdr = 1100b57cec5SDimitry Andric const_cast<Elf_Shdr *>(reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // This assumes the address passed in matches the target address bitness 1130b57cec5SDimitry Andric // The template-based type cast handles everything else. 1140b57cec5SDimitry Andric shdr->sh_addr = static_cast<addr_type>(Addr); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric template <class ELFT> 1180b57cec5SDimitry Andric void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, 1190b57cec5SDimitry Andric uint64_t Addr) { 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric Elf_Sym *sym = const_cast<Elf_Sym *>( 1220b57cec5SDimitry Andric ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl())); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // This assumes the address passed in matches the target address bitness 1250b57cec5SDimitry Andric // The template-based type cast handles everything else. 1260b57cec5SDimitry Andric sym->st_value = static_cast<addr_type>(Addr); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric class LoadedELFObjectInfo final 1300b57cec5SDimitry Andric : public LoadedObjectInfoHelper<LoadedELFObjectInfo, 1310b57cec5SDimitry Andric RuntimeDyld::LoadedObjectInfo> { 1320b57cec5SDimitry Andric public: 1330b57cec5SDimitry Andric LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap) 1340b57cec5SDimitry Andric : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {} 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric OwningBinary<ObjectFile> 1370b57cec5SDimitry Andric getObjectForDebug(const ObjectFile &Obj) const override; 1380b57cec5SDimitry Andric }; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric template <typename ELFT> 1410b57cec5SDimitry Andric static Expected<std::unique_ptr<DyldELFObject<ELFT>>> 1420b57cec5SDimitry Andric createRTDyldELFObject(MemoryBufferRef Buffer, const ObjectFile &SourceObject, 1430b57cec5SDimitry Andric const LoadedELFObjectInfo &L) { 1440b57cec5SDimitry Andric typedef typename ELFT::Shdr Elf_Shdr; 1450b57cec5SDimitry Andric typedef typename ELFT::uint addr_type; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric Expected<std::unique_ptr<DyldELFObject<ELFT>>> ObjOrErr = 1480b57cec5SDimitry Andric DyldELFObject<ELFT>::create(Buffer); 1490b57cec5SDimitry Andric if (Error E = ObjOrErr.takeError()) 1500b57cec5SDimitry Andric return std::move(E); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric std::unique_ptr<DyldELFObject<ELFT>> Obj = std::move(*ObjOrErr); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric // Iterate over all sections in the object. 1550b57cec5SDimitry Andric auto SI = SourceObject.section_begin(); 1560b57cec5SDimitry Andric for (const auto &Sec : Obj->sections()) { 1578bcb0991SDimitry Andric Expected<StringRef> NameOrErr = Sec.getName(); 1588bcb0991SDimitry Andric if (!NameOrErr) { 1598bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 1608bcb0991SDimitry Andric continue; 1618bcb0991SDimitry Andric } 1628bcb0991SDimitry Andric 1638bcb0991SDimitry Andric if (*NameOrErr != "") { 1640b57cec5SDimitry Andric DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); 1650b57cec5SDimitry Andric Elf_Shdr *shdr = const_cast<Elf_Shdr *>( 1660b57cec5SDimitry Andric reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric if (uint64_t SecLoadAddr = L.getSectionLoadAddress(*SI)) { 1690b57cec5SDimitry Andric // This assumes that the address passed in matches the target address 1700b57cec5SDimitry Andric // bitness. The template-based type cast handles everything else. 1710b57cec5SDimitry Andric shdr->sh_addr = static_cast<addr_type>(SecLoadAddr); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric ++SI; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric return std::move(Obj); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric static OwningBinary<ObjectFile> 1810b57cec5SDimitry Andric createELFDebugObject(const ObjectFile &Obj, const LoadedELFObjectInfo &L) { 1820b57cec5SDimitry Andric assert(Obj.isELF() && "Not an ELF object file."); 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Buffer = 1850b57cec5SDimitry Andric MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName()); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> DebugObj(nullptr); 1880b57cec5SDimitry Andric handleAllErrors(DebugObj.takeError()); 1890b57cec5SDimitry Andric if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) 1900b57cec5SDimitry Andric DebugObj = 1910b57cec5SDimitry Andric createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), Obj, L); 1920b57cec5SDimitry Andric else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) 1930b57cec5SDimitry Andric DebugObj = 1940b57cec5SDimitry Andric createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), Obj, L); 1950b57cec5SDimitry Andric else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) 1960b57cec5SDimitry Andric DebugObj = 1970b57cec5SDimitry Andric createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), Obj, L); 1980b57cec5SDimitry Andric else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) 1990b57cec5SDimitry Andric DebugObj = 2000b57cec5SDimitry Andric createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), Obj, L); 2010b57cec5SDimitry Andric else 2020b57cec5SDimitry Andric llvm_unreachable("Unexpected ELF format"); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric handleAllErrors(DebugObj.takeError()); 2050b57cec5SDimitry Andric return OwningBinary<ObjectFile>(std::move(*DebugObj), std::move(Buffer)); 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric OwningBinary<ObjectFile> 2090b57cec5SDimitry Andric LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { 2100b57cec5SDimitry Andric return createELFDebugObject(Obj, *this); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric } // anonymous namespace 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric namespace llvm { 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, 2180b57cec5SDimitry Andric JITSymbolResolver &Resolver) 2190b57cec5SDimitry Andric : RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0), CurrentGOTIndex(0) {} 22081ad6265SDimitry Andric RuntimeDyldELF::~RuntimeDyldELF() = default; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric void RuntimeDyldELF::registerEHFrames() { 223*0fca6ea1SDimitry Andric for (SID EHFrameSID : UnregisteredEHFrameSections) { 2240b57cec5SDimitry Andric uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress(); 2250b57cec5SDimitry Andric uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress(); 2260b57cec5SDimitry Andric size_t EHFrameSize = Sections[EHFrameSID].getSize(); 2270b57cec5SDimitry Andric MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric UnregisteredEHFrameSections.clear(); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric std::unique_ptr<RuntimeDyldELF> 2330b57cec5SDimitry Andric llvm::RuntimeDyldELF::create(Triple::ArchType Arch, 2340b57cec5SDimitry Andric RuntimeDyld::MemoryManager &MemMgr, 2350b57cec5SDimitry Andric JITSymbolResolver &Resolver) { 2360b57cec5SDimitry Andric switch (Arch) { 2370b57cec5SDimitry Andric default: 2388bcb0991SDimitry Andric return std::make_unique<RuntimeDyldELF>(MemMgr, Resolver); 2390b57cec5SDimitry Andric case Triple::mips: 2400b57cec5SDimitry Andric case Triple::mipsel: 2410b57cec5SDimitry Andric case Triple::mips64: 2420b57cec5SDimitry Andric case Triple::mips64el: 2438bcb0991SDimitry Andric return std::make_unique<RuntimeDyldELFMips>(MemMgr, Resolver); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric std::unique_ptr<RuntimeDyld::LoadedObjectInfo> 2480b57cec5SDimitry Andric RuntimeDyldELF::loadObject(const object::ObjectFile &O) { 2490b57cec5SDimitry Andric if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) 2508bcb0991SDimitry Andric return std::make_unique<LoadedELFObjectInfo>(*this, *ObjSectionToIDOrErr); 2510b57cec5SDimitry Andric else { 2520b57cec5SDimitry Andric HasError = true; 2530b57cec5SDimitry Andric raw_string_ostream ErrStream(ErrorStr); 2540b57cec5SDimitry Andric logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream); 2550b57cec5SDimitry Andric return nullptr; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, 2600b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 2610b57cec5SDimitry Andric uint32_t Type, int64_t Addend, 2620b57cec5SDimitry Andric uint64_t SymOffset) { 2630b57cec5SDimitry Andric switch (Type) { 2640b57cec5SDimitry Andric default: 2651106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 2660b57cec5SDimitry Andric break; 2670b57cec5SDimitry Andric case ELF::R_X86_64_NONE: 2680b57cec5SDimitry Andric break; 269fe6060f1SDimitry Andric case ELF::R_X86_64_8: { 270fe6060f1SDimitry Andric Value += Addend; 271fe6060f1SDimitry Andric assert((int64_t)Value <= INT8_MAX && (int64_t)Value >= INT8_MIN); 272fe6060f1SDimitry Andric uint8_t TruncatedAddr = (Value & 0xFF); 273fe6060f1SDimitry Andric *Section.getAddressWithOffset(Offset) = TruncatedAddr; 274fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at " 275fe6060f1SDimitry Andric << format("%p\n", Section.getAddressWithOffset(Offset))); 276fe6060f1SDimitry Andric break; 277fe6060f1SDimitry Andric } 278fe6060f1SDimitry Andric case ELF::R_X86_64_16: { 279fe6060f1SDimitry Andric Value += Addend; 280fe6060f1SDimitry Andric assert((int64_t)Value <= INT16_MAX && (int64_t)Value >= INT16_MIN); 281fe6060f1SDimitry Andric uint16_t TruncatedAddr = (Value & 0xFFFF); 282fe6060f1SDimitry Andric support::ulittle16_t::ref(Section.getAddressWithOffset(Offset)) = 283fe6060f1SDimitry Andric TruncatedAddr; 284fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at " 285fe6060f1SDimitry Andric << format("%p\n", Section.getAddressWithOffset(Offset))); 286fe6060f1SDimitry Andric break; 287fe6060f1SDimitry Andric } 2880b57cec5SDimitry Andric case ELF::R_X86_64_64: { 2890b57cec5SDimitry Andric support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = 2900b57cec5SDimitry Andric Value + Addend; 2910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " 2920b57cec5SDimitry Andric << format("%p\n", Section.getAddressWithOffset(Offset))); 2930b57cec5SDimitry Andric break; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric case ELF::R_X86_64_32: 2960b57cec5SDimitry Andric case ELF::R_X86_64_32S: { 2970b57cec5SDimitry Andric Value += Addend; 2980b57cec5SDimitry Andric assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) || 2990b57cec5SDimitry Andric (Type == ELF::R_X86_64_32S && 3000b57cec5SDimitry Andric ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN))); 3010b57cec5SDimitry Andric uint32_t TruncatedAddr = (Value & 0xFFFFFFFF); 3020b57cec5SDimitry Andric support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = 3030b57cec5SDimitry Andric TruncatedAddr; 3040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at " 3050b57cec5SDimitry Andric << format("%p\n", Section.getAddressWithOffset(Offset))); 3060b57cec5SDimitry Andric break; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric case ELF::R_X86_64_PC8: { 3090b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 3100b57cec5SDimitry Andric int64_t RealOffset = Value + Addend - FinalAddress; 3110b57cec5SDimitry Andric assert(isInt<8>(RealOffset)); 3120b57cec5SDimitry Andric int8_t TruncOffset = (RealOffset & 0xFF); 3130b57cec5SDimitry Andric Section.getAddress()[Offset] = TruncOffset; 3140b57cec5SDimitry Andric break; 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric case ELF::R_X86_64_PC32: { 3170b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 3180b57cec5SDimitry Andric int64_t RealOffset = Value + Addend - FinalAddress; 3190b57cec5SDimitry Andric assert(isInt<32>(RealOffset)); 3200b57cec5SDimitry Andric int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); 3210b57cec5SDimitry Andric support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = 3220b57cec5SDimitry Andric TruncOffset; 3230b57cec5SDimitry Andric break; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric case ELF::R_X86_64_PC64: { 3260b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 3270b57cec5SDimitry Andric int64_t RealOffset = Value + Addend - FinalAddress; 3280b57cec5SDimitry Andric support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = 3290b57cec5SDimitry Andric RealOffset; 3300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", RealOffset) << " at " 3310b57cec5SDimitry Andric << format("%p\n", FinalAddress)); 3320b57cec5SDimitry Andric break; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric case ELF::R_X86_64_GOTOFF64: { 3350b57cec5SDimitry Andric // Compute Value - GOTBase. 3360b57cec5SDimitry Andric uint64_t GOTBase = 0; 3370b57cec5SDimitry Andric for (const auto &Section : Sections) { 3380b57cec5SDimitry Andric if (Section.getName() == ".got") { 3390b57cec5SDimitry Andric GOTBase = Section.getLoadAddressWithOffset(0); 3400b57cec5SDimitry Andric break; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric assert(GOTBase != 0 && "missing GOT"); 3440b57cec5SDimitry Andric int64_t GOTOffset = Value - GOTBase + Addend; 3450b57cec5SDimitry Andric support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = GOTOffset; 3460b57cec5SDimitry Andric break; 3470b57cec5SDimitry Andric } 348349cc55cSDimitry Andric case ELF::R_X86_64_DTPMOD64: { 349349cc55cSDimitry Andric // We only have one DSO, so the module id is always 1. 350349cc55cSDimitry Andric support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = 1; 351349cc55cSDimitry Andric break; 352349cc55cSDimitry Andric } 353349cc55cSDimitry Andric case ELF::R_X86_64_DTPOFF64: 354349cc55cSDimitry Andric case ELF::R_X86_64_TPOFF64: { 355349cc55cSDimitry Andric // DTPOFF64 should resolve to the offset in the TLS block, TPOFF64 to the 356349cc55cSDimitry Andric // offset in the *initial* TLS block. Since we are statically linking, all 357349cc55cSDimitry Andric // TLS blocks already exist in the initial block, so resolve both 358349cc55cSDimitry Andric // relocations equally. 359349cc55cSDimitry Andric support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = 360349cc55cSDimitry Andric Value + Addend; 361349cc55cSDimitry Andric break; 362349cc55cSDimitry Andric } 363349cc55cSDimitry Andric case ELF::R_X86_64_DTPOFF32: 364349cc55cSDimitry Andric case ELF::R_X86_64_TPOFF32: { 365349cc55cSDimitry Andric // As for the (D)TPOFF64 relocations above, both DTPOFF32 and TPOFF32 can 366349cc55cSDimitry Andric // be resolved equally. 367349cc55cSDimitry Andric int64_t RealValue = Value + Addend; 368349cc55cSDimitry Andric assert(RealValue >= INT32_MIN && RealValue <= INT32_MAX); 369349cc55cSDimitry Andric int32_t TruncValue = RealValue; 370349cc55cSDimitry Andric support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = 371349cc55cSDimitry Andric TruncValue; 372349cc55cSDimitry Andric break; 373349cc55cSDimitry Andric } 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, 3780b57cec5SDimitry Andric uint64_t Offset, uint32_t Value, 3790b57cec5SDimitry Andric uint32_t Type, int32_t Addend) { 3800b57cec5SDimitry Andric switch (Type) { 3810b57cec5SDimitry Andric case ELF::R_386_32: { 3820b57cec5SDimitry Andric support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = 3830b57cec5SDimitry Andric Value + Addend; 3840b57cec5SDimitry Andric break; 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric // Handle R_386_PLT32 like R_386_PC32 since it should be able to 3870b57cec5SDimitry Andric // reach any 32 bit address. 3880b57cec5SDimitry Andric case ELF::R_386_PLT32: 3890b57cec5SDimitry Andric case ELF::R_386_PC32: { 3900b57cec5SDimitry Andric uint32_t FinalAddress = 3910b57cec5SDimitry Andric Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF; 3920b57cec5SDimitry Andric uint32_t RealOffset = Value + Addend - FinalAddress; 3930b57cec5SDimitry Andric support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = 3940b57cec5SDimitry Andric RealOffset; 3950b57cec5SDimitry Andric break; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric default: 3980b57cec5SDimitry Andric // There are other relocation types, but it appears these are the 3990b57cec5SDimitry Andric // only ones currently used by the LLVM ELF object writer 4001106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 4010b57cec5SDimitry Andric break; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, 4060b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 4070b57cec5SDimitry Andric uint32_t Type, int64_t Addend) { 4080b57cec5SDimitry Andric uint32_t *TargetPtr = 4090b57cec5SDimitry Andric reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset)); 4100b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 4110b57cec5SDimitry Andric // Data should use target endian. Code should always use little endian. 4120b57cec5SDimitry Andric bool isBE = Arch == Triple::aarch64_be; 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x" 4150b57cec5SDimitry Andric << format("%llx", Section.getAddressWithOffset(Offset)) 4160b57cec5SDimitry Andric << " FinalAddress: 0x" << format("%llx", FinalAddress) 4170b57cec5SDimitry Andric << " Value: 0x" << format("%llx", Value) << " Type: 0x" 4180b57cec5SDimitry Andric << format("%x", Type) << " Addend: 0x" 4190b57cec5SDimitry Andric << format("%llx", Addend) << "\n"); 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric switch (Type) { 4220b57cec5SDimitry Andric default: 4231106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 4240b57cec5SDimitry Andric break; 42504eeddc0SDimitry Andric case ELF::R_AARCH64_NONE: 42604eeddc0SDimitry Andric break; 4270b57cec5SDimitry Andric case ELF::R_AARCH64_ABS16: { 4280b57cec5SDimitry Andric uint64_t Result = Value + Addend; 42906c3fb27SDimitry Andric assert(Result == static_cast<uint64_t>(llvm::SignExtend64(Result, 16)) || 43006c3fb27SDimitry Andric (Result >> 16) == 0); 4310b57cec5SDimitry Andric write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU)); 4320b57cec5SDimitry Andric break; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric case ELF::R_AARCH64_ABS32: { 4350b57cec5SDimitry Andric uint64_t Result = Value + Addend; 43606c3fb27SDimitry Andric assert(Result == static_cast<uint64_t>(llvm::SignExtend64(Result, 32)) || 43706c3fb27SDimitry Andric (Result >> 32) == 0); 4380b57cec5SDimitry Andric write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU)); 4390b57cec5SDimitry Andric break; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric case ELF::R_AARCH64_ABS64: 4420b57cec5SDimitry Andric write(isBE, TargetPtr, Value + Addend); 4430b57cec5SDimitry Andric break; 4445ffd83dbSDimitry Andric case ELF::R_AARCH64_PLT32: { 4455ffd83dbSDimitry Andric uint64_t Result = Value + Addend - FinalAddress; 4465ffd83dbSDimitry Andric assert(static_cast<int64_t>(Result) >= INT32_MIN && 4475ffd83dbSDimitry Andric static_cast<int64_t>(Result) <= INT32_MAX); 4485ffd83dbSDimitry Andric write(isBE, TargetPtr, static_cast<uint32_t>(Result)); 4495ffd83dbSDimitry Andric break; 4505ffd83dbSDimitry Andric } 45181ad6265SDimitry Andric case ELF::R_AARCH64_PREL16: { 45281ad6265SDimitry Andric uint64_t Result = Value + Addend - FinalAddress; 45381ad6265SDimitry Andric assert(static_cast<int64_t>(Result) >= INT16_MIN && 45481ad6265SDimitry Andric static_cast<int64_t>(Result) <= UINT16_MAX); 45581ad6265SDimitry Andric write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU)); 45681ad6265SDimitry Andric break; 45781ad6265SDimitry Andric } 4580b57cec5SDimitry Andric case ELF::R_AARCH64_PREL32: { 4590b57cec5SDimitry Andric uint64_t Result = Value + Addend - FinalAddress; 4600b57cec5SDimitry Andric assert(static_cast<int64_t>(Result) >= INT32_MIN && 4610b57cec5SDimitry Andric static_cast<int64_t>(Result) <= UINT32_MAX); 4620b57cec5SDimitry Andric write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU)); 4630b57cec5SDimitry Andric break; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric case ELF::R_AARCH64_PREL64: 4660b57cec5SDimitry Andric write(isBE, TargetPtr, Value + Addend - FinalAddress); 4670b57cec5SDimitry Andric break; 468fe6060f1SDimitry Andric case ELF::R_AARCH64_CONDBR19: { 469fe6060f1SDimitry Andric uint64_t BranchImm = Value + Addend - FinalAddress; 470fe6060f1SDimitry Andric 471fe6060f1SDimitry Andric assert(isInt<21>(BranchImm)); 472fe6060f1SDimitry Andric *TargetPtr &= 0xff00001fU; 473fe6060f1SDimitry Andric // Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ 474fe6060f1SDimitry Andric or32le(TargetPtr, (BranchImm & 0x001FFFFC) << 3); 475fe6060f1SDimitry Andric break; 476fe6060f1SDimitry Andric } 477fe6060f1SDimitry Andric case ELF::R_AARCH64_TSTBR14: { 478fe6060f1SDimitry Andric uint64_t BranchImm = Value + Addend - FinalAddress; 479fe6060f1SDimitry Andric 480fe6060f1SDimitry Andric assert(isInt<16>(BranchImm)); 481fe6060f1SDimitry Andric 48206c3fb27SDimitry Andric uint32_t RawInstr = *(support::little32_t *)TargetPtr; 48306c3fb27SDimitry Andric *(support::little32_t *)TargetPtr = RawInstr & 0xfff8001fU; 48406c3fb27SDimitry Andric 485fe6060f1SDimitry Andric // Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ 486753f127fSDimitry Andric or32le(TargetPtr, (BranchImm & 0x0000FFFC) << 3); 487fe6060f1SDimitry Andric break; 488fe6060f1SDimitry Andric } 4890b57cec5SDimitry Andric case ELF::R_AARCH64_CALL26: // fallthrough 4900b57cec5SDimitry Andric case ELF::R_AARCH64_JUMP26: { 4910b57cec5SDimitry Andric // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the 4920b57cec5SDimitry Andric // calculation. 4930b57cec5SDimitry Andric uint64_t BranchImm = Value + Addend - FinalAddress; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric // "Check that -2^27 <= result < 2^27". 4960b57cec5SDimitry Andric assert(isInt<28>(BranchImm)); 4970b57cec5SDimitry Andric or32le(TargetPtr, (BranchImm & 0x0FFFFFFC) >> 2); 4980b57cec5SDimitry Andric break; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric case ELF::R_AARCH64_MOVW_UABS_G3: 5010b57cec5SDimitry Andric or32le(TargetPtr, ((Value + Addend) & 0xFFFF000000000000) >> 43); 5020b57cec5SDimitry Andric break; 5030b57cec5SDimitry Andric case ELF::R_AARCH64_MOVW_UABS_G2_NC: 5040b57cec5SDimitry Andric or32le(TargetPtr, ((Value + Addend) & 0xFFFF00000000) >> 27); 5050b57cec5SDimitry Andric break; 5060b57cec5SDimitry Andric case ELF::R_AARCH64_MOVW_UABS_G1_NC: 5070b57cec5SDimitry Andric or32le(TargetPtr, ((Value + Addend) & 0xFFFF0000) >> 11); 5080b57cec5SDimitry Andric break; 5090b57cec5SDimitry Andric case ELF::R_AARCH64_MOVW_UABS_G0_NC: 5100b57cec5SDimitry Andric or32le(TargetPtr, ((Value + Addend) & 0xFFFF) << 5); 5110b57cec5SDimitry Andric break; 5120b57cec5SDimitry Andric case ELF::R_AARCH64_ADR_PREL_PG_HI21: { 5130b57cec5SDimitry Andric // Operation: Page(S+A) - Page(P) 5140b57cec5SDimitry Andric uint64_t Result = 5150b57cec5SDimitry Andric ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric // Check that -2^32 <= X < 2^32 5180b57cec5SDimitry Andric assert(isInt<33>(Result) && "overflow check failed for relocation"); 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric // Immediate goes in bits 30:29 + 5:23 of ADRP instruction, taken 5210b57cec5SDimitry Andric // from bits 32:12 of X. 5220b57cec5SDimitry Andric write32AArch64Addr(TargetPtr, Result >> 12); 5230b57cec5SDimitry Andric break; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric case ELF::R_AARCH64_ADD_ABS_LO12_NC: 5260b57cec5SDimitry Andric // Operation: S + A 5270b57cec5SDimitry Andric // Immediate goes in bits 21:10 of LD/ST instruction, taken 5280b57cec5SDimitry Andric // from bits 11:0 of X 5290b57cec5SDimitry Andric or32AArch64Imm(TargetPtr, Value + Addend); 5300b57cec5SDimitry Andric break; 5310b57cec5SDimitry Andric case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 5320b57cec5SDimitry Andric // Operation: S + A 5330b57cec5SDimitry Andric // Immediate goes in bits 21:10 of LD/ST instruction, taken 5340b57cec5SDimitry Andric // from bits 11:0 of X 5350b57cec5SDimitry Andric or32AArch64Imm(TargetPtr, getBits(Value + Addend, 0, 11)); 5360b57cec5SDimitry Andric break; 5370b57cec5SDimitry Andric case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 5380b57cec5SDimitry Andric // Operation: S + A 5390b57cec5SDimitry Andric // Immediate goes in bits 21:10 of LD/ST instruction, taken 5400b57cec5SDimitry Andric // from bits 11:1 of X 5410b57cec5SDimitry Andric or32AArch64Imm(TargetPtr, getBits(Value + Addend, 1, 11)); 5420b57cec5SDimitry Andric break; 5430b57cec5SDimitry Andric case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 5440b57cec5SDimitry Andric // Operation: S + A 5450b57cec5SDimitry Andric // Immediate goes in bits 21:10 of LD/ST instruction, taken 5460b57cec5SDimitry Andric // from bits 11:2 of X 5470b57cec5SDimitry Andric or32AArch64Imm(TargetPtr, getBits(Value + Addend, 2, 11)); 5480b57cec5SDimitry Andric break; 5490b57cec5SDimitry Andric case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 5500b57cec5SDimitry Andric // Operation: S + A 5510b57cec5SDimitry Andric // Immediate goes in bits 21:10 of LD/ST instruction, taken 5520b57cec5SDimitry Andric // from bits 11:3 of X 5530b57cec5SDimitry Andric or32AArch64Imm(TargetPtr, getBits(Value + Addend, 3, 11)); 5540b57cec5SDimitry Andric break; 5550b57cec5SDimitry Andric case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 5560b57cec5SDimitry Andric // Operation: S + A 5570b57cec5SDimitry Andric // Immediate goes in bits 21:10 of LD/ST instruction, taken 5580b57cec5SDimitry Andric // from bits 11:4 of X 5590b57cec5SDimitry Andric or32AArch64Imm(TargetPtr, getBits(Value + Addend, 4, 11)); 5600b57cec5SDimitry Andric break; 561fe6060f1SDimitry Andric case ELF::R_AARCH64_LD_PREL_LO19: { 562fe6060f1SDimitry Andric // Operation: S + A - P 563fe6060f1SDimitry Andric uint64_t Result = Value + Addend - FinalAddress; 564fe6060f1SDimitry Andric 565fe6060f1SDimitry Andric // "Check that -2^20 <= result < 2^20". 566fe6060f1SDimitry Andric assert(isInt<21>(Result)); 567fe6060f1SDimitry Andric 568fe6060f1SDimitry Andric *TargetPtr &= 0xff00001fU; 569fe6060f1SDimitry Andric // Immediate goes in bits 23:5 of LD imm instruction, taken 570fe6060f1SDimitry Andric // from bits 20:2 of X 571fe6060f1SDimitry Andric *TargetPtr |= ((Result & 0xffc) << (5 - 2)); 572fe6060f1SDimitry Andric break; 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric case ELF::R_AARCH64_ADR_PREL_LO21: { 575fe6060f1SDimitry Andric // Operation: S + A - P 576fe6060f1SDimitry Andric uint64_t Result = Value + Addend - FinalAddress; 577fe6060f1SDimitry Andric 578fe6060f1SDimitry Andric // "Check that -2^20 <= result < 2^20". 579fe6060f1SDimitry Andric assert(isInt<21>(Result)); 580fe6060f1SDimitry Andric 581fe6060f1SDimitry Andric *TargetPtr &= 0x9f00001fU; 582fe6060f1SDimitry Andric // Immediate goes in bits 23:5, 30:29 of ADR imm instruction, taken 583fe6060f1SDimitry Andric // from bits 20:0 of X 584fe6060f1SDimitry Andric *TargetPtr |= ((Result & 0xffc) << (5 - 2)); 585fe6060f1SDimitry Andric *TargetPtr |= (Result & 0x3) << 29; 586fe6060f1SDimitry Andric break; 587fe6060f1SDimitry Andric } 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, 5920b57cec5SDimitry Andric uint64_t Offset, uint32_t Value, 5930b57cec5SDimitry Andric uint32_t Type, int32_t Addend) { 5940b57cec5SDimitry Andric // TODO: Add Thumb relocations. 5950b57cec5SDimitry Andric uint32_t *TargetPtr = 5960b57cec5SDimitry Andric reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset)); 5970b57cec5SDimitry Andric uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF; 5980b57cec5SDimitry Andric Value += Addend; 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " 6010b57cec5SDimitry Andric << Section.getAddressWithOffset(Offset) 6020b57cec5SDimitry Andric << " FinalAddress: " << format("%p", FinalAddress) 6030b57cec5SDimitry Andric << " Value: " << format("%x", Value) 6040b57cec5SDimitry Andric << " Type: " << format("%x", Type) 6050b57cec5SDimitry Andric << " Addend: " << format("%x", Addend) << "\n"); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric switch (Type) { 6080b57cec5SDimitry Andric default: 6090b57cec5SDimitry Andric llvm_unreachable("Not implemented relocation type!"); 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric case ELF::R_ARM_NONE: 6120b57cec5SDimitry Andric break; 6130b57cec5SDimitry Andric // Write a 31bit signed offset 6140b57cec5SDimitry Andric case ELF::R_ARM_PREL31: 6150b57cec5SDimitry Andric support::ulittle32_t::ref{TargetPtr} = 6160b57cec5SDimitry Andric (support::ulittle32_t::ref{TargetPtr} & 0x80000000) | 6170b57cec5SDimitry Andric ((Value - FinalAddress) & ~0x80000000); 6180b57cec5SDimitry Andric break; 6190b57cec5SDimitry Andric case ELF::R_ARM_TARGET1: 6200b57cec5SDimitry Andric case ELF::R_ARM_ABS32: 6210b57cec5SDimitry Andric support::ulittle32_t::ref{TargetPtr} = Value; 6220b57cec5SDimitry Andric break; 6230b57cec5SDimitry Andric // Write first 16 bit of 32 bit value to the mov instruction. 6240b57cec5SDimitry Andric // Last 4 bit should be shifted. 6250b57cec5SDimitry Andric case ELF::R_ARM_MOVW_ABS_NC: 6260b57cec5SDimitry Andric case ELF::R_ARM_MOVT_ABS: 6270b57cec5SDimitry Andric if (Type == ELF::R_ARM_MOVW_ABS_NC) 6280b57cec5SDimitry Andric Value = Value & 0xFFFF; 6290b57cec5SDimitry Andric else if (Type == ELF::R_ARM_MOVT_ABS) 6300b57cec5SDimitry Andric Value = (Value >> 16) & 0xFFFF; 6310b57cec5SDimitry Andric support::ulittle32_t::ref{TargetPtr} = 6320b57cec5SDimitry Andric (support::ulittle32_t::ref{TargetPtr} & ~0x000F0FFF) | (Value & 0xFFF) | 6330b57cec5SDimitry Andric (((Value >> 12) & 0xF) << 16); 6340b57cec5SDimitry Andric break; 6350b57cec5SDimitry Andric // Write 24 bit relative value to the branch instruction. 6360b57cec5SDimitry Andric case ELF::R_ARM_PC24: // Fall through. 6370b57cec5SDimitry Andric case ELF::R_ARM_CALL: // Fall through. 6380b57cec5SDimitry Andric case ELF::R_ARM_JUMP24: 6390b57cec5SDimitry Andric int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); 6400b57cec5SDimitry Andric RelValue = (RelValue & 0x03FFFFFC) >> 2; 6410b57cec5SDimitry Andric assert((support::ulittle32_t::ref{TargetPtr} & 0xFFFFFF) == 0xFFFFFE); 6420b57cec5SDimitry Andric support::ulittle32_t::ref{TargetPtr} = 6430b57cec5SDimitry Andric (support::ulittle32_t::ref{TargetPtr} & 0xFF000000) | RelValue; 6440b57cec5SDimitry Andric break; 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) { 6490b57cec5SDimitry Andric if (Arch == Triple::UnknownArch || 650*0fca6ea1SDimitry Andric Triple::getArchTypePrefix(Arch) != "mips") { 6510b57cec5SDimitry Andric IsMipsO32ABI = false; 6520b57cec5SDimitry Andric IsMipsN32ABI = false; 6530b57cec5SDimitry Andric IsMipsN64ABI = false; 6540b57cec5SDimitry Andric return; 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric if (auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) { 6570b57cec5SDimitry Andric unsigned AbiVariant = E->getPlatformFlags(); 6580b57cec5SDimitry Andric IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32; 6590b57cec5SDimitry Andric IsMipsN32ABI = AbiVariant & ELF::EF_MIPS_ABI2; 6600b57cec5SDimitry Andric } 661*0fca6ea1SDimitry Andric IsMipsN64ABI = Obj.getFileFormatName() == "elf64-mips"; 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric // Return the .TOC. section and offset. 6650b57cec5SDimitry Andric Error RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj, 6660b57cec5SDimitry Andric ObjSectionToIDMap &LocalSections, 6670b57cec5SDimitry Andric RelocationValueRef &Rel) { 6680b57cec5SDimitry Andric // Set a default SectionID in case we do not find a TOC section below. 6690b57cec5SDimitry Andric // This may happen for references to TOC base base (sym@toc, .odp 6700b57cec5SDimitry Andric // relocation) without a .toc directive. In this case just use the 6710b57cec5SDimitry Andric // first section (which is usually the .odp) since the code won't 6720b57cec5SDimitry Andric // reference the .toc base directly. 6730b57cec5SDimitry Andric Rel.SymbolName = nullptr; 6740b57cec5SDimitry Andric Rel.SectionID = 0; 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric // The TOC consists of sections .got, .toc, .tocbss, .plt in that 6770b57cec5SDimitry Andric // order. The TOC starts where the first of these sections starts. 6780b57cec5SDimitry Andric for (auto &Section : Obj.sections()) { 6798bcb0991SDimitry Andric Expected<StringRef> NameOrErr = Section.getName(); 6808bcb0991SDimitry Andric if (!NameOrErr) 6818bcb0991SDimitry Andric return NameOrErr.takeError(); 6828bcb0991SDimitry Andric StringRef SectionName = *NameOrErr; 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric if (SectionName == ".got" 6850b57cec5SDimitry Andric || SectionName == ".toc" 6860b57cec5SDimitry Andric || SectionName == ".tocbss" 6870b57cec5SDimitry Andric || SectionName == ".plt") { 6880b57cec5SDimitry Andric if (auto SectionIDOrErr = 6890b57cec5SDimitry Andric findOrEmitSection(Obj, Section, false, LocalSections)) 6900b57cec5SDimitry Andric Rel.SectionID = *SectionIDOrErr; 6910b57cec5SDimitry Andric else 6920b57cec5SDimitry Andric return SectionIDOrErr.takeError(); 6930b57cec5SDimitry Andric break; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric } 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 6980b57cec5SDimitry Andric // thus permitting a full 64 Kbytes segment. 6990b57cec5SDimitry Andric Rel.Addend = 0x8000; 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric return Error::success(); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric // Returns the sections and offset associated with the ODP entry referenced 7050b57cec5SDimitry Andric // by Symbol. 7060b57cec5SDimitry Andric Error RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, 7070b57cec5SDimitry Andric ObjSectionToIDMap &LocalSections, 7080b57cec5SDimitry Andric RelocationValueRef &Rel) { 7090b57cec5SDimitry Andric // Get the ELF symbol value (st_value) to compare with Relocation offset in 7100b57cec5SDimitry Andric // .opd entries 7110b57cec5SDimitry Andric for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); 7120b57cec5SDimitry Andric si != se; ++si) { 7138bcb0991SDimitry Andric 7148bcb0991SDimitry Andric Expected<section_iterator> RelSecOrErr = si->getRelocatedSection(); 7158bcb0991SDimitry Andric if (!RelSecOrErr) 716349cc55cSDimitry Andric report_fatal_error(Twine(toString(RelSecOrErr.takeError()))); 7178bcb0991SDimitry Andric 7188bcb0991SDimitry Andric section_iterator RelSecI = *RelSecOrErr; 7190b57cec5SDimitry Andric if (RelSecI == Obj.section_end()) 7200b57cec5SDimitry Andric continue; 7210b57cec5SDimitry Andric 7228bcb0991SDimitry Andric Expected<StringRef> NameOrErr = RelSecI->getName(); 7238bcb0991SDimitry Andric if (!NameOrErr) 7248bcb0991SDimitry Andric return NameOrErr.takeError(); 7258bcb0991SDimitry Andric StringRef RelSectionName = *NameOrErr; 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric if (RelSectionName != ".opd") 7280b57cec5SDimitry Andric continue; 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric for (elf_relocation_iterator i = si->relocation_begin(), 7310b57cec5SDimitry Andric e = si->relocation_end(); 7320b57cec5SDimitry Andric i != e;) { 7330b57cec5SDimitry Andric // The R_PPC64_ADDR64 relocation indicates the first field 7340b57cec5SDimitry Andric // of a .opd entry 7350b57cec5SDimitry Andric uint64_t TypeFunc = i->getType(); 7360b57cec5SDimitry Andric if (TypeFunc != ELF::R_PPC64_ADDR64) { 7370b57cec5SDimitry Andric ++i; 7380b57cec5SDimitry Andric continue; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric uint64_t TargetSymbolOffset = i->getOffset(); 7420b57cec5SDimitry Andric symbol_iterator TargetSymbol = i->getSymbol(); 7430b57cec5SDimitry Andric int64_t Addend; 7440b57cec5SDimitry Andric if (auto AddendOrErr = i->getAddend()) 7450b57cec5SDimitry Andric Addend = *AddendOrErr; 7460b57cec5SDimitry Andric else 7470b57cec5SDimitry Andric return AddendOrErr.takeError(); 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric ++i; 7500b57cec5SDimitry Andric if (i == e) 7510b57cec5SDimitry Andric break; 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric // Just check if following relocation is a R_PPC64_TOC 7540b57cec5SDimitry Andric uint64_t TypeTOC = i->getType(); 7550b57cec5SDimitry Andric if (TypeTOC != ELF::R_PPC64_TOC) 7560b57cec5SDimitry Andric continue; 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric // Finally compares the Symbol value and the target symbol offset 7590b57cec5SDimitry Andric // to check if this .opd entry refers to the symbol the relocation 7600b57cec5SDimitry Andric // points to. 7610b57cec5SDimitry Andric if (Rel.Addend != (int64_t)TargetSymbolOffset) 7620b57cec5SDimitry Andric continue; 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric section_iterator TSI = Obj.section_end(); 7650b57cec5SDimitry Andric if (auto TSIOrErr = TargetSymbol->getSection()) 7660b57cec5SDimitry Andric TSI = *TSIOrErr; 7670b57cec5SDimitry Andric else 7680b57cec5SDimitry Andric return TSIOrErr.takeError(); 7690b57cec5SDimitry Andric assert(TSI != Obj.section_end() && "TSI should refer to a valid section"); 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric bool IsCode = TSI->isText(); 7720b57cec5SDimitry Andric if (auto SectionIDOrErr = findOrEmitSection(Obj, *TSI, IsCode, 7730b57cec5SDimitry Andric LocalSections)) 7740b57cec5SDimitry Andric Rel.SectionID = *SectionIDOrErr; 7750b57cec5SDimitry Andric else 7760b57cec5SDimitry Andric return SectionIDOrErr.takeError(); 7770b57cec5SDimitry Andric Rel.Addend = (intptr_t)Addend; 7780b57cec5SDimitry Andric return Error::success(); 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric llvm_unreachable("Attempting to get address of ODP entry!"); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric // Relocation masks following the #lo(value), #hi(value), #ha(value), 7850b57cec5SDimitry Andric // #higher(value), #highera(value), #highest(value), and #highesta(value) 7860b57cec5SDimitry Andric // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi 7870b57cec5SDimitry Andric // document. 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric static inline uint16_t applyPPClo(uint64_t value) { return value & 0xffff; } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric static inline uint16_t applyPPChi(uint64_t value) { 7920b57cec5SDimitry Andric return (value >> 16) & 0xffff; 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric static inline uint16_t applyPPCha (uint64_t value) { 7960b57cec5SDimitry Andric return ((value + 0x8000) >> 16) & 0xffff; 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric static inline uint16_t applyPPChigher(uint64_t value) { 8000b57cec5SDimitry Andric return (value >> 32) & 0xffff; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric static inline uint16_t applyPPChighera (uint64_t value) { 8040b57cec5SDimitry Andric return ((value + 0x8000) >> 32) & 0xffff; 8050b57cec5SDimitry Andric } 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric static inline uint16_t applyPPChighest(uint64_t value) { 8080b57cec5SDimitry Andric return (value >> 48) & 0xffff; 8090b57cec5SDimitry Andric } 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric static inline uint16_t applyPPChighesta (uint64_t value) { 8120b57cec5SDimitry Andric return ((value + 0x8000) >> 48) & 0xffff; 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric void RuntimeDyldELF::resolvePPC32Relocation(const SectionEntry &Section, 8160b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 8170b57cec5SDimitry Andric uint32_t Type, int64_t Addend) { 8180b57cec5SDimitry Andric uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 8190b57cec5SDimitry Andric switch (Type) { 8200b57cec5SDimitry Andric default: 8211106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 8220b57cec5SDimitry Andric break; 8230b57cec5SDimitry Andric case ELF::R_PPC_ADDR16_LO: 8240b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); 8250b57cec5SDimitry Andric break; 8260b57cec5SDimitry Andric case ELF::R_PPC_ADDR16_HI: 8270b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChi(Value + Addend)); 8280b57cec5SDimitry Andric break; 8290b57cec5SDimitry Andric case ELF::R_PPC_ADDR16_HA: 8300b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPCha(Value + Addend)); 8310b57cec5SDimitry Andric break; 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, 8360b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 8370b57cec5SDimitry Andric uint32_t Type, int64_t Addend) { 8380b57cec5SDimitry Andric uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 8390b57cec5SDimitry Andric switch (Type) { 8400b57cec5SDimitry Andric default: 8411106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 8420b57cec5SDimitry Andric break; 8430b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16: 8440b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); 8450b57cec5SDimitry Andric break; 8460b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_DS: 8470b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3); 8480b57cec5SDimitry Andric break; 8490b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_LO: 8500b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); 8510b57cec5SDimitry Andric break; 8520b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_LO_DS: 8530b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3); 8540b57cec5SDimitry Andric break; 8550b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HI: 8560b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HIGH: 8570b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChi(Value + Addend)); 8580b57cec5SDimitry Andric break; 8590b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HA: 8600b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HIGHA: 8610b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPCha(Value + Addend)); 8620b57cec5SDimitry Andric break; 8630b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HIGHER: 8640b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChigher(Value + Addend)); 8650b57cec5SDimitry Andric break; 8660b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HIGHERA: 8670b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChighera(Value + Addend)); 8680b57cec5SDimitry Andric break; 8690b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HIGHEST: 8700b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChighest(Value + Addend)); 8710b57cec5SDimitry Andric break; 8720b57cec5SDimitry Andric case ELF::R_PPC64_ADDR16_HIGHESTA: 8730b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChighesta(Value + Addend)); 8740b57cec5SDimitry Andric break; 8750b57cec5SDimitry Andric case ELF::R_PPC64_ADDR14: { 8760b57cec5SDimitry Andric assert(((Value + Addend) & 3) == 0); 8770b57cec5SDimitry Andric // Preserve the AA/LK bits in the branch instruction 8780b57cec5SDimitry Andric uint8_t aalk = *(LocalAddress + 3); 8790b57cec5SDimitry Andric writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc)); 8800b57cec5SDimitry Andric } break; 8810b57cec5SDimitry Andric case ELF::R_PPC64_REL16_LO: { 8820b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 8830b57cec5SDimitry Andric uint64_t Delta = Value - FinalAddress + Addend; 8840b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPClo(Delta)); 8850b57cec5SDimitry Andric } break; 8860b57cec5SDimitry Andric case ELF::R_PPC64_REL16_HI: { 8870b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 8880b57cec5SDimitry Andric uint64_t Delta = Value - FinalAddress + Addend; 8890b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPChi(Delta)); 8900b57cec5SDimitry Andric } break; 8910b57cec5SDimitry Andric case ELF::R_PPC64_REL16_HA: { 8920b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 8930b57cec5SDimitry Andric uint64_t Delta = Value - FinalAddress + Addend; 8940b57cec5SDimitry Andric writeInt16BE(LocalAddress, applyPPCha(Delta)); 8950b57cec5SDimitry Andric } break; 8960b57cec5SDimitry Andric case ELF::R_PPC64_ADDR32: { 8970b57cec5SDimitry Andric int64_t Result = static_cast<int64_t>(Value + Addend); 8980b57cec5SDimitry Andric if (SignExtend64<32>(Result) != Result) 8990b57cec5SDimitry Andric llvm_unreachable("Relocation R_PPC64_ADDR32 overflow"); 9000b57cec5SDimitry Andric writeInt32BE(LocalAddress, Result); 9010b57cec5SDimitry Andric } break; 9020b57cec5SDimitry Andric case ELF::R_PPC64_REL24: { 9030b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 9040b57cec5SDimitry Andric int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend); 9050b57cec5SDimitry Andric if (SignExtend64<26>(delta) != delta) 9060b57cec5SDimitry Andric llvm_unreachable("Relocation R_PPC64_REL24 overflow"); 9070b57cec5SDimitry Andric // We preserve bits other than LI field, i.e. PO and AA/LK fields. 9080b57cec5SDimitry Andric uint32_t Inst = readBytesUnaligned(LocalAddress, 4); 9090b57cec5SDimitry Andric writeInt32BE(LocalAddress, (Inst & 0xFC000003) | (delta & 0x03FFFFFC)); 9100b57cec5SDimitry Andric } break; 9110b57cec5SDimitry Andric case ELF::R_PPC64_REL32: { 9120b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 9130b57cec5SDimitry Andric int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend); 9140b57cec5SDimitry Andric if (SignExtend64<32>(delta) != delta) 9150b57cec5SDimitry Andric llvm_unreachable("Relocation R_PPC64_REL32 overflow"); 9160b57cec5SDimitry Andric writeInt32BE(LocalAddress, delta); 9170b57cec5SDimitry Andric } break; 9180b57cec5SDimitry Andric case ELF::R_PPC64_REL64: { 9190b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); 9200b57cec5SDimitry Andric uint64_t Delta = Value - FinalAddress + Addend; 9210b57cec5SDimitry Andric writeInt64BE(LocalAddress, Delta); 9220b57cec5SDimitry Andric } break; 9230b57cec5SDimitry Andric case ELF::R_PPC64_ADDR64: 9240b57cec5SDimitry Andric writeInt64BE(LocalAddress, Value + Addend); 9250b57cec5SDimitry Andric break; 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section, 9300b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 9310b57cec5SDimitry Andric uint32_t Type, int64_t Addend) { 9320b57cec5SDimitry Andric uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 9330b57cec5SDimitry Andric switch (Type) { 9340b57cec5SDimitry Andric default: 9351106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 9360b57cec5SDimitry Andric break; 9370b57cec5SDimitry Andric case ELF::R_390_PC16DBL: 9380b57cec5SDimitry Andric case ELF::R_390_PLT16DBL: { 9390b57cec5SDimitry Andric int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); 9400b57cec5SDimitry Andric assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow"); 9410b57cec5SDimitry Andric writeInt16BE(LocalAddress, Delta / 2); 9420b57cec5SDimitry Andric break; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric case ELF::R_390_PC32DBL: 9450b57cec5SDimitry Andric case ELF::R_390_PLT32DBL: { 9460b57cec5SDimitry Andric int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); 9470b57cec5SDimitry Andric assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow"); 9480b57cec5SDimitry Andric writeInt32BE(LocalAddress, Delta / 2); 9490b57cec5SDimitry Andric break; 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric case ELF::R_390_PC16: { 9520b57cec5SDimitry Andric int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); 9530b57cec5SDimitry Andric assert(int16_t(Delta) == Delta && "R_390_PC16 overflow"); 9540b57cec5SDimitry Andric writeInt16BE(LocalAddress, Delta); 9550b57cec5SDimitry Andric break; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric case ELF::R_390_PC32: { 9580b57cec5SDimitry Andric int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); 9590b57cec5SDimitry Andric assert(int32_t(Delta) == Delta && "R_390_PC32 overflow"); 9600b57cec5SDimitry Andric writeInt32BE(LocalAddress, Delta); 9610b57cec5SDimitry Andric break; 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric case ELF::R_390_PC64: { 9640b57cec5SDimitry Andric int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); 9650b57cec5SDimitry Andric writeInt64BE(LocalAddress, Delta); 9660b57cec5SDimitry Andric break; 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric case ELF::R_390_8: 9690b57cec5SDimitry Andric *LocalAddress = (uint8_t)(Value + Addend); 9700b57cec5SDimitry Andric break; 9710b57cec5SDimitry Andric case ELF::R_390_16: 9720b57cec5SDimitry Andric writeInt16BE(LocalAddress, Value + Addend); 9730b57cec5SDimitry Andric break; 9740b57cec5SDimitry Andric case ELF::R_390_32: 9750b57cec5SDimitry Andric writeInt32BE(LocalAddress, Value + Addend); 9760b57cec5SDimitry Andric break; 9770b57cec5SDimitry Andric case ELF::R_390_64: 9780b57cec5SDimitry Andric writeInt64BE(LocalAddress, Value + Addend); 9790b57cec5SDimitry Andric break; 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section, 9840b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 9850b57cec5SDimitry Andric uint32_t Type, int64_t Addend) { 9860b57cec5SDimitry Andric bool isBE = Arch == Triple::bpfeb; 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric switch (Type) { 9890b57cec5SDimitry Andric default: 9901106035dSDimitry Andric report_fatal_error("Relocation type not implemented yet!"); 9910b57cec5SDimitry Andric break; 9920b57cec5SDimitry Andric case ELF::R_BPF_NONE: 993fe6060f1SDimitry Andric case ELF::R_BPF_64_64: 994fe6060f1SDimitry Andric case ELF::R_BPF_64_32: 995fe6060f1SDimitry Andric case ELF::R_BPF_64_NODYLD32: 9960b57cec5SDimitry Andric break; 997fe6060f1SDimitry Andric case ELF::R_BPF_64_ABS64: { 9980b57cec5SDimitry Andric write(isBE, Section.getAddressWithOffset(Offset), Value + Addend); 9990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " 10000b57cec5SDimitry Andric << format("%p\n", Section.getAddressWithOffset(Offset))); 10010b57cec5SDimitry Andric break; 10020b57cec5SDimitry Andric } 1003fe6060f1SDimitry Andric case ELF::R_BPF_64_ABS32: { 10040b57cec5SDimitry Andric Value += Addend; 10050b57cec5SDimitry Andric assert(Value <= UINT32_MAX); 10060b57cec5SDimitry Andric write(isBE, Section.getAddressWithOffset(Offset), static_cast<uint32_t>(Value)); 10070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Writing " << format("%p", Value) << " at " 10080b57cec5SDimitry Andric << format("%p\n", Section.getAddressWithOffset(Offset))); 10090b57cec5SDimitry Andric break; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric // The target location for the relocation is described by RE.SectionID and 10150b57cec5SDimitry Andric // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each 10160b57cec5SDimitry Andric // SectionEntry has three members describing its location. 10170b57cec5SDimitry Andric // SectionEntry::Address is the address at which the section has been loaded 10180b57cec5SDimitry Andric // into memory in the current (host) process. SectionEntry::LoadAddress is the 10190b57cec5SDimitry Andric // address that the section will have in the target process. 10200b57cec5SDimitry Andric // SectionEntry::ObjAddress is the address of the bits for this section in the 10210b57cec5SDimitry Andric // original emitted object image (also in the current address space). 10220b57cec5SDimitry Andric // 10230b57cec5SDimitry Andric // Relocations will be applied as if the section were loaded at 10240b57cec5SDimitry Andric // SectionEntry::LoadAddress, but they will be applied at an address based 10250b57cec5SDimitry Andric // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to 10260b57cec5SDimitry Andric // Target memory contents if they are required for value calculations. 10270b57cec5SDimitry Andric // 10280b57cec5SDimitry Andric // The Value parameter here is the load address of the symbol for the 10290b57cec5SDimitry Andric // relocation to be applied. For relocations which refer to symbols in the 10300b57cec5SDimitry Andric // current object Value will be the LoadAddress of the section in which 10310b57cec5SDimitry Andric // the symbol resides (RE.Addend provides additional information about the 10320b57cec5SDimitry Andric // symbol location). For external symbols, Value will be the address of the 10330b57cec5SDimitry Andric // symbol in the target address space. 10340b57cec5SDimitry Andric void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE, 10350b57cec5SDimitry Andric uint64_t Value) { 10360b57cec5SDimitry Andric const SectionEntry &Section = Sections[RE.SectionID]; 10370b57cec5SDimitry Andric return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, 10380b57cec5SDimitry Andric RE.SymOffset, RE.SectionID); 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, 10420b57cec5SDimitry Andric uint64_t Offset, uint64_t Value, 10430b57cec5SDimitry Andric uint32_t Type, int64_t Addend, 10440b57cec5SDimitry Andric uint64_t SymOffset, SID SectionID) { 10450b57cec5SDimitry Andric switch (Arch) { 10460b57cec5SDimitry Andric case Triple::x86_64: 10470b57cec5SDimitry Andric resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset); 10480b57cec5SDimitry Andric break; 10490b57cec5SDimitry Andric case Triple::x86: 10500b57cec5SDimitry Andric resolveX86Relocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, 10510b57cec5SDimitry Andric (uint32_t)(Addend & 0xffffffffL)); 10520b57cec5SDimitry Andric break; 10530b57cec5SDimitry Andric case Triple::aarch64: 10540b57cec5SDimitry Andric case Triple::aarch64_be: 10550b57cec5SDimitry Andric resolveAArch64Relocation(Section, Offset, Value, Type, Addend); 10560b57cec5SDimitry Andric break; 10570b57cec5SDimitry Andric case Triple::arm: // Fall through. 10580b57cec5SDimitry Andric case Triple::armeb: 10590b57cec5SDimitry Andric case Triple::thumb: 10600b57cec5SDimitry Andric case Triple::thumbeb: 10610b57cec5SDimitry Andric resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, 10620b57cec5SDimitry Andric (uint32_t)(Addend & 0xffffffffL)); 10630b57cec5SDimitry Andric break; 1064e8d8bef9SDimitry Andric case Triple::ppc: // Fall through. 1065e8d8bef9SDimitry Andric case Triple::ppcle: 10660b57cec5SDimitry Andric resolvePPC32Relocation(Section, Offset, Value, Type, Addend); 10670b57cec5SDimitry Andric break; 10680b57cec5SDimitry Andric case Triple::ppc64: // Fall through. 10690b57cec5SDimitry Andric case Triple::ppc64le: 10700b57cec5SDimitry Andric resolvePPC64Relocation(Section, Offset, Value, Type, Addend); 10710b57cec5SDimitry Andric break; 10720b57cec5SDimitry Andric case Triple::systemz: 10730b57cec5SDimitry Andric resolveSystemZRelocation(Section, Offset, Value, Type, Addend); 10740b57cec5SDimitry Andric break; 10750b57cec5SDimitry Andric case Triple::bpfel: 10760b57cec5SDimitry Andric case Triple::bpfeb: 10770b57cec5SDimitry Andric resolveBPFRelocation(Section, Offset, Value, Type, Addend); 10780b57cec5SDimitry Andric break; 10790b57cec5SDimitry Andric default: 10800b57cec5SDimitry Andric llvm_unreachable("Unsupported CPU type!"); 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const { 10850b57cec5SDimitry Andric return (void *)(Sections[SectionID].getObjAddress() + Offset); 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric void RuntimeDyldELF::processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value) { 10890b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset); 10900b57cec5SDimitry Andric if (Value.SymbolName) 10910b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 10920b57cec5SDimitry Andric else 10930b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType, 10970b57cec5SDimitry Andric bool IsLocal) const { 10980b57cec5SDimitry Andric switch (RelType) { 10990b57cec5SDimitry Andric case ELF::R_MICROMIPS_GOT16: 11000b57cec5SDimitry Andric if (IsLocal) 11010b57cec5SDimitry Andric return ELF::R_MICROMIPS_LO16; 11020b57cec5SDimitry Andric break; 11030b57cec5SDimitry Andric case ELF::R_MICROMIPS_HI16: 11040b57cec5SDimitry Andric return ELF::R_MICROMIPS_LO16; 11050b57cec5SDimitry Andric case ELF::R_MIPS_GOT16: 11060b57cec5SDimitry Andric if (IsLocal) 11070b57cec5SDimitry Andric return ELF::R_MIPS_LO16; 11080b57cec5SDimitry Andric break; 11090b57cec5SDimitry Andric case ELF::R_MIPS_HI16: 11100b57cec5SDimitry Andric return ELF::R_MIPS_LO16; 11110b57cec5SDimitry Andric case ELF::R_MIPS_PCHI16: 11120b57cec5SDimitry Andric return ELF::R_MIPS_PCLO16; 11130b57cec5SDimitry Andric default: 11140b57cec5SDimitry Andric break; 11150b57cec5SDimitry Andric } 11160b57cec5SDimitry Andric return ELF::R_MIPS_NONE; 11170b57cec5SDimitry Andric } 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric // Sometimes we don't need to create thunk for a branch. 11200b57cec5SDimitry Andric // This typically happens when branch target is located 11210b57cec5SDimitry Andric // in the same object file. In such case target is either 11220b57cec5SDimitry Andric // a weak symbol or symbol in a different executable section. 11230b57cec5SDimitry Andric // This function checks if branch target is located in the 11240b57cec5SDimitry Andric // same object file and if distance between source and target 11250b57cec5SDimitry Andric // fits R_AARCH64_CALL26 relocation. If both conditions are 11260b57cec5SDimitry Andric // met, it emits direct jump to the target and returns true. 11270b57cec5SDimitry Andric // Otherwise false is returned and thunk is created. 11280b57cec5SDimitry Andric bool RuntimeDyldELF::resolveAArch64ShortBranch( 11290b57cec5SDimitry Andric unsigned SectionID, relocation_iterator RelI, 11300b57cec5SDimitry Andric const RelocationValueRef &Value) { 1131*0fca6ea1SDimitry Andric uint64_t TargetOffset; 1132*0fca6ea1SDimitry Andric unsigned TargetSectionID; 11330b57cec5SDimitry Andric if (Value.SymbolName) { 11340b57cec5SDimitry Andric auto Loc = GlobalSymbolTable.find(Value.SymbolName); 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric // Don't create direct branch for external symbols. 11370b57cec5SDimitry Andric if (Loc == GlobalSymbolTable.end()) 11380b57cec5SDimitry Andric return false; 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric const auto &SymInfo = Loc->second; 1141*0fca6ea1SDimitry Andric 1142*0fca6ea1SDimitry Andric TargetSectionID = SymInfo.getSectionID(); 1143*0fca6ea1SDimitry Andric TargetOffset = SymInfo.getOffset(); 11440b57cec5SDimitry Andric } else { 1145*0fca6ea1SDimitry Andric TargetSectionID = Value.SectionID; 1146*0fca6ea1SDimitry Andric TargetOffset = 0; 11470b57cec5SDimitry Andric } 1148*0fca6ea1SDimitry Andric 1149*0fca6ea1SDimitry Andric // We don't actually know the load addresses at this point, so if the 1150*0fca6ea1SDimitry Andric // branch is cross-section, we don't know exactly how far away it is. 1151*0fca6ea1SDimitry Andric if (TargetSectionID != SectionID) 1152*0fca6ea1SDimitry Andric return false; 1153*0fca6ea1SDimitry Andric 1154*0fca6ea1SDimitry Andric uint64_t SourceOffset = RelI->getOffset(); 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric // R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^27 11570b57cec5SDimitry Andric // If distance between source and target is out of range then we should 11580b57cec5SDimitry Andric // create thunk. 1159*0fca6ea1SDimitry Andric if (!isInt<28>(TargetOffset + Value.Addend - SourceOffset)) 11600b57cec5SDimitry Andric return false; 11610b57cec5SDimitry Andric 1162*0fca6ea1SDimitry Andric RelocationEntry RE(SectionID, SourceOffset, RelI->getType(), Value.Addend); 1163*0fca6ea1SDimitry Andric if (Value.SymbolName) 1164*0fca6ea1SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 1165*0fca6ea1SDimitry Andric else 1166*0fca6ea1SDimitry Andric addRelocationForSection(RE, Value.SectionID); 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric return true; 11690b57cec5SDimitry Andric } 11700b57cec5SDimitry Andric 11710b57cec5SDimitry Andric void RuntimeDyldELF::resolveAArch64Branch(unsigned SectionID, 11720b57cec5SDimitry Andric const RelocationValueRef &Value, 11730b57cec5SDimitry Andric relocation_iterator RelI, 11740b57cec5SDimitry Andric StubMap &Stubs) { 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation."); 11770b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric uint64_t Offset = RelI->getOffset(); 11800b57cec5SDimitry Andric unsigned RelType = RelI->getType(); 11810b57cec5SDimitry Andric // Look for an existing stub. 11820b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 11830b57cec5SDimitry Andric if (i != Stubs.end()) { 11840b57cec5SDimitry Andric resolveRelocation(Section, Offset, 1185*0fca6ea1SDimitry Andric Section.getLoadAddressWithOffset(i->second), RelType, 0); 11860b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 11870b57cec5SDimitry Andric } else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) { 11880b57cec5SDimitry Andric // Create a new stub function. 11890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 11900b57cec5SDimitry Andric Stubs[Value] = Section.getStubOffset(); 11910b57cec5SDimitry Andric uint8_t *StubTargetAddr = createStubFunction( 11920b57cec5SDimitry Andric Section.getAddressWithOffset(Section.getStubOffset())); 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric RelocationEntry REmovz_g3(SectionID, StubTargetAddr - Section.getAddress(), 11950b57cec5SDimitry Andric ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend); 11960b57cec5SDimitry Andric RelocationEntry REmovk_g2(SectionID, 11970b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 4, 11980b57cec5SDimitry Andric ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend); 11990b57cec5SDimitry Andric RelocationEntry REmovk_g1(SectionID, 12000b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 8, 12010b57cec5SDimitry Andric ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend); 12020b57cec5SDimitry Andric RelocationEntry REmovk_g0(SectionID, 12030b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 12, 12040b57cec5SDimitry Andric ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend); 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric if (Value.SymbolName) { 12070b57cec5SDimitry Andric addRelocationForSymbol(REmovz_g3, Value.SymbolName); 12080b57cec5SDimitry Andric addRelocationForSymbol(REmovk_g2, Value.SymbolName); 12090b57cec5SDimitry Andric addRelocationForSymbol(REmovk_g1, Value.SymbolName); 12100b57cec5SDimitry Andric addRelocationForSymbol(REmovk_g0, Value.SymbolName); 12110b57cec5SDimitry Andric } else { 12120b57cec5SDimitry Andric addRelocationForSection(REmovz_g3, Value.SectionID); 12130b57cec5SDimitry Andric addRelocationForSection(REmovk_g2, Value.SectionID); 12140b57cec5SDimitry Andric addRelocationForSection(REmovk_g1, Value.SectionID); 12150b57cec5SDimitry Andric addRelocationForSection(REmovk_g0, Value.SectionID); 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric resolveRelocation(Section, Offset, 1218*0fca6ea1SDimitry Andric Section.getLoadAddressWithOffset(Section.getStubOffset()), 12190b57cec5SDimitry Andric RelType, 0); 12200b57cec5SDimitry Andric Section.advanceStubOffset(getMaxStubSize()); 12210b57cec5SDimitry Andric } 12220b57cec5SDimitry Andric } 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric Expected<relocation_iterator> 12250b57cec5SDimitry Andric RuntimeDyldELF::processRelocationRef( 12260b57cec5SDimitry Andric unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, 12270b57cec5SDimitry Andric ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { 12280b57cec5SDimitry Andric const auto &Obj = cast<ELFObjectFileBase>(O); 12290b57cec5SDimitry Andric uint64_t RelType = RelI->getType(); 12300b57cec5SDimitry Andric int64_t Addend = 0; 12310b57cec5SDimitry Andric if (Expected<int64_t> AddendOrErr = ELFRelocationRef(*RelI).getAddend()) 12320b57cec5SDimitry Andric Addend = *AddendOrErr; 12330b57cec5SDimitry Andric else 12340b57cec5SDimitry Andric consumeError(AddendOrErr.takeError()); 12350b57cec5SDimitry Andric elf_symbol_iterator Symbol = RelI->getSymbol(); 12360b57cec5SDimitry Andric 12370b57cec5SDimitry Andric // Obtain the symbol name which is referenced in the relocation 12380b57cec5SDimitry Andric StringRef TargetName; 12390b57cec5SDimitry Andric if (Symbol != Obj.symbol_end()) { 12400b57cec5SDimitry Andric if (auto TargetNameOrErr = Symbol->getName()) 12410b57cec5SDimitry Andric TargetName = *TargetNameOrErr; 12420b57cec5SDimitry Andric else 12430b57cec5SDimitry Andric return TargetNameOrErr.takeError(); 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend 12460b57cec5SDimitry Andric << " TargetName: " << TargetName << "\n"); 12470b57cec5SDimitry Andric RelocationValueRef Value; 12480b57cec5SDimitry Andric // First search for the symbol in the local symbol table 12490b57cec5SDimitry Andric SymbolRef::Type SymType = SymbolRef::ST_Unknown; 12500b57cec5SDimitry Andric 12510b57cec5SDimitry Andric // Search for the symbol in the global symbol table 12520b57cec5SDimitry Andric RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end(); 12530b57cec5SDimitry Andric if (Symbol != Obj.symbol_end()) { 12540b57cec5SDimitry Andric gsi = GlobalSymbolTable.find(TargetName.data()); 12550b57cec5SDimitry Andric Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType(); 12560b57cec5SDimitry Andric if (!SymTypeOrErr) { 12570b57cec5SDimitry Andric std::string Buf; 12580b57cec5SDimitry Andric raw_string_ostream OS(Buf); 12590b57cec5SDimitry Andric logAllUnhandledErrors(SymTypeOrErr.takeError(), OS); 1260349cc55cSDimitry Andric report_fatal_error(Twine(OS.str())); 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric SymType = *SymTypeOrErr; 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric if (gsi != GlobalSymbolTable.end()) { 12650b57cec5SDimitry Andric const auto &SymInfo = gsi->second; 12660b57cec5SDimitry Andric Value.SectionID = SymInfo.getSectionID(); 12670b57cec5SDimitry Andric Value.Offset = SymInfo.getOffset(); 12680b57cec5SDimitry Andric Value.Addend = SymInfo.getOffset() + Addend; 12690b57cec5SDimitry Andric } else { 12700b57cec5SDimitry Andric switch (SymType) { 12710b57cec5SDimitry Andric case SymbolRef::ST_Debug: { 12720b57cec5SDimitry Andric // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously 12730b57cec5SDimitry Andric // and can be changed by another developers. Maybe best way is add 12740b57cec5SDimitry Andric // a new symbol type ST_Section to SymbolRef and use it. 12750b57cec5SDimitry Andric auto SectionOrErr = Symbol->getSection(); 12760b57cec5SDimitry Andric if (!SectionOrErr) { 12770b57cec5SDimitry Andric std::string Buf; 12780b57cec5SDimitry Andric raw_string_ostream OS(Buf); 12790b57cec5SDimitry Andric logAllUnhandledErrors(SectionOrErr.takeError(), OS); 1280349cc55cSDimitry Andric report_fatal_error(Twine(OS.str())); 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric section_iterator si = *SectionOrErr; 12830b57cec5SDimitry Andric if (si == Obj.section_end()) 12840b57cec5SDimitry Andric llvm_unreachable("Symbol section not found, bad object file format!"); 12850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tThis is section symbol\n"); 12860b57cec5SDimitry Andric bool isCode = si->isText(); 12870b57cec5SDimitry Andric if (auto SectionIDOrErr = findOrEmitSection(Obj, (*si), isCode, 12880b57cec5SDimitry Andric ObjSectionToID)) 12890b57cec5SDimitry Andric Value.SectionID = *SectionIDOrErr; 12900b57cec5SDimitry Andric else 12910b57cec5SDimitry Andric return SectionIDOrErr.takeError(); 12920b57cec5SDimitry Andric Value.Addend = Addend; 12930b57cec5SDimitry Andric break; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric case SymbolRef::ST_Data: 12960b57cec5SDimitry Andric case SymbolRef::ST_Function: 129706c3fb27SDimitry Andric case SymbolRef::ST_Other: 12980b57cec5SDimitry Andric case SymbolRef::ST_Unknown: { 12990b57cec5SDimitry Andric Value.SymbolName = TargetName.data(); 13000b57cec5SDimitry Andric Value.Addend = Addend; 13010b57cec5SDimitry Andric 13020b57cec5SDimitry Andric // Absolute relocations will have a zero symbol ID (STN_UNDEF), which 13030b57cec5SDimitry Andric // will manifest here as a NULL symbol name. 13040b57cec5SDimitry Andric // We can set this as a valid (but empty) symbol name, and rely 13050b57cec5SDimitry Andric // on addRelocationForSymbol to handle this. 13060b57cec5SDimitry Andric if (!Value.SymbolName) 13070b57cec5SDimitry Andric Value.SymbolName = ""; 13080b57cec5SDimitry Andric break; 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric default: 13110b57cec5SDimitry Andric llvm_unreachable("Unresolved symbol type!"); 13120b57cec5SDimitry Andric break; 13130b57cec5SDimitry Andric } 13140b57cec5SDimitry Andric } 13150b57cec5SDimitry Andric 13160b57cec5SDimitry Andric uint64_t Offset = RelI->getOffset(); 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset 13190b57cec5SDimitry Andric << "\n"); 13200b57cec5SDimitry Andric if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be)) { 1321fe6060f1SDimitry Andric if ((RelType == ELF::R_AARCH64_CALL26 || 1322fe6060f1SDimitry Andric RelType == ELF::R_AARCH64_JUMP26) && 1323fe6060f1SDimitry Andric MemMgr.allowStubAllocation()) { 13240b57cec5SDimitry Andric resolveAArch64Branch(SectionID, Value, RelI, Stubs); 13250b57cec5SDimitry Andric } else if (RelType == ELF::R_AARCH64_ADR_GOT_PAGE) { 13264824e7fdSDimitry Andric // Create new GOT entry or find existing one. If GOT entry is 13270b57cec5SDimitry Andric // to be created, then we also emit ABS64 relocation for it. 13280b57cec5SDimitry Andric uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64); 13290b57cec5SDimitry Andric resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, 13300b57cec5SDimitry Andric ELF::R_AARCH64_ADR_PREL_PG_HI21); 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric } else if (RelType == ELF::R_AARCH64_LD64_GOT_LO12_NC) { 13330b57cec5SDimitry Andric uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64); 13340b57cec5SDimitry Andric resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, 13350b57cec5SDimitry Andric ELF::R_AARCH64_LDST64_ABS_LO12_NC); 13360b57cec5SDimitry Andric } else { 13370b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 13380b57cec5SDimitry Andric } 13390b57cec5SDimitry Andric } else if (Arch == Triple::arm) { 13400b57cec5SDimitry Andric if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL || 13410b57cec5SDimitry Andric RelType == ELF::R_ARM_JUMP24) { 13420b57cec5SDimitry Andric // This is an ARM branch relocation, need to use a stub function. 13430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.\n"); 13440b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 13450b57cec5SDimitry Andric 13460b57cec5SDimitry Andric // Look for an existing stub. 13470b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 13480b57cec5SDimitry Andric if (i != Stubs.end()) { 1349*0fca6ea1SDimitry Andric resolveRelocation(Section, Offset, 1350*0fca6ea1SDimitry Andric Section.getLoadAddressWithOffset(i->second), RelType, 1351*0fca6ea1SDimitry Andric 0); 13520b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 13530b57cec5SDimitry Andric } else { 13540b57cec5SDimitry Andric // Create a new stub function. 13550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 13560b57cec5SDimitry Andric Stubs[Value] = Section.getStubOffset(); 13570b57cec5SDimitry Andric uint8_t *StubTargetAddr = createStubFunction( 13580b57cec5SDimitry Andric Section.getAddressWithOffset(Section.getStubOffset())); 13590b57cec5SDimitry Andric RelocationEntry RE(SectionID, StubTargetAddr - Section.getAddress(), 13600b57cec5SDimitry Andric ELF::R_ARM_ABS32, Value.Addend); 13610b57cec5SDimitry Andric if (Value.SymbolName) 13620b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 13630b57cec5SDimitry Andric else 13640b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 13650b57cec5SDimitry Andric 1366*0fca6ea1SDimitry Andric resolveRelocation( 1367*0fca6ea1SDimitry Andric Section, Offset, 1368*0fca6ea1SDimitry Andric Section.getLoadAddressWithOffset(Section.getStubOffset()), RelType, 1369*0fca6ea1SDimitry Andric 0); 13700b57cec5SDimitry Andric Section.advanceStubOffset(getMaxStubSize()); 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric } else { 13730b57cec5SDimitry Andric uint32_t *Placeholder = 13740b57cec5SDimitry Andric reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset)); 13750b57cec5SDimitry Andric if (RelType == ELF::R_ARM_PREL31 || RelType == ELF::R_ARM_TARGET1 || 13760b57cec5SDimitry Andric RelType == ELF::R_ARM_ABS32) { 13770b57cec5SDimitry Andric Value.Addend += *Placeholder; 13780b57cec5SDimitry Andric } else if (RelType == ELF::R_ARM_MOVW_ABS_NC || RelType == ELF::R_ARM_MOVT_ABS) { 13790b57cec5SDimitry Andric // See ELF for ARM documentation 13800b57cec5SDimitry Andric Value.Addend += (int16_t)((*Placeholder & 0xFFF) | (((*Placeholder >> 16) & 0xF) << 12)); 13810b57cec5SDimitry Andric } 13820b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric } else if (IsMipsO32ABI) { 13850b57cec5SDimitry Andric uint8_t *Placeholder = reinterpret_cast<uint8_t *>( 13860b57cec5SDimitry Andric computePlaceholderAddress(SectionID, Offset)); 13870b57cec5SDimitry Andric uint32_t Opcode = readBytesUnaligned(Placeholder, 4); 13880b57cec5SDimitry Andric if (RelType == ELF::R_MIPS_26) { 13890b57cec5SDimitry Andric // This is an Mips branch relocation, need to use a stub function. 13900b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); 13910b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 13920b57cec5SDimitry Andric 13930b57cec5SDimitry Andric // Extract the addend from the instruction. 13940b57cec5SDimitry Andric // We shift up by two since the Value will be down shifted again 13950b57cec5SDimitry Andric // when applying the relocation. 13960b57cec5SDimitry Andric uint32_t Addend = (Opcode & 0x03ffffff) << 2; 13970b57cec5SDimitry Andric 13980b57cec5SDimitry Andric Value.Addend += Addend; 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric // Look up for existing stub. 14010b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 14020b57cec5SDimitry Andric if (i != Stubs.end()) { 14030b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, i->second); 14040b57cec5SDimitry Andric addRelocationForSection(RE, SectionID); 14050b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 14060b57cec5SDimitry Andric } else { 14070b57cec5SDimitry Andric // Create a new stub function. 14080b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 14090b57cec5SDimitry Andric Stubs[Value] = Section.getStubOffset(); 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric unsigned AbiVariant = Obj.getPlatformFlags(); 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric uint8_t *StubTargetAddr = createStubFunction( 14140b57cec5SDimitry Andric Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant); 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric // Creating Hi and Lo relocations for the filled stub instructions. 14170b57cec5SDimitry Andric RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(), 14180b57cec5SDimitry Andric ELF::R_MIPS_HI16, Value.Addend); 14190b57cec5SDimitry Andric RelocationEntry RELo(SectionID, 14200b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 4, 14210b57cec5SDimitry Andric ELF::R_MIPS_LO16, Value.Addend); 14220b57cec5SDimitry Andric 14230b57cec5SDimitry Andric if (Value.SymbolName) { 14240b57cec5SDimitry Andric addRelocationForSymbol(REHi, Value.SymbolName); 14250b57cec5SDimitry Andric addRelocationForSymbol(RELo, Value.SymbolName); 14260b57cec5SDimitry Andric } else { 14270b57cec5SDimitry Andric addRelocationForSection(REHi, Value.SectionID); 14280b57cec5SDimitry Andric addRelocationForSection(RELo, Value.SectionID); 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset()); 14320b57cec5SDimitry Andric addRelocationForSection(RE, SectionID); 14330b57cec5SDimitry Andric Section.advanceStubOffset(getMaxStubSize()); 14340b57cec5SDimitry Andric } 14350b57cec5SDimitry Andric } else if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16) { 14360b57cec5SDimitry Andric int64_t Addend = (Opcode & 0x0000ffff) << 16; 14370b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Addend); 14380b57cec5SDimitry Andric PendingRelocs.push_back(std::make_pair(Value, RE)); 14390b57cec5SDimitry Andric } else if (RelType == ELF::R_MIPS_LO16 || RelType == ELF::R_MIPS_PCLO16) { 14400b57cec5SDimitry Andric int64_t Addend = Value.Addend + SignExtend32<16>(Opcode & 0x0000ffff); 14410b57cec5SDimitry Andric for (auto I = PendingRelocs.begin(); I != PendingRelocs.end();) { 14420b57cec5SDimitry Andric const RelocationValueRef &MatchingValue = I->first; 14430b57cec5SDimitry Andric RelocationEntry &Reloc = I->second; 14440b57cec5SDimitry Andric if (MatchingValue == Value && 14450b57cec5SDimitry Andric RelType == getMatchingLoRelocation(Reloc.RelType) && 14460b57cec5SDimitry Andric SectionID == Reloc.SectionID) { 14470b57cec5SDimitry Andric Reloc.Addend += Addend; 14480b57cec5SDimitry Andric if (Value.SymbolName) 14490b57cec5SDimitry Andric addRelocationForSymbol(Reloc, Value.SymbolName); 14500b57cec5SDimitry Andric else 14510b57cec5SDimitry Andric addRelocationForSection(Reloc, Value.SectionID); 14520b57cec5SDimitry Andric I = PendingRelocs.erase(I); 14530b57cec5SDimitry Andric } else 14540b57cec5SDimitry Andric ++I; 14550b57cec5SDimitry Andric } 14560b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Addend); 14570b57cec5SDimitry Andric if (Value.SymbolName) 14580b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 14590b57cec5SDimitry Andric else 14600b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 14610b57cec5SDimitry Andric } else { 14620b57cec5SDimitry Andric if (RelType == ELF::R_MIPS_32) 14630b57cec5SDimitry Andric Value.Addend += Opcode; 14640b57cec5SDimitry Andric else if (RelType == ELF::R_MIPS_PC16) 14650b57cec5SDimitry Andric Value.Addend += SignExtend32<18>((Opcode & 0x0000ffff) << 2); 14660b57cec5SDimitry Andric else if (RelType == ELF::R_MIPS_PC19_S2) 14670b57cec5SDimitry Andric Value.Addend += SignExtend32<21>((Opcode & 0x0007ffff) << 2); 14680b57cec5SDimitry Andric else if (RelType == ELF::R_MIPS_PC21_S2) 14690b57cec5SDimitry Andric Value.Addend += SignExtend32<23>((Opcode & 0x001fffff) << 2); 14700b57cec5SDimitry Andric else if (RelType == ELF::R_MIPS_PC26_S2) 14710b57cec5SDimitry Andric Value.Addend += SignExtend32<28>((Opcode & 0x03ffffff) << 2); 14720b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric } else if (IsMipsN32ABI || IsMipsN64ABI) { 14750b57cec5SDimitry Andric uint32_t r_type = RelType & 0xff; 14760b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); 14770b57cec5SDimitry Andric if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE 14780b57cec5SDimitry Andric || r_type == ELF::R_MIPS_GOT_DISP) { 14790b57cec5SDimitry Andric StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName); 14800b57cec5SDimitry Andric if (i != GOTSymbolOffsets.end()) 14810b57cec5SDimitry Andric RE.SymOffset = i->second; 14820b57cec5SDimitry Andric else { 14830b57cec5SDimitry Andric RE.SymOffset = allocateGOTEntries(1); 14840b57cec5SDimitry Andric GOTSymbolOffsets[TargetName] = RE.SymOffset; 14850b57cec5SDimitry Andric } 14860b57cec5SDimitry Andric if (Value.SymbolName) 14870b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 14880b57cec5SDimitry Andric else 14890b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 14900b57cec5SDimitry Andric } else if (RelType == ELF::R_MIPS_26) { 14910b57cec5SDimitry Andric // This is an Mips branch relocation, need to use a stub function. 14920b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); 14930b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 14940b57cec5SDimitry Andric 14950b57cec5SDimitry Andric // Look up for existing stub. 14960b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 14970b57cec5SDimitry Andric if (i != Stubs.end()) { 14980b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, i->second); 14990b57cec5SDimitry Andric addRelocationForSection(RE, SectionID); 15000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 15010b57cec5SDimitry Andric } else { 15020b57cec5SDimitry Andric // Create a new stub function. 15030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 15040b57cec5SDimitry Andric Stubs[Value] = Section.getStubOffset(); 15050b57cec5SDimitry Andric 15060b57cec5SDimitry Andric unsigned AbiVariant = Obj.getPlatformFlags(); 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric uint8_t *StubTargetAddr = createStubFunction( 15090b57cec5SDimitry Andric Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant); 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric if (IsMipsN32ABI) { 15120b57cec5SDimitry Andric // Creating Hi and Lo relocations for the filled stub instructions. 15130b57cec5SDimitry Andric RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(), 15140b57cec5SDimitry Andric ELF::R_MIPS_HI16, Value.Addend); 15150b57cec5SDimitry Andric RelocationEntry RELo(SectionID, 15160b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 4, 15170b57cec5SDimitry Andric ELF::R_MIPS_LO16, Value.Addend); 15180b57cec5SDimitry Andric if (Value.SymbolName) { 15190b57cec5SDimitry Andric addRelocationForSymbol(REHi, Value.SymbolName); 15200b57cec5SDimitry Andric addRelocationForSymbol(RELo, Value.SymbolName); 15210b57cec5SDimitry Andric } else { 15220b57cec5SDimitry Andric addRelocationForSection(REHi, Value.SectionID); 15230b57cec5SDimitry Andric addRelocationForSection(RELo, Value.SectionID); 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric } else { 15260b57cec5SDimitry Andric // Creating Highest, Higher, Hi and Lo relocations for the filled stub 15270b57cec5SDimitry Andric // instructions. 15280b57cec5SDimitry Andric RelocationEntry REHighest(SectionID, 15290b57cec5SDimitry Andric StubTargetAddr - Section.getAddress(), 15300b57cec5SDimitry Andric ELF::R_MIPS_HIGHEST, Value.Addend); 15310b57cec5SDimitry Andric RelocationEntry REHigher(SectionID, 15320b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 4, 15330b57cec5SDimitry Andric ELF::R_MIPS_HIGHER, Value.Addend); 15340b57cec5SDimitry Andric RelocationEntry REHi(SectionID, 15350b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 12, 15360b57cec5SDimitry Andric ELF::R_MIPS_HI16, Value.Addend); 15370b57cec5SDimitry Andric RelocationEntry RELo(SectionID, 15380b57cec5SDimitry Andric StubTargetAddr - Section.getAddress() + 20, 15390b57cec5SDimitry Andric ELF::R_MIPS_LO16, Value.Addend); 15400b57cec5SDimitry Andric if (Value.SymbolName) { 15410b57cec5SDimitry Andric addRelocationForSymbol(REHighest, Value.SymbolName); 15420b57cec5SDimitry Andric addRelocationForSymbol(REHigher, Value.SymbolName); 15430b57cec5SDimitry Andric addRelocationForSymbol(REHi, Value.SymbolName); 15440b57cec5SDimitry Andric addRelocationForSymbol(RELo, Value.SymbolName); 15450b57cec5SDimitry Andric } else { 15460b57cec5SDimitry Andric addRelocationForSection(REHighest, Value.SectionID); 15470b57cec5SDimitry Andric addRelocationForSection(REHigher, Value.SectionID); 15480b57cec5SDimitry Andric addRelocationForSection(REHi, Value.SectionID); 15490b57cec5SDimitry Andric addRelocationForSection(RELo, Value.SectionID); 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric } 15520b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset()); 15530b57cec5SDimitry Andric addRelocationForSection(RE, SectionID); 15540b57cec5SDimitry Andric Section.advanceStubOffset(getMaxStubSize()); 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric } else { 15570b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 15580b57cec5SDimitry Andric } 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andric } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { 15610b57cec5SDimitry Andric if (RelType == ELF::R_PPC64_REL24) { 15620b57cec5SDimitry Andric // Determine ABI variant in use for this object. 15630b57cec5SDimitry Andric unsigned AbiVariant = Obj.getPlatformFlags(); 15640b57cec5SDimitry Andric AbiVariant &= ELF::EF_PPC64_ABI; 15650b57cec5SDimitry Andric // A PPC branch relocation will need a stub function if the target is 15660b57cec5SDimitry Andric // an external symbol (either Value.SymbolName is set, or SymType is 15670b57cec5SDimitry Andric // Symbol::ST_Unknown) or if the target address is not within the 15680b57cec5SDimitry Andric // signed 24-bits branch address. 15690b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 15700b57cec5SDimitry Andric uint8_t *Target = Section.getAddressWithOffset(Offset); 15710b57cec5SDimitry Andric bool RangeOverflow = false; 15720b57cec5SDimitry Andric bool IsExtern = Value.SymbolName || SymType == SymbolRef::ST_Unknown; 15730b57cec5SDimitry Andric if (!IsExtern) { 15740b57cec5SDimitry Andric if (AbiVariant != 2) { 15750b57cec5SDimitry Andric // In the ELFv1 ABI, a function call may point to the .opd entry, 15760b57cec5SDimitry Andric // so the final symbol value is calculated based on the relocation 15770b57cec5SDimitry Andric // values in the .opd section. 15780b57cec5SDimitry Andric if (auto Err = findOPDEntrySection(Obj, ObjSectionToID, Value)) 15790b57cec5SDimitry Andric return std::move(Err); 15800b57cec5SDimitry Andric } else { 15810b57cec5SDimitry Andric // In the ELFv2 ABI, a function symbol may provide a local entry 15820b57cec5SDimitry Andric // point, which must be used for direct calls. 15830b57cec5SDimitry Andric if (Value.SectionID == SectionID){ 15840b57cec5SDimitry Andric uint8_t SymOther = Symbol->getOther(); 15850b57cec5SDimitry Andric Value.Addend += ELF::decodePPC64LocalEntryOffset(SymOther); 15860b57cec5SDimitry Andric } 15870b57cec5SDimitry Andric } 15880b57cec5SDimitry Andric uint8_t *RelocTarget = 15890b57cec5SDimitry Andric Sections[Value.SectionID].getAddressWithOffset(Value.Addend); 15900b57cec5SDimitry Andric int64_t delta = static_cast<int64_t>(Target - RelocTarget); 15910b57cec5SDimitry Andric // If it is within 26-bits branch range, just set the branch target 15920b57cec5SDimitry Andric if (SignExtend64<26>(delta) != delta) { 15930b57cec5SDimitry Andric RangeOverflow = true; 15940b57cec5SDimitry Andric } else if ((AbiVariant != 2) || 15950b57cec5SDimitry Andric (AbiVariant == 2 && Value.SectionID == SectionID)) { 15960b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); 15970b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 15980b57cec5SDimitry Andric } 15990b57cec5SDimitry Andric } 16000b57cec5SDimitry Andric if (IsExtern || (AbiVariant == 2 && Value.SectionID != SectionID) || 16010b57cec5SDimitry Andric RangeOverflow) { 16020b57cec5SDimitry Andric // It is an external symbol (either Value.SymbolName is set, or 16030b57cec5SDimitry Andric // SymType is SymbolRef::ST_Unknown) or out of range. 16040b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 16050b57cec5SDimitry Andric if (i != Stubs.end()) { 16060b57cec5SDimitry Andric // Symbol function stub already created, just relocate to it 16070b57cec5SDimitry Andric resolveRelocation(Section, Offset, 1608*0fca6ea1SDimitry Andric Section.getLoadAddressWithOffset(i->second), 16090b57cec5SDimitry Andric RelType, 0); 16100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 16110b57cec5SDimitry Andric } else { 16120b57cec5SDimitry Andric // Create a new stub function. 16130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 16140b57cec5SDimitry Andric Stubs[Value] = Section.getStubOffset(); 16150b57cec5SDimitry Andric uint8_t *StubTargetAddr = createStubFunction( 16160b57cec5SDimitry Andric Section.getAddressWithOffset(Section.getStubOffset()), 16170b57cec5SDimitry Andric AbiVariant); 16180b57cec5SDimitry Andric RelocationEntry RE(SectionID, StubTargetAddr - Section.getAddress(), 16190b57cec5SDimitry Andric ELF::R_PPC64_ADDR64, Value.Addend); 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric // Generates the 64-bits address loads as exemplified in section 16220b57cec5SDimitry Andric // 4.5.1 in PPC64 ELF ABI. Note that the relocations need to 16230b57cec5SDimitry Andric // apply to the low part of the instructions, so we have to update 16240b57cec5SDimitry Andric // the offset according to the target endianness. 16250b57cec5SDimitry Andric uint64_t StubRelocOffset = StubTargetAddr - Section.getAddress(); 16260b57cec5SDimitry Andric if (!IsTargetLittleEndian) 16270b57cec5SDimitry Andric StubRelocOffset += 2; 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric RelocationEntry REhst(SectionID, StubRelocOffset + 0, 16300b57cec5SDimitry Andric ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend); 16310b57cec5SDimitry Andric RelocationEntry REhr(SectionID, StubRelocOffset + 4, 16320b57cec5SDimitry Andric ELF::R_PPC64_ADDR16_HIGHER, Value.Addend); 16330b57cec5SDimitry Andric RelocationEntry REh(SectionID, StubRelocOffset + 12, 16340b57cec5SDimitry Andric ELF::R_PPC64_ADDR16_HI, Value.Addend); 16350b57cec5SDimitry Andric RelocationEntry REl(SectionID, StubRelocOffset + 16, 16360b57cec5SDimitry Andric ELF::R_PPC64_ADDR16_LO, Value.Addend); 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric if (Value.SymbolName) { 16390b57cec5SDimitry Andric addRelocationForSymbol(REhst, Value.SymbolName); 16400b57cec5SDimitry Andric addRelocationForSymbol(REhr, Value.SymbolName); 16410b57cec5SDimitry Andric addRelocationForSymbol(REh, Value.SymbolName); 16420b57cec5SDimitry Andric addRelocationForSymbol(REl, Value.SymbolName); 16430b57cec5SDimitry Andric } else { 16440b57cec5SDimitry Andric addRelocationForSection(REhst, Value.SectionID); 16450b57cec5SDimitry Andric addRelocationForSection(REhr, Value.SectionID); 16460b57cec5SDimitry Andric addRelocationForSection(REh, Value.SectionID); 16470b57cec5SDimitry Andric addRelocationForSection(REl, Value.SectionID); 16480b57cec5SDimitry Andric } 16490b57cec5SDimitry Andric 1650*0fca6ea1SDimitry Andric resolveRelocation( 1651*0fca6ea1SDimitry Andric Section, Offset, 1652*0fca6ea1SDimitry Andric Section.getLoadAddressWithOffset(Section.getStubOffset()), 16530b57cec5SDimitry Andric RelType, 0); 16540b57cec5SDimitry Andric Section.advanceStubOffset(getMaxStubSize()); 16550b57cec5SDimitry Andric } 16560b57cec5SDimitry Andric if (IsExtern || (AbiVariant == 2 && Value.SectionID != SectionID)) { 16570b57cec5SDimitry Andric // Restore the TOC for external calls 16580b57cec5SDimitry Andric if (AbiVariant == 2) 16590b57cec5SDimitry Andric writeInt32BE(Target + 4, 0xE8410018); // ld r2,24(r1) 16600b57cec5SDimitry Andric else 16610b57cec5SDimitry Andric writeInt32BE(Target + 4, 0xE8410028); // ld r2,40(r1) 16620b57cec5SDimitry Andric } 16630b57cec5SDimitry Andric } 16640b57cec5SDimitry Andric } else if (RelType == ELF::R_PPC64_TOC16 || 16650b57cec5SDimitry Andric RelType == ELF::R_PPC64_TOC16_DS || 16660b57cec5SDimitry Andric RelType == ELF::R_PPC64_TOC16_LO || 16670b57cec5SDimitry Andric RelType == ELF::R_PPC64_TOC16_LO_DS || 16680b57cec5SDimitry Andric RelType == ELF::R_PPC64_TOC16_HI || 16690b57cec5SDimitry Andric RelType == ELF::R_PPC64_TOC16_HA) { 16700b57cec5SDimitry Andric // These relocations are supposed to subtract the TOC address from 16710b57cec5SDimitry Andric // the final value. This does not fit cleanly into the RuntimeDyld 16720b57cec5SDimitry Andric // scheme, since there may be *two* sections involved in determining 16730b57cec5SDimitry Andric // the relocation value (the section of the symbol referred to by the 16740b57cec5SDimitry Andric // relocation, and the TOC section associated with the current module). 16750b57cec5SDimitry Andric // 16760b57cec5SDimitry Andric // Fortunately, these relocations are currently only ever generated 16770b57cec5SDimitry Andric // referring to symbols that themselves reside in the TOC, which means 16780b57cec5SDimitry Andric // that the two sections are actually the same. Thus they cancel out 16790b57cec5SDimitry Andric // and we can immediately resolve the relocation right now. 16800b57cec5SDimitry Andric switch (RelType) { 16810b57cec5SDimitry Andric case ELF::R_PPC64_TOC16: RelType = ELF::R_PPC64_ADDR16; break; 16820b57cec5SDimitry Andric case ELF::R_PPC64_TOC16_DS: RelType = ELF::R_PPC64_ADDR16_DS; break; 16830b57cec5SDimitry Andric case ELF::R_PPC64_TOC16_LO: RelType = ELF::R_PPC64_ADDR16_LO; break; 16840b57cec5SDimitry Andric case ELF::R_PPC64_TOC16_LO_DS: RelType = ELF::R_PPC64_ADDR16_LO_DS; break; 16850b57cec5SDimitry Andric case ELF::R_PPC64_TOC16_HI: RelType = ELF::R_PPC64_ADDR16_HI; break; 16860b57cec5SDimitry Andric case ELF::R_PPC64_TOC16_HA: RelType = ELF::R_PPC64_ADDR16_HA; break; 16870b57cec5SDimitry Andric default: llvm_unreachable("Wrong relocation type."); 16880b57cec5SDimitry Andric } 16890b57cec5SDimitry Andric 16900b57cec5SDimitry Andric RelocationValueRef TOCValue; 16910b57cec5SDimitry Andric if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, TOCValue)) 16920b57cec5SDimitry Andric return std::move(Err); 16930b57cec5SDimitry Andric if (Value.SymbolName || Value.SectionID != TOCValue.SectionID) 16940b57cec5SDimitry Andric llvm_unreachable("Unsupported TOC relocation."); 16950b57cec5SDimitry Andric Value.Addend -= TOCValue.Addend; 16960b57cec5SDimitry Andric resolveRelocation(Sections[SectionID], Offset, Value.Addend, RelType, 0); 16970b57cec5SDimitry Andric } else { 16980b57cec5SDimitry Andric // There are two ways to refer to the TOC address directly: either 16990b57cec5SDimitry Andric // via a ELF::R_PPC64_TOC relocation (where both symbol and addend are 17000b57cec5SDimitry Andric // ignored), or via any relocation that refers to the magic ".TOC." 17010b57cec5SDimitry Andric // symbols (in which case the addend is respected). 17020b57cec5SDimitry Andric if (RelType == ELF::R_PPC64_TOC) { 17030b57cec5SDimitry Andric RelType = ELF::R_PPC64_ADDR64; 17040b57cec5SDimitry Andric if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value)) 17050b57cec5SDimitry Andric return std::move(Err); 17060b57cec5SDimitry Andric } else if (TargetName == ".TOC.") { 17070b57cec5SDimitry Andric if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value)) 17080b57cec5SDimitry Andric return std::move(Err); 17090b57cec5SDimitry Andric Value.Addend += Addend; 17100b57cec5SDimitry Andric } 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric if (Value.SymbolName) 17150b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 17160b57cec5SDimitry Andric else 17170b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric } else if (Arch == Triple::systemz && 17200b57cec5SDimitry Andric (RelType == ELF::R_390_PLT32DBL || RelType == ELF::R_390_GOTENT)) { 17210b57cec5SDimitry Andric // Create function stubs for both PLT and GOT references, regardless of 17220b57cec5SDimitry Andric // whether the GOT reference is to data or code. The stub contains the 17230b57cec5SDimitry Andric // full address of the symbol, as needed by GOT references, and the 17240b57cec5SDimitry Andric // executable part only adds an overhead of 8 bytes. 17250b57cec5SDimitry Andric // 17260b57cec5SDimitry Andric // We could try to conserve space by allocating the code and data 17270b57cec5SDimitry Andric // parts of the stub separately. However, as things stand, we allocate 17280b57cec5SDimitry Andric // a stub for every relocation, so using a GOT in JIT code should be 17290b57cec5SDimitry Andric // no less space efficient than using an explicit constant pool. 17300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation."); 17310b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric // Look for an existing stub. 17340b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 17350b57cec5SDimitry Andric uintptr_t StubAddress; 17360b57cec5SDimitry Andric if (i != Stubs.end()) { 17370b57cec5SDimitry Andric StubAddress = uintptr_t(Section.getAddressWithOffset(i->second)); 17380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 17390b57cec5SDimitry Andric } else { 17400b57cec5SDimitry Andric // Create a new stub function. 17410b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 17420b57cec5SDimitry Andric 17430b57cec5SDimitry Andric uintptr_t BaseAddress = uintptr_t(Section.getAddress()); 17440b57cec5SDimitry Andric StubAddress = 1745bdd1243dSDimitry Andric alignTo(BaseAddress + Section.getStubOffset(), getStubAlignment()); 17460b57cec5SDimitry Andric unsigned StubOffset = StubAddress - BaseAddress; 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric Stubs[Value] = StubOffset; 17490b57cec5SDimitry Andric createStubFunction((uint8_t *)StubAddress); 17500b57cec5SDimitry Andric RelocationEntry RE(SectionID, StubOffset + 8, ELF::R_390_64, 17510b57cec5SDimitry Andric Value.Offset); 17520b57cec5SDimitry Andric if (Value.SymbolName) 17530b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 17540b57cec5SDimitry Andric else 17550b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 17560b57cec5SDimitry Andric Section.advanceStubOffset(getMaxStubSize()); 17570b57cec5SDimitry Andric } 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric if (RelType == ELF::R_390_GOTENT) 17600b57cec5SDimitry Andric resolveRelocation(Section, Offset, StubAddress + 8, ELF::R_390_PC32DBL, 17610b57cec5SDimitry Andric Addend); 17620b57cec5SDimitry Andric else 17630b57cec5SDimitry Andric resolveRelocation(Section, Offset, StubAddress, RelType, Addend); 17640b57cec5SDimitry Andric } else if (Arch == Triple::x86_64) { 17650b57cec5SDimitry Andric if (RelType == ELF::R_X86_64_PLT32) { 17660b57cec5SDimitry Andric // The way the PLT relocations normally work is that the linker allocates 17670b57cec5SDimitry Andric // the 17680b57cec5SDimitry Andric // PLT and this relocation makes a PC-relative call into the PLT. The PLT 17690b57cec5SDimitry Andric // entry will then jump to an address provided by the GOT. On first call, 17700b57cec5SDimitry Andric // the 17710b57cec5SDimitry Andric // GOT address will point back into PLT code that resolves the symbol. After 17720b57cec5SDimitry Andric // the first call, the GOT entry points to the actual function. 17730b57cec5SDimitry Andric // 17740b57cec5SDimitry Andric // For local functions we're ignoring all of that here and just replacing 17750b57cec5SDimitry Andric // the PLT32 relocation type with PC32, which will translate the relocation 17760b57cec5SDimitry Andric // into a PC-relative call directly to the function. For external symbols we 17770b57cec5SDimitry Andric // can't be sure the function will be within 2^32 bytes of the call site, so 17780b57cec5SDimitry Andric // we need to create a stub, which calls into the GOT. This case is 17790b57cec5SDimitry Andric // equivalent to the usual PLT implementation except that we use the stub 17800b57cec5SDimitry Andric // mechanism in RuntimeDyld (which puts stubs at the end of the section) 17810b57cec5SDimitry Andric // rather than allocating a PLT section. 1782fe6060f1SDimitry Andric if (Value.SymbolName && MemMgr.allowStubAllocation()) { 17830b57cec5SDimitry Andric // This is a call to an external function. 17840b57cec5SDimitry Andric // Look for an existing stub. 1785e8d8bef9SDimitry Andric SectionEntry *Section = &Sections[SectionID]; 17860b57cec5SDimitry Andric StubMap::const_iterator i = Stubs.find(Value); 17870b57cec5SDimitry Andric uintptr_t StubAddress; 17880b57cec5SDimitry Andric if (i != Stubs.end()) { 1789e8d8bef9SDimitry Andric StubAddress = uintptr_t(Section->getAddress()) + i->second; 17900b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Stub function found\n"); 17910b57cec5SDimitry Andric } else { 17920b57cec5SDimitry Andric // Create a new stub function (equivalent to a PLT entry). 17930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Create a new stub function\n"); 17940b57cec5SDimitry Andric 1795e8d8bef9SDimitry Andric uintptr_t BaseAddress = uintptr_t(Section->getAddress()); 1796bdd1243dSDimitry Andric StubAddress = alignTo(BaseAddress + Section->getStubOffset(), 1797bdd1243dSDimitry Andric getStubAlignment()); 17980b57cec5SDimitry Andric unsigned StubOffset = StubAddress - BaseAddress; 17990b57cec5SDimitry Andric Stubs[Value] = StubOffset; 18000b57cec5SDimitry Andric createStubFunction((uint8_t *)StubAddress); 18010b57cec5SDimitry Andric 18020b57cec5SDimitry Andric // Bump our stub offset counter 1803e8d8bef9SDimitry Andric Section->advanceStubOffset(getMaxStubSize()); 18040b57cec5SDimitry Andric 18050b57cec5SDimitry Andric // Allocate a GOT Entry 18060b57cec5SDimitry Andric uint64_t GOTOffset = allocateGOTEntries(1); 1807e8d8bef9SDimitry Andric // This potentially creates a new Section which potentially 1808e8d8bef9SDimitry Andric // invalidates the Section pointer, so reload it. 1809e8d8bef9SDimitry Andric Section = &Sections[SectionID]; 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric // The load of the GOT address has an addend of -4 18120b57cec5SDimitry Andric resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4, 18130b57cec5SDimitry Andric ELF::R_X86_64_PC32); 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric // Fill in the value of the symbol we're targeting into the GOT 18160b57cec5SDimitry Andric addRelocationForSymbol( 18170b57cec5SDimitry Andric computeGOTOffsetRE(GOTOffset, 0, ELF::R_X86_64_64), 18180b57cec5SDimitry Andric Value.SymbolName); 18190b57cec5SDimitry Andric } 18200b57cec5SDimitry Andric 18210b57cec5SDimitry Andric // Make the target call a call into the stub table. 1822e8d8bef9SDimitry Andric resolveRelocation(*Section, Offset, StubAddress, ELF::R_X86_64_PC32, 18230b57cec5SDimitry Andric Addend); 18240b57cec5SDimitry Andric } else { 1825fe6060f1SDimitry Andric Value.Addend += support::ulittle32_t::ref( 1826fe6060f1SDimitry Andric computePlaceholderAddress(SectionID, Offset)); 1827fe6060f1SDimitry Andric processSimpleRelocation(SectionID, Offset, ELF::R_X86_64_PC32, Value); 18280b57cec5SDimitry Andric } 18290b57cec5SDimitry Andric } else if (RelType == ELF::R_X86_64_GOTPCREL || 18300b57cec5SDimitry Andric RelType == ELF::R_X86_64_GOTPCRELX || 18310b57cec5SDimitry Andric RelType == ELF::R_X86_64_REX_GOTPCRELX) { 18320b57cec5SDimitry Andric uint64_t GOTOffset = allocateGOTEntries(1); 18330b57cec5SDimitry Andric resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, 18340b57cec5SDimitry Andric ELF::R_X86_64_PC32); 18350b57cec5SDimitry Andric 18360b57cec5SDimitry Andric // Fill in the value of the symbol we're targeting into the GOT 18370b57cec5SDimitry Andric RelocationEntry RE = 18380b57cec5SDimitry Andric computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64); 18390b57cec5SDimitry Andric if (Value.SymbolName) 18400b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 18410b57cec5SDimitry Andric else 18420b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 18430b57cec5SDimitry Andric } else if (RelType == ELF::R_X86_64_GOT64) { 18440b57cec5SDimitry Andric // Fill in a 64-bit GOT offset. 18450b57cec5SDimitry Andric uint64_t GOTOffset = allocateGOTEntries(1); 18460b57cec5SDimitry Andric resolveRelocation(Sections[SectionID], Offset, GOTOffset, 18470b57cec5SDimitry Andric ELF::R_X86_64_64, 0); 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric // Fill in the value of the symbol we're targeting into the GOT 18500b57cec5SDimitry Andric RelocationEntry RE = 18510b57cec5SDimitry Andric computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64); 18520b57cec5SDimitry Andric if (Value.SymbolName) 18530b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 18540b57cec5SDimitry Andric else 18550b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 1856349cc55cSDimitry Andric } else if (RelType == ELF::R_X86_64_GOTPC32) { 18570b57cec5SDimitry Andric // Materialize the address of the base of the GOT relative to the PC. 18580b57cec5SDimitry Andric // This doesn't create a GOT entry, but it does mean we need a GOT 18590b57cec5SDimitry Andric // section. 18600b57cec5SDimitry Andric (void)allocateGOTEntries(0); 1861349cc55cSDimitry Andric resolveGOTOffsetRelocation(SectionID, Offset, Addend, ELF::R_X86_64_PC32); 1862349cc55cSDimitry Andric } else if (RelType == ELF::R_X86_64_GOTPC64) { 1863349cc55cSDimitry Andric (void)allocateGOTEntries(0); 18640b57cec5SDimitry Andric resolveGOTOffsetRelocation(SectionID, Offset, Addend, ELF::R_X86_64_PC64); 18650b57cec5SDimitry Andric } else if (RelType == ELF::R_X86_64_GOTOFF64) { 18660b57cec5SDimitry Andric // GOTOFF relocations ultimately require a section difference relocation. 18670b57cec5SDimitry Andric (void)allocateGOTEntries(0); 18680b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 18690b57cec5SDimitry Andric } else if (RelType == ELF::R_X86_64_PC32) { 18700b57cec5SDimitry Andric Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); 18710b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 18720b57cec5SDimitry Andric } else if (RelType == ELF::R_X86_64_PC64) { 18730b57cec5SDimitry Andric Value.Addend += support::ulittle64_t::ref(computePlaceholderAddress(SectionID, Offset)); 18740b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 1875349cc55cSDimitry Andric } else if (RelType == ELF::R_X86_64_GOTTPOFF) { 1876349cc55cSDimitry Andric processX86_64GOTTPOFFRelocation(SectionID, Offset, Value, Addend); 1877349cc55cSDimitry Andric } else if (RelType == ELF::R_X86_64_TLSGD || 1878349cc55cSDimitry Andric RelType == ELF::R_X86_64_TLSLD) { 1879349cc55cSDimitry Andric // The next relocation must be the relocation for __tls_get_addr. 1880349cc55cSDimitry Andric ++RelI; 1881349cc55cSDimitry Andric auto &GetAddrRelocation = *RelI; 1882349cc55cSDimitry Andric processX86_64TLSRelocation(SectionID, Offset, RelType, Value, Addend, 1883349cc55cSDimitry Andric GetAddrRelocation); 18840b57cec5SDimitry Andric } else { 18850b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 18860b57cec5SDimitry Andric } 18870b57cec5SDimitry Andric } else { 18880b57cec5SDimitry Andric if (Arch == Triple::x86) { 18890b57cec5SDimitry Andric Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); 18900b57cec5SDimitry Andric } 18910b57cec5SDimitry Andric processSimpleRelocation(SectionID, Offset, RelType, Value); 18920b57cec5SDimitry Andric } 18930b57cec5SDimitry Andric return ++RelI; 18940b57cec5SDimitry Andric } 18950b57cec5SDimitry Andric 1896349cc55cSDimitry Andric void RuntimeDyldELF::processX86_64GOTTPOFFRelocation(unsigned SectionID, 1897349cc55cSDimitry Andric uint64_t Offset, 1898349cc55cSDimitry Andric RelocationValueRef Value, 1899349cc55cSDimitry Andric int64_t Addend) { 1900349cc55cSDimitry Andric // Use the approach from "x86-64 Linker Optimizations" from the TLS spec 1901349cc55cSDimitry Andric // to replace the GOTTPOFF relocation with a TPOFF relocation. The spec 1902349cc55cSDimitry Andric // only mentions one optimization even though there are two different 1903349cc55cSDimitry Andric // code sequences for the Initial Exec TLS Model. We match the code to 1904349cc55cSDimitry Andric // find out which one was used. 1905349cc55cSDimitry Andric 1906349cc55cSDimitry Andric // A possible TLS code sequence and its replacement 1907349cc55cSDimitry Andric struct CodeSequence { 1908349cc55cSDimitry Andric // The expected code sequence 1909349cc55cSDimitry Andric ArrayRef<uint8_t> ExpectedCodeSequence; 1910349cc55cSDimitry Andric // The negative offset of the GOTTPOFF relocation to the beginning of 1911349cc55cSDimitry Andric // the sequence 1912349cc55cSDimitry Andric uint64_t TLSSequenceOffset; 1913349cc55cSDimitry Andric // The new code sequence 1914349cc55cSDimitry Andric ArrayRef<uint8_t> NewCodeSequence; 1915349cc55cSDimitry Andric // The offset of the new TPOFF relocation 1916349cc55cSDimitry Andric uint64_t TpoffRelocationOffset; 1917349cc55cSDimitry Andric }; 1918349cc55cSDimitry Andric 1919349cc55cSDimitry Andric std::array<CodeSequence, 2> CodeSequences; 1920349cc55cSDimitry Andric 1921349cc55cSDimitry Andric // Initial Exec Code Model Sequence 1922349cc55cSDimitry Andric { 1923349cc55cSDimitry Andric static const std::initializer_list<uint8_t> ExpectedCodeSequenceList = { 1924349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 1925349cc55cSDimitry Andric 0x00, // mov %fs:0, %rax 1926349cc55cSDimitry Andric 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // add x@gotpoff(%rip), 1927349cc55cSDimitry Andric // %rax 1928349cc55cSDimitry Andric }; 1929349cc55cSDimitry Andric CodeSequences[0].ExpectedCodeSequence = 1930349cc55cSDimitry Andric ArrayRef<uint8_t>(ExpectedCodeSequenceList); 1931349cc55cSDimitry Andric CodeSequences[0].TLSSequenceOffset = 12; 1932349cc55cSDimitry Andric 1933349cc55cSDimitry Andric static const std::initializer_list<uint8_t> NewCodeSequenceList = { 1934349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0, %rax 1935349cc55cSDimitry Andric 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff(%rax), %rax 1936349cc55cSDimitry Andric }; 1937349cc55cSDimitry Andric CodeSequences[0].NewCodeSequence = ArrayRef<uint8_t>(NewCodeSequenceList); 1938349cc55cSDimitry Andric CodeSequences[0].TpoffRelocationOffset = 12; 1939349cc55cSDimitry Andric } 1940349cc55cSDimitry Andric 1941349cc55cSDimitry Andric // Initial Exec Code Model Sequence, II 1942349cc55cSDimitry Andric { 1943349cc55cSDimitry Andric static const std::initializer_list<uint8_t> ExpectedCodeSequenceList = { 1944349cc55cSDimitry Andric 0x48, 0x8b, 0x05, 0x00, 0x00, 0x00, 0x00, // mov x@gotpoff(%rip), %rax 1945349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x00, 0x00, 0x00, 0x00 // mov %fs:(%rax), %rax 1946349cc55cSDimitry Andric }; 1947349cc55cSDimitry Andric CodeSequences[1].ExpectedCodeSequence = 1948349cc55cSDimitry Andric ArrayRef<uint8_t>(ExpectedCodeSequenceList); 1949349cc55cSDimitry Andric CodeSequences[1].TLSSequenceOffset = 3; 1950349cc55cSDimitry Andric 1951349cc55cSDimitry Andric static const std::initializer_list<uint8_t> NewCodeSequenceList = { 1952349cc55cSDimitry Andric 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, // 6 byte nop 1953349cc55cSDimitry Andric 0x64, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:x@tpoff, %rax 1954349cc55cSDimitry Andric }; 1955349cc55cSDimitry Andric CodeSequences[1].NewCodeSequence = ArrayRef<uint8_t>(NewCodeSequenceList); 1956349cc55cSDimitry Andric CodeSequences[1].TpoffRelocationOffset = 10; 1957349cc55cSDimitry Andric } 1958349cc55cSDimitry Andric 1959349cc55cSDimitry Andric bool Resolved = false; 1960349cc55cSDimitry Andric auto &Section = Sections[SectionID]; 1961349cc55cSDimitry Andric for (const auto &C : CodeSequences) { 1962349cc55cSDimitry Andric assert(C.ExpectedCodeSequence.size() == C.NewCodeSequence.size() && 1963349cc55cSDimitry Andric "Old and new code sequences must have the same size"); 1964349cc55cSDimitry Andric 1965349cc55cSDimitry Andric if (Offset < C.TLSSequenceOffset || 1966349cc55cSDimitry Andric (Offset - C.TLSSequenceOffset + C.NewCodeSequence.size()) > 1967349cc55cSDimitry Andric Section.getSize()) { 1968349cc55cSDimitry Andric // This can't be a matching sequence as it doesn't fit in the current 1969349cc55cSDimitry Andric // section 1970349cc55cSDimitry Andric continue; 1971349cc55cSDimitry Andric } 1972349cc55cSDimitry Andric 1973349cc55cSDimitry Andric auto TLSSequenceStartOffset = Offset - C.TLSSequenceOffset; 1974349cc55cSDimitry Andric auto *TLSSequence = Section.getAddressWithOffset(TLSSequenceStartOffset); 1975349cc55cSDimitry Andric if (ArrayRef<uint8_t>(TLSSequence, C.ExpectedCodeSequence.size()) != 1976349cc55cSDimitry Andric C.ExpectedCodeSequence) { 1977349cc55cSDimitry Andric continue; 1978349cc55cSDimitry Andric } 1979349cc55cSDimitry Andric 1980349cc55cSDimitry Andric memcpy(TLSSequence, C.NewCodeSequence.data(), C.NewCodeSequence.size()); 1981349cc55cSDimitry Andric 1982349cc55cSDimitry Andric // The original GOTTPOFF relocation has an addend as it is PC relative, 1983349cc55cSDimitry Andric // so it needs to be corrected. The TPOFF32 relocation is used as an 1984349cc55cSDimitry Andric // absolute value (which is an offset from %fs:0), so remove the addend 1985349cc55cSDimitry Andric // again. 1986349cc55cSDimitry Andric RelocationEntry RE(SectionID, 1987349cc55cSDimitry Andric TLSSequenceStartOffset + C.TpoffRelocationOffset, 1988349cc55cSDimitry Andric ELF::R_X86_64_TPOFF32, Value.Addend - Addend); 1989349cc55cSDimitry Andric 1990349cc55cSDimitry Andric if (Value.SymbolName) 1991349cc55cSDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 1992349cc55cSDimitry Andric else 1993349cc55cSDimitry Andric addRelocationForSection(RE, Value.SectionID); 1994349cc55cSDimitry Andric 1995349cc55cSDimitry Andric Resolved = true; 1996349cc55cSDimitry Andric break; 1997349cc55cSDimitry Andric } 1998349cc55cSDimitry Andric 1999349cc55cSDimitry Andric if (!Resolved) { 2000349cc55cSDimitry Andric // The GOTTPOFF relocation was not used in one of the sequences 2001349cc55cSDimitry Andric // described in the spec, so we can't optimize it to a TPOFF 2002349cc55cSDimitry Andric // relocation. 2003349cc55cSDimitry Andric uint64_t GOTOffset = allocateGOTEntries(1); 2004349cc55cSDimitry Andric resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, 2005349cc55cSDimitry Andric ELF::R_X86_64_PC32); 2006349cc55cSDimitry Andric RelocationEntry RE = 2007349cc55cSDimitry Andric computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_TPOFF64); 2008349cc55cSDimitry Andric if (Value.SymbolName) 2009349cc55cSDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 2010349cc55cSDimitry Andric else 2011349cc55cSDimitry Andric addRelocationForSection(RE, Value.SectionID); 2012349cc55cSDimitry Andric } 2013349cc55cSDimitry Andric } 2014349cc55cSDimitry Andric 2015349cc55cSDimitry Andric void RuntimeDyldELF::processX86_64TLSRelocation( 2016349cc55cSDimitry Andric unsigned SectionID, uint64_t Offset, uint64_t RelType, 2017349cc55cSDimitry Andric RelocationValueRef Value, int64_t Addend, 2018349cc55cSDimitry Andric const RelocationRef &GetAddrRelocation) { 2019349cc55cSDimitry Andric // Since we are statically linking and have no additional DSOs, we can resolve 2020349cc55cSDimitry Andric // the relocation directly without using __tls_get_addr. 2021349cc55cSDimitry Andric // Use the approach from "x86-64 Linker Optimizations" from the TLS spec 2022349cc55cSDimitry Andric // to replace it with the Local Exec relocation variant. 2023349cc55cSDimitry Andric 2024349cc55cSDimitry Andric // Find out whether the code was compiled with the large or small memory 2025349cc55cSDimitry Andric // model. For this we look at the next relocation which is the relocation 2026349cc55cSDimitry Andric // for the __tls_get_addr function. If it's a 32 bit relocation, it's the 2027349cc55cSDimitry Andric // small code model, with a 64 bit relocation it's the large code model. 2028349cc55cSDimitry Andric bool IsSmallCodeModel; 2029349cc55cSDimitry Andric // Is the relocation for the __tls_get_addr a PC-relative GOT relocation? 2030349cc55cSDimitry Andric bool IsGOTPCRel = false; 2031349cc55cSDimitry Andric 2032349cc55cSDimitry Andric switch (GetAddrRelocation.getType()) { 2033349cc55cSDimitry Andric case ELF::R_X86_64_GOTPCREL: 2034349cc55cSDimitry Andric case ELF::R_X86_64_REX_GOTPCRELX: 2035349cc55cSDimitry Andric case ELF::R_X86_64_GOTPCRELX: 2036349cc55cSDimitry Andric IsGOTPCRel = true; 2037bdd1243dSDimitry Andric [[fallthrough]]; 2038349cc55cSDimitry Andric case ELF::R_X86_64_PLT32: 2039349cc55cSDimitry Andric IsSmallCodeModel = true; 2040349cc55cSDimitry Andric break; 2041349cc55cSDimitry Andric case ELF::R_X86_64_PLTOFF64: 2042349cc55cSDimitry Andric IsSmallCodeModel = false; 2043349cc55cSDimitry Andric break; 2044349cc55cSDimitry Andric default: 2045349cc55cSDimitry Andric report_fatal_error( 2046349cc55cSDimitry Andric "invalid TLS relocations for General/Local Dynamic TLS Model: " 2047349cc55cSDimitry Andric "expected PLT or GOT relocation for __tls_get_addr function"); 2048349cc55cSDimitry Andric } 2049349cc55cSDimitry Andric 2050349cc55cSDimitry Andric // The negative offset to the start of the TLS code sequence relative to 2051349cc55cSDimitry Andric // the offset of the TLSGD/TLSLD relocation 2052349cc55cSDimitry Andric uint64_t TLSSequenceOffset; 2053349cc55cSDimitry Andric // The expected start of the code sequence 2054349cc55cSDimitry Andric ArrayRef<uint8_t> ExpectedCodeSequence; 2055349cc55cSDimitry Andric // The new TLS code sequence that will replace the existing code 2056349cc55cSDimitry Andric ArrayRef<uint8_t> NewCodeSequence; 2057349cc55cSDimitry Andric 2058349cc55cSDimitry Andric if (RelType == ELF::R_X86_64_TLSGD) { 2059349cc55cSDimitry Andric // The offset of the new TPOFF32 relocation (offset starting from the 2060349cc55cSDimitry Andric // beginning of the whole TLS sequence) 2061349cc55cSDimitry Andric uint64_t TpoffRelocOffset; 2062349cc55cSDimitry Andric 2063349cc55cSDimitry Andric if (IsSmallCodeModel) { 2064349cc55cSDimitry Andric if (!IsGOTPCRel) { 2065349cc55cSDimitry Andric static const std::initializer_list<uint8_t> CodeSequence = { 2066349cc55cSDimitry Andric 0x66, // data16 (no-op prefix) 2067349cc55cSDimitry Andric 0x48, 0x8d, 0x3d, 0x00, 0x00, 2068349cc55cSDimitry Andric 0x00, 0x00, // lea <disp32>(%rip), %rdi 2069349cc55cSDimitry Andric 0x66, 0x66, // two data16 prefixes 2070349cc55cSDimitry Andric 0x48, // rex64 (no-op prefix) 2071349cc55cSDimitry Andric 0xe8, 0x00, 0x00, 0x00, 0x00 // call __tls_get_addr@plt 2072349cc55cSDimitry Andric }; 2073349cc55cSDimitry Andric ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence); 2074349cc55cSDimitry Andric TLSSequenceOffset = 4; 2075349cc55cSDimitry Andric } else { 2076349cc55cSDimitry Andric // This code sequence is not described in the TLS spec but gcc 2077349cc55cSDimitry Andric // generates it sometimes. 2078349cc55cSDimitry Andric static const std::initializer_list<uint8_t> CodeSequence = { 2079349cc55cSDimitry Andric 0x66, // data16 (no-op prefix) 2080349cc55cSDimitry Andric 0x48, 0x8d, 0x3d, 0x00, 0x00, 2081349cc55cSDimitry Andric 0x00, 0x00, // lea <disp32>(%rip), %rdi 2082349cc55cSDimitry Andric 0x66, // data16 prefix (no-op prefix) 2083349cc55cSDimitry Andric 0x48, // rex64 (no-op prefix) 2084349cc55cSDimitry Andric 0xff, 0x15, 0x00, 0x00, 0x00, 2085349cc55cSDimitry Andric 0x00 // call *__tls_get_addr@gotpcrel(%rip) 2086349cc55cSDimitry Andric }; 2087349cc55cSDimitry Andric ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence); 2088349cc55cSDimitry Andric TLSSequenceOffset = 4; 2089349cc55cSDimitry Andric } 2090349cc55cSDimitry Andric 2091349cc55cSDimitry Andric // The replacement code for the small code model. It's the same for 2092349cc55cSDimitry Andric // both sequences. 2093349cc55cSDimitry Andric static const std::initializer_list<uint8_t> SmallSequence = { 2094349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 2095349cc55cSDimitry Andric 0x00, // mov %fs:0, %rax 2096349cc55cSDimitry Andric 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff(%rax), 2097349cc55cSDimitry Andric // %rax 2098349cc55cSDimitry Andric }; 2099349cc55cSDimitry Andric NewCodeSequence = ArrayRef<uint8_t>(SmallSequence); 2100349cc55cSDimitry Andric TpoffRelocOffset = 12; 2101349cc55cSDimitry Andric } else { 2102349cc55cSDimitry Andric static const std::initializer_list<uint8_t> CodeSequence = { 2103349cc55cSDimitry Andric 0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00, // lea <disp32>(%rip), 2104349cc55cSDimitry Andric // %rdi 2105349cc55cSDimitry Andric 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2106349cc55cSDimitry Andric 0x00, // movabs $__tls_get_addr@pltoff, %rax 2107349cc55cSDimitry Andric 0x48, 0x01, 0xd8, // add %rbx, %rax 2108349cc55cSDimitry Andric 0xff, 0xd0 // call *%rax 2109349cc55cSDimitry Andric }; 2110349cc55cSDimitry Andric ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence); 2111349cc55cSDimitry Andric TLSSequenceOffset = 3; 2112349cc55cSDimitry Andric 2113349cc55cSDimitry Andric // The replacement code for the large code model 2114349cc55cSDimitry Andric static const std::initializer_list<uint8_t> LargeSequence = { 2115349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 2116349cc55cSDimitry Andric 0x00, // mov %fs:0, %rax 2117349cc55cSDimitry Andric 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00, // lea x@tpoff(%rax), 2118349cc55cSDimitry Andric // %rax 2119349cc55cSDimitry Andric 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 // nopw 0x0(%rax,%rax,1) 2120349cc55cSDimitry Andric }; 2121349cc55cSDimitry Andric NewCodeSequence = ArrayRef<uint8_t>(LargeSequence); 2122349cc55cSDimitry Andric TpoffRelocOffset = 12; 2123349cc55cSDimitry Andric } 2124349cc55cSDimitry Andric 2125349cc55cSDimitry Andric // The TLSGD/TLSLD relocations are PC-relative, so they have an addend. 2126349cc55cSDimitry Andric // The new TPOFF32 relocations is used as an absolute offset from 2127349cc55cSDimitry Andric // %fs:0, so remove the TLSGD/TLSLD addend again. 2128349cc55cSDimitry Andric RelocationEntry RE(SectionID, Offset - TLSSequenceOffset + TpoffRelocOffset, 2129349cc55cSDimitry Andric ELF::R_X86_64_TPOFF32, Value.Addend - Addend); 2130349cc55cSDimitry Andric if (Value.SymbolName) 2131349cc55cSDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 2132349cc55cSDimitry Andric else 2133349cc55cSDimitry Andric addRelocationForSection(RE, Value.SectionID); 2134349cc55cSDimitry Andric } else if (RelType == ELF::R_X86_64_TLSLD) { 2135349cc55cSDimitry Andric if (IsSmallCodeModel) { 2136349cc55cSDimitry Andric if (!IsGOTPCRel) { 2137349cc55cSDimitry Andric static const std::initializer_list<uint8_t> CodeSequence = { 2138349cc55cSDimitry Andric 0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, // leaq <disp32>(%rip), %rdi 2139349cc55cSDimitry Andric 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00 // call __tls_get_addr@plt 2140349cc55cSDimitry Andric }; 2141349cc55cSDimitry Andric ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence); 2142349cc55cSDimitry Andric TLSSequenceOffset = 3; 2143349cc55cSDimitry Andric 2144349cc55cSDimitry Andric // The replacement code for the small code model 2145349cc55cSDimitry Andric static const std::initializer_list<uint8_t> SmallSequence = { 2146349cc55cSDimitry Andric 0x66, 0x66, 0x66, // three data16 prefixes (no-op) 2147349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 2148349cc55cSDimitry Andric 0x00, 0x00, 0x00, 0x00 // mov %fs:0, %rax 2149349cc55cSDimitry Andric }; 2150349cc55cSDimitry Andric NewCodeSequence = ArrayRef<uint8_t>(SmallSequence); 2151349cc55cSDimitry Andric } else { 2152349cc55cSDimitry Andric // This code sequence is not described in the TLS spec but gcc 2153349cc55cSDimitry Andric // generates it sometimes. 2154349cc55cSDimitry Andric static const std::initializer_list<uint8_t> CodeSequence = { 2155349cc55cSDimitry Andric 0x48, 0x8d, 0x3d, 0x00, 2156349cc55cSDimitry Andric 0x00, 0x00, 0x00, // leaq <disp32>(%rip), %rdi 2157349cc55cSDimitry Andric 0xff, 0x15, 0x00, 0x00, 2158349cc55cSDimitry Andric 0x00, 0x00 // call 2159349cc55cSDimitry Andric // *__tls_get_addr@gotpcrel(%rip) 2160349cc55cSDimitry Andric }; 2161349cc55cSDimitry Andric ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence); 2162349cc55cSDimitry Andric TLSSequenceOffset = 3; 2163349cc55cSDimitry Andric 2164349cc55cSDimitry Andric // The replacement is code is just like above but it needs to be 2165349cc55cSDimitry Andric // one byte longer. 2166349cc55cSDimitry Andric static const std::initializer_list<uint8_t> SmallSequence = { 2167349cc55cSDimitry Andric 0x0f, 0x1f, 0x40, 0x00, // 4 byte nop 2168349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 2169349cc55cSDimitry Andric 0x00, 0x00, 0x00, 0x00 // mov %fs:0, %rax 2170349cc55cSDimitry Andric }; 2171349cc55cSDimitry Andric NewCodeSequence = ArrayRef<uint8_t>(SmallSequence); 2172349cc55cSDimitry Andric } 2173349cc55cSDimitry Andric } else { 2174349cc55cSDimitry Andric // This is the same sequence as for the TLSGD sequence with the large 2175349cc55cSDimitry Andric // memory model above 2176349cc55cSDimitry Andric static const std::initializer_list<uint8_t> CodeSequence = { 2177349cc55cSDimitry Andric 0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00, // lea <disp32>(%rip), 2178349cc55cSDimitry Andric // %rdi 2179349cc55cSDimitry Andric 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2180349cc55cSDimitry Andric 0x48, // movabs $__tls_get_addr@pltoff, %rax 2181349cc55cSDimitry Andric 0x01, 0xd8, // add %rbx, %rax 2182349cc55cSDimitry Andric 0xff, 0xd0 // call *%rax 2183349cc55cSDimitry Andric }; 2184349cc55cSDimitry Andric ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence); 2185349cc55cSDimitry Andric TLSSequenceOffset = 3; 2186349cc55cSDimitry Andric 2187349cc55cSDimitry Andric // The replacement code for the large code model 2188349cc55cSDimitry Andric static const std::initializer_list<uint8_t> LargeSequence = { 2189349cc55cSDimitry Andric 0x66, 0x66, 0x66, // three data16 prefixes (no-op) 2190349cc55cSDimitry Andric 0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 2191349cc55cSDimitry Andric 0x00, // 10 byte nop 2192349cc55cSDimitry Andric 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax 2193349cc55cSDimitry Andric }; 2194349cc55cSDimitry Andric NewCodeSequence = ArrayRef<uint8_t>(LargeSequence); 2195349cc55cSDimitry Andric } 2196349cc55cSDimitry Andric } else { 2197349cc55cSDimitry Andric llvm_unreachable("both TLS relocations handled above"); 2198349cc55cSDimitry Andric } 2199349cc55cSDimitry Andric 2200349cc55cSDimitry Andric assert(ExpectedCodeSequence.size() == NewCodeSequence.size() && 2201349cc55cSDimitry Andric "Old and new code sequences must have the same size"); 2202349cc55cSDimitry Andric 2203349cc55cSDimitry Andric auto &Section = Sections[SectionID]; 2204349cc55cSDimitry Andric if (Offset < TLSSequenceOffset || 2205349cc55cSDimitry Andric (Offset - TLSSequenceOffset + NewCodeSequence.size()) > 2206349cc55cSDimitry Andric Section.getSize()) { 2207349cc55cSDimitry Andric report_fatal_error("unexpected end of section in TLS sequence"); 2208349cc55cSDimitry Andric } 2209349cc55cSDimitry Andric 2210349cc55cSDimitry Andric auto *TLSSequence = Section.getAddressWithOffset(Offset - TLSSequenceOffset); 2211349cc55cSDimitry Andric if (ArrayRef<uint8_t>(TLSSequence, ExpectedCodeSequence.size()) != 2212349cc55cSDimitry Andric ExpectedCodeSequence) { 2213349cc55cSDimitry Andric report_fatal_error( 2214349cc55cSDimitry Andric "invalid TLS sequence for Global/Local Dynamic TLS Model"); 2215349cc55cSDimitry Andric } 2216349cc55cSDimitry Andric 2217349cc55cSDimitry Andric memcpy(TLSSequence, NewCodeSequence.data(), NewCodeSequence.size()); 2218349cc55cSDimitry Andric } 2219349cc55cSDimitry Andric 22200b57cec5SDimitry Andric size_t RuntimeDyldELF::getGOTEntrySize() { 22210b57cec5SDimitry Andric // We don't use the GOT in all of these cases, but it's essentially free 22220b57cec5SDimitry Andric // to put them all here. 22230b57cec5SDimitry Andric size_t Result = 0; 22240b57cec5SDimitry Andric switch (Arch) { 22250b57cec5SDimitry Andric case Triple::x86_64: 22260b57cec5SDimitry Andric case Triple::aarch64: 22270b57cec5SDimitry Andric case Triple::aarch64_be: 22280b57cec5SDimitry Andric case Triple::ppc64: 22290b57cec5SDimitry Andric case Triple::ppc64le: 22300b57cec5SDimitry Andric case Triple::systemz: 22310b57cec5SDimitry Andric Result = sizeof(uint64_t); 22320b57cec5SDimitry Andric break; 22330b57cec5SDimitry Andric case Triple::x86: 22340b57cec5SDimitry Andric case Triple::arm: 22350b57cec5SDimitry Andric case Triple::thumb: 22360b57cec5SDimitry Andric Result = sizeof(uint32_t); 22370b57cec5SDimitry Andric break; 22380b57cec5SDimitry Andric case Triple::mips: 22390b57cec5SDimitry Andric case Triple::mipsel: 22400b57cec5SDimitry Andric case Triple::mips64: 22410b57cec5SDimitry Andric case Triple::mips64el: 22420b57cec5SDimitry Andric if (IsMipsO32ABI || IsMipsN32ABI) 22430b57cec5SDimitry Andric Result = sizeof(uint32_t); 22440b57cec5SDimitry Andric else if (IsMipsN64ABI) 22450b57cec5SDimitry Andric Result = sizeof(uint64_t); 22460b57cec5SDimitry Andric else 22470b57cec5SDimitry Andric llvm_unreachable("Mips ABI not handled"); 22480b57cec5SDimitry Andric break; 22490b57cec5SDimitry Andric default: 22500b57cec5SDimitry Andric llvm_unreachable("Unsupported CPU type!"); 22510b57cec5SDimitry Andric } 22520b57cec5SDimitry Andric return Result; 22530b57cec5SDimitry Andric } 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned no) { 22560b57cec5SDimitry Andric if (GOTSectionID == 0) { 22570b57cec5SDimitry Andric GOTSectionID = Sections.size(); 22580b57cec5SDimitry Andric // Reserve a section id. We'll allocate the section later 22590b57cec5SDimitry Andric // once we know the total size 22600b57cec5SDimitry Andric Sections.push_back(SectionEntry(".got", nullptr, 0, 0, 0)); 22610b57cec5SDimitry Andric } 22620b57cec5SDimitry Andric uint64_t StartOffset = CurrentGOTIndex * getGOTEntrySize(); 22630b57cec5SDimitry Andric CurrentGOTIndex += no; 22640b57cec5SDimitry Andric return StartOffset; 22650b57cec5SDimitry Andric } 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric uint64_t RuntimeDyldELF::findOrAllocGOTEntry(const RelocationValueRef &Value, 22680b57cec5SDimitry Andric unsigned GOTRelType) { 22690b57cec5SDimitry Andric auto E = GOTOffsetMap.insert({Value, 0}); 22700b57cec5SDimitry Andric if (E.second) { 22710b57cec5SDimitry Andric uint64_t GOTOffset = allocateGOTEntries(1); 22720b57cec5SDimitry Andric 22730b57cec5SDimitry Andric // Create relocation for newly created GOT entry 22740b57cec5SDimitry Andric RelocationEntry RE = 22750b57cec5SDimitry Andric computeGOTOffsetRE(GOTOffset, Value.Offset, GOTRelType); 22760b57cec5SDimitry Andric if (Value.SymbolName) 22770b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 22780b57cec5SDimitry Andric else 22790b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 22800b57cec5SDimitry Andric 22810b57cec5SDimitry Andric E.first->second = GOTOffset; 22820b57cec5SDimitry Andric } 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric return E.first->second; 22850b57cec5SDimitry Andric } 22860b57cec5SDimitry Andric 22870b57cec5SDimitry Andric void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, 22880b57cec5SDimitry Andric uint64_t Offset, 22890b57cec5SDimitry Andric uint64_t GOTOffset, 22900b57cec5SDimitry Andric uint32_t Type) { 22910b57cec5SDimitry Andric // Fill in the relative address of the GOT Entry into the stub 22920b57cec5SDimitry Andric RelocationEntry GOTRE(SectionID, Offset, Type, GOTOffset); 22930b57cec5SDimitry Andric addRelocationForSection(GOTRE, GOTSectionID); 22940b57cec5SDimitry Andric } 22950b57cec5SDimitry Andric 22960b57cec5SDimitry Andric RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(uint64_t GOTOffset, 22970b57cec5SDimitry Andric uint64_t SymbolOffset, 22980b57cec5SDimitry Andric uint32_t Type) { 22990b57cec5SDimitry Andric return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset); 23000b57cec5SDimitry Andric } 23010b57cec5SDimitry Andric 2302bdd1243dSDimitry Andric void RuntimeDyldELF::processNewSymbol(const SymbolRef &ObjSymbol, SymbolTableEntry& Symbol) { 2303bdd1243dSDimitry Andric // This should never return an error as `processNewSymbol` wouldn't have been 2304bdd1243dSDimitry Andric // called if getFlags() returned an error before. 2305bdd1243dSDimitry Andric auto ObjSymbolFlags = cantFail(ObjSymbol.getFlags()); 2306bdd1243dSDimitry Andric 2307bdd1243dSDimitry Andric if (ObjSymbolFlags & SymbolRef::SF_Indirect) { 2308bdd1243dSDimitry Andric if (IFuncStubSectionID == 0) { 2309bdd1243dSDimitry Andric // Create a dummy section for the ifunc stubs. It will be actually 2310bdd1243dSDimitry Andric // allocated in finalizeLoad() below. 2311bdd1243dSDimitry Andric IFuncStubSectionID = Sections.size(); 2312bdd1243dSDimitry Andric Sections.push_back( 2313bdd1243dSDimitry Andric SectionEntry(".text.__llvm_IFuncStubs", nullptr, 0, 0, 0)); 2314bdd1243dSDimitry Andric // First 64B are reserverd for the IFunc resolver 2315bdd1243dSDimitry Andric IFuncStubOffset = 64; 2316bdd1243dSDimitry Andric } 2317bdd1243dSDimitry Andric 2318bdd1243dSDimitry Andric IFuncStubs.push_back(IFuncStub{IFuncStubOffset, Symbol}); 2319bdd1243dSDimitry Andric // Modify the symbol so that it points to the ifunc stub instead of to the 2320bdd1243dSDimitry Andric // resolver function. 2321bdd1243dSDimitry Andric Symbol = SymbolTableEntry(IFuncStubSectionID, IFuncStubOffset, 2322bdd1243dSDimitry Andric Symbol.getFlags()); 2323bdd1243dSDimitry Andric IFuncStubOffset += getMaxIFuncStubSize(); 2324bdd1243dSDimitry Andric } 2325bdd1243dSDimitry Andric } 2326bdd1243dSDimitry Andric 23270b57cec5SDimitry Andric Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, 23280b57cec5SDimitry Andric ObjSectionToIDMap &SectionMap) { 23290b57cec5SDimitry Andric if (IsMipsO32ABI) 23300b57cec5SDimitry Andric if (!PendingRelocs.empty()) 23310b57cec5SDimitry Andric return make_error<RuntimeDyldError>("Can't find matching LO16 reloc"); 23320b57cec5SDimitry Andric 2333bdd1243dSDimitry Andric // Create the IFunc stubs if necessary. This must be done before processing 2334bdd1243dSDimitry Andric // the GOT entries, as the IFunc stubs may create some. 2335bdd1243dSDimitry Andric if (IFuncStubSectionID != 0) { 2336bdd1243dSDimitry Andric uint8_t *IFuncStubsAddr = MemMgr.allocateCodeSection( 2337bdd1243dSDimitry Andric IFuncStubOffset, 1, IFuncStubSectionID, ".text.__llvm_IFuncStubs"); 2338bdd1243dSDimitry Andric if (!IFuncStubsAddr) 2339bdd1243dSDimitry Andric return make_error<RuntimeDyldError>( 2340bdd1243dSDimitry Andric "Unable to allocate memory for IFunc stubs!"); 2341bdd1243dSDimitry Andric Sections[IFuncStubSectionID] = 2342bdd1243dSDimitry Andric SectionEntry(".text.__llvm_IFuncStubs", IFuncStubsAddr, IFuncStubOffset, 2343bdd1243dSDimitry Andric IFuncStubOffset, 0); 2344bdd1243dSDimitry Andric 2345bdd1243dSDimitry Andric createIFuncResolver(IFuncStubsAddr); 2346bdd1243dSDimitry Andric 2347bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Creating IFunc stubs SectionID: " 2348bdd1243dSDimitry Andric << IFuncStubSectionID << " Addr: " 2349bdd1243dSDimitry Andric << Sections[IFuncStubSectionID].getAddress() << '\n'); 2350bdd1243dSDimitry Andric for (auto &IFuncStub : IFuncStubs) { 2351bdd1243dSDimitry Andric auto &Symbol = IFuncStub.OriginalSymbol; 2352bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "\tSectionID: " << Symbol.getSectionID() 2353bdd1243dSDimitry Andric << " Offset: " << format("%p", Symbol.getOffset()) 2354bdd1243dSDimitry Andric << " IFuncStubOffset: " 2355bdd1243dSDimitry Andric << format("%p\n", IFuncStub.StubOffset)); 2356bdd1243dSDimitry Andric createIFuncStub(IFuncStubSectionID, 0, IFuncStub.StubOffset, 2357bdd1243dSDimitry Andric Symbol.getSectionID(), Symbol.getOffset()); 2358bdd1243dSDimitry Andric } 2359bdd1243dSDimitry Andric 2360bdd1243dSDimitry Andric IFuncStubSectionID = 0; 2361bdd1243dSDimitry Andric IFuncStubOffset = 0; 2362bdd1243dSDimitry Andric IFuncStubs.clear(); 2363bdd1243dSDimitry Andric } 2364bdd1243dSDimitry Andric 23650b57cec5SDimitry Andric // If necessary, allocate the global offset table 23660b57cec5SDimitry Andric if (GOTSectionID != 0) { 23670b57cec5SDimitry Andric // Allocate memory for the section 23680b57cec5SDimitry Andric size_t TotalSize = CurrentGOTIndex * getGOTEntrySize(); 23690b57cec5SDimitry Andric uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(), 23700b57cec5SDimitry Andric GOTSectionID, ".got", false); 23710b57cec5SDimitry Andric if (!Addr) 23720b57cec5SDimitry Andric return make_error<RuntimeDyldError>("Unable to allocate memory for GOT!"); 23730b57cec5SDimitry Andric 23740b57cec5SDimitry Andric Sections[GOTSectionID] = 23750b57cec5SDimitry Andric SectionEntry(".got", Addr, TotalSize, TotalSize, 0); 23760b57cec5SDimitry Andric 23770b57cec5SDimitry Andric // For now, initialize all GOT entries to zero. We'll fill them in as 23780b57cec5SDimitry Andric // needed when GOT-based relocations are applied. 23790b57cec5SDimitry Andric memset(Addr, 0, TotalSize); 23800b57cec5SDimitry Andric if (IsMipsN32ABI || IsMipsN64ABI) { 23810b57cec5SDimitry Andric // To correctly resolve Mips GOT relocations, we need a mapping from 23820b57cec5SDimitry Andric // object's sections to GOTs. 23830b57cec5SDimitry Andric for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); 23840b57cec5SDimitry Andric SI != SE; ++SI) { 23850b57cec5SDimitry Andric if (SI->relocation_begin() != SI->relocation_end()) { 23868bcb0991SDimitry Andric Expected<section_iterator> RelSecOrErr = SI->getRelocatedSection(); 23878bcb0991SDimitry Andric if (!RelSecOrErr) 23888bcb0991SDimitry Andric return make_error<RuntimeDyldError>( 23898bcb0991SDimitry Andric toString(RelSecOrErr.takeError())); 23908bcb0991SDimitry Andric 23918bcb0991SDimitry Andric section_iterator RelocatedSection = *RelSecOrErr; 23920b57cec5SDimitry Andric ObjSectionToIDMap::iterator i = SectionMap.find(*RelocatedSection); 23930b57cec5SDimitry Andric assert(i != SectionMap.end()); 23940b57cec5SDimitry Andric SectionToGOTMap[i->second] = GOTSectionID; 23950b57cec5SDimitry Andric } 23960b57cec5SDimitry Andric } 23970b57cec5SDimitry Andric GOTSymbolOffsets.clear(); 23980b57cec5SDimitry Andric } 23990b57cec5SDimitry Andric } 24000b57cec5SDimitry Andric 24010b57cec5SDimitry Andric // Look for and record the EH frame section. 24020b57cec5SDimitry Andric ObjSectionToIDMap::iterator i, e; 24030b57cec5SDimitry Andric for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { 24040b57cec5SDimitry Andric const SectionRef &Section = i->first; 24058bcb0991SDimitry Andric 24060b57cec5SDimitry Andric StringRef Name; 24078bcb0991SDimitry Andric Expected<StringRef> NameOrErr = Section.getName(); 24088bcb0991SDimitry Andric if (NameOrErr) 24098bcb0991SDimitry Andric Name = *NameOrErr; 24108bcb0991SDimitry Andric else 24118bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 24128bcb0991SDimitry Andric 24130b57cec5SDimitry Andric if (Name == ".eh_frame") { 24140b57cec5SDimitry Andric UnregisteredEHFrameSections.push_back(i->second); 24150b57cec5SDimitry Andric break; 24160b57cec5SDimitry Andric } 24170b57cec5SDimitry Andric } 24180b57cec5SDimitry Andric 241906c3fb27SDimitry Andric GOTOffsetMap.clear(); 24200b57cec5SDimitry Andric GOTSectionID = 0; 24210b57cec5SDimitry Andric CurrentGOTIndex = 0; 24220b57cec5SDimitry Andric 24230b57cec5SDimitry Andric return Error::success(); 24240b57cec5SDimitry Andric } 24250b57cec5SDimitry Andric 24260b57cec5SDimitry Andric bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { 24270b57cec5SDimitry Andric return Obj.isELF(); 24280b57cec5SDimitry Andric } 24290b57cec5SDimitry Andric 2430bdd1243dSDimitry Andric void RuntimeDyldELF::createIFuncResolver(uint8_t *Addr) const { 2431bdd1243dSDimitry Andric if (Arch == Triple::x86_64) { 2432bdd1243dSDimitry Andric // The adddres of the GOT1 entry is in %r11, the GOT2 entry is in %r11+8 2433bdd1243dSDimitry Andric // (see createIFuncStub() for details) 2434bdd1243dSDimitry Andric // The following code first saves all registers that contain the original 2435bdd1243dSDimitry Andric // function arguments as those registers are not saved by the resolver 2436bdd1243dSDimitry Andric // function. %r11 is saved as well so that the GOT2 entry can be updated 2437bdd1243dSDimitry Andric // afterwards. Then it calls the actual IFunc resolver function whose 2438bdd1243dSDimitry Andric // address is stored in GOT2. After the resolver function returns, all 2439bdd1243dSDimitry Andric // saved registers are restored and the return value is written to GOT1. 2440bdd1243dSDimitry Andric // Finally, jump to the now resolved function. 2441bdd1243dSDimitry Andric // clang-format off 2442bdd1243dSDimitry Andric const uint8_t StubCode[] = { 2443bdd1243dSDimitry Andric 0x57, // push %rdi 2444bdd1243dSDimitry Andric 0x56, // push %rsi 2445bdd1243dSDimitry Andric 0x52, // push %rdx 2446bdd1243dSDimitry Andric 0x51, // push %rcx 2447bdd1243dSDimitry Andric 0x41, 0x50, // push %r8 2448bdd1243dSDimitry Andric 0x41, 0x51, // push %r9 2449bdd1243dSDimitry Andric 0x41, 0x53, // push %r11 2450bdd1243dSDimitry Andric 0x41, 0xff, 0x53, 0x08, // call *0x8(%r11) 2451bdd1243dSDimitry Andric 0x41, 0x5b, // pop %r11 2452bdd1243dSDimitry Andric 0x41, 0x59, // pop %r9 2453bdd1243dSDimitry Andric 0x41, 0x58, // pop %r8 2454bdd1243dSDimitry Andric 0x59, // pop %rcx 2455bdd1243dSDimitry Andric 0x5a, // pop %rdx 2456bdd1243dSDimitry Andric 0x5e, // pop %rsi 2457bdd1243dSDimitry Andric 0x5f, // pop %rdi 2458bdd1243dSDimitry Andric 0x49, 0x89, 0x03, // mov %rax,(%r11) 2459bdd1243dSDimitry Andric 0xff, 0xe0 // jmp *%rax 2460bdd1243dSDimitry Andric }; 2461bdd1243dSDimitry Andric // clang-format on 2462bdd1243dSDimitry Andric static_assert(sizeof(StubCode) <= 64, 2463bdd1243dSDimitry Andric "maximum size of the IFunc resolver is 64B"); 2464bdd1243dSDimitry Andric memcpy(Addr, StubCode, sizeof(StubCode)); 2465bdd1243dSDimitry Andric } else { 2466bdd1243dSDimitry Andric report_fatal_error( 2467bdd1243dSDimitry Andric "IFunc resolver is not supported for target architecture"); 2468bdd1243dSDimitry Andric } 2469bdd1243dSDimitry Andric } 2470bdd1243dSDimitry Andric 2471bdd1243dSDimitry Andric void RuntimeDyldELF::createIFuncStub(unsigned IFuncStubSectionID, 2472bdd1243dSDimitry Andric uint64_t IFuncResolverOffset, 2473bdd1243dSDimitry Andric uint64_t IFuncStubOffset, 2474bdd1243dSDimitry Andric unsigned IFuncSectionID, 2475bdd1243dSDimitry Andric uint64_t IFuncOffset) { 2476bdd1243dSDimitry Andric auto &IFuncStubSection = Sections[IFuncStubSectionID]; 2477bdd1243dSDimitry Andric auto *Addr = IFuncStubSection.getAddressWithOffset(IFuncStubOffset); 2478bdd1243dSDimitry Andric 2479bdd1243dSDimitry Andric if (Arch == Triple::x86_64) { 2480bdd1243dSDimitry Andric // The first instruction loads a PC-relative address into %r11 which is a 2481bdd1243dSDimitry Andric // GOT entry for this stub. This initially contains the address to the 2482bdd1243dSDimitry Andric // IFunc resolver. We can use %r11 here as it's caller saved but not used 2483bdd1243dSDimitry Andric // to pass any arguments. In fact, x86_64 ABI even suggests using %r11 for 2484bdd1243dSDimitry Andric // code in the PLT. The IFunc resolver will use %r11 to update the GOT 2485bdd1243dSDimitry Andric // entry. 2486bdd1243dSDimitry Andric // 2487bdd1243dSDimitry Andric // The next instruction just jumps to the address contained in the GOT 2488bdd1243dSDimitry Andric // entry. As mentioned above, we do this two-step jump by first setting 2489bdd1243dSDimitry Andric // %r11 so that the IFunc resolver has access to it. 2490bdd1243dSDimitry Andric // 2491bdd1243dSDimitry Andric // The IFunc resolver of course also needs to know the actual address of 2492bdd1243dSDimitry Andric // the actual IFunc resolver function. This will be stored in a GOT entry 2493bdd1243dSDimitry Andric // right next to the first one for this stub. So, the IFunc resolver will 2494bdd1243dSDimitry Andric // be able to call it with %r11+8. 2495bdd1243dSDimitry Andric // 2496bdd1243dSDimitry Andric // In total, two adjacent GOT entries (+relocation) and one additional 2497bdd1243dSDimitry Andric // relocation are required: 2498bdd1243dSDimitry Andric // GOT1: Address of the IFunc resolver. 2499bdd1243dSDimitry Andric // GOT2: Address of the IFunc resolver function. 2500bdd1243dSDimitry Andric // IFuncStubOffset+3: 32-bit PC-relative address of GOT1. 2501bdd1243dSDimitry Andric uint64_t GOT1 = allocateGOTEntries(2); 2502bdd1243dSDimitry Andric uint64_t GOT2 = GOT1 + getGOTEntrySize(); 2503bdd1243dSDimitry Andric 2504bdd1243dSDimitry Andric RelocationEntry RE1(GOTSectionID, GOT1, ELF::R_X86_64_64, 2505bdd1243dSDimitry Andric IFuncResolverOffset, {}); 2506bdd1243dSDimitry Andric addRelocationForSection(RE1, IFuncStubSectionID); 2507bdd1243dSDimitry Andric RelocationEntry RE2(GOTSectionID, GOT2, ELF::R_X86_64_64, IFuncOffset, {}); 2508bdd1243dSDimitry Andric addRelocationForSection(RE2, IFuncSectionID); 2509bdd1243dSDimitry Andric 2510bdd1243dSDimitry Andric const uint8_t StubCode[] = { 2511bdd1243dSDimitry Andric 0x4c, 0x8d, 0x1d, 0x00, 0x00, 0x00, 0x00, // leaq 0x0(%rip),%r11 2512bdd1243dSDimitry Andric 0x41, 0xff, 0x23 // jmpq *(%r11) 2513bdd1243dSDimitry Andric }; 2514bdd1243dSDimitry Andric assert(sizeof(StubCode) <= getMaxIFuncStubSize() && 2515bdd1243dSDimitry Andric "IFunc stub size must not exceed getMaxIFuncStubSize()"); 2516bdd1243dSDimitry Andric memcpy(Addr, StubCode, sizeof(StubCode)); 2517bdd1243dSDimitry Andric 2518bdd1243dSDimitry Andric // The PC-relative value starts 4 bytes from the end of the leaq 2519bdd1243dSDimitry Andric // instruction, so the addend is -4. 2520bdd1243dSDimitry Andric resolveGOTOffsetRelocation(IFuncStubSectionID, IFuncStubOffset + 3, 2521bdd1243dSDimitry Andric GOT1 - 4, ELF::R_X86_64_PC32); 2522bdd1243dSDimitry Andric } else { 2523bdd1243dSDimitry Andric report_fatal_error("IFunc stub is not supported for target architecture"); 2524bdd1243dSDimitry Andric } 2525bdd1243dSDimitry Andric } 2526bdd1243dSDimitry Andric 2527bdd1243dSDimitry Andric unsigned RuntimeDyldELF::getMaxIFuncStubSize() const { 2528bdd1243dSDimitry Andric if (Arch == Triple::x86_64) { 2529bdd1243dSDimitry Andric return 10; 2530bdd1243dSDimitry Andric } 2531bdd1243dSDimitry Andric return 0; 2532bdd1243dSDimitry Andric } 2533bdd1243dSDimitry Andric 25340b57cec5SDimitry Andric bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const { 25350b57cec5SDimitry Andric unsigned RelTy = R.getType(); 25360b57cec5SDimitry Andric if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) 25370b57cec5SDimitry Andric return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE || 25380b57cec5SDimitry Andric RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC; 25390b57cec5SDimitry Andric 25400b57cec5SDimitry Andric if (Arch == Triple::x86_64) 25410b57cec5SDimitry Andric return RelTy == ELF::R_X86_64_GOTPCREL || 25420b57cec5SDimitry Andric RelTy == ELF::R_X86_64_GOTPCRELX || 25430b57cec5SDimitry Andric RelTy == ELF::R_X86_64_GOT64 || 25440b57cec5SDimitry Andric RelTy == ELF::R_X86_64_REX_GOTPCRELX; 25450b57cec5SDimitry Andric return false; 25460b57cec5SDimitry Andric } 25470b57cec5SDimitry Andric 25480b57cec5SDimitry Andric bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const { 25490b57cec5SDimitry Andric if (Arch != Triple::x86_64) 25500b57cec5SDimitry Andric return true; // Conservative answer 25510b57cec5SDimitry Andric 25520b57cec5SDimitry Andric switch (R.getType()) { 25530b57cec5SDimitry Andric default: 25540b57cec5SDimitry Andric return true; // Conservative answer 25550b57cec5SDimitry Andric 25560b57cec5SDimitry Andric 25570b57cec5SDimitry Andric case ELF::R_X86_64_GOTPCREL: 25580b57cec5SDimitry Andric case ELF::R_X86_64_GOTPCRELX: 25590b57cec5SDimitry Andric case ELF::R_X86_64_REX_GOTPCRELX: 25600b57cec5SDimitry Andric case ELF::R_X86_64_GOTPC64: 25610b57cec5SDimitry Andric case ELF::R_X86_64_GOT64: 25620b57cec5SDimitry Andric case ELF::R_X86_64_GOTOFF64: 25630b57cec5SDimitry Andric case ELF::R_X86_64_PC32: 25640b57cec5SDimitry Andric case ELF::R_X86_64_PC64: 25650b57cec5SDimitry Andric case ELF::R_X86_64_64: 25660b57cec5SDimitry Andric // We know that these reloation types won't need a stub function. This list 25670b57cec5SDimitry Andric // can be extended as needed. 25680b57cec5SDimitry Andric return false; 25690b57cec5SDimitry Andric } 25700b57cec5SDimitry Andric } 25710b57cec5SDimitry Andric 25720b57cec5SDimitry Andric } // namespace llvm 2573