diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
| commit | 5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch) | |
| tree | a6140557876943cdd800ee997c9317283394b22c /lib/ExecutionEngine/RuntimeDyld | |
| parent | f03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff) | |
Notes
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld')
16 files changed, 938 insertions, 495 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt index 12bbcc61db7e..e78408a3b6ae 100644 --- a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt +++ b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_library(LLVMRuntimeDyld RTDyldMemoryManager.cpp RuntimeDyld.cpp RuntimeDyldChecker.cpp + RuntimeDyldCOFF.cpp RuntimeDyldELF.cpp RuntimeDyldMachO.cpp ) diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 304014edb247..24a3ec19aed4 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -13,10 +13,12 @@ #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "RuntimeDyldCheckerImpl.h" +#include "RuntimeDyldCOFF.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldMachO.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MutexGuard.h" @@ -55,7 +57,8 @@ static void dumpSectionMemory(const SectionEntry &S, StringRef State) { unsigned BytesRemaining = S.Size; if (StartPadding) { - dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr & ~(ColsPerRow - 1)) << ":"; + dbgs() << "\n" << format("0x%016" PRIx64, + LoadAddr & ~(uint64_t)(ColsPerRow - 1)) << ":"; while (StartPadding--) dbgs() << " "; } @@ -90,7 +93,7 @@ void RuntimeDyldImpl::resolveRelocations() { // entry provides the section to which the relocation will be applied. uint64_t Addr = Sections[i].LoadAddress; DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t" - << format("0x%x", Addr) << "\n"); + << format("%p", (uintptr_t)Addr) << "\n"); DEBUG(dumpSectionMemory(Sections[i], "before relocations")); resolveRelocationList(Relocations[i], Addr); DEBUG(dumpSectionMemory(Sections[i], "after relocations")); @@ -149,68 +152,65 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager - if (MemMgr->needsToReserveAllocationSpace()) { + if (MemMgr.needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW); - MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + MemMgr.reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments - CommonSymbolMap CommonSymbols; - // Maximum required total memory to allocate all common symbols - uint64_t CommonSize = 0; + CommonSymbolList CommonSymbols; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - object::SymbolRef::Type SymType; - StringRef Name; - Check(I->getType(SymType)); - Check(I->getName(Name)); - uint32_t Flags = I->getFlags(); bool IsCommon = Flags & SymbolRef::SF_Common; - if (IsCommon) { - // Add the common symbols to a list. We'll allocate them all below. - if (!GlobalSymbolTable.count(Name)) { - uint32_t Align; - Check(I->getAlignment(Align)); - uint64_t Size = 0; - Check(I->getSize(Size)); - CommonSize += Size + Align; - CommonSymbols[*I] = CommonSymbolInfo(Size, Align); - } - } else { + if (IsCommon) + CommonSymbols.push_back(*I); + else { + object::SymbolRef::Type SymType; + Check(I->getType(SymType)); + if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { + + StringRef Name; uint64_t SectOffset; - StringRef SectionData; - section_iterator SI = Obj.section_end(); + Check(I->getName(Name)); Check(getOffset(*I, SectOffset)); + section_iterator SI = Obj.section_end(); Check(I->getSection(SI)); if (SI == Obj.section_end()) continue; + StringRef SectionData; Check(SI->getContents(SectionData)); bool IsCode = SI->isText(); unsigned SectionID = findOrEmitSection(Obj, *SI, IsCode, LocalSections); - DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << " SID: " << SectionID); - GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name + << " SID: " << SectionID << " Offset: " + << format("%p", (uintptr_t)SectOffset) + << " flags: " << Flags << "\n"); + JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; + if (Flags & SymbolRef::SF_Weak) + RTDyldSymFlags |= JITSymbolFlags::Weak; + if (Flags & SymbolRef::SF_Exported) + RTDyldSymFlags |= JITSymbolFlags::Exported; + GlobalSymbolTable[Name] = + SymbolTableEntry(SectionID, SectOffset, RTDyldSymFlags); } } - DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols - if (CommonSize != 0) - emitCommonSymbols(Obj, CommonSymbols, CommonSize, GlobalSymbolTable); + emitCommonSymbols(Obj, CommonSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); @@ -220,6 +220,9 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); + if (RelocatedSection == SE) + continue; + relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); @@ -267,6 +270,20 @@ static bool isRequiredForExecution(const SectionRef &Section) { const ObjectFile *Obj = Section.getObject(); if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) return ELFObj->getSectionFlags(Section) & ELF::SHF_ALLOC; + if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) { + const coff_section *CoffSection = COFFObj->getCOFFSection(Section); + // Avoid loading zero-sized COFF sections. + // In PE files, VirtualSize gives the section size, and SizeOfRawData + // may be zero for sections with content. In Obj files, SizeOfRawData + // gives the section size, and VirtualSize is always zero. Hence + // the need to check for both cases below. + bool HasContent = (CoffSection->VirtualSize > 0) + || (CoffSection->SizeOfRawData > 0); + bool IsDiscardable = CoffSection->Characteristics & + (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO); + return HasContent && !IsDiscardable; + } + assert(isa<MachOObjectFile>(Obj)); return true; } @@ -276,6 +293,15 @@ static bool isReadOnlyData(const SectionRef &Section) { if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) return !(ELFObj->getSectionFlags(Section) & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) + return ((COFFObj->getCOFFSection(Section)->Characteristics & + (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ + | COFF::IMAGE_SCN_MEM_WRITE)) + == + (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ)); + assert(isa<MachOObjectFile>(Obj)); return false; } @@ -284,6 +310,9 @@ static bool isZeroInit(const SectionRef &Section) { const ObjectFile *Obj = Section.getObject(); if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) return ELFObj->getSectionType(Section) == ELF::SHT_NOBITS; + if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) + return COFFObj->getCOFFSection(Section)->Characteristics & + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; auto *MachO = cast<MachOObjectFile>(Obj); unsigned SectionType = MachO->getSectionType(Section); @@ -332,19 +361,20 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, if (Name == ".eh_frame") SectionSize += 4; - if (SectionSize > 0) { - // save the total size of the section - if (IsCode) { - CodeSectionSizes.push_back(SectionSize); - } else if (IsReadOnly) { - ROSectionSizes.push_back(SectionSize); - } else { - RWSectionSizes.push_back(SectionSize); - } - // update the max alignment - if (Alignment > MaxAlignment) { - MaxAlignment = Alignment; - } + if (!SectionSize) + SectionSize = 1; + + if (IsCode) { + CodeSectionSizes.push_back(SectionSize); + } else if (IsReadOnly) { + ROSectionSizes.push_back(SectionSize); + } else { + RWSectionSizes.push_back(SectionSize); + } + + // update the max alignment + if (Alignment > MaxAlignment) { + MaxAlignment = Alignment; } } } @@ -442,38 +472,73 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, - SymbolTableMap &SymbolTable) { + CommonSymbolList &CommonSymbols) { + if (CommonSymbols.empty()) + return; + + uint64_t CommonSize = 0; + CommonSymbolList SymbolsToAllocate; + + DEBUG(dbgs() << "Processing common symbols...\n"); + + for (const auto &Sym : CommonSymbols) { + StringRef Name; + Check(Sym.getName(Name)); + + // Skip common symbols already elsewhere. + if (GlobalSymbolTable.count(Name) || + Resolver.findSymbolInLogicalDylib(Name)) { + DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name + << "'\n"); + continue; + } + + uint32_t Align = 0; + uint64_t Size = 0; + Check(Sym.getAlignment(Align)); + Check(Sym.getSize(Size)); + + CommonSize += Align + Size; + SymbolsToAllocate.push_back(Sym); + } + // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void *), - SectionID, StringRef(), false); + uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, sizeof(void *), + SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; - Sections.push_back(SectionEntry("<common symbols>", Addr, TotalSize, 0)); - memset(Addr, 0, TotalSize); + Sections.push_back(SectionEntry("<common symbols>", Addr, CommonSize, 0)); + memset(Addr, 0, CommonSize); DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: " - << format("%p", Addr) << " DataSize: " << TotalSize << "\n"); + << format("%p", Addr) << " DataSize: " << CommonSize << "\n"); // Assign the address of each symbol - for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(), - itEnd = CommonSymbols.end(); it != itEnd; ++it) { - uint64_t Size = it->second.first; - uint64_t Align = it->second.second; + for (auto &Sym : SymbolsToAllocate) { + uint32_t Align; + uint64_t Size; StringRef Name; - it->first.getName(Name); + Check(Sym.getAlignment(Align)); + Check(Sym.getSize(Size)); + Check(Sym.getName(Name)); if (Align) { // This symbol has an alignment requirement. uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align); Addr += AlignOffset; Offset += AlignOffset; - DEBUG(dbgs() << "Allocating common symbol " << Name << " address " - << format("%p\n", Addr)); } - SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); + uint32_t Flags = Sym.getFlags(); + JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; + if (Flags & SymbolRef::SF_Weak) + RTDyldSymFlags |= JITSymbolFlags::Weak; + if (Flags & SymbolRef::SF_Exported) + RTDyldSymFlags |= JITSymbolFlags::Exported; + DEBUG(dbgs() << "Allocating common symbol " << Name << " address " + << format("%p", Addr) << "\n"); + GlobalSymbolTable[Name] = + SymbolTableEntry(SectionID, Offset, RTDyldSymFlags); Offset += Size; Addr += Size; } @@ -483,7 +548,6 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode) { StringRef data; - Check(Section.getContents(data)); uint64_t Alignment64 = Section.getAlignment(); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; @@ -510,21 +574,26 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, uint8_t *Addr; const char *pData = nullptr; + // In either case, set the location of the unrelocated section in memory, + // since we still process relocations for it even if we're not applying them. + Check(Section.getContents(data)); + // Virtual sections have no data in the object image, so leave pData = 0 + if (!IsVirtual) + pData = data.data(); + // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { Allocate = DataSize + PaddingSize + StubBufSize; - Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, - Name) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, - Name, IsReadOnly); + if (!Allocate) + Allocate = 1; + Addr = IsCode ? MemMgr.allocateCodeSection(Allocate, Alignment, SectionID, + Name) + : MemMgr.allocateDataSection(Allocate, Alignment, SectionID, + Name, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); - // Virtual sections have no data in the object image, so leave pData = 0 - if (!IsVirtual) - pData = data.data(); - // Zero-initialize or copy the data from the image if (IsZeroInit || IsVirtual) memset(Addr, 0, DataSize); @@ -589,14 +658,15 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, // Relocation by symbol. If the symbol is found in the global symbol table, // create an appropriate section relocation. Otherwise, add it to // ExternalSymbolRelocations. - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(SymbolName); + RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(SymbolName); if (Loc == GlobalSymbolTable.end()) { ExternalSymbolRelocations[SymbolName].push_back(RE); } else { // Copy the RE since we want to modify its addend. RelocationEntry RECopy = RE; - RECopy.Addend += Loc->second.second; - Relocations[Loc->second.first].push_back(RECopy); + const auto &SymInfo = Loc->second; + RECopy.Addend += SymInfo.getOffset(); + Relocations[SymInfo.getSectionID()].push_back(RECopy); } } @@ -721,11 +791,11 @@ void RuntimeDyldImpl::resolveExternalSymbols() { resolveRelocationList(Relocs, 0); } else { uint64_t Addr = 0; - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { - // This is an external symbol, try to get its address from - // MemoryManager. - Addr = MemMgr->getSymbolAddress(Name.data()); + // This is an external symbol, try to get its address from the symbol + // resolver. + Addr = Resolver.findSymbol(Name.data()).getAddress(); // The call to getSymbolAddress may have caused additional modules to // be loaded, which may have added new entries to the // ExternalSymbolRelocations map. Consquently, we need to update our @@ -736,8 +806,9 @@ void RuntimeDyldImpl::resolveExternalSymbols() { } else { // We found the symbol in our global table. It was probably in a // Module that we loaded previously. - SymbolLoc SymLoc = Loc->second; - Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second; + const auto &SymInfo = Loc->second; + Addr = getSectionLoadAddress(SymInfo.getSectionID()) + + SymInfo.getOffset(); } // FIXME: Implement error handling that doesn't kill the host program! @@ -745,7 +816,6 @@ void RuntimeDyldImpl::resolveExternalSymbols() { report_fatal_error("Program used external function '" + Name + "' which could not be resolved!"); - updateGOTEntries(Name, Addr); DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t" << format("0x%lx", Addr) << "\n"); // This list may have been updated when we called getSymbolAddress, so @@ -770,7 +840,12 @@ uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( return 0; } -RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { +void RuntimeDyld::MemoryManager::anchor() {} +void RuntimeDyld::SymbolResolver::anchor() {} + +RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : MemMgr(MemMgr), Resolver(Resolver) { // FIXME: There's a potential issue lurking here if a single instance of // RuntimeDyld is used to load multiple objects. The current implementation // associates a single memory manager with a RuntimeDyld instance. Even @@ -778,26 +853,40 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { // they share a single memory manager. This can become a problem when page // permissions are applied. Dyld = nullptr; - MM = mm; ProcessAllSections = false; Checker = nullptr; } RuntimeDyld::~RuntimeDyld() {} +static std::unique_ptr<RuntimeDyldCOFF> +createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldCOFF> Dyld = + RuntimeDyldCOFF::create(Arch, MM, Resolver); + Dyld->setProcessAllSections(ProcessAllSections); + Dyld->setRuntimeDyldChecker(Checker); + return Dyld; +} + static std::unique_ptr<RuntimeDyldELF> -createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections, - RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM)); +createRuntimeDyldELF(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM, Resolver)); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; } static std::unique_ptr<RuntimeDyldMachO> -createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM, - bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr<RuntimeDyldMachO> Dyld(RuntimeDyldMachO::create(Arch, MM)); +createRuntimeDyldMachO(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, + RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldMachO> Dyld = + RuntimeDyldMachO::create(Arch, MM, Resolver); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; @@ -807,10 +896,14 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyld::loadObject(const ObjectFile &Obj) { if (!Dyld) { if (Obj.isELF()) - Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); + Dyld = createRuntimeDyldELF(MemMgr, Resolver, ProcessAllSections, Checker); else if (Obj.isMachO()) Dyld = createRuntimeDyldMachO( - static_cast<Triple::ArchType>(Obj.getArch()), MM, + static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver, + ProcessAllSections, Checker); + else if (Obj.isCOFF()) + Dyld = createRuntimeDyldCOFF( + static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver, ProcessAllSections, Checker); else report_fatal_error("Incompatible object format!"); @@ -822,16 +915,16 @@ RuntimeDyld::loadObject(const ObjectFile &Obj) { return Dyld->loadObject(Obj); } -void *RuntimeDyld::getSymbolAddress(StringRef Name) const { +void *RuntimeDyld::getSymbolLocalAddress(StringRef Name) const { if (!Dyld) return nullptr; - return Dyld->getSymbolAddress(Name); + return Dyld->getSymbolLocalAddress(Name); } -uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) const { +RuntimeDyld::SymbolInfo RuntimeDyld::getSymbol(StringRef Name) const { if (!Dyld) - return 0; - return Dyld->getSymbolLoadAddress(Name); + return nullptr; + return Dyld->getSymbol(Name); } void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp new file mode 100644 index 000000000000..c8d3d22966de --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -0,0 +1,88 @@ +//===-- RuntimeDyldCOFF.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 COFF support for the MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#include "RuntimeDyldCOFF.h" +#include "Targets/RuntimeDyldCOFFX86_64.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ObjectFile.h" + +using namespace llvm; +using namespace llvm::object; + +#define DEBUG_TYPE "dyld" + +namespace { + +class LoadedCOFFObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper<LoadedCOFFObjectInfo> { +public: + LoadedCOFFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary<ObjectFile> + getObjectForDebug(const ObjectFile &Obj) const override { + return OwningBinary<ObjectFile>(); + } +}; +} + +namespace llvm { + +std::unique_ptr<RuntimeDyldCOFF> +llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { + switch (Arch) { + default: + llvm_unreachable("Unsupported target for RuntimeDyldCOFF."); + break; + case Triple::x86_64: + return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver); + } +} + +std::unique_ptr<RuntimeDyld::LoadedObjectInfo> +RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique<LoadedCOFFObjectInfo>(*this, SectionStartIdx, + SectionEndIdx); +} + +uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) { + uint64_t Address; + if (Sym.getAddress(Address)) + return UnknownAddressOrSize; + + if (Address == UnknownAddressOrSize) + return UnknownAddressOrSize; + + const ObjectFile *Obj = Sym.getObject(); + section_iterator SecI(Obj->section_end()); + if (Sym.getSection(SecI)) + return UnknownAddressOrSize; + + if (SecI == Obj->section_end()) + return UnknownAddressOrSize; + + uint64_t SectionAddress = SecI->getAddress(); + return Address - SectionAddress; +} + +bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isCOFF(); +} + +} // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h new file mode 100644 index 000000000000..32b8fa269be0 --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -0,0 +1,50 @@ +//===-- RuntimeDyldCOFF.h - 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. +// +//===----------------------------------------------------------------------===// +// +// COFF support for MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_RUNTIME_DYLD_COFF_H +#define LLVM_RUNTIME_DYLD_COFF_H + +#include "RuntimeDyldImpl.h" +#include "llvm/ADT/DenseMap.h" + +#define DEBUG_TYPE "dyld" + +using namespace llvm; + +namespace llvm { + +// Common base class for COFF dynamic linker support. +// Concrete subclasses for each target can be found in ./Targets. +class RuntimeDyldCOFF : public RuntimeDyldImpl { + +public: + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> + loadObject(const object::ObjectFile &Obj) override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; + + static std::unique_ptr<RuntimeDyldCOFF> + create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); + +protected: + RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} + uint64_t getSymbolOffset(const SymbolRef &Sym); +}; + +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index f3e5c77cd08c..957571b092da 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -260,9 +260,7 @@ private: << "'. Instruction has only " << format("%i", Inst.getNumOperands()) << " operands.\nInstruction is:\n "; - Inst.dump_pretty(ErrMsgStream, - Checker.Disassembler->getContext().getAsmInfo(), - Checker.InstPrinter); + Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter); return std::make_pair(EvalResult(ErrMsgStream.str()), ""); } @@ -272,9 +270,7 @@ private: raw_string_ostream ErrMsgStream(ErrMsg); ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '" << Symbol << "' is not an immediate.\nInstruction is:\n "; - Inst.dump_pretty(ErrMsgStream, - Checker.Disassembler->getContext().getAsmInfo(), - Checker.InstPrinter); + Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter); return std::make_pair(EvalResult(ErrMsgStream.str()), ""); } @@ -314,7 +310,7 @@ private: ""); uint64_t SymbolAddr = PCtx.IsInsideLoad - ? Checker.getSymbolLinkerAddr(Symbol) + ? Checker.getSymbolLocalAddr(Symbol) : Checker.getSymbolRemoteAddr(Symbol); uint64_t NextPC = SymbolAddr + InstSize; @@ -441,7 +437,7 @@ private: // The value for the symbol depends on the context we're evaluating in: // Inside a load this is the address in the linker's memory, outside a // load it's the address in the target processes memory. - uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLinkerAddr(Symbol) + uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol) : Checker.getSymbolRemoteAddr(Symbol); // Looks like a plain symbol reference. @@ -731,18 +727,18 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, } bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const { - return getRTDyld().getSymbolAddress(Symbol) != nullptr; + return getRTDyld().getSymbolLocalAddress(Symbol) != nullptr; } -uint64_t RuntimeDyldCheckerImpl::getSymbolLinkerAddr(StringRef Symbol) const { +uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const { return static_cast<uint64_t>( - reinterpret_cast<uintptr_t>(getRTDyld().getSymbolAddress(Symbol))); + reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol))); } uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { - if (uint64_t InternalSymbolAddr = getRTDyld().getSymbolLoadAddress(Symbol)) - return InternalSymbolAddr; - return getRTDyld().MemMgr->getSymbolAddress(Symbol); + if (auto InternalSymbol = getRTDyld().getSymbol(Symbol)) + return InternalSymbol.getAddress(); + return getRTDyld().Resolver.findSymbol(Symbol).getAddress(); } uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, @@ -850,14 +846,16 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor( StringRef RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const { - RuntimeDyldImpl::SymbolTableMap::const_iterator pos = + RTDyldSymbolTable::const_iterator pos = getRTDyld().GlobalSymbolTable.find(Name); if (pos == getRTDyld().GlobalSymbolTable.end()) return StringRef(); - RuntimeDyldImpl::SymbolLoc Loc = pos->second; - uint8_t *SectionAddr = getRTDyld().getSectionAddress(Loc.first); - return StringRef(reinterpret_cast<const char *>(SectionAddr) + Loc.second, - getRTDyld().Sections[Loc.first].Size - Loc.second); + const auto &SymInfo = pos->second; + uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID()); + return StringRef(reinterpret_cast<const char *>(SectionAddr) + + SymInfo.getOffset(), + getRTDyld().Sections[SymInfo.getSectionID()].Size - + SymInfo.getOffset()); } void RuntimeDyldCheckerImpl::registerSection( @@ -887,9 +885,10 @@ void RuntimeDyldCheckerImpl::registerStubMap( // If this is a (Section, Offset) pair, do a reverse lookup in the // global symbol table to find the name. for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) { - if (GSTEntry.second.first == StubMapEntry.first.SectionID && - GSTEntry.second.second == - static_cast<uint64_t>(StubMapEntry.first.Offset)) { + const auto &SymInfo = GSTEntry.second; + if (SymInfo.getSectionID() == StubMapEntry.first.SectionID && + SymInfo.getOffset() == + static_cast<uint64_t>(StubMapEntry.first.Offset)) { SymbolName = GSTEntry.first(); break; } @@ -930,6 +929,6 @@ bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, std::pair<uint64_t, std::string> RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName, - bool LinkerAddress) { - return Impl->getSectionAddr(FileName, SectionName, LinkerAddress); + bool LocalAddress) { + return Impl->getSectionAddr(FileName, SectionName, LocalAddress); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h index de20c1ec6603..69d2a7d6b668 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h @@ -19,6 +19,7 @@ class RuntimeDyldCheckerImpl { friend class RuntimeDyldChecker; friend class RuntimeDyldImpl; friend class RuntimeDyldCheckerExprEval; + friend class RuntimeDyldELF; public: RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler, @@ -42,7 +43,7 @@ private: RuntimeDyldImpl &getRTDyld() const { return *RTDyld.Dyld; } bool isSymbolValid(StringRef Symbol) const; - uint64_t getSymbolLinkerAddr(StringRef Symbol) const; + uint64_t getSymbolLocalAddr(StringRef Symbol) const; uint64_t getSymbolRemoteAddr(StringRef Symbol) const; uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 2664a10ece5f..95421b35db5c 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldELF.h" +#include "RuntimeDyldCheckerImpl.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -103,11 +104,12 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, sym->st_value = static_cast<addr_type>(Addr); } -class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo { +class LoadedELFObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper<LoadedELFObjectInfo> { public: LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, unsigned EndIdx) - : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} OwningBinary<ObjectFile> getObjectForDebug(const ObjectFile &Obj) const override; @@ -183,32 +185,30 @@ LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { namespace llvm { -RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} +RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0), CurrentGOTIndex(0) {} RuntimeDyldELF::~RuntimeDyldELF() {} void RuntimeDyldELF::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { SID EHFrameSID = UnregisteredEHFrameSections[i]; uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); RegisteredEHFrameSections.push_back(EHFrameSID); } UnregisteredEHFrameSections.clear(); } void RuntimeDyldELF::deregisterEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) { SID EHFrameSID = RegisteredEHFrameSections[i]; uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); } RegisteredEHFrameSections.clear(); } @@ -247,40 +247,18 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, << format("%p\n", Section.Address + Offset)); break; } - case ELF::R_X86_64_GOTPCREL: { - // findGOTEntry returns the 'G + GOT' part of the relocation calculation - // based on the load/target address of the GOT (not the current/local addr). - uint64_t GOTAddr = findGOTEntry(Value, SymOffset); - uint64_t FinalAddress = Section.LoadAddress + Offset; - // The processRelocationRef method combines the symbol offset and the addend - // and in most cases that's what we want. For this relocation type, we need - // the raw addend, so we subtract the symbol offset to get it. - int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress; - assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); - int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); - support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset; - break; - } case ELF::R_X86_64_PC32: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle32_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); uint64_t FinalAddress = Section.LoadAddress + Offset; - int64_t RealOffset = Placeholder + Value + Addend - FinalAddress; - assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); + int64_t RealOffset = Value + Addend - FinalAddress; + assert(isInt<32>(RealOffset)); int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset; break; } case ELF::R_X86_64_PC64: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle64_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); uint64_t FinalAddress = Section.LoadAddress + Offset; - support::ulittle64_t::ref(Section.Address + Offset) = - Placeholder + Value + Addend - FinalAddress; + int64_t RealOffset = Value + Addend - FinalAddress; + support::ulittle64_t::ref(Section.Address + Offset) = RealOffset; break; } } @@ -291,21 +269,12 @@ void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, uint32_t Type, int32_t Addend) { switch (Type) { case ELF::R_386_32: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle32_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); - support::ulittle32_t::ref(Section.Address + Offset) = - Placeholder + Value + Addend; + support::ulittle32_t::ref(Section.Address + Offset) = Value + Addend; break; } case ELF::R_386_PC32: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle32_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); - uint32_t RealOffset = Placeholder + Value + Addend - FinalAddress; + uint32_t RealOffset = Value + Addend - FinalAddress; support::ulittle32_t::ref(Section.Address + Offset) = RealOffset; break; } @@ -354,8 +323,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, uint64_t BranchImm = Value + Addend - FinalAddress; // "Check that -2^27 <= result < 2^27". - assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) && - static_cast<int64_t>(BranchImm) < (1LL << 27)); + assert(isInt<28>(BranchImm)); // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. @@ -418,9 +386,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); // Check that -2^32 <= X < 2^32 - assert(static_cast<int64_t>(Result) >= (-1LL << 32) && - static_cast<int64_t>(Result) < (1LL << 32) && - "overflow check failed for relocation"); + assert(isInt<33>(Result) && "overflow check failed for relocation"); // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. @@ -462,8 +428,6 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend) { // TODO: Add Thumb relocations. - uint32_t *Placeholder = - reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); Value += Addend; @@ -480,39 +444,27 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, case ELF::R_ARM_NONE: break; - // Write a 32bit value to relocation address, taking into account the - // implicit addend encoded in the target. case ELF::R_ARM_PREL31: case ELF::R_ARM_TARGET1: case ELF::R_ARM_ABS32: - *TargetPtr = *Placeholder + Value; + *TargetPtr = Value; break; - // Write first 16 bit of 32 bit value to the mov instruction. - // Last 4 bit should be shifted. + // 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: - // We are not expecting any other addend in the relocation address. - // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2 - // non-contiguous fields. - assert((*Placeholder & 0x000F0FFF) == 0); - Value = Value & 0xFFFF; - *TargetPtr = *Placeholder | (Value & 0xFFF); - *TargetPtr |= ((Value >> 12) & 0xF) << 16; - break; - // Write last 16 bit of 32 bit value to the mov instruction. - // Last 4 bit should be shifted. case ELF::R_ARM_MOVT_ABS: - // We are not expecting any other addend in the relocation address. - // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC. - assert((*Placeholder & 0x000F0FFF) == 0); - - Value = (Value >> 16) & 0xFFFF; - *TargetPtr = *Placeholder | (Value & 0xFFF); + if (Type == ELF::R_ARM_MOVW_ABS_NC) + Value = Value & 0xFFFF; + else if (Type == ELF::R_ARM_MOVT_ABS) + Value = (Value >> 16) & 0xFFFF; + *TargetPtr &= ~0x000F0FFF; + *TargetPtr |= Value & 0xFFF; *TargetPtr |= ((Value >> 12) & 0xF) << 16; break; - // Write 24 bit relative value to the branch instruction. + // 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: { + case ELF::R_ARM_JUMP24: int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); RelValue = (RelValue & 0x03FFFFFC) >> 2; assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE); @@ -520,21 +472,11 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, *TargetPtr |= RelValue; break; } - case ELF::R_ARM_PRIVATE_0: - // This relocation is reserved by the ARM ELF ABI for internal use. We - // appropriate it here to act as an R_ARM_ABS32 without any addend for use - // in the stubs created during JIT (which can't put an addend into the - // original object file). - *TargetPtr = Value; - break; - } } void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend) { - uint32_t *Placeholder = - reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset); Value += Addend; @@ -549,30 +491,17 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, llvm_unreachable("Not implemented relocation type!"); break; case ELF::R_MIPS_32: - *TargetPtr = Value + (*Placeholder); + *TargetPtr = Value; break; case ELF::R_MIPS_26: - *TargetPtr = ((*Placeholder) & 0xfc000000) | ((Value & 0x0fffffff) >> 2); + *TargetPtr = ((*TargetPtr) & 0xfc000000) | ((Value & 0x0fffffff) >> 2); break; case ELF::R_MIPS_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. - Value += ((*Placeholder) & 0x0000ffff) << 16; *TargetPtr = - ((*Placeholder) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); + ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); break; case ELF::R_MIPS_LO16: - Value += ((*Placeholder) & 0x0000ffff); - *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff); - break; - case ELF::R_MIPS_UNUSED1: - // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2 - // are used for internal JIT purpose. These relocations are similar to - // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into - // account. - *TargetPtr = - ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); - break; - case ELF::R_MIPS_UNUSED2: *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); break; } @@ -898,6 +827,18 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, } } +void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const { + return (void*)(Sections[SectionID].ObjAddress + 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); +} + relocation_iterator RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &Obj, @@ -920,15 +861,16 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( SymbolRef::Type SymType = SymbolRef::ST_Unknown; // Search for the symbol in the global symbol table - SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); + RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end(); if (Symbol != Obj.symbol_end()) { gsi = GlobalSymbolTable.find(TargetName.data()); Symbol->getType(SymType); } if (gsi != GlobalSymbolTable.end()) { - Value.SectionID = gsi->second.first; - Value.Offset = gsi->second.second; - Value.Addend = gsi->second.second + Addend; + 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: { @@ -1014,80 +956,103 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( 0); Section.StubOffset += getMaxStubSize(); } - } else if (Arch == Triple::arm && - (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."); - SectionEntry &Section = Sections[SectionID]; + } 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."); + SectionEntry &Section = Sections[SectionID]; - // Look for an existing stub. - StubMap::const_iterator i = Stubs.find(Value); - if (i != Stubs.end()) { - resolveRelocation(Section, Offset, (uint64_t)Section.Address + 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.StubOffset; - uint8_t *StubTargetAddr = + // Look for an existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + resolveRelocation(Section, Offset, (uint64_t)Section.Address + 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.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); - RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, - ELF::R_ARM_PRIVATE_0, Value.Addend); - if (Value.SymbolName) - addRelocationForSymbol(RE, Value.SymbolName); - else - addRelocationForSection(RE, Value.SectionID); + RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, + ELF::R_ARM_ABS32, Value.Addend); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + Section.StubOffset, RelType, - 0); - Section.StubOffset += getMaxStubSize(); + resolveRelocation(Section, Offset, + (uint64_t)Section.Address + Section.StubOffset, RelType, + 0); + Section.StubOffset += 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 ((Arch == Triple::mipsel || Arch == Triple::mips) && - 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]; - uint8_t *Target = Section.Address + Offset; - uint32_t *TargetAddress = (uint32_t *)Target; + } else if ((Arch == Triple::mipsel || Arch == Triple::mips)) { + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset)); + 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. - uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2; + // 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 = ((*Placeholder) & 0x03ffffff) << 2; - Value.Addend += Addend; + 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.StubOffset; - uint8_t *StubTargetAddr = + // 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.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); - // Creating Hi and Lo relocations for the filled stub instructions. - RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, - ELF::R_MIPS_UNUSED1, Value.Addend); - RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 4, - ELF::R_MIPS_UNUSED2, Value.Addend); + // Creating Hi and Lo relocations for the filled stub instructions. + RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 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); - } + 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.StubOffset); - addRelocationForSection(RE, SectionID); - Section.StubOffset += getMaxStubSize(); + RelocationEntry RE(SectionID, Offset, RelType, Section.StubOffset); + addRelocationForSection(RE, SectionID); + Section.StubOffset += getMaxStubSize(); + } + } else { + if (RelType == ELF::R_MIPS_HI16) + Value.Addend += ((*Placeholder) & 0x0000ffff) << 16; + else if (RelType == ELF::R_MIPS_LO16) + Value.Addend += ((*Placeholder) & 0x0000ffff); + else if (RelType == ELF::R_MIPS_32) + Value.Addend += *Placeholder; + processSimpleRelocation(SectionID, Offset, RelType, Value); } } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { if (RelType == ELF::R_PPC64_REL24) { @@ -1127,7 +1092,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( RangeOverflow = true; } } - if (SymType == SymbolRef::ST_Unknown || RangeOverflow == true) { + if (SymType == SymbolRef::ST_Unknown || RangeOverflow) { // It is an external symbol (SymbolRef::ST_Unknown) or within a range // larger than 24-bits. StubMap::const_iterator i = Stubs.find(Value); @@ -1286,93 +1251,95 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( Addend); else resolveRelocation(Section, Offset, StubAddress, RelType, Addend); - } else if (Arch == Triple::x86_64 && 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()) { + } 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.Address) + i->second; DEBUG(dbgs() << " Stub function found\n"); - } else { + } 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.Address); uintptr_t StubAlignment = getStubAlignment(); StubAddress = (BaseAddress + Section.StubOffset + StubAlignment - 1) & - -StubAlignment; + -StubAlignment; unsigned StubOffset = StubAddress - BaseAddress; Stubs[Value] = StubOffset; createStubFunction((uint8_t *)StubAddress); - // Create a GOT entry for the external function. - GOTEntries.push_back(Value); - - // Make our stub function a relative call to the GOT entry. - RelocationEntry RE(SectionID, StubOffset + 2, ELF::R_X86_64_GOTPCREL, - -4); - addRelocationForSymbol(RE, Value.SymbolName); - // Bump our stub offset counter Section.StubOffset = StubOffset + getMaxStubSize(); + + // Allocate a GOT Entry + uint64_t GOTOffset = allocateGOTEntries(SectionID, 1); + + // The load of the GOT address has an addend of -4 + resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4); + + // Fill in the value of the symbol we're targeting into the GOT + addRelocationForSymbol(computeGOTOffsetRE(SectionID,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) { + uint64_t GOTOffset = allocateGOTEntries(SectionID, 1); + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend); - // Make the target call a call into the stub table. - resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32, - Addend); + // Fill in the value of the symbol we're targeting into the GOT + RelocationEntry RE = computeGOTOffsetRE(SectionID, 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 { - RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend, - Value.Offset); - addRelocationForSection(RE, Value.SectionID); + processSimpleRelocation(SectionID, Offset, RelType, Value); } } else { - if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) { - GOTEntries.push_back(Value); + if (Arch == Triple::x86) { + Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); } - RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset); - if (Value.SymbolName) - addRelocationForSymbol(RE, Value.SymbolName); - else - addRelocationForSection(RE, Value.SectionID); + processSimpleRelocation(SectionID, Offset, RelType, Value); } return ++RelI; } -void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) { - - SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator it; - SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator end = GOTs.end(); - - for (it = GOTs.begin(); it != end; ++it) { - GOTRelocations &GOTEntries = it->second; - for (int i = 0, e = GOTEntries.size(); i != e; ++i) { - if (GOTEntries[i].SymbolName != nullptr && - GOTEntries[i].SymbolName == Name) { - GOTEntries[i].Offset = Addr; - } - } - } -} - 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. @@ -1399,83 +1366,53 @@ size_t RuntimeDyldELF::getGOTEntrySize() { return Result; } -uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { - - const size_t GOTEntrySize = getGOTEntrySize(); - - SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator it; - SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator end = - GOTs.end(); - - int GOTIndex = -1; - for (it = GOTs.begin(); it != end; ++it) { - SID GOTSectionID = it->first; - const GOTRelocations &GOTEntries = it->second; - - // Find the matching entry in our vector. - uint64_t SymbolOffset = 0; - for (int i = 0, e = GOTEntries.size(); i != e; ++i) { - if (!GOTEntries[i].SymbolName) { - if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress && - GOTEntries[i].Offset == Offset) { - GOTIndex = i; - SymbolOffset = GOTEntries[i].Offset; - break; - } - } else { - // GOT entries for external symbols use the addend as the address when - // the external symbol has been resolved. - if (GOTEntries[i].Offset == LoadAddress) { - GOTIndex = i; - // Don't use the Addend here. The relocation handler will use it. - break; - } - } - } - - if (GOTIndex != -1) { - if (GOTEntrySize == sizeof(uint64_t)) { - uint64_t *LocalGOTAddr = (uint64_t *)getSectionAddress(GOTSectionID); - // Fill in this entry with the address of the symbol being referenced. - LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset; - } else { - uint32_t *LocalGOTAddr = (uint32_t *)getSectionAddress(GOTSectionID); - // Fill in this entry with the address of the symbol being referenced. - LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset); - } - - // Calculate the load address of this entry - return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize); - } +uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned no) +{ + (void)SectionID; // The GOT Section is the same for all section in the object file + 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", 0, 0, 0)); } + uint64_t StartOffset = CurrentGOTIndex * getGOTEntrySize(); + CurrentGOTIndex += no; + return StartOffset; +} + +void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, uint64_t GOTOffset) +{ + // Fill in the relative address of the GOT Entry into the stub + RelocationEntry GOTRE(SectionID, Offset, ELF::R_X86_64_PC32, GOTOffset); + addRelocationForSection(GOTRE, GOTSectionID); +} - assert(GOTIndex != -1 && "Unable to find requested GOT entry."); - return 0; +RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID, uint64_t GOTOffset, uint64_t SymbolOffset, + uint32_t Type) +{ + (void)SectionID; // The GOT Section is the same for all section in the object file + return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset); } void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { // If necessary, allocate the global offset table - if (MemMgr) { - // Allocate the GOT if necessary - size_t numGOTEntries = GOTEntries.size(); - if (numGOTEntries != 0) { - // Allocate memory for the section - unsigned SectionID = Sections.size(); - size_t TotalSize = numGOTEntries * getGOTEntrySize(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(), - SectionID, ".got", false); - if (!Addr) - report_fatal_error("Unable to allocate memory for GOT!"); + 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) + report_fatal_error("Unable to allocate memory for GOT!"); - GOTs.push_back(std::make_pair(SectionID, GOTEntries)); - Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0)); - // 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); - } - } else { - report_fatal_error("Unable to allocate memory for GOT!"); + Sections[GOTSectionID] = SectionEntry(".got", Addr, 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); } // Look for and record the EH frame section. @@ -1489,6 +1426,9 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, break; } } + + GOTSectionID = 0; + CurrentGOTIndex = 0; } bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index b4414b08c480..9a4a8630e4c4 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -20,16 +20,6 @@ using namespace llvm; namespace llvm { -namespace { -// Helper for extensive error checking in debug builds. -std::error_code Check(std::error_code Err) { - if (Err) { - report_fatal_error(Err.message()); - } - return Err; -} - -} // end anonymous namespace class RuntimeDyldELF : public RuntimeDyldImpl { @@ -90,16 +80,39 @@ class RuntimeDyldELF : public RuntimeDyldImpl { ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); size_t getGOTEntrySize(); - void updateGOTEntries(StringRef Name, uint64_t Addr) override; + SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } + + // Allocate no GOT entries for use in the given section. + uint64_t allocateGOTEntries(unsigned SectionID, unsigned no); + + // Resolve the relvative address of GOTOffset in Section ID and place + // it at the given Offset + void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, + uint64_t GOTOffset); + + // For a GOT entry referenced from SectionID, compute a relocation entry + // that will place the final resolved value in the GOT slot + RelocationEntry computeGOTOffsetRE(unsigned SectionID, + uint64_t GOTOffset, + uint64_t SymbolOffset, + unsigned Type); + + // Compute the address in memory where we can find the placeholder + void *computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const; + + // Split out common case for createing the RelocationEntry for when the relocation requires + // no particular advanced processing. + void processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value); + + // The tentative ID for the GOT section + unsigned GOTSectionID; - // Relocation entries for symbols whose position-independent offset is - // updated in a global offset table. - typedef SmallVector<RelocationValueRef, 2> GOTRelocations; - GOTRelocations GOTEntries; // List of entries requiring finalization. - SmallVector<std::pair<SID, GOTRelocations>, 8> GOTs; // Allocated tables. + // Records the current number of allocated slots in the GOT + // (This would be equivalent to GOTEntries.size() were it not for relocations + // that consume more than one slot) + unsigned CurrentGOTIndex; // When a module is loaded we save the SectionID of the EH frame section // in a table until we receive a request to register all unregistered @@ -108,8 +121,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector<SID, 2> RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm); - virtual ~RuntimeDyldELF(); + RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); + ~RuntimeDyldELF() override; std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &O) override; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 2f3e3a8f0344..90e61a50a1b0 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/Object/ObjectFile.h" @@ -36,6 +37,14 @@ using namespace llvm::object; namespace llvm { + // Helper for extensive error checking in debug builds. +inline std::error_code Check(std::error_code Err) { + if (Err) { + report_fatal_error(Err.message()); + } + return Err; +} + class Twine; /// SectionEntry - represents a section emitted into memory by the dynamic @@ -43,7 +52,7 @@ class Twine; class SectionEntry { public: /// Name - section name. - StringRef Name; + std::string Name; /// Address - address in the linker's memory where the section resides. uint8_t *Address; @@ -156,12 +165,34 @@ public: } }; +/// @brief Symbol info for RuntimeDyld. +class SymbolTableEntry : public JITSymbolBase { +public: + SymbolTableEntry() + : JITSymbolBase(JITSymbolFlags::None), Offset(0), SectionID(0) {} + + SymbolTableEntry(unsigned SectionID, uint64_t Offset, JITSymbolFlags Flags) + : JITSymbolBase(Flags), Offset(Offset), SectionID(SectionID) {} + + unsigned getSectionID() const { return SectionID; } + uint64_t getOffset() const { return Offset; } + +private: + uint64_t Offset; + unsigned SectionID; +}; + +typedef StringMap<SymbolTableEntry> RTDyldSymbolTable; + class RuntimeDyldImpl { friend class RuntimeDyld::LoadedObjectInfo; friend class RuntimeDyldCheckerImpl; protected: // The MemoryManager to load objects into. - RTDyldMemoryManager *MemMgr; + RuntimeDyld::MemoryManager &MemMgr; + + // The symbol resolver to use for external symbols. + RuntimeDyld::SymbolResolver &Resolver; // Attached RuntimeDyldChecker instance. Null if no instance attached. RuntimeDyldCheckerImpl *Checker; @@ -172,22 +203,17 @@ protected: SectionList Sections; typedef unsigned SID; // Type for SectionIDs -#define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) +#define RTDYLD_INVALID_SECTION_ID ((RuntimeDyldImpl::SID)(-1)) // Keep a map of sections from object file to the SectionID which // references it. typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; - // A global symbol table for symbols from all loaded modules. Maps the - // symbol name to a (SectionID, offset in section) pair. - typedef std::pair<unsigned, uintptr_t> SymbolLoc; - typedef StringMap<SymbolLoc> SymbolTableMap; - SymbolTableMap GlobalSymbolTable; + // A global symbol table for symbols from all loaded modules. + RTDyldSymbolTable GlobalSymbolTable; - // Pair representing the size and alignment requirement for a common symbol. - typedef std::pair<unsigned, unsigned> CommonSymbolInfo; // Keep a map of common symbols to their info pairs - typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap; + typedef std::vector<SymbolRef> CommonSymbolList; // For each symbol, keep a list of relocations based on it. Anytime // its address is reassigned (the JIT re-compiled the function, e.g.), @@ -287,9 +313,7 @@ protected: /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. - void emitCommonSymbols(const ObjectFile &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, SymbolTableMap &SymbolTable); + void emitCommonSymbols(const ObjectFile &Obj, CommonSymbolList &CommonSymbols); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be @@ -337,10 +361,6 @@ protected: /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); - /// \brief Update GOT entries for external symbols. - // The base class does nothing. ELF overrides this. - virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {} - // \brief Compute an upper bound of the memory that is required to load all // sections void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, @@ -354,8 +374,10 @@ protected: std::pair<unsigned, unsigned> loadObjectImpl(const object::ObjectFile &Obj); public: - RuntimeDyldImpl(RTDyldMemoryManager *mm) - : MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) { + RuntimeDyldImpl(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : MemMgr(MemMgr), Resolver(Resolver), Checker(nullptr), + ProcessAllSections(false), HasError(false) { } virtual ~RuntimeDyldImpl(); @@ -371,24 +393,26 @@ public: virtual std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &Obj) = 0; - uint8_t* getSymbolAddress(StringRef Name) const { + uint8_t* getSymbolLocalAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); if (pos == GlobalSymbolTable.end()) return nullptr; - SymbolLoc Loc = pos->second; - return getSectionAddress(Loc.first) + Loc.second; + const auto &SymInfo = pos->second; + return getSectionAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); } - uint64_t getSymbolLoadAddress(StringRef Name) const { + RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); if (pos == GlobalSymbolTable.end()) - return 0; - SymbolLoc Loc = pos->second; - return getSectionLoadAddress(Loc.first) + Loc.second; + return nullptr; + const auto &SymEntry = pos->second; + uint64_t TargetAddr = + getSectionLoadAddress(SymEntry.getSectionID()) + SymEntry.getOffset(); + return RuntimeDyld::SymbolInfo(TargetAddr, SymEntry.getFlags()); } void resolveRelocations(); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index d75be2807862..d4a680d749a1 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -26,11 +26,12 @@ using namespace llvm::object; namespace { -class LoadedMachOObjectInfo : public RuntimeDyld::LoadedObjectInfo { +class LoadedMachOObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> { public: LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, unsigned EndIdx) - : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} OwningBinary<ObjectFile> getObjectForDebug(const ObjectFile &Obj) const override { @@ -64,17 +65,18 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); - SymbolTableMap::const_iterator SI = + RTDyldSymbolTable::const_iterator SI = GlobalSymbolTable.find(TargetName.data()); if (SI != GlobalSymbolTable.end()) { - Value.SectionID = SI->second.first; - Value.Offset = SI->second.second + RE.Addend; + const auto &SymInfo = SI->second; + Value.SectionID = SymInfo.getSectionID(); + Value.Offset = SymInfo.getOffset() + RE.Addend; } else { Value.SymbolName = TargetName.data(); Value.Offset = RE.Addend; } } else { - SectionRef Sec = Obj.getRelocationSection(RelInfo); + SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); bool IsCode = Sec.isText(); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); @@ -252,8 +254,6 @@ static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { template <typename Impl> void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || @@ -276,22 +276,28 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { P = processFDE(P, DeltaForText, DeltaForEH); } while (P != End); - MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, - EHFrame->Size); + MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, + EHFrame->Size); } UnregisteredEHFrameSections.clear(); } std::unique_ptr<RuntimeDyldMachO> -RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); break; - case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM); - case Triple::aarch64: return make_unique<RuntimeDyldMachOAArch64>(MM); - case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM); - case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM); + case Triple::arm: + return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver); + case Triple::aarch64: + return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver); + case Triple::x86: + return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver); + case Triple::x86_64: + return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver); } } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index f8bfc03b6d22..45a94ba928fd 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -49,7 +49,9 @@ protected: // EH frame sections with the memory manager. SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections; - RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldMachO(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} /// This convenience method uses memcpy to extract a contiguous addend (the /// addend size and offset are taken from the corresponding fields of the RE). @@ -114,8 +116,10 @@ protected: public: /// Create a RuntimeDyldMachO instance for the given target architecture. - static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch, - RTDyldMemoryManager *mm); + static std::unique_ptr<RuntimeDyldMachO> + create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &O) override; @@ -142,7 +146,9 @@ private: int64_t DeltaForEH); public: - RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {} + RuntimeDyldMachOCRTPBase(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachO(MemMgr, Resolver) {} void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h new file mode 100644 index 000000000000..478665ea3d01 --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -0,0 +1,216 @@ +//===-- RuntimeDyldCOFFX86_64.h --- COFF/X86_64 specific code ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// COFF x86_x64 support for MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H + +#include "llvm/Object/COFF.h" +#include "llvm/Support/COFF.h" +#include "../RuntimeDyldCOFF.h" + +#define DEBUG_TYPE "dyld" + +namespace llvm { + +class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF { + +private: + // When a module is loaded we save the SectionID of the unwind + // sections in a table until we receive a request to register all + // unregisteredEH frame sections with the memory manager. + SmallVector<SID, 2> UnregisteredEHFrameSections; + SmallVector<SID, 2> RegisteredEHFrameSections; + +public: + RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldCOFF(MM, Resolver) {} + + unsigned getMaxStubSize() override { + return 6; // 2-byte jmp instruction + 32-bit relative address + } + + // 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 resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { + const SectionEntry &Section = Sections[RE.SectionID]; + uint8_t *Target = Section.Address + RE.Offset; + + switch (RE.RelType) { + + case COFF::IMAGE_REL_AMD64_REL32: + case COFF::IMAGE_REL_AMD64_REL32_1: + case COFF::IMAGE_REL_AMD64_REL32_2: + case COFF::IMAGE_REL_AMD64_REL32_3: + case COFF::IMAGE_REL_AMD64_REL32_4: + case COFF::IMAGE_REL_AMD64_REL32_5: { + uint32_t *TargetAddress = (uint32_t *)Target; + uint64_t FinalAddress = Section.LoadAddress + RE.Offset; + // Delta is the distance from the start of the reloc to the end of the + // instruction with the reloc. + uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32); + Value -= FinalAddress + Delta; + uint64_t Result = Value + RE.Addend; + assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow"); + assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow"); + *TargetAddress = Result; + break; + } + + case COFF::IMAGE_REL_AMD64_ADDR32NB: { + // Note ADDR32NB requires a well-established notion of + // image base. This address must be less than or equal + // to every section's load address, and all sections must be + // within a 32 bit offset from the base. + // + // For now we just set these to zero. + uint32_t *TargetAddress = (uint32_t *)Target; + *TargetAddress = 0; + break; + } + + case COFF::IMAGE_REL_AMD64_ADDR64: { + uint64_t *TargetAddress = (uint64_t *)Target; + *TargetAddress = Value + RE.Addend; + break; + } + + default: + llvm_unreachable("Relocation type not implemented yet!"); + break; + } + } + + relocation_iterator processRelocationRef(unsigned SectionID, + relocation_iterator RelI, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { + // If possible, find the symbol referred to in the relocation, + // and the section that contains it. + symbol_iterator Symbol = RelI->getSymbol(); + if (Symbol == Obj.symbol_end()) + report_fatal_error("Unknown symbol in relocation"); + section_iterator SecI(Obj.section_end()); + Symbol->getSection(SecI); + // If there is no section, this must be an external reference. + const bool IsExtern = SecI == Obj.section_end(); + + // Determine the Addend used to adjust the relocation value. + uint64_t RelType; + Check(RelI->getType(RelType)); + uint64_t Offset; + Check(RelI->getOffset(Offset)); + uint64_t Addend = 0; + SectionEntry &Section = Sections[SectionID]; + uintptr_t ObjTarget = Section.ObjAddress + Offset; + + switch (RelType) { + + case COFF::IMAGE_REL_AMD64_REL32: + case COFF::IMAGE_REL_AMD64_REL32_1: + case COFF::IMAGE_REL_AMD64_REL32_2: + case COFF::IMAGE_REL_AMD64_REL32_3: + case COFF::IMAGE_REL_AMD64_REL32_4: + case COFF::IMAGE_REL_AMD64_REL32_5: + case COFF::IMAGE_REL_AMD64_ADDR32NB: { + uint32_t *Displacement = (uint32_t *)ObjTarget; + Addend = *Displacement; + break; + } + + case COFF::IMAGE_REL_AMD64_ADDR64: { + uint64_t *Displacement = (uint64_t *)ObjTarget; + Addend = *Displacement; + break; + } + + default: + break; + } + + StringRef TargetName; + Symbol->getName(TargetName); + + DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset + << " RelType: " << RelType << " TargetName: " << TargetName + << " Addend " << Addend << "\n"); + + if (IsExtern) { + RelocationEntry RE(SectionID, Offset, RelType, Addend); + addRelocationForSymbol(RE, TargetName); + } else { + bool IsCode = SecI->isText(); + unsigned TargetSectionID = + findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID); + uint64_t TargetOffset = getSymbolOffset(*Symbol); + RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); + addRelocationForSection(RE, TargetSectionID); + } + + return ++RelI; + } + + unsigned getStubAlignment() override { return 1; } + void registerEHFrames() override { + for (auto const &EHFrameSID : UnregisteredEHFrameSections) { + uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; + uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; + size_t EHFrameSize = Sections[EHFrameSID].Size; + MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + RegisteredEHFrameSections.push_back(EHFrameSID); + } + UnregisteredEHFrameSections.clear(); + } + void deregisterEHFrames() override { + // Stub + } + void finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) override { + // Look for and record the EH frame section IDs. + for (const auto &SectionPair : SectionMap) { + const SectionRef &Section = SectionPair.first; + StringRef Name; + Check(Section.getName(Name)); + // Note unwind info is split across .pdata and .xdata, so this + // may not be sufficiently general for all users. + if (Name == ".xdata") { + UnregisteredEHFrameSections.push_back(SectionPair.second); + } + } + } +}; + +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index 196fa62a0a07..99fd6e333b47 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -23,8 +23,9 @@ public: typedef uint64_t TargetPtrT; - RuntimeDyldMachOAArch64(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 09e430e22619..09e51f27da4f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -25,7 +25,9 @@ public: typedef uint32_t TargetPtrT; - RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 67d7027c1858..053f90ce05a1 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -22,8 +22,9 @@ public: typedef uint32_t TargetPtrT; - RuntimeDyldMachOI386(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 0; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 0734017e2204..4b3b01ba3c96 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -22,8 +22,9 @@ public: typedef uint64_t TargetPtrT; - RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } |
