|  | //===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Implementation of ELF support for the MC-JIT runtime dynamic linker. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "RuntimeDyldELF.h" | 
|  | #include "RuntimeDyldCheckerImpl.h" | 
|  | #include "Targets/RuntimeDyldELFMips.h" | 
|  | #include "llvm/ADT/IntervalMap.h" | 
|  | #include "llvm/ADT/STLExtras.h" | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/ADT/Triple.h" | 
|  | #include "llvm/BinaryFormat/ELF.h" | 
|  | #include "llvm/MC/MCStreamer.h" | 
|  | #include "llvm/Object/ELFObjectFile.h" | 
|  | #include "llvm/Object/ObjectFile.h" | 
|  | #include "llvm/Support/Endian.h" | 
|  | #include "llvm/Support/MemoryBuffer.h" | 
|  | #include "llvm/Support/TargetRegistry.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::object; | 
|  | using namespace llvm::support::endian; | 
|  |  | 
|  | #define DEBUG_TYPE "dyld" | 
|  |  | 
|  | static void or32le(void *P, int32_t V) { write32le(P, read32le(P) | V); } | 
|  |  | 
|  | static void or32AArch64Imm(void *L, uint64_t Imm) { | 
|  | or32le(L, (Imm & 0xFFF) << 10); | 
|  | } | 
|  |  | 
|  | template <class T> static void write(bool isBE, void *P, T V) { | 
|  | isBE ? write<T, support::big>(P, V) : write<T, support::little>(P, V); | 
|  | } | 
|  |  | 
|  | static void write32AArch64Addr(void *L, uint64_t Imm) { | 
|  | uint32_t ImmLo = (Imm & 0x3) << 29; | 
|  | uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; | 
|  | uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); | 
|  | write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi); | 
|  | } | 
|  |  | 
|  | // Return the bits [Start, End] from Val shifted Start bits. | 
|  | // For instance, getBits(0xF0, 4, 8) returns 0xF. | 
|  | static uint64_t getBits(uint64_t Val, int Start, int End) { | 
|  | uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1; | 
|  | return (Val >> Start) & Mask; | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { | 
|  | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) | 
|  |  | 
|  | typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; | 
|  | typedef Elf_Sym_Impl<ELFT> Elf_Sym; | 
|  | typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; | 
|  | typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; | 
|  |  | 
|  | typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; | 
|  |  | 
|  | typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; | 
|  |  | 
|  | public: | 
|  | DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec); | 
|  |  | 
|  | void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); | 
|  |  | 
|  | void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr); | 
|  |  | 
|  | // Methods for type inquiry through isa, cast and dyn_cast | 
|  | static bool classof(const Binary *v) { | 
|  | return (isa<ELFObjectFile<ELFT>>(v) && | 
|  | classof(cast<ELFObjectFile<ELFT>>(v))); | 
|  | } | 
|  | static bool classof(const ELFObjectFile<ELFT> *v) { | 
|  | return v->isDyldType(); | 
|  | } | 
|  | }; | 
|  |  | 
|  |  | 
|  |  | 
|  | // The MemoryBuffer passed into this constructor is just a wrapper around the | 
|  | // actual memory.  Ultimately, the Binary parent class will take ownership of | 
|  | // this MemoryBuffer object but not the underlying memory. | 
|  | template <class ELFT> | 
|  | DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC) | 
|  | : ELFObjectFile<ELFT>(Wrapper, EC) { | 
|  | this->isDyldELFObject = true; | 
|  | } | 
|  |  | 
|  | template <class ELFT> | 
|  | void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec, | 
|  | uint64_t Addr) { | 
|  | DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); | 
|  | Elf_Shdr *shdr = | 
|  | const_cast<Elf_Shdr *>(reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); | 
|  |  | 
|  | // This assumes the address passed in matches the target address bitness | 
|  | // The template-based type cast handles everything else. | 
|  | shdr->sh_addr = static_cast<addr_type>(Addr); | 
|  | } | 
|  |  | 
|  | template <class ELFT> | 
|  | void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, | 
|  | uint64_t Addr) { | 
|  |  | 
|  | Elf_Sym *sym = const_cast<Elf_Sym *>( | 
|  | ELFObjectFile<ELFT>::getSymbol(SymRef.getRawDataRefImpl())); | 
|  |  | 
|  | // This assumes the address passed in matches the target address bitness | 
|  | // The template-based type cast handles everything else. | 
|  | sym->st_value = static_cast<addr_type>(Addr); | 
|  | } | 
|  |  | 
|  | class LoadedELFObjectInfo final | 
|  | : public LoadedObjectInfoHelper<LoadedELFObjectInfo, | 
|  | RuntimeDyld::LoadedObjectInfo> { | 
|  | public: | 
|  | LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap) | 
|  | : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {} | 
|  |  | 
|  | OwningBinary<ObjectFile> | 
|  | getObjectForDebug(const ObjectFile &Obj) const override; | 
|  | }; | 
|  |  | 
|  | template <typename ELFT> | 
|  | std::unique_ptr<DyldELFObject<ELFT>> | 
|  | createRTDyldELFObject(MemoryBufferRef Buffer, | 
|  | const ObjectFile &SourceObject, | 
|  | const LoadedELFObjectInfo &L, | 
|  | std::error_code &ec) { | 
|  | typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; | 
|  | typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; | 
|  |  | 
|  | std::unique_ptr<DyldELFObject<ELFT>> Obj = | 
|  | llvm::make_unique<DyldELFObject<ELFT>>(Buffer, ec); | 
|  |  | 
|  | // Iterate over all sections in the object. | 
|  | auto SI = SourceObject.section_begin(); | 
|  | for (const auto &Sec : Obj->sections()) { | 
|  | StringRef SectionName; | 
|  | Sec.getName(SectionName); | 
|  | if (SectionName != "") { | 
|  | DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); | 
|  | Elf_Shdr *shdr = const_cast<Elf_Shdr *>( | 
|  | reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); | 
|  |  | 
|  | if (uint64_t SecLoadAddr = L.getSectionLoadAddress(*SI)) { | 
|  | // This assumes that the address passed in matches the target address | 
|  | // bitness. The template-based type cast handles everything else. | 
|  | shdr->sh_addr = static_cast<addr_type>(SecLoadAddr); | 
|  | } | 
|  | } | 
|  | ++SI; | 
|  | } | 
|  |  | 
|  | return Obj; | 
|  | } | 
|  |  | 
|  | OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj, | 
|  | const LoadedELFObjectInfo &L) { | 
|  | assert(Obj.isELF() && "Not an ELF object file."); | 
|  |  | 
|  | std::unique_ptr<MemoryBuffer> Buffer = | 
|  | MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName()); | 
|  |  | 
|  | std::error_code ec; | 
|  |  | 
|  | std::unique_ptr<ObjectFile> DebugObj; | 
|  | if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) { | 
|  | typedef ELFType<support::little, false> ELF32LE; | 
|  | DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), Obj, L, | 
|  | ec); | 
|  | } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) { | 
|  | typedef ELFType<support::big, false> ELF32BE; | 
|  | DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), Obj, L, | 
|  | ec); | 
|  | } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) { | 
|  | typedef ELFType<support::big, true> ELF64BE; | 
|  | DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), Obj, L, | 
|  | ec); | 
|  | } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) { | 
|  | typedef ELFType<support::little, true> ELF64LE; | 
|  | DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), Obj, L, | 
|  | ec); | 
|  | } else | 
|  | llvm_unreachable("Unexpected ELF format"); | 
|  |  | 
|  | assert(!ec && "Could not construct copy ELF object file"); | 
|  |  | 
|  | return OwningBinary<ObjectFile>(std::move(DebugObj), std::move(Buffer)); | 
|  | } | 
|  |  | 
|  | OwningBinary<ObjectFile> | 
|  | LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { | 
|  | return createELFDebugObject(Obj, *this); | 
|  | } | 
|  |  | 
|  | } // anonymous namespace | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, | 
|  | JITSymbolResolver &Resolver) | 
|  | : RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0), CurrentGOTIndex(0) {} | 
|  | RuntimeDyldELF::~RuntimeDyldELF() {} | 
|  |  | 
|  | void RuntimeDyldELF::registerEHFrames() { | 
|  | for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { | 
|  | SID EHFrameSID = UnregisteredEHFrameSections[i]; | 
|  | uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress(); | 
|  | uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress(); | 
|  | size_t EHFrameSize = Sections[EHFrameSID].getSize(); | 
|  | MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); | 
|  | } | 
|  | UnregisteredEHFrameSections.clear(); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<RuntimeDyldELF> | 
|  | llvm::RuntimeDyldELF::create(Triple::ArchType Arch, | 
|  | RuntimeDyld::MemoryManager &MemMgr, | 
|  | JITSymbolResolver &Resolver) { | 
|  | switch (Arch) { | 
|  | default: | 
|  | return make_unique<RuntimeDyldELF>(MemMgr, Resolver); | 
|  | case Triple::mips: | 
|  | case Triple::mipsel: | 
|  | case Triple::mips64: | 
|  | case Triple::mips64el: | 
|  | return make_unique<RuntimeDyldELFMips>(MemMgr, Resolver); | 
|  | } | 
|  | } | 
|  |  | 
|  | std::unique_ptr<RuntimeDyld::LoadedObjectInfo> | 
|  | RuntimeDyldELF::loadObject(const object::ObjectFile &O) { | 
|  | if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) | 
|  | return llvm::make_unique<LoadedELFObjectInfo>(*this, *ObjSectionToIDOrErr); | 
|  | else { | 
|  | HasError = true; | 
|  | raw_string_ostream ErrStream(ErrorStr); | 
|  | logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, ""); | 
|  | return nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend, | 
|  | uint64_t SymOffset) { | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | case ELF::R_X86_64_NONE: | 
|  | break; | 
|  | case ELF::R_X86_64_64: { | 
|  | support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = | 
|  | Value + Addend; | 
|  | DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " | 
|  | << format("%p\n", Section.getAddressWithOffset(Offset))); | 
|  | break; | 
|  | } | 
|  | case ELF::R_X86_64_32: | 
|  | case ELF::R_X86_64_32S: { | 
|  | Value += Addend; | 
|  | assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) || | 
|  | (Type == ELF::R_X86_64_32S && | 
|  | ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN))); | 
|  | uint32_t TruncatedAddr = (Value & 0xFFFFFFFF); | 
|  | support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = | 
|  | TruncatedAddr; | 
|  | DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at " | 
|  | << format("%p\n", Section.getAddressWithOffset(Offset))); | 
|  | break; | 
|  | } | 
|  | case ELF::R_X86_64_PC8: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | int64_t RealOffset = Value + Addend - FinalAddress; | 
|  | assert(isInt<8>(RealOffset)); | 
|  | int8_t TruncOffset = (RealOffset & 0xFF); | 
|  | Section.getAddress()[Offset] = TruncOffset; | 
|  | break; | 
|  | } | 
|  | case ELF::R_X86_64_PC32: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | int64_t RealOffset = Value + Addend - FinalAddress; | 
|  | assert(isInt<32>(RealOffset)); | 
|  | int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); | 
|  | support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = | 
|  | TruncOffset; | 
|  | break; | 
|  | } | 
|  | case ELF::R_X86_64_PC64: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | int64_t RealOffset = Value + Addend - FinalAddress; | 
|  | support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = | 
|  | RealOffset; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint32_t Value, | 
|  | uint32_t Type, int32_t Addend) { | 
|  | switch (Type) { | 
|  | case ELF::R_386_32: { | 
|  | support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = | 
|  | Value + Addend; | 
|  | break; | 
|  | } | 
|  | case ELF::R_386_PC32: { | 
|  | uint32_t FinalAddress = | 
|  | Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF; | 
|  | uint32_t RealOffset = Value + Addend - FinalAddress; | 
|  | support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) = | 
|  | RealOffset; | 
|  | break; | 
|  | } | 
|  | default: | 
|  | // There are other relocation types, but it appears these are the | 
|  | // only ones currently used by the LLVM ELF object writer | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend) { | 
|  | uint32_t *TargetPtr = | 
|  | reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset)); | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | // Data should use target endian. Code should always use little endian. | 
|  | bool isBE = Arch == Triple::aarch64_be; | 
|  |  | 
|  | DEBUG(dbgs() << "resolveAArch64Relocation, LocalAddress: 0x" | 
|  | << format("%llx", Section.getAddressWithOffset(Offset)) | 
|  | << " FinalAddress: 0x" << format("%llx", FinalAddress) | 
|  | << " Value: 0x" << format("%llx", Value) << " Type: 0x" | 
|  | << format("%x", Type) << " Addend: 0x" << format("%llx", Addend) | 
|  | << "\n"); | 
|  |  | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | case ELF::R_AARCH64_ABS64: | 
|  | write(isBE, TargetPtr, Value + Addend); | 
|  | break; | 
|  | case ELF::R_AARCH64_PREL32: { | 
|  | uint64_t Result = Value + Addend - FinalAddress; | 
|  | assert(static_cast<int64_t>(Result) >= INT32_MIN && | 
|  | static_cast<int64_t>(Result) <= UINT32_MAX); | 
|  | write(isBE, TargetPtr, static_cast<uint32_t>(Result & 0xffffffffU)); | 
|  | break; | 
|  | } | 
|  | case ELF::R_AARCH64_PREL64: | 
|  | write(isBE, TargetPtr, Value + Addend - FinalAddress); | 
|  | break; | 
|  | case ELF::R_AARCH64_CALL26: // fallthrough | 
|  | case ELF::R_AARCH64_JUMP26: { | 
|  | // Operation: S+A-P. Set Call or B immediate value to bits fff_fffc of the | 
|  | // calculation. | 
|  | uint64_t BranchImm = Value + Addend - FinalAddress; | 
|  |  | 
|  | // "Check that -2^27 <= result < 2^27". | 
|  | assert(isInt<28>(BranchImm)); | 
|  | or32le(TargetPtr, (BranchImm & 0x0FFFFFFC) >> 2); | 
|  | break; | 
|  | } | 
|  | case ELF::R_AARCH64_MOVW_UABS_G3: | 
|  | or32le(TargetPtr, ((Value + Addend) & 0xFFFF000000000000) >> 43); | 
|  | break; | 
|  | case ELF::R_AARCH64_MOVW_UABS_G2_NC: | 
|  | or32le(TargetPtr, ((Value + Addend) & 0xFFFF00000000) >> 27); | 
|  | break; | 
|  | case ELF::R_AARCH64_MOVW_UABS_G1_NC: | 
|  | or32le(TargetPtr, ((Value + Addend) & 0xFFFF0000) >> 11); | 
|  | break; | 
|  | case ELF::R_AARCH64_MOVW_UABS_G0_NC: | 
|  | or32le(TargetPtr, ((Value + Addend) & 0xFFFF) << 5); | 
|  | break; | 
|  | case ELF::R_AARCH64_ADR_PREL_PG_HI21: { | 
|  | // Operation: Page(S+A) - Page(P) | 
|  | uint64_t Result = | 
|  | ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); | 
|  |  | 
|  | // Check that -2^32 <= X < 2^32 | 
|  | assert(isInt<33>(Result) && "overflow check failed for relocation"); | 
|  |  | 
|  | // Immediate goes in bits 30:29 + 5:23 of ADRP instruction, taken | 
|  | // from bits 32:12 of X. | 
|  | write32AArch64Addr(TargetPtr, Result >> 12); | 
|  | break; | 
|  | } | 
|  | case ELF::R_AARCH64_ADD_ABS_LO12_NC: | 
|  | // Operation: S + A | 
|  | // Immediate goes in bits 21:10 of LD/ST instruction, taken | 
|  | // from bits 11:0 of X | 
|  | or32AArch64Imm(TargetPtr, Value + Addend); | 
|  | break; | 
|  | case ELF::R_AARCH64_LDST8_ABS_LO12_NC: | 
|  | // Operation: S + A | 
|  | // Immediate goes in bits 21:10 of LD/ST instruction, taken | 
|  | // from bits 11:0 of X | 
|  | or32AArch64Imm(TargetPtr, getBits(Value + Addend, 0, 11)); | 
|  | break; | 
|  | case ELF::R_AARCH64_LDST16_ABS_LO12_NC: | 
|  | // Operation: S + A | 
|  | // Immediate goes in bits 21:10 of LD/ST instruction, taken | 
|  | // from bits 11:1 of X | 
|  | or32AArch64Imm(TargetPtr, getBits(Value + Addend, 1, 11)); | 
|  | break; | 
|  | case ELF::R_AARCH64_LDST32_ABS_LO12_NC: | 
|  | // Operation: S + A | 
|  | // Immediate goes in bits 21:10 of LD/ST instruction, taken | 
|  | // from bits 11:2 of X | 
|  | or32AArch64Imm(TargetPtr, getBits(Value + Addend, 2, 11)); | 
|  | break; | 
|  | case ELF::R_AARCH64_LDST64_ABS_LO12_NC: | 
|  | // Operation: S + A | 
|  | // Immediate goes in bits 21:10 of LD/ST instruction, taken | 
|  | // from bits 11:3 of X | 
|  | or32AArch64Imm(TargetPtr, getBits(Value + Addend, 3, 11)); | 
|  | break; | 
|  | case ELF::R_AARCH64_LDST128_ABS_LO12_NC: | 
|  | // Operation: S + A | 
|  | // Immediate goes in bits 21:10 of LD/ST instruction, taken | 
|  | // from bits 11:4 of X | 
|  | or32AArch64Imm(TargetPtr, getBits(Value + Addend, 4, 11)); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint32_t Value, | 
|  | uint32_t Type, int32_t Addend) { | 
|  | // TODO: Add Thumb relocations. | 
|  | uint32_t *TargetPtr = | 
|  | reinterpret_cast<uint32_t *>(Section.getAddressWithOffset(Offset)); | 
|  | uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset) & 0xFFFFFFFF; | 
|  | Value += Addend; | 
|  |  | 
|  | DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " | 
|  | << Section.getAddressWithOffset(Offset) | 
|  | << " FinalAddress: " << format("%p", FinalAddress) << " Value: " | 
|  | << format("%x", Value) << " Type: " << format("%x", Type) | 
|  | << " Addend: " << format("%x", Addend) << "\n"); | 
|  |  | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Not implemented relocation type!"); | 
|  |  | 
|  | case ELF::R_ARM_NONE: | 
|  | break; | 
|  | // Write a 31bit signed offset | 
|  | case ELF::R_ARM_PREL31: | 
|  | support::ulittle32_t::ref{TargetPtr} = | 
|  | (support::ulittle32_t::ref{TargetPtr} & 0x80000000) | | 
|  | ((Value - FinalAddress) & ~0x80000000); | 
|  | break; | 
|  | case ELF::R_ARM_TARGET1: | 
|  | case ELF::R_ARM_ABS32: | 
|  | support::ulittle32_t::ref{TargetPtr} = Value; | 
|  | break; | 
|  | // Write first 16 bit of 32 bit value to the mov instruction. | 
|  | // Last 4 bit should be shifted. | 
|  | case ELF::R_ARM_MOVW_ABS_NC: | 
|  | case ELF::R_ARM_MOVT_ABS: | 
|  | if (Type == ELF::R_ARM_MOVW_ABS_NC) | 
|  | Value = Value & 0xFFFF; | 
|  | else if (Type == ELF::R_ARM_MOVT_ABS) | 
|  | Value = (Value >> 16) & 0xFFFF; | 
|  | support::ulittle32_t::ref{TargetPtr} = | 
|  | (support::ulittle32_t::ref{TargetPtr} & ~0x000F0FFF) | (Value & 0xFFF) | | 
|  | (((Value >> 12) & 0xF) << 16); | 
|  | break; | 
|  | // Write 24 bit relative value to the branch instruction. | 
|  | case ELF::R_ARM_PC24: // Fall through. | 
|  | case ELF::R_ARM_CALL: // Fall through. | 
|  | case ELF::R_ARM_JUMP24: | 
|  | int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); | 
|  | RelValue = (RelValue & 0x03FFFFFC) >> 2; | 
|  | assert((support::ulittle32_t::ref{TargetPtr} & 0xFFFFFF) == 0xFFFFFE); | 
|  | support::ulittle32_t::ref{TargetPtr} = | 
|  | (support::ulittle32_t::ref{TargetPtr} & 0xFF000000) | RelValue; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) { | 
|  | if (Arch == Triple::UnknownArch || | 
|  | !StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) { | 
|  | IsMipsO32ABI = false; | 
|  | IsMipsN32ABI = false; | 
|  | IsMipsN64ABI = false; | 
|  | return; | 
|  | } | 
|  | unsigned AbiVariant; | 
|  | Obj.getPlatformFlags(AbiVariant); | 
|  | IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32; | 
|  | IsMipsN32ABI = AbiVariant & ELF::EF_MIPS_ABI2; | 
|  | IsMipsN64ABI = Obj.getFileFormatName().equals("ELF64-mips"); | 
|  | } | 
|  |  | 
|  | // Return the .TOC. section and offset. | 
|  | Error RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj, | 
|  | ObjSectionToIDMap &LocalSections, | 
|  | RelocationValueRef &Rel) { | 
|  | // Set a default SectionID in case we do not find a TOC section below. | 
|  | // This may happen for references to TOC base base (sym@toc, .odp | 
|  | // relocation) without a .toc directive.  In this case just use the | 
|  | // first section (which is usually the .odp) since the code won't | 
|  | // reference the .toc base directly. | 
|  | Rel.SymbolName = nullptr; | 
|  | Rel.SectionID = 0; | 
|  |  | 
|  | // The TOC consists of sections .got, .toc, .tocbss, .plt in that | 
|  | // order. The TOC starts where the first of these sections starts. | 
|  | for (auto &Section: Obj.sections()) { | 
|  | StringRef SectionName; | 
|  | if (auto EC = Section.getName(SectionName)) | 
|  | return errorCodeToError(EC); | 
|  |  | 
|  | if (SectionName == ".got" | 
|  | || SectionName == ".toc" | 
|  | || SectionName == ".tocbss" | 
|  | || SectionName == ".plt") { | 
|  | if (auto SectionIDOrErr = | 
|  | findOrEmitSection(Obj, Section, false, LocalSections)) | 
|  | Rel.SectionID = *SectionIDOrErr; | 
|  | else | 
|  | return SectionIDOrErr.takeError(); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 | 
|  | // thus permitting a full 64 Kbytes segment. | 
|  | Rel.Addend = 0x8000; | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | // Returns the sections and offset associated with the ODP entry referenced | 
|  | // by Symbol. | 
|  | Error RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, | 
|  | ObjSectionToIDMap &LocalSections, | 
|  | RelocationValueRef &Rel) { | 
|  | // Get the ELF symbol value (st_value) to compare with Relocation offset in | 
|  | // .opd entries | 
|  | for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); | 
|  | si != se; ++si) { | 
|  | section_iterator RelSecI = si->getRelocatedSection(); | 
|  | if (RelSecI == Obj.section_end()) | 
|  | continue; | 
|  |  | 
|  | StringRef RelSectionName; | 
|  | if (auto EC = RelSecI->getName(RelSectionName)) | 
|  | return errorCodeToError(EC); | 
|  |  | 
|  | if (RelSectionName != ".opd") | 
|  | continue; | 
|  |  | 
|  | for (elf_relocation_iterator i = si->relocation_begin(), | 
|  | e = si->relocation_end(); | 
|  | i != e;) { | 
|  | // The R_PPC64_ADDR64 relocation indicates the first field | 
|  | // of a .opd entry | 
|  | uint64_t TypeFunc = i->getType(); | 
|  | if (TypeFunc != ELF::R_PPC64_ADDR64) { | 
|  | ++i; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | uint64_t TargetSymbolOffset = i->getOffset(); | 
|  | symbol_iterator TargetSymbol = i->getSymbol(); | 
|  | int64_t Addend; | 
|  | if (auto AddendOrErr = i->getAddend()) | 
|  | Addend = *AddendOrErr; | 
|  | else | 
|  | return errorCodeToError(AddendOrErr.getError()); | 
|  |  | 
|  | ++i; | 
|  | if (i == e) | 
|  | break; | 
|  |  | 
|  | // Just check if following relocation is a R_PPC64_TOC | 
|  | uint64_t TypeTOC = i->getType(); | 
|  | if (TypeTOC != ELF::R_PPC64_TOC) | 
|  | continue; | 
|  |  | 
|  | // Finally compares the Symbol value and the target symbol offset | 
|  | // to check if this .opd entry refers to the symbol the relocation | 
|  | // points to. | 
|  | if (Rel.Addend != (int64_t)TargetSymbolOffset) | 
|  | continue; | 
|  |  | 
|  | section_iterator TSI = Obj.section_end(); | 
|  | if (auto TSIOrErr = TargetSymbol->getSection()) | 
|  | TSI = *TSIOrErr; | 
|  | else | 
|  | return TSIOrErr.takeError(); | 
|  | assert(TSI != Obj.section_end() && "TSI should refer to a valid section"); | 
|  |  | 
|  | bool IsCode = TSI->isText(); | 
|  | if (auto SectionIDOrErr = findOrEmitSection(Obj, *TSI, IsCode, | 
|  | LocalSections)) | 
|  | Rel.SectionID = *SectionIDOrErr; | 
|  | else | 
|  | return SectionIDOrErr.takeError(); | 
|  | Rel.Addend = (intptr_t)Addend; | 
|  | return Error::success(); | 
|  | } | 
|  | } | 
|  | llvm_unreachable("Attempting to get address of ODP entry!"); | 
|  | } | 
|  |  | 
|  | // Relocation masks following the #lo(value), #hi(value), #ha(value), | 
|  | // #higher(value), #highera(value), #highest(value), and #highesta(value) | 
|  | // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi | 
|  | // document. | 
|  |  | 
|  | static inline uint16_t applyPPClo(uint64_t value) { return value & 0xffff; } | 
|  |  | 
|  | static inline uint16_t applyPPChi(uint64_t value) { | 
|  | return (value >> 16) & 0xffff; | 
|  | } | 
|  |  | 
|  | static inline uint16_t applyPPCha (uint64_t value) { | 
|  | return ((value + 0x8000) >> 16) & 0xffff; | 
|  | } | 
|  |  | 
|  | static inline uint16_t applyPPChigher(uint64_t value) { | 
|  | return (value >> 32) & 0xffff; | 
|  | } | 
|  |  | 
|  | static inline uint16_t applyPPChighera (uint64_t value) { | 
|  | return ((value + 0x8000) >> 32) & 0xffff; | 
|  | } | 
|  |  | 
|  | static inline uint16_t applyPPChighest(uint64_t value) { | 
|  | return (value >> 48) & 0xffff; | 
|  | } | 
|  |  | 
|  | static inline uint16_t applyPPChighesta (uint64_t value) { | 
|  | return ((value + 0x8000) >> 48) & 0xffff; | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolvePPC32Relocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend) { | 
|  | uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | case ELF::R_PPC_ADDR16_LO: | 
|  | writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC_ADDR16_HI: | 
|  | writeInt16BE(LocalAddress, applyPPChi(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC_ADDR16_HA: | 
|  | writeInt16BE(LocalAddress, applyPPCha(Value + Addend)); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend) { | 
|  | uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16: | 
|  | writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_DS: | 
|  | writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_LO: | 
|  | writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_LO_DS: | 
|  | writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_HI: | 
|  | writeInt16BE(LocalAddress, applyPPChi(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_HA: | 
|  | writeInt16BE(LocalAddress, applyPPCha(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_HIGHER: | 
|  | writeInt16BE(LocalAddress, applyPPChigher(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_HIGHERA: | 
|  | writeInt16BE(LocalAddress, applyPPChighera(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_HIGHEST: | 
|  | writeInt16BE(LocalAddress, applyPPChighest(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR16_HIGHESTA: | 
|  | writeInt16BE(LocalAddress, applyPPChighesta(Value + Addend)); | 
|  | break; | 
|  | case ELF::R_PPC64_ADDR14: { | 
|  | assert(((Value + Addend) & 3) == 0); | 
|  | // Preserve the AA/LK bits in the branch instruction | 
|  | uint8_t aalk = *(LocalAddress + 3); | 
|  | writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc)); | 
|  | } break; | 
|  | case ELF::R_PPC64_REL16_LO: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | uint64_t Delta = Value - FinalAddress + Addend; | 
|  | writeInt16BE(LocalAddress, applyPPClo(Delta)); | 
|  | } break; | 
|  | case ELF::R_PPC64_REL16_HI: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | uint64_t Delta = Value - FinalAddress + Addend; | 
|  | writeInt16BE(LocalAddress, applyPPChi(Delta)); | 
|  | } break; | 
|  | case ELF::R_PPC64_REL16_HA: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | uint64_t Delta = Value - FinalAddress + Addend; | 
|  | writeInt16BE(LocalAddress, applyPPCha(Delta)); | 
|  | } break; | 
|  | case ELF::R_PPC64_ADDR32: { | 
|  | int64_t Result = static_cast<int64_t>(Value + Addend); | 
|  | if (SignExtend64<32>(Result) != Result) | 
|  | llvm_unreachable("Relocation R_PPC64_ADDR32 overflow"); | 
|  | writeInt32BE(LocalAddress, Result); | 
|  | } break; | 
|  | case ELF::R_PPC64_REL24: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend); | 
|  | if (SignExtend64<26>(delta) != delta) | 
|  | llvm_unreachable("Relocation R_PPC64_REL24 overflow"); | 
|  | // Generates a 'bl <address>' instruction | 
|  | writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC)); | 
|  | } break; | 
|  | case ELF::R_PPC64_REL32: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | int64_t delta = static_cast<int64_t>(Value - FinalAddress + Addend); | 
|  | if (SignExtend64<32>(delta) != delta) | 
|  | llvm_unreachable("Relocation R_PPC64_REL32 overflow"); | 
|  | writeInt32BE(LocalAddress, delta); | 
|  | } break; | 
|  | case ELF::R_PPC64_REL64: { | 
|  | uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); | 
|  | uint64_t Delta = Value - FinalAddress + Addend; | 
|  | writeInt64BE(LocalAddress, Delta); | 
|  | } break; | 
|  | case ELF::R_PPC64_ADDR64: | 
|  | writeInt64BE(LocalAddress, Value + Addend); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend) { | 
|  | uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | case ELF::R_390_PC16DBL: | 
|  | case ELF::R_390_PLT16DBL: { | 
|  | int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); | 
|  | assert(int16_t(Delta / 2) * 2 == Delta && "R_390_PC16DBL overflow"); | 
|  | writeInt16BE(LocalAddress, Delta / 2); | 
|  | break; | 
|  | } | 
|  | case ELF::R_390_PC32DBL: | 
|  | case ELF::R_390_PLT32DBL: { | 
|  | int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); | 
|  | assert(int32_t(Delta / 2) * 2 == Delta && "R_390_PC32DBL overflow"); | 
|  | writeInt32BE(LocalAddress, Delta / 2); | 
|  | break; | 
|  | } | 
|  | case ELF::R_390_PC16: { | 
|  | int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); | 
|  | assert(int16_t(Delta) == Delta && "R_390_PC16 overflow"); | 
|  | writeInt16BE(LocalAddress, Delta); | 
|  | break; | 
|  | } | 
|  | case ELF::R_390_PC32: { | 
|  | int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); | 
|  | assert(int32_t(Delta) == Delta && "R_390_PC32 overflow"); | 
|  | writeInt32BE(LocalAddress, Delta); | 
|  | break; | 
|  | } | 
|  | case ELF::R_390_PC64: { | 
|  | int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); | 
|  | writeInt64BE(LocalAddress, Delta); | 
|  | break; | 
|  | } | 
|  | case ELF::R_390_8: | 
|  | *LocalAddress = (uint8_t)(Value + Addend); | 
|  | break; | 
|  | case ELF::R_390_16: | 
|  | writeInt16BE(LocalAddress, Value + Addend); | 
|  | break; | 
|  | case ELF::R_390_32: | 
|  | writeInt32BE(LocalAddress, Value + Addend); | 
|  | break; | 
|  | case ELF::R_390_64: | 
|  | writeInt64BE(LocalAddress, Value + Addend); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend) { | 
|  | bool isBE = Arch == Triple::bpfeb; | 
|  |  | 
|  | switch (Type) { | 
|  | default: | 
|  | llvm_unreachable("Relocation type not implemented yet!"); | 
|  | break; | 
|  | case ELF::R_BPF_NONE: | 
|  | break; | 
|  | case ELF::R_BPF_64_64: { | 
|  | write(isBE, Section.getAddressWithOffset(Offset), Value + Addend); | 
|  | DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " | 
|  | << format("%p\n", Section.getAddressWithOffset(Offset))); | 
|  | break; | 
|  | } | 
|  | case ELF::R_BPF_64_32: { | 
|  | Value += Addend; | 
|  | assert(Value <= UINT32_MAX); | 
|  | write(isBE, Section.getAddressWithOffset(Offset), static_cast<uint32_t>(Value)); | 
|  | DEBUG(dbgs() << "Writing " << format("%p", Value) << " at " | 
|  | << format("%p\n", Section.getAddressWithOffset(Offset))); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // The target location for the relocation is described by RE.SectionID and | 
|  | // RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each | 
|  | // SectionEntry has three members describing its location. | 
|  | // SectionEntry::Address is the address at which the section has been loaded | 
|  | // into memory in the current (host) process.  SectionEntry::LoadAddress is the | 
|  | // address that the section will have in the target process. | 
|  | // SectionEntry::ObjAddress is the address of the bits for this section in the | 
|  | // original emitted object image (also in the current address space). | 
|  | // | 
|  | // Relocations will be applied as if the section were loaded at | 
|  | // SectionEntry::LoadAddress, but they will be applied at an address based | 
|  | // on SectionEntry::Address.  SectionEntry::ObjAddress will be used to refer to | 
|  | // Target memory contents if they are required for value calculations. | 
|  | // | 
|  | // The Value parameter here is the load address of the symbol for the | 
|  | // relocation to be applied.  For relocations which refer to symbols in the | 
|  | // current object Value will be the LoadAddress of the section in which | 
|  | // the symbol resides (RE.Addend provides additional information about the | 
|  | // symbol location).  For external symbols, Value will be the address of the | 
|  | // symbol in the target address space. | 
|  | void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE, | 
|  | uint64_t Value) { | 
|  | const SectionEntry &Section = Sections[RE.SectionID]; | 
|  | return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend, | 
|  | RE.SymOffset, RE.SectionID); | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, | 
|  | uint64_t Offset, uint64_t Value, | 
|  | uint32_t Type, int64_t Addend, | 
|  | uint64_t SymOffset, SID SectionID) { | 
|  | switch (Arch) { | 
|  | case Triple::x86_64: | 
|  | resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset); | 
|  | break; | 
|  | case Triple::x86: | 
|  | resolveX86Relocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, | 
|  | (uint32_t)(Addend & 0xffffffffL)); | 
|  | break; | 
|  | case Triple::aarch64: | 
|  | case Triple::aarch64_be: | 
|  | resolveAArch64Relocation(Section, Offset, Value, Type, Addend); | 
|  | break; | 
|  | case Triple::arm: // Fall through. | 
|  | case Triple::armeb: | 
|  | case Triple::thumb: | 
|  | case Triple::thumbeb: | 
|  | resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, | 
|  | (uint32_t)(Addend & 0xffffffffL)); | 
|  | break; | 
|  | case Triple::ppc: | 
|  | resolvePPC32Relocation(Section, Offset, Value, Type, Addend); | 
|  | break; | 
|  | case Triple::ppc64: // Fall through. | 
|  | case Triple::ppc64le: | 
|  | resolvePPC64Relocation(Section, Offset, Value, Type, Addend); | 
|  | break; | 
|  | case Triple::systemz: | 
|  | resolveSystemZRelocation(Section, Offset, Value, Type, Addend); | 
|  | break; | 
|  | case Triple::bpfel: | 
|  | case Triple::bpfeb: | 
|  | resolveBPFRelocation(Section, Offset, Value, Type, Addend); | 
|  | break; | 
|  | default: | 
|  | llvm_unreachable("Unsupported CPU type!"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const { | 
|  | return (void *)(Sections[SectionID].getObjAddress() + Offset); | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value) { | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset); | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } | 
|  |  | 
|  | uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType, | 
|  | bool IsLocal) const { | 
|  | switch (RelType) { | 
|  | case ELF::R_MICROMIPS_GOT16: | 
|  | if (IsLocal) | 
|  | return ELF::R_MICROMIPS_LO16; | 
|  | break; | 
|  | case ELF::R_MICROMIPS_HI16: | 
|  | return ELF::R_MICROMIPS_LO16; | 
|  | case ELF::R_MIPS_GOT16: | 
|  | if (IsLocal) | 
|  | return ELF::R_MIPS_LO16; | 
|  | break; | 
|  | case ELF::R_MIPS_HI16: | 
|  | return ELF::R_MIPS_LO16; | 
|  | case ELF::R_MIPS_PCHI16: | 
|  | return ELF::R_MIPS_PCLO16; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | return ELF::R_MIPS_NONE; | 
|  | } | 
|  |  | 
|  | // Sometimes we don't need to create thunk for a branch. | 
|  | // This typically happens when branch target is located | 
|  | // in the same object file. In such case target is either | 
|  | // a weak symbol or symbol in a different executable section. | 
|  | // This function checks if branch target is located in the | 
|  | // same object file and if distance between source and target | 
|  | // fits R_AARCH64_CALL26 relocation. If both conditions are | 
|  | // met, it emits direct jump to the target and returns true. | 
|  | // Otherwise false is returned and thunk is created. | 
|  | bool RuntimeDyldELF::resolveAArch64ShortBranch( | 
|  | unsigned SectionID, relocation_iterator RelI, | 
|  | const RelocationValueRef &Value) { | 
|  | uint64_t Address; | 
|  | if (Value.SymbolName) { | 
|  | auto Loc = GlobalSymbolTable.find(Value.SymbolName); | 
|  |  | 
|  | // Don't create direct branch for external symbols. | 
|  | if (Loc == GlobalSymbolTable.end()) | 
|  | return false; | 
|  |  | 
|  | const auto &SymInfo = Loc->second; | 
|  | Address = | 
|  | uint64_t(Sections[SymInfo.getSectionID()].getLoadAddressWithOffset( | 
|  | SymInfo.getOffset())); | 
|  | } else { | 
|  | Address = uint64_t(Sections[Value.SectionID].getLoadAddress()); | 
|  | } | 
|  | uint64_t Offset = RelI->getOffset(); | 
|  | uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset); | 
|  |  | 
|  | // R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^27 | 
|  | // If distance between source and target is out of range then we should | 
|  | // create thunk. | 
|  | if (!isInt<28>(Address + Value.Addend - SourceAddress)) | 
|  | return false; | 
|  |  | 
|  | resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(), | 
|  | Value.Addend); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveAArch64Branch(unsigned SectionID, | 
|  | const RelocationValueRef &Value, | 
|  | relocation_iterator RelI, | 
|  | StubMap &Stubs) { | 
|  |  | 
|  | DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation."); | 
|  | SectionEntry &Section = Sections[SectionID]; | 
|  |  | 
|  | uint64_t Offset = RelI->getOffset(); | 
|  | unsigned RelType = RelI->getType(); | 
|  | // Look for an existing stub. | 
|  | StubMap::const_iterator i = Stubs.find(Value); | 
|  | if (i != Stubs.end()) { | 
|  | resolveRelocation(Section, Offset, | 
|  | (uint64_t)Section.getAddressWithOffset(i->second), | 
|  | RelType, 0); | 
|  | DEBUG(dbgs() << " Stub function found\n"); | 
|  | } else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) { | 
|  | // Create a new stub function. | 
|  | DEBUG(dbgs() << " Create a new stub function\n"); | 
|  | Stubs[Value] = Section.getStubOffset(); | 
|  | uint8_t *StubTargetAddr = createStubFunction( | 
|  | Section.getAddressWithOffset(Section.getStubOffset())); | 
|  |  | 
|  | RelocationEntry REmovz_g3(SectionID, StubTargetAddr - Section.getAddress(), | 
|  | ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend); | 
|  | RelocationEntry REmovk_g2(SectionID, | 
|  | StubTargetAddr - Section.getAddress() + 4, | 
|  | ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend); | 
|  | RelocationEntry REmovk_g1(SectionID, | 
|  | StubTargetAddr - Section.getAddress() + 8, | 
|  | ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend); | 
|  | RelocationEntry REmovk_g0(SectionID, | 
|  | StubTargetAddr - Section.getAddress() + 12, | 
|  | ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend); | 
|  |  | 
|  | if (Value.SymbolName) { | 
|  | addRelocationForSymbol(REmovz_g3, Value.SymbolName); | 
|  | addRelocationForSymbol(REmovk_g2, Value.SymbolName); | 
|  | addRelocationForSymbol(REmovk_g1, Value.SymbolName); | 
|  | addRelocationForSymbol(REmovk_g0, Value.SymbolName); | 
|  | } else { | 
|  | addRelocationForSection(REmovz_g3, Value.SectionID); | 
|  | addRelocationForSection(REmovk_g2, Value.SectionID); | 
|  | addRelocationForSection(REmovk_g1, Value.SectionID); | 
|  | addRelocationForSection(REmovk_g0, Value.SectionID); | 
|  | } | 
|  | resolveRelocation(Section, Offset, | 
|  | reinterpret_cast<uint64_t>(Section.getAddressWithOffset( | 
|  | Section.getStubOffset())), | 
|  | RelType, 0); | 
|  | Section.advanceStubOffset(getMaxStubSize()); | 
|  | } | 
|  | } | 
|  |  | 
|  | Expected<relocation_iterator> | 
|  | RuntimeDyldELF::processRelocationRef( | 
|  | unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, | 
|  | ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { | 
|  | const auto &Obj = cast<ELFObjectFileBase>(O); | 
|  | uint64_t RelType = RelI->getType(); | 
|  | ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(*RelI).getAddend(); | 
|  | int64_t Addend = AddendOrErr ? *AddendOrErr : 0; | 
|  | elf_symbol_iterator Symbol = RelI->getSymbol(); | 
|  |  | 
|  | // Obtain the symbol name which is referenced in the relocation | 
|  | StringRef TargetName; | 
|  | if (Symbol != Obj.symbol_end()) { | 
|  | if (auto TargetNameOrErr = Symbol->getName()) | 
|  | TargetName = *TargetNameOrErr; | 
|  | else | 
|  | return TargetNameOrErr.takeError(); | 
|  | } | 
|  | DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend | 
|  | << " TargetName: " << TargetName << "\n"); | 
|  | RelocationValueRef Value; | 
|  | // First search for the symbol in the local symbol table | 
|  | SymbolRef::Type SymType = SymbolRef::ST_Unknown; | 
|  |  | 
|  | // Search for the symbol in the global symbol table | 
|  | RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end(); | 
|  | if (Symbol != Obj.symbol_end()) { | 
|  | gsi = GlobalSymbolTable.find(TargetName.data()); | 
|  | Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType(); | 
|  | if (!SymTypeOrErr) { | 
|  | std::string Buf; | 
|  | raw_string_ostream OS(Buf); | 
|  | logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, ""); | 
|  | OS.flush(); | 
|  | report_fatal_error(Buf); | 
|  | } | 
|  | SymType = *SymTypeOrErr; | 
|  | } | 
|  | if (gsi != GlobalSymbolTable.end()) { | 
|  | const auto &SymInfo = gsi->second; | 
|  | Value.SectionID = SymInfo.getSectionID(); | 
|  | Value.Offset = SymInfo.getOffset(); | 
|  | Value.Addend = SymInfo.getOffset() + Addend; | 
|  | } else { | 
|  | switch (SymType) { | 
|  | case SymbolRef::ST_Debug: { | 
|  | // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously | 
|  | // and can be changed by another developers. Maybe best way is add | 
|  | // a new symbol type ST_Section to SymbolRef and use it. | 
|  | auto SectionOrErr = Symbol->getSection(); | 
|  | if (!SectionOrErr) { | 
|  | std::string Buf; | 
|  | raw_string_ostream OS(Buf); | 
|  | logAllUnhandledErrors(SectionOrErr.takeError(), OS, ""); | 
|  | OS.flush(); | 
|  | report_fatal_error(Buf); | 
|  | } | 
|  | section_iterator si = *SectionOrErr; | 
|  | if (si == Obj.section_end()) | 
|  | llvm_unreachable("Symbol section not found, bad object file format!"); | 
|  | DEBUG(dbgs() << "\t\tThis is section symbol\n"); | 
|  | bool isCode = si->isText(); | 
|  | if (auto SectionIDOrErr = findOrEmitSection(Obj, (*si), isCode, | 
|  | ObjSectionToID)) | 
|  | Value.SectionID = *SectionIDOrErr; | 
|  | else | 
|  | return SectionIDOrErr.takeError(); | 
|  | Value.Addend = Addend; | 
|  | break; | 
|  | } | 
|  | case SymbolRef::ST_Data: | 
|  | case SymbolRef::ST_Function: | 
|  | case SymbolRef::ST_Unknown: { | 
|  | Value.SymbolName = TargetName.data(); | 
|  | Value.Addend = Addend; | 
|  |  | 
|  | // Absolute relocations will have a zero symbol ID (STN_UNDEF), which | 
|  | // will manifest here as a NULL symbol name. | 
|  | // We can set this as a valid (but empty) symbol name, and rely | 
|  | // on addRelocationForSymbol to handle this. | 
|  | if (!Value.SymbolName) | 
|  | Value.SymbolName = ""; | 
|  | break; | 
|  | } | 
|  | default: | 
|  | llvm_unreachable("Unresolved symbol type!"); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | uint64_t Offset = RelI->getOffset(); | 
|  |  | 
|  | DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset | 
|  | << "\n"); | 
|  | if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be)) { | 
|  | if (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26) { | 
|  | resolveAArch64Branch(SectionID, Value, RelI, Stubs); | 
|  | } else if (RelType == ELF::R_AARCH64_ADR_GOT_PAGE) { | 
|  | // Craete new GOT entry or find existing one. If GOT entry is | 
|  | // to be created, then we also emit ABS64 relocation for it. | 
|  | uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64); | 
|  | resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, | 
|  | ELF::R_AARCH64_ADR_PREL_PG_HI21); | 
|  |  | 
|  | } else if (RelType == ELF::R_AARCH64_LD64_GOT_LO12_NC) { | 
|  | uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64); | 
|  | resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, | 
|  | ELF::R_AARCH64_LDST64_ABS_LO12_NC); | 
|  | } else { | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } | 
|  | } else if (Arch == Triple::arm) { | 
|  | if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL || | 
|  | RelType == ELF::R_ARM_JUMP24) { | 
|  | // This is an ARM branch relocation, need to use a stub function. | 
|  | DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.\n"); | 
|  | SectionEntry &Section = Sections[SectionID]; | 
|  |  | 
|  | // Look for an existing stub. | 
|  | StubMap::const_iterator i = Stubs.find(Value); | 
|  | if (i != Stubs.end()) { | 
|  | resolveRelocation( | 
|  | Section, Offset, | 
|  | reinterpret_cast<uint64_t>(Section.getAddressWithOffset(i->second)), | 
|  | RelType, 0); | 
|  | DEBUG(dbgs() << " Stub function found\n"); | 
|  | } else { | 
|  | // Create a new stub function. | 
|  | DEBUG(dbgs() << " Create a new stub function\n"); | 
|  | Stubs[Value] = Section.getStubOffset(); | 
|  | uint8_t *StubTargetAddr = createStubFunction( | 
|  | Section.getAddressWithOffset(Section.getStubOffset())); | 
|  | RelocationEntry RE(SectionID, StubTargetAddr - Section.getAddress(), | 
|  | ELF::R_ARM_ABS32, Value.Addend); | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  |  | 
|  | resolveRelocation(Section, Offset, reinterpret_cast<uint64_t>( | 
|  | Section.getAddressWithOffset( | 
|  | Section.getStubOffset())), | 
|  | RelType, 0); | 
|  | Section.advanceStubOffset(getMaxStubSize()); | 
|  | } | 
|  | } else { | 
|  | uint32_t *Placeholder = | 
|  | reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset)); | 
|  | if (RelType == ELF::R_ARM_PREL31 || RelType == ELF::R_ARM_TARGET1 || | 
|  | RelType == ELF::R_ARM_ABS32) { | 
|  | Value.Addend += *Placeholder; | 
|  | } else if (RelType == ELF::R_ARM_MOVW_ABS_NC || RelType == ELF::R_ARM_MOVT_ABS) { | 
|  | // See ELF for ARM documentation | 
|  | Value.Addend += (int16_t)((*Placeholder & 0xFFF) | (((*Placeholder >> 16) & 0xF) << 12)); | 
|  | } | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } | 
|  | } else if (IsMipsO32ABI) { | 
|  | uint8_t *Placeholder = reinterpret_cast<uint8_t *>( | 
|  | computePlaceholderAddress(SectionID, Offset)); | 
|  | uint32_t Opcode = readBytesUnaligned(Placeholder, 4); | 
|  | if (RelType == ELF::R_MIPS_26) { | 
|  | // This is an Mips branch relocation, need to use a stub function. | 
|  | DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); | 
|  | SectionEntry &Section = Sections[SectionID]; | 
|  |  | 
|  | // Extract the addend from the instruction. | 
|  | // We shift up by two since the Value will be down shifted again | 
|  | // when applying the relocation. | 
|  | uint32_t Addend = (Opcode & 0x03ffffff) << 2; | 
|  |  | 
|  | Value.Addend += Addend; | 
|  |  | 
|  | //  Look up for existing stub. | 
|  | StubMap::const_iterator i = Stubs.find(Value); | 
|  | if (i != Stubs.end()) { | 
|  | RelocationEntry RE(SectionID, Offset, RelType, i->second); | 
|  | addRelocationForSection(RE, SectionID); | 
|  | DEBUG(dbgs() << " Stub function found\n"); | 
|  | } else { | 
|  | // Create a new stub function. | 
|  | DEBUG(dbgs() << " Create a new stub function\n"); | 
|  | Stubs[Value] = Section.getStubOffset(); | 
|  |  | 
|  | unsigned AbiVariant; | 
|  | O.getPlatformFlags(AbiVariant); | 
|  |  | 
|  | uint8_t *StubTargetAddr = createStubFunction( | 
|  | Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant); | 
|  |  | 
|  | // Creating Hi and Lo relocations for the filled stub instructions. | 
|  | RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(), | 
|  | ELF::R_MIPS_HI16, Value.Addend); | 
|  | RelocationEntry RELo(SectionID, | 
|  | StubTargetAddr - Section.getAddress() + 4, | 
|  | ELF::R_MIPS_LO16, Value.Addend); | 
|  |  | 
|  | if (Value.SymbolName) { | 
|  | addRelocationForSymbol(REHi, Value.SymbolName); | 
|  | addRelocationForSymbol(RELo, Value.SymbolName); | 
|  | } | 
|  | else { | 
|  | addRelocationForSection(REHi, Value.SectionID); | 
|  | addRelocationForSection(RELo, Value.SectionID); | 
|  | } | 
|  |  | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset()); | 
|  | addRelocationForSection(RE, SectionID); | 
|  | Section.advanceStubOffset(getMaxStubSize()); | 
|  | } | 
|  | } else if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16) { | 
|  | int64_t Addend = (Opcode & 0x0000ffff) << 16; | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Addend); | 
|  | PendingRelocs.push_back(std::make_pair(Value, RE)); | 
|  | } else if (RelType == ELF::R_MIPS_LO16 || RelType == ELF::R_MIPS_PCLO16) { | 
|  | int64_t Addend = Value.Addend + SignExtend32<16>(Opcode & 0x0000ffff); | 
|  | for (auto I = PendingRelocs.begin(); I != PendingRelocs.end();) { | 
|  | const RelocationValueRef &MatchingValue = I->first; | 
|  | RelocationEntry &Reloc = I->second; | 
|  | if (MatchingValue == Value && | 
|  | RelType == getMatchingLoRelocation(Reloc.RelType) && | 
|  | SectionID == Reloc.SectionID) { | 
|  | Reloc.Addend += Addend; | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(Reloc, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(Reloc, Value.SectionID); | 
|  | I = PendingRelocs.erase(I); | 
|  | } else | 
|  | ++I; | 
|  | } | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Addend); | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } else { | 
|  | if (RelType == ELF::R_MIPS_32) | 
|  | Value.Addend += Opcode; | 
|  | else if (RelType == ELF::R_MIPS_PC16) | 
|  | Value.Addend += SignExtend32<18>((Opcode & 0x0000ffff) << 2); | 
|  | else if (RelType == ELF::R_MIPS_PC19_S2) | 
|  | Value.Addend += SignExtend32<21>((Opcode & 0x0007ffff) << 2); | 
|  | else if (RelType == ELF::R_MIPS_PC21_S2) | 
|  | Value.Addend += SignExtend32<23>((Opcode & 0x001fffff) << 2); | 
|  | else if (RelType == ELF::R_MIPS_PC26_S2) | 
|  | Value.Addend += SignExtend32<28>((Opcode & 0x03ffffff) << 2); | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } | 
|  | } else if (IsMipsN32ABI || IsMipsN64ABI) { | 
|  | uint32_t r_type = RelType & 0xff; | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); | 
|  | if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE | 
|  | || r_type == ELF::R_MIPS_GOT_DISP) { | 
|  | StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName); | 
|  | if (i != GOTSymbolOffsets.end()) | 
|  | RE.SymOffset = i->second; | 
|  | else { | 
|  | RE.SymOffset = allocateGOTEntries(1); | 
|  | GOTSymbolOffsets[TargetName] = RE.SymOffset; | 
|  | } | 
|  | } | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { | 
|  | if (RelType == ELF::R_PPC64_REL24) { | 
|  | // Determine ABI variant in use for this object. | 
|  | unsigned AbiVariant; | 
|  | Obj.getPlatformFlags(AbiVariant); | 
|  | AbiVariant &= ELF::EF_PPC64_ABI; | 
|  | // A PPC branch relocation will need a stub function if the target is | 
|  | // an external symbol (either Value.SymbolName is set, or SymType is | 
|  | // Symbol::ST_Unknown) or if the target address is not within the | 
|  | // signed 24-bits branch address. | 
|  | SectionEntry &Section = Sections[SectionID]; | 
|  | uint8_t *Target = Section.getAddressWithOffset(Offset); | 
|  | bool RangeOverflow = false; | 
|  | if (!Value.SymbolName && SymType != SymbolRef::ST_Unknown) { | 
|  | if (AbiVariant != 2) { | 
|  | // In the ELFv1 ABI, a function call may point to the .opd entry, | 
|  | // so the final symbol value is calculated based on the relocation | 
|  | // values in the .opd section. | 
|  | if (auto Err = findOPDEntrySection(Obj, ObjSectionToID, Value)) | 
|  | return std::move(Err); | 
|  | } else { | 
|  | // In the ELFv2 ABI, a function symbol may provide a local entry | 
|  | // point, which must be used for direct calls. | 
|  | uint8_t SymOther = Symbol->getOther(); | 
|  | Value.Addend += ELF::decodePPC64LocalEntryOffset(SymOther); | 
|  | } | 
|  | uint8_t *RelocTarget = | 
|  | Sections[Value.SectionID].getAddressWithOffset(Value.Addend); | 
|  | int64_t delta = static_cast<int64_t>(Target - RelocTarget); | 
|  | // If it is within 26-bits branch range, just set the branch target | 
|  | if (SignExtend64<26>(delta) == delta) { | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } else { | 
|  | RangeOverflow = true; | 
|  | } | 
|  | } | 
|  | if (Value.SymbolName || SymType == SymbolRef::ST_Unknown || | 
|  | RangeOverflow) { | 
|  | // It is an external symbol (either Value.SymbolName is set, or | 
|  | // SymType is SymbolRef::ST_Unknown) or out of range. | 
|  | StubMap::const_iterator i = Stubs.find(Value); | 
|  | if (i != Stubs.end()) { | 
|  | // Symbol function stub already created, just relocate to it | 
|  | resolveRelocation(Section, Offset, | 
|  | reinterpret_cast<uint64_t>( | 
|  | Section.getAddressWithOffset(i->second)), | 
|  | RelType, 0); | 
|  | DEBUG(dbgs() << " Stub function found\n"); | 
|  | } else { | 
|  | // Create a new stub function. | 
|  | DEBUG(dbgs() << " Create a new stub function\n"); | 
|  | Stubs[Value] = Section.getStubOffset(); | 
|  | uint8_t *StubTargetAddr = createStubFunction( | 
|  | Section.getAddressWithOffset(Section.getStubOffset()), | 
|  | AbiVariant); | 
|  | RelocationEntry RE(SectionID, StubTargetAddr - Section.getAddress(), | 
|  | ELF::R_PPC64_ADDR64, Value.Addend); | 
|  |  | 
|  | // Generates the 64-bits address loads as exemplified in section | 
|  | // 4.5.1 in PPC64 ELF ABI.  Note that the relocations need to | 
|  | // apply to the low part of the instructions, so we have to update | 
|  | // the offset according to the target endianness. | 
|  | uint64_t StubRelocOffset = StubTargetAddr - Section.getAddress(); | 
|  | if (!IsTargetLittleEndian) | 
|  | StubRelocOffset += 2; | 
|  |  | 
|  | RelocationEntry REhst(SectionID, StubRelocOffset + 0, | 
|  | ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend); | 
|  | RelocationEntry REhr(SectionID, StubRelocOffset + 4, | 
|  | ELF::R_PPC64_ADDR16_HIGHER, Value.Addend); | 
|  | RelocationEntry REh(SectionID, StubRelocOffset + 12, | 
|  | ELF::R_PPC64_ADDR16_HI, Value.Addend); | 
|  | RelocationEntry REl(SectionID, StubRelocOffset + 16, | 
|  | ELF::R_PPC64_ADDR16_LO, Value.Addend); | 
|  |  | 
|  | if (Value.SymbolName) { | 
|  | addRelocationForSymbol(REhst, Value.SymbolName); | 
|  | addRelocationForSymbol(REhr, Value.SymbolName); | 
|  | addRelocationForSymbol(REh, Value.SymbolName); | 
|  | addRelocationForSymbol(REl, Value.SymbolName); | 
|  | } else { | 
|  | addRelocationForSection(REhst, Value.SectionID); | 
|  | addRelocationForSection(REhr, Value.SectionID); | 
|  | addRelocationForSection(REh, Value.SectionID); | 
|  | addRelocationForSection(REl, Value.SectionID); | 
|  | } | 
|  |  | 
|  | resolveRelocation(Section, Offset, reinterpret_cast<uint64_t>( | 
|  | Section.getAddressWithOffset( | 
|  | Section.getStubOffset())), | 
|  | RelType, 0); | 
|  | Section.advanceStubOffset(getMaxStubSize()); | 
|  | } | 
|  | if (Value.SymbolName || SymType == SymbolRef::ST_Unknown) { | 
|  | // Restore the TOC for external calls | 
|  | if (AbiVariant == 2) | 
|  | writeInt32BE(Target + 4, 0xE8410018); // ld r2,28(r1) | 
|  | else | 
|  | writeInt32BE(Target + 4, 0xE8410028); // ld r2,40(r1) | 
|  | } | 
|  | } | 
|  | } else if (RelType == ELF::R_PPC64_TOC16 || | 
|  | RelType == ELF::R_PPC64_TOC16_DS || | 
|  | RelType == ELF::R_PPC64_TOC16_LO || | 
|  | RelType == ELF::R_PPC64_TOC16_LO_DS || | 
|  | RelType == ELF::R_PPC64_TOC16_HI || | 
|  | RelType == ELF::R_PPC64_TOC16_HA) { | 
|  | // These relocations are supposed to subtract the TOC address from | 
|  | // the final value.  This does not fit cleanly into the RuntimeDyld | 
|  | // scheme, since there may be *two* sections involved in determining | 
|  | // the relocation value (the section of the symbol referred to by the | 
|  | // relocation, and the TOC section associated with the current module). | 
|  | // | 
|  | // Fortunately, these relocations are currently only ever generated | 
|  | // referring to symbols that themselves reside in the TOC, which means | 
|  | // that the two sections are actually the same.  Thus they cancel out | 
|  | // and we can immediately resolve the relocation right now. | 
|  | switch (RelType) { | 
|  | case ELF::R_PPC64_TOC16: RelType = ELF::R_PPC64_ADDR16; break; | 
|  | case ELF::R_PPC64_TOC16_DS: RelType = ELF::R_PPC64_ADDR16_DS; break; | 
|  | case ELF::R_PPC64_TOC16_LO: RelType = ELF::R_PPC64_ADDR16_LO; break; | 
|  | case ELF::R_PPC64_TOC16_LO_DS: RelType = ELF::R_PPC64_ADDR16_LO_DS; break; | 
|  | case ELF::R_PPC64_TOC16_HI: RelType = ELF::R_PPC64_ADDR16_HI; break; | 
|  | case ELF::R_PPC64_TOC16_HA: RelType = ELF::R_PPC64_ADDR16_HA; break; | 
|  | default: llvm_unreachable("Wrong relocation type."); | 
|  | } | 
|  |  | 
|  | RelocationValueRef TOCValue; | 
|  | if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, TOCValue)) | 
|  | return std::move(Err); | 
|  | if (Value.SymbolName || Value.SectionID != TOCValue.SectionID) | 
|  | llvm_unreachable("Unsupported TOC relocation."); | 
|  | Value.Addend -= TOCValue.Addend; | 
|  | resolveRelocation(Sections[SectionID], Offset, Value.Addend, RelType, 0); | 
|  | } else { | 
|  | // There are two ways to refer to the TOC address directly: either | 
|  | // via a ELF::R_PPC64_TOC relocation (where both symbol and addend are | 
|  | // ignored), or via any relocation that refers to the magic ".TOC." | 
|  | // symbols (in which case the addend is respected). | 
|  | if (RelType == ELF::R_PPC64_TOC) { | 
|  | RelType = ELF::R_PPC64_ADDR64; | 
|  | if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value)) | 
|  | return std::move(Err); | 
|  | } else if (TargetName == ".TOC.") { | 
|  | if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value)) | 
|  | return std::move(Err); | 
|  | Value.Addend += Addend; | 
|  | } | 
|  |  | 
|  | RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); | 
|  |  | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } | 
|  | } else if (Arch == Triple::systemz && | 
|  | (RelType == ELF::R_390_PLT32DBL || RelType == ELF::R_390_GOTENT)) { | 
|  | // Create function stubs for both PLT and GOT references, regardless of | 
|  | // whether the GOT reference is to data or code.  The stub contains the | 
|  | // full address of the symbol, as needed by GOT references, and the | 
|  | // executable part only adds an overhead of 8 bytes. | 
|  | // | 
|  | // We could try to conserve space by allocating the code and data | 
|  | // parts of the stub separately.  However, as things stand, we allocate | 
|  | // a stub for every relocation, so using a GOT in JIT code should be | 
|  | // no less space efficient than using an explicit constant pool. | 
|  | DEBUG(dbgs() << "\t\tThis is a SystemZ indirect relocation."); | 
|  | SectionEntry &Section = Sections[SectionID]; | 
|  |  | 
|  | // Look for an existing stub. | 
|  | StubMap::const_iterator i = Stubs.find(Value); | 
|  | uintptr_t StubAddress; | 
|  | if (i != Stubs.end()) { | 
|  | StubAddress = uintptr_t(Section.getAddressWithOffset(i->second)); | 
|  | DEBUG(dbgs() << " Stub function found\n"); | 
|  | } else { | 
|  | // Create a new stub function. | 
|  | DEBUG(dbgs() << " Create a new stub function\n"); | 
|  |  | 
|  | uintptr_t BaseAddress = uintptr_t(Section.getAddress()); | 
|  | uintptr_t StubAlignment = getStubAlignment(); | 
|  | StubAddress = | 
|  | (BaseAddress + Section.getStubOffset() + StubAlignment - 1) & | 
|  | -StubAlignment; | 
|  | unsigned StubOffset = StubAddress - BaseAddress; | 
|  |  | 
|  | Stubs[Value] = StubOffset; | 
|  | createStubFunction((uint8_t *)StubAddress); | 
|  | RelocationEntry RE(SectionID, StubOffset + 8, ELF::R_390_64, | 
|  | Value.Offset); | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | Section.advanceStubOffset(getMaxStubSize()); | 
|  | } | 
|  |  | 
|  | if (RelType == ELF::R_390_GOTENT) | 
|  | resolveRelocation(Section, Offset, StubAddress + 8, ELF::R_390_PC32DBL, | 
|  | Addend); | 
|  | else | 
|  | resolveRelocation(Section, Offset, StubAddress, RelType, Addend); | 
|  | } else if (Arch == Triple::x86_64) { | 
|  | if (RelType == ELF::R_X86_64_PLT32) { | 
|  | // The way the PLT relocations normally work is that the linker allocates | 
|  | // the | 
|  | // PLT and this relocation makes a PC-relative call into the PLT.  The PLT | 
|  | // entry will then jump to an address provided by the GOT.  On first call, | 
|  | // the | 
|  | // GOT address will point back into PLT code that resolves the symbol. After | 
|  | // the first call, the GOT entry points to the actual function. | 
|  | // | 
|  | // For local functions we're ignoring all of that here and just replacing | 
|  | // the PLT32 relocation type with PC32, which will translate the relocation | 
|  | // into a PC-relative call directly to the function. For external symbols we | 
|  | // can't be sure the function will be within 2^32 bytes of the call site, so | 
|  | // we need to create a stub, which calls into the GOT.  This case is | 
|  | // equivalent to the usual PLT implementation except that we use the stub | 
|  | // mechanism in RuntimeDyld (which puts stubs at the end of the section) | 
|  | // rather than allocating a PLT section. | 
|  | if (Value.SymbolName) { | 
|  | // This is a call to an external function. | 
|  | // Look for an existing stub. | 
|  | SectionEntry &Section = Sections[SectionID]; | 
|  | StubMap::const_iterator i = Stubs.find(Value); | 
|  | uintptr_t StubAddress; | 
|  | if (i != Stubs.end()) { | 
|  | StubAddress = uintptr_t(Section.getAddress()) + i->second; | 
|  | DEBUG(dbgs() << " Stub function found\n"); | 
|  | } else { | 
|  | // Create a new stub function (equivalent to a PLT entry). | 
|  | DEBUG(dbgs() << " Create a new stub function\n"); | 
|  |  | 
|  | uintptr_t BaseAddress = uintptr_t(Section.getAddress()); | 
|  | uintptr_t StubAlignment = getStubAlignment(); | 
|  | StubAddress = | 
|  | (BaseAddress + Section.getStubOffset() + StubAlignment - 1) & | 
|  | -StubAlignment; | 
|  | unsigned StubOffset = StubAddress - BaseAddress; | 
|  | Stubs[Value] = StubOffset; | 
|  | createStubFunction((uint8_t *)StubAddress); | 
|  |  | 
|  | // Bump our stub offset counter | 
|  | Section.advanceStubOffset(getMaxStubSize()); | 
|  |  | 
|  | // Allocate a GOT Entry | 
|  | uint64_t GOTOffset = allocateGOTEntries(1); | 
|  |  | 
|  | // The load of the GOT address has an addend of -4 | 
|  | resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4, | 
|  | ELF::R_X86_64_PC32); | 
|  |  | 
|  | // Fill in the value of the symbol we're targeting into the GOT | 
|  | addRelocationForSymbol( | 
|  | computeGOTOffsetRE(GOTOffset, 0, ELF::R_X86_64_64), | 
|  | Value.SymbolName); | 
|  | } | 
|  |  | 
|  | // Make the target call a call into the stub table. | 
|  | resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32, | 
|  | Addend); | 
|  | } else { | 
|  | RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend, | 
|  | Value.Offset); | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } | 
|  | } else if (RelType == ELF::R_X86_64_GOTPCREL || | 
|  | RelType == ELF::R_X86_64_GOTPCRELX || | 
|  | RelType == ELF::R_X86_64_REX_GOTPCRELX) { | 
|  | uint64_t GOTOffset = allocateGOTEntries(1); | 
|  | resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, | 
|  | ELF::R_X86_64_PC32); | 
|  |  | 
|  | // Fill in the value of the symbol we're targeting into the GOT | 
|  | RelocationEntry RE = | 
|  | computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64); | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  | } else if (RelType == ELF::R_X86_64_PC32) { | 
|  | Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } else if (RelType == ELF::R_X86_64_PC64) { | 
|  | Value.Addend += support::ulittle64_t::ref(computePlaceholderAddress(SectionID, Offset)); | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } else { | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } | 
|  | } else { | 
|  | if (Arch == Triple::x86) { | 
|  | Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); | 
|  | } | 
|  | processSimpleRelocation(SectionID, Offset, RelType, Value); | 
|  | } | 
|  | return ++RelI; | 
|  | } | 
|  |  | 
|  | size_t RuntimeDyldELF::getGOTEntrySize() { | 
|  | // We don't use the GOT in all of these cases, but it's essentially free | 
|  | // to put them all here. | 
|  | size_t Result = 0; | 
|  | switch (Arch) { | 
|  | case Triple::x86_64: | 
|  | case Triple::aarch64: | 
|  | case Triple::aarch64_be: | 
|  | case Triple::ppc64: | 
|  | case Triple::ppc64le: | 
|  | case Triple::systemz: | 
|  | Result = sizeof(uint64_t); | 
|  | break; | 
|  | case Triple::x86: | 
|  | case Triple::arm: | 
|  | case Triple::thumb: | 
|  | Result = sizeof(uint32_t); | 
|  | break; | 
|  | case Triple::mips: | 
|  | case Triple::mipsel: | 
|  | case Triple::mips64: | 
|  | case Triple::mips64el: | 
|  | if (IsMipsO32ABI || IsMipsN32ABI) | 
|  | Result = sizeof(uint32_t); | 
|  | else if (IsMipsN64ABI) | 
|  | Result = sizeof(uint64_t); | 
|  | else | 
|  | llvm_unreachable("Mips ABI not handled"); | 
|  | break; | 
|  | default: | 
|  | llvm_unreachable("Unsupported CPU type!"); | 
|  | } | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned no) { | 
|  | if (GOTSectionID == 0) { | 
|  | GOTSectionID = Sections.size(); | 
|  | // Reserve a section id. We'll allocate the section later | 
|  | // once we know the total size | 
|  | Sections.push_back(SectionEntry(".got", nullptr, 0, 0, 0)); | 
|  | } | 
|  | uint64_t StartOffset = CurrentGOTIndex * getGOTEntrySize(); | 
|  | CurrentGOTIndex += no; | 
|  | return StartOffset; | 
|  | } | 
|  |  | 
|  | uint64_t RuntimeDyldELF::findOrAllocGOTEntry(const RelocationValueRef &Value, | 
|  | unsigned GOTRelType) { | 
|  | auto E = GOTOffsetMap.insert({Value, 0}); | 
|  | if (E.second) { | 
|  | uint64_t GOTOffset = allocateGOTEntries(1); | 
|  |  | 
|  | // Create relocation for newly created GOT entry | 
|  | RelocationEntry RE = | 
|  | computeGOTOffsetRE(GOTOffset, Value.Offset, GOTRelType); | 
|  | if (Value.SymbolName) | 
|  | addRelocationForSymbol(RE, Value.SymbolName); | 
|  | else | 
|  | addRelocationForSection(RE, Value.SectionID); | 
|  |  | 
|  | E.first->second = GOTOffset; | 
|  | } | 
|  |  | 
|  | return E.first->second; | 
|  | } | 
|  |  | 
|  | void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, | 
|  | uint64_t Offset, | 
|  | uint64_t GOTOffset, | 
|  | uint32_t Type) { | 
|  | // Fill in the relative address of the GOT Entry into the stub | 
|  | RelocationEntry GOTRE(SectionID, Offset, Type, GOTOffset); | 
|  | addRelocationForSection(GOTRE, GOTSectionID); | 
|  | } | 
|  |  | 
|  | RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(uint64_t GOTOffset, | 
|  | uint64_t SymbolOffset, | 
|  | uint32_t Type) { | 
|  | return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset); | 
|  | } | 
|  |  | 
|  | Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, | 
|  | ObjSectionToIDMap &SectionMap) { | 
|  | if (IsMipsO32ABI) | 
|  | if (!PendingRelocs.empty()) | 
|  | return make_error<RuntimeDyldError>("Can't find matching LO16 reloc"); | 
|  |  | 
|  | // If necessary, allocate the global offset table | 
|  | if (GOTSectionID != 0) { | 
|  | // Allocate memory for the section | 
|  | size_t TotalSize = CurrentGOTIndex * getGOTEntrySize(); | 
|  | uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(), | 
|  | GOTSectionID, ".got", false); | 
|  | if (!Addr) | 
|  | return make_error<RuntimeDyldError>("Unable to allocate memory for GOT!"); | 
|  |  | 
|  | Sections[GOTSectionID] = | 
|  | SectionEntry(".got", Addr, TotalSize, TotalSize, 0); | 
|  |  | 
|  | if (Checker) | 
|  | Checker->registerSection(Obj.getFileName(), GOTSectionID); | 
|  |  | 
|  | // For now, initialize all GOT entries to zero.  We'll fill them in as | 
|  | // needed when GOT-based relocations are applied. | 
|  | memset(Addr, 0, TotalSize); | 
|  | if (IsMipsN32ABI || IsMipsN64ABI) { | 
|  | // To correctly resolve Mips GOT relocations, we need a mapping from | 
|  | // object's sections to GOTs. | 
|  | for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); | 
|  | SI != SE; ++SI) { | 
|  | if (SI->relocation_begin() != SI->relocation_end()) { | 
|  | section_iterator RelocatedSection = SI->getRelocatedSection(); | 
|  | ObjSectionToIDMap::iterator i = SectionMap.find(*RelocatedSection); | 
|  | assert (i != SectionMap.end()); | 
|  | SectionToGOTMap[i->second] = GOTSectionID; | 
|  | } | 
|  | } | 
|  | GOTSymbolOffsets.clear(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Look for and record the EH frame section. | 
|  | ObjSectionToIDMap::iterator i, e; | 
|  | for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { | 
|  | const SectionRef &Section = i->first; | 
|  | StringRef Name; | 
|  | Section.getName(Name); | 
|  | if (Name == ".eh_frame") { | 
|  | UnregisteredEHFrameSections.push_back(i->second); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | GOTSectionID = 0; | 
|  | CurrentGOTIndex = 0; | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { | 
|  | return Obj.isELF(); | 
|  | } | 
|  |  | 
|  | bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const { | 
|  | unsigned RelTy = R.getType(); | 
|  | if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) | 
|  | return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE || | 
|  | RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC; | 
|  |  | 
|  | if (Arch == Triple::x86_64) | 
|  | return RelTy == ELF::R_X86_64_GOTPCREL || | 
|  | RelTy == ELF::R_X86_64_GOTPCRELX || | 
|  | RelTy == ELF::R_X86_64_REX_GOTPCRELX; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const { | 
|  | if (Arch != Triple::x86_64) | 
|  | return true;  // Conservative answer | 
|  |  | 
|  | switch (R.getType()) { | 
|  | default: | 
|  | return true;  // Conservative answer | 
|  |  | 
|  |  | 
|  | case ELF::R_X86_64_GOTPCREL: | 
|  | case ELF::R_X86_64_GOTPCRELX: | 
|  | case ELF::R_X86_64_REX_GOTPCRELX: | 
|  | case ELF::R_X86_64_PC32: | 
|  | case ELF::R_X86_64_PC64: | 
|  | case ELF::R_X86_64_64: | 
|  | // We know that these reloation types won't need a stub function.  This list | 
|  | // can be extended as needed. | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | } // namespace llvm |