From c3e7231c1fe6b242b07b653d103223ada7f0f604 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 13 Mar 2020 09:24:09 -0700 Subject: [PATCH] [MCJIT] Check for RuntimeDyld errors in MCJIT::finalizeLoadedModules. Patch based on https://reviews.llvm.org/D75912 by Alexander Shishkin. Thanks Alexander! To minimize disruption to existing clients, who may be relying on the fact that unused references to unresolved symbols do not generate an error, this patch makes error checking opt-in: Clients can call ExecutionEngine::hasError or LLVMExecutionEngineGetError to check whether and error has occurred. Differential revision: https://reviews.llvm.org/D75912 --- include/llvm-c/ExecutionEngine.h | 5 +++++ include/llvm/ExecutionEngine/ExecutionEngine.h | 14 ++++++++++++++ lib/ExecutionEngine/ExecutionEngineBindings.cpp | 12 ++++++++++++ lib/ExecutionEngine/MCJIT/MCJIT.cpp | 4 ++++ 4 files changed, 35 insertions(+) diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index f31b97ad762..c5fc9bdb4d0 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -149,6 +149,11 @@ uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); +/// Returns true on error, false on success. If true is returned then the error +/// message is copied to OutStr and cleared in the ExecutionEngine instance. +LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, + char **OutError); + /*===-- Operations on memory managers -------------------------------------===*/ typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 9b41ed4391c..2562da7cf60 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -158,6 +158,8 @@ protected: /// getMangledName - Get mangled name. std::string getMangledName(const GlobalValue *GV); + std::string ErrMsg; + public: /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must /// be held while changing the internal state of any of those classes. @@ -275,8 +277,20 @@ public: /// object have been relocated using mapSectionAddress. When this method is /// called the MCJIT execution engine will reapply relocations for a loaded /// object. This method has no effect for the interpeter. + /// + /// Returns true on success, false on failure. Error messages can be retrieved + /// by calling getError(); virtual void finalizeObject() {} + /// Returns true if an error has been recorded. + bool hasError() const { return !ErrMsg.empty(); } + + /// Clear the error message. + void clearErrorMessage() { ErrMsg.clear(); } + + /// Returns the most recent error message. + const std::string &getErrorMessage() const { return ErrMsg; } + /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a program. /// diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index ff1e8050c7e..addec6871fa 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -308,6 +308,18 @@ uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) { return unwrap(EE)->getFunctionAddress(Name); } +LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE, + char **OutError) { + assert(OutError && "OutError must be non-null"); + auto *ExecEngine = unwrap(EE); + if (ExecEngine->hasError()) { + *OutError = strdup(ExecEngine->getErrorMessage().c_str()); + ExecEngine->clearErrorMessage(); + return true; + } + return false; +} + /*===-- Operations on memory managers -------------------------------------===*/ namespace { diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 9c3d0d53984..d2af987946e 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -239,6 +239,10 @@ void MCJIT::finalizeLoadedModules() { // Resolve any outstanding relocations. Dyld.resolveRelocations(); + // Check for Dyld error. + if (Dyld.hasError()) + ErrMsg = Dyld.getErrorString().str(); + OwnedModules.markAllLoadedModulesAsFinalized(); // Register EH frame data for any module we own which has been loaded