diff options
Diffstat (limited to 'lib/ExecutionEngine')
44 files changed, 1797 insertions, 903 deletions
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk index 9f1befd..6578e2b 100644 --- a/lib/ExecutionEngine/Android.mk +++ b/lib/ExecutionEngine/Android.mk @@ -7,7 +7,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ ExecutionEngineBindings.cpp \ ExecutionEngine.cpp \ - RTDyldMemoryManager.cpp \ + GDBRegistrationListener.cpp \ + SectionMemoryManager.cpp \ TargetSelect.cpp LOCAL_MODULE:= libLLVMExecutionEngine diff --git a/lib/ExecutionEngine/CMakeLists.txt b/lib/ExecutionEngine/CMakeLists.txt index fae5bb9..e8a18d3 100644 --- a/lib/ExecutionEngine/CMakeLists.txt +++ b/lib/ExecutionEngine/CMakeLists.txt @@ -3,13 +3,17 @@ add_llvm_library(LLVMExecutionEngine ExecutionEngine.cpp ExecutionEngineBindings.cpp - JITEventListener.cpp - RTDyldMemoryManager.cpp + GDBRegistrationListener.cpp + SectionMemoryManager.cpp TargetSelect.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine ) add_subdirectory(Interpreter) add_subdirectory(MCJIT) +add_subdirectory(Orc) add_subdirectory(RuntimeDyld) if( LLVM_USE_OPROFILE ) diff --git a/lib/ExecutionEngine/EventListenerCommon.h b/lib/ExecutionEngine/EventListenerCommon.h index 66645d7..6453099 100644 --- a/lib/ExecutionEngine/EventListenerCommon.h +++ b/lib/ExecutionEngine/EventListenerCommon.h @@ -26,13 +26,13 @@ namespace jitprofiling { class FilenameCache { // Holds the filename of each Scope, so that we can pass a null-terminated - // string into oprofile. Use an AssertingVH rather than a ValueMap because we - // shouldn't be modifying any MDNodes while this map is alive. - DenseMap<AssertingVH<MDNode>, std::string> Filenames; - DenseMap<AssertingVH<MDNode>, std::string> Paths; + // string into oprofile. + DenseMap<const MDNode *, std::string> Filenames; + DenseMap<const MDNode *, std::string> Paths; public: const char *getFilename(MDNode *Scope) { + assert(Scope->isResolved() && "Expected Scope to be resolved"); std::string &Filename = Filenames[Scope]; if (Filename.empty()) { DIScope DIScope(Scope); @@ -42,6 +42,7 @@ class FilenameCache { } const char *getFullPath(MDNode *Scope) { + assert(Scope->isResolved() && "Expected Scope to be resolved"); std::string &P = Paths[Scope]; if (P.empty()) { DIScope DIScope(Scope); diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 5a6d656..12e0e6a 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -16,8 +16,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -43,17 +42,20 @@ using namespace llvm; STATISTIC(NumInitBytes, "Number of bytes of global vars initialized"); STATISTIC(NumGlobals , "Number of global vars initialized"); -// Pin the vtable to this file. -void ObjectCache::anchor() {} -void ObjectBuffer::anchor() {} -void ObjectBufferStream::anchor() {} - ExecutionEngine *(*ExecutionEngine::MCJITCtor)( std::unique_ptr<Module> M, std::string *ErrorStr, - RTDyldMemoryManager *MCJMM, std::unique_ptr<TargetMachine> TM) = nullptr; + std::unique_ptr<RTDyldMemoryManager> MCJMM, + std::unique_ptr<TargetMachine> TM) = nullptr; + +ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)( + std::string *ErrorStr, std::unique_ptr<RTDyldMemoryManager> OrcJMM, + std::unique_ptr<TargetMachine> TM) = nullptr; + ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M, std::string *ErrorStr) =nullptr; +void JITEventListener::anchor() {} + ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M) : EEState(*this), LazyFunctionCreator(nullptr) { @@ -140,7 +142,8 @@ bool ExecutionEngine::removeModule(Module *M) { Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { for (unsigned i = 0, e = Modules.size(); i != e; ++i) { - if (Function *F = Modules[i]->getFunction(FnName)) + Function *F = Modules[i]->getFunction(FnName); + if (F && !F->isDeclaration()) return F; } return nullptr; @@ -396,6 +399,23 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn, return runFunction(Fn, GVArgs).IntVal.getZExtValue(); } +EngineBuilder::EngineBuilder() { + InitEngine(); +} + +EngineBuilder::EngineBuilder(std::unique_ptr<Module> M) + : M(std::move(M)), MCJMM(nullptr) { + InitEngine(); +} + +EngineBuilder::~EngineBuilder() {} + +EngineBuilder &EngineBuilder::setMCJITMemoryManager( + std::unique_ptr<RTDyldMemoryManager> mcjmm) { + MCJMM = std::move(mcjmm); + return *this; +} + void EngineBuilder::InitEngine() { WhichEngine = EngineKind::Either; ErrorStr = nullptr; @@ -404,6 +424,7 @@ void EngineBuilder::InitEngine() { Options = TargetOptions(); RelocModel = Reloc::Default; CMModel = CodeModel::JITDefault; + UseOrcMCJITReplacement = false; // IR module verification is enabled by default in debug builds, and disabled // by default in release builds. @@ -446,9 +467,14 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { } ExecutionEngine *EE = nullptr; - if (ExecutionEngine::MCJITCtor) - EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, MCJMM, + if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) { + EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MCJMM), + std::move(TheTM)); + EE->addModule(std::move(M)); + } else if (ExecutionEngine::MCJITCtor) + EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MCJMM), std::move(TheTM)); + if (EE) { EE->setVerifyModules(VerifyModules); return EE; diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 58271df..aaa53f0 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -188,7 +188,8 @@ LLVMBool LLVMCreateMCJITCompilerForModule( .setCodeModel(unwrap(options.CodeModel)) .setTargetOptions(targetOptions); if (options.MCJMM) - builder.setMCJITMemoryManager(unwrap(options.MCJMM)); + builder.setMCJITMemoryManager( + std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM))); if (ExecutionEngine *JIT = builder.create()) { *OutJIT = wrap(JIT); return 0; @@ -327,6 +328,14 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global)); } +uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) { + return unwrap(EE)->getGlobalValueAddress(Name); +} + +uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) { + return unwrap(EE)->getFunctionAddress(Name); +} + /*===-- Operations on memory managers -------------------------------------===*/ namespace { diff --git a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp b/lib/ExecutionEngine/GDBRegistrationListener.cpp index dfa3a20..8ef878c 100644 --- a/lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp +++ b/lib/ExecutionEngine/GDBRegistrationListener.cpp @@ -1,4 +1,4 @@ -//===-- GDBRegistrar.cpp - Registers objects with GDB ---------------------===// +//===----- GDBRegistrationListener.cpp - Registers objects with GDB -------===// // // The LLVM Compiler Infrastructure // @@ -7,15 +7,17 @@ // //===----------------------------------------------------------------------===// -#include "JITRegistrar.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Support/ManagedStatic.h" using namespace llvm; +using namespace llvm::object; // This must be kept in sync with gdb/gdb/jit.h . extern "C" { @@ -60,37 +62,59 @@ extern "C" { namespace { +struct RegisteredObjectInfo { + RegisteredObjectInfo() {} + + RegisteredObjectInfo(std::size_t Size, jit_code_entry *Entry, + OwningBinary<ObjectFile> Obj) + : Size(Size), Entry(Entry), Obj(std::move(Obj)) {} + + RegisteredObjectInfo(RegisteredObjectInfo &&Other) + : Size(Other.Size), Entry(Other.Entry), Obj(std::move(Other.Obj)) {} + + RegisteredObjectInfo& operator=(RegisteredObjectInfo &&Other) { + Size = Other.Size; + Entry = Other.Entry; + Obj = std::move(Other.Obj); + return *this; + } + + std::size_t Size; + jit_code_entry *Entry; + OwningBinary<ObjectFile> Obj; +}; + // Buffer for an in-memory object file in executable memory -typedef llvm::DenseMap< const char*, - std::pair<std::size_t, jit_code_entry*> > +typedef llvm::DenseMap< const char*, RegisteredObjectInfo> RegisteredObjectBufferMap; /// Global access point for the JIT debugging interface designed for use with a /// singleton toolbox. Handles thread-safe registration and deregistration of /// object files that are in executable memory managed by the client of this /// class. -class GDBJITRegistrar : public JITRegistrar { +class GDBJITRegistrationListener : public JITEventListener { /// A map of in-memory object files that have been registered with the /// JIT interface. RegisteredObjectBufferMap ObjectBufferMap; public: /// Instantiates the JIT service. - GDBJITRegistrar() : ObjectBufferMap() {} + GDBJITRegistrationListener() : ObjectBufferMap() {} /// Unregisters each object that was previously registered and releases all /// internal resources. - virtual ~GDBJITRegistrar(); + virtual ~GDBJITRegistrationListener(); /// Creates an entry in the JIT registry for the buffer @p Object, /// which must contain an object file in executable memory with any /// debug information for the debugger. - void registerObject(const ObjectBuffer &Object) override; + void NotifyObjectEmitted(const ObjectFile &Object, + const RuntimeDyld::LoadedObjectInfo &L) override; /// Removes the internal registration of @p Object, and /// frees associated resources. /// Returns true if @p Object was found in ObjectBufferMap. - bool deregisterObject(const ObjectBuffer &Object) override; + void NotifyFreeingObject(const ObjectFile &Object) override; private: /// Deregister the debug info for the given object file from the debugger @@ -119,10 +143,11 @@ void NotifyDebugger(jit_code_entry* JITCodeEntry) { __jit_debug_register_code(); } -GDBJITRegistrar::~GDBJITRegistrar() { +GDBJITRegistrationListener::~GDBJITRegistrationListener() { // Free all registered object files. llvm::MutexGuard locked(*JITDebugLock); - for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end(); + for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), + E = ObjectBufferMap.end(); I != E; ++I) { // Call the private method that doesn't update the map so our iterator // doesn't break. @@ -131,14 +156,24 @@ GDBJITRegistrar::~GDBJITRegistrar() { ObjectBufferMap.clear(); } -void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) { +void GDBJITRegistrationListener::NotifyObjectEmitted( + const ObjectFile &Object, + const RuntimeDyld::LoadedObjectInfo &L) { + + OwningBinary<ObjectFile> DebugObj = L.getObjectForDebug(Object); + + // Bail out if debug objects aren't supported. + if (!DebugObj.getBinary()) + return; + + const char *Buffer = DebugObj.getBinary()->getMemoryBufferRef().getBufferStart(); + size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize(); - const char *Buffer = Object.getBufferStart(); - size_t Size = Object.getBufferSize(); + const char *Key = Object.getMemoryBufferRef().getBufferStart(); - assert(Buffer && "Attempt to register a null object with a debugger."); + assert(Key && "Attempt to register a null object with a debugger."); llvm::MutexGuard locked(*JITDebugLock); - assert(ObjectBufferMap.find(Buffer) == ObjectBufferMap.end() && + assert(ObjectBufferMap.find(Key) == ObjectBufferMap.end() && "Second attempt to perform debug registration."); jit_code_entry* JITCodeEntry = new jit_code_entry(); @@ -149,28 +184,27 @@ void GDBJITRegistrar::registerObject(const ObjectBuffer &Object) { JITCodeEntry->symfile_addr = Buffer; JITCodeEntry->symfile_size = Size; - ObjectBufferMap[Buffer] = std::make_pair(Size, JITCodeEntry); + ObjectBufferMap[Key] = RegisteredObjectInfo(Size, JITCodeEntry, + std::move(DebugObj)); NotifyDebugger(JITCodeEntry); } } -bool GDBJITRegistrar::deregisterObject(const ObjectBuffer& Object) { - const char *Buffer = Object.getBufferStart(); +void GDBJITRegistrationListener::NotifyFreeingObject(const ObjectFile& Object) { + const char *Key = Object.getMemoryBufferRef().getBufferStart(); llvm::MutexGuard locked(*JITDebugLock); - RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Buffer); + RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Key); if (I != ObjectBufferMap.end()) { deregisterObjectInternal(I); ObjectBufferMap.erase(I); - return true; } - return false; } -void GDBJITRegistrar::deregisterObjectInternal( +void GDBJITRegistrationListener::deregisterObjectInternal( RegisteredObjectBufferMap::iterator I) { - jit_code_entry*& JITCodeEntry = I->second.second; + jit_code_entry*& JITCodeEntry = I->second.Entry; // Do the unregistration. { @@ -200,14 +234,14 @@ void GDBJITRegistrar::deregisterObjectInternal( JITCodeEntry = nullptr; } -llvm::ManagedStatic<GDBJITRegistrar> TheRegistrar; +llvm::ManagedStatic<GDBJITRegistrationListener> GDBRegListener; } // end namespace namespace llvm { -JITRegistrar& JITRegistrar::getGDBRegistrar() { - return *TheRegistrar; +JITEventListener* JITEventListener::createGDBRegistrationListener() { + return &*GDBRegListener; } } // namespace llvm diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index b23ca88..aa32452 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -13,25 +13,24 @@ //===----------------------------------------------------------------------===// #include "llvm/Config/config.h" +#include "EventListenerCommon.h" +#include "IntelJITEventsWrapper.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/DebugInfo/DWARF/DIContext.h" #include "llvm/ExecutionEngine/JITEventListener.h" - #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Metadata.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" -#include "llvm/IR/ValueHandle.h" -#include "EventListenerCommon.h" -#include "IntelJITEventsWrapper.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::jitprofiling; +using namespace llvm::object; #define DEBUG_TYPE "amplifier-jit-event-listener" @@ -48,6 +47,7 @@ class IntelJITEventListener : public JITEventListener { typedef DenseMap<const void *, MethodAddressVector> ObjectMap; ObjectMap LoadedObjectMap; + std::map<const char*, OwningBinary<ObjectFile>> DebugObjects; public: IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { @@ -57,9 +57,10 @@ public: ~IntelJITEventListener() { } - virtual void NotifyObjectEmitted(const ObjectImage &Obj); + void NotifyObjectEmitted(const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - virtual void NotifyFreeingObject(const ObjectImage &Obj); + void NotifyFreeingObject(const ObjectFile &Obj) override; }; static LineNumberInfo DILineInfoToIntelJITFormat(uintptr_t StartAddress, @@ -95,23 +96,29 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat( return Result; } -void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { +void IntelJITEventListener::NotifyObjectEmitted( + const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + + OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj); + const ObjectFile &DebugObj = *DebugObjOwner.getBinary(); + // Get the address of the object image for use as a unique identifier - const void* ObjData = Obj.getData().data(); - DIContext* Context = DIContext::getDWARFContext(*Obj.getObjectFile()); + const void* ObjData = DebugObj.getData().data(); + DIContext* Context = DIContext::getDWARFContext(DebugObj); MethodAddressVector Functions; // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = Obj.begin_symbols(), - E = Obj.end_symbols(); + for (symbol_iterator I = DebugObj.symbol_begin(), + E = DebugObj.symbol_end(); I != E; ++I) { std::vector<LineNumberInfo> LineInfo; std::string SourceFileName; - object::SymbolRef::Type SymType; + SymbolRef::Type SymType; if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { + if (SymType == SymbolRef::ST_Function) { StringRef Name; uint64_t Addr; uint64_t Size; @@ -141,6 +148,18 @@ void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { FunctionMessage.line_number_size = 0; FunctionMessage.line_number_table = 0; } else { + // Source line information for the address range is provided as + // a code offset for the start of the corresponding sub-range and + // a source line. JIT API treats offsets in LineNumberInfo structures + // as the end of the corresponding code region. The start of the code + // is taken from the previous element. Need to shift the elements. + + LineNumberInfo last = LineInfo.back(); + last.Offset = FunctionMessage.method_size; + LineInfo.push_back(last); + for (size_t i = LineInfo.size() - 2; i > 0; --i) + LineInfo[i].LineNumber = LineInfo[i - 1].LineNumber; + SourceFileName = Lines.front().second.FileName; FunctionMessage.source_file_name = const_cast<char *>(SourceFileName.c_str()); FunctionMessage.line_number_size = LineInfo.size(); @@ -162,11 +181,18 @@ void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { // registered function addresses for each loaded object. We will // use the MethodIDs map to get the registered ID for each function. LoadedObjectMap[ObjData] = Functions; + DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); } -void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { +void IntelJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { + // This object may not have been registered with the listener. If it wasn't, + // bail out. + if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) + return; + // Get the address of the object image for use as a unique identifier - const void* ObjData = Obj.getData().data(); + const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + const void* ObjData = DebugObj.getData().data(); // Get the object's function list from LoadedObjectMap ObjectMap::iterator OI = LoadedObjectMap.find(ObjData); @@ -190,6 +216,7 @@ void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { // Erase the object from LoadedObjectMap LoadedObjectMap.erase(OI); + DebugObjects.erase(Obj.getData().data()); } } // anonymous namespace. diff --git a/lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt b/lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt index e36493e..1247cbd 100644 --- a/lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt +++ b/lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt @@ -21,4 +21,4 @@ type = OptionalLibrary name = IntelJITEvents parent = ExecutionEngine -required_libraries = Core DebugInfo Support +required_libraries = Core DebugInfoDWARF Support diff --git a/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c b/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c index 7b507de..e966889 100644 --- a/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c +++ b/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c @@ -24,6 +24,7 @@ #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ #include <pthread.h> #include <dlfcn.h> +#include <stdint.h> #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ #include <malloc.h> #include <stdlib.h> @@ -371,7 +372,7 @@ static int loadiJIT_Funcs() #if ITT_PLATFORM==ITT_PLATFORM_WIN FUNC_NotifyEvent = (TPNotify)GetProcAddress(m_libHandle, "NotifyEvent"); #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ - FUNC_NotifyEvent = (TPNotify)dlsym(m_libHandle, "NotifyEvent"); + FUNC_NotifyEvent = (TPNotify)(intptr_t)dlsym(m_libHandle, "NotifyEvent"); #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ if (!FUNC_NotifyEvent) { @@ -382,7 +383,7 @@ static int loadiJIT_Funcs() #if ITT_PLATFORM==ITT_PLATFORM_WIN FUNC_Initialize = (TPInitialize)GetProcAddress(m_libHandle, "Initialize"); #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ - FUNC_Initialize = (TPInitialize)dlsym(m_libHandle, "Initialize"); + FUNC_Initialize = (TPInitialize)(intptr_t)dlsym(m_libHandle, "Initialize"); #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ if (!FUNC_Initialize) { diff --git a/lib/ExecutionEngine/JITEventListener.cpp b/lib/ExecutionEngine/JITEventListener.cpp deleted file mode 100644 index 2a6a007..0000000 --- a/lib/ExecutionEngine/JITEventListener.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//===-- JITEventListener.cpp ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITEventListener.h" - -using namespace llvm; - -// Out-of-line definition of the virtual destructor as this is the key function. -JITEventListener::~JITEventListener() {} diff --git a/lib/ExecutionEngine/LLVMBuild.txt b/lib/ExecutionEngine/LLVMBuild.txt index ecae078..8fdda9a 100644 --- a/lib/ExecutionEngine/LLVMBuild.txt +++ b/lib/ExecutionEngine/LLVMBuild.txt @@ -16,10 +16,10 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT +subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT Orc [component_0] type = Library name = ExecutionEngine parent = Libraries -required_libraries = Core MC Support +required_libraries = Core MC Object Support RuntimeDyld diff --git a/lib/ExecutionEngine/MCJIT/Android.mk b/lib/ExecutionEngine/MCJIT/Android.mk index 0314958..5827212 100644 --- a/lib/ExecutionEngine/MCJIT/Android.mk +++ b/lib/ExecutionEngine/MCJIT/Android.mk @@ -4,9 +4,8 @@ LOCAL_PATH:= $(call my-dir) # ===================================================== include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - MCJIT.cpp \ - SectionMemoryManager.cpp +LOCAL_SRC_FILES := \ + MCJIT.cpp LOCAL_MODULE:= libLLVMMCJIT diff --git a/lib/ExecutionEngine/MCJIT/CMakeLists.txt b/lib/ExecutionEngine/MCJIT/CMakeLists.txt index 088635a..2911a50 100644 --- a/lib/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/lib/ExecutionEngine/MCJIT/CMakeLists.txt @@ -1,4 +1,3 @@ add_llvm_library(LLVMMCJIT MCJIT.cpp - SectionMemoryManager.cpp ) diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index da5f037..e500d3d 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -11,26 +11,25 @@ #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Object/Archive.h" -#include "llvm/PassManager.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MutexGuard.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; +void ObjectCache::anchor() {} + namespace { static struct RegisterJIT { @@ -44,21 +43,24 @@ extern "C" void LLVMLinkInMCJIT() { ExecutionEngine *MCJIT::createJIT(std::unique_ptr<Module> M, std::string *ErrorStr, - RTDyldMemoryManager *MemMgr, + std::unique_ptr<RTDyldMemoryManager> MemMgr, std::unique_ptr<TargetMachine> TM) { // Try to register the program as a source of symbols to resolve against. // // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr); - return new MCJIT(std::move(M), std::move(TM), - MemMgr ? MemMgr : new SectionMemoryManager()); + std::unique_ptr<RTDyldMemoryManager> MM = std::move(MemMgr); + if (!MM) + MM = std::unique_ptr<SectionMemoryManager>(new SectionMemoryManager()); + + return new MCJIT(std::move(M), std::move(TM), std::move(MM)); } MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, - RTDyldMemoryManager *MM) + std::unique_ptr<RTDyldMemoryManager> MM) : ExecutionEngine(std::move(M)), TM(std::move(tm)), Ctx(nullptr), - MemMgr(this, MM), Dyld(&MemMgr), ObjCache(nullptr) { + MemMgr(this, std::move(MM)), Dyld(&MemMgr), ObjCache(nullptr) { // FIXME: We are managing our modules, so we do not want the base class // ExecutionEngine to manage them as well. To avoid double destruction // of the first (and only) module added in ExecutionEngine constructor @@ -73,7 +75,8 @@ MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, Modules.clear(); OwnedModules.addModule(std::move(First)); - setDataLayout(TM->getSubtargetImpl()->getDataLayout()); + setDataLayout(TM->getDataLayout()); + RegisterJITEventListener(JITEventListener::createGDBRegistrationListener()); } MCJIT::~MCJIT() { @@ -99,13 +102,13 @@ bool MCJIT::removeModule(Module *M) { } void MCJIT::addObjectFile(std::unique_ptr<object::ObjectFile> Obj) { - std::unique_ptr<ObjectImage> LoadedObject = Dyld.loadObject(std::move(Obj)); - if (!LoadedObject || Dyld.hasError()) + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = Dyld.loadObject(*Obj); + if (Dyld.hasError()) report_fatal_error(Dyld.getErrorString()); - NotifyObjectEmitted(*LoadedObject); + NotifyObjectEmitted(*Obj, *L); - LoadedObjects.push_back(std::move(LoadedObject)); + LoadedObjects.push_back(std::move(Obj)); } void MCJIT::addObjectFile(object::OwningBinary<object::ObjectFile> Obj) { @@ -125,43 +128,45 @@ void MCJIT::setObjectCache(ObjectCache* NewCache) { ObjCache = NewCache; } -std::unique_ptr<ObjectBufferStream> MCJIT::emitObject(Module *M) { +std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) { MutexGuard locked(lock); // This must be a module which has already been added but not loaded to this // MCJIT instance, since these conditions are tested by our caller, // generateCodeForModule. - PassManager PM; + legacy::PassManager PM; - M->setDataLayout(TM->getSubtargetImpl()->getDataLayout()); + M->setDataLayout(TM->getDataLayout()); PM.add(new DataLayoutPass()); // The RuntimeDyld will take ownership of this shortly - std::unique_ptr<ObjectBufferStream> CompiledObject(new ObjectBufferStream()); + SmallVector<char, 4096> ObjBufferSV; + raw_svector_ostream ObjStream(ObjBufferSV); // Turn the machine code intermediate representation into bytes in memory // that may be executed. - if (TM->addPassesToEmitMC(PM, Ctx, CompiledObject->getOStream(), - !getVerifyModules())) { + if (TM->addPassesToEmitMC(PM, Ctx, ObjStream, !getVerifyModules())) report_fatal_error("Target does not support MC emission!"); - } // Initialize passes. PM.run(*M); // Flush the output buffer to get the generated code into memory - CompiledObject->flush(); + ObjStream.flush(); + + std::unique_ptr<MemoryBuffer> CompiledObjBuffer( + new ObjectMemoryBuffer(std::move(ObjBufferSV))); // If we have an object cache, tell it about the new object. // Note that we're using the compiled image, not the loaded image (as below). if (ObjCache) { // MemoryBuffer is a thin wrapper around the actual memory, so it's OK // to create a temporary object here and delete it after the call. - MemoryBufferRef MB = CompiledObject->getMemBuffer(); + MemoryBufferRef MB = CompiledObjBuffer->getMemBufferRef(); ObjCache->notifyObjectCompiled(M, MB); } - return CompiledObject; + return CompiledObjBuffer; } void MCJIT::generateCodeForModule(Module *M) { @@ -176,14 +181,10 @@ void MCJIT::generateCodeForModule(Module *M) { if (OwnedModules.hasModuleBeenLoaded(M)) return; - std::unique_ptr<ObjectBuffer> ObjectToLoad; + std::unique_ptr<MemoryBuffer> ObjectToLoad; // Try to load the pre-compiled object from cache if possible - if (ObjCache) { - if (std::unique_ptr<MemoryBuffer> PreCompiledObject = - ObjCache->getObject(M)) - ObjectToLoad = - llvm::make_unique<ObjectBuffer>(std::move(PreCompiledObject)); - } + if (ObjCache) + ObjectToLoad = ObjCache->getObject(M); // If the cache did not contain a suitable object, compile the object if (!ObjectToLoad) { @@ -193,17 +194,18 @@ void MCJIT::generateCodeForModule(Module *M) { // Load the object into the dynamic linker. // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list). - std::unique_ptr<ObjectImage> LoadedObject = - Dyld.loadObject(std::move(ObjectToLoad)); - if (!LoadedObject) - report_fatal_error(Dyld.getErrorString()); + ErrorOr<std::unique_ptr<object::ObjectFile>> LoadedObject = + object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef()); + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L = + Dyld.loadObject(*LoadedObject.get()); - // FIXME: Make this optional, maybe even move it to a JIT event listener - LoadedObject->registerWithDebugger(); + if (Dyld.hasError()) + report_fatal_error(Dyld.getErrorString()); - NotifyObjectEmitted(*LoadedObject); + NotifyObjectEmitted(*LoadedObject.get(), *L); - LoadedObjects.push_back(std::move(LoadedObject)); + Buffers.push_back(std::move(ObjectToLoad)); + LoadedObjects.push_back(std::move(*LoadedObject)); OwnedModules.markModuleAsLoaded(M); } @@ -253,7 +255,7 @@ void MCJIT::finalizeModule(Module *M) { } uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) { - Mangler Mang(TM->getSubtargetImpl()->getDataLayout()); + Mangler Mang(TM->getDataLayout()); SmallString<128> FullName; Mang.getNameWithPrefix(FullName, Name); return Dyld.getSymbolLoadAddress(FullName); @@ -353,7 +355,7 @@ uint64_t MCJIT::getFunctionAddress(const std::string &Name) { void *MCJIT::getPointerToFunction(Function *F) { MutexGuard locked(lock); - Mangler Mang(TM->getSubtargetImpl()->getDataLayout()); + Mangler Mang(TM->getDataLayout()); SmallString<128> Name; TM->getNameWithPrefix(Name, F, Mang); @@ -406,7 +408,8 @@ Function *MCJIT::FindFunctionNamedInModulePtrSet(const char *FnName, ModulePtrSet::iterator I, ModulePtrSet::iterator E) { for (; I != E; ++I) { - if (Function *F = (*I)->getFunction(FnName)) + Function *F = (*I)->getFunction(FnName); + if (F && !F->isDeclaration()) return F; } return nullptr; @@ -549,6 +552,7 @@ void MCJIT::RegisterJITEventListener(JITEventListener *L) { MutexGuard locked(lock); EventListeners.push_back(L); } + void MCJIT::UnregisterJITEventListener(JITEventListener *L) { if (!L) return; @@ -559,14 +563,17 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) { EventListeners.pop_back(); } } -void MCJIT::NotifyObjectEmitted(const ObjectImage& Obj) { + +void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj, + const RuntimeDyld::LoadedObjectInfo &L) { MutexGuard locked(lock); - MemMgr.notifyObjectLoaded(this, &Obj); + MemMgr.notifyObjectLoaded(this, Obj); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { - EventListeners[I]->NotifyObjectEmitted(Obj); + EventListeners[I]->NotifyObjectEmitted(Obj, L); } } -void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) { + +void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { MutexGuard locked(lock); for (JITEventListener *L : EventListeners) L->NotifyFreeingObject(Obj); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index bc943b9..de4a8f6 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -15,7 +15,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectCache.h" -#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Module.h" @@ -28,8 +28,9 @@ class MCJIT; // to that object. class LinkingMemoryManager : public RTDyldMemoryManager { public: - LinkingMemoryManager(MCJIT *Parent, RTDyldMemoryManager *MM) - : ParentEngine(Parent), ClientMM(MM) {} + LinkingMemoryManager(MCJIT *Parent, + std::unique_ptr<RTDyldMemoryManager> MM) + : ParentEngine(Parent), ClientMM(std::move(MM)) {} uint64_t getSymbolAddress(const std::string &Name) override; @@ -57,7 +58,7 @@ public: } void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *Obj) override { + const object::ObjectFile &Obj) override { ClientMM->notifyObjectLoaded(EE, Obj); } @@ -102,7 +103,7 @@ private: class MCJIT : public ExecutionEngine { MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, - RTDyldMemoryManager *MemMgr); + std::unique_ptr<RTDyldMemoryManager> MemMgr); typedef llvm::SmallPtrSet<Module *, 4> ModulePtrSet; @@ -222,7 +223,7 @@ class MCJIT : public ExecutionEngine { SmallVector<object::OwningBinary<object::Archive>, 2> Archives; SmallVector<std::unique_ptr<MemoryBuffer>, 2> Buffers; - SmallVector<std::unique_ptr<ObjectImage>, 2> LoadedObjects; + SmallVector<std::unique_ptr<object::ObjectFile>, 2> LoadedObjects; // An optional ObjectCache to be notified of compiled objects and used to // perform lookup of pre-compiled code to avoid re-compilation. @@ -325,7 +326,7 @@ public: static ExecutionEngine *createJIT(std::unique_ptr<Module> M, std::string *ErrorStr, - RTDyldMemoryManager *MemMgr, + std::unique_ptr<RTDyldMemoryManager> MemMgr, std::unique_ptr<TargetMachine> TM); // @} @@ -341,10 +342,11 @@ protected: /// this function call is expected to be the contained module. The module /// is passed as a parameter here to prepare for multiple module support in /// the future. - std::unique_ptr<ObjectBufferStream> emitObject(Module *M); + std::unique_ptr<MemoryBuffer> emitObject(Module *M); - void NotifyObjectEmitted(const ObjectImage& Obj); - void NotifyFreeingObject(const ObjectImage& Obj); + void NotifyObjectEmitted(const object::ObjectFile& Obj, + const RuntimeDyld::LoadedObjectInfo &L); + void NotifyFreeingObject(const object::ObjectFile& Obj); uint64_t getExistingSymbolAddress(const std::string &Name); Module *findModuleForSymbol(const std::string &Name, diff --git a/lib/ExecutionEngine/MCJIT/ObjectBuffer.h b/lib/ExecutionEngine/MCJIT/ObjectBuffer.h new file mode 100644 index 0000000..92310f3 --- /dev/null +++ b/lib/ExecutionEngine/MCJIT/ObjectBuffer.h @@ -0,0 +1,48 @@ +//===--- ObjectBuffer.h - Utility class to wrap object memory ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a wrapper class to hold the memory into which an +// object will be generated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H +#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class ObjectMemoryBuffer : public MemoryBuffer { +public: + template <unsigned N> + ObjectMemoryBuffer(SmallVector<char, N> SV) + : SV(SV), BufferName("<in-memory object>") { + init(this->SV.begin(), this->SV.end(), false); + } + + template <unsigned N> + ObjectMemoryBuffer(SmallVector<char, N> SV, StringRef Name) + : SV(SV), BufferName(Name) { + init(this->SV.begin(), this->SV.end(), false); + } + const char* getBufferIdentifier() const override { return BufferName.c_str(); } + + BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } + +private: + SmallVector<char, 4096> SV; + std::string BufferName; +}; + +} // namespace llvm + +#endif diff --git a/lib/ExecutionEngine/Makefile b/lib/ExecutionEngine/Makefile index cf71432..e9a5b79 100644 --- a/lib/ExecutionEngine/Makefile +++ b/lib/ExecutionEngine/Makefile @@ -11,7 +11,7 @@ LIBRARYNAME = LLVMExecutionEngine include $(LEVEL)/Makefile.config -PARALLEL_DIRS = Interpreter MCJIT RuntimeDyld +PARALLEL_DIRS = Interpreter MCJIT Orc RuntimeDyld ifeq ($(USE_INTEL_JITEVENTS), 1) PARALLEL_DIRS += IntelJITEvents diff --git a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp index 5a8ccb6..9ab4003 100644 --- a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -13,49 +13,50 @@ //===----------------------------------------------------------------------===// #include "llvm/Config/config.h" +#include "EventListenerCommon.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/JITEventListener.h" - +#include "llvm/ExecutionEngine/OProfileWrapper.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/ExecutionEngine/ObjectImage.h" -#include "llvm/ExecutionEngine/OProfileWrapper.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" -#include "EventListenerCommon.h" - +#include "llvm/Support/raw_ostream.h" #include <dirent.h> #include <fcntl.h> using namespace llvm; using namespace llvm::jitprofiling; +using namespace llvm::object; #define DEBUG_TYPE "oprofile-jit-event-listener" namespace { class OProfileJITEventListener : public JITEventListener { - OProfileWrapper& Wrapper; + std::unique_ptr<OProfileWrapper> Wrapper; void initialize(); + std::map<const char*, OwningBinary<ObjectFile>> DebugObjects; public: - OProfileJITEventListener(OProfileWrapper& LibraryWrapper) - : Wrapper(LibraryWrapper) { + OProfileJITEventListener(std::unique_ptr<OProfileWrapper> LibraryWrapper) + : Wrapper(std::move(LibraryWrapper)) { initialize(); } ~OProfileJITEventListener(); - virtual void NotifyObjectEmitted(const ObjectImage &Obj); + void NotifyObjectEmitted(const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) override; - virtual void NotifyFreeingObject(const ObjectImage &Obj); + void NotifyFreeingObject(const ObjectFile &Obj) override; }; void OProfileJITEventListener::initialize() { - if (!Wrapper.op_open_agent()) { + if (!Wrapper->op_open_agent()) { const std::string err_str = sys::StrError(); DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n"); } else { @@ -64,8 +65,8 @@ void OProfileJITEventListener::initialize() { } OProfileJITEventListener::~OProfileJITEventListener() { - if (Wrapper.isAgentAvailable()) { - if (Wrapper.op_close_agent() == -1) { + if (Wrapper->isAgentAvailable()) { + if (Wrapper->op_close_agent() == -1) { const std::string err_str = sys::StrError(); DEBUG(dbgs() << "Failed to disconnect from OProfile agent: " << err_str << "\n"); @@ -75,17 +76,22 @@ OProfileJITEventListener::~OProfileJITEventListener() { } } -void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { - if (!Wrapper.isAgentAvailable()) { +void OProfileJITEventListener::NotifyObjectEmitted( + const ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + if (!Wrapper->isAgentAvailable()) { return; } + OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj); + const ObjectFile &DebugObj = *DebugObjOwner.getBinary(); + // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); + for (symbol_iterator I = DebugObj.symbol_begin(), E = DebugObj.symbol_end(); I != E; ++I) { - object::SymbolRef::Type SymType; + SymbolRef::Type SymType; if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { + if (SymType == SymbolRef::ST_Function) { StringRef Name; uint64_t Addr; uint64_t Size; @@ -93,7 +99,7 @@ void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { if (I->getAddress(Addr)) continue; if (I->getSize(Size)) continue; - if (Wrapper.op_write_native_code(Name.data(), Addr, (void*)Addr, Size) + if (Wrapper->op_write_native_code(Name.data(), Addr, (void*)Addr, Size) == -1) { DEBUG(dbgs() << "Failed to tell OProfile about native function " << Name << " at [" @@ -103,45 +109,48 @@ void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { // TODO: support line number info (similar to IntelJITEventListener.cpp) } } -} -void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { - if (!Wrapper.isAgentAvailable()) { - return; - } - - // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); - I != E; ++I) { - object::SymbolRef::Type SymType; - if (I->getType(SymType)) continue; - if (SymType == object::SymbolRef::ST_Function) { - uint64_t Addr; - if (I->getAddress(Addr)) continue; + DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); +} - if (Wrapper.op_unload_native_code(Addr) == -1) { - DEBUG(dbgs() - << "Failed to tell OProfile about unload of native function at " - << (void*)Addr << "\n"); - continue; +void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { + if (Wrapper->isAgentAvailable()) { + + // If there was no agent registered when the original object was loaded then + // we won't have created a debug object for it, so bail out. + if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) + return; + + const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); + + // Use symbol info to iterate functions in the object. + for (symbol_iterator I = DebugObj.symbol_begin(), + E = DebugObj.symbol_end(); + I != E; ++I) { + SymbolRef::Type SymType; + if (I->getType(SymType)) continue; + if (SymType == SymbolRef::ST_Function) { + uint64_t Addr; + if (I->getAddress(Addr)) continue; + + if (Wrapper->op_unload_native_code(Addr) == -1) { + DEBUG(dbgs() + << "Failed to tell OProfile about unload of native function at " + << (void*)Addr << "\n"); + continue; + } } } } + + DebugObjects.erase(Obj.getData().data()); } } // anonymous namespace. namespace llvm { JITEventListener *JITEventListener::createOProfileJITEventListener() { - static std::unique_ptr<OProfileWrapper> JITProfilingWrapper( - new OProfileWrapper); - return new OProfileJITEventListener(*JITProfilingWrapper); -} - -// for testing -JITEventListener *JITEventListener::createOProfileJITEventListener( - OProfileWrapper* TestImpl) { - return new OProfileJITEventListener(*TestImpl); + return new OProfileJITEventListener(llvm::make_unique<OProfileWrapper>()); } } // namespace llvm diff --git a/lib/ExecutionEngine/Orc/Android.mk b/lib/ExecutionEngine/Orc/Android.mk new file mode 100644 index 0000000..61c1daf --- /dev/null +++ b/lib/ExecutionEngine/Orc/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + CloneSubModule.cpp \ + IndirectionUtils.cpp \ + OrcMCJITReplacement.cpp \ + OrcTargetSupport.cpp + +LOCAL_MODULE:= libLLVMOrcJIT + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/lib/ExecutionEngine/Orc/CMakeLists.txt b/lib/ExecutionEngine/Orc/CMakeLists.txt new file mode 100644 index 0000000..b0a8445 --- /dev/null +++ b/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -0,0 +1,9 @@ +add_llvm_library(LLVMOrcJIT + CloneSubModule.cpp + IndirectionUtils.cpp + OrcMCJITReplacement.cpp + OrcTargetSupport.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc + ) diff --git a/lib/ExecutionEngine/Orc/CloneSubModule.cpp b/lib/ExecutionEngine/Orc/CloneSubModule.cpp new file mode 100644 index 0000000..a3196ad --- /dev/null +++ b/lib/ExecutionEngine/Orc/CloneSubModule.cpp @@ -0,0 +1,108 @@ +#include "llvm/ExecutionEngine/Orc/CloneSubModule.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/Cloning.h" + +namespace llvm { +namespace orc { + +void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap) { + if (Orig.hasInitializer()) + New.setInitializer(MapValue(Orig.getInitializer(), VMap)); +} + +void copyFunctionBody(Function &New, const Function &Orig, + ValueToValueMapTy &VMap) { + if (!Orig.isDeclaration()) { + Function::arg_iterator DestI = New.arg_begin(); + for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end(); + ++J) { + DestI->setName(J->getName()); + VMap[J] = DestI++; + } + + SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned. + CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns); + } +} + +void CloneSubModule(llvm::Module &Dst, const Module &Src, + HandleGlobalVariableFtor HandleGlobalVariable, + HandleFunctionFtor HandleFunction, bool CloneInlineAsm) { + + ValueToValueMapTy VMap; + + if (CloneInlineAsm) + Dst.appendModuleInlineAsm(Src.getModuleInlineAsm()); + + // Copy global variables (but not initializers, yet). + for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end(); + I != E; ++I) { + GlobalVariable *GV = new GlobalVariable( + Dst, I->getType()->getElementType(), I->isConstant(), I->getLinkage(), + (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr, + I->getThreadLocalMode(), I->getType()->getAddressSpace()); + GV->copyAttributesFrom(I); + VMap[I] = GV; + } + + // Loop over the functions in the module, making external functions as before + for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) { + Function *NF = + Function::Create(cast<FunctionType>(I->getType()->getElementType()), + I->getLinkage(), I->getName(), &Dst); + NF->copyAttributesFrom(I); + VMap[I] = NF; + } + + // Loop over the aliases in the module + for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end(); + I != E; ++I) { + auto *PTy = cast<PointerType>(I->getType()); + auto *GA = + GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), + I->getLinkage(), I->getName(), &Dst); + GA->copyAttributesFrom(I); + VMap[I] = GA; + } + + // Now that all of the things that global variable initializer can refer to + // have been created, loop through and copy the global variable referrers + // over... We also set the attributes on the global now. + for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end(); + I != E; ++I) { + GlobalVariable &GV = *cast<GlobalVariable>(VMap[I]); + HandleGlobalVariable(GV, *I, VMap); + } + + // Similarly, copy over function bodies now... + // + for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) { + Function &F = *cast<Function>(VMap[I]); + HandleFunction(F, *I, VMap); + } + + // And aliases + for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end(); + I != E; ++I) { + GlobalAlias *GA = cast<GlobalAlias>(VMap[I]); + if (const Constant *C = I->getAliasee()) + GA->setAliasee(MapValue(C, VMap)); + } + + // And named metadata.... + for (Module::const_named_metadata_iterator I = Src.named_metadata_begin(), + E = Src.named_metadata_end(); + I != E; ++I) { + const NamedMDNode &NMD = *I; + NamedMDNode *NewNMD = Dst.getOrInsertNamedMetadata(NMD.getName()); + for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) + NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap)); + } + +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp new file mode 100644 index 0000000..61c947f --- /dev/null +++ b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -0,0 +1,118 @@ +//===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===// +// +// 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/CloneSubModule.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/IRBuilder.h" +#include <set> + +namespace llvm { +namespace orc { + +GlobalVariable* createImplPointer(Function &F, const Twine &Name, + Constant *Initializer) { + assert(F.getParent() && "Function isn't in a module."); + if (!Initializer) + Initializer = Constant::getNullValue(F.getType()); + Module &M = *F.getParent(); + return new GlobalVariable(M, F.getType(), false, GlobalValue::ExternalLinkage, + Initializer, Name, nullptr, + GlobalValue::NotThreadLocal, 0, true); +} + +void makeStub(Function &F, GlobalVariable &ImplPointer) { + assert(F.isDeclaration() && "Can't turn a definition into a stub."); + assert(F.getParent() && "Function isn't in a module."); + Module &M = *F.getParent(); + BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F); + IRBuilder<> Builder(EntryBlock); + LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer); + std::vector<Value*> CallArgs; + for (auto &A : F.args()) + CallArgs.push_back(&A); + CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs); + Call->setTailCall(); + Builder.CreateRet(Call); +} + +void partition(Module &M, const ModulePartitionMap &PMap) { + + for (auto &KVPair : PMap) { + + auto ExtractGlobalVars = + [&](GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap) { + if (KVPair.second.count(&Orig)) { + copyGVInitializer(New, Orig, VMap); + } + if (New.getLinkage() == GlobalValue::PrivateLinkage) { + New.setLinkage(GlobalValue::ExternalLinkage); + New.setVisibility(GlobalValue::HiddenVisibility); + } + }; + + auto ExtractFunctions = + [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { + if (KVPair.second.count(&Orig)) + copyFunctionBody(New, Orig, VMap); + if (New.getLinkage() == GlobalValue::InternalLinkage) { + New.setLinkage(GlobalValue::ExternalLinkage); + New.setVisibility(GlobalValue::HiddenVisibility); + } + }; + + CloneSubModule(*KVPair.first, M, ExtractGlobalVars, ExtractFunctions, + false); + } +} + +FullyPartitionedModule fullyPartition(Module &M) { + FullyPartitionedModule MP; + + ModulePartitionMap PMap; + + for (auto &F : M) { + + if (F.isDeclaration()) + continue; + + std::string NewModuleName = (M.getName() + "." + F.getName()).str(); + MP.Functions.push_back( + llvm::make_unique<Module>(NewModuleName, M.getContext())); + MP.Functions.back()->setDataLayout(M.getDataLayout()); + PMap[MP.Functions.back().get()].insert(&F); + } + + MP.GlobalVars = + llvm::make_unique<Module>((M.getName() + ".globals_and_stubs").str(), + M.getContext()); + MP.GlobalVars->setDataLayout(M.getDataLayout()); + + MP.Commons = + llvm::make_unique<Module>((M.getName() + ".commons").str(), M.getContext()); + MP.Commons->setDataLayout(M.getDataLayout()); + + // Make sure there's at least an empty set for the stubs map or we'll fail + // to clone anything for it (including the decls). + PMap[MP.GlobalVars.get()] = ModulePartitionMap::mapped_type(); + for (auto &GV : M.globals()) + if (GV.getLinkage() == GlobalValue::CommonLinkage) + PMap[MP.Commons.get()].insert(&GV); + else + PMap[MP.GlobalVars.get()].insert(&GV); + + partition(M, PMap); + + return MP; +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/lib/ExecutionEngine/Orc/LLVMBuild.txt b/lib/ExecutionEngine/Orc/LLVMBuild.txt new file mode 100644 index 0000000..8f05172 --- /dev/null +++ b/lib/ExecutionEngine/Orc/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./lib/ExecutionEngine/MCJIT/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = OrcJIT +parent = ExecutionEngine +required_libraries = Core ExecutionEngine Object RuntimeDyld Support TransformUtils diff --git a/lib/ExecutionEngine/Orc/Makefile b/lib/ExecutionEngine/Orc/Makefile new file mode 100644 index 0000000..ac30234 --- /dev/null +++ b/lib/ExecutionEngine/Orc/Makefile @@ -0,0 +1,13 @@ +##===- 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/OrcMCJITReplacement.cpp b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp new file mode 100644 index 0000000..48fd31e --- /dev/null +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp @@ -0,0 +1,128 @@ +//===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OrcMCJITReplacement.h" +#include "llvm/ExecutionEngine/GenericValue.h" + +namespace { + +static struct RegisterJIT { + RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); } +} JITRegistrator; + +} + +extern "C" void LLVMLinkInOrcMCJITReplacement() {} + +namespace llvm { +namespace orc { + +GenericValue +OrcMCJITReplacement::runFunction(Function *F, + const std::vector<GenericValue> &ArgValues) { + assert(F && "Function *F was null at entry to run()"); + + void *FPtr = getPointerToFunction(F); + assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); + FunctionType *FTy = F->getFunctionType(); + Type *RetTy = FTy->getReturnType(); + + assert((FTy->getNumParams() == ArgValues.size() || + (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && + "Wrong number of arguments passed into function!"); + assert(FTy->getNumParams() == ArgValues.size() && + "This doesn't support passing arguments through varargs (yet)!"); + + // Handle some common cases first. These cases correspond to common `main' + // prototypes. + if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { + switch (ArgValues.size()) { + case 3: + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy() && + FTy->getParamType(2)->isPointerTy()) { + int (*PF)(int, char **, const char **) = + (int (*)(int, char **, const char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]), + (const char **)GVTOP(ArgValues[2]))); + return rv; + } + break; + case 2: + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy()) { + int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]))); + return rv; + } + break; + case 1: + if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) { + GenericValue rv; + int (*PF)(int) = (int (*)(int))(intptr_t)FPtr; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); + return rv; + } + break; + } + } + + // Handle cases where no arguments are passed first. + if (ArgValues.empty()) { + GenericValue rv; + switch (RetTy->getTypeID()) { + default: + llvm_unreachable("Unknown return type for function call!"); + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); + if (BitWidth == 1) + rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)()); + else if (BitWidth <= 8) + rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)()); + else if (BitWidth <= 16) + rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)()); + else if (BitWidth <= 32) + rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)()); + else if (BitWidth <= 64) + rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)()); + else + llvm_unreachable("Integer types > 64 bits not supported"); + return rv; + } + case Type::VoidTyID: + rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)()); + return rv; + case Type::FloatTyID: + rv.FloatVal = ((float (*)())(intptr_t)FPtr)(); + return rv; + case Type::DoubleTyID: + rv.DoubleVal = ((double (*)())(intptr_t)FPtr)(); + return rv; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + llvm_unreachable("long double not supported yet"); + case Type::PointerTyID: + return PTOGV(((void *(*)())(intptr_t)FPtr)()); + } + } + + llvm_unreachable("Full-featured argument passing not supported yet!"); +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h new file mode 100644 index 0000000..1b7b161 --- /dev/null +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -0,0 +1,332 @@ +//===---- OrcMCJITReplacement.h - Orc based MCJIT replacement ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Orc based MCJIT replacement. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H +#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/Object/Archive.h" + +namespace llvm { +namespace orc { + +class OrcMCJITReplacement : public ExecutionEngine { + + class ForwardingRTDyldMM : public RTDyldMemoryManager { + public: + ForwardingRTDyldMM(OrcMCJITReplacement &M) : M(M) {} + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override { + uint8_t *Addr = + M.MM->allocateCodeSection(Size, Alignment, SectionID, SectionName); + M.SectionsAllocatedSinceLastLoad.insert(Addr); + return Addr; + } + + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool IsReadOnly) override { + uint8_t *Addr = M.MM->allocateDataSection(Size, Alignment, SectionID, + SectionName, IsReadOnly); + M.SectionsAllocatedSinceLastLoad.insert(Addr); + return Addr; + } + + void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, + uintptr_t DataSizeRW) override { + return M.MM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + } + + bool needsToReserveAllocationSpace() override { + return M.MM->needsToReserveAllocationSpace(); + } + + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override { + return M.MM->registerEHFrames(Addr, LoadAddr, Size); + } + + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override { + return M.MM->deregisterEHFrames(Addr, LoadAddr, Size); + } + + uint64_t getSymbolAddress(const std::string &Name) override { + return M.getSymbolAddressWithoutMangling(Name); + } + + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override { + return M.MM->getPointerToNamedFunction(Name, AbortOnFailure); + } + + void notifyObjectLoaded(ExecutionEngine *EE, + const object::ObjectFile &O) override { + return M.MM->notifyObjectLoaded(EE, O); + } + + bool finalizeMemory(std::string *ErrMsg = nullptr) override { + // Each set of objects loaded will be finalized exactly once, but since + // symbol lookup during relocation may recursively trigger the + // loading/relocation of other modules, and since we're forwarding all + // finalizeMemory calls to a single underlying memory manager, we need to + // defer forwarding the call on until all necessary objects have been + // loaded. Otherwise, during the relocation of a leaf object, we will end + // up finalizing memory, causing a crash further up the stack when we + // attempt to apply relocations to finalized memory. + // To avoid finalizing too early, look at how many objects have been + // loaded but not yet finalized. This is a bit of a hack that relies on + // the fact that we're lazily emitting object files: The only way you can + // get more than one set of objects loaded but not yet finalized is if + // they were loaded during relocation of another set. + if (M.UnfinalizedSections.size() == 1) + return M.MM->finalizeMemory(ErrMsg); + return false; + } + + private: + OrcMCJITReplacement &M; + }; + +private: + + static ExecutionEngine * + createOrcMCJITReplacement(std::string *ErrorMsg, + std::unique_ptr<RTDyldMemoryManager> OrcJMM, + std::unique_ptr<TargetMachine> TM) { + return new OrcMCJITReplacement(std::move(OrcJMM), std::move(TM)); + } + +public: + static void Register() { + OrcMCJITReplacementCtor = createOrcMCJITReplacement; + } + + OrcMCJITReplacement(std::unique_ptr<RTDyldMemoryManager> MM, + std::unique_ptr<TargetMachine> TM) + : TM(std::move(TM)), MM(std::move(MM)), Mang(this->TM->getDataLayout()), + NotifyObjectLoaded(*this), NotifyFinalized(*this), + ObjectLayer(ObjectLayerT::CreateRTDyldMMFtor(), NotifyObjectLoaded, + NotifyFinalized), + CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)), + LazyEmitLayer(CompileLayer) { + setDataLayout(this->TM->getDataLayout()); + } + + void addModule(std::unique_ptr<Module> M) override { + + // If this module doesn't have a DataLayout attached then attach the + // default. + if (!M->getDataLayout()) + M->setDataLayout(getDataLayout()); + + Modules.push_back(std::move(M)); + std::vector<Module *> Ms; + Ms.push_back(&*Modules.back()); + LazyEmitLayer.addModuleSet(std::move(Ms), + llvm::make_unique<ForwardingRTDyldMM>(*this)); + } + + void addObjectFile(std::unique_ptr<object::ObjectFile> O) override { + std::vector<std::unique_ptr<object::ObjectFile>> Objs; + Objs.push_back(std::move(O)); + ObjectLayer.addObjectSet(std::move(Objs), + llvm::make_unique<ForwardingRTDyldMM>(*this)); + } + + 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)); + auto H = + ObjectLayer.addObjectSet(std::move(Objs), + llvm::make_unique<ForwardingRTDyldMM>(*this)); + + std::vector<std::unique_ptr<MemoryBuffer>> Bufs; + Bufs.push_back(std::move(Buf)); + ObjectLayer.takeOwnershipOfBuffers(H, std::move(Bufs)); + } + + void addArchive(object::OwningBinary<object::Archive> A) override { + Archives.push_back(std::move(A)); + } + + uint64_t getSymbolAddress(StringRef Name) { + return getSymbolAddressWithoutMangling(Mangle(Name)); + } + + void finalizeObject() override { + // This is deprecated - Aim to remove in ExecutionEngine. + // REMOVE IF POSSIBLE - Doesn't make sense for New JIT. + } + + void mapSectionAddress(const void *LocalAddress, + uint64_t TargetAddress) override { + for (auto &P : UnfinalizedSections) + if (P.second.count(LocalAddress)) + ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress); + } + + uint64_t getGlobalValueAddress(const std::string &Name) override { + return getSymbolAddress(Name); + } + + uint64_t getFunctionAddress(const std::string &Name) override { + return getSymbolAddress(Name); + } + + void *getPointerToFunction(Function *F) override { + uint64_t FAddr = getSymbolAddress(F->getName()); + return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr)); + } + + void *getPointerToNamedFunction(StringRef Name, + bool AbortOnFailure = true) override { + uint64_t Addr = getSymbolAddress(Name); + if (!Addr && AbortOnFailure) + llvm_unreachable("Missing symbol!"); + return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr)); + } + + GenericValue runFunction(Function *F, + const std::vector<GenericValue> &ArgValues) override; + + void setObjectCache(ObjectCache *NewCache) override { + CompileLayer.setObjectCache(NewCache); + } + +private: + uint64_t getSymbolAddressWithoutMangling(StringRef Name) { + if (uint64_t Addr = LazyEmitLayer.findSymbol(Name, false).getAddress()) + return Addr; + if (uint64_t Addr = MM->getSymbolAddress(Name)) + return Addr; + if (uint64_t Addr = scanArchives(Name)) + return Addr; + + return 0; + } + + uint64_t scanArchives(StringRef 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 (ChildIt != A->child_end()) { + // FIXME: Support nested archives? + ErrorOr<std::unique_ptr<object::Binary>> ChildBinOrErr = + ChildIt->getAsBinary(); + if (ChildBinOrErr.getError()) + continue; + std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get(); + if (ChildBin->isObject()) { + std::vector<std::unique_ptr<object::ObjectFile>> ObjSet; + ObjSet.push_back(std::unique_ptr<object::ObjectFile>( + static_cast<object::ObjectFile *>(ChildBin.release()))); + ObjectLayer.addObjectSet( + std::move(ObjSet), llvm::make_unique<ForwardingRTDyldMM>(*this)); + if (uint64_t Addr = ObjectLayer.findSymbol(Name, true).getAddress()) + return Addr; + } + } + } + return 0; + } + + 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) {} + + void operator()(ObjectLinkingLayerBase::ObjSetHandleT H, + const ObjListT &Objects, + const LoadedObjInfoListT &Infos) const { + M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad); + M.SectionsAllocatedSinceLastLoad = SectionAddrSet(); + assert(Objects.size() == Infos.size() && + "Incorrect number of Infos for Objects."); + for (unsigned I = 0; I < Objects.size(); ++I) + M.MM->notifyObjectLoaded(&M, *Objects[I]); + }; + + private: + OrcMCJITReplacement &M; + }; + + class NotifyFinalizedT { + public: + NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {} + void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) { + M.UnfinalizedSections.erase(H); + } + + private: + OrcMCJITReplacement &M; + }; + + std::string Mangle(StringRef Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + typedef ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT; + typedef IRCompileLayer<ObjectLayerT> CompileLayerT; + typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT; + + std::unique_ptr<TargetMachine> TM; + std::unique_ptr<RTDyldMemoryManager> MM; + Mangler Mang; + + NotifyObjectLoadedT NotifyObjectLoaded; + NotifyFinalizedT NotifyFinalized; + + ObjectLayerT ObjectLayer; + CompileLayerT CompileLayer; + LazyEmitLayerT LazyEmitLayer; + + // We need to store ObjLayerT::ObjSetHandles for each of the object sets + // that have been emitted but not yet finalized so that we can forward the + // mapSectionAddress calls appropriately. + typedef std::set<const void *> SectionAddrSet; + struct ObjSetHandleCompare { + bool operator()(ObjectLayerT::ObjSetHandleT H1, + ObjectLayerT::ObjSetHandleT H2) const { + return &*H1 < &*H2; + } + }; + SectionAddrSet SectionsAllocatedSinceLastLoad; + std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare> + UnfinalizedSections; + + std::vector<object::OwningBinary<object::Archive>> Archives; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H diff --git a/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp b/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp new file mode 100644 index 0000000..b5dda8e --- /dev/null +++ b/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp @@ -0,0 +1,128 @@ +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h" +#include <array> + +using namespace llvm::orc; + +namespace { + +std::array<const char *, 12> X86GPRsToSave = {{ + "rbp", "rbx", "r12", "r13", "r14", "r15", // Callee saved. + "rdi", "rsi", "rdx", "rcx", "r8", "r9", // Int args. +}}; + +std::array<const char *, 8> X86XMMsToSave = {{ + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" // FP args +}}; + +template <typename OStream> unsigned saveX86Regs(OStream &OS) { + for (const auto &GPR : X86GPRsToSave) + OS << " pushq %" << GPR << "\n"; + + OS << " subq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n"; + + for (unsigned i = 0; i < X86XMMsToSave.size(); ++i) + OS << " movdqu %" << X86XMMsToSave[i] << ", " + << (16 * (X86XMMsToSave.size() - i - 1)) << "(%rsp)\n"; + + return (8 * X86GPRsToSave.size()) + (16 * X86XMMsToSave.size()); +} + +template <typename OStream> void restoreX86Regs(OStream &OS) { + for (unsigned i = 0; i < X86XMMsToSave.size(); ++i) + OS << " movdqu " << (16 * i) << "(%rsp), %" + << X86XMMsToSave[(X86XMMsToSave.size() - i - 1)] << "\n"; + OS << " addq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n"; + + for (unsigned i = 0; i < X86GPRsToSave.size(); ++i) + OS << " popq %" << X86GPRsToSave[X86GPRsToSave.size() - i - 1] << "\n"; +} + +template <typename TargetT> +uint64_t executeCompileCallback(JITCompileCallbackManagerBase<TargetT> *JCBM, + TargetAddress CallbackID) { + return JCBM->executeCompileCallback(CallbackID); +} + +} + +namespace llvm { +namespace orc { + +const char* OrcX86_64::ResolverBlockName = "orc_resolver_block"; + +void OrcX86_64::insertResolverBlock( + Module &M, JITCompileCallbackManagerBase<OrcX86_64> &JCBM) { + auto CallbackPtr = executeCompileCallback<OrcX86_64>; + uint64_t CallbackAddr = + static_cast<uint64_t>(reinterpret_cast<uintptr_t>(CallbackPtr)); + + std::ostringstream AsmStream; + Triple TT(M.getTargetTriple()); + + if (TT.getOS() == Triple::Darwin) + AsmStream << ".section __TEXT,__text,regular,pure_instructions\n" + << ".align 4, 0x90\n"; + else + AsmStream << ".text\n" + << ".align 16, 0x90\n"; + + AsmStream << "jit_callback_manager_addr:\n" + << " .quad " << &JCBM << "\n" + << ResolverBlockName << ":\n"; + + uint64_t ReturnAddrOffset = saveX86Regs(AsmStream); + + // Compute index, load object address, and call JIT. + AsmStream << " leaq jit_callback_manager_addr(%rip), %rdi\n" + << " movq (%rdi), %rdi\n" + << " movq " << ReturnAddrOffset << "(%rsp), %rsi\n" + << " movabsq $" << CallbackAddr << ", %rax\n" + << " callq *%rax\n" + << " movq %rax, " << ReturnAddrOffset << "(%rsp)\n"; + + restoreX86Regs(AsmStream); + + AsmStream << " retq\n"; + + M.appendModuleInlineAsm(AsmStream.str()); +} + +OrcX86_64::LabelNameFtor +OrcX86_64::insertCompileCallbackTrampolines(Module &M, + TargetAddress ResolverBlockAddr, + unsigned NumCalls, + unsigned StartIndex) { + const char *ResolverBlockPtrName = "Lorc_resolve_block_addr"; + + std::ostringstream AsmStream; + Triple TT(M.getTargetTriple()); + + if (TT.getOS() == Triple::Darwin) + AsmStream << ".section __TEXT,__text,regular,pure_instructions\n" + << ".align 4, 0x90\n"; + else + AsmStream << ".text\n" + << ".align 16, 0x90\n"; + + AsmStream << ResolverBlockPtrName << ":\n" + << " .quad " << ResolverBlockAddr << "\n"; + + auto GetLabelName = + [=](unsigned I) { + std::ostringstream LabelStream; + LabelStream << "orc_jcc_" << (StartIndex + I); + return LabelStream.str(); + }; + + for (unsigned I = 0; I < NumCalls; ++I) + AsmStream << GetLabelName(I) << ":\n" + << " callq *" << ResolverBlockPtrName << "(%rip)\n"; + + M.appendModuleInlineAsm(AsmStream.str()); + + return GetLabelName; +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/lib/ExecutionEngine/RuntimeDyld/Android.mk b/lib/ExecutionEngine/RuntimeDyld/Android.mk index eb2e438..76aae67 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Android.mk +++ b/lib/ExecutionEngine/RuntimeDyld/Android.mk @@ -4,12 +4,12 @@ LOCAL_PATH:= $(call my-dir) # ===================================================== include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - GDBRegistrar.cpp \ - RuntimeDyld.cpp \ - RuntimeDyldChecker.cpp \ - RuntimeDyldELF.cpp \ - RuntimeDyldMachO.cpp +LOCAL_SRC_FILES := \ + RTDyldMemoryManager.cpp \ + RuntimeDyldChecker.cpp \ + RuntimeDyld.cpp \ + RuntimeDyldELF.cpp \ + RuntimeDyldMachO.cpp LOCAL_MODULE:= libLLVMRuntimeDyld diff --git a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt index eb1a60b..12bbcc6 100644 --- a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt +++ b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt @@ -1,5 +1,5 @@ add_llvm_library(LLVMRuntimeDyld - GDBRegistrar.cpp + RTDyldMemoryManager.cpp RuntimeDyld.cpp RuntimeDyldChecker.cpp RuntimeDyldELF.cpp diff --git a/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h b/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h deleted file mode 100644 index 636011f..0000000 --- a/lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- JITRegistrar.h - Registers objects with a debugger ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_JITREGISTRAR_H -#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_JITREGISTRAR_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" - -namespace llvm { - -/// Global access point for the JIT debugging interface. -class JITRegistrar { - virtual void anchor(); -public: - /// Instantiates the JIT service. - JITRegistrar() {} - - /// Unregisters each object that was previously registered and releases all - /// internal resources. - virtual ~JITRegistrar() {} - - /// Creates an entry in the JIT registry for the buffer @p Object, - /// which must contain an object file in executable memory with any - /// debug information for the debugger. - virtual void registerObject(const ObjectBuffer &Object) = 0; - - /// Removes the internal registration of @p Object, and - /// frees associated resources. - /// Returns true if @p Object was previously registered. - virtual bool deregisterObject(const ObjectBuffer &Object) = 0; - - /// Returns a reference to a GDB JIT registrar singleton - static JITRegistrar& getGDBRegistrar(); -}; - -} // end namespace llvm - -#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h deleted file mode 100644 index 9bbf6a0d..0000000 --- a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h +++ /dev/null @@ -1,86 +0,0 @@ -//===-- ObjectImageCommon.h - Format independent executuable object image -===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_OBJECTIMAGECOMMON_H -#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_OBJECTIMAGECOMMON_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" -#include "llvm/Object/ObjectFile.h" - -#include <memory> - -namespace llvm { - -namespace object { - class ObjectFile; -} - -class ObjectImageCommon : public ObjectImage { - ObjectImageCommon(); // = delete - ObjectImageCommon(const ObjectImageCommon &other); // = delete - void anchor() override; - -protected: - std::unique_ptr<object::ObjectFile> ObjFile; - - // This form of the constructor allows subclasses to use - // format-specific subclasses of ObjectFile directly - ObjectImageCommon(std::unique_ptr<ObjectBuffer> Input, - std::unique_ptr<object::ObjectFile> Obj) - : ObjectImage(std::move(Input)), ObjFile(std::move(Obj)) {} - -public: - ObjectImageCommon(std::unique_ptr<ObjectBuffer> Input) - : ObjectImage(std::move(Input)) { - // FIXME: error checking? createObjectFile returns an ErrorOr<ObjectFile*> - // and should probably be checked for failure. - MemoryBufferRef Buf = Buffer->getMemBuffer(); - ObjFile = std::move(object::ObjectFile::createObjectFile(Buf).get()); - } - ObjectImageCommon(std::unique_ptr<object::ObjectFile> Input) - : ObjectImage(nullptr), ObjFile(std::move(Input)) {} - virtual ~ObjectImageCommon() { } - - object::symbol_iterator begin_symbols() const override - { return ObjFile->symbol_begin(); } - object::symbol_iterator end_symbols() const override - { return ObjFile->symbol_end(); } - - object::section_iterator begin_sections() const override - { return ObjFile->section_begin(); } - object::section_iterator end_sections() const override - { return ObjFile->section_end(); } - - /* Triple::ArchType */ unsigned getArch() const override - { return ObjFile->getArch(); } - - StringRef getData() const override { return ObjFile->getData(); } - - object::ObjectFile* getObjectFile() const override { return ObjFile.get(); } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) override {} - void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) override {} - - // Subclasses can override these methods to provide JIT debugging support - void registerWithDebugger() override {} - void deregisterWithDebugger() override {} -}; - -} // end namespace llvm - -#endif diff --git a/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp index 51b2d0f..2a5e4f8 100644 --- a/lib/ExecutionEngine/RTDyldMemoryManager.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -13,6 +13,7 @@ #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include <cstdlib> @@ -210,6 +211,11 @@ ARM_MATH_IMPORTS(ARM_MATH_DECL) #undef ARM_MATH_DECL #endif +#if defined(__linux__) && defined(__GLIBC__) && \ + (defined(__i386__) || defined(__x86_64__)) +extern "C" LLVM_ATTRIBUTE_WEAK void __morestack(); +#endif + uint64_t RTDyldMemoryManager::getSymbolAddressInProcess(const std::string &Name) { // This implementation assumes that the host program is the target. @@ -233,6 +239,12 @@ RTDyldMemoryManager::getSymbolAddressInProcess(const std::string &Name) { if (Name == "lstat64") return (uint64_t)&lstat64; if (Name == "atexit") return (uint64_t)&atexit; if (Name == "mknod") return (uint64_t)&mknod; + +#if defined(__i386__) || defined(__x86_64__) + // __morestack lives in libgcc, a static library. + if (&__morestack && Name == "__morestack") + return (uint64_t)&__morestack; +#endif #endif // __linux__ && __GLIBC__ // See ARM_MATH_IMPORTS definition for explanation diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index c7c67f6..54f1a1c 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -12,13 +12,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "JITRegistrar.h" -#include "ObjectImageCommon.h" #include "RuntimeDyldCheckerImpl.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldMachO.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MutexGuard.h" @@ -30,10 +28,8 @@ using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. RuntimeDyldImpl::~RuntimeDyldImpl() {} -// Pin the JITRegistrar's and ObjectImage*'s vtables to this file. -void JITRegistrar::anchor() {} -void ObjectImage::anchor() {} -void ObjectImageCommon::anchor() {} +// Pin LoadedObjectInfo's vtables to this file. +void RuntimeDyld::LoadedObjectInfo::anchor() {} namespace llvm { @@ -139,93 +135,88 @@ static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) { return object_error::success; } -std::unique_ptr<ObjectImage> -RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) { +std::pair<unsigned, unsigned> +RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { MutexGuard locked(lock); - if (!Obj) - return nullptr; + // Grab the first Section ID. We'll use this later to construct the underlying + // range for the returned LoadedObjectInfo. + unsigned SectionsAddedBeginIdx = Sections.size(); // Save information about our target - Arch = (Triple::ArchType)Obj->getArch(); - IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian(); + Arch = (Triple::ArchType)Obj.getArch(); + IsTargetLittleEndian = Obj.isLittleEndian(); // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager if (MemMgr->needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; - computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW); + computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW); MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } - // Symbols found in this object - StringMap<SymbolLoc> LocalSymbols; // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments - CommonSymbolMap CommonSymbols; - // Maximum required total memory to allocate all common symbols - uint64_t CommonSize = 0; + CommonSymbolList CommonSymbols; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); - for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; + for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - object::SymbolRef::Type SymType; - StringRef Name; - Check(I->getType(SymType)); - Check(I->getName(Name)); - uint32_t Flags = I->getFlags(); bool IsCommon = Flags & SymbolRef::SF_Common; - if (IsCommon) { - // Add the common symbols to a list. We'll allocate them all below. - if (!GlobalSymbolTable.count(Name)) { - uint32_t Align; - Check(I->getAlignment(Align)); - uint64_t Size = 0; - Check(I->getSize(Size)); - CommonSize += Size + Align; - CommonSymbols[*I] = CommonSymbolInfo(Size, Align); - } - } else { + if (IsCommon) + CommonSymbols.push_back(*I); + else { + object::SymbolRef::Type SymType; + Check(I->getType(SymType)); + if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { + + StringRef Name; uint64_t SectOffset; - StringRef SectionData; - section_iterator SI = Obj->end_sections(); + Check(I->getName(Name)); Check(getOffset(*I, SectOffset)); + section_iterator SI = Obj.section_end(); Check(I->getSection(SI)); - if (SI == Obj->end_sections()) + if (SI == Obj.section_end()) continue; + StringRef SectionData; Check(SI->getContents(SectionData)); bool IsCode = SI->isText(); unsigned SectionID = - findOrEmitSection(*Obj, *SI, IsCode, LocalSections); - LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); - DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << " SID: " << SectionID); - GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + findOrEmitSection(Obj, *SI, IsCode, LocalSections); + DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name + << " SID: " << SectionID << " Offset: " + << format("%p", (uintptr_t)SectOffset) + << " flags: " << Flags << "\n"); + SymbolInfo::Visibility Vis = + (Flags & SymbolRef::SF_Exported) ? + SymbolInfo::Default : SymbolInfo::Hidden; + GlobalSymbolTable[Name] = SymbolInfo(SectionID, SectOffset, Vis); } } - DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols - if (CommonSize != 0) - emitCommonSymbols(*Obj, CommonSymbols, CommonSize, GlobalSymbolTable); + emitCommonSymbols(Obj, CommonSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); - for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); + if (RelocatedSection == SE) + continue; + relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); @@ -234,23 +225,24 @@ RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) { bool IsCode = RelocatedSection->isText(); SectionID = - findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections); + findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (; I != E;) - I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols, - Stubs); + I = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs); // If there is an attached checker, notify it about the stubs for this // section so that they can be verified. if (Checker) - Checker->registerStubMap(Obj->getImageName(), SectionID, Stubs); + Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs); } // Give the subclasses a chance to tie-up any loose ends. - finalizeLoad(*Obj, LocalSections); + finalizeLoad(Obj, LocalSections); + + unsigned SectionsAddedEndIdx = Sections.size(); - return Obj; + return std::make_pair(SectionsAddedBeginIdx, SectionsAddedEndIdx); } // A helper method for computeTotalAllocSize. @@ -268,9 +260,37 @@ computeAllocationSizeForSections(std::vector<uint64_t> &SectionSizes, return TotalSize; } +static bool isRequiredForExecution(const SectionRef &Section) { + const ObjectFile *Obj = Section.getObject(); + if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) + return ELFObj->getSectionFlags(Section) & ELF::SHF_ALLOC; + assert(isa<MachOObjectFile>(Obj)); + return true; + } + +static bool isReadOnlyData(const SectionRef &Section) { + const ObjectFile *Obj = Section.getObject(); + if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) + return !(ELFObj->getSectionFlags(Section) & + (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + assert(isa<MachOObjectFile>(Obj)); + return false; +} + +static bool isZeroInit(const SectionRef &Section) { + const ObjectFile *Obj = Section.getObject(); + if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) + return ELFObj->getSectionType(Section) == ELF::SHT_NOBITS; + + auto *MachO = cast<MachOObjectFile>(Obj); + unsigned SectionType = MachO->getSectionType(Section); + return SectionType == MachO::S_ZEROFILL || + SectionType == MachO::S_GB_ZEROFILL; +} + // Compute an upper bound of the memory size that is required to load all // sections -void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, +void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW) { @@ -282,11 +302,11 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, // Collect sizes of all sections to be loaded; // also determine the max alignment of all sections - for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { const SectionRef &Section = *SI; - bool IsRequired = Section.isRequiredForExecution(); + bool IsRequired = isRequiredForExecution(Section); // Consider only the sections that are required to be loaded for execution if (IsRequired) { @@ -294,7 +314,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, uint64_t DataSize = Section.getSize(); uint64_t Alignment64 = Section.getAlignment(); bool IsCode = Section.isText(); - bool IsReadOnly = Section.isReadOnlyData(); + bool IsReadOnly = isReadOnlyData(Section); Check(Section.getName(Name)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; @@ -328,7 +348,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, // Compute the size of all common symbols uint64_t CommonSize = 0; - for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; + for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { uint32_t Flags = I->getFlags(); if (Flags & SymbolRef::SF_Common) { @@ -353,7 +373,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, } // compute stub buffer size for the given section -unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, +unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section) { unsigned StubSize = getMaxStubSize(); if (StubSize == 0) { @@ -363,7 +383,7 @@ unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, // necessary section allocation size in loadObject by walking all the sections // once. unsigned StubBufSize = 0; - for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator RelSecI = SI->getRelocatedSection(); if (!(RelSecI == Section)) @@ -418,46 +438,77 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } } -void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, - SymbolTableMap &SymbolTable) { +void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, + CommonSymbolList &CommonSymbols) { + if (CommonSymbols.empty()) + return; + + uint64_t CommonSize = 0; + CommonSymbolList SymbolsToAllocate; + + DEBUG(dbgs() << "Processing common symbols...\n"); + + for (const auto &Sym : CommonSymbols) { + StringRef Name; + Check(Sym.getName(Name)); + + // Skip common symbols already elsewhere. + if (GlobalSymbolTable.count(Name) || + MemMgr->getSymbolAddressInLogicalDylib(Name)) { + DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name + << "'\n"); + continue; + } + + uint32_t Align = 0; + uint64_t Size = 0; + Check(Sym.getAlignment(Align)); + Check(Sym.getSize(Size)); + + CommonSize += Align + Size; + SymbolsToAllocate.push_back(Sym); + } + // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void *), + uint8_t *Addr = MemMgr->allocateDataSection(CommonSize, sizeof(void *), SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; - Sections.push_back(SectionEntry("<common symbols>", Addr, TotalSize, 0)); - memset(Addr, 0, TotalSize); + Sections.push_back(SectionEntry("<common symbols>", Addr, CommonSize, 0)); + memset(Addr, 0, CommonSize); DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: " - << format("%p", Addr) << " DataSize: " << TotalSize << "\n"); + << format("%p", Addr) << " DataSize: " << CommonSize << "\n"); // Assign the address of each symbol - for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(), - itEnd = CommonSymbols.end(); it != itEnd; ++it) { - uint64_t Size = it->second.first; - uint64_t Align = it->second.second; + for (auto &Sym : SymbolsToAllocate) { + uint32_t Align; + uint64_t Size; StringRef Name; - it->first.getName(Name); + Check(Sym.getAlignment(Align)); + Check(Sym.getSize(Size)); + Check(Sym.getName(Name)); if (Align) { // This symbol has an alignment requirement. uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align); Addr += AlignOffset; Offset += AlignOffset; - DEBUG(dbgs() << "Allocating common symbol " << Name << " address " - << format("%p\n", Addr)); } - Obj.updateSymbolAddress(it->first, (uint64_t)Addr); - SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); + uint32_t Flags = Sym.getFlags(); + SymbolInfo::Visibility Vis = + (Flags & SymbolRef::SF_Exported) ? + SymbolInfo::Default : SymbolInfo::Hidden; + DEBUG(dbgs() << "Allocating common symbol " << Name << " address " + << format("%p", Addr) << "\n"); + GlobalSymbolTable[Name] = SymbolInfo(SectionID, Offset, Vis); Offset += Size; Addr += Size; } } -unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, +unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode) { StringRef data; @@ -468,10 +519,10 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, unsigned PaddingSize = 0; unsigned StubBufSize = 0; StringRef Name; - bool IsRequired = Section.isRequiredForExecution(); + bool IsRequired = isRequiredForExecution(Section); bool IsVirtual = Section.isVirtual(); - bool IsZeroInit = Section.isZeroInit(); - bool IsReadOnly = Section.isReadOnlyData(); + bool IsZeroInit = isZeroInit(Section); + bool IsReadOnly = isReadOnlyData(Section); uint64_t DataSize = Section.getSize(); Check(Section.getName(Name)); @@ -521,7 +572,6 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); - Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything @@ -537,12 +587,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); if (Checker) - Checker->registerSection(Obj.getImageName(), SectionID); + Checker->registerSection(Obj.getFileName(), SectionID); return SectionID; } -unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj, +unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections) { @@ -568,14 +618,15 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, // Relocation by symbol. If the symbol is found in the global symbol table, // create an appropriate section relocation. Otherwise, add it to // ExternalSymbolRelocations. - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(SymbolName); + RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(SymbolName); if (Loc == GlobalSymbolTable.end()) { ExternalSymbolRelocations[SymbolName].push_back(RE); } else { // Copy the RE since we want to modify its addend. RelocationEntry RECopy = RE; - RECopy.Addend += Loc->second.second; - Relocations[Loc->second.first].push_back(RECopy); + const auto &SymInfo = Loc->second; + RECopy.Addend += SymInfo.getOffset(); + Relocations[SymInfo.getSectionID()].push_back(RECopy); } } @@ -700,7 +751,7 @@ void RuntimeDyldImpl::resolveExternalSymbols() { resolveRelocationList(Relocs, 0); } else { uint64_t Addr = 0; - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { // This is an external symbol, try to get its address from // MemoryManager. @@ -715,8 +766,9 @@ void RuntimeDyldImpl::resolveExternalSymbols() { } else { // We found the symbol in our global table. It was probably in a // Module that we loaded previously. - SymbolLoc SymLoc = Loc->second; - Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second; + const auto &SymInfo = Loc->second; + Addr = getSectionLoadAddress(SymInfo.getSectionID()) + + SymInfo.getOffset(); } // FIXME: Implement error handling that doesn't kill the host program! @@ -739,6 +791,16 @@ void RuntimeDyldImpl::resolveExternalSymbols() { //===----------------------------------------------------------------------===// // RuntimeDyld class implementation + +uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( + StringRef SectionName) const { + for (unsigned I = BeginIdx; I != EndIdx; ++I) + if (RTDyld.Sections[I].Name == SectionName) + return RTDyld.Sections[I].LoadAddress; + + return 0; +} + RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { // FIXME: There's a potential issue lurking here if a single instance of // RuntimeDyld is used to load multiple objects. The current implementation @@ -772,78 +834,23 @@ createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM, return Dyld; } -std::unique_ptr<ObjectImage> -RuntimeDyld::loadObject(std::unique_ptr<ObjectFile> InputObject) { - std::unique_ptr<ObjectImage> InputImage; - - ObjectFile &Obj = *InputObject; - - if (InputObject->isELF()) { - InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject))); - if (!Dyld) +std::unique_ptr<RuntimeDyld::LoadedObjectInfo> +RuntimeDyld::loadObject(const ObjectFile &Obj) { + if (!Dyld) { + if (Obj.isELF()) Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); - } else if (InputObject->isMachO()) { - InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject))); - if (!Dyld) + else if (Obj.isMachO()) Dyld = createRuntimeDyldMachO( - static_cast<Triple::ArchType>(InputImage->getArch()), MM, - ProcessAllSections, Checker); - } else - report_fatal_error("Incompatible object format!"); - - if (!Dyld->isCompatibleFile(&Obj)) - report_fatal_error("Incompatible object format!"); - - return Dyld->loadObject(std::move(InputImage)); -} - -std::unique_ptr<ObjectImage> -RuntimeDyld::loadObject(std::unique_ptr<ObjectBuffer> InputBuffer) { - std::unique_ptr<ObjectImage> InputImage; - sys::fs::file_magic Type = sys::fs::identify_magic(InputBuffer->getBuffer()); - auto *InputBufferPtr = InputBuffer.get(); - - switch (Type) { - case sys::fs::file_magic::elf: - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::elf_executable: - case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: - InputImage = RuntimeDyldELF::createObjectImage(std::move(InputBuffer)); - if (!Dyld) - Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); - break; - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::macho_executable: - case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: - case sys::fs::file_magic::macho_core: - case sys::fs::file_magic::macho_preload_executable: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib: - case sys::fs::file_magic::macho_dynamic_linker: - case sys::fs::file_magic::macho_bundle: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: - InputImage = RuntimeDyldMachO::createObjectImage(std::move(InputBuffer)); - if (!Dyld) - Dyld = createRuntimeDyldMachO( - static_cast<Triple::ArchType>(InputImage->getArch()), MM, - ProcessAllSections, Checker); - break; - case sys::fs::file_magic::unknown: - case sys::fs::file_magic::bitcode: - case sys::fs::file_magic::archive: - case sys::fs::file_magic::coff_object: - case sys::fs::file_magic::coff_import_library: - case sys::fs::file_magic::pecoff_executable: - case sys::fs::file_magic::macho_universal_binary: - case sys::fs::file_magic::windows_resource: - report_fatal_error("Incompatible object format!"); + static_cast<Triple::ArchType>(Obj.getArch()), MM, + ProcessAllSections, Checker); + else + report_fatal_error("Incompatible object format!"); } - if (!Dyld->isCompatibleFormat(InputBufferPtr)) + if (!Dyld->isCompatibleFile(Obj)) report_fatal_error("Incompatible object format!"); - return Dyld->loadObject(std::move(InputImage)); + return Dyld->loadObject(Obj); } void *RuntimeDyld::getSymbolAddress(StringRef Name) const { @@ -858,6 +865,12 @@ uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) const { return Dyld->getSymbolLoadAddress(Name); } +uint64_t RuntimeDyld::getExportedSymbolLoadAddress(StringRef Name) const { + if (!Dyld) + return 0; + return Dyld->getExportedSymbolLoadAddress(Name); +} + void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); } void RuntimeDyld::reassignSectionAddress(unsigned SectionID, uint64_t Addr) { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index 8818349..976a434 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" +#include "RuntimeDyldCheckerImpl.h" +#include "RuntimeDyldImpl.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/Path.h" -#include "RuntimeDyldCheckerImpl.h" -#include "RuntimeDyldImpl.h" #include <cctype> #include <memory> @@ -260,9 +260,7 @@ private: << "'. Instruction has only " << format("%i", Inst.getNumOperands()) << " operands.\nInstruction is:\n "; - Inst.dump_pretty(ErrMsgStream, - Checker.Disassembler->getContext().getAsmInfo(), - Checker.InstPrinter); + Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter); return std::make_pair(EvalResult(ErrMsgStream.str()), ""); } @@ -272,9 +270,7 @@ private: raw_string_ostream ErrMsgStream(ErrMsg); ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '" << Symbol << "' is not an immediate.\nInstruction is:\n "; - Inst.dump_pretty(ErrMsgStream, - Checker.Disassembler->getContext().getAsmInfo(), - Checker.InstPrinter); + Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter); return std::make_pair(EvalResult(ErrMsgStream.str()), ""); } @@ -740,7 +736,9 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLinkerAddr(StringRef Symbol) const { } uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { - return getRTDyld().getAnySymbolRemoteAddress(Symbol); + if (uint64_t InternalSymbolAddr = getRTDyld().getSymbolLoadAddress(Symbol)) + return InternalSymbolAddr; + return getRTDyld().MemMgr->getSymbolAddress(Symbol); } uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, @@ -848,14 +846,16 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor( StringRef RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const { - RuntimeDyldImpl::SymbolTableMap::const_iterator pos = + RTDyldSymbolTable::const_iterator pos = getRTDyld().GlobalSymbolTable.find(Name); if (pos == getRTDyld().GlobalSymbolTable.end()) return StringRef(); - RuntimeDyldImpl::SymbolLoc Loc = pos->second; - uint8_t *SectionAddr = getRTDyld().getSectionAddress(Loc.first); - return StringRef(reinterpret_cast<const char *>(SectionAddr) + Loc.second, - getRTDyld().Sections[Loc.first].Size - Loc.second); + const auto &SymInfo = pos->second; + uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID()); + return StringRef(reinterpret_cast<const char *>(SectionAddr) + + SymInfo.getOffset(), + getRTDyld().Sections[SymInfo.getSectionID()].Size - + SymInfo.getOffset()); } void RuntimeDyldCheckerImpl::registerSection( @@ -885,9 +885,10 @@ void RuntimeDyldCheckerImpl::registerStubMap( // If this is a (Section, Offset) pair, do a reverse lookup in the // global symbol table to find the name. for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) { - if (GSTEntry.second.first == StubMapEntry.first.SectionID && - GSTEntry.second.second == - static_cast<uint64_t>(StubMapEntry.first.Offset)) { + const auto &SymInfo = GSTEntry.second; + if (SymInfo.getSectionID() == StubMapEntry.first.SectionID && + SymInfo.getOffset() == + static_cast<uint64_t>(StubMapEntry.first.Offset)) { SymbolName = GSTEntry.first(); break; } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index d95cffe..0f3ca0f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -12,27 +12,23 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldELF.h" -#include "JITRegistrar.h" -#include "ObjectImageCommon.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; using namespace llvm::object; #define DEBUG_TYPE "dyld" -namespace { - static inline std::error_code check(std::error_code Err) { if (Err) { report_fatal_error(Err.message()); @@ -40,6 +36,8 @@ static inline std::error_code check(std::error_code Err) { return Err; } +namespace { + template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -52,16 +50,12 @@ template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> { typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; - std::unique_ptr<ObjectFile> UnderlyingFile; - public: - DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile, - MemoryBufferRef Wrapper, std::error_code &ec); - DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec); void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); - void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr); + + void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr); // Methods for type inquiry through isa, cast and dyn_cast static inline bool classof(const Binary *v) { @@ -71,42 +65,10 @@ public: static inline bool classof(const ELFObjectFile<ELFT> *v) { return v->isDyldType(); } -}; - -template <class ELFT> class ELFObjectImage : public ObjectImageCommon { - bool Registered; -public: - ELFObjectImage(std::unique_ptr<ObjectBuffer> Input, - std::unique_ptr<DyldELFObject<ELFT>> Obj) - : ObjectImageCommon(std::move(Input), std::move(Obj)), Registered(false) { - } - - virtual ~ELFObjectImage() { - if (Registered) - deregisterWithDebugger(); - } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override { - static_cast<DyldELFObject<ELFT>*>(getObjectFile()) - ->updateSectionAddress(Sec, Addr); - } +}; - void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override { - static_cast<DyldELFObject<ELFT>*>(getObjectFile()) - ->updateSymbolAddress(Sym, Addr); - } - void registerWithDebugger() override { - JITRegistrar::getGDBRegistrar().registerObject(*Buffer); - Registered = true; - } - void deregisterWithDebugger() override { - JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); - } -}; // The MemoryBuffer passed into this constructor is just a wrapper around the // actual memory. Ultimately, the Binary parent class will take ownership of @@ -118,14 +80,6 @@ DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC) } template <class ELFT> -DyldELFObject<ELFT>::DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile, - MemoryBufferRef Wrapper, std::error_code &EC) - : ELFObjectFile<ELFT>(Wrapper, EC), - UnderlyingFile(std::move(UnderlyingFile)) { - this->isDyldELFObject = true; -} - -template <class ELFT> void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); @@ -149,10 +103,89 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, sym->st_value = static_cast<addr_type>(Addr); } +class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo { +public: + LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary<ObjectFile> + getObjectForDebug(const ObjectFile &Obj) const override; +}; + +template <typename ELFT> +std::unique_ptr<DyldELFObject<ELFT>> +createRTDyldELFObject(MemoryBufferRef Buffer, + const LoadedELFObjectInfo &L, + std::error_code &ec) { + typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type; + + std::unique_ptr<DyldELFObject<ELFT>> Obj = + llvm::make_unique<DyldELFObject<ELFT>>(Buffer, ec); + + // Iterate over all sections in the object. + for (const auto &Sec : Obj->sections()) { + StringRef SectionName; + Sec.getName(SectionName); + if (SectionName != "") { + DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); + Elf_Shdr *shdr = const_cast<Elf_Shdr *>( + reinterpret_cast<const Elf_Shdr *>(ShdrRef.p)); + + if (uint64_t SecLoadAddr = L.getSectionLoadAddress(SectionName)) { + // This assumes that the address passed in matches the target address + // bitness. The template-based type cast handles everything else. + shdr->sh_addr = static_cast<addr_type>(SecLoadAddr); + } + } + } + + return Obj; +} + +OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj, + const LoadedELFObjectInfo &L) { + assert(Obj.isELF() && "Not an ELF object file."); + + std::unique_ptr<MemoryBuffer> Buffer = + MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName()); + + std::error_code ec; + + std::unique_ptr<ObjectFile> DebugObj; + if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) { + typedef ELFType<support::little, 2, false> ELF32LE; + DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) { + typedef ELFType<support::big, 2, false> ELF32BE; + DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) { + typedef ELFType<support::big, 2, true> ELF64BE; + DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) { + typedef ELFType<support::little, 2, true> ELF64LE; + DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), L, ec); + } else + llvm_unreachable("Unexpected ELF format"); + + assert(!ec && "Could not construct copy ELF object file"); + + return OwningBinary<ObjectFile>(std::move(DebugObj), std::move(Buffer)); +} + +OwningBinary<ObjectFile> +LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { + return createELFDebugObject(Obj, *this); +} + } // namespace namespace llvm { +RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} +RuntimeDyldELF::~RuntimeDyldELF() {} + void RuntimeDyldELF::registerEHFrames() { if (!MemMgr) return; @@ -180,83 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() { RegisteredEHFrameSections.clear(); } -ObjectImage * -RuntimeDyldELF::createObjectImageFromFile(std::unique_ptr<object::ObjectFile> ObjFile) { - if (!ObjFile) - return nullptr; - - std::error_code ec; - MemoryBufferRef Buffer = ObjFile->getMemoryBufferRef(); - - if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique<DyldELFObject<ELFType<support::little, 2, false>>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage<ELFType<support::little, 2, false>>( - nullptr, std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique<DyldELFObject<ELFType<support::big, 2, false>>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage<ELFType<support::big, 2, false>>(nullptr, std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) { - auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 2, true>>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage<ELFType<support::big, 2, true>>(nullptr, - std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique<DyldELFObject<ELFType<support::little, 2, true>>>( - std::move(ObjFile), Buffer, ec); - return new ELFObjectImage<ELFType<support::little, 2, true>>( - nullptr, std::move(Obj)); - } else - llvm_unreachable("Unexpected ELF format"); +std::unique_ptr<RuntimeDyld::LoadedObjectInfo> +RuntimeDyldELF::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique<LoadedELFObjectInfo>(*this, SectionStartIdx, + SectionEndIdx); } -std::unique_ptr<ObjectImage> -RuntimeDyldELF::createObjectImage(std::unique_ptr<ObjectBuffer> Buffer) { - if (Buffer->getBufferSize() < ELF::EI_NIDENT) - llvm_unreachable("Unexpected ELF object size"); - std::pair<unsigned char, unsigned char> Ident = - std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS], - (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]); - std::error_code ec; - - MemoryBufferRef Buf = Buffer->getMemBuffer(); - - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) { - auto Obj = - llvm::make_unique<DyldELFObject<ELFType<support::little, 4, false>>>( - Buf, ec); - return llvm::make_unique< - ELFObjectImage<ELFType<support::little, 4, false>>>(std::move(Buffer), - std::move(Obj)); - } - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) { - auto Obj = - llvm::make_unique<DyldELFObject<ELFType<support::big, 4, false>>>(Buf, - ec); - return llvm::make_unique<ELFObjectImage<ELFType<support::big, 4, false>>>( - std::move(Buffer), std::move(Obj)); - } - if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) { - auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 8, true>>>( - Buf, ec); - return llvm::make_unique<ELFObjectImage<ELFType<support::big, 8, true>>>( - std::move(Buffer), std::move(Obj)); - } - assert(Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB && - "Unexpected ELF format"); - auto Obj = - llvm::make_unique<DyldELFObject<ELFType<support::little, 8, true>>>(Buf, - ec); - return llvm::make_unique<ELFObjectImage<ELFType<support::little, 8, true>>>( - std::move(Buffer), std::move(Obj)); -} - -RuntimeDyldELF::~RuntimeDyldELF() {} - void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, @@ -615,7 +579,7 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, } // Return the .TOC. section and offset. -void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, +void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel) { // Set a default SectionID in case we do not find a TOC section below. @@ -628,7 +592,7 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, // The TOC consists of sections .got, .toc, .tocbss, .plt in that // order. The TOC starts where the first of these sections starts. - for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); + for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { StringRef SectionName; @@ -650,15 +614,15 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, // Returns the sections and offset associated with the ODP entry referenced // by Symbol. -void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, +void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &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.begin_sections(), se = Obj.end_sections(); + for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { section_iterator RelSecI = si->getRelocatedSection(); - if (RelSecI == Obj.end_sections()) + if (RelSecI == Obj.section_end()) continue; StringRef RelSectionName; @@ -700,7 +664,7 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, if (Rel.Addend != (int64_t)TargetSymbolOffset) continue; - section_iterator tsi(Obj.end_sections()); + section_iterator tsi(Obj.section_end()); check(TargetSymbol->getSection(tsi)); bool IsCode = tsi->isText(); Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections); @@ -935,8 +899,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, } relocation_iterator RuntimeDyldELF::processRelocationRef( - unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, + unsigned SectionID, relocation_iterator RelI, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { uint64_t RelType; Check(RelI->getType(RelType)); @@ -946,66 +911,60 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // Obtain the symbol name which is referenced in the relocation StringRef TargetName; - if (Symbol != Obj.end_symbols()) + if (Symbol != Obj.symbol_end()) Symbol->getName(TargetName); DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend << " TargetName: " << TargetName << "\n"); RelocationValueRef Value; // First search for the symbol in the local symbol table - SymbolTableMap::const_iterator lsi = Symbols.end(); SymbolRef::Type SymType = SymbolRef::ST_Unknown; - if (Symbol != Obj.end_symbols()) { - lsi = Symbols.find(TargetName.data()); + + // Search for the symbol in the global symbol table + RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end(); + if (Symbol != Obj.symbol_end()) { + gsi = GlobalSymbolTable.find(TargetName.data()); Symbol->getType(SymType); } - if (lsi != Symbols.end()) { - Value.SectionID = lsi->second.first; - Value.Offset = lsi->second.second; - Value.Addend = lsi->second.second + Addend; + if (gsi != GlobalSymbolTable.end()) { + const auto &SymInfo = gsi->second; + Value.SectionID = SymInfo.getSectionID(); + Value.Offset = SymInfo.getOffset(); + Value.Addend = SymInfo.getOffset() + Addend; } else { - // Search for the symbol in the global symbol table - SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); - if (Symbol != Obj.end_symbols()) - gsi = GlobalSymbolTable.find(TargetName.data()); - if (gsi != GlobalSymbolTable.end()) { - Value.SectionID = gsi->second.first; - Value.Offset = gsi->second.second; - Value.Addend = gsi->second.second + Addend; - } else { - switch (SymType) { - case SymbolRef::ST_Debug: { - // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously - // and can be changed by another developers. Maybe best way is add - // a new symbol type ST_Section to SymbolRef and use it. - section_iterator si(Obj.end_sections()); - Symbol->getSection(si); - if (si == Obj.end_sections()) - 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); - Value.Addend = Addend; - break; - } - case SymbolRef::ST_Data: - case SymbolRef::ST_Unknown: { - Value.SymbolName = TargetName.data(); - Value.Addend = Addend; - - // Absolute relocations will have a zero symbol ID (STN_UNDEF), which - // will manifest here as a NULL symbol name. - // We can set this as a valid (but empty) symbol name, and rely - // on addRelocationForSymbol to handle this. - if (!Value.SymbolName) - Value.SymbolName = ""; - break; - } - default: - llvm_unreachable("Unresolved symbol type!"); - break; - } + switch (SymType) { + case SymbolRef::ST_Debug: { + // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously + // and can be changed by another developers. Maybe best way is add + // a new symbol type ST_Section to SymbolRef and use it. + section_iterator si(Obj.section_end()); + Symbol->getSection(si); + 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); + Value.Addend = Addend; + break; + } + case SymbolRef::ST_Data: + case SymbolRef::ST_Unknown: { + Value.SymbolName = TargetName.data(); + Value.Addend = Addend; + + // Absolute relocations will have a zero symbol ID (STN_UNDEF), which + // will manifest here as a NULL symbol name. + // We can set this as a valid (but empty) symbol name, and rely + // on addRelocationForSymbol to handle this. + if (!Value.SymbolName) + Value.SymbolName = ""; + break; + } + default: + llvm_unreachable("Unresolved symbol type!"); + break; } } + uint64_t Offset; Check(RelI->getOffset(Offset)); @@ -1135,7 +1094,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( if (RelType == ELF::R_PPC64_REL24) { // Determine ABI variant in use for this object. unsigned AbiVariant; - Obj.getObjectFile()->getPlatformFlags(AbiVariant); + Obj.getPlatformFlags(AbiVariant); AbiVariant &= ELF::EF_PPC64_ABI; // A PPC branch relocation will need a stub function if the target is // an external symbol (Symbol::ST_Unknown) or if the target address @@ -1495,7 +1454,7 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { return 0; } -void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg, +void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { // If necessary, allocate the global offset table if (MemMgr) { @@ -1533,15 +1492,8 @@ void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg, } } -bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { - if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) - return false; - return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, - strlen(ELF::ElfMagic))) == 0; -} - -bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isELF(); +bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isELF(); } } // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 4aeab81..b4414b0 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -28,9 +28,11 @@ std::error_code Check(std::error_code Err) { } return Err; } + } // end anonymous namespace class RuntimeDyldELF : public RuntimeDyldImpl { + void resolveRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset = 0); @@ -81,9 +83,11 @@ class RuntimeDyldELF : public RuntimeDyldImpl { return 1; } - void findPPC64TOCSection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, + void findPPC64TOCSection(const ObjectFile &Obj, + ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, + void findOPDEntrySection(const ObjectFile &Obj, + ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); @@ -104,24 +108,23 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector<SID, 2> RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldELF(RTDyldMemoryManager *mm); + virtual ~RuntimeDyldELF(); + + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> + loadObject(const object::ObjectFile &O) override; void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override; - bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; - bool isCompatibleFile(const object::ObjectFile *Buffer) const override; + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; void registerEHFrames() override; void deregisterEHFrames() override; - void finalizeLoad(ObjectImage &ObjImg, + void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; - virtual ~RuntimeDyldELF(); - - static std::unique_ptr<ObjectImage> - createObjectImage(std::unique_ptr<ObjectBuffer> InputBuffer); - static ObjectImage *createObjectImageFromFile(std::unique_ptr<object::ObjectFile> Obj); }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 69ea3b4..f37a9a7 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -18,7 +18,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/Object/ObjectFile.h" @@ -37,7 +36,6 @@ using namespace llvm::object; namespace llvm { -class ObjectBuffer; class Twine; /// SectionEntry - represents a section emitted into memory by the dynamic @@ -158,16 +156,31 @@ public: } }; -class RuntimeDyldImpl { - friend class RuntimeDyldCheckerImpl; +/// @brief Symbol info for RuntimeDyld. +class SymbolInfo { +public: + typedef enum { Hidden = 0, Default = 1 } Visibility; + + SymbolInfo() : Offset(0), SectionID(0), Vis(Hidden) {} + + SymbolInfo(unsigned SectionID, uint64_t Offset, Visibility Vis) + : Offset(Offset), SectionID(SectionID), Vis(Vis) {} + + unsigned getSectionID() const { return SectionID; } + uint64_t getOffset() const { return Offset; } + Visibility getVisibility() const { return Vis; } + private: + uint64_t Offset; + unsigned SectionID : 31; + Visibility Vis : 1; +}; - uint64_t getAnySymbolRemoteAddress(StringRef Symbol) { - if (uint64_t InternalSymbolAddr = getSymbolLoadAddress(Symbol)) - return InternalSymbolAddr; - return MemMgr->getSymbolAddress(Symbol); - } +typedef StringMap<SymbolInfo> RTDyldSymbolTable; +class RuntimeDyldImpl { + friend class RuntimeDyld::LoadedObjectInfo; + friend class RuntimeDyldCheckerImpl; protected: // The MemoryManager to load objects into. RTDyldMemoryManager *MemMgr; @@ -187,16 +200,11 @@ protected: // references it. typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; - // A global symbol table for symbols from all loaded modules. Maps the - // symbol name to a (SectionID, offset in section) pair. - typedef std::pair<unsigned, uintptr_t> SymbolLoc; - typedef StringMap<SymbolLoc> SymbolTableMap; - SymbolTableMap GlobalSymbolTable; + // A global symbol table for symbols from all loaded modules. + RTDyldSymbolTable GlobalSymbolTable; - // Pair representing the size and alignment requirement for a common symbol. - typedef std::pair<unsigned, unsigned> CommonSymbolInfo; // Keep a map of common symbols to their info pairs - typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap; + typedef std::vector<SymbolRef> CommonSymbolList; // For each symbol, keep a list of relocations based on it. Anytime // its address is reassigned (the JIT re-compiled the function, e.g.), @@ -296,14 +304,13 @@ 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(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, SymbolTableMap &SymbolTable); + void emitCommonSymbols(const ObjectFile &Obj, CommonSymbolList &CommonSymbols); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be /// used for emits, else allocateDataSection() will be used. /// \return SectionID. - unsigned emitSection(ObjectImage &Obj, const SectionRef &Section, + unsigned emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode); /// \brief Find Section in LocalSections. If the secton is not found - emit @@ -311,7 +318,7 @@ protected: /// \param IsCode if it's true then allocateCodeSection() will be /// used for emmits, else allocateDataSection() will be used. /// \return SectionID. - unsigned findOrEmitSection(ObjectImage &Obj, const SectionRef &Section, + unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections); // \brief Add a relocation entry that uses the given section. @@ -339,8 +346,8 @@ protected: /// \return Iterator to the next relocation that needs to be parsed. virtual relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) = 0; + const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) = 0; /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); @@ -351,13 +358,16 @@ protected: // \brief Compute an upper bound of the memory that is required to load all // sections - void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, + void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW); // \brief Compute the stub buffer size required for a section - unsigned computeSectionStubBufSize(ObjectImage &Obj, + unsigned computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section); + // \brief Implementation of the generic part of the loadObject algorithm. + std::pair<unsigned, unsigned> loadObjectImpl(const object::ObjectFile &Obj); + public: RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) { @@ -373,27 +383,37 @@ public: this->Checker = Checker; } - std::unique_ptr<ObjectImage> - loadObject(std::unique_ptr<ObjectImage> InputObject); + virtual std::unique_ptr<RuntimeDyld::LoadedObjectInfo> + loadObject(const object::ObjectFile &Obj) = 0; uint8_t* getSymbolAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); if (pos == GlobalSymbolTable.end()) return nullptr; - SymbolLoc Loc = pos->second; - return getSectionAddress(Loc.first) + Loc.second; + const auto &SymInfo = pos->second; + return getSectionAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); } uint64_t getSymbolLoadAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); if (pos == GlobalSymbolTable.end()) return 0; - SymbolLoc Loc = pos->second; - return getSectionLoadAddress(Loc.first) + Loc.second; + const auto &SymInfo = pos->second; + return getSectionLoadAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); + } + + uint64_t getExportedSymbolLoadAddress(StringRef Name) const { + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos == GlobalSymbolTable.end()) + return 0; + const auto &SymInfo = pos->second; + if (SymInfo.getVisibility() == SymbolInfo::Hidden) + return 0; + return getSectionLoadAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); } void resolveRelocations(); @@ -411,14 +431,14 @@ public: // Get the error message. StringRef getErrorString() { return ErrorStr; } - virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; - virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0; + virtual bool isCompatibleFile(const ObjectFile &Obj) const = 0; virtual void registerEHFrames(); virtual void deregisterEHFrames(); - virtual void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) {} + virtual void finalizeLoad(const ObjectFile &ObjImg, + ObjSectionToIDMap &SectionMap) {} }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index d3d6f5d..2d39662 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -12,19 +12,34 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldMachO.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" - -#include "Targets/RuntimeDyldMachOARM.h" #include "Targets/RuntimeDyldMachOAArch64.h" +#include "Targets/RuntimeDyldMachOARM.h" #include "Targets/RuntimeDyldMachOI386.h" #include "Targets/RuntimeDyldMachOX86_64.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" using namespace llvm; using namespace llvm::object; #define DEBUG_TYPE "dyld" +namespace { + +class LoadedMachOObjectInfo : public RuntimeDyld::LoadedObjectInfo { +public: + LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary<ObjectFile> + getObjectForDebug(const ObjectFile &Obj) const override { + return OwningBinary<ObjectFile>(); + } +}; + +} + namespace llvm { int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { @@ -35,12 +50,11 @@ int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { } RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( - ObjectImage &ObjImg, const relocation_iterator &RI, - const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols) { + const ObjectFile &BaseTObj, const relocation_iterator &RI, + const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; @@ -50,24 +64,20 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); - SymbolTableMap::const_iterator SI = Symbols.find(TargetName.data()); - if (SI != Symbols.end()) { - Value.SectionID = SI->second.first; - Value.Offset = SI->second.second + RE.Addend; + RTDyldSymbolTable::const_iterator SI = + GlobalSymbolTable.find(TargetName.data()); + if (SI != GlobalSymbolTable.end()) { + const auto &SymInfo = SI->second; + Value.SectionID = SymInfo.getSectionID(); + Value.Offset = SymInfo.getOffset() + RE.Addend; } else { - SI = GlobalSymbolTable.find(TargetName.data()); - if (SI != GlobalSymbolTable.end()) { - Value.SectionID = SI->second.first; - Value.Offset = SI->second.second + RE.Addend; - } else { - Value.SymbolName = TargetName.data(); - Value.Offset = RE.Addend; - } + Value.SymbolName = TargetName.data(); + Value.Offset = RE.Addend; } } else { SectionRef Sec = Obj.getRelocationSection(RelInfo); bool IsCode = Sec.isText(); - Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); + Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); Value.Offset = RE.Addend - Addr; } @@ -76,11 +86,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( } void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, - ObjectImage &ObjImg, + const ObjectFile &BaseTObj, const relocation_iterator &RI, unsigned OffsetToNextPC) { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); @@ -125,7 +135,7 @@ RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, // Populate __pointers section. void RuntimeDyldMachO::populateIndirectSymbolPointersSection( - MachOObjectFile &Obj, + const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID) { assert(!Obj.is64Bit() && @@ -163,28 +173,12 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection( } } -bool -RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { - if (InputBuffer->getBufferSize() < 4) - return false; - StringRef Magic(InputBuffer->getBufferStart(), 4); - if (Magic == "\xFE\xED\xFA\xCE") - return true; - if (Magic == "\xCE\xFA\xED\xFE") - return true; - if (Magic == "\xFE\xED\xFA\xCF") - return true; - if (Magic == "\xCF\xFA\xED\xFE") - return true; - return false; -} - -bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isMachO(); +bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isMachO(); } template <typename Impl> -void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(ObjectImage &ObjImg, +void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &ObjImg, ObjSectionToIDMap &SectionMap) { unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; unsigned TextSID = RTDYLD_INVALID_SECTION_ID; @@ -284,7 +278,7 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { } std::unique_ptr<RuntimeDyldMachO> -llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); @@ -296,4 +290,12 @@ llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { } } +std::unique_ptr<RuntimeDyld::LoadedObjectInfo> +RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique<LoadedMachOObjectInfo>(*this, SectionStartIdx, + SectionEndIdx); +} + } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 7583474..f8bfc03 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -14,7 +14,6 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H -#include "ObjectImageCommon.h" #include "RuntimeDyldImpl.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Format.h" @@ -61,10 +60,11 @@ protected: /// filled in, since immediate encodings are highly target/opcode specific. /// For targets/opcodes with simple, contiguous immediates (e.g. X86) the /// memcpyAddend method can be used to read the immediate. - RelocationEntry getRelocationEntry(unsigned SectionID, ObjectImage &ObjImg, + RelocationEntry getRelocationEntry(unsigned SectionID, + const ObjectFile &BaseTObj, const relocation_iterator &RI) const { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); @@ -87,14 +87,14 @@ 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(ObjectImage &ObjImg, + RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols); + ObjSectionToIDMap &ObjSectionToID); /// Make the RelocationValueRef addend PC-relative. - void makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg, + void makeValueAddendPCRel(RelocationValueRef &Value, + const ObjectFile &BaseTObj, const relocation_iterator &RI, unsigned OffsetToNextPC); @@ -107,31 +107,22 @@ protected: // Populate __pointers section. - void populateIndirectSymbolPointersSection(MachOObjectFile &Obj, + void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID); public: - /// Create an ObjectImage from the given ObjectBuffer. - static std::unique_ptr<ObjectImage> - createObjectImage(std::unique_ptr<ObjectBuffer> InputBuffer) { - return llvm::make_unique<ObjectImageCommon>(std::move(InputBuffer)); - } - - /// Create an ObjectImage from the given ObjectFile. - static ObjectImage * - createObjectImageFromFile(std::unique_ptr<object::ObjectFile> InputObject) { - return new ObjectImageCommon(std::move(InputObject)); - } /// Create a RuntimeDyldMachO instance for the given target architecture. static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch, RTDyldMemoryManager *mm); + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> + loadObject(const object::ObjectFile &O) override; + SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } - bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; - bool isCompatibleFile(const object::ObjectFile *Obj) const override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; }; /// RuntimeDyldMachOTarget - Templated base class for generic MachO linker @@ -153,7 +144,7 @@ private: public: RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {} - void finalizeLoad(ObjectImage &ObjImg, + void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; void registerEHFrames() override; }; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index f5cf9ac..196fa62 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -183,8 +183,8 @@ public: assert(isInt<33>(Addend) && "Invalid page reloc value."); // Encode the addend into the instruction. - uint32_t ImmLoValue = (uint32_t)(Addend << 17) & 0x60000000; - uint32_t ImmHiValue = (uint32_t)(Addend >> 9) & 0x00FFFFE0; + uint32_t ImmLoValue = ((uint64_t)Addend << 17) & 0x60000000; + uint32_t ImmHiValue = ((uint64_t)Addend >> 9) & 0x00FFFFE0; *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue; break; } @@ -243,10 +243,11 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); @@ -268,10 +269,10 @@ public: RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); } - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\ "ARM64_RELOC_ADDEND and embedded addend in the instruction."); @@ -282,7 +283,7 @@ public: bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); RE.Addend = Value.Offset; @@ -359,7 +360,7 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) {} private: diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 9766751..09e430e 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -49,29 +49,30 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = Obj.getAnyRelocationType(RelInfo); if (Obj.isRelocationScattered(RelInfo)) { if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) - return processHALFSECTDIFFRelocation(SectionID, RelI, ObjImg, + return processHALFSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); else return ++++RelI; } - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); if (RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 8); + makeValueAddendPCRel(Value, Obj, RelI, 8); if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) processBranchRelocation(RE, Value, Stubs); @@ -154,15 +155,14 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__nl_symbol_ptr") - populateIndirectSymbolPointersSection( - cast<MachOObjectFile>(*ObjImg.getObjectFile()), - Section, SectionID); + populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), + Section, SectionID); } private: @@ -199,25 +199,25 @@ private: relocation_iterator processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, + const ObjectFile &BaseTObj, ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast<const MachOObjectFile *>(Obj.getObjectFile()); + const MachOObjectFile &MachO = + static_cast<const MachOObjectFile&>(BaseTObj); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + MachO.getRelocation(RelI->getRawDataRefImpl()); // For a half-diff relocation the length bits actually record whether this // is a movw/movt, and whether this is arm or thumb. // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). - unsigned HalfDiffKindBits = MachO->getAnyRelocationLength(RE); + unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE); if (HalfDiffKindBits & 0x2) llvm_unreachable("Thumb not yet supported."); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); + uint32_t RelocType = MachO.getAnyRelocationType(RE); + bool IsPCRel = MachO.getAnyRelocationPCRel(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; @@ -226,27 +226,27 @@ private: ++RelI; MachO::any_relocation_info RE2 = - MachO->getRelocation(RelI->getRawDataRefImpl()); - uint32_t AddrA = MachO->getScatteredRelocationValue(RE); - section_iterator SAI = getSectionByAddress(*MachO, AddrA); - assert(SAI != MachO->section_end() && "Can't find section for address A"); + MachO.getRelocation(RelI->getRawDataRefImpl()); + uint32_t AddrA = MachO.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(MachO, AddrA); + assert(SAI != MachO.section_end() && "Can't find section for address A"); uint64_t SectionABase = SAI->getAddress(); uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; bool IsCode = SectionA.isText(); uint32_t SectionAID = - findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); + findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID); - uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); - section_iterator SBI = getSectionByAddress(*MachO, AddrB); - assert(SBI != MachO->section_end() && "Can't find section for address B"); + uint32_t AddrB = MachO.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(MachO, AddrB); + assert(SBI != MachO.section_end() && "Can't find section for address B"); uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; uint32_t SectionBID = - findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); + findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID); - uint32_t OtherHalf = MachO->getAnyRelocationAddress(RE2) & 0xffff; + uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff; unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift)); int64_t Addend = FullImmVal - (AddrA - AddrB); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 258b847..67d7027 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -31,10 +31,11 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = Obj.getAnyRelocationType(RelInfo); @@ -42,18 +43,18 @@ public: if (Obj.isRelocationScattered(RelInfo)) { if (RelType == MachO::GENERIC_RELOC_SECTDIFF || RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) - return processSECTDIFFRelocation(SectionID, RelI, ObjImg, + return processSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); else if (RelType == MachO::GENERIC_RELOC_VANILLA) - return processI386ScatteredVANILLA(SectionID, RelI, ObjImg, + return processI386ScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); llvm_unreachable("Unhandled scattered relocation."); } - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = memcpyAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); // Addends for external, PC-rel relocations on i386 point back to the zero // offset. Calculate the final offset from the relocation target instead. @@ -66,7 +67,7 @@ public: // Value.Addend += RelocAddr + 4; // } if (RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); RE.Addend = Value.Offset; @@ -110,34 +111,32 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__jump_table") - populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section, - SectionID); + populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); else if (Name == "__pointers") - populateIndirectSymbolPointersSection( - cast<MachOObjectFile>(*ObjImg.getObjectFile()), - Section, SectionID); + populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), + Section, SectionID); } private: relocation_iterator processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, + const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast<const MachOObjectFile *>(Obj.getObjectFile()); + const MachOObjectFile &Obj = + static_cast<const MachOObjectFile&>(BaseObjT); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); - unsigned Size = MachO->getAnyRelocationLength(RE); + uint32_t RelocType = Obj.getAnyRelocationType(RE); + bool IsPCRel = Obj.getAnyRelocationPCRel(RE); + unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; @@ -146,11 +145,11 @@ private: ++RelI; MachO::any_relocation_info RE2 = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); - uint32_t AddrA = MachO->getScatteredRelocationValue(RE); - section_iterator SAI = getSectionByAddress(*MachO, AddrA); - assert(SAI != MachO->section_end() && "Can't find section for address A"); + uint32_t AddrA = Obj.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(Obj, AddrA); + assert(SAI != Obj.section_end() && "Can't find section for address A"); uint64_t SectionABase = SAI->getAddress(); uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; @@ -158,9 +157,9 @@ private: uint32_t SectionAID = findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); - uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); - section_iterator SBI = getSectionByAddress(*MachO, AddrB); - assert(SBI != MachO->section_end() && "Can't find section for address B"); + uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(Obj, AddrB); + assert(SBI != Obj.section_end() && "Can't find section for address B"); uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; @@ -186,26 +185,27 @@ private: } relocation_iterator processI386ScatteredVANILLA( - unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseObjT, RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast<const MachOObjectFile *>(Obj.getObjectFile()); + const MachOObjectFile &Obj = + static_cast<const MachOObjectFile&>(BaseObjT); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); - unsigned Size = MachO->getAnyRelocationLength(RE); + uint32_t RelocType = Obj.getAnyRelocationType(RE); + bool IsPCRel = Obj.getAnyRelocationPCRel(RE); + unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; unsigned NumBytes = 1 << Size; int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); - unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE); - section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr); - assert(TargetSI != MachO->section_end() && "Can't find section for symbol"); + unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE); + section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr); + assert(TargetSI != Obj.section_end() && "Can't find section for symbol"); uint64_t SectionBaseAddr = TargetSI->getAddress(); SectionRef TargetSection = *TargetSI; bool IsCode = TargetSection.isText(); @@ -221,7 +221,7 @@ private: } // Populate stubs in __jump_table section. - void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection, + void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection, unsigned JTSectionID) { assert(!Obj.is64Bit() && "__jump_table section not supported in 64-bit MachO."); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 84d9e80..0734017 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -31,24 +31,25 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + static_cast<const MachOObjectFile &>(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); assert(!Obj.isRelocationScattered(RelInfo) && "Scattered relocations not supported on X86_64"); - RelocationEntry RE(getRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); RE.Addend = memcpyAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI, 1 << RE.Size); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); if (RE.RelType == MachO::X86_64_RELOC_GOT || RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) @@ -97,7 +98,7 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) {} private: diff --git a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/lib/ExecutionEngine/SectionMemoryManager.cpp index 5986084..5986084 100644 --- a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp +++ b/lib/ExecutionEngine/SectionMemoryManager.cpp |