diff options
Diffstat (limited to 'lib/ExecutionEngine')
43 files changed, 1836 insertions, 875 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 41c8da40346a..a8e68bf49abc 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -103,12 +103,10 @@ public: /// \brief Returns the address the GlobalVariable should be written into. The /// GVMemoryBlock object prefixes that. static char *Create(const GlobalVariable *GV, const DataLayout& TD) { - Type *ElTy = GV->getType()->getElementType(); + Type *ElTy = GV->getValueType(); size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy); void *RawMemory = ::operator new( - RoundUpToAlignment(sizeof(GVMemoryBlock), - TD.getPreferredAlignment(GV)) - + GVSize); + alignTo(sizeof(GVMemoryBlock), TD.getPreferredAlignment(GV)) + GVSize); new(RawMemory) GVMemoryBlock(GV); return static_cast<char*>(RawMemory) + sizeof(GVMemoryBlock); } @@ -237,10 +235,8 @@ void ExecutionEngine::clearAllGlobalMappings() { void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) { MutexGuard locked(lock); - for (Function &FI : *M) - EEState.RemoveMapping(getMangledName(&FI)); - for (GlobalVariable &GI : M->globals()) - EEState.RemoveMapping(getMangledName(&GI)); + for (GlobalObject &GO : M->global_objects()) + EEState.RemoveMapping(getMangledName(&GO)); } uint64_t ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, @@ -476,8 +472,7 @@ EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {} EngineBuilder::EngineBuilder(std::unique_ptr<Module> M) : M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr), OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr), - RelocModel(Reloc::Default), CMModel(CodeModel::JITDefault), - UseOrcMCJITReplacement(false) { + CMModel(CodeModel::JITDefault), UseOrcMCJITReplacement(false) { // IR module verification is enabled by default in debug builds, and disabled // by default in release builds. #ifndef NDEBUG @@ -1355,7 +1350,7 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { if (!GV->isThreadLocal()) InitializeMemory(GV->getInitializer(), GA); - Type *ElTy = GV->getType()->getElementType(); + Type *ElTy = GV->getValueType(); size_t GVSize = (size_t)getDataLayout().getTypeAllocSize(ElTy); NumInitBytes += (unsigned)GVSize; ++NumGlobals; diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index ff7c4dce0d5d..d6b209a91d76 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -17,6 +17,7 @@ #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" +#include "llvm/Support/CodeGenCWrappers.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetOptions.h" #include <cstring> @@ -215,10 +216,12 @@ void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { } void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) { + unwrap(EE)->finalizeObject(); unwrap(EE)->runStaticConstructorsDestructors(false); } void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { + unwrap(EE)->finalizeObject(); unwrap(EE)->runStaticConstructorsDestructors(true); } diff --git a/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt b/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt index 65f2a2f51f9b..3b8c4b973e68 100644 --- a/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt +++ b/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt @@ -3,9 +3,9 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) if( HAVE_LIBDL ) set(LLVM_INTEL_JIT_LIBS ${CMAKE_DL_LIBS}) endif() -if( HAVE_LIBPTHREAD ) - set(LLVM_INTEL_JIT_LIBS pthread ${LLVM_INTEL_JIT_LIBS}) -endif() + +set(LLVM_INTEL_JIT_LIBS ${PTHREAD_LIB} ${LLVM_INTEL_JIT_LIBS}) + add_llvm_library(LLVMIntelJITEvents IntelJITEventListener.cpp diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index a131763193c0..0051c69efb7d 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -113,16 +113,29 @@ void IntelJITEventListener::NotifyObjectEmitted( std::vector<LineNumberInfo> LineInfo; std::string SourceFileName; - if (Sym.getType() != SymbolRef::ST_Function) + Expected<SymbolRef::Type> SymTypeOrErr = Sym.getType(); + if (!SymTypeOrErr) { + // TODO: Actually report errors helpfully. + consumeError(SymTypeOrErr.takeError()); + continue; + } + SymbolRef::Type SymType = *SymTypeOrErr; + if (SymType != SymbolRef::ST_Function) continue; - ErrorOr<StringRef> Name = Sym.getName(); - if (!Name) + Expected<StringRef> Name = Sym.getName(); + if (!Name) { + // TODO: Actually report errors helpfully. + consumeError(Name.takeError()); continue; + } - ErrorOr<uint64_t> AddrOrErr = Sym.getAddress(); - if (AddrOrErr.getError()) + Expected<uint64_t> AddrOrErr = Sym.getAddress(); + if (!AddrOrErr) { + // TODO: Actually report errors helpfully. + consumeError(AddrOrErr.takeError()); continue; + } uint64_t Addr = *AddrOrErr; uint64_t Size = P.second; diff --git a/lib/ExecutionEngine/IntelJITEvents/Makefile b/lib/ExecutionEngine/IntelJITEvents/Makefile deleted file mode 100644 index dcf3126cc529..000000000000 --- a/lib/ExecutionEngine/IntelJITEvents/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -##===- lib/ExecutionEngine/JITProfile/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = LLVMIntelJITEvents - -include $(LEVEL)/Makefile.config - -SOURCES := IntelJITEventListener.cpp \ - jitprofiling.c -CPPFLAGS += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/lib/ExecutionEngine/Interpreter/Makefile b/lib/ExecutionEngine/Interpreter/Makefile deleted file mode 100644 index 5def1365c61a..000000000000 --- a/lib/ExecutionEngine/Interpreter/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/Interpreter/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMInterpreter - -include $(LEVEL)/Makefile.common diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 6cbebe98e7c9..7fb328babfe8 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -85,6 +85,9 @@ MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM, std::unique_ptr<Module> First = std::move(Modules[0]); Modules.clear(); + if (First->getDataLayout().isDefault()) + First->setDataLayout(getDataLayout()); + OwnedModules.addModule(std::move(First)); RegisterJITEventListener(JITEventListener::createGDBRegistrationListener()); } @@ -103,6 +106,10 @@ MCJIT::~MCJIT() { void MCJIT::addModule(std::unique_ptr<Module> M) { MutexGuard locked(lock); + + if (M->getDataLayout().isDefault()) + M->setDataLayout(getDataLayout()); + OwnedModules.addModule(std::move(M)); } @@ -192,11 +199,7 @@ void MCJIT::generateCodeForModule(Module *M) { if (ObjCache) ObjectToLoad = ObjCache->getObject(M); - if (M->getDataLayout().isDefault()) { - M->setDataLayout(getDataLayout()); - } else { - assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch"); - } + assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch"); // If the cache did not contain a suitable object, compile the object if (!ObjectToLoad) { @@ -206,8 +209,15 @@ void MCJIT::generateCodeForModule(Module *M) { // Load the object into the dynamic linker. // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list). - ErrorOr<std::unique_ptr<object::ObjectFile>> LoadedObject = + Expected<std::unique_ptr<object::ObjectFile>> LoadedObject = object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef()); + if (!LoadedObject) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(LoadedObject.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(*LoadedObject.get()); @@ -317,15 +327,19 @@ RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, for (object::OwningBinary<object::Archive> &OB : Archives) { object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive - object::Archive::child_iterator ChildIt = A->findSym(Name); - if (std::error_code EC = ChildIt->getError()) - report_fatal_error(EC.message()); - if (ChildIt != A->child_end()) { + auto OptionalChildOrErr = A->findSym(Name); + if (!OptionalChildOrErr) + report_fatal_error(OptionalChildOrErr.takeError()); + auto &OptionalChild = *OptionalChildOrErr; + if (OptionalChild) { // FIXME: Support nested archives? - ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr = - (*ChildIt)->getAsBinary(); - if (ChildBinOrErr.getError()) + Expected<std::unique_ptr<object::Binary>> ChildBinOrErr = + OptionalChild->getAsBinary(); + if (!ChildBinOrErr) { + // TODO: Actually report errors helpfully. + consumeError(ChildBinOrErr.takeError()); continue; + } std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get(); if (ChildBin->isObject()) { std::unique_ptr<object::ObjectFile> OF( @@ -480,6 +494,7 @@ GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) { assert(F && "Function *F was null at entry to run()"); void *FPtr = getPointerToFunction(F); + finalizeModule(F->getParent()); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); FunctionType *FTy = F->getFunctionType(); Type *RetTy = FTy->getReturnType(); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 3c9d2fd50336..e25f76cd57f3 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -10,7 +10,6 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H #define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" diff --git a/lib/ExecutionEngine/MCJIT/Makefile b/lib/ExecutionEngine/MCJIT/Makefile deleted file mode 100644 index 967efbc0efa4..000000000000 --- a/lib/ExecutionEngine/MCJIT/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMCJIT - -include $(LEVEL)/Makefile.common diff --git a/lib/ExecutionEngine/Makefile b/lib/ExecutionEngine/Makefile deleted file mode 100644 index e9a5b79ddf62..000000000000 --- a/lib/ExecutionEngine/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- lib/ExecutionEngine/Makefile ------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../.. -LIBRARYNAME = LLVMExecutionEngine - -include $(LEVEL)/Makefile.config - -PARALLEL_DIRS = Interpreter MCJIT Orc RuntimeDyld - -ifeq ($(USE_INTEL_JITEVENTS), 1) -PARALLEL_DIRS += IntelJITEvents -endif - -ifeq ($(USE_OPROFILE), 1) -PARALLEL_DIRS += OProfileJIT -endif - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/lib/ExecutionEngine/OProfileJIT/Makefile b/lib/ExecutionEngine/OProfileJIT/Makefile deleted file mode 100644 index fd3adce26c1f..000000000000 --- a/lib/ExecutionEngine/OProfileJIT/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -##===- lib/ExecutionEngine/OProfileJIT/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = LLVMOProfileJIT - -include $(LEVEL)/Makefile.config - -SOURCES += OProfileJITEventListener.cpp \ - OProfileWrapper.cpp -CPPFLAGS += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp b/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp index 04edbd2a300e..d96278a8137b 100644 --- a/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp +++ b/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp @@ -23,7 +23,6 @@ #include <cstring> #include <dirent.h> #include <fcntl.h> -#include <sstream> #include <stddef.h> #include <sys/stat.h> #include <unistd.h> diff --git a/lib/ExecutionEngine/Orc/CMakeLists.txt b/lib/ExecutionEngine/Orc/CMakeLists.txt index d26f212e00c9..76720a7c52ec 100644 --- a/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -2,9 +2,8 @@ add_llvm_library(LLVMOrcJIT ExecutionUtils.cpp IndirectionUtils.cpp NullResolver.cpp - OrcArchitectureSupport.cpp + OrcABISupport.cpp OrcCBindings.cpp - OrcCBindingsStack.cpp OrcError.cpp OrcMCJITReplacement.cpp OrcRemoteTargetRPCAPI.cpp diff --git a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index 34564e42b10f..6f7c29feef0d 100644 --- a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -10,10 +10,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/IRBuilder.h" #include "llvm/Transforms/Utils/Cloning.h" -#include <set> #include <sstream> namespace llvm { @@ -22,6 +22,55 @@ namespace orc { void JITCompileCallbackManager::anchor() {} void IndirectStubsManager::anchor() {} +std::unique_ptr<JITCompileCallbackManager> +createLocalCompileCallbackManager(const Triple &T, + TargetAddress ErrorHandlerAddress) { + switch (T.getArch()) { + default: return nullptr; + + case Triple::x86: { + typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT; + return llvm::make_unique<CCMgrT>(ErrorHandlerAddress); + } + + case Triple::x86_64: { + if ( T.getOS() == Triple::OSType::Win32 ) { + typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT; + return llvm::make_unique<CCMgrT>(ErrorHandlerAddress); + } else { + typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_SysV> CCMgrT; + return llvm::make_unique<CCMgrT>(ErrorHandlerAddress); + } + } + } +} + +std::function<std::unique_ptr<IndirectStubsManager>()> +createLocalIndirectStubsManagerBuilder(const Triple &T) { + switch (T.getArch()) { + default: return nullptr; + + case Triple::x86: + return [](){ + return llvm::make_unique< + orc::LocalIndirectStubsManager<orc::OrcI386>>(); + }; + + case Triple::x86_64: + if (T.getOS() == Triple::OSType::Win32) { + return [](){ + return llvm::make_unique< + orc::LocalIndirectStubsManager<orc::OrcX86_64_Win32>>(); + }; + } else { + return [](){ + return llvm::make_unique< + orc::LocalIndirectStubsManager<orc::OrcX86_64_SysV>>(); + }; + } + } +} + Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr) { Constant *AddrIntVal = ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr); @@ -95,7 +144,7 @@ static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) { V.setLinkage(GlobalValue::ExternalLinkage); V.setVisibility(GlobalValue::HiddenVisibility); } - V.setUnnamedAddr(false); + V.setUnnamedAddr(GlobalValue::UnnamedAddr::None); assert(!R.needsRenaming(V) && "Invalid global name."); } @@ -116,7 +165,7 @@ Function* cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap) { assert(F.getParent() != &Dst && "Can't copy decl over existing function."); Function *NewF = - Function::Create(cast<FunctionType>(F.getType()->getElementType()), + Function::Create(cast<FunctionType>(F.getValueType()), F.getLinkage(), F.getName(), &Dst); NewF->copyAttributesFrom(&F); @@ -154,7 +203,7 @@ GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap) { assert(GV.getParent() != &Dst && "Can't copy decl over existing global var."); GlobalVariable *NewGV = new GlobalVariable( - Dst, GV.getType()->getElementType(), GV.isConstant(), + Dst, GV.getValueType(), GV.isConstant(), GV.getLinkage(), nullptr, GV.getName(), nullptr, GV.getThreadLocalMode(), GV.getType()->getAddressSpace()); NewGV->copyAttributesFrom(&GV); diff --git a/lib/ExecutionEngine/Orc/Makefile b/lib/ExecutionEngine/Orc/Makefile deleted file mode 100644 index ac302348ee7e..000000000000 --- a/lib/ExecutionEngine/Orc/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/OrcJIT/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMOrcJIT - -include $(LEVEL)/Makefile.common diff --git a/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/lib/ExecutionEngine/Orc/OrcABISupport.cpp new file mode 100644 index 000000000000..9869b6c7050c --- /dev/null +++ b/lib/ExecutionEngine/Orc/OrcABISupport.cpp @@ -0,0 +1,542 @@ +//===------------- OrcABISupport.cpp - ABI specific support code ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Process.h" + +namespace llvm { +namespace orc { + +void OrcAArch64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, + void *CallbackMgr) { + + const uint32_t ResolverCode[] = { + // resolver_entry: + 0xa9bf47fd, // 0x000: stp x29, x17, [sp, #-16]! + 0x910003fd, // 0x004: mov x29, sp + 0xa9bf73fb, // 0x008: stp x27, x28, [sp, #-16]! + 0xa9bf6bf9, // 0x00c: stp x25, x26, [sp, #-16]! + 0xa9bf63f7, // 0x010: stp x23, x24, [sp, #-16]! + 0xa9bf5bf5, // 0x014: stp x21, x22, [sp, #-16]! + 0xa9bf53f3, // 0x018: stp x19, x20, [sp, #-16]! + 0xa9bf3fee, // 0x01c: stp x14, x15, [sp, #-16]! + 0xa9bf37ec, // 0x020: stp x12, x13, [sp, #-16]! + 0xa9bf2fea, // 0x024: stp x10, x11, [sp, #-16]! + 0xa9bf27e8, // 0x028: stp x8, x9, [sp, #-16]! + 0xa9bf1fe6, // 0x02c: stp x6, x7, [sp, #-16]! + 0xa9bf17e4, // 0x030: stp x4, x5, [sp, #-16]! + 0xa9bf0fe2, // 0x034: stp x2, x3, [sp, #-16]! + 0xa9bf07e0, // 0x038: stp x0, x1, [sp, #-16]! + 0xadbf7ffe, // 0x03c: stp q30, q31, [sp, #-32]! + 0xadbf77fc, // 0x040: stp q28, q29, [sp, #-32]! + 0xadbf6ffa, // 0x044: stp q26, q27, [sp, #-32]! + 0xadbf67f8, // 0x048: stp q24, q25, [sp, #-32]! + 0xadbf5ff6, // 0x04c: stp q22, q23, [sp, #-32]! + 0xadbf57f4, // 0x050: stp q20, q21, [sp, #-32]! + 0xadbf4ff2, // 0x054: stp q18, q19, [sp, #-32]! + 0xadbf47f0, // 0x058: stp q16, q17, [sp, #-32]! + 0xadbf3fee, // 0x05c: stp q14, q15, [sp, #-32]! + 0xadbf37ec, // 0x060: stp q12, q13, [sp, #-32]! + 0xadbf2fea, // 0x064: stp q10, q11, [sp, #-32]! + 0xadbf27e8, // 0x068: stp q8, q9, [sp, #-32]! + 0xadbf1fe6, // 0x06c: stp q6, q7, [sp, #-32]! + 0xadbf17e4, // 0x070: stp q4, q5, [sp, #-32]! + 0xadbf0fe2, // 0x074: stp q2, q3, [sp, #-32]! + 0xadbf07e0, // 0x078: stp q0, q1, [sp, #-32]! + 0x580004e0, // 0x07c: ldr x0, Lcallbackmgr + 0xaa1e03e1, // 0x080: mov x1, x30 + 0xd1003021, // 0x084: sub x1, x1, #12 + 0x58000442, // 0x088: ldr x2, Lreentry_fn_ptr + 0xd63f0040, // 0x08c: blr x2 + 0xaa0003f1, // 0x090: mov x17, x0 + 0xacc107e0, // 0x094: ldp q0, q1, [sp], #32 + 0xacc10fe2, // 0x098: ldp q2, q3, [sp], #32 + 0xacc117e4, // 0x09c: ldp q4, q5, [sp], #32 + 0xacc11fe6, // 0x0a0: ldp q6, q7, [sp], #32 + 0xacc127e8, // 0x0a4: ldp q8, q9, [sp], #32 + 0xacc12fea, // 0x0a8: ldp q10, q11, [sp], #32 + 0xacc137ec, // 0x0ac: ldp q12, q13, [sp], #32 + 0xacc13fee, // 0x0b0: ldp q14, q15, [sp], #32 + 0xacc147f0, // 0x0b4: ldp q16, q17, [sp], #32 + 0xacc14ff2, // 0x0b8: ldp q18, q19, [sp], #32 + 0xacc157f4, // 0x0bc: ldp q20, q21, [sp], #32 + 0xacc15ff6, // 0x0c0: ldp q22, q23, [sp], #32 + 0xacc167f8, // 0x0c4: ldp q24, q25, [sp], #32 + 0xacc16ffa, // 0x0c8: ldp q26, q27, [sp], #32 + 0xacc177fc, // 0x0cc: ldp q28, q29, [sp], #32 + 0xacc17ffe, // 0x0d0: ldp q30, q31, [sp], #32 + 0xa8c107e0, // 0x0d4: ldp x0, x1, [sp], #16 + 0xa8c10fe2, // 0x0d8: ldp x2, x3, [sp], #16 + 0xa8c117e4, // 0x0dc: ldp x4, x5, [sp], #16 + 0xa8c11fe6, // 0x0e0: ldp x6, x7, [sp], #16 + 0xa8c127e8, // 0x0e4: ldp x8, x9, [sp], #16 + 0xa8c12fea, // 0x0e8: ldp x10, x11, [sp], #16 + 0xa8c137ec, // 0x0ec: ldp x12, x13, [sp], #16 + 0xa8c13fee, // 0x0f0: ldp x14, x15, [sp], #16 + 0xa8c153f3, // 0x0f4: ldp x19, x20, [sp], #16 + 0xa8c15bf5, // 0x0f8: ldp x21, x22, [sp], #16 + 0xa8c163f7, // 0x0fc: ldp x23, x24, [sp], #16 + 0xa8c16bf9, // 0x100: ldp x25, x26, [sp], #16 + 0xa8c173fb, // 0x104: ldp x27, x28, [sp], #16 + 0xa8c17bfd, // 0x108: ldp x29, x30, [sp], #16 + 0xd65f0220, // 0x10c: ret x17 + 0x01234567, // 0x110: Lreentry_fn_ptr: + 0xdeadbeef, // 0x114: .quad 0 + 0x98765432, // 0x118: Lcallbackmgr: + 0xcafef00d // 0x11c: .quad 0 + }; + + const unsigned ReentryFnAddrOffset = 0x110; + const unsigned CallbackMgrAddrOffset = 0x118; + + memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); + memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, + sizeof(CallbackMgr)); +} + +void OrcAArch64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, + unsigned NumTrampolines) { + + unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8); + + memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *)); + + // OffsetToPtr is actually the offset from the PC for the 2nd instruction, so + // subtract 32-bits. + OffsetToPtr -= 4; + + uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem); + + for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) { + Trampolines[3 * I + 0] = 0xaa1e03f1; // mov x17, x30 + Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // mov x16, Lptr + Trampolines[3 * I + 2] = 0xd63f0200; // blr x16 + } + +} + +Error OrcAArch64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, + unsigned MinStubs, + void *InitialPtrVal) { + // Stub format is: + // + // .section __orc_stubs + // stub1: + // ldr x0, ptr1 ; PC-rel load of ptr1 + // br x0 ; Jump to resolver + // stub2: + // ldr x0, ptr2 ; PC-rel load of ptr2 + // br x0 ; Jump to resolver + // + // ... + // + // .section __orc_ptrs + // ptr1: + // .quad 0x0 + // ptr2: + // .quad 0x0 + // + // ... + + const unsigned StubSize = IndirectStubsInfo::StubSize; + + // Emit at least MinStubs, rounded up to fill the pages allocated. + unsigned PageSize = sys::Process::getPageSize(); + unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; + unsigned NumStubs = (NumPages * PageSize) / StubSize; + + // Allocate memory for stubs and pointers in one call. + std::error_code EC; + auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( + 2 * NumPages * PageSize, nullptr, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); + + if (EC) + return errorCodeToError(EC); + + // Create separate MemoryBlocks representing the stubs and pointers. + sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); + sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + + NumPages * PageSize, + NumPages * PageSize); + + // Populate the stubs page stubs and mark it executable. + uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base()); + uint64_t PtrOffsetField = static_cast<uint64_t>(NumPages * PageSize) + << 3; + + for (unsigned I = 0; I < NumStubs; ++I) + Stub[I] = 0xd61f020058000010 | PtrOffsetField; + + if (auto EC = sys::Memory::protectMappedMemory( + StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) + return errorCodeToError(EC); + + // Initialize all pointers to point at FailureAddress. + void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); + for (unsigned I = 0; I < NumStubs; ++I) + Ptr[I] = InitialPtrVal; + + StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); + + return Error::success(); +} + +void OrcX86_64_Base::writeTrampolines(uint8_t *TrampolineMem, + void *ResolverAddr, + unsigned NumTrampolines) { + + unsigned OffsetToPtr = NumTrampolines * TrampolineSize; + + memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *)); + + uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineMem); + uint64_t CallIndirPCRel = 0xf1c40000000015ff; + + for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) + Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16); +} + +Error OrcX86_64_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, + unsigned MinStubs, + void *InitialPtrVal) { + // Stub format is: + // + // .section __orc_stubs + // stub1: + // jmpq *ptr1(%rip) + // .byte 0xC4 ; <- Invalid opcode padding. + // .byte 0xF1 + // stub2: + // jmpq *ptr2(%rip) + // + // ... + // + // .section __orc_ptrs + // ptr1: + // .quad 0x0 + // ptr2: + // .quad 0x0 + // + // ... + + const unsigned StubSize = IndirectStubsInfo::StubSize; + + // Emit at least MinStubs, rounded up to fill the pages allocated. + unsigned PageSize = sys::Process::getPageSize(); + unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; + unsigned NumStubs = (NumPages * PageSize) / StubSize; + + // Allocate memory for stubs and pointers in one call. + std::error_code EC; + auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( + 2 * NumPages * PageSize, nullptr, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); + + if (EC) + return errorCodeToError(EC); + + // Create separate MemoryBlocks representing the stubs and pointers. + sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); + sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + + NumPages * PageSize, + NumPages * PageSize); + + // Populate the stubs page stubs and mark it executable. + uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base()); + uint64_t PtrOffsetField = static_cast<uint64_t>(NumPages * PageSize - 6) + << 16; + for (unsigned I = 0; I < NumStubs; ++I) + Stub[I] = 0xF1C40000000025ff | PtrOffsetField; + + if (auto EC = sys::Memory::protectMappedMemory( + StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) + return errorCodeToError(EC); + + // Initialize all pointers to point at FailureAddress. + void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); + for (unsigned I = 0; I < NumStubs; ++I) + Ptr[I] = InitialPtrVal; + + StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); + + return Error::success(); +} + +void OrcX86_64_SysV::writeResolverCode(uint8_t *ResolverMem, + JITReentryFn ReentryFn, + void *CallbackMgr) { + + const uint8_t ResolverCode[] = { + // resolver_entry: + 0x55, // 0x00: pushq %rbp + 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp + 0x50, // 0x04: pushq %rax + 0x53, // 0x05: pushq %rbx + 0x51, // 0x06: pushq %rcx + 0x52, // 0x07: pushq %rdx + 0x56, // 0x08: pushq %rsi + 0x57, // 0x09: pushq %rdi + 0x41, 0x50, // 0x0a: pushq %r8 + 0x41, 0x51, // 0x0c: pushq %r9 + 0x41, 0x52, // 0x0e: pushq %r10 + 0x41, 0x53, // 0x10: pushq %r11 + 0x41, 0x54, // 0x12: pushq %r12 + 0x41, 0x55, // 0x14: pushq %r13 + 0x41, 0x56, // 0x16: pushq %r14 + 0x41, 0x57, // 0x18: pushq %r15 + 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 0x208, %rsp + 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) + 0x48, 0xbf, // 0x26: movabsq <CBMgr>, %rdi + + // 0x28: Callback manager addr. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x48, 0x8b, 0x75, 0x08, // 0x30: movq 8(%rbp), %rsi + 0x48, 0x83, 0xee, 0x06, // 0x34: subq $6, %rsi + 0x48, 0xb8, // 0x38: movabsq <REntry>, %rax + + // 0x3a: JIT re-entry fn addr: + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xff, 0xd0, // 0x42: callq *%rax + 0x48, 0x89, 0x45, 0x08, // 0x44: movq %rax, 8(%rbp) + 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x48: fxrstor64 (%rsp) + 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x4d: addq 0x208, %rsp + 0x41, 0x5f, // 0x54: popq %r15 + 0x41, 0x5e, // 0x56: popq %r14 + 0x41, 0x5d, // 0x58: popq %r13 + 0x41, 0x5c, // 0x5a: popq %r12 + 0x41, 0x5b, // 0x5c: popq %r11 + 0x41, 0x5a, // 0x5e: popq %r10 + 0x41, 0x59, // 0x60: popq %r9 + 0x41, 0x58, // 0x62: popq %r8 + 0x5f, // 0x64: popq %rdi + 0x5e, // 0x65: popq %rsi + 0x5a, // 0x66: popq %rdx + 0x59, // 0x67: popq %rcx + 0x5b, // 0x68: popq %rbx + 0x58, // 0x69: popq %rax + 0x5d, // 0x6a: popq %rbp + 0xc3, // 0x6b: retq + }; + + const unsigned ReentryFnAddrOffset = 0x3a; + const unsigned CallbackMgrAddrOffset = 0x28; + + memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); + memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, + sizeof(CallbackMgr)); +} + +void OrcX86_64_Win32::writeResolverCode(uint8_t *ResolverMem, + JITReentryFn ReentryFn, + void *CallbackMgr) { + + // resolverCode is similar to OrcX86_64 with differences specific to windows x64 calling convention: + // arguments go into rcx, rdx and come in reverse order, shadow space allocation on stack + const uint8_t ResolverCode[] = { + // resolver_entry: + 0x55, // 0x00: pushq %rbp + 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp + 0x50, // 0x04: pushq %rax + 0x53, // 0x05: pushq %rbx + 0x51, // 0x06: pushq %rcx + 0x52, // 0x07: pushq %rdx + 0x56, // 0x08: pushq %rsi + 0x57, // 0x09: pushq %rdi + 0x41, 0x50, // 0x0a: pushq %r8 + 0x41, 0x51, // 0x0c: pushq %r9 + 0x41, 0x52, // 0x0e: pushq %r10 + 0x41, 0x53, // 0x10: pushq %r11 + 0x41, 0x54, // 0x12: pushq %r12 + 0x41, 0x55, // 0x14: pushq %r13 + 0x41, 0x56, // 0x16: pushq %r14 + 0x41, 0x57, // 0x18: pushq %r15 + 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 0x208, %rsp + 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) + + 0x48, 0xb9, // 0x26: movabsq <CBMgr>, %rcx + // 0x28: Callback manager addr. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x48, 0x8B, 0x55, 0x08, // 0x30: mov rdx, [rbp+0x8] + 0x48, 0x83, 0xea, 0x06, // 0x34: sub rdx, 0x6 + + 0x48, 0xb8, // 0x38: movabsq <REntry>, %rax + // 0x3a: JIT re-entry fn addr: + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // 0x42: sub rsp, 0x20 (Allocate shadow space) + 0x48, 0x83, 0xEC, 0x20, + 0xff, 0xd0, // 0x46: callq *%rax + + // 0x48: add rsp, 0x20 (Free shadow space) + 0x48, 0x83, 0xC4, 0x20, + + 0x48, 0x89, 0x45, 0x08, // 0x4C: movq %rax, 8(%rbp) + 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x50: fxrstor64 (%rsp) + 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x55: addq 0x208, %rsp + 0x41, 0x5f, // 0x5C: popq %r15 + 0x41, 0x5e, // 0x5E: popq %r14 + 0x41, 0x5d, // 0x60: popq %r13 + 0x41, 0x5c, // 0x62: popq %r12 + 0x41, 0x5b, // 0x64: popq %r11 + 0x41, 0x5a, // 0x66: popq %r10 + 0x41, 0x59, // 0x68: popq %r9 + 0x41, 0x58, // 0x6a: popq %r8 + 0x5f, // 0x6c: popq %rdi + 0x5e, // 0x6d: popq %rsi + 0x5a, // 0x6e: popq %rdx + 0x59, // 0x6f: popq %rcx + 0x5b, // 0x70: popq %rbx + 0x58, // 0x71: popq %rax + 0x5d, // 0x72: popq %rbp + 0xc3, // 0x73: retq + }; + + + const unsigned ReentryFnAddrOffset = 0x3a; + const unsigned CallbackMgrAddrOffset = 0x28; + + memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); + memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, + sizeof(CallbackMgr)); +} + +void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, + void *CallbackMgr) { + + const uint8_t ResolverCode[] = { + // resolver_entry: + 0x55, // 0x00: pushl %ebp + 0x89, 0xe5, // 0x01: movl %esp, %ebp + 0x54, // 0x03: pushl %esp + 0x83, 0xe4, 0xf0, // 0x04: andl $-0x10, %esp + 0x50, // 0x07: pushl %eax + 0x53, // 0x08: pushl %ebx + 0x51, // 0x09: pushl %ecx + 0x52, // 0x0a: pushl %edx + 0x56, // 0x0b: pushl %esi + 0x57, // 0x0c: pushl %edi + 0x81, 0xec, 0x18, 0x02, 0x00, 0x00, // 0x0d: subl $0x218, %esp + 0x0f, 0xae, 0x44, 0x24, 0x10, // 0x13: fxsave 0x10(%esp) + 0x8b, 0x75, 0x04, // 0x18: movl 0x4(%ebp), %esi + 0x83, 0xee, 0x05, // 0x1b: subl $0x5, %esi + 0x89, 0x74, 0x24, 0x04, // 0x1e: movl %esi, 0x4(%esp) + 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, + 0x00, // 0x22: movl <cbmgr>, (%esp) + 0xb8, 0x00, 0x00, 0x00, 0x00, // 0x29: movl <reentry>, %eax + 0xff, 0xd0, // 0x2e: calll *%eax + 0x89, 0x45, 0x04, // 0x30: movl %eax, 0x4(%ebp) + 0x0f, 0xae, 0x4c, 0x24, 0x10, // 0x33: fxrstor 0x10(%esp) + 0x81, 0xc4, 0x18, 0x02, 0x00, 0x00, // 0x38: addl $0x218, %esp + 0x5f, // 0x3e: popl %edi + 0x5e, // 0x3f: popl %esi + 0x5a, // 0x40: popl %edx + 0x59, // 0x41: popl %ecx + 0x5b, // 0x42: popl %ebx + 0x58, // 0x43: popl %eax + 0x8b, 0x65, 0xfc, // 0x44: movl -0x4(%ebp), %esp + 0x5d, // 0x48: popl %ebp + 0xc3 // 0x49: retl + }; + + const unsigned ReentryFnAddrOffset = 0x2a; + const unsigned CallbackMgrAddrOffset = 0x25; + + memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); + memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, + sizeof(CallbackMgr)); +} + +void OrcI386::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, + unsigned NumTrampolines) { + + uint64_t CallRelImm = 0xF1C4C400000000e8; + uint64_t Resolver = reinterpret_cast<uint64_t>(ResolverAddr); + uint64_t ResolverRel = + Resolver - reinterpret_cast<uint64_t>(TrampolineMem) - 5; + + uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineMem); + for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize) + Trampolines[I] = CallRelImm | (ResolverRel << 8); +} + +Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, + unsigned MinStubs, void *InitialPtrVal) { + // Stub format is: + // + // .section __orc_stubs + // stub1: + // jmpq *ptr1 + // .byte 0xC4 ; <- Invalid opcode padding. + // .byte 0xF1 + // stub2: + // jmpq *ptr2 + // + // ... + // + // .section __orc_ptrs + // ptr1: + // .quad 0x0 + // ptr2: + // .quad 0x0 + // + // ... + + const unsigned StubSize = IndirectStubsInfo::StubSize; + + // Emit at least MinStubs, rounded up to fill the pages allocated. + unsigned PageSize = sys::Process::getPageSize(); + unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; + unsigned NumStubs = (NumPages * PageSize) / StubSize; + + // Allocate memory for stubs and pointers in one call. + std::error_code EC; + auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( + 2 * NumPages * PageSize, nullptr, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); + + if (EC) + return errorCodeToError(EC); + + // Create separate MemoryBlocks representing the stubs and pointers. + sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); + sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) + + NumPages * PageSize, + NumPages * PageSize); + + // Populate the stubs page stubs and mark it executable. + uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlock.base()); + uint64_t PtrAddr = reinterpret_cast<uint64_t>(PtrsBlock.base()); + for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4) + Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16); + + if (auto EC = sys::Memory::protectMappedMemory( + StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) + return errorCodeToError(EC); + + // Initialize all pointers to point at FailureAddress. + void **Ptr = reinterpret_cast<void **>(PtrsBlock.base()); + for (unsigned I = 0; I < NumStubs; ++I) + Ptr[I] = InitialPtrVal; + + StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); + + return Error::success(); +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp b/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp deleted file mode 100644 index 01e829f7909e..000000000000 --- a/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp +++ /dev/null @@ -1,171 +0,0 @@ -//===------ OrcArchSupport.cpp - Architecture specific support code -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" -#include "llvm/Support/Process.h" -#include <array> - -namespace llvm { -namespace orc { - -void OrcX86_64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, - void *CallbackMgr) { - - const uint8_t ResolverCode[] = { - // resolver_entry: - 0x55, // 0x00: pushq %rbp - 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp - 0x50, // 0x04: pushq %rax - 0x53, // 0x05: pushq %rbx - 0x51, // 0x06: pushq %rcx - 0x52, // 0x07: pushq %rdx - 0x56, // 0x08: pushq %rsi - 0x57, // 0x09: pushq %rdi - 0x41, 0x50, // 0x0a: pushq %r8 - 0x41, 0x51, // 0x0c: pushq %r9 - 0x41, 0x52, // 0x0e: pushq %r10 - 0x41, 0x53, // 0x10: pushq %r11 - 0x41, 0x54, // 0x12: pushq %r12 - 0x41, 0x55, // 0x14: pushq %r13 - 0x41, 0x56, // 0x16: pushq %r14 - 0x41, 0x57, // 0x18: pushq %r15 - 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 20, %rsp - 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) - 0x48, 0x8d, 0x3d, 0x43, 0x00, 0x00, 0x00, // 0x26: leaq 67(%rip), %rdi - 0x48, 0x8b, 0x3f, // 0x2d: movq (%rdi), %rdi - 0x48, 0x8b, 0x75, 0x08, // 0x30: movq 8(%rbp), %rsi - 0x48, 0x83, 0xee, 0x06, // 0x34: subq $6, %rsi - 0x48, 0xb8, // 0x38: movabsq $0, %rax - - // 0x3a: JIT re-entry fn addr: - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0xff, 0xd0, // 0x42: callq *%rax - 0x48, 0x89, 0x45, 0x08, // 0x44: movq %rax, 8(%rbp) - 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x48: fxrstor64 (%rsp) - 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x4d: addq 20, %rsp - 0x41, 0x5f, // 0x54: popq %r15 - 0x41, 0x5e, // 0x56: popq %r14 - 0x41, 0x5d, // 0x58: popq %r13 - 0x41, 0x5c, // 0x5a: popq %r12 - 0x41, 0x5b, // 0x5c: popq %r11 - 0x41, 0x5a, // 0x5e: popq %r10 - 0x41, 0x59, // 0x60: popq %r9 - 0x41, 0x58, // 0x62: popq %r8 - 0x5f, // 0x64: popq %rdi - 0x5e, // 0x65: popq %rsi - 0x5a, // 0x66: popq %rdx - 0x59, // 0x67: popq %rcx - 0x5b, // 0x68: popq %rbx - 0x58, // 0x69: popq %rax - 0x5d, // 0x6a: popq %rbp - 0xc3, // 0x6b: retq - 0x00, 0x00, 0x00, 0x00, // 0x6c: <padding> - - // 0x70: Callback mgr address. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - const unsigned ReentryFnAddrOffset = 0x3a; - const unsigned CallbackMgrAddrOffset = 0x70; - - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, - sizeof(CallbackMgr)); -} - -void OrcX86_64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, - unsigned NumTrampolines) { - - unsigned OffsetToPtr = NumTrampolines * TrampolineSize; - - memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void*)); - - uint64_t *Trampolines = reinterpret_cast<uint64_t*>(TrampolineMem); - uint64_t CallIndirPCRel = 0xf1c40000000015ff; - - for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) - Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16); -} - -std::error_code OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, - void *InitialPtrVal) { - // Stub format is: - // - // .section __orc_stubs - // stub1: - // jmpq *ptr1(%rip) - // .byte 0xC4 ; <- Invalid opcode padding. - // .byte 0xF1 - // stub2: - // jmpq *ptr2(%rip) - // - // ... - // - // .section __orc_ptrs - // ptr1: - // .quad 0x0 - // ptr2: - // .quad 0x0 - // - // ... - - const unsigned StubSize = IndirectStubsInfo::StubSize; - - // Emit at least MinStubs, rounded up to fill the pages allocated. - unsigned PageSize = sys::Process::getPageSize(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; - - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = - sys::OwningMemoryBlock( - sys::Memory::allocateMappedMemory(2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | - sys::Memory::MF_WRITE, - EC)); - - if (EC) - return EC; - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast<char*>(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); - - // Populate the stubs page stubs and mark it executable. - uint64_t *Stub = reinterpret_cast<uint64_t*>(StubsBlock.base()); - uint64_t PtrOffsetField = - static_cast<uint64_t>(NumPages * PageSize - 6) << 16; - for (unsigned I = 0; I < NumStubs; ++I) - Stub[I] = 0xF1C40000000025ff | PtrOffsetField; - - if (auto EC = sys::Memory::protectMappedMemory(StubsBlock, - sys::Memory::MF_READ | - sys::Memory::MF_EXEC)) - return EC; - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast<void**>(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo.NumStubs = NumStubs; - StubsInfo.StubsMem = std::move(StubsMem); - - return std::error_code(); -} - -} // End namespace orc. -} // End namespace llvm. diff --git a/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/lib/ExecutionEngine/Orc/OrcCBindings.cpp index d2379cd441d5..8dcd49aaab5b 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindings.cpp +++ b/lib/ExecutionEngine/Orc/OrcCBindings.cpp @@ -17,17 +17,21 @@ LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) { Triple T(TM2->getTargetTriple()); - auto CompileCallbackMgr = OrcCBindingsStack::createCompileCallbackMgr(T); + auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0); auto IndirectStubsMgrBuilder = - OrcCBindingsStack::createIndirectStubsMgrBuilder(T); + orc::createLocalIndirectStubsManagerBuilder(T); - OrcCBindingsStack *JITStack = - new OrcCBindingsStack(*TM2, std::move(CompileCallbackMgr), - IndirectStubsMgrBuilder); + OrcCBindingsStack *JITStack = new OrcCBindingsStack( + *TM2, std::move(CompileCallbackMgr), IndirectStubsMgrBuilder); return wrap(JITStack); } +const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack) { + OrcCBindingsStack &J = *unwrap(JITStack); + return J.getErrorMessage().c_str(); +} + void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName, const char *SymbolName) { OrcCBindingsStack &J = *unwrap(JITStack); @@ -36,9 +40,7 @@ void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName, strcpy(*MangledName, Mangled.c_str()); } -void LLVMOrcDisposeMangledSymbol(char *MangledName) { - delete[] MangledName; -} +void LLVMOrcDisposeMangledSymbol(char *MangledName) { delete[] MangledName; } LLVMOrcTargetAddress LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack, @@ -48,18 +50,18 @@ LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack, return J.createLazyCompileCallback(Callback, CallbackCtx); } -void LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, - const char *StubName, - LLVMOrcTargetAddress InitAddr) { +LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack, + const char *StubName, + LLVMOrcTargetAddress InitAddr) { OrcCBindingsStack &J = *unwrap(JITStack); - J.createIndirectStub(StubName, InitAddr); + return J.createIndirectStub(StubName, InitAddr); } -void LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, - const char *StubName, - LLVMOrcTargetAddress NewAddr) { +LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, + const char *StubName, + LLVMOrcTargetAddress NewAddr) { OrcCBindingsStack &J = *unwrap(JITStack); - J.setIndirectStubPointer(StubName, NewAddr); + return J.setIndirectStubPointer(StubName, NewAddr); } LLVMOrcModuleHandle diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp b/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp deleted file mode 100644 index 956daae372da..000000000000 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===-------- OrcCBindingsStack.cpp - Orc JIT stack for C bindings --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "OrcCBindingsStack.h" - -#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include <cstdio> -#include <system_error> - -using namespace llvm; - -std::unique_ptr<OrcCBindingsStack::CompileCallbackMgr> -OrcCBindingsStack::createCompileCallbackMgr(Triple T) { - switch (T.getArch()) { - default: return nullptr; - - case Triple::x86_64: { - typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64> CCMgrT; - return llvm::make_unique<CCMgrT>(0); - } - } -} - -OrcCBindingsStack::IndirectStubsManagerBuilder -OrcCBindingsStack::createIndirectStubsMgrBuilder(Triple T) { - switch (T.getArch()) { - default: return nullptr; - - case Triple::x86_64: - return [](){ - return llvm::make_unique< - orc::LocalIndirectStubsManager<orc::OrcX86_64>>(); - }; - } -} diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index aae6a99432bc..9ae9b20feb0a 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -10,6 +10,7 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H +#include "llvm-c/OrcBindings.h" #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" @@ -17,7 +18,7 @@ #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/IR/LLVMContext.h" -#include "llvm-c/OrcBindings.h" +#include "llvm/Support/Error.h" namespace llvm { @@ -28,19 +29,18 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) class OrcCBindingsStack { public: - typedef orc::JITCompileCallbackManager CompileCallbackMgr; typedef orc::ObjectLinkingLayer<> ObjLayerT; typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT; - typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr> CODLayerT; + typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr> + CODLayerT; typedef std::function<std::unique_ptr<CompileCallbackMgr>()> - CallbackManagerBuilder; + CallbackManagerBuilder; typedef CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder; private: - class GenericHandle { public: virtual ~GenericHandle() {} @@ -49,20 +49,17 @@ private: virtual void removeModule() = 0; }; - template <typename LayerT> - class GenericHandleImpl : public GenericHandle { + template <typename LayerT> class GenericHandleImpl : public GenericHandle { public: GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleSetHandleT Handle) - : Layer(Layer), Handle(std::move(Handle)) {} + : Layer(Layer), Handle(std::move(Handle)) {} orc::JITSymbol findSymbolIn(const std::string &Name, bool ExportedSymbolsOnly) override { return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly); } - void removeModule() override { - return Layer.removeModuleSet(Handle); - } + void removeModule() override { return Layer.removeModuleSet(Handle); } private: LayerT &Layer; @@ -77,26 +74,22 @@ private: } public: - // We need a 'ModuleSetHandleT' to conform to the layer concept. typedef unsigned ModuleSetHandleT; typedef unsigned ModuleHandleT; - static std::unique_ptr<CompileCallbackMgr> createCompileCallbackMgr(Triple T); - static IndirectStubsManagerBuilder createIndirectStubsMgrBuilder(Triple T); - OrcCBindingsStack(TargetMachine &TM, - std::unique_ptr<CompileCallbackMgr> CCMgr, + std::unique_ptr<CompileCallbackMgr> CCMgr, IndirectStubsManagerBuilder IndirectStubsMgrBuilder) - : DL(TM.createDataLayout()), CCMgr(std::move(CCMgr)), - ObjectLayer(), - CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)), - CODLayer(CompileLayer, - [](Function &F) { std::set<Function*> S; S.insert(&F); return S; }, - *this->CCMgr, std::move(IndirectStubsMgrBuilder), false), - IndirectStubsMgr(IndirectStubsMgrBuilder()), - CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {} + : DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()), + CCMgr(std::move(CCMgr)), ObjectLayer(), + CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)), + CODLayer(CompileLayer, + [](Function &F) { return std::set<Function *>({&F}); }, + *this->CCMgr, std::move(IndirectStubsMgrBuilder), false), + CXXRuntimeOverrides( + [this](const std::string &S) { return mangle(S); }) {} ~OrcCBindingsStack() { // Run any destructors registered with __cxa_atexit. @@ -124,55 +117,52 @@ public: createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) { auto CCInfo = CCMgr->getCompileCallback(); - CCInfo.setCompileAction( - [=]() -> orc::TargetAddress { - return Callback(wrap(this), CallbackCtx); - }); + CCInfo.setCompileAction([=]() -> orc::TargetAddress { + return Callback(wrap(this), CallbackCtx); + }); return CCInfo.getAddress(); } - void createIndirectStub(StringRef StubName, orc::TargetAddress Addr) { - IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported); + LLVMOrcErrorCode createIndirectStub(StringRef StubName, + orc::TargetAddress Addr) { + return mapError( + IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported)); } - void setIndirectStubPointer(StringRef Name, orc::TargetAddress Addr) { - IndirectStubsMgr->updatePointer(Name, Addr); + LLVMOrcErrorCode setIndirectStubPointer(StringRef Name, + orc::TargetAddress Addr) { + return mapError(IndirectStubsMgr->updatePointer(Name, Addr)); } - std::shared_ptr<RuntimeDyld::SymbolResolver> + std::unique_ptr<RuntimeDyld::SymbolResolver> createResolver(LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx) { - auto Resolver = orc::createLambdaResolver( - [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) { - // Search order: - // 1. JIT'd symbols. - // 2. Runtime overrides. - // 3. External resolver (if present). - - if (auto Sym = CODLayer.findSymbol(Name, true)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), - Sym.getFlags()); - if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) - return Sym; - - if (ExternalResolver) - return RuntimeDyld::SymbolInfo(ExternalResolver(Name.c_str(), - ExternalResolverCtx), - llvm::JITSymbolFlags::Exported); - - return RuntimeDyld::SymbolInfo(nullptr); - }, - [](const std::string &Name) { - return RuntimeDyld::SymbolInfo(nullptr); - } - ); - - return std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(Resolver)); + return orc::createLambdaResolver( + [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) { + // Search order: + // 1. JIT'd symbols. + // 2. Runtime overrides. + // 3. External resolver (if present). + + if (auto Sym = CODLayer.findSymbol(Name, true)) + return Sym.toRuntimeDyldSymbol(); + if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) + return Sym; + + if (ExternalResolver) + return RuntimeDyld::SymbolInfo( + ExternalResolver(Name.c_str(), ExternalResolverCtx), + llvm::JITSymbolFlags::Exported); + + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &Name) { + return RuntimeDyld::SymbolInfo(nullptr); + }); } template <typename LayerT> - ModuleHandleT addIRModule(LayerT &Layer, - Module *M, + ModuleHandleT addIRModule(LayerT &Layer, Module *M, std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx) { @@ -193,7 +183,7 @@ public: auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx); // Add the module to the JIT. - std::vector<Module*> S; + std::vector<Module *> S; S.push_back(std::move(M)); auto LH = Layer.addModuleSet(std::move(S), std::move(MemMgr), @@ -210,7 +200,7 @@ public: return H; } - ModuleHandleT addIRModuleEager(Module* M, + ModuleHandleT addIRModuleEager(Module *M, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx) { return addIRModule(CompileLayer, std::move(M), @@ -218,11 +208,11 @@ public: std::move(ExternalResolver), ExternalResolverCtx); } - ModuleHandleT addIRModuleLazy(Module* M, + ModuleHandleT addIRModuleLazy(Module *M, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx) { return addIRModule(CODLayer, std::move(M), - llvm::make_unique<SectionMemoryManager>(), + llvm::make_unique<SectionMemoryManager>(), std::move(ExternalResolver), ExternalResolverCtx); } @@ -243,8 +233,9 @@ public: return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly); } -private: + const std::string &getErrorMessage() const { return ErrMsg; } +private: template <typename LayerT> unsigned createHandle(LayerT &Layer, typename LayerT::ModuleSetHandleT Handle) { @@ -261,21 +252,34 @@ private: return NewHandle; } + LLVMOrcErrorCode mapError(Error Err) { + LLVMOrcErrorCode Result = LLVMOrcErrSuccess; + handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { + // Handler of last resort. + Result = LLVMOrcErrGeneric; + ErrMsg = ""; + raw_string_ostream ErrStream(ErrMsg); + EIB.log(ErrStream); + }); + return Result; + } + DataLayout DL; SectionMemoryManager CCMgrMemMgr; + std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr; + std::unique_ptr<CompileCallbackMgr> CCMgr; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; CODLayerT CODLayer; - std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr; - std::vector<std::unique_ptr<GenericHandle>> GenericHandles; std::vector<unsigned> FreeHandleIndexes; orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners; + std::string ErrMsg; }; } // end namespace llvm diff --git a/lib/ExecutionEngine/Orc/OrcError.cpp b/lib/ExecutionEngine/Orc/OrcError.cpp index e95115ec6fed..22f1303f4330 100644 --- a/lib/ExecutionEngine/Orc/OrcError.cpp +++ b/lib/ExecutionEngine/Orc/OrcError.cpp @@ -20,6 +20,9 @@ using namespace llvm::orc; namespace { +// FIXME: This class is only here to support the transition to llvm::Error. It +// will be removed once this transition is complete. Clients should prefer to +// deal with the Error value directly, rather than converting to error_code. class OrcErrorCategory : public std::error_category { public: const char *name() const LLVM_NOEXCEPT override { return "orc"; } @@ -38,6 +41,8 @@ public: return "Remote indirect stubs owner Id already in use"; case OrcErrorCode::UnexpectedRPCCall: return "Unexpected RPC call"; + case OrcErrorCode::UnexpectedRPCResponse: + return "Unexpected RPC response"; } llvm_unreachable("Unhandled error code"); } @@ -49,9 +54,10 @@ static ManagedStatic<OrcErrorCategory> OrcErrCat; namespace llvm { namespace orc { -std::error_code orcError(OrcErrorCode ErrCode) { +Error orcError(OrcErrorCode ErrCode) { typedef std::underlying_type<OrcErrorCode>::type UT; - return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat); + return errorCodeToError( + std::error_code(static_cast<UT>(ErrCode), *OrcErrCat)); } } } diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 2ab70a9fee86..d1083072c98b 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -121,7 +121,7 @@ class OrcMCJITReplacement : public ExecutionEngine { RuntimeDyld::SymbolInfo findSymbolInLogicalDylib(const std::string &Name) override { - return M.ClientResolver->findSymbolInLogicalDylib(Name); + return M.ClientResolver->findSymbol(Name); } private: @@ -178,11 +178,10 @@ public: } void addObjectFile(object::OwningBinary<object::ObjectFile> O) override { - std::unique_ptr<object::ObjectFile> Obj; - std::unique_ptr<MemoryBuffer> Buf; - std::tie(Obj, Buf) = O.takeBinary(); - std::vector<std::unique_ptr<object::ObjectFile>> Objs; - Objs.push_back(std::move(Obj)); + std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>> Objs; + Objs.push_back( + llvm::make_unique<object::OwningBinary<object::ObjectFile>>( + std::move(O))); ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver); } @@ -246,11 +245,11 @@ private: RuntimeDyld::SymbolInfo findMangledSymbol(StringRef Name) { if (auto Sym = LazyEmitLayer.findSymbol(Name, false)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + return Sym.toRuntimeDyldSymbol(); if (auto Sym = ClientResolver->findSymbol(Name)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + return Sym; if (auto Sym = scanArchives(Name)) - return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + return Sym.toRuntimeDyldSymbol(); return nullptr; } @@ -259,15 +258,19 @@ private: for (object::OwningBinary<object::Archive> &OB : Archives) { object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive - object::Archive::child_iterator ChildIt = A->findSym(Name); - if (std::error_code EC = ChildIt->getError()) - report_fatal_error(EC.message()); - if (ChildIt != A->child_end()) { + auto OptionalChildOrErr = A->findSym(Name); + if (!OptionalChildOrErr) + report_fatal_error(OptionalChildOrErr.takeError()); + auto &OptionalChild = *OptionalChildOrErr; + if (OptionalChild) { // FIXME: Support nested archives? - ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr = - (*ChildIt)->getAsBinary(); - if (ChildBinOrErr.getError()) + Expected<std::unique_ptr<object::Binary>> ChildBinOrErr = + OptionalChild->getAsBinary(); + if (!ChildBinOrErr) { + // TODO: Actually report errors helpfully. + consumeError(ChildBinOrErr.takeError()); continue; + } std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get(); if (ChildBin->isObject()) { std::vector<std::unique_ptr<object::ObjectFile>> ObjSet; @@ -284,12 +287,12 @@ private: class NotifyObjectLoadedT { public: - typedef std::vector<std::unique_ptr<object::ObjectFile>> ObjListT; typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>> LoadedObjInfoListT; NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {} + template <typename ObjListT> void operator()(ObjectLinkingLayerBase::ObjSetHandleT H, const ObjListT &Objects, const LoadedObjInfoListT &Infos) const { @@ -298,10 +301,21 @@ private: assert(Objects.size() == Infos.size() && "Incorrect number of Infos for Objects."); for (unsigned I = 0; I < Objects.size(); ++I) - M.MemMgr.notifyObjectLoaded(&M, *Objects[I]); + M.MemMgr.notifyObjectLoaded(&M, getObject(*Objects[I])); } private: + + static const object::ObjectFile& getObject(const object::ObjectFile &Obj) { + return Obj; + } + + template <typename ObjT> + static const object::ObjectFile& + getObject(const object::OwningBinary<ObjT> &Obj) { + return *Obj.getBinary(); + } + OrcMCJITReplacement &M; }; diff --git a/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp b/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp index 064633b4e490..d1a021aee3ab 100644 --- a/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp +++ b/lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp @@ -13,71 +13,41 @@ namespace llvm { namespace orc { namespace remote { -const char *OrcRemoteTargetRPCAPI::getJITProcIdName(JITProcId Id) { +#define FUNCNAME(X) \ + case X ## Id: \ + return #X + +const char *OrcRemoteTargetRPCAPI::getJITFuncIdName(JITFuncId Id) { switch (Id) { case InvalidId: - return "*** Invalid JITProcId ***"; - case CallIntVoidId: - return "CallIntVoid"; - case CallIntVoidResponseId: - return "CallIntVoidResponse"; - case CallMainId: - return "CallMain"; - case CallMainResponseId: - return "CallMainResponse"; - case CallVoidVoidId: - return "CallVoidVoid"; - case CallVoidVoidResponseId: - return "CallVoidVoidResponse"; - case CreateRemoteAllocatorId: - return "CreateRemoteAllocator"; - case CreateIndirectStubsOwnerId: - return "CreateIndirectStubsOwner"; - case DestroyRemoteAllocatorId: - return "DestroyRemoteAllocator"; - case DestroyIndirectStubsOwnerId: - return "DestroyIndirectStubsOwner"; - case EmitIndirectStubsId: - return "EmitIndirectStubs"; - case EmitIndirectStubsResponseId: - return "EmitIndirectStubsResponse"; - case EmitResolverBlockId: - return "EmitResolverBlock"; - case EmitTrampolineBlockId: - return "EmitTrampolineBlock"; - case EmitTrampolineBlockResponseId: - return "EmitTrampolineBlockResponse"; - case GetSymbolAddressId: - return "GetSymbolAddress"; - case GetSymbolAddressResponseId: - return "GetSymbolAddressResponse"; - case GetRemoteInfoId: - return "GetRemoteInfo"; - case GetRemoteInfoResponseId: - return "GetRemoteInfoResponse"; - case ReadMemId: - return "ReadMem"; - case ReadMemResponseId: - return "ReadMemResponse"; - case ReserveMemId: - return "ReserveMem"; - case ReserveMemResponseId: - return "ReserveMemResponse"; - case RequestCompileId: - return "RequestCompile"; - case RequestCompileResponseId: - return "RequestCompileResponse"; - case SetProtectionsId: - return "SetProtections"; - case TerminateSessionId: - return "TerminateSession"; - case WriteMemId: - return "WriteMem"; - case WritePtrId: - return "WritePtr"; + return "*** Invalid JITFuncId ***"; + FUNCNAME(CallIntVoid); + FUNCNAME(CallMain); + FUNCNAME(CallVoidVoid); + FUNCNAME(CreateRemoteAllocator); + FUNCNAME(CreateIndirectStubsOwner); + FUNCNAME(DeregisterEHFrames); + FUNCNAME(DestroyRemoteAllocator); + FUNCNAME(DestroyIndirectStubsOwner); + FUNCNAME(EmitIndirectStubs); + FUNCNAME(EmitResolverBlock); + FUNCNAME(EmitTrampolineBlock); + FUNCNAME(GetSymbolAddress); + FUNCNAME(GetRemoteInfo); + FUNCNAME(ReadMem); + FUNCNAME(RegisterEHFrames); + FUNCNAME(ReserveMem); + FUNCNAME(RequestCompile); + FUNCNAME(SetProtections); + FUNCNAME(TerminateSession); + FUNCNAME(WriteMem); + FUNCNAME(WritePtr); }; return nullptr; } -} -} -} + +#undef FUNCNAME + +} // end namespace remote +} // end namespace orc +} // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/Makefile b/lib/ExecutionEngine/RuntimeDyld/Makefile deleted file mode 100644 index 5d6f26d950fe..000000000000 --- a/lib/ExecutionEngine/RuntimeDyld/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMRuntimeDyld - -include $(LEVEL)/Makefile.common diff --git a/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp index ecd99004bade..e39acc7ee144 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -94,9 +94,8 @@ static const char *processFDE(const char *Entry, bool isDeregister) { // This implementation handles frame registration for local targets. // Memory managers for remote targets should re-implement this function // and use the LoadAddr parameter. -void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, - uint64_t LoadAddr, - size_t Size) { +void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr, + size_t Size) { // On OS X OS X __register_frame takes a single FDE as an argument. // See http://lists.llvm.org/pipermail/llvm-dev/2013-April/061768.html const char *P = (const char *)Addr; @@ -106,9 +105,8 @@ void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, } while(P != End); } -void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, - uint64_t LoadAddr, - size_t Size) { +void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr, + size_t Size) { const char *P = (const char *)Addr; const char *End = P + Size; do { @@ -118,9 +116,8 @@ void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, #else -void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, - uint64_t LoadAddr, - size_t Size) { +void RTDyldMemoryManager::registerEHFramesInProcess(uint8_t *Addr, + size_t Size) { // On Linux __register_frame takes a single argument: // a pointer to the start of the .eh_frame section. @@ -129,9 +126,8 @@ void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, __register_frame(Addr); } -void RTDyldMemoryManager::deregisterEHFrames(uint8_t *Addr, - uint64_t LoadAddr, - size_t Size) { +void RTDyldMemoryManager::deregisterEHFramesInProcess(uint8_t *Addr, + size_t Size) { __deregister_frame(Addr); } @@ -266,18 +262,15 @@ RTDyldMemoryManager::getSymbolAddressInProcess(const std::string &Name) { // is called before ExecutionEngine::runFunctionAsMain() is called. if (Name == "__main") return (uint64_t)&jit_noop; - // Try to demangle Name before looking it up in the process, otherwise symbol - // '_<Name>' (if present) will shadow '<Name>', and there will be no way to - // refer to the latter. - const char *NameStr = Name.c_str(); + // DynamicLibrary::SearchForAddresOfSymbol expects an unmangled 'C' symbol + // name so ff we're on Darwin, strip the leading '_' off. +#ifdef __APPLE__ if (NameStr[0] == '_') - if (void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr + 1)) - return (uint64_t)Ptr; + ++NameStr; +#endif - // If we Name did not require demangling, or we failed to find the demangled - // name, try again without demangling. return (uint64_t)sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); } @@ -288,6 +281,7 @@ void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name, if (!Addr && AbortOnFailure) report_fatal_error("Program used external function '" + Name + "' which could not be resolved!"); + return (void*)Addr; } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index d16b2db24e1a..1dfbe31f2717 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -19,6 +19,7 @@ #include "RuntimeDyldMachO.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/COFF.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MutexGuard.h" @@ -27,6 +28,41 @@ using namespace llvm::object; #define DEBUG_TYPE "dyld" +namespace { + +enum RuntimeDyldErrorCode { + GenericRTDyldError = 1 +}; + +// FIXME: This class is only here to support the transition to llvm::Error. It +// will be removed once this transition is complete. Clients should prefer to +// deal with the Error value directly, rather than converting to error_code. +class RuntimeDyldErrorCategory : public std::error_category { +public: + const char *name() const LLVM_NOEXCEPT override { return "runtimedyld"; } + + std::string message(int Condition) const override { + switch (static_cast<RuntimeDyldErrorCode>(Condition)) { + case GenericRTDyldError: return "Generic RuntimeDyld error"; + } + llvm_unreachable("Unrecognized RuntimeDyldErrorCode"); + } +}; + +static ManagedStatic<RuntimeDyldErrorCategory> RTDyldErrorCategory; + +} + +char RuntimeDyldError::ID = 0; + +void RuntimeDyldError::log(raw_ostream &OS) const { + OS << ErrMsg << "\n"; +} + +std::error_code RuntimeDyldError::convertToErrorCode() const { + return std::error_code(GenericRTDyldError, *RTDyldErrorCategory); +} + // Empty out-of-line virtual destructor as the key function. RuntimeDyldImpl::~RuntimeDyldImpl() {} @@ -125,16 +161,16 @@ void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress, llvm_unreachable("Attempting to remap address of unknown section!"); } -static std::error_code getOffset(const SymbolRef &Sym, SectionRef Sec, - uint64_t &Result) { - ErrorOr<uint64_t> AddressOrErr = Sym.getAddress(); - if (std::error_code EC = AddressOrErr.getError()) - return EC; +static Error getOffset(const SymbolRef &Sym, SectionRef Sec, + uint64_t &Result) { + Expected<uint64_t> AddressOrErr = Sym.getAddress(); + if (!AddressOrErr) + return AddressOrErr.takeError(); Result = *AddressOrErr - Sec.getAddress(); - return std::error_code(); + return Error::success(); } -RuntimeDyldImpl::ObjSectionToIDMap +Expected<RuntimeDyldImpl::ObjSectionToIDMap> RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { MutexGuard locked(lock); @@ -148,8 +184,11 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { if (MemMgr.needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, RODataSize = 0, RWDataSize = 0; uint32_t CodeAlign = 1, RODataAlign = 1, RWDataAlign = 1; - computeTotalAllocSize(Obj, CodeSize, CodeAlign, RODataSize, RODataAlign, - RWDataSize, RWDataAlign); + if (auto Err = computeTotalAllocSize(Obj, + CodeSize, CodeAlign, + RODataSize, RODataAlign, + RWDataSize, RWDataAlign)) + return std::move(Err); MemMgr.reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, RWDataSize, RWDataAlign); } @@ -169,13 +208,21 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { if (Flags & SymbolRef::SF_Common) CommonSymbols.push_back(*I); else { - object::SymbolRef::Type SymType = I->getType(); + + // Get the symbol type. + object::SymbolRef::Type SymType; + if (auto SymTypeOrErr = I->getType()) + SymType = *SymTypeOrErr; + else + return SymTypeOrErr.takeError(); // Get symbol name. - ErrorOr<StringRef> NameOrErr = I->getName(); - Check(NameOrErr.getError()); - StringRef Name = *NameOrErr; - + StringRef Name; + if (auto NameOrErr = I->getName()) + Name = *NameOrErr; + else + return NameOrErr.takeError(); + // Compute JIT symbol flags. JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; if (Flags & SymbolRef::SF_Weak) @@ -185,32 +232,46 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { if (Flags & SymbolRef::SF_Absolute && SymType != object::SymbolRef::ST_File) { - auto Addr = I->getAddress(); - Check(Addr.getError()); - uint64_t SectOffset = *Addr; + uint64_t Addr = 0; + if (auto AddrOrErr = I->getAddress()) + Addr = *AddrOrErr; + else + return AddrOrErr.takeError(); + unsigned SectionID = AbsoluteSymbolSection; DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name << " SID: " << SectionID << " Offset: " - << format("%p", (uintptr_t)SectOffset) + << format("%p", (uintptr_t)Addr) << " flags: " << Flags << "\n"); GlobalSymbolTable[Name] = - SymbolTableEntry(SectionID, SectOffset, RTDyldSymFlags); + SymbolTableEntry(SectionID, Addr, RTDyldSymFlags); } else if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown || SymType == object::SymbolRef::ST_Other) { - ErrorOr<section_iterator> SIOrErr = I->getSection(); - Check(SIOrErr.getError()); - section_iterator SI = *SIOrErr; + section_iterator SI = Obj.section_end(); + if (auto SIOrErr = I->getSection()) + SI = *SIOrErr; + else + return SIOrErr.takeError(); + if (SI == Obj.section_end()) continue; + // Get symbol offset. uint64_t SectOffset; - Check(getOffset(*I, *SI, SectOffset)); + if (auto Err = getOffset(*I, *SI, SectOffset)) + return std::move(Err); + bool IsCode = SI->isText(); - unsigned SectionID = findOrEmitSection(Obj, *SI, IsCode, LocalSections); + unsigned SectionID; + if (auto SectionIDOrErr = findOrEmitSection(Obj, *SI, IsCode, + LocalSections)) + SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << " SID: " << SectionID << " Offset: " @@ -223,13 +284,13 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { } // Allocate common symbols - emitCommonSymbols(Obj, CommonSymbols); + if (auto Err = emitCommonSymbols(Obj, CommonSymbols)) + return std::move(Err); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { - unsigned SectionID = 0; StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); @@ -243,12 +304,20 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { continue; bool IsCode = RelocatedSection->isText(); - SectionID = - findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections); + unsigned SectionID = 0; + if (auto SectionIDOrErr = findOrEmitSection(Obj, *RelocatedSection, IsCode, + LocalSections)) + SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); + DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (; I != E;) - I = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs); + if (auto IOrErr = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs)) + I = *IOrErr; + else + return IOrErr.takeError(); // If there is an attached checker, notify it about the stubs for this // section so that they can be verified. @@ -257,7 +326,8 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { } // Give the subclasses a chance to tie-up any loose ends. - finalizeLoad(Obj, LocalSections); + if (auto Err = finalizeLoad(Obj, LocalSections)) + return std::move(Err); // for (auto E : LocalSections) // llvm::dbgs() << "Added: " << E.first.getRawDataRefImpl() << " -> " << E.second << "\n"; @@ -288,16 +358,17 @@ static bool isRequiredForExecution(const SectionRef Section) { 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 + // 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); + 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; } @@ -336,13 +407,13 @@ static bool isZeroInit(const SectionRef Section) { // Compute an upper bound of the memory size that is required to load all // sections -void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, - uint64_t &CodeSize, - uint32_t &CodeAlign, - uint64_t &RODataSize, - uint32_t &RODataAlign, - uint64_t &RWDataSize, - uint32_t &RWDataAlign) { +Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, + uint64_t &CodeSize, + uint32_t &CodeAlign, + uint64_t &RODataSize, + uint32_t &RODataAlign, + uint64_t &RWDataSize, + uint32_t &RWDataAlign) { // Compute the size of all sections required for execution std::vector<uint64_t> CodeSectionSizes; std::vector<uint64_t> ROSectionSizes; @@ -358,13 +429,15 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, // Consider only the sections that are required to be loaded for execution if (IsRequired) { - StringRef Name; uint64_t DataSize = Section.getSize(); uint64_t Alignment64 = Section.getAlignment(); + unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; bool IsCode = Section.isText(); bool IsReadOnly = isReadOnlyData(Section); - Check(Section.getName(Name)); - unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; + + StringRef Name; + if (auto EC = Section.getName(Name)) + return errorCodeToError(EC); uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section); uint64_t SectionSize = DataSize + StubBufSize; @@ -395,17 +468,24 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, // Compute the size of all common symbols uint64_t CommonSize = 0; + uint32_t CommonAlign = 1; for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { uint32_t Flags = I->getFlags(); if (Flags & SymbolRef::SF_Common) { // Add the common symbols to a list. We'll allocate them all below. uint64_t Size = I->getCommonSize(); - CommonSize += Size; + uint32_t Align = I->getAlignment(); + // If this is the first common symbol, use its alignment as the alignment + // for the common symbols section. + if (CommonSize == 0) + CommonAlign = Align; + CommonSize = alignTo(CommonSize, Align) + Size; } } if (CommonSize != 0) { RWSectionSizes.push_back(CommonSize); + RWDataAlign = std::max(RWDataAlign, CommonAlign); } // Compute the required allocation space for each different type of sections @@ -416,6 +496,8 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, CodeSize = computeAllocationSizeForSections(CodeSectionSizes, CodeAlign); RODataSize = computeAllocationSizeForSections(ROSectionSizes, RODataAlign); RWDataSize = computeAllocationSizeForSections(RWSectionSizes, RWDataAlign); + + return Error::success(); } // compute stub buffer size for the given section @@ -483,20 +565,23 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } } -void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, - CommonSymbolList &CommonSymbols) { +Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, + CommonSymbolList &CommonSymbols) { if (CommonSymbols.empty()) - return; + return Error::success(); uint64_t CommonSize = 0; + uint32_t CommonAlign = CommonSymbols.begin()->getAlignment(); CommonSymbolList SymbolsToAllocate; DEBUG(dbgs() << "Processing common symbols...\n"); for (const auto &Sym : CommonSymbols) { - ErrorOr<StringRef> NameOrErr = Sym.getName(); - Check(NameOrErr.getError()); - StringRef Name = *NameOrErr; + StringRef Name; + if (auto NameOrErr = Sym.getName()) + Name = *NameOrErr; + else + return NameOrErr.takeError(); // Skip common symbols already elsewhere. if (GlobalSymbolTable.count(Name) || @@ -509,14 +594,15 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, uint32_t Align = Sym.getAlignment(); uint64_t Size = Sym.getCommonSize(); - CommonSize += Align + Size; + CommonSize = alignTo(CommonSize, Align) + Size; + SymbolsToAllocate.push_back(Sym); } // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, sizeof(void *), - SectionID, StringRef(), false); + uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, CommonAlign, SectionID, + "<common symbols>", false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; @@ -531,9 +617,11 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, for (auto &Sym : SymbolsToAllocate) { uint32_t Align = Sym.getAlignment(); uint64_t Size = Sym.getCommonSize(); - ErrorOr<StringRef> NameOrErr = Sym.getName(); - Check(NameOrErr.getError()); - StringRef Name = *NameOrErr; + StringRef Name; + if (auto NameOrErr = Sym.getName()) + Name = *NameOrErr; + else + return NameOrErr.takeError(); if (Align) { // This symbol has an alignment requirement. uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align); @@ -556,24 +644,29 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, if (Checker) Checker->registerSection(Obj.getFileName(), SectionID); -} -unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, - const SectionRef &Section, bool IsCode) { + return Error::success(); +} +Expected<unsigned> +RuntimeDyldImpl::emitSection(const ObjectFile &Obj, + const SectionRef &Section, + bool IsCode) { StringRef data; uint64_t Alignment64 = Section.getAlignment(); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; unsigned PaddingSize = 0; unsigned StubBufSize = 0; - StringRef Name; bool IsRequired = isRequiredForExecution(Section); bool IsVirtual = Section.isVirtual(); bool IsZeroInit = isZeroInit(Section); bool IsReadOnly = isReadOnlyData(Section); uint64_t DataSize = Section.getSize(); - Check(Section.getName(Name)); + + StringRef Name; + if (auto EC = Section.getName(Name)) + return errorCodeToError(EC); StubBufSize = computeSectionStubBufSize(Obj, Section); @@ -593,7 +686,8 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, if (!IsVirtual && !IsZeroInit) { // 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)); + if (auto EC = Section.getContents(data)) + return errorCodeToError(EC); pData = data.data(); } @@ -655,17 +749,21 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, return SectionID; } -unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj, - const SectionRef &Section, - bool IsCode, - ObjSectionToIDMap &LocalSections) { +Expected<unsigned> +RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj, + const SectionRef &Section, + bool IsCode, + ObjSectionToIDMap &LocalSections) { unsigned SectionID = 0; ObjSectionToIDMap::iterator i = LocalSections.find(Section); if (i != LocalSections.end()) SectionID = i->second; else { - SectionID = emitSection(Obj, Section, IsCode); + if (auto SectionIDOrErr = emitSection(Obj, Section, IsCode)) + SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); LocalSections[Section] = SectionID; } return SectionID; @@ -718,7 +816,10 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr, // 8: 03200008 jr t9. // c: 00000000 nop. const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000; - const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0; + const unsigned NopInstr = 0x0; + unsigned JrT9Instr = 0x03200008; + if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6) + JrT9Instr = 0x03200009; writeBytesUnaligned(LuiT9Instr, Addr, 4); writeBytesUnaligned(AdduiT9Instr, Addr+4, 4); @@ -818,7 +919,11 @@ void RuntimeDyldImpl::resolveExternalSymbols() { if (Loc == GlobalSymbolTable.end()) { // This is an external symbol, try to get its address from the symbol // resolver. - Addr = Resolver.findSymbol(Name.data()).getAddress(); + // First search for the symbol in this logical dylib. + Addr = Resolver.findSymbolInLogicalDylib(Name.data()).getAddress(); + // If that fails, try searching for an external symbol. + if (!Addr) + 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 diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp index e5fab929ea29..24bd9a002c20 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -13,6 +13,7 @@ #include "RuntimeDyldCOFF.h" #include "Targets/RuntimeDyldCOFFI386.h" +#include "Targets/RuntimeDyldCOFFThumb.h" #include "Targets/RuntimeDyldCOFFX86_64.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" @@ -45,11 +46,11 @@ llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, RuntimeDyld::SymbolResolver &Resolver) { switch (Arch) { - default: - llvm_unreachable("Unsupported target for RuntimeDyldCOFF."); - break; + default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF."); case Triple::x86: return make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver); + case Triple::thumb: + return make_unique<RuntimeDyldCOFFThumb>(MemMgr, Resolver); case Triple::x86_64: return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver); } @@ -57,7 +58,14 @@ llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) { - return llvm::make_unique<LoadedCOFFObjectInfo>(*this, loadObjectImpl(O)); + if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) { + return llvm::make_unique<LoadedCOFFObjectInfo>(*this, *ObjSectionToIDOrErr); + } else { + HasError = true; + raw_string_ostream ErrStream(ErrorStr); + logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, ""); + return nullptr; + } } uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h index 32b8fa269be0..03a91f6cf690 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -15,7 +15,6 @@ #define LLVM_RUNTIME_DYLD_COFF_H #include "RuntimeDyldImpl.h" -#include "llvm/ADT/DenseMap.h" #define DEBUG_TYPE "dyld" diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index 58ce88a68f23..090b9a3857e3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -7,16 +7,17 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "RuntimeDyldCheckerImpl.h" #include "RuntimeDyldImpl.h" -#include "llvm/ExecutionEngine/RuntimeDyldChecker.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/Path.h" #include <cctype> #include <memory> +#include <utility> #define DEBUG_TYPE "rtdyld" @@ -97,7 +98,8 @@ private: public: EvalResult() : Value(0), ErrorMsg("") {} EvalResult(uint64_t Value) : Value(Value), ErrorMsg("") {} - EvalResult(std::string ErrorMsg) : Value(0), ErrorMsg(ErrorMsg) {} + EvalResult(std::string ErrorMsg) + : Value(0), ErrorMsg(std::move(ErrorMsg)) {} uint64_t getValue() const { return Value; } bool hasError() const { return ErrorMsg != ""; } const std::string &getErrorMsg() const { return ErrorMsg; } @@ -582,7 +584,7 @@ private: // Returns a pair containing the result of the slice operation, plus the // expression remaining to be parsed. std::pair<EvalResult, StringRef> - evalSliceExpr(std::pair<EvalResult, StringRef> Ctx) const { + evalSliceExpr(const std::pair<EvalResult, StringRef> &Ctx) const { EvalResult SubExprResult; StringRef RemainingExpr; std::tie(SubExprResult, RemainingExpr) = Ctx; @@ -626,7 +628,7 @@ private: // Returns a pair containing the ultimate result of evaluating the // expression, plus the expression remaining to be evaluated. std::pair<EvalResult, StringRef> - evalComplexExpr(std::pair<EvalResult, StringRef> LHSAndRemaining, + evalComplexExpr(const std::pair<EvalResult, StringRef> &LHSAndRemaining, ParseContext PCtx) const { EvalResult LHSResult; StringRef RemainingExpr; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h index 69d2a7d6b668..b7263be09934 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h @@ -11,7 +11,6 @@ #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDCHECKERIMPL_H #include "RuntimeDyldImpl.h" -#include <set> namespace llvm { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index e09b71af18a5..9cbdb13a3572 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -30,13 +30,6 @@ using namespace llvm::object; #define DEBUG_TYPE "dyld" -static inline std::error_code check(std::error_code Err) { - if (Err) { - report_fatal_error(Err.message()); - } - return Err; -} - namespace { template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { @@ -220,7 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() { std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyldELF::loadObject(const object::ObjectFile &O) { - return llvm::make_unique<LoadedELFObjectInfo>(*this, loadObjectImpl(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, @@ -781,9 +781,9 @@ void RuntimeDyldELF::applyMIPS64Relocation(uint8_t *TargetPtr, } // Return the .TOC. section and offset. -void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj, - ObjSectionToIDMap &LocalSections, - RelocationValueRef &Rel) { +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 @@ -796,13 +796,18 @@ void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj, // order. The TOC starts where the first of these sections starts. for (auto &Section: Obj.sections()) { StringRef SectionName; - check(Section.getName(SectionName)); + if (auto EC = Section.getName(SectionName)) + return errorCodeToError(EC); if (SectionName == ".got" || SectionName == ".toc" || SectionName == ".tocbss" || SectionName == ".plt") { - Rel.SectionID = findOrEmitSection(Obj, Section, false, LocalSections); + if (auto SectionIDOrErr = + findOrEmitSection(Obj, Section, false, LocalSections)) + Rel.SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); break; } } @@ -810,13 +815,15 @@ void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj, // 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. -void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, - ObjSectionToIDMap &LocalSections, - RelocationValueRef &Rel) { +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(); @@ -826,7 +833,9 @@ void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, continue; StringRef RelSectionName; - check(RelSecI->getName(RelSectionName)); + if (auto EC = RelSecI->getName(RelSectionName)) + return errorCodeToError(EC); + if (RelSectionName != ".opd") continue; @@ -843,9 +852,11 @@ void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, uint64_t TargetSymbolOffset = i->getOffset(); symbol_iterator TargetSymbol = i->getSymbol(); - ErrorOr<int64_t> AddendOrErr = i->getAddend(); - Check(AddendOrErr.getError()); - int64_t Addend = *AddendOrErr; + int64_t Addend; + if (auto AddendOrErr = i->getAddend()) + Addend = *AddendOrErr; + else + return errorCodeToError(AddendOrErr.getError()); ++i; if (i == e) @@ -862,13 +873,21 @@ void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj, if (Rel.Addend != (int64_t)TargetSymbolOffset) continue; - ErrorOr<section_iterator> TSIOrErr = TargetSymbol->getSection(); - check(TSIOrErr.getError()); - section_iterator tsi = *TSIOrErr; - bool IsCode = tsi->isText(); - Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections); + 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; + return Error::success(); } } llvm_unreachable("Attempting to get address of ODP entry!"); @@ -1047,6 +1066,11 @@ void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section, case ELF::R_390_64: writeInt64BE(LocalAddress, Value + Addend); break; + case ELF::R_390_PC64: { + int64_t Delta = (Value + Addend) - Section.getLoadAddressWithOffset(Offset); + writeInt64BE(LocalAddress, Delta); + break; + } } } @@ -1163,7 +1187,8 @@ uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType, return ELF::R_MIPS_NONE; } -relocation_iterator RuntimeDyldELF::processRelocationRef( +Expected<relocation_iterator> +RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { const auto &Obj = cast<ELFObjectFileBase>(O); @@ -1175,10 +1200,10 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // Obtain the symbol name which is referenced in the relocation StringRef TargetName; if (Symbol != Obj.symbol_end()) { - ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); - if (std::error_code EC = TargetNameOrErr.getError()) - report_fatal_error(EC.message()); - TargetName = *TargetNameOrErr; + if (auto TargetNameOrErr = Symbol->getName()) + TargetName = *TargetNameOrErr; + else + return TargetNameOrErr.takeError(); } DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend << " TargetName: " << TargetName << "\n"); @@ -1190,7 +1215,15 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end(); if (Symbol != Obj.symbol_end()) { gsi = GlobalSymbolTable.find(TargetName.data()); - SymType = Symbol->getType(); + 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; @@ -1203,12 +1236,24 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // 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. - section_iterator si = *Symbol->getSection(); + 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(); - Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID); + if (auto SectionIDOrErr = findOrEmitSection(Obj, (*si), isCode, + ObjSectionToID)) + Value.SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); Value.Addend = Addend; break; } @@ -1289,7 +1334,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( 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."); + DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.\n"); SectionEntry &Section = Sections[SectionID]; // Look for an existing stub. @@ -1357,8 +1402,12 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // 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())); + Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant); // Creating Hi and Lo relocations for the filled stub instructions. RelocationEntry REHi(SectionID, StubTargetAddr - Section.getAddress(), @@ -1453,7 +1502,8 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // 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. - findOPDEntrySection(Obj, ObjSectionToID, Value); + 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. @@ -1565,7 +1615,8 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( } RelocationValueRef TOCValue; - findPPC64TOCSection(Obj, ObjSectionToID, 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; @@ -1577,9 +1628,11 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // symbols (in which case the addend is respected). if (RelType == ELF::R_PPC64_TOC) { RelType = ELF::R_PPC64_ADDR64; - findPPC64TOCSection(Obj, ObjSectionToID, Value); + if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value)) + return std::move(Err); } else if (TargetName == ".TOC.") { - findPPC64TOCSection(Obj, ObjSectionToID, Value); + if (auto Err = findPPC64TOCSection(Obj, ObjSectionToID, Value)) + return std::move(Err); Value.Addend += Addend; } @@ -1700,7 +1753,9 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( Value.Offset); addRelocationForSection(RE, Value.SectionID); } - } else if (RelType == ELF::R_X86_64_GOTPCREL) { + } 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(SectionID, 1); resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend); @@ -1791,11 +1846,11 @@ RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID, uint64_t return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset); } -void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, +Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { if (IsMipsO32ABI) if (!PendingRelocs.empty()) - report_fatal_error("Can't find matching LO16 reloc"); + return make_error<RuntimeDyldError>("Can't find matching LO16 reloc"); // If necessary, allocate the global offset table if (GOTSectionID != 0) { @@ -1804,7 +1859,7 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(), GOTSectionID, ".got", false); if (!Addr) - report_fatal_error("Unable to allocate memory for GOT!"); + return make_error<RuntimeDyldError>("Unable to allocate memory for GOT!"); Sections[GOTSectionID] = SectionEntry(".got", Addr, TotalSize, TotalSize, 0); @@ -1845,6 +1900,8 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, GOTSectionID = 0; CurrentGOTIndex = 0; + + return Error::success(); } bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { @@ -1861,6 +1918,8 @@ bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const { 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: diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 041811d3e285..82931b9f45a6 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -20,6 +20,9 @@ using namespace llvm; namespace llvm { +namespace object { +class ELFObjectFileBase; +} class RuntimeDyldELF : public RuntimeDyldImpl { @@ -90,12 +93,12 @@ class RuntimeDyldELF : public RuntimeDyldImpl { void setMipsABI(const ObjectFile &Obj) override; - void findPPC64TOCSection(const ELFObjectFileBase &Obj, - ObjSectionToIDMap &LocalSections, - RelocationValueRef &Rel); - void findOPDEntrySection(const ELFObjectFileBase &Obj, - ObjSectionToIDMap &LocalSections, - RelocationValueRef &Rel); + Error findPPC64TOCSection(const ELFObjectFileBase &Obj, + ObjSectionToIDMap &LocalSections, + RelocationValueRef &Rel); + Error findOPDEntrySection(const ELFObjectFileBase &Obj, + ObjSectionToIDMap &LocalSections, + RelocationValueRef &Rel); size_t getGOTEntrySize(); @@ -163,7 +166,7 @@ public: loadObject(const object::ObjectFile &O) override; void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; - relocation_iterator + Expected<relocation_iterator> processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, @@ -171,8 +174,8 @@ public: bool isCompatibleFile(const object::ObjectFile &Obj) const override; void registerEHFrames() override; void deregisterEHFrames() override; - void finalizeLoad(const ObjectFile &Obj, - ObjSectionToIDMap &SectionMap) override; + Error finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) override; }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index ab732c69ee2f..76bd3fc295b8 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -14,7 +14,6 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" @@ -28,7 +27,6 @@ #include "llvm/Support/Host.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/SwapByteOrder.h" -#include "llvm/Support/raw_ostream.h" #include <map> #include <unordered_map> #include <system_error> @@ -38,16 +36,12 @@ 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; +#define UNIMPLEMENTED_RELOC(RelType) \ + case RelType: \ + return make_error<RuntimeDyldError>("Unimplemented relocation: " #RelType) + /// SectionEntry - represents a section emitted into memory by the dynamic /// linker. class SectionEntry { @@ -302,13 +296,6 @@ protected: bool HasError; std::string ErrorStr; - // Set the error state and record an error string. - bool Error(const Twine &Msg) { - ErrorStr = Msg.str(); - HasError = true; - return true; - } - uint64_t getSectionLoadAddress(unsigned SectionID) const { return Sections[SectionID].getLoadAddress(); } @@ -361,22 +348,25 @@ 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, CommonSymbolList &CommonSymbols); + Error 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 /// used for emits, else allocateDataSection() will be used. /// \return SectionID. - unsigned emitSection(const ObjectFile &Obj, const SectionRef &Section, - bool IsCode); + Expected<unsigned> emitSection(const ObjectFile &Obj, + const SectionRef &Section, + bool IsCode); /// \brief Find Section in LocalSections. If the secton is not found - emit /// it and store in LocalSections. /// \param IsCode if it's true then allocateCodeSection() will be /// used for emmits, else allocateDataSection() will be used. /// \return SectionID. - unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, - bool IsCode, ObjSectionToIDMap &LocalSections); + Expected<unsigned> findOrEmitSection(const ObjectFile &Obj, + const SectionRef &Section, bool IsCode, + ObjSectionToIDMap &LocalSections); // \brief Add a relocation entry that uses the given section. void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID); @@ -401,7 +391,7 @@ protected: /// relocation pairs) and stores it to Relocations or SymbolRelocations /// (this depends on the object file type). /// \return Iterator to the next relocation that needs to be parsed. - virtual relocation_iterator + virtual Expected<relocation_iterator> processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) = 0; @@ -411,17 +401,17 @@ protected: // \brief Compute an upper bound of the memory that is required to load all // sections - void computeTotalAllocSize(const ObjectFile &Obj, - uint64_t &CodeSize, uint32_t &CodeAlign, - uint64_t &RODataSize, uint32_t &RODataAlign, - uint64_t &RWDataSize, uint32_t &RWDataAlign); + Error computeTotalAllocSize(const ObjectFile &Obj, + uint64_t &CodeSize, uint32_t &CodeAlign, + uint64_t &RODataSize, uint32_t &RODataAlign, + uint64_t &RWDataSize, uint32_t &RWDataAlign); // \brief Compute the stub buffer size required for a section unsigned computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section); // \brief Implementation of the generic part of the loadObject algorithm. - ObjSectionToIDMap loadObjectImpl(const object::ObjectFile &Obj); + Expected<ObjSectionToIDMap> loadObjectImpl(const object::ObjectFile &Obj); // \brief Return true if the relocation R may require allocating a stub. virtual bool relocationNeedsStub(const RelocationRef &R) const { @@ -496,8 +486,10 @@ public: virtual void deregisterEHFrames(); - virtual void finalizeLoad(const ObjectFile &ObjImg, - ObjSectionToIDMap &SectionMap) {} + virtual Error finalizeLoad(const ObjectFile &ObjImg, + ObjSectionToIDMap &SectionMap) { + return Error::success(); + } }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 739e8d65dbf4..fd109aea91d4 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -50,7 +50,8 @@ int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes)); } -relocation_iterator RuntimeDyldMachO::processScatteredVANILLA( +Expected<relocation_iterator> +RuntimeDyldMachO::processScatteredVANILLA( unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { @@ -74,8 +75,12 @@ relocation_iterator RuntimeDyldMachO::processScatteredVANILLA( uint64_t SectionBaseAddr = TargetSI->getAddress(); SectionRef TargetSection = *TargetSI; bool IsCode = TargetSection.isText(); - uint32_t TargetSectionID = - findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); + uint32_t TargetSectionID = ~0U; + if (auto TargetSectionIDOrErr = + findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); Addend -= SectionBaseAddr; RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); @@ -86,7 +91,8 @@ relocation_iterator RuntimeDyldMachO::processScatteredVANILLA( } -RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( +Expected<RelocationValueRef> +RuntimeDyldMachO::getRelocationValueRef( const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { @@ -99,10 +105,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); if (IsExternal) { symbol_iterator Symbol = RI->getSymbol(); - ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); - if (std::error_code EC = TargetNameOrErr.getError()) - report_fatal_error(EC.message()); - StringRef TargetName = *TargetNameOrErr; + StringRef TargetName; + if (auto TargetNameOrErr = Symbol->getName()) + TargetName = *TargetNameOrErr; + else + return TargetNameOrErr.takeError(); RTDyldSymbolTable::const_iterator SI = GlobalSymbolTable.find(TargetName.data()); if (SI != GlobalSymbolTable.end()) { @@ -116,7 +123,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( } else { SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); bool IsCode = Sec.isText(); - Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); + if (auto SectionIDOrErr = findOrEmitSection(Obj, Sec, IsCode, + ObjSectionToID)) + Value.SectionID = *SectionIDOrErr; + else + return SectionIDOrErr.takeError(); uint64_t Addr = Sec.getAddress(); Value.Offset = RE.Addend - Addr; } @@ -164,7 +175,7 @@ RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, // Populate __pointers section. -void RuntimeDyldMachO::populateIndirectSymbolPointersSection( +Error RuntimeDyldMachO::populateIndirectSymbolPointersSection( const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID) { @@ -191,10 +202,11 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection( unsigned SymbolIndex = Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); - ErrorOr<StringRef> IndirectSymbolNameOrErr = SI->getName(); - if (std::error_code EC = IndirectSymbolNameOrErr.getError()) - report_fatal_error(EC.message()); - StringRef IndirectSymbolName = *IndirectSymbolNameOrErr; + StringRef IndirectSymbolName; + if (auto IndirectSymbolNameOrErr = SI->getName()) + IndirectSymbolName = *IndirectSymbolNameOrErr; + else + return IndirectSymbolNameOrErr.takeError(); DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex << ", PT offset: " << PTEntryOffset << "\n"); RelocationEntry RE(PTSectionID, PTEntryOffset, @@ -202,6 +214,7 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection( addRelocationForSymbol(RE, IndirectSymbolName); PTEntryOffset += PTEntrySize; } + return Error::success(); } bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { @@ -209,8 +222,9 @@ bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { } template <typename Impl> -void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, - ObjSectionToIDMap &SectionMap) { +Error +RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) { unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; unsigned TextSID = RTDYLD_INVALID_SECTION_ID; unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; @@ -222,20 +236,34 @@ void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, // Force emission of the __text, __eh_frame, and __gcc_except_tab sections // if they're present. Otherwise call down to the impl to handle other // sections that have already been emitted. - if (Name == "__text") - TextSID = findOrEmitSection(Obj, Section, true, SectionMap); - else if (Name == "__eh_frame") - EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap); - else if (Name == "__gcc_except_tab") - ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap); - else { + if (Name == "__text") { + if (auto TextSIDOrErr = findOrEmitSection(Obj, Section, true, SectionMap)) + TextSID = *TextSIDOrErr; + else + return TextSIDOrErr.takeError(); + } else if (Name == "__eh_frame") { + if (auto EHFrameSIDOrErr = findOrEmitSection(Obj, Section, false, + SectionMap)) + EHFrameSID = *EHFrameSIDOrErr; + else + return EHFrameSIDOrErr.takeError(); + } else if (Name == "__gcc_except_tab") { + if (auto ExceptTabSIDOrErr = findOrEmitSection(Obj, Section, true, + SectionMap)) + ExceptTabSID = *ExceptTabSIDOrErr; + else + return ExceptTabSIDOrErr.takeError(); + } else { auto I = SectionMap.find(Section); if (I != SectionMap.end()) - impl().finalizeSection(Obj, I->second, Section); + if (auto Err = impl().finalizeSection(Obj, I->second, Section)) + return Err; } } UnregisteredEHFrameSections.push_back( EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); + + return Error::success(); } template <typename Impl> @@ -302,9 +330,9 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { uint8_t *P = EHFrame->getAddress(); uint8_t *End = P + EHFrame->getSize(); - do { + while (P != End) { P = processFDE(P, DeltaForText, DeltaForEH); - } while (P != End); + } MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(), EHFrame->getSize()); @@ -333,7 +361,15 @@ RuntimeDyldMachO::create(Triple::ArchType Arch, std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { - return llvm::make_unique<LoadedMachOObjectInfo>(*this, loadObjectImpl(O)); + if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) + return llvm::make_unique<LoadedMachOObjectInfo>(*this, + *ObjSectionToIDOrErr); + else { + HasError = true; + raw_string_ostream ErrStream(ErrorStr); + logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, ""); + return nullptr; + } } } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index c8ae47b0db22..30f3bb3bf07d 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -80,10 +80,10 @@ protected: } /// Process a scattered vanilla relocation. - relocation_iterator processScatteredVANILLA( - unsigned SectionID, relocation_iterator RelI, - const ObjectFile &BaseObjT, - RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID); + Expected<relocation_iterator> + processScatteredVANILLA(unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseObjT, + RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID); /// Construct a RelocationValueRef representing the relocation target. /// For Symbols in known sections, this will return a RelocationValueRef @@ -94,10 +94,11 @@ protected: /// In both cases the Addend field is *NOT* fixed up to be PC-relative. That /// should be done by the caller where appropriate by calling makePCRel on /// the RelocationValueRef. - RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj, - const relocation_iterator &RI, - const RelocationEntry &RE, - ObjSectionToIDMap &ObjSectionToID); + Expected<RelocationValueRef> + getRelocationValueRef(const ObjectFile &BaseTObj, + const relocation_iterator &RI, + const RelocationEntry &RE, + ObjSectionToIDMap &ObjSectionToID); /// Make the RelocationValueRef addend PC-relative. void makeValueAddendPCRel(RelocationValueRef &Value, @@ -113,9 +114,9 @@ protected: // Populate __pointers section. - void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj, - const SectionRef &PTSection, - unsigned PTSectionID); + Error populateIndirectSymbolPointersSection(const MachOObjectFile &Obj, + const SectionRef &PTSection, + unsigned PTSectionID); public: @@ -154,8 +155,8 @@ public: RuntimeDyld::SymbolResolver &Resolver) : RuntimeDyldMachO(MemMgr, Resolver) {} - void finalizeLoad(const ObjectFile &Obj, - ObjSectionToIDMap &SectionMap) override; + Error finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) override; void registerEHFrames() override; }; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h index fbfbb3285233..44fda87e0f94 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h @@ -34,40 +34,66 @@ public: unsigned getStubAlignment() override { return 1; } - relocation_iterator processRelocationRef(unsigned SectionID, - relocation_iterator RelI, - const ObjectFile &Obj, - ObjSectionToIDMap &ObjSectionToID, - StubMap &Stubs) override { + Expected<relocation_iterator> + processRelocationRef(unsigned SectionID, + relocation_iterator RelI, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { + auto Symbol = RelI->getSymbol(); if (Symbol == Obj.symbol_end()) report_fatal_error("Unknown symbol in relocation"); - ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); - if (auto EC = TargetNameOrErr.getError()) - report_fatal_error(EC.message()); + Expected<StringRef> TargetNameOrErr = Symbol->getName(); + if (!TargetNameOrErr) + return TargetNameOrErr.takeError(); StringRef TargetName = *TargetNameOrErr; - auto Section = *Symbol->getSection(); + auto SectionOrErr = Symbol->getSection(); + if (!SectionOrErr) + return SectionOrErr.takeError(); + auto Section = *SectionOrErr; uint64_t RelType = RelI->getType(); uint64_t Offset = RelI->getOffset(); + // Determine the Addend used to adjust the relocation value. + uint64_t Addend = 0; + SectionEntry &AddendSection = Sections[SectionID]; + uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset; + uint8_t *Displacement = (uint8_t *)ObjTarget; + + switch (RelType) { + case COFF::IMAGE_REL_I386_DIR32: + case COFF::IMAGE_REL_I386_DIR32NB: + case COFF::IMAGE_REL_I386_SECREL: + case COFF::IMAGE_REL_I386_REL32: { + Addend = readBytesUnaligned(Displacement, 4); + break; + } + default: + break; + } + #if !defined(NDEBUG) SmallString<32> RelTypeName; RelI->getTypeName(RelTypeName); #endif DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset << " RelType: " << RelTypeName << " TargetName: " << TargetName - << "\n"); + << " Addend " << Addend << "\n"); unsigned TargetSectionID = -1; if (Section == Obj.section_end()) { RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); addRelocationForSymbol(RE, TargetName); } else { - TargetSectionID = - findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID); + if (auto TargetSectionIDOrErr = + findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); switch (RelType) { case COFF::IMAGE_REL_I386_ABSOLUTE: @@ -77,7 +103,7 @@ public: case COFF::IMAGE_REL_I386_DIR32NB: case COFF::IMAGE_REL_I386_REL32: { RelocationEntry RE = - RelocationEntry(SectionID, Offset, RelType, 0, TargetSectionID, + RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, getSymbolOffset(*Symbol), 0, 0, false, 0); addRelocationForSection(RE, TargetSectionID); break; @@ -90,7 +116,7 @@ public: } case COFF::IMAGE_REL_I386_SECREL: { RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, - getSymbolOffset(*Symbol)); + getSymbolOffset(*Symbol) + Addend); addRelocationForSection(RE, TargetSectionID); break; } @@ -148,8 +174,10 @@ public: } case COFF::IMAGE_REL_I386_REL32: { // 32-bit relative displacement to the target. - uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() - - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset; + uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1) + ? Value + : Sections[RE.Sections.SectionA].getLoadAddress(); + Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset; assert(static_cast<int32_t>(Result) <= INT32_MAX && "relocation overflow"); assert(static_cast<int32_t>(Result) >= INT32_MIN && @@ -190,9 +218,6 @@ public: void registerEHFrames() override {} void deregisterEHFrames() override {} - - void finalizeLoad(const ObjectFile &Obj, - ObjSectionToIDMap &SectionMap) override {} }; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h new file mode 100644 index 000000000000..ff7d1d439252 --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFThumb.h @@ -0,0 +1,291 @@ +//===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb 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 thumb support for MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H + +#include "llvm/Object/COFF.h" +#include "llvm/Support/COFF.h" +#include "../RuntimeDyldCOFF.h" + +#define DEBUG_TYPE "dyld" + +namespace llvm { + +class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF { +public: + RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldCOFF(MM, Resolver) {} + + unsigned getMaxStubSize() override { + return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding + } + + unsigned getStubAlignment() override { return 1; } + + Expected<relocation_iterator> + processRelocationRef(unsigned SectionID, + relocation_iterator RelI, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { + auto Symbol = RelI->getSymbol(); + if (Symbol == Obj.symbol_end()) + report_fatal_error("Unknown symbol in relocation"); + + Expected<StringRef> TargetNameOrErr = Symbol->getName(); + if (!TargetNameOrErr) + return TargetNameOrErr.takeError(); + StringRef TargetName = *TargetNameOrErr; + + auto SectionOrErr = Symbol->getSection(); + if (!SectionOrErr) + return SectionOrErr.takeError(); + auto Section = *SectionOrErr; + + uint64_t RelType = RelI->getType(); + uint64_t Offset = RelI->getOffset(); + + // Determine the Addend used to adjust the relocation value. + uint64_t Addend = 0; + SectionEntry &AddendSection = Sections[SectionID]; + uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset; + uint8_t *Displacement = (uint8_t *)ObjTarget; + + switch (RelType) { + case COFF::IMAGE_REL_ARM_ADDR32: + case COFF::IMAGE_REL_ARM_ADDR32NB: + case COFF::IMAGE_REL_ARM_SECREL: + Addend = readBytesUnaligned(Displacement, 4); + break; + default: + break; + } + +#if !defined(NDEBUG) + SmallString<32> RelTypeName; + RelI->getTypeName(RelTypeName); +#endif + DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset + << " RelType: " << RelTypeName << " TargetName: " << TargetName + << " Addend " << Addend << "\n"); + + unsigned TargetSectionID = -1; + if (Section == Obj.section_end()) { + RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); + addRelocationForSymbol(RE, TargetName); + } else { + if (auto TargetSectionIDOrErr = + findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); + + switch (RelType) { + default: llvm_unreachable("unsupported relocation type"); + case COFF::IMAGE_REL_ARM_ABSOLUTE: + // This relocation is ignored. + break; + case COFF::IMAGE_REL_ARM_ADDR32: + case COFF::IMAGE_REL_ARM_ADDR32NB: { + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, + getSymbolOffset(*Symbol), 0, 0, false, 0); + addRelocationForSection(RE, TargetSectionID); + break; + } + case COFF::IMAGE_REL_ARM_SECTION: { + RelocationEntry RE = + RelocationEntry(TargetSectionID, Offset, RelType, 0); + addRelocationForSection(RE, TargetSectionID); + break; + } + case COFF::IMAGE_REL_ARM_SECREL: { + RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, + getSymbolOffset(*Symbol) + Addend); + addRelocationForSection(RE, TargetSectionID); + break; + } + case COFF::IMAGE_REL_ARM_MOV32T: { + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, + getSymbolOffset(*Symbol), 0, 0, false, 0); + addRelocationForSection(RE, TargetSectionID); + break; + } + case COFF::IMAGE_REL_ARM_BRANCH20T: + case COFF::IMAGE_REL_ARM_BRANCH24T: + case COFF::IMAGE_REL_ARM_BLX23T: { + RelocationEntry RE = + RelocationEntry(SectionID, Offset, RelType, + getSymbolOffset(*Symbol) + Addend, true, 0); + addRelocationForSection(RE, TargetSectionID); + break; + } + } + } + + return ++RelI; + } + + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { + const auto Section = Sections[RE.SectionID]; + uint8_t *Target = Section.getAddressWithOffset(RE.Offset); + + switch (RE.RelType) { + default: llvm_unreachable("unsupported relocation type"); + case COFF::IMAGE_REL_ARM_ABSOLUTE: + // This relocation is ignored. + break; + case COFF::IMAGE_REL_ARM_ADDR32: { + // The target's 32-bit VA. + uint64_t Result = + RE.Sections.SectionA == static_cast<uint32_t>(-1) + ? Value + : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); + assert(static_cast<int32_t>(Result) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(Result) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_ADDR32" + << " TargetSection: " << RE.Sections.SectionA + << " Value: " << format("0x%08" PRIx32, Result) << '\n'); + writeBytesUnaligned(Result, Target, 4); + break; + } + case COFF::IMAGE_REL_ARM_ADDR32NB: { + // The target's 32-bit RVA. + // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase + uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() - + Sections[0].getLoadAddress() + RE.Addend; + assert(static_cast<int32_t>(Result) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(Result) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_ADDR32NB" + << " TargetSection: " << RE.Sections.SectionA + << " Value: " << format("0x%08" PRIx32, Result) << '\n'); + writeBytesUnaligned(Result, Target, 4); + break; + } + case COFF::IMAGE_REL_ARM_SECTION: + // 16-bit section index of the section that contains the target. + assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID + << '\n'); + writeBytesUnaligned(RE.SectionID, Target, 2); + break; + case COFF::IMAGE_REL_ARM_SECREL: + // 32-bit offset of the target from the beginning of its section. + assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend + << '\n'); + writeBytesUnaligned(RE.Addend, Target, 2); + break; + case COFF::IMAGE_REL_ARM_MOV32T: { + // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair. + uint64_t Result = + Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend); + assert(static_cast<int32_t>(Result) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(Result) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_MOV32T" + << " TargetSection: " << RE.Sections.SectionA + << " Value: " << format("0x%08" PRIx32, Result) << '\n'); + + // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8| + // imm32 = zext imm4:i:imm3:imm8 + // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8| + // imm16 = imm4:i:imm3:imm8 + + auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) { + Bytes[0] |= ((Immediate & 0xf000) >> 12); + Bytes[1] |= ((Immediate & 0x0800) >> 11); + Bytes[2] |= ((Immediate & 0x00ff) >> 0); + Bytes[3] |= ((Immediate & 0x0700) >> 8); + }; + + EncodeImmediate(&Target[0], static_cast<uint32_t>(Result) >> 00); + EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16); + + break; + } + case COFF::IMAGE_REL_ARM_BRANCH20T: { + // The most significant 20-bits of the signed 21-bit relative displacement + uint64_t Value = + RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; + assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_BRANCH20T" + << " Value: " << static_cast<int32_t>(Value) << '\n'); + static_cast<void>(Value); + llvm_unreachable("unimplemented relocation"); + break; + } + case COFF::IMAGE_REL_ARM_BRANCH24T: { + // The most significant 24-bits of the signed 25-bit relative displacement + uint64_t Value = + RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; + assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_BRANCH24T" + << " Value: " << static_cast<int32_t>(Value) << '\n'); + static_cast<void>(Value); + llvm_unreachable("unimplemented relocation"); + break; + } + case COFF::IMAGE_REL_ARM_BLX23T: { + // The most significant 24-bits of the signed 25-bit relative displacement + uint64_t Value = + RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4; + assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && + "relocation overflow"); + assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && + "relocation underflow"); + DEBUG(dbgs() << "\t\tOffset: " << RE.Offset + << " RelType: IMAGE_REL_ARM_BLX23T" + << " Value: " << static_cast<int32_t>(Value) << '\n'); + static_cast<void>(Value); + llvm_unreachable("unimplemented relocation"); + break; + } + } + } + + void registerEHFrames() override {} + void deregisterEHFrames() override {} +}; + +} + +#endif + diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h index 25f538d8f3da..df8681da24d1 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -106,17 +106,21 @@ public: } } - relocation_iterator processRelocationRef(unsigned SectionID, - relocation_iterator RelI, - const ObjectFile &Obj, - ObjSectionToIDMap &ObjSectionToID, - StubMap &Stubs) override { + Expected<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 = *Symbol->getSection(); + auto SectionOrError = Symbol->getSection(); + if (!SectionOrError) + return SectionOrError.takeError(); + section_iterator SecI = *SectionOrError; // If there is no section, this must be an external reference. const bool IsExtern = SecI == Obj.section_end(); @@ -151,9 +155,9 @@ public: break; } - ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); - if (std::error_code EC = TargetNameOrErr.getError()) - report_fatal_error(EC.message()); + Expected<StringRef> TargetNameOrErr = Symbol->getName(); + if (!TargetNameOrErr) + return TargetNameOrErr.takeError(); StringRef TargetName = *TargetNameOrErr; DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset @@ -165,8 +169,12 @@ public: addRelocationForSymbol(RE, TargetName); } else { bool IsCode = SecI->isText(); - unsigned TargetSectionID = - findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID); + unsigned TargetSectionID; + if (auto TargetSectionIDOrErr = + findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID)) + TargetSectionID = *TargetSectionIDOrErr; + else + return TargetSectionIDOrErr.takeError(); uint64_t TargetOffset = getSymbolOffset(*Symbol); RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); addRelocationForSection(RE, TargetSectionID); @@ -189,19 +197,21 @@ public: void deregisterEHFrames() override { // Stub } - void finalizeLoad(const ObjectFile &Obj, - ObjSectionToIDMap &SectionMap) override { + Error 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)); + if (auto EC = Section.getName(Name)) + return errorCodeToError(EC); // 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); } } + return Error::success(); } }; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index dbca37747ce8..63598f197070 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -242,7 +242,7 @@ public: } } - relocation_iterator + Expected<relocation_iterator> processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID, @@ -252,7 +252,9 @@ public: MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); - assert(!Obj.isRelocationScattered(RelInfo) && ""); + if (Obj.isRelocationScattered(RelInfo)) + return make_error<RuntimeDyldError>("Scattered relocations not supported " + "for MachO AArch64"); // ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit // addend for the following relocation. If found: (1) store the associated @@ -270,6 +272,9 @@ public: RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); } + if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_SUBTRACTOR) + return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = decodeAddend(RE); @@ -278,8 +283,11 @@ public: if (ExplicitAddend) RE.Addend = ExplicitAddend; - RelocationValueRef Value( - getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); + RelocationValueRef Value; + if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) + Value = *ValueOrErr; + else + return ValueOrErr.takeError(); bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) @@ -349,7 +357,15 @@ public: encodeAddend(LocalAddress, /*Size=*/4, RelType, Value); break; } - case MachO::ARM64_RELOC_SUBTRACTOR: + case MachO::ARM64_RELOC_SUBTRACTOR: { + uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); + uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); + assert((Value == SectionABase || Value == SectionBBase) && + "Unexpected SUBTRACTOR relocation value."); + Value = SectionABase - SectionBBase + RE.Addend; + writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); + break; + } case MachO::ARM64_RELOC_POINTER_TO_GOT: case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: @@ -360,8 +376,10 @@ public: } } - void finalizeSection(const ObjectFile &Obj, unsigned SectionID, - const SectionRef &Section) {} + Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, + const SectionRef &Section) { + return Error::success(); + } private: void processGOTRelocation(const RelocationEntry &RE, @@ -398,6 +416,47 @@ private: RE.IsPCRel, RE.Size); addRelocationForSection(TargetRE, RE.SectionID); } + + Expected<relocation_iterator> + processSubtractRelocation(unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID) { + const MachOObjectFile &Obj = + static_cast<const MachOObjectFile&>(BaseObjT); + MachO::any_relocation_info RE = + Obj.getRelocation(RelI->getRawDataRefImpl()); + + unsigned Size = Obj.getAnyRelocationLength(RE); + uint64_t Offset = RelI->getOffset(); + uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset); + unsigned NumBytes = 1 << Size; + + Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName(); + if (!SubtrahendNameOrErr) + return SubtrahendNameOrErr.takeError(); + auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr); + unsigned SectionBID = SubtrahendI->second.getSectionID(); + uint64_t SectionBOffset = SubtrahendI->second.getOffset(); + int64_t Addend = + SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8); + + ++RelI; + Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName(); + if (!MinuendNameOrErr) + return MinuendNameOrErr.takeError(); + auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr); + unsigned SectionAID = MinuendI->second.getSectionID(); + uint64_t SectionAOffset = MinuendI->second.getOffset(); + + RelocationEntry R(SectionID, Offset, MachO::ARM64_RELOC_SUBTRACTOR, (uint64_t)Addend, + SectionAID, SectionAOffset, SectionBID, SectionBOffset, + false, Size); + + addRelocationForSection(R, SectionAID); + + return ++RelI; + } + }; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 7731df09bd21..0abf9daba505 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -11,6 +11,7 @@ #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H #include "../RuntimeDyldMachO.h" +#include <string> #define DEBUG_TYPE "dyld" @@ -49,7 +50,7 @@ public: } } - relocation_iterator + Expected<relocation_iterator> processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID, @@ -70,10 +71,30 @@ public: return ++RelI; } + // Sanity check relocation type. + switch (RelType) { + UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PAIR); + UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_SECTDIFF); + UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_LOCAL_SECTDIFF); + UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PB_LA_PTR); + UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_RELOC_BR22); + UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_32BIT_BRANCH); + UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_HALF); + default: + if (RelType > MachO::ARM_RELOC_HALF_SECTDIFF) + return make_error<RuntimeDyldError>(("MachO ARM relocation type " + + Twine(RelType) + + " is out of range").str()); + break; + } + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = decodeAddend(RE); - RelocationValueRef Value( - getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); + RelocationValueRef Value; + if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) + Value = *ValueOrErr; + else + return ValueOrErr.takeError(); if (RE.IsPCRel) makeValueAddendPCRel(Value, RelI, 8); @@ -108,8 +129,6 @@ public: } switch (RE.RelType) { - default: - llvm_unreachable("Invalid relocation type!"); case MachO::ARM_RELOC_VANILLA: writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; @@ -147,26 +166,20 @@ public: break; } - case MachO::ARM_THUMB_RELOC_BR22: - case MachO::ARM_THUMB_32BIT_BRANCH: - case MachO::ARM_RELOC_HALF: - case MachO::ARM_RELOC_PAIR: - case MachO::ARM_RELOC_SECTDIFF: - case MachO::ARM_RELOC_LOCAL_SECTDIFF: - case MachO::ARM_RELOC_PB_LA_PTR: - Error("Relocation type not implemented yet!"); - return; + default: + llvm_unreachable("Invalid relocation type"); } } - void finalizeSection(const ObjectFile &Obj, unsigned SectionID, + Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__nl_symbol_ptr") - populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), - Section, SectionID); + return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), + Section, SectionID); + return Error::success(); } private: @@ -201,7 +214,7 @@ private: resolveRelocation(TargetRE, (uint64_t)Addr); } - relocation_iterator + Expected<relocation_iterator> processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseTObj, ObjSectionToIDMap &ObjSectionToID) { @@ -237,8 +250,12 @@ private: uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; bool IsCode = SectionA.isText(); - uint32_t SectionAID = - findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID); + uint32_t SectionAID = ~0U; + if (auto SectionAIDOrErr = + findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID)) + SectionAID = *SectionAIDOrErr; + else + return SectionAIDOrErr.takeError(); uint32_t AddrB = MachO.getScatteredRelocationValue(RE2); section_iterator SBI = getSectionByAddress(MachO, AddrB); @@ -246,8 +263,12 @@ private: uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; - uint32_t SectionBID = - findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID); + uint32_t SectionBID = ~0U; + if (auto SectionBIDOrErr = + findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID)) + SectionBID = *SectionBIDOrErr; + else + return SectionBIDOrErr.takeError(); uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff; unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 85059d70a3eb..2c79b3f7c819 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -11,6 +11,7 @@ #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H #include "../RuntimeDyldMachO.h" +#include <string> #define DEBUG_TYPE "dyld" @@ -30,7 +31,7 @@ public: unsigned getStubAlignment() override { return 1; } - relocation_iterator + Expected<relocation_iterator> processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID, @@ -48,13 +49,29 @@ public: ObjSectionToID); else if (RelType == MachO::GENERIC_RELOC_VANILLA) return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); - llvm_unreachable("Unhandled scattered relocation."); + return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation " + "type: " + Twine(RelType)).str()); + } + + switch (RelType) { + UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR); + UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR); + UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV); + default: + if (RelType > MachO::GENERIC_RELOC_TLV) + return make_error<RuntimeDyldError>(("MachO I386 relocation type " + + Twine(RelType) + + " is out of range").str()); + break; } RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = memcpyAddend(RE); - RelocationValueRef Value( - getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); + RelocationValueRef Value; + if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) + Value = *ValueOrErr; + else + return ValueOrErr.takeError(); // Addends for external, PC-rel relocations on i386 point back to the zero // offset. Calculate the final offset from the relocation target instead. @@ -91,8 +108,6 @@ public: } switch (RE.RelType) { - default: - llvm_unreachable("Invalid relocation type!"); case MachO::GENERIC_RELOC_VANILLA: writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; @@ -106,25 +121,26 @@ public: writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); break; } - case MachO::GENERIC_RELOC_PB_LA_PTR: - Error("Relocation type not implemented yet!"); + default: + llvm_unreachable("Invalid relocation type!"); } } - void finalizeSection(const ObjectFile &Obj, unsigned SectionID, + Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__jump_table") - populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); + return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); else if (Name == "__pointers") - populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), - Section, SectionID); + return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), + Section, SectionID); + return Error::success(); } private: - relocation_iterator + Expected<relocation_iterator> processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID) { @@ -153,8 +169,12 @@ private: uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; bool IsCode = SectionA.isText(); - uint32_t SectionAID = - findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); + uint32_t SectionAID = ~0U; + if (auto SectionAIDOrErr = + findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID)) + SectionAID = *SectionAIDOrErr; + else + return SectionAIDOrErr.takeError(); uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); section_iterator SBI = getSectionByAddress(Obj, AddrB); @@ -162,8 +182,12 @@ private: uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; - uint32_t SectionBID = - findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); + uint32_t SectionBID = ~0U; + if (auto SectionBIDOrErr = + findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID)) + SectionBID = *SectionBIDOrErr; + else + return SectionBIDOrErr.takeError(); // Compute the addend 'C' from the original expression 'A - B + C'. Addend -= AddrA - AddrB; @@ -183,11 +207,9 @@ private: } // Populate stubs in __jump_table section. - void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection, + Error populateJumpTable(const MachOObjectFile &Obj, + const SectionRef &JTSection, unsigned JTSectionID) { - assert(!Obj.is64Bit() && - "__jump_table section not supported in 64-bit MachO."); - MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); uint32_t JTSectionSize = Sec32.size; @@ -197,16 +219,17 @@ private: uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); unsigned JTEntryOffset = 0; - assert((JTSectionSize % JTEntrySize) == 0 && - "Jump-table section does not contain a whole number of stubs?"); + if (JTSectionSize % JTEntrySize != 0) + return make_error<RuntimeDyldError>("Jump-table section does not contain " + "a whole number of stubs?"); for (unsigned i = 0; i < NumJTEntries; ++i) { unsigned SymbolIndex = Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); - ErrorOr<StringRef> IndirectSymbolName = SI->getName(); - if (std::error_code EC = IndirectSymbolName.getError()) - report_fatal_error(EC.message()); + Expected<StringRef> IndirectSymbolName = SI->getName(); + if (!IndirectSymbolName) + return IndirectSymbolName.takeError(); uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; createStubFunction(JTEntryAddr); RelocationEntry RE(JTSectionID, JTEntryOffset + 1, @@ -214,6 +237,8 @@ private: addRelocationForSymbol(RE, *IndirectSymbolName); JTEntryOffset += JTEntrySize; } + + return Error::success(); } }; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 2242295bc1ee..bc4822983244 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -11,6 +11,7 @@ #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H #include "../RuntimeDyldMachO.h" +#include <string> #define DEBUG_TYPE "dyld" @@ -30,7 +31,7 @@ public: unsigned getStubAlignment() override { return 1; } - relocation_iterator + Expected<relocation_iterator> processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID, @@ -49,13 +50,26 @@ public: RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = memcpyAddend(RE); - RelocationValueRef Value( - getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); + RelocationValueRef Value; + if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) + Value = *ValueOrErr; + else + return ValueOrErr.takeError(); bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) makeValueAddendPCRel(Value, RelI, 1 << RE.Size); + switch (RelType) { + UNIMPLEMENTED_RELOC(MachO::X86_64_RELOC_TLV); + default: + if (RelType > MachO::X86_64_RELOC_TLV) + return make_error<RuntimeDyldError>(("MachO X86_64 relocation type " + + Twine(RelType) + + " is out of range").str()); + break; + } + if (RE.RelType == MachO::X86_64_RELOC_GOT || RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) processGOTRelocation(RE, Value, Stubs); @@ -104,15 +118,13 @@ public: writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); break; } - case MachO::X86_64_RELOC_GOT_LOAD: - case MachO::X86_64_RELOC_GOT: - case MachO::X86_64_RELOC_TLV: - Error("Relocation type not implemented yet!"); } } - void finalizeSection(const ObjectFile &Obj, unsigned SectionID, - const SectionRef &Section) {} + Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, + const SectionRef &Section) { + return Error::success(); + } private: void processGOTRelocation(const RelocationEntry &RE, @@ -143,12 +155,12 @@ private: resolveRelocation(TargetRE, (uint64_t)Addr); } - relocation_iterator + Expected<relocation_iterator> processSubtractRelocation(unsigned SectionID, relocation_iterator RelI, - const ObjectFile &BaseObjT, + const MachOObjectFile &BaseObj, ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile&>(BaseObjT); + static_cast<const MachOObjectFile&>(BaseObj); MachO::any_relocation_info RE = Obj.getRelocation(RelI->getRawDataRefImpl()); @@ -156,23 +168,60 @@ private: uint64_t Offset = RelI->getOffset(); uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset); unsigned NumBytes = 1 << Size; - - ErrorOr<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName(); - if (auto EC = SubtrahendNameOrErr.getError()) - report_fatal_error(EC.message()); - auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr); - unsigned SectionBID = SubtrahendI->second.getSectionID(); - uint64_t SectionBOffset = SubtrahendI->second.getOffset(); int64_t Addend = SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8); + unsigned SectionBID = ~0U; + uint64_t SectionBOffset = 0; + + MachO::any_relocation_info RelInfo = + Obj.getRelocation(RelI->getRawDataRefImpl()); + + bool AIsExternal = BaseObj.getPlainRelocationExternal(RelInfo); + + if (AIsExternal) { + Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName(); + if (!SubtrahendNameOrErr) + return SubtrahendNameOrErr.takeError(); + auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr); + SectionBID = SubtrahendI->second.getSectionID(); + SectionBOffset = SubtrahendI->second.getOffset(); + } else { + SectionRef SecB = Obj.getAnyRelocationSection(RelInfo); + bool IsCode = SecB.isText(); + Expected<unsigned> SectionBIDOrErr = + findOrEmitSection(Obj, SecB, IsCode, ObjSectionToID); + if (!SectionBIDOrErr) + return SectionBIDOrErr.takeError(); + SectionBID = *SectionBIDOrErr; + Addend += SecB.getAddress(); + } + ++RelI; - ErrorOr<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName(); - if (auto EC = MinuendNameOrErr.getError()) - report_fatal_error(EC.message()); - auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr); - unsigned SectionAID = MinuendI->second.getSectionID(); - uint64_t SectionAOffset = MinuendI->second.getOffset(); + + unsigned SectionAID = ~0U; + uint64_t SectionAOffset = 0; + + RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); + + bool BIsExternal = BaseObj.getPlainRelocationExternal(RelInfo); + if (BIsExternal) { + Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName(); + if (!MinuendNameOrErr) + return MinuendNameOrErr.takeError(); + auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr); + SectionAID = MinuendI->second.getSectionID(); + SectionAOffset = MinuendI->second.getOffset(); + } else { + SectionRef SecA = Obj.getAnyRelocationSection(RelInfo); + bool IsCode = SecA.isText(); + Expected<unsigned> SectionAIDOrErr = + findOrEmitSection(Obj, SecA, IsCode, ObjSectionToID); + if (!SectionAIDOrErr) + return SectionAIDOrErr.takeError(); + SectionAID = *SectionAIDOrErr; + Addend -= SecA.getAddress(); + } RelocationEntry R(SectionID, Offset, MachO::X86_64_RELOC_SUBTRACTOR, (uint64_t)Addend, SectionAID, SectionAOffset, SectionBID, SectionBOffset, diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index 57f6e0804143..b45f0c89de8b 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -14,11 +14,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/IR/Module.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" |