Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
35269 views
//===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Implementation of ELF support for the MC-JIT runtime dynamic linker.9//10//===----------------------------------------------------------------------===//1112#include "RuntimeDyldELF.h"13#include "RuntimeDyldCheckerImpl.h"14#include "Targets/RuntimeDyldELFMips.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/BinaryFormat/ELF.h"18#include "llvm/Object/ELFObjectFile.h"19#include "llvm/Object/ObjectFile.h"20#include "llvm/Support/Endian.h"21#include "llvm/Support/MemoryBuffer.h"22#include "llvm/TargetParser/Triple.h"2324using namespace llvm;25using namespace llvm::object;26using namespace llvm::support::endian;2728#define DEBUG_TYPE "dyld"2930static void or32le(void *P, int32_t V) { write32le(P, read32le(P) | V); }3132static void or32AArch64Imm(void *L, uint64_t Imm) {33or32le(L, (Imm & 0xFFF) << 10);34}3536template <class T> static void write(bool isBE, void *P, T V) {37isBE ? write<T, llvm::endianness::big>(P, V)38: write<T, llvm::endianness::little>(P, V);39}4041static void write32AArch64Addr(void *L, uint64_t Imm) {42uint32_t ImmLo = (Imm & 0x3) << 29;43uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;44uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);45write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);46}4748// Return the bits [Start, End] from Val shifted Start bits.49// For instance, getBits(0xF0, 4, 8) returns 0xF.50static uint64_t getBits(uint64_t Val, int Start, int End) {51uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1;52return (Val >> Start) & Mask;53}5455namespace {5657template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {58LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)5960typedef typename ELFT::uint addr_type;6162DyldELFObject(ELFObjectFile<ELFT> &&Obj);6364public:65static Expected<std::unique_ptr<DyldELFObject>>66create(MemoryBufferRef Wrapper);6768void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);6970void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr);7172// Methods for type inquiry through isa, cast and dyn_cast73static bool classof(const Binary *v) {74return (isa<ELFObjectFile<ELFT>>(v) &&75classof(cast<ELFObjectFile<ELFT>>(v)));76}77static bool classof(const ELFObjectFile<ELFT> *v) {78return v->isDyldType();79}80};81828384// The MemoryBuffer passed into this constructor is just a wrapper around the85// actual memory. Ultimately, the Binary parent class will take ownership of86// this MemoryBuffer object but not the underlying memory.87template <class ELFT>88DyldELFObject<ELFT>::DyldELFObject(ELFObjectFile<ELFT> &&Obj)89: ELFObjectFile<ELFT>(std::move(Obj)) {90this->isDyldELFObject = true;91}9293template <class ELFT>94Expected<std::unique_ptr<DyldELFObject<ELFT>>>95DyldELFObject<ELFT>::create(MemoryBufferRef Wrapper) {96auto Obj = ELFObjectFile<ELFT>::create(Wrapper);97if (auto E = Obj.takeError())98return std::move(E);99std::unique_ptr<DyldELFObject<ELFT>> Ret(100new DyldELFObject<ELFT>(std::move(*Obj)));101return std::move(Ret);102}103104template <class ELFT>105void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,106uint64_t Addr) {107DataRefImpl ShdrRef = Sec.getRawDataRefImpl();108Elf_Shdr *shdr =109const_cast<Elf_Shdr *>(reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));110111// This assumes the address passed in matches the target address bitness112// The template-based type cast handles everything else.113shdr->sh_addr = static_cast<addr_type>(Addr);114}115116template <class ELFT>117void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,118uint64_t Addr) {119120Elf_Sym *sym = const_cast<Elf_Sym *>(121ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl()));122123// This assumes the address passed in matches the target address bitness124// The template-based type cast handles everything else.125sym->st_value = static_cast<addr_type>(Addr);126}127128class LoadedELFObjectInfo final129: public LoadedObjectInfoHelper<LoadedELFObjectInfo,130RuntimeDyld::LoadedObjectInfo> {131public:132LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap)133: LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}134135OwningBinary<ObjectFile>136getObjectForDebug(const ObjectFile &Obj) const override;137};138139template <typename ELFT>140static Expected<std::unique_ptr<DyldELFObject<ELFT>>>141createRTDyldELFObject(MemoryBufferRef Buffer, const ObjectFile &SourceObject,142const LoadedELFObjectInfo &L) {143typedef typename ELFT::Shdr Elf_Shdr;144typedef typename ELFT::uint addr_type;145146Expected<std::unique_ptr<DyldELFObject<ELFT>>> ObjOrErr =147DyldELFObject<ELFT>::create(Buffer);148if (Error E = ObjOrErr.takeError())149return std::move(E);150151std::unique_ptr<DyldELFObject<ELFT>> Obj = std::move(*ObjOrErr);152153// Iterate over all sections in the object.154auto SI = SourceObject.section_begin();155for (const auto &Sec : Obj->sections()) {156Expected<StringRef> NameOrErr = Sec.getName();157if (!NameOrErr) {158consumeError(NameOrErr.takeError());159continue;160}161162if (*NameOrErr != "") {163DataRefImpl ShdrRef = Sec.getRawDataRefImpl();164Elf_Shdr *shdr = const_cast<Elf_Shdr *>(165reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));166167if (uint64_t SecLoadAddr = L.getSectionLoadAddress(*SI)) {168// This assumes that the address passed in matches the target address169// bitness. The template-based type cast handles everything else.170shdr->sh_addr = static_cast<addr_type>(SecLoadAddr);171}172}173++SI;174}175176return std::move(Obj);177}178179static OwningBinary<ObjectFile>180createELFDebugObject(const ObjectFile &Obj, const LoadedELFObjectInfo &L) {181assert(Obj.isELF() && "Not an ELF object file.");182183std::unique_ptr<MemoryBuffer> Buffer =184MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName());185186Expected<std::unique_ptr<ObjectFile>> DebugObj(nullptr);187handleAllErrors(DebugObj.takeError());188if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian())189DebugObj =190createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), Obj, L);191else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian())192DebugObj =193createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), Obj, L);194else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian())195DebugObj =196createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), Obj, L);197else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian())198DebugObj =199createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), Obj, L);200else201llvm_unreachable("Unexpected ELF format");202203handleAllErrors(DebugObj.takeError());204return OwningBinary<ObjectFile>(std::move(*DebugObj), std::move(Buffer));205}206207OwningBinary<ObjectFile>208LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const {209return createELFDebugObject(Obj, *this);210}211212} // anonymous namespace213214namespace llvm {215216RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr,217JITSymbolResolver &Resolver)218: RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0), CurrentGOTIndex(0) {}219RuntimeDyldELF::~RuntimeDyldELF() = default;220221void RuntimeDyldELF::registerEHFrames() {222for (SID EHFrameSID : UnregisteredEHFrameSections) {223uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();224uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();225size_t EHFrameSize = Sections[EHFrameSID].getSize();226MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);227}228UnregisteredEHFrameSections.clear();229}230231std::unique_ptr<RuntimeDyldELF>232llvm::RuntimeDyldELF::create(Triple::ArchType Arch,233RuntimeDyld::MemoryManager &MemMgr,234JITSymbolResolver &Resolver) {235switch (Arch) {236default:237return std::make_unique<RuntimeDyldELF>(MemMgr, Resolver);238case Triple::mips:239case Triple::mipsel:240case Triple::mips64:241case Triple::mips64el:242return std::make_unique<RuntimeDyldELFMips>(MemMgr, Resolver);243}244}245246std::unique_ptr<RuntimeDyld::LoadedObjectInfo>247RuntimeDyldELF::loadObject(const object::ObjectFile &O) {248if (auto ObjSectionToIDOrErr = loadObjectImpl(O))249return std::make_unique<LoadedELFObjectInfo>(*this, *ObjSectionToIDOrErr);250else {251HasError = true;252raw_string_ostream ErrStream(ErrorStr);253logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream);254return nullptr;255}256}257258void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,259uint64_t Offset, uint64_t Value,260uint32_t Type, int64_t Addend,261uint64_t SymOffset) {262switch (Type) {263default:264report_fatal_error("Relocation type not implemented yet!");265break;266case ELF::R_X86_64_NONE:267break;268case ELF::R_X86_64_8: {269Value += Addend;270assert((int64_t)Value <= INT8_MAX && (int64_t)Value >= INT8_MIN);271uint8_t TruncatedAddr = (Value & 0xFF);272*Section.getAddressWithOffset(Offset) = TruncatedAddr;273LLVM_DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at "274<< format("%p\n", Section.getAddressWithOffset(Offset)));275break;276}277case ELF::R_X86_64_16: {278Value += Addend;279assert((int64_t)Value <= INT16_MAX && (int64_t)Value >= INT16_MIN);280uint16_t TruncatedAddr = (Value & 0xFFFF);281support::ulittle16_t::ref(Section.getAddressWithOffset(Offset)) =282TruncatedAddr;283LLVM_DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at "284<< format("%p\n", Section.getAddressWithOffset(Offset)));285break;286}287case ELF::R_X86_64_64: {288support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) =289Value + Addend;290LLVM_DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at "291<< format("%p\n", Section.getAddressWithOffset(Offset)));292break;293}294case ELF::R_X86_64_32:295case ELF::R_X86_64_32S: {296Value += Addend;297assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) ||298(Type == ELF::R_X86_64_32S &&299((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN)));300uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);301support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =302TruncatedAddr;303LLVM_DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at "304<< format("%p\n", Section.getAddressWithOffset(Offset)));305break;306}307case ELF::R_X86_64_PC8: {308uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);309int64_t RealOffset = Value + Addend - FinalAddress;310assert(isInt<8>(RealOffset));311int8_t TruncOffset = (RealOffset & 0xFF);312Section.getAddress()[Offset] = TruncOffset;313break;314}315case ELF::R_X86_64_PC32: {316uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);317int64_t RealOffset = Value + Addend - FinalAddress;318assert(isInt<32>(RealOffset));319int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);320support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =321TruncOffset;322break;323}324case ELF::R_X86_64_PC64: {325uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);326int64_t RealOffset = Value + Addend - FinalAddress;327support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) =328RealOffset;329LLVM_DEBUG(dbgs() << "Writing " << format("%p", RealOffset) << " at "330<< format("%p\n", FinalAddress));331break;332}333case ELF::R_X86_64_GOTOFF64: {334// Compute Value - GOTBase.335uint64_t GOTBase = 0;336for (const auto &Section : Sections) {337if (Section.getName() == ".got") {338GOTBase = Section.getLoadAddressWithOffset(0);339break;340}341}342assert(GOTBase != 0 && "missing GOT");343int64_t GOTOffset = Value - GOTBase + Addend;344support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = GOTOffset;345break;346}347case ELF::R_X86_64_DTPMOD64: {348// We only have one DSO, so the module id is always 1.349support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = 1;350break;351}352case ELF::R_X86_64_DTPOFF64:353case ELF::R_X86_64_TPOFF64: {354// DTPOFF64 should resolve to the offset in the TLS block, TPOFF64 to the355// offset in the *initial* TLS block. Since we are statically linking, all356// TLS blocks already exist in the initial block, so resolve both357// relocations equally.358support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) =359Value + Addend;360break;361}362case ELF::R_X86_64_DTPOFF32:363case ELF::R_X86_64_TPOFF32: {364// As for the (D)TPOFF64 relocations above, both DTPOFF32 and TPOFF32 can365// be resolved equally.366int64_t RealValue = Value + Addend;367assert(RealValue >= INT32_MIN && RealValue <= INT32_MAX);368int32_t TruncValue = RealValue;369support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =370TruncValue;371break;372}373}374}375376void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,377uint64_t Offset, uint32_t Value,378uint32_t Type, int32_t Addend) {379switch (Type) {380case ELF::R_386_32: {381support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =382Value + Addend;383break;384}385// Handle R_386_PLT32 like R_386_PC32 since it should be able to386// reach any 32 bit address.387case ELF::R_386_PLT32:388case ELF::R_386_PC32: {389uint32_t FinalAddress =390Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF;391uint32_t RealOffset = Value + Addend - FinalAddress;392support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =393RealOffset;394break;395}396default:397// There are other relocation types, but it appears these are the398// only ones currently used by the LLVM ELF object writer399report_fatal_error("Relocation type not implemented yet!");400break;401}402}403404void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,405uint64_t Offset, uint64_t Value,406uint32_t Type, int64_t Addend) {407uint32_t *TargetPtr =408reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset));409uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);410// Data should use target endian. Code should always use little endian.411bool isBE = Arch == Triple::aarch64_be;412413LLVM_DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x"414<< format("%llx", Section.getAddressWithOffset(Offset))415<< " FinalAddress: 0x" << format("%llx", FinalAddress)416<< " Value: 0x" << format("%llx", Value) << " Type: 0x"417<< format("%x", Type) << " Addend: 0x"418<< format("%llx", Addend) << "\n");419420switch (Type) {421default:422report_fatal_error("Relocation type not implemented yet!");423break;424case ELF::R_AARCH64_NONE:425break;426case ELF::R_AARCH64_ABS16: {427uint64_t Result = Value + Addend;428assert(Result == static_cast<uint64_t>(llvm::SignExtend64(Result, 16)) ||429(Result >> 16) == 0);430write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU));431break;432}433case ELF::R_AARCH64_ABS32: {434uint64_t Result = Value + Addend;435assert(Result == static_cast<uint64_t>(llvm::SignExtend64(Result, 32)) ||436(Result >> 32) == 0);437write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU));438break;439}440case ELF::R_AARCH64_ABS64:441write(isBE, TargetPtr, Value + Addend);442break;443case ELF::R_AARCH64_PLT32: {444uint64_t Result = Value + Addend - FinalAddress;445assert(static_cast<int64_t>(Result) >= INT32_MIN &&446static_cast<int64_t>(Result) <= INT32_MAX);447write(isBE, TargetPtr, static_cast<uint32_t>(Result));448break;449}450case ELF::R_AARCH64_PREL16: {451uint64_t Result = Value + Addend - FinalAddress;452assert(static_cast<int64_t>(Result) >= INT16_MIN &&453static_cast<int64_t>(Result) <= UINT16_MAX);454write(isBE, TargetPtr, static_cast<uint16_t>(Result & 0xffffU));455break;456}457case ELF::R_AARCH64_PREL32: {458uint64_t Result = Value + Addend - FinalAddress;459assert(static_cast<int64_t>(Result) >= INT32_MIN &&460static_cast<int64_t>(Result) <= UINT32_MAX);461write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU));462break;463}464case ELF::R_AARCH64_PREL64:465write(isBE, TargetPtr, Value + Addend - FinalAddress);466break;467case ELF::R_AARCH64_CONDBR19: {468uint64_t BranchImm = Value + Addend - FinalAddress;469470assert(isInt<21>(BranchImm));471*TargetPtr &= 0xff00001fU;472// Immediate:20:2 goes in bits 23:5 of Bcc, CBZ, CBNZ473or32le(TargetPtr, (BranchImm & 0x001FFFFC) << 3);474break;475}476case ELF::R_AARCH64_TSTBR14: {477uint64_t BranchImm = Value + Addend - FinalAddress;478479assert(isInt<16>(BranchImm));480481uint32_t RawInstr = *(support::little32_t *)TargetPtr;482*(support::little32_t *)TargetPtr = RawInstr & 0xfff8001fU;483484// Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ485or32le(TargetPtr, (BranchImm & 0x0000FFFC) << 3);486break;487}488case ELF::R_AARCH64_CALL26: // fallthrough489case ELF::R_AARCH64_JUMP26: {490// Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the491// calculation.492uint64_t BranchImm = Value + Addend - FinalAddress;493494// "Check that -2^27 <= result < 2^27".495assert(isInt<28>(BranchImm));496or32le(TargetPtr, (BranchImm & 0x0FFFFFFC) >> 2);497break;498}499case ELF::R_AARCH64_MOVW_UABS_G3:500or32le(TargetPtr, ((Value + Addend) & 0xFFFF000000000000) >> 43);501break;502case ELF::R_AARCH64_MOVW_UABS_G2_NC:503or32le(TargetPtr, ((Value + Addend) & 0xFFFF00000000) >> 27);504break;505case ELF::R_AARCH64_MOVW_UABS_G1_NC:506or32le(TargetPtr, ((Value + Addend) & 0xFFFF0000) >> 11);507break;508case ELF::R_AARCH64_MOVW_UABS_G0_NC:509or32le(TargetPtr, ((Value + Addend) & 0xFFFF) << 5);510break;511case ELF::R_AARCH64_ADR_PREL_PG_HI21: {512// Operation: Page(S+A) - Page(P)513uint64_t Result =514((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL);515516// Check that -2^32 <= X < 2^32517assert(isInt<33>(Result) && "overflow check failed for relocation");518519// Immediate goes in bits 30:29 + 5:23 of ADRP instruction, taken520// from bits 32:12 of X.521write32AArch64Addr(TargetPtr, Result >> 12);522break;523}524case ELF::R_AARCH64_ADD_ABS_LO12_NC:525// Operation: S + A526// Immediate goes in bits 21:10 of LD/ST instruction, taken527// from bits 11:0 of X528or32AArch64Imm(TargetPtr, Value + Addend);529break;530case ELF::R_AARCH64_LDST8_ABS_LO12_NC:531// Operation: S + A532// Immediate goes in bits 21:10 of LD/ST instruction, taken533// from bits 11:0 of X534or32AArch64Imm(TargetPtr, getBits(Value + Addend, 0, 11));535break;536case ELF::R_AARCH64_LDST16_ABS_LO12_NC:537// Operation: S + A538// Immediate goes in bits 21:10 of LD/ST instruction, taken539// from bits 11:1 of X540or32AArch64Imm(TargetPtr, getBits(Value + Addend, 1, 11));541break;542case ELF::R_AARCH64_LDST32_ABS_LO12_NC:543// Operation: S + A544// Immediate goes in bits 21:10 of LD/ST instruction, taken545// from bits 11:2 of X546or32AArch64Imm(TargetPtr, getBits(Value + Addend, 2, 11));547break;548case ELF::R_AARCH64_LDST64_ABS_LO12_NC:549// Operation: S + A550// Immediate goes in bits 21:10 of LD/ST instruction, taken551// from bits 11:3 of X552or32AArch64Imm(TargetPtr, getBits(Value + Addend, 3, 11));553break;554case ELF::R_AARCH64_LDST128_ABS_LO12_NC:555// Operation: S + A556// Immediate goes in bits 21:10 of LD/ST instruction, taken557// from bits 11:4 of X558or32AArch64Imm(TargetPtr, getBits(Value + Addend, 4, 11));559break;560case ELF::R_AARCH64_LD_PREL_LO19: {561// Operation: S + A - P562uint64_t Result = Value + Addend - FinalAddress;563564// "Check that -2^20 <= result < 2^20".565assert(isInt<21>(Result));566567*TargetPtr &= 0xff00001fU;568// Immediate goes in bits 23:5 of LD imm instruction, taken569// from bits 20:2 of X570*TargetPtr |= ((Result & 0xffc) << (5 - 2));571break;572}573case ELF::R_AARCH64_ADR_PREL_LO21: {574// Operation: S + A - P575uint64_t Result = Value + Addend - FinalAddress;576577// "Check that -2^20 <= result < 2^20".578assert(isInt<21>(Result));579580*TargetPtr &= 0x9f00001fU;581// Immediate goes in bits 23:5, 30:29 of ADR imm instruction, taken582// from bits 20:0 of X583*TargetPtr |= ((Result & 0xffc) << (5 - 2));584*TargetPtr |= (Result & 0x3) << 29;585break;586}587}588}589590void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,591uint64_t Offset, uint32_t Value,592uint32_t Type, int32_t Addend) {593// TODO: Add Thumb relocations.594uint32_t *TargetPtr =595reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset));596uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF;597Value += Addend;598599LLVM_DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: "600<< Section.getAddressWithOffset(Offset)601<< " FinalAddress: " << format("%p", FinalAddress)602<< " Value: " << format("%x", Value)603<< " Type: " << format("%x", Type)604<< " Addend: " << format("%x", Addend) << "\n");605606switch (Type) {607default:608llvm_unreachable("Not implemented relocation type!");609610case ELF::R_ARM_NONE:611break;612// Write a 31bit signed offset613case ELF::R_ARM_PREL31:614support::ulittle32_t::ref{TargetPtr} =615(support::ulittle32_t::ref{TargetPtr} & 0x80000000) |616((Value - FinalAddress) & ~0x80000000);617break;618case ELF::R_ARM_TARGET1:619case ELF::R_ARM_ABS32:620support::ulittle32_t::ref{TargetPtr} = Value;621break;622// Write first 16 bit of 32 bit value to the mov instruction.623// Last 4 bit should be shifted.624case ELF::R_ARM_MOVW_ABS_NC:625case ELF::R_ARM_MOVT_ABS:626if (Type == ELF::R_ARM_MOVW_ABS_NC)627Value = Value & 0xFFFF;628else if (Type == ELF::R_ARM_MOVT_ABS)629Value = (Value >> 16) & 0xFFFF;630support::ulittle32_t::ref{TargetPtr} =631(support::ulittle32_t::ref{TargetPtr} & ~0x000F0FFF) | (Value & 0xFFF) |632(((Value >> 12) & 0xF) << 16);633break;634// Write 24 bit relative value to the branch instruction.635case ELF::R_ARM_PC24: // Fall through.636case ELF::R_ARM_CALL: // Fall through.637case ELF::R_ARM_JUMP24:638int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);639RelValue = (RelValue & 0x03FFFFFC) >> 2;640assert((support::ulittle32_t::ref{TargetPtr} & 0xFFFFFF) == 0xFFFFFE);641support::ulittle32_t::ref{TargetPtr} =642(support::ulittle32_t::ref{TargetPtr} & 0xFF000000) | RelValue;643break;644}645}646647void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) {648if (Arch == Triple::UnknownArch ||649Triple::getArchTypePrefix(Arch) != "mips") {650IsMipsO32ABI = false;651IsMipsN32ABI = false;652IsMipsN64ABI = false;653return;654}655if (auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) {656unsigned AbiVariant = E->getPlatformFlags();657IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32;658IsMipsN32ABI = AbiVariant & ELF::EF_MIPS_ABI2;659}660IsMipsN64ABI = Obj.getFileFormatName() == "elf64-mips";661}662663// Return the .TOC. section and offset.664Error RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,665ObjSectionToIDMap &LocalSections,666RelocationValueRef &Rel) {667// Set a default SectionID in case we do not find a TOC section below.668// This may happen for references to TOC base base (sym@toc, .odp669// relocation) without a .toc directive. In this case just use the670// first section (which is usually the .odp) since the code won't671// reference the .toc base directly.672Rel.SymbolName = nullptr;673Rel.SectionID = 0;674675// The TOC consists of sections .got, .toc, .tocbss, .plt in that676// order. The TOC starts where the first of these sections starts.677for (auto &Section : Obj.sections()) {678Expected<StringRef> NameOrErr = Section.getName();679if (!NameOrErr)680return NameOrErr.takeError();681StringRef SectionName = *NameOrErr;682683if (SectionName == ".got"684|| SectionName == ".toc"685|| SectionName == ".tocbss"686|| SectionName == ".plt") {687if (auto SectionIDOrErr =688findOrEmitSection(Obj, Section, false, LocalSections))689Rel.SectionID = *SectionIDOrErr;690else691return SectionIDOrErr.takeError();692break;693}694}695696// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000697// thus permitting a full 64 Kbytes segment.698Rel.Addend = 0x8000;699700return Error::success();701}702703// Returns the sections and offset associated with the ODP entry referenced704// by Symbol.705Error RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,706ObjSectionToIDMap &LocalSections,707RelocationValueRef &Rel) {708// Get the ELF symbol value (st_value) to compare with Relocation offset in709// .opd entries710for (section_iterator si = Obj.section_begin(), se = Obj.section_end();711si != se; ++si) {712713Expected<section_iterator> RelSecOrErr = si->getRelocatedSection();714if (!RelSecOrErr)715report_fatal_error(Twine(toString(RelSecOrErr.takeError())));716717section_iterator RelSecI = *RelSecOrErr;718if (RelSecI == Obj.section_end())719continue;720721Expected<StringRef> NameOrErr = RelSecI->getName();722if (!NameOrErr)723return NameOrErr.takeError();724StringRef RelSectionName = *NameOrErr;725726if (RelSectionName != ".opd")727continue;728729for (elf_relocation_iterator i = si->relocation_begin(),730e = si->relocation_end();731i != e;) {732// The R_PPC64_ADDR64 relocation indicates the first field733// of a .opd entry734uint64_t TypeFunc = i->getType();735if (TypeFunc != ELF::R_PPC64_ADDR64) {736++i;737continue;738}739740uint64_t TargetSymbolOffset = i->getOffset();741symbol_iterator TargetSymbol = i->getSymbol();742int64_t Addend;743if (auto AddendOrErr = i->getAddend())744Addend = *AddendOrErr;745else746return AddendOrErr.takeError();747748++i;749if (i == e)750break;751752// Just check if following relocation is a R_PPC64_TOC753uint64_t TypeTOC = i->getType();754if (TypeTOC != ELF::R_PPC64_TOC)755continue;756757// Finally compares the Symbol value and the target symbol offset758// to check if this .opd entry refers to the symbol the relocation759// points to.760if (Rel.Addend != (int64_t)TargetSymbolOffset)761continue;762763section_iterator TSI = Obj.section_end();764if (auto TSIOrErr = TargetSymbol->getSection())765TSI = *TSIOrErr;766else767return TSIOrErr.takeError();768assert(TSI != Obj.section_end() && "TSI should refer to a valid section");769770bool IsCode = TSI->isText();771if (auto SectionIDOrErr = findOrEmitSection(Obj, *TSI, IsCode,772LocalSections))773Rel.SectionID = *SectionIDOrErr;774else775return SectionIDOrErr.takeError();776Rel.Addend = (intptr_t)Addend;777return Error::success();778}779}780llvm_unreachable("Attempting to get address of ODP entry!");781}782783// Relocation masks following the #lo(value), #hi(value), #ha(value),784// #higher(value), #highera(value), #highest(value), and #highesta(value)785// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi786// document.787788static inline uint16_t applyPPClo(uint64_t value) { return value & 0xffff; }789790static inline uint16_t applyPPChi(uint64_t value) {791return (value >> 16) & 0xffff;792}793794static inline uint16_t applyPPCha (uint64_t value) {795return ((value + 0x8000) >> 16) & 0xffff;796}797798static inline uint16_t applyPPChigher(uint64_t value) {799return (value >> 32) & 0xffff;800}801802static inline uint16_t applyPPChighera (uint64_t value) {803return ((value + 0x8000) >> 32) & 0xffff;804}805806static inline uint16_t applyPPChighest(uint64_t value) {807return (value >> 48) & 0xffff;808}809810static inline uint16_t applyPPChighesta (uint64_t value) {811return ((value + 0x8000) >> 48) & 0xffff;812}813814void RuntimeDyldELF::resolvePPC32Relocation(const SectionEntry &Section,815uint64_t Offset, uint64_t Value,816uint32_t Type, int64_t Addend) {817uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);818switch (Type) {819default:820report_fatal_error("Relocation type not implemented yet!");821break;822case ELF::R_PPC_ADDR16_LO:823writeInt16BE(LocalAddress, applyPPClo(Value + Addend));824break;825case ELF::R_PPC_ADDR16_HI:826writeInt16BE(LocalAddress, applyPPChi(Value + Addend));827break;828case ELF::R_PPC_ADDR16_HA:829writeInt16BE(LocalAddress, applyPPCha(Value + Addend));830break;831}832}833834void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,835uint64_t Offset, uint64_t Value,836uint32_t Type, int64_t Addend) {837uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);838switch (Type) {839default:840report_fatal_error("Relocation type not implemented yet!");841break;842case ELF::R_PPC64_ADDR16:843writeInt16BE(LocalAddress, applyPPClo(Value + Addend));844break;845case ELF::R_PPC64_ADDR16_DS:846writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3);847break;848case ELF::R_PPC64_ADDR16_LO:849writeInt16BE(LocalAddress, applyPPClo(Value + Addend));850break;851case ELF::R_PPC64_ADDR16_LO_DS:852writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3);853break;854case ELF::R_PPC64_ADDR16_HI:855case ELF::R_PPC64_ADDR16_HIGH:856writeInt16BE(LocalAddress, applyPPChi(Value + Addend));857break;858case ELF::R_PPC64_ADDR16_HA:859case ELF::R_PPC64_ADDR16_HIGHA:860writeInt16BE(LocalAddress, applyPPCha(Value + Addend));861break;862case ELF::R_PPC64_ADDR16_HIGHER:863writeInt16BE(LocalAddress, applyPPChigher(Value + Addend));864break;865case ELF::R_PPC64_ADDR16_HIGHERA:866writeInt16BE(LocalAddress, applyPPChighera(Value + Addend));867break;868case ELF::R_PPC64_ADDR16_HIGHEST:869writeInt16BE(LocalAddress, applyPPChighest(Value + Addend));870break;871case ELF::R_PPC64_ADDR16_HIGHESTA:872writeInt16BE(LocalAddress, applyPPChighesta(Value + Addend));873break;874case ELF::R_PPC64_ADDR14: {875assert(((Value + Addend) & 3) == 0);876// Preserve the AA/LK bits in the branch instruction877uint8_t aalk = *(LocalAddress + 3);878writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc));879} break;880case ELF::R_PPC64_REL16_LO: {881uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);882uint64_t Delta = Value - FinalAddress + Addend;883writeInt16BE(LocalAddress, applyPPClo(Delta));884} break;885case ELF::R_PPC64_REL16_HI: {886uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);887uint64_t Delta = Value - FinalAddress + Addend;888writeInt16BE(LocalAddress, applyPPChi(Delta));889} break;890case ELF::R_PPC64_REL16_HA: {891uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);892uint64_t Delta = Value - FinalAddress + Addend;893writeInt16BE(LocalAddress, applyPPCha(Delta));894} break;895case ELF::R_PPC64_ADDR32: {896int64_t Result = static_cast<int64_t>(Value + Addend);897if (SignExtend64<32>(Result) != Result)898llvm_unreachable("Relocation R_PPC64_ADDR32 overflow");899writeInt32BE(LocalAddress, Result);900} break;901case ELF::R_PPC64_REL24: {902uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);903int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend);904if (SignExtend64<26>(delta) != delta)905llvm_unreachable("Relocation R_PPC64_REL24 overflow");906// We preserve bits other than LI field, i.e. PO and AA/LK fields.907uint32_t Inst = readBytesUnaligned(LocalAddress, 4);908writeInt32BE(LocalAddress, (Inst & 0xFC000003) | (delta & 0x03FFFFFC));909} break;910case ELF::R_PPC64_REL32: {911uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);912int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend);913if (SignExtend64<32>(delta) != delta)914llvm_unreachable("Relocation R_PPC64_REL32 overflow");915writeInt32BE(LocalAddress, delta);916} break;917case ELF::R_PPC64_REL64: {918uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);919uint64_t Delta = Value - FinalAddress + Addend;920writeInt64BE(LocalAddress, Delta);921} break;922case ELF::R_PPC64_ADDR64:923writeInt64BE(LocalAddress, Value + Addend);924break;925}926}927928void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,929uint64_t Offset, uint64_t Value,930uint32_t Type, int64_t Addend) {931uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);932switch (Type) {933default:934report_fatal_error("Relocation type not implemented yet!");935break;936case ELF::R_390_PC16DBL:937case ELF::R_390_PLT16DBL: {938int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset);939assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow");940writeInt16BE(LocalAddress, Delta / 2);941break;942}943case ELF::R_390_PC32DBL:944case ELF::R_390_PLT32DBL: {945int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset);946assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow");947writeInt32BE(LocalAddress, Delta / 2);948break;949}950case ELF::R_390_PC16: {951int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset);952assert(int16_t(Delta) == Delta && "R_390_PC16 overflow");953writeInt16BE(LocalAddress, Delta);954break;955}956case ELF::R_390_PC32: {957int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset);958assert(int32_t(Delta) == Delta && "R_390_PC32 overflow");959writeInt32BE(LocalAddress, Delta);960break;961}962case ELF::R_390_PC64: {963int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset);964writeInt64BE(LocalAddress, Delta);965break;966}967case ELF::R_390_8:968*LocalAddress = (uint8_t)(Value + Addend);969break;970case ELF::R_390_16:971writeInt16BE(LocalAddress, Value + Addend);972break;973case ELF::R_390_32:974writeInt32BE(LocalAddress, Value + Addend);975break;976case ELF::R_390_64:977writeInt64BE(LocalAddress, Value + Addend);978break;979}980}981982void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,983uint64_t Offset, uint64_t Value,984uint32_t Type, int64_t Addend) {985bool isBE = Arch == Triple::bpfeb;986987switch (Type) {988default:989report_fatal_error("Relocation type not implemented yet!");990break;991case ELF::R_BPF_NONE:992case ELF::R_BPF_64_64:993case ELF::R_BPF_64_32:994case ELF::R_BPF_64_NODYLD32:995break;996case ELF::R_BPF_64_ABS64: {997write(isBE, Section.getAddressWithOffset(Offset), Value + Addend);998LLVM_DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at "999<< format("%p\n", Section.getAddressWithOffset(Offset)));1000break;1001}1002case ELF::R_BPF_64_ABS32: {1003Value += Addend;1004assert(Value <= UINT32_MAX);1005write(isBE, Section.getAddressWithOffset(Offset), static_cast<uint32_t>(Value));1006LLVM_DEBUG(dbgs() << "Writing " << format("%p", Value) << " at "1007<< format("%p\n", Section.getAddressWithOffset(Offset)));1008break;1009}1010}1011}10121013// The target location for the relocation is described by RE.SectionID and1014// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each1015// SectionEntry has three members describing its location.1016// SectionEntry::Address is the address at which the section has been loaded1017// into memory in the current (host) process. SectionEntry::LoadAddress is the1018// address that the section will have in the target process.1019// SectionEntry::ObjAddress is the address of the bits for this section in the1020// original emitted object image (also in the current address space).1021//1022// Relocations will be applied as if the section were loaded at1023// SectionEntry::LoadAddress, but they will be applied at an address based1024// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to1025// Target memory contents if they are required for value calculations.1026//1027// The Value parameter here is the load address of the symbol for the1028// relocation to be applied. For relocations which refer to symbols in the1029// current object Value will be the LoadAddress of the section in which1030// the symbol resides (RE.Addend provides additional information about the1031// symbol location). For external symbols, Value will be the address of the1032// symbol in the target address space.1033void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,1034uint64_t Value) {1035const SectionEntry &Section = Sections[RE.SectionID];1036return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,1037RE.SymOffset, RE.SectionID);1038}10391040void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,1041uint64_t Offset, uint64_t Value,1042uint32_t Type, int64_t Addend,1043uint64_t SymOffset, SID SectionID) {1044switch (Arch) {1045case Triple::x86_64:1046resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset);1047break;1048case Triple::x86:1049resolveX86Relocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,1050(uint32_t)(Addend & 0xffffffffL));1051break;1052case Triple::aarch64:1053case Triple::aarch64_be:1054resolveAArch64Relocation(Section, Offset, Value, Type, Addend);1055break;1056case Triple::arm: // Fall through.1057case Triple::armeb:1058case Triple::thumb:1059case Triple::thumbeb:1060resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,1061(uint32_t)(Addend & 0xffffffffL));1062break;1063case Triple::ppc: // Fall through.1064case Triple::ppcle:1065resolvePPC32Relocation(Section, Offset, Value, Type, Addend);1066break;1067case Triple::ppc64: // Fall through.1068case Triple::ppc64le:1069resolvePPC64Relocation(Section, Offset, Value, Type, Addend);1070break;1071case Triple::systemz:1072resolveSystemZRelocation(Section, Offset, Value, Type, Addend);1073break;1074case Triple::bpfel:1075case Triple::bpfeb:1076resolveBPFRelocation(Section, Offset, Value, Type, Addend);1077break;1078default:1079llvm_unreachable("Unsupported CPU type!");1080}1081}10821083void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const {1084return (void *)(Sections[SectionID].getObjAddress() + Offset);1085}10861087void RuntimeDyldELF::processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value) {1088RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset);1089if (Value.SymbolName)1090addRelocationForSymbol(RE, Value.SymbolName);1091else1092addRelocationForSection(RE, Value.SectionID);1093}10941095uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType,1096bool IsLocal) const {1097switch (RelType) {1098case ELF::R_MICROMIPS_GOT16:1099if (IsLocal)1100return ELF::R_MICROMIPS_LO16;1101break;1102case ELF::R_MICROMIPS_HI16:1103return ELF::R_MICROMIPS_LO16;1104case ELF::R_MIPS_GOT16:1105if (IsLocal)1106return ELF::R_MIPS_LO16;1107break;1108case ELF::R_MIPS_HI16:1109return ELF::R_MIPS_LO16;1110case ELF::R_MIPS_PCHI16:1111return ELF::R_MIPS_PCLO16;1112default:1113break;1114}1115return ELF::R_MIPS_NONE;1116}11171118// Sometimes we don't need to create thunk for a branch.1119// This typically happens when branch target is located1120// in the same object file. In such case target is either1121// a weak symbol or symbol in a different executable section.1122// This function checks if branch target is located in the1123// same object file and if distance between source and target1124// fits R_AARCH64_CALL26 relocation. If both conditions are1125// met, it emits direct jump to the target and returns true.1126// Otherwise false is returned and thunk is created.1127bool RuntimeDyldELF::resolveAArch64ShortBranch(1128unsigned SectionID, relocation_iterator RelI,1129const RelocationValueRef &Value) {1130uint64_t TargetOffset;1131unsigned TargetSectionID;1132if (Value.SymbolName) {1133auto Loc = GlobalSymbolTable.find(Value.SymbolName);11341135// Don't create direct branch for external symbols.1136if (Loc == GlobalSymbolTable.end())1137return false;11381139const auto &SymInfo = Loc->second;11401141TargetSectionID = SymInfo.getSectionID();1142TargetOffset = SymInfo.getOffset();1143} else {1144TargetSectionID = Value.SectionID;1145TargetOffset = 0;1146}11471148// We don't actually know the load addresses at this point, so if the1149// branch is cross-section, we don't know exactly how far away it is.1150if (TargetSectionID != SectionID)1151return false;11521153uint64_t SourceOffset = RelI->getOffset();11541155// R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^271156// If distance between source and target is out of range then we should1157// create thunk.1158if (!isInt<28>(TargetOffset + Value.Addend - SourceOffset))1159return false;11601161RelocationEntry RE(SectionID, SourceOffset, RelI->getType(), Value.Addend);1162if (Value.SymbolName)1163addRelocationForSymbol(RE, Value.SymbolName);1164else1165addRelocationForSection(RE, Value.SectionID);11661167return true;1168}11691170void RuntimeDyldELF::resolveAArch64Branch(unsigned SectionID,1171const RelocationValueRef &Value,1172relocation_iterator RelI,1173StubMap &Stubs) {11741175LLVM_DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation.");1176SectionEntry &Section = Sections[SectionID];11771178uint64_t Offset = RelI->getOffset();1179unsigned RelType = RelI->getType();1180// Look for an existing stub.1181StubMap::const_iterator i = Stubs.find(Value);1182if (i != Stubs.end()) {1183resolveRelocation(Section, Offset,1184Section.getLoadAddressWithOffset(i->second), RelType, 0);1185LLVM_DEBUG(dbgs() << " Stub function found\n");1186} else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) {1187// Create a new stub function.1188LLVM_DEBUG(dbgs() << " Create a new stub function\n");1189Stubs[Value] = Section.getStubOffset();1190uint8_t *StubTargetAddr = createStubFunction(1191Section.getAddressWithOffset(Section.getStubOffset()));11921193RelocationEntry REmovz_g3(SectionID, StubTargetAddr - Section.getAddress(),1194ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend);1195RelocationEntry REmovk_g2(SectionID,1196StubTargetAddr - Section.getAddress() + 4,1197ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend);1198RelocationEntry REmovk_g1(SectionID,1199StubTargetAddr - Section.getAddress() + 8,1200ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend);1201RelocationEntry REmovk_g0(SectionID,1202StubTargetAddr - Section.getAddress() + 12,1203ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend);12041205if (Value.SymbolName) {1206addRelocationForSymbol(REmovz_g3, Value.SymbolName);1207addRelocationForSymbol(REmovk_g2, Value.SymbolName);1208addRelocationForSymbol(REmovk_g1, Value.SymbolName);1209addRelocationForSymbol(REmovk_g0, Value.SymbolName);1210} else {1211addRelocationForSection(REmovz_g3, Value.SectionID);1212addRelocationForSection(REmovk_g2, Value.SectionID);1213addRelocationForSection(REmovk_g1, Value.SectionID);1214addRelocationForSection(REmovk_g0, Value.SectionID);1215}1216resolveRelocation(Section, Offset,1217Section.getLoadAddressWithOffset(Section.getStubOffset()),1218RelType, 0);1219Section.advanceStubOffset(getMaxStubSize());1220}1221}12221223Expected<relocation_iterator>1224RuntimeDyldELF::processRelocationRef(1225unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,1226ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) {1227const auto &Obj = cast<ELFObjectFileBase>(O);1228uint64_t RelType = RelI->getType();1229int64_t Addend = 0;1230if (Expected<int64_t> AddendOrErr = ELFRelocationRef(*RelI).getAddend())1231Addend = *AddendOrErr;1232else1233consumeError(AddendOrErr.takeError());1234elf_symbol_iterator Symbol = RelI->getSymbol();12351236// Obtain the symbol name which is referenced in the relocation1237StringRef TargetName;1238if (Symbol != Obj.symbol_end()) {1239if (auto TargetNameOrErr = Symbol->getName())1240TargetName = *TargetNameOrErr;1241else1242return TargetNameOrErr.takeError();1243}1244LLVM_DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend1245<< " TargetName: " << TargetName << "\n");1246RelocationValueRef Value;1247// First search for the symbol in the local symbol table1248SymbolRef::Type SymType = SymbolRef::ST_Unknown;12491250// Search for the symbol in the global symbol table1251RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end();1252if (Symbol != Obj.symbol_end()) {1253gsi = GlobalSymbolTable.find(TargetName.data());1254Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType();1255if (!SymTypeOrErr) {1256std::string Buf;1257raw_string_ostream OS(Buf);1258logAllUnhandledErrors(SymTypeOrErr.takeError(), OS);1259report_fatal_error(Twine(OS.str()));1260}1261SymType = *SymTypeOrErr;1262}1263if (gsi != GlobalSymbolTable.end()) {1264const auto &SymInfo = gsi->second;1265Value.SectionID = SymInfo.getSectionID();1266Value.Offset = SymInfo.getOffset();1267Value.Addend = SymInfo.getOffset() + Addend;1268} else {1269switch (SymType) {1270case SymbolRef::ST_Debug: {1271// TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously1272// and can be changed by another developers. Maybe best way is add1273// a new symbol type ST_Section to SymbolRef and use it.1274auto SectionOrErr = Symbol->getSection();1275if (!SectionOrErr) {1276std::string Buf;1277raw_string_ostream OS(Buf);1278logAllUnhandledErrors(SectionOrErr.takeError(), OS);1279report_fatal_error(Twine(OS.str()));1280}1281section_iterator si = *SectionOrErr;1282if (si == Obj.section_end())1283llvm_unreachable("Symbol section not found, bad object file format!");1284LLVM_DEBUG(dbgs() << "\t\tThis is section symbol\n");1285bool isCode = si->isText();1286if (auto SectionIDOrErr = findOrEmitSection(Obj, (*si), isCode,1287ObjSectionToID))1288Value.SectionID = *SectionIDOrErr;1289else1290return SectionIDOrErr.takeError();1291Value.Addend = Addend;1292break;1293}1294case SymbolRef::ST_Data:1295case SymbolRef::ST_Function:1296case SymbolRef::ST_Other:1297case SymbolRef::ST_Unknown: {1298Value.SymbolName = TargetName.data();1299Value.Addend = Addend;13001301// Absolute relocations will have a zero symbol ID (STN_UNDEF), which1302// will manifest here as a NULL symbol name.1303// We can set this as a valid (but empty) symbol name, and rely1304// on addRelocationForSymbol to handle this.1305if (!Value.SymbolName)1306Value.SymbolName = "";1307break;1308}1309default:1310llvm_unreachable("Unresolved symbol type!");1311break;1312}1313}13141315uint64_t Offset = RelI->getOffset();13161317LLVM_DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset1318<< "\n");1319if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be)) {1320if ((RelType == ELF::R_AARCH64_CALL26 ||1321RelType == ELF::R_AARCH64_JUMP26) &&1322MemMgr.allowStubAllocation()) {1323resolveAArch64Branch(SectionID, Value, RelI, Stubs);1324} else if (RelType == ELF::R_AARCH64_ADR_GOT_PAGE) {1325// Create new GOT entry or find existing one. If GOT entry is1326// to be created, then we also emit ABS64 relocation for it.1327uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64);1328resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,1329ELF::R_AARCH64_ADR_PREL_PG_HI21);13301331} else if (RelType == ELF::R_AARCH64_LD64_GOT_LO12_NC) {1332uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64);1333resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,1334ELF::R_AARCH64_LDST64_ABS_LO12_NC);1335} else {1336processSimpleRelocation(SectionID, Offset, RelType, Value);1337}1338} else if (Arch == Triple::arm) {1339if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL ||1340RelType == ELF::R_ARM_JUMP24) {1341// This is an ARM branch relocation, need to use a stub function.1342LLVM_DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.\n");1343SectionEntry &Section = Sections[SectionID];13441345// Look for an existing stub.1346StubMap::const_iterator i = Stubs.find(Value);1347if (i != Stubs.end()) {1348resolveRelocation(Section, Offset,1349Section.getLoadAddressWithOffset(i->second), RelType,13500);1351LLVM_DEBUG(dbgs() << " Stub function found\n");1352} else {1353// Create a new stub function.1354LLVM_DEBUG(dbgs() << " Create a new stub function\n");1355Stubs[Value] = Section.getStubOffset();1356uint8_t *StubTargetAddr = createStubFunction(1357Section.getAddressWithOffset(Section.getStubOffset()));1358RelocationEntry RE(SectionID, StubTargetAddr - Section.getAddress(),1359ELF::R_ARM_ABS32, Value.Addend);1360if (Value.SymbolName)1361addRelocationForSymbol(RE, Value.SymbolName);1362else1363addRelocationForSection(RE, Value.SectionID);13641365resolveRelocation(1366Section, Offset,1367Section.getLoadAddressWithOffset(Section.getStubOffset()), RelType,13680);1369Section.advanceStubOffset(getMaxStubSize());1370}1371} else {1372uint32_t *Placeholder =1373reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset));1374if (RelType == ELF::R_ARM_PREL31 || RelType == ELF::R_ARM_TARGET1 ||1375RelType == ELF::R_ARM_ABS32) {1376Value.Addend += *Placeholder;1377} else if (RelType == ELF::R_ARM_MOVW_ABS_NC || RelType == ELF::R_ARM_MOVT_ABS) {1378// See ELF for ARM documentation1379Value.Addend += (int16_t)((*Placeholder & 0xFFF) | (((*Placeholder >> 16) & 0xF) << 12));1380}1381processSimpleRelocation(SectionID, Offset, RelType, Value);1382}1383} else if (IsMipsO32ABI) {1384uint8_t *Placeholder = reinterpret_cast<uint8_t *>(1385computePlaceholderAddress(SectionID, Offset));1386uint32_t Opcode = readBytesUnaligned(Placeholder, 4);1387if (RelType == ELF::R_MIPS_26) {1388// This is an Mips branch relocation, need to use a stub function.1389LLVM_DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");1390SectionEntry &Section = Sections[SectionID];13911392// Extract the addend from the instruction.1393// We shift up by two since the Value will be down shifted again1394// when applying the relocation.1395uint32_t Addend = (Opcode & 0x03ffffff) << 2;13961397Value.Addend += Addend;13981399// Look up for existing stub.1400StubMap::const_iterator i = Stubs.find(Value);1401if (i != Stubs.end()) {1402RelocationEntry RE(SectionID, Offset, RelType, i->second);1403addRelocationForSection(RE, SectionID);1404LLVM_DEBUG(dbgs() << " Stub function found\n");1405} else {1406// Create a new stub function.1407LLVM_DEBUG(dbgs() << " Create a new stub function\n");1408Stubs[Value] = Section.getStubOffset();14091410unsigned AbiVariant = Obj.getPlatformFlags();14111412uint8_t *StubTargetAddr = createStubFunction(1413Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant);14141415// Creating Hi and Lo relocations for the filled stub instructions.1416RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(),1417ELF::R_MIPS_HI16, Value.Addend);1418RelocationEntry RELo(SectionID,1419StubTargetAddr - Section.getAddress() + 4,1420ELF::R_MIPS_LO16, Value.Addend);14211422if (Value.SymbolName) {1423addRelocationForSymbol(REHi, Value.SymbolName);1424addRelocationForSymbol(RELo, Value.SymbolName);1425} else {1426addRelocationForSection(REHi, Value.SectionID);1427addRelocationForSection(RELo, Value.SectionID);1428}14291430RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset());1431addRelocationForSection(RE, SectionID);1432Section.advanceStubOffset(getMaxStubSize());1433}1434} else if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16) {1435int64_t Addend = (Opcode & 0x0000ffff) << 16;1436RelocationEntry RE(SectionID, Offset, RelType, Addend);1437PendingRelocs.push_back(std::make_pair(Value, RE));1438} else if (RelType == ELF::R_MIPS_LO16 || RelType == ELF::R_MIPS_PCLO16) {1439int64_t Addend = Value.Addend + SignExtend32<16>(Opcode & 0x0000ffff);1440for (auto I = PendingRelocs.begin(); I != PendingRelocs.end();) {1441const RelocationValueRef &MatchingValue = I->first;1442RelocationEntry &Reloc = I->second;1443if (MatchingValue == Value &&1444RelType == getMatchingLoRelocation(Reloc.RelType) &&1445SectionID == Reloc.SectionID) {1446Reloc.Addend += Addend;1447if (Value.SymbolName)1448addRelocationForSymbol(Reloc, Value.SymbolName);1449else1450addRelocationForSection(Reloc, Value.SectionID);1451I = PendingRelocs.erase(I);1452} else1453++I;1454}1455RelocationEntry RE(SectionID, Offset, RelType, Addend);1456if (Value.SymbolName)1457addRelocationForSymbol(RE, Value.SymbolName);1458else1459addRelocationForSection(RE, Value.SectionID);1460} else {1461if (RelType == ELF::R_MIPS_32)1462Value.Addend += Opcode;1463else if (RelType == ELF::R_MIPS_PC16)1464Value.Addend += SignExtend32<18>((Opcode & 0x0000ffff) << 2);1465else if (RelType == ELF::R_MIPS_PC19_S2)1466Value.Addend += SignExtend32<21>((Opcode & 0x0007ffff) << 2);1467else if (RelType == ELF::R_MIPS_PC21_S2)1468Value.Addend += SignExtend32<23>((Opcode & 0x001fffff) << 2);1469else if (RelType == ELF::R_MIPS_PC26_S2)1470Value.Addend += SignExtend32<28>((Opcode & 0x03ffffff) << 2);1471processSimpleRelocation(SectionID, Offset, RelType, Value);1472}1473} else if (IsMipsN32ABI || IsMipsN64ABI) {1474uint32_t r_type = RelType & 0xff;1475RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);1476if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE1477|| r_type == ELF::R_MIPS_GOT_DISP) {1478StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName);1479if (i != GOTSymbolOffsets.end())1480RE.SymOffset = i->second;1481else {1482RE.SymOffset = allocateGOTEntries(1);1483GOTSymbolOffsets[TargetName] = RE.SymOffset;1484}1485if (Value.SymbolName)1486addRelocationForSymbol(RE, Value.SymbolName);1487else1488addRelocationForSection(RE, Value.SectionID);1489} else if (RelType == ELF::R_MIPS_26) {1490// This is an Mips branch relocation, need to use a stub function.1491LLVM_DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");1492SectionEntry &Section = Sections[SectionID];14931494// Look up for existing stub.1495StubMap::const_iterator i = Stubs.find(Value);1496if (i != Stubs.end()) {1497RelocationEntry RE(SectionID, Offset, RelType, i->second);1498addRelocationForSection(RE, SectionID);1499LLVM_DEBUG(dbgs() << " Stub function found\n");1500} else {1501// Create a new stub function.1502LLVM_DEBUG(dbgs() << " Create a new stub function\n");1503Stubs[Value] = Section.getStubOffset();15041505unsigned AbiVariant = Obj.getPlatformFlags();15061507uint8_t *StubTargetAddr = createStubFunction(1508Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant);15091510if (IsMipsN32ABI) {1511// Creating Hi and Lo relocations for the filled stub instructions.1512RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(),1513ELF::R_MIPS_HI16, Value.Addend);1514RelocationEntry RELo(SectionID,1515StubTargetAddr - Section.getAddress() + 4,1516ELF::R_MIPS_LO16, Value.Addend);1517if (Value.SymbolName) {1518addRelocationForSymbol(REHi, Value.SymbolName);1519addRelocationForSymbol(RELo, Value.SymbolName);1520} else {1521addRelocationForSection(REHi, Value.SectionID);1522addRelocationForSection(RELo, Value.SectionID);1523}1524} else {1525// Creating Highest, Higher, Hi and Lo relocations for the filled stub1526// instructions.1527RelocationEntry REHighest(SectionID,1528StubTargetAddr - Section.getAddress(),1529ELF::R_MIPS_HIGHEST, Value.Addend);1530RelocationEntry REHigher(SectionID,1531StubTargetAddr - Section.getAddress() + 4,1532ELF::R_MIPS_HIGHER, Value.Addend);1533RelocationEntry REHi(SectionID,1534StubTargetAddr - Section.getAddress() + 12,1535ELF::R_MIPS_HI16, Value.Addend);1536RelocationEntry RELo(SectionID,1537StubTargetAddr - Section.getAddress() + 20,1538ELF::R_MIPS_LO16, Value.Addend);1539if (Value.SymbolName) {1540addRelocationForSymbol(REHighest, Value.SymbolName);1541addRelocationForSymbol(REHigher, Value.SymbolName);1542addRelocationForSymbol(REHi, Value.SymbolName);1543addRelocationForSymbol(RELo, Value.SymbolName);1544} else {1545addRelocationForSection(REHighest, Value.SectionID);1546addRelocationForSection(REHigher, Value.SectionID);1547addRelocationForSection(REHi, Value.SectionID);1548addRelocationForSection(RELo, Value.SectionID);1549}1550}1551RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset());1552addRelocationForSection(RE, SectionID);1553Section.advanceStubOffset(getMaxStubSize());1554}1555} else {1556processSimpleRelocation(SectionID, Offset, RelType, Value);1557}15581559} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {1560if (RelType == ELF::R_PPC64_REL24) {1561// Determine ABI variant in use for this object.1562unsigned AbiVariant = Obj.getPlatformFlags();1563AbiVariant &= ELF::EF_PPC64_ABI;1564// A PPC branch relocation will need a stub function if the target is1565// an external symbol (either Value.SymbolName is set, or SymType is1566// Symbol::ST_Unknown) or if the target address is not within the1567// signed 24-bits branch address.1568SectionEntry &Section = Sections[SectionID];1569uint8_t *Target = Section.getAddressWithOffset(Offset);1570bool RangeOverflow = false;1571bool IsExtern = Value.SymbolName || SymType == SymbolRef::ST_Unknown;1572if (!IsExtern) {1573if (AbiVariant != 2) {1574// In the ELFv1 ABI, a function call may point to the .opd entry,1575// so the final symbol value is calculated based on the relocation1576// values in the .opd section.1577if (auto Err = findOPDEntrySection(Obj, ObjSectionToID, Value))1578return std::move(Err);1579} else {1580// In the ELFv2 ABI, a function symbol may provide a local entry1581// point, which must be used for direct calls.1582if (Value.SectionID == SectionID){1583uint8_t SymOther = Symbol->getOther();1584Value.Addend += ELF::decodePPC64LocalEntryOffset(SymOther);1585}1586}1587uint8_t *RelocTarget =1588Sections[Value.SectionID].getAddressWithOffset(Value.Addend);1589int64_t delta = static_cast<int64_t>(Target - RelocTarget);1590// If it is within 26-bits branch range, just set the branch target1591if (SignExtend64<26>(delta) != delta) {1592RangeOverflow = true;1593} else if ((AbiVariant != 2) ||1594(AbiVariant == 2 && Value.SectionID == SectionID)) {1595RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);1596addRelocationForSection(RE, Value.SectionID);1597}1598}1599if (IsExtern || (AbiVariant == 2 && Value.SectionID != SectionID) ||1600RangeOverflow) {1601// It is an external symbol (either Value.SymbolName is set, or1602// SymType is SymbolRef::ST_Unknown) or out of range.1603StubMap::const_iterator i = Stubs.find(Value);1604if (i != Stubs.end()) {1605// Symbol function stub already created, just relocate to it1606resolveRelocation(Section, Offset,1607Section.getLoadAddressWithOffset(i->second),1608RelType, 0);1609LLVM_DEBUG(dbgs() << " Stub function found\n");1610} else {1611// Create a new stub function.1612LLVM_DEBUG(dbgs() << " Create a new stub function\n");1613Stubs[Value] = Section.getStubOffset();1614uint8_t *StubTargetAddr = createStubFunction(1615Section.getAddressWithOffset(Section.getStubOffset()),1616AbiVariant);1617RelocationEntry RE(SectionID, StubTargetAddr - Section.getAddress(),1618ELF::R_PPC64_ADDR64, Value.Addend);16191620// Generates the 64-bits address loads as exemplified in section1621// 4.5.1 in PPC64 ELF ABI. Note that the relocations need to1622// apply to the low part of the instructions, so we have to update1623// the offset according to the target endianness.1624uint64_t StubRelocOffset = StubTargetAddr - Section.getAddress();1625if (!IsTargetLittleEndian)1626StubRelocOffset += 2;16271628RelocationEntry REhst(SectionID, StubRelocOffset + 0,1629ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend);1630RelocationEntry REhr(SectionID, StubRelocOffset + 4,1631ELF::R_PPC64_ADDR16_HIGHER, Value.Addend);1632RelocationEntry REh(SectionID, StubRelocOffset + 12,1633ELF::R_PPC64_ADDR16_HI, Value.Addend);1634RelocationEntry REl(SectionID, StubRelocOffset + 16,1635ELF::R_PPC64_ADDR16_LO, Value.Addend);16361637if (Value.SymbolName) {1638addRelocationForSymbol(REhst, Value.SymbolName);1639addRelocationForSymbol(REhr, Value.SymbolName);1640addRelocationForSymbol(REh, Value.SymbolName);1641addRelocationForSymbol(REl, Value.SymbolName);1642} else {1643addRelocationForSection(REhst, Value.SectionID);1644addRelocationForSection(REhr, Value.SectionID);1645addRelocationForSection(REh, Value.SectionID);1646addRelocationForSection(REl, Value.SectionID);1647}16481649resolveRelocation(1650Section, Offset,1651Section.getLoadAddressWithOffset(Section.getStubOffset()),1652RelType, 0);1653Section.advanceStubOffset(getMaxStubSize());1654}1655if (IsExtern || (AbiVariant == 2 && Value.SectionID != SectionID)) {1656// Restore the TOC for external calls1657if (AbiVariant == 2)1658writeInt32BE(Target + 4, 0xE8410018); // ld r2,24(r1)1659else1660writeInt32BE(Target + 4, 0xE8410028); // ld r2,40(r1)1661}1662}1663} else if (RelType == ELF::R_PPC64_TOC16 ||1664RelType == ELF::R_PPC64_TOC16_DS ||1665RelType == ELF::R_PPC64_TOC16_LO ||1666RelType == ELF::R_PPC64_TOC16_LO_DS ||1667RelType == ELF::R_PPC64_TOC16_HI ||1668RelType == ELF::R_PPC64_TOC16_HA) {1669// These relocations are supposed to subtract the TOC address from1670// the final value. This does not fit cleanly into the RuntimeDyld1671// scheme, since there may be *two* sections involved in determining1672// the relocation value (the section of the symbol referred to by the1673// relocation, and the TOC section associated with the current module).1674//1675// Fortunately, these relocations are currently only ever generated1676// referring to symbols that themselves reside in the TOC, which means1677// that the two sections are actually the same. Thus they cancel out1678// and we can immediately resolve the relocation right now.1679switch (RelType) {1680case ELF::R_PPC64_TOC16: RelType = ELF::R_PPC64_ADDR16; break;1681case ELF::R_PPC64_TOC16_DS: RelType = ELF::R_PPC64_ADDR16_DS; break;1682case ELF::R_PPC64_TOC16_LO: RelType = ELF::R_PPC64_ADDR16_LO; break;1683case ELF::R_PPC64_TOC16_LO_DS: RelType = ELF::R_PPC64_ADDR16_LO_DS; break;1684case ELF::R_PPC64_TOC16_HI: RelType = ELF::R_PPC64_ADDR16_HI; break;1685case ELF::R_PPC64_TOC16_HA: RelType = ELF::R_PPC64_ADDR16_HA; break;1686default: llvm_unreachable("Wrong relocation type.");1687}16881689RelocationValueRef TOCValue;1690if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, TOCValue))1691return std::move(Err);1692if (Value.SymbolName || Value.SectionID != TOCValue.SectionID)1693llvm_unreachable("Unsupported TOC relocation.");1694Value.Addend -= TOCValue.Addend;1695resolveRelocation(Sections[SectionID], Offset, Value.Addend, RelType, 0);1696} else {1697// There are two ways to refer to the TOC address directly: either1698// via a ELF::R_PPC64_TOC relocation (where both symbol and addend are1699// ignored), or via any relocation that refers to the magic ".TOC."1700// symbols (in which case the addend is respected).1701if (RelType == ELF::R_PPC64_TOC) {1702RelType = ELF::R_PPC64_ADDR64;1703if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value))1704return std::move(Err);1705} else if (TargetName == ".TOC.") {1706if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value))1707return std::move(Err);1708Value.Addend += Addend;1709}17101711RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);17121713if (Value.SymbolName)1714addRelocationForSymbol(RE, Value.SymbolName);1715else1716addRelocationForSection(RE, Value.SectionID);1717}1718} else if (Arch == Triple::systemz &&1719(RelType == ELF::R_390_PLT32DBL || RelType == ELF::R_390_GOTENT)) {1720// Create function stubs for both PLT and GOT references, regardless of1721// whether the GOT reference is to data or code. The stub contains the1722// full address of the symbol, as needed by GOT references, and the1723// executable part only adds an overhead of 8 bytes.1724//1725// We could try to conserve space by allocating the code and data1726// parts of the stub separately. However, as things stand, we allocate1727// a stub for every relocation, so using a GOT in JIT code should be1728// no less space efficient than using an explicit constant pool.1729LLVM_DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation.");1730SectionEntry &Section = Sections[SectionID];17311732// Look for an existing stub.1733StubMap::const_iterator i = Stubs.find(Value);1734uintptr_t StubAddress;1735if (i != Stubs.end()) {1736StubAddress = uintptr_t(Section.getAddressWithOffset(i->second));1737LLVM_DEBUG(dbgs() << " Stub function found\n");1738} else {1739// Create a new stub function.1740LLVM_DEBUG(dbgs() << " Create a new stub function\n");17411742uintptr_t BaseAddress = uintptr_t(Section.getAddress());1743StubAddress =1744alignTo(BaseAddress + Section.getStubOffset(), getStubAlignment());1745unsigned StubOffset = StubAddress - BaseAddress;17461747Stubs[Value] = StubOffset;1748createStubFunction((uint8_t *)StubAddress);1749RelocationEntry RE(SectionID, StubOffset + 8, ELF::R_390_64,1750Value.Offset);1751if (Value.SymbolName)1752addRelocationForSymbol(RE, Value.SymbolName);1753else1754addRelocationForSection(RE, Value.SectionID);1755Section.advanceStubOffset(getMaxStubSize());1756}17571758if (RelType == ELF::R_390_GOTENT)1759resolveRelocation(Section, Offset, StubAddress + 8, ELF::R_390_PC32DBL,1760Addend);1761else1762resolveRelocation(Section, Offset, StubAddress, RelType, Addend);1763} else if (Arch == Triple::x86_64) {1764if (RelType == ELF::R_X86_64_PLT32) {1765// The way the PLT relocations normally work is that the linker allocates1766// the1767// PLT and this relocation makes a PC-relative call into the PLT. The PLT1768// entry will then jump to an address provided by the GOT. On first call,1769// the1770// GOT address will point back into PLT code that resolves the symbol. After1771// the first call, the GOT entry points to the actual function.1772//1773// For local functions we're ignoring all of that here and just replacing1774// the PLT32 relocation type with PC32, which will translate the relocation1775// into a PC-relative call directly to the function. For external symbols we1776// can't be sure the function will be within 2^32 bytes of the call site, so1777// we need to create a stub, which calls into the GOT. This case is1778// equivalent to the usual PLT implementation except that we use the stub1779// mechanism in RuntimeDyld (which puts stubs at the end of the section)1780// rather than allocating a PLT section.1781if (Value.SymbolName && MemMgr.allowStubAllocation()) {1782// This is a call to an external function.1783// Look for an existing stub.1784SectionEntry *Section = &Sections[SectionID];1785StubMap::const_iterator i = Stubs.find(Value);1786uintptr_t StubAddress;1787if (i != Stubs.end()) {1788StubAddress = uintptr_t(Section->getAddress()) + i->second;1789LLVM_DEBUG(dbgs() << " Stub function found\n");1790} else {1791// Create a new stub function (equivalent to a PLT entry).1792LLVM_DEBUG(dbgs() << " Create a new stub function\n");17931794uintptr_t BaseAddress = uintptr_t(Section->getAddress());1795StubAddress = alignTo(BaseAddress + Section->getStubOffset(),1796getStubAlignment());1797unsigned StubOffset = StubAddress - BaseAddress;1798Stubs[Value] = StubOffset;1799createStubFunction((uint8_t *)StubAddress);18001801// Bump our stub offset counter1802Section->advanceStubOffset(getMaxStubSize());18031804// Allocate a GOT Entry1805uint64_t GOTOffset = allocateGOTEntries(1);1806// This potentially creates a new Section which potentially1807// invalidates the Section pointer, so reload it.1808Section = &Sections[SectionID];18091810// The load of the GOT address has an addend of -41811resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4,1812ELF::R_X86_64_PC32);18131814// Fill in the value of the symbol we're targeting into the GOT1815addRelocationForSymbol(1816computeGOTOffsetRE(GOTOffset, 0, ELF::R_X86_64_64),1817Value.SymbolName);1818}18191820// Make the target call a call into the stub table.1821resolveRelocation(*Section, Offset, StubAddress, ELF::R_X86_64_PC32,1822Addend);1823} else {1824Value.Addend += support::ulittle32_t::ref(1825computePlaceholderAddress(SectionID, Offset));1826processSimpleRelocation(SectionID, Offset, ELF::R_X86_64_PC32, Value);1827}1828} else if (RelType == ELF::R_X86_64_GOTPCREL ||1829RelType == ELF::R_X86_64_GOTPCRELX ||1830RelType == ELF::R_X86_64_REX_GOTPCRELX) {1831uint64_t GOTOffset = allocateGOTEntries(1);1832resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,1833ELF::R_X86_64_PC32);18341835// Fill in the value of the symbol we're targeting into the GOT1836RelocationEntry RE =1837computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64);1838if (Value.SymbolName)1839addRelocationForSymbol(RE, Value.SymbolName);1840else1841addRelocationForSection(RE, Value.SectionID);1842} else if (RelType == ELF::R_X86_64_GOT64) {1843// Fill in a 64-bit GOT offset.1844uint64_t GOTOffset = allocateGOTEntries(1);1845resolveRelocation(Sections[SectionID], Offset, GOTOffset,1846ELF::R_X86_64_64, 0);18471848// Fill in the value of the symbol we're targeting into the GOT1849RelocationEntry RE =1850computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64);1851if (Value.SymbolName)1852addRelocationForSymbol(RE, Value.SymbolName);1853else1854addRelocationForSection(RE, Value.SectionID);1855} else if (RelType == ELF::R_X86_64_GOTPC32) {1856// Materialize the address of the base of the GOT relative to the PC.1857// This doesn't create a GOT entry, but it does mean we need a GOT1858// section.1859(void)allocateGOTEntries(0);1860resolveGOTOffsetRelocation(SectionID, Offset, Addend, ELF::R_X86_64_PC32);1861} else if (RelType == ELF::R_X86_64_GOTPC64) {1862(void)allocateGOTEntries(0);1863resolveGOTOffsetRelocation(SectionID, Offset, Addend, ELF::R_X86_64_PC64);1864} else if (RelType == ELF::R_X86_64_GOTOFF64) {1865// GOTOFF relocations ultimately require a section difference relocation.1866(void)allocateGOTEntries(0);1867processSimpleRelocation(SectionID, Offset, RelType, Value);1868} else if (RelType == ELF::R_X86_64_PC32) {1869Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));1870processSimpleRelocation(SectionID, Offset, RelType, Value);1871} else if (RelType == ELF::R_X86_64_PC64) {1872Value.Addend += support::ulittle64_t::ref(computePlaceholderAddress(SectionID, Offset));1873processSimpleRelocation(SectionID, Offset, RelType, Value);1874} else if (RelType == ELF::R_X86_64_GOTTPOFF) {1875processX86_64GOTTPOFFRelocation(SectionID, Offset, Value, Addend);1876} else if (RelType == ELF::R_X86_64_TLSGD ||1877RelType == ELF::R_X86_64_TLSLD) {1878// The next relocation must be the relocation for __tls_get_addr.1879++RelI;1880auto &GetAddrRelocation = *RelI;1881processX86_64TLSRelocation(SectionID, Offset, RelType, Value, Addend,1882GetAddrRelocation);1883} else {1884processSimpleRelocation(SectionID, Offset, RelType, Value);1885}1886} else {1887if (Arch == Triple::x86) {1888Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));1889}1890processSimpleRelocation(SectionID, Offset, RelType, Value);1891}1892return ++RelI;1893}18941895void RuntimeDyldELF::processX86_64GOTTPOFFRelocation(unsigned SectionID,1896uint64_t Offset,1897RelocationValueRef Value,1898int64_t Addend) {1899// Use the approach from "x86-64 Linker Optimizations" from the TLS spec1900// to replace the GOTTPOFF relocation with a TPOFF relocation. The spec1901// only mentions one optimization even though there are two different1902// code sequences for the Initial Exec TLS Model. We match the code to1903// find out which one was used.19041905// A possible TLS code sequence and its replacement1906struct CodeSequence {1907// The expected code sequence1908ArrayRef<uint8_t> ExpectedCodeSequence;1909// The negative offset of the GOTTPOFF relocation to the beginning of1910// the sequence1911uint64_t TLSSequenceOffset;1912// The new code sequence1913ArrayRef<uint8_t> NewCodeSequence;1914// The offset of the new TPOFF relocation1915uint64_t TpoffRelocationOffset;1916};19171918std::array<CodeSequence, 2> CodeSequences;19191920// Initial Exec Code Model Sequence1921{1922static const std::initializer_list<uint8_t> ExpectedCodeSequenceList = {19230x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00,19240x00, // mov %fs:0, %rax19250x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // add x@gotpoff(%rip),1926// %rax1927};1928CodeSequences[0].ExpectedCodeSequence =1929ArrayRef<uint8_t>(ExpectedCodeSequenceList);1930CodeSequences[0].TLSSequenceOffset = 12;19311932static const std::initializer_list<uint8_t> NewCodeSequenceList = {19330x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0, %rax19340x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff(%rax), %rax1935};1936CodeSequences[0].NewCodeSequence = ArrayRef<uint8_t>(NewCodeSequenceList);1937CodeSequences[0].TpoffRelocationOffset = 12;1938}19391940// Initial Exec Code Model Sequence, II1941{1942static const std::initializer_list<uint8_t> ExpectedCodeSequenceList = {19430x48, 0x8b, 0x05, 0x00, 0x00, 0x00, 0x00, // mov x@gotpoff(%rip), %rax19440x64, 0x48, 0x8b, 0x00, 0x00, 0x00, 0x00 // mov %fs:(%rax), %rax1945};1946CodeSequences[1].ExpectedCodeSequence =1947ArrayRef<uint8_t>(ExpectedCodeSequenceList);1948CodeSequences[1].TLSSequenceOffset = 3;19491950static const std::initializer_list<uint8_t> NewCodeSequenceList = {19510x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, // 6 byte nop19520x64, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:x@tpoff, %rax1953};1954CodeSequences[1].NewCodeSequence = ArrayRef<uint8_t>(NewCodeSequenceList);1955CodeSequences[1].TpoffRelocationOffset = 10;1956}19571958bool Resolved = false;1959auto &Section = Sections[SectionID];1960for (const auto &C : CodeSequences) {1961assert(C.ExpectedCodeSequence.size() == C.NewCodeSequence.size() &&1962"Old and new code sequences must have the same size");19631964if (Offset < C.TLSSequenceOffset ||1965(Offset - C.TLSSequenceOffset + C.NewCodeSequence.size()) >1966Section.getSize()) {1967// This can't be a matching sequence as it doesn't fit in the current1968// section1969continue;1970}19711972auto TLSSequenceStartOffset = Offset - C.TLSSequenceOffset;1973auto *TLSSequence = Section.getAddressWithOffset(TLSSequenceStartOffset);1974if (ArrayRef<uint8_t>(TLSSequence, C.ExpectedCodeSequence.size()) !=1975C.ExpectedCodeSequence) {1976continue;1977}19781979memcpy(TLSSequence, C.NewCodeSequence.data(), C.NewCodeSequence.size());19801981// The original GOTTPOFF relocation has an addend as it is PC relative,1982// so it needs to be corrected. The TPOFF32 relocation is used as an1983// absolute value (which is an offset from %fs:0), so remove the addend1984// again.1985RelocationEntry RE(SectionID,1986TLSSequenceStartOffset + C.TpoffRelocationOffset,1987ELF::R_X86_64_TPOFF32, Value.Addend - Addend);19881989if (Value.SymbolName)1990addRelocationForSymbol(RE, Value.SymbolName);1991else1992addRelocationForSection(RE, Value.SectionID);19931994Resolved = true;1995break;1996}19971998if (!Resolved) {1999// The GOTTPOFF relocation was not used in one of the sequences2000// described in the spec, so we can't optimize it to a TPOFF2001// relocation.2002uint64_t GOTOffset = allocateGOTEntries(1);2003resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,2004ELF::R_X86_64_PC32);2005RelocationEntry RE =2006computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_TPOFF64);2007if (Value.SymbolName)2008addRelocationForSymbol(RE, Value.SymbolName);2009else2010addRelocationForSection(RE, Value.SectionID);2011}2012}20132014void RuntimeDyldELF::processX86_64TLSRelocation(2015unsigned SectionID, uint64_t Offset, uint64_t RelType,2016RelocationValueRef Value, int64_t Addend,2017const RelocationRef &GetAddrRelocation) {2018// Since we are statically linking and have no additional DSOs, we can resolve2019// the relocation directly without using __tls_get_addr.2020// Use the approach from "x86-64 Linker Optimizations" from the TLS spec2021// to replace it with the Local Exec relocation variant.20222023// Find out whether the code was compiled with the large or small memory2024// model. For this we look at the next relocation which is the relocation2025// for the __tls_get_addr function. If it's a 32 bit relocation, it's the2026// small code model, with a 64 bit relocation it's the large code model.2027bool IsSmallCodeModel;2028// Is the relocation for the __tls_get_addr a PC-relative GOT relocation?2029bool IsGOTPCRel = false;20302031switch (GetAddrRelocation.getType()) {2032case ELF::R_X86_64_GOTPCREL:2033case ELF::R_X86_64_REX_GOTPCRELX:2034case ELF::R_X86_64_GOTPCRELX:2035IsGOTPCRel = true;2036[[fallthrough]];2037case ELF::R_X86_64_PLT32:2038IsSmallCodeModel = true;2039break;2040case ELF::R_X86_64_PLTOFF64:2041IsSmallCodeModel = false;2042break;2043default:2044report_fatal_error(2045"invalid TLS relocations for General/Local Dynamic TLS Model: "2046"expected PLT or GOT relocation for __tls_get_addr function");2047}20482049// The negative offset to the start of the TLS code sequence relative to2050// the offset of the TLSGD/TLSLD relocation2051uint64_t TLSSequenceOffset;2052// The expected start of the code sequence2053ArrayRef<uint8_t> ExpectedCodeSequence;2054// The new TLS code sequence that will replace the existing code2055ArrayRef<uint8_t> NewCodeSequence;20562057if (RelType == ELF::R_X86_64_TLSGD) {2058// The offset of the new TPOFF32 relocation (offset starting from the2059// beginning of the whole TLS sequence)2060uint64_t TpoffRelocOffset;20612062if (IsSmallCodeModel) {2063if (!IsGOTPCRel) {2064static const std::initializer_list<uint8_t> CodeSequence = {20650x66, // data16 (no-op prefix)20660x48, 0x8d, 0x3d, 0x00, 0x00,20670x00, 0x00, // lea <disp32>(%rip), %rdi20680x66, 0x66, // two data16 prefixes20690x48, // rex64 (no-op prefix)20700xe8, 0x00, 0x00, 0x00, 0x00 // call __tls_get_addr@plt2071};2072ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence);2073TLSSequenceOffset = 4;2074} else {2075// This code sequence is not described in the TLS spec but gcc2076// generates it sometimes.2077static const std::initializer_list<uint8_t> CodeSequence = {20780x66, // data16 (no-op prefix)20790x48, 0x8d, 0x3d, 0x00, 0x00,20800x00, 0x00, // lea <disp32>(%rip), %rdi20810x66, // data16 prefix (no-op prefix)20820x48, // rex64 (no-op prefix)20830xff, 0x15, 0x00, 0x00, 0x00,20840x00 // call *__tls_get_addr@gotpcrel(%rip)2085};2086ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence);2087TLSSequenceOffset = 4;2088}20892090// The replacement code for the small code model. It's the same for2091// both sequences.2092static const std::initializer_list<uint8_t> SmallSequence = {20930x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00,20940x00, // mov %fs:0, %rax20950x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff(%rax),2096// %rax2097};2098NewCodeSequence = ArrayRef<uint8_t>(SmallSequence);2099TpoffRelocOffset = 12;2100} else {2101static const std::initializer_list<uint8_t> CodeSequence = {21020x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00, // lea <disp32>(%rip),2103// %rdi21040x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,21050x00, // movabs $__tls_get_addr@pltoff, %rax21060x48, 0x01, 0xd8, // add %rbx, %rax21070xff, 0xd0 // call *%rax2108};2109ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence);2110TLSSequenceOffset = 3;21112112// The replacement code for the large code model2113static const std::initializer_list<uint8_t> LargeSequence = {21140x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00,21150x00, // mov %fs:0, %rax21160x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00, // lea x@tpoff(%rax),2117// %rax21180x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 // nopw 0x0(%rax,%rax,1)2119};2120NewCodeSequence = ArrayRef<uint8_t>(LargeSequence);2121TpoffRelocOffset = 12;2122}21232124// The TLSGD/TLSLD relocations are PC-relative, so they have an addend.2125// The new TPOFF32 relocations is used as an absolute offset from2126// %fs:0, so remove the TLSGD/TLSLD addend again.2127RelocationEntry RE(SectionID, Offset - TLSSequenceOffset + TpoffRelocOffset,2128ELF::R_X86_64_TPOFF32, Value.Addend - Addend);2129if (Value.SymbolName)2130addRelocationForSymbol(RE, Value.SymbolName);2131else2132addRelocationForSection(RE, Value.SectionID);2133} else if (RelType == ELF::R_X86_64_TLSLD) {2134if (IsSmallCodeModel) {2135if (!IsGOTPCRel) {2136static const std::initializer_list<uint8_t> CodeSequence = {21370x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, // leaq <disp32>(%rip), %rdi21380x00, 0xe8, 0x00, 0x00, 0x00, 0x00 // call __tls_get_addr@plt2139};2140ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence);2141TLSSequenceOffset = 3;21422143// The replacement code for the small code model2144static const std::initializer_list<uint8_t> SmallSequence = {21450x66, 0x66, 0x66, // three data16 prefixes (no-op)21460x64, 0x48, 0x8b, 0x04, 0x25,21470x00, 0x00, 0x00, 0x00 // mov %fs:0, %rax2148};2149NewCodeSequence = ArrayRef<uint8_t>(SmallSequence);2150} else {2151// This code sequence is not described in the TLS spec but gcc2152// generates it sometimes.2153static const std::initializer_list<uint8_t> CodeSequence = {21540x48, 0x8d, 0x3d, 0x00,21550x00, 0x00, 0x00, // leaq <disp32>(%rip), %rdi21560xff, 0x15, 0x00, 0x00,21570x00, 0x00 // call2158// *__tls_get_addr@gotpcrel(%rip)2159};2160ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence);2161TLSSequenceOffset = 3;21622163// The replacement is code is just like above but it needs to be2164// one byte longer.2165static const std::initializer_list<uint8_t> SmallSequence = {21660x0f, 0x1f, 0x40, 0x00, // 4 byte nop21670x64, 0x48, 0x8b, 0x04, 0x25,21680x00, 0x00, 0x00, 0x00 // mov %fs:0, %rax2169};2170NewCodeSequence = ArrayRef<uint8_t>(SmallSequence);2171}2172} else {2173// This is the same sequence as for the TLSGD sequence with the large2174// memory model above2175static const std::initializer_list<uint8_t> CodeSequence = {21760x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00, // lea <disp32>(%rip),2177// %rdi21780x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,21790x48, // movabs $__tls_get_addr@pltoff, %rax21800x01, 0xd8, // add %rbx, %rax21810xff, 0xd0 // call *%rax2182};2183ExpectedCodeSequence = ArrayRef<uint8_t>(CodeSequence);2184TLSSequenceOffset = 3;21852186// The replacement code for the large code model2187static const std::initializer_list<uint8_t> LargeSequence = {21880x66, 0x66, 0x66, // three data16 prefixes (no-op)21890x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00,21900x00, // 10 byte nop21910x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax2192};2193NewCodeSequence = ArrayRef<uint8_t>(LargeSequence);2194}2195} else {2196llvm_unreachable("both TLS relocations handled above");2197}21982199assert(ExpectedCodeSequence.size() == NewCodeSequence.size() &&2200"Old and new code sequences must have the same size");22012202auto &Section = Sections[SectionID];2203if (Offset < TLSSequenceOffset ||2204(Offset - TLSSequenceOffset + NewCodeSequence.size()) >2205Section.getSize()) {2206report_fatal_error("unexpected end of section in TLS sequence");2207}22082209auto *TLSSequence = Section.getAddressWithOffset(Offset - TLSSequenceOffset);2210if (ArrayRef<uint8_t>(TLSSequence, ExpectedCodeSequence.size()) !=2211ExpectedCodeSequence) {2212report_fatal_error(2213"invalid TLS sequence for Global/Local Dynamic TLS Model");2214}22152216memcpy(TLSSequence, NewCodeSequence.data(), NewCodeSequence.size());2217}22182219size_t RuntimeDyldELF::getGOTEntrySize() {2220// We don't use the GOT in all of these cases, but it's essentially free2221// to put them all here.2222size_t Result = 0;2223switch (Arch) {2224case Triple::x86_64:2225case Triple::aarch64:2226case Triple::aarch64_be:2227case Triple::ppc64:2228case Triple::ppc64le:2229case Triple::systemz:2230Result = sizeof(uint64_t);2231break;2232case Triple::x86:2233case Triple::arm:2234case Triple::thumb:2235Result = sizeof(uint32_t);2236break;2237case Triple::mips:2238case Triple::mipsel:2239case Triple::mips64:2240case Triple::mips64el:2241if (IsMipsO32ABI || IsMipsN32ABI)2242Result = sizeof(uint32_t);2243else if (IsMipsN64ABI)2244Result = sizeof(uint64_t);2245else2246llvm_unreachable("Mips ABI not handled");2247break;2248default:2249llvm_unreachable("Unsupported CPU type!");2250}2251return Result;2252}22532254uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned no) {2255if (GOTSectionID == 0) {2256GOTSectionID = Sections.size();2257// Reserve a section id. We'll allocate the section later2258// once we know the total size2259Sections.push_back(SectionEntry(".got", nullptr, 0, 0, 0));2260}2261uint64_t StartOffset = CurrentGOTIndex * getGOTEntrySize();2262CurrentGOTIndex += no;2263return StartOffset;2264}22652266uint64_t RuntimeDyldELF::findOrAllocGOTEntry(const RelocationValueRef &Value,2267unsigned GOTRelType) {2268auto E = GOTOffsetMap.insert({Value, 0});2269if (E.second) {2270uint64_t GOTOffset = allocateGOTEntries(1);22712272// Create relocation for newly created GOT entry2273RelocationEntry RE =2274computeGOTOffsetRE(GOTOffset, Value.Offset, GOTRelType);2275if (Value.SymbolName)2276addRelocationForSymbol(RE, Value.SymbolName);2277else2278addRelocationForSection(RE, Value.SectionID);22792280E.first->second = GOTOffset;2281}22822283return E.first->second;2284}22852286void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID,2287uint64_t Offset,2288uint64_t GOTOffset,2289uint32_t Type) {2290// Fill in the relative address of the GOT Entry into the stub2291RelocationEntry GOTRE(SectionID, Offset, Type, GOTOffset);2292addRelocationForSection(GOTRE, GOTSectionID);2293}22942295RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(uint64_t GOTOffset,2296uint64_t SymbolOffset,2297uint32_t Type) {2298return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset);2299}23002301void RuntimeDyldELF::processNewSymbol(const SymbolRef &ObjSymbol, SymbolTableEntry& Symbol) {2302// This should never return an error as `processNewSymbol` wouldn't have been2303// called if getFlags() returned an error before.2304auto ObjSymbolFlags = cantFail(ObjSymbol.getFlags());23052306if (ObjSymbolFlags & SymbolRef::SF_Indirect) {2307if (IFuncStubSectionID == 0) {2308// Create a dummy section for the ifunc stubs. It will be actually2309// allocated in finalizeLoad() below.2310IFuncStubSectionID = Sections.size();2311Sections.push_back(2312SectionEntry(".text.__llvm_IFuncStubs", nullptr, 0, 0, 0));2313// First 64B are reserverd for the IFunc resolver2314IFuncStubOffset = 64;2315}23162317IFuncStubs.push_back(IFuncStub{IFuncStubOffset, Symbol});2318// Modify the symbol so that it points to the ifunc stub instead of to the2319// resolver function.2320Symbol = SymbolTableEntry(IFuncStubSectionID, IFuncStubOffset,2321Symbol.getFlags());2322IFuncStubOffset += getMaxIFuncStubSize();2323}2324}23252326Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,2327ObjSectionToIDMap &SectionMap) {2328if (IsMipsO32ABI)2329if (!PendingRelocs.empty())2330return make_error<RuntimeDyldError>("Can't find matching LO16 reloc");23312332// Create the IFunc stubs if necessary. This must be done before processing2333// the GOT entries, as the IFunc stubs may create some.2334if (IFuncStubSectionID != 0) {2335uint8_t *IFuncStubsAddr = MemMgr.allocateCodeSection(2336IFuncStubOffset, 1, IFuncStubSectionID, ".text.__llvm_IFuncStubs");2337if (!IFuncStubsAddr)2338return make_error<RuntimeDyldError>(2339"Unable to allocate memory for IFunc stubs!");2340Sections[IFuncStubSectionID] =2341SectionEntry(".text.__llvm_IFuncStubs", IFuncStubsAddr, IFuncStubOffset,2342IFuncStubOffset, 0);23432344createIFuncResolver(IFuncStubsAddr);23452346LLVM_DEBUG(dbgs() << "Creating IFunc stubs SectionID: "2347<< IFuncStubSectionID << " Addr: "2348<< Sections[IFuncStubSectionID].getAddress() << '\n');2349for (auto &IFuncStub : IFuncStubs) {2350auto &Symbol = IFuncStub.OriginalSymbol;2351LLVM_DEBUG(dbgs() << "\tSectionID: " << Symbol.getSectionID()2352<< " Offset: " << format("%p", Symbol.getOffset())2353<< " IFuncStubOffset: "2354<< format("%p\n", IFuncStub.StubOffset));2355createIFuncStub(IFuncStubSectionID, 0, IFuncStub.StubOffset,2356Symbol.getSectionID(), Symbol.getOffset());2357}23582359IFuncStubSectionID = 0;2360IFuncStubOffset = 0;2361IFuncStubs.clear();2362}23632364// If necessary, allocate the global offset table2365if (GOTSectionID != 0) {2366// Allocate memory for the section2367size_t TotalSize = CurrentGOTIndex * getGOTEntrySize();2368uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(),2369GOTSectionID, ".got", false);2370if (!Addr)2371return make_error<RuntimeDyldError>("Unable to allocate memory for GOT!");23722373Sections[GOTSectionID] =2374SectionEntry(".got", Addr, TotalSize, TotalSize, 0);23752376// For now, initialize all GOT entries to zero. We'll fill them in as2377// needed when GOT-based relocations are applied.2378memset(Addr, 0, TotalSize);2379if (IsMipsN32ABI || IsMipsN64ABI) {2380// To correctly resolve Mips GOT relocations, we need a mapping from2381// object's sections to GOTs.2382for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();2383SI != SE; ++SI) {2384if (SI->relocation_begin() != SI->relocation_end()) {2385Expected<section_iterator> RelSecOrErr = SI->getRelocatedSection();2386if (!RelSecOrErr)2387return make_error<RuntimeDyldError>(2388toString(RelSecOrErr.takeError()));23892390section_iterator RelocatedSection = *RelSecOrErr;2391ObjSectionToIDMap::iterator i = SectionMap.find(*RelocatedSection);2392assert(i != SectionMap.end());2393SectionToGOTMap[i->second] = GOTSectionID;2394}2395}2396GOTSymbolOffsets.clear();2397}2398}23992400// Look for and record the EH frame section.2401ObjSectionToIDMap::iterator i, e;2402for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {2403const SectionRef &Section = i->first;24042405StringRef Name;2406Expected<StringRef> NameOrErr = Section.getName();2407if (NameOrErr)2408Name = *NameOrErr;2409else2410consumeError(NameOrErr.takeError());24112412if (Name == ".eh_frame") {2413UnregisteredEHFrameSections.push_back(i->second);2414break;2415}2416}24172418GOTOffsetMap.clear();2419GOTSectionID = 0;2420CurrentGOTIndex = 0;24212422return Error::success();2423}24242425bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {2426return Obj.isELF();2427}24282429void RuntimeDyldELF::createIFuncResolver(uint8_t *Addr) const {2430if (Arch == Triple::x86_64) {2431// The adddres of the GOT1 entry is in %r11, the GOT2 entry is in %r11+82432// (see createIFuncStub() for details)2433// The following code first saves all registers that contain the original2434// function arguments as those registers are not saved by the resolver2435// function. %r11 is saved as well so that the GOT2 entry can be updated2436// afterwards. Then it calls the actual IFunc resolver function whose2437// address is stored in GOT2. After the resolver function returns, all2438// saved registers are restored and the return value is written to GOT1.2439// Finally, jump to the now resolved function.2440// clang-format off2441const uint8_t StubCode[] = {24420x57, // push %rdi24430x56, // push %rsi24440x52, // push %rdx24450x51, // push %rcx24460x41, 0x50, // push %r824470x41, 0x51, // push %r924480x41, 0x53, // push %r1124490x41, 0xff, 0x53, 0x08, // call *0x8(%r11)24500x41, 0x5b, // pop %r1124510x41, 0x59, // pop %r924520x41, 0x58, // pop %r824530x59, // pop %rcx24540x5a, // pop %rdx24550x5e, // pop %rsi24560x5f, // pop %rdi24570x49, 0x89, 0x03, // mov %rax,(%r11)24580xff, 0xe0 // jmp *%rax2459};2460// clang-format on2461static_assert(sizeof(StubCode) <= 64,2462"maximum size of the IFunc resolver is 64B");2463memcpy(Addr, StubCode, sizeof(StubCode));2464} else {2465report_fatal_error(2466"IFunc resolver is not supported for target architecture");2467}2468}24692470void RuntimeDyldELF::createIFuncStub(unsigned IFuncStubSectionID,2471uint64_t IFuncResolverOffset,2472uint64_t IFuncStubOffset,2473unsigned IFuncSectionID,2474uint64_t IFuncOffset) {2475auto &IFuncStubSection = Sections[IFuncStubSectionID];2476auto *Addr = IFuncStubSection.getAddressWithOffset(IFuncStubOffset);24772478if (Arch == Triple::x86_64) {2479// The first instruction loads a PC-relative address into %r11 which is a2480// GOT entry for this stub. This initially contains the address to the2481// IFunc resolver. We can use %r11 here as it's caller saved but not used2482// to pass any arguments. In fact, x86_64 ABI even suggests using %r11 for2483// code in the PLT. The IFunc resolver will use %r11 to update the GOT2484// entry.2485//2486// The next instruction just jumps to the address contained in the GOT2487// entry. As mentioned above, we do this two-step jump by first setting2488// %r11 so that the IFunc resolver has access to it.2489//2490// The IFunc resolver of course also needs to know the actual address of2491// the actual IFunc resolver function. This will be stored in a GOT entry2492// right next to the first one for this stub. So, the IFunc resolver will2493// be able to call it with %r11+8.2494//2495// In total, two adjacent GOT entries (+relocation) and one additional2496// relocation are required:2497// GOT1: Address of the IFunc resolver.2498// GOT2: Address of the IFunc resolver function.2499// IFuncStubOffset+3: 32-bit PC-relative address of GOT1.2500uint64_t GOT1 = allocateGOTEntries(2);2501uint64_t GOT2 = GOT1 + getGOTEntrySize();25022503RelocationEntry RE1(GOTSectionID, GOT1, ELF::R_X86_64_64,2504IFuncResolverOffset, {});2505addRelocationForSection(RE1, IFuncStubSectionID);2506RelocationEntry RE2(GOTSectionID, GOT2, ELF::R_X86_64_64, IFuncOffset, {});2507addRelocationForSection(RE2, IFuncSectionID);25082509const uint8_t StubCode[] = {25100x4c, 0x8d, 0x1d, 0x00, 0x00, 0x00, 0x00, // leaq 0x0(%rip),%r1125110x41, 0xff, 0x23 // jmpq *(%r11)2512};2513assert(sizeof(StubCode) <= getMaxIFuncStubSize() &&2514"IFunc stub size must not exceed getMaxIFuncStubSize()");2515memcpy(Addr, StubCode, sizeof(StubCode));25162517// The PC-relative value starts 4 bytes from the end of the leaq2518// instruction, so the addend is -4.2519resolveGOTOffsetRelocation(IFuncStubSectionID, IFuncStubOffset + 3,2520GOT1 - 4, ELF::R_X86_64_PC32);2521} else {2522report_fatal_error("IFunc stub is not supported for target architecture");2523}2524}25252526unsigned RuntimeDyldELF::getMaxIFuncStubSize() const {2527if (Arch == Triple::x86_64) {2528return 10;2529}2530return 0;2531}25322533bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {2534unsigned RelTy = R.getType();2535if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)2536return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE ||2537RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC;25382539if (Arch == Triple::x86_64)2540return RelTy == ELF::R_X86_64_GOTPCREL ||2541RelTy == ELF::R_X86_64_GOTPCRELX ||2542RelTy == ELF::R_X86_64_GOT64 ||2543RelTy == ELF::R_X86_64_REX_GOTPCRELX;2544return false;2545}25462547bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const {2548if (Arch != Triple::x86_64)2549return true; // Conservative answer25502551switch (R.getType()) {2552default:2553return true; // Conservative answer255425552556case ELF::R_X86_64_GOTPCREL:2557case ELF::R_X86_64_GOTPCRELX:2558case ELF::R_X86_64_REX_GOTPCRELX:2559case ELF::R_X86_64_GOTPC64:2560case ELF::R_X86_64_GOT64:2561case ELF::R_X86_64_GOTOFF64:2562case ELF::R_X86_64_PC32:2563case ELF::R_X86_64_PC64:2564case ELF::R_X86_64_64:2565// We know that these reloation types won't need a stub function. This list2566// can be extended as needed.2567return false;2568}2569}25702571} // namespace llvm257225732574