diff options
author | dim <dim@FreeBSD.org> | 2015-05-27 20:26:41 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-05-27 20:26:41 +0000 |
commit | 5ef8fd3549d38e883a31881636be3dc2a275de20 (patch) | |
tree | bd13a22d9db57ccf3eddbc07b32c18109521d050 /contrib/llvm/lib/ExecutionEngine | |
parent | 77794ebe2d5718eb502c93ec32f8ccae4d8a0b7b (diff) | |
parent | 782067d0278612ee75d024b9b135c221c327e9e8 (diff) | |
download | FreeBSD-src-5ef8fd3549d38e883a31881636be3dc2a275de20.zip FreeBSD-src-5ef8fd3549d38e883a31881636be3dc2a275de20.tar.gz |
Merge llvm trunk r238337 from ^/vendor/llvm/dist, resolve conflicts, and
preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine')
34 files changed, 2112 insertions, 791 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/EventListenerCommon.h b/contrib/llvm/lib/ExecutionEngine/EventListenerCommon.h deleted file mode 100644 index 6f17427..0000000 --- a/contrib/llvm/lib/ExecutionEngine/EventListenerCommon.h +++ /dev/null @@ -1,68 +0,0 @@ -//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Common functionality for JITEventListener implementations
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef EVENT_LISTENER_COMMON_H
-#define EVENT_LISTENER_COMMON_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/IR/DebugInfo.h"
-#include "llvm/IR/Metadata.h"
-#include "llvm/IR/ValueHandle.h"
-#include "llvm/Support/Path.h"
-
-namespace llvm {
-
-namespace jitprofiling {
-
-class FilenameCache {
- // Holds the filename of each Scope, so that we can pass a null-terminated
- // 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);
- Filename = DIScope.getFilename();
- }
- return Filename.c_str();
- }
-
- const char *getFullPath(MDNode *Scope) {
- assert(Scope->isResolved() && "Expected Scope to be resolved");
- std::string &P = Paths[Scope];
- if (P.empty()) {
- DIScope DIScope(Scope);
- StringRef DirName = DIScope.getDirectory();
- StringRef FileName = DIScope.getFilename();
- SmallString<256> FullPath;
- if (DirName != "." && DirName != "") {
- FullPath = DirName;
- }
- if (FileName != "") {
- sys::path::append(FullPath, FileName);
- }
- P = FullPath.str();
- }
- return P.c_str();
- }
-};
-
-} // namespace jitprofiling
-
-} // namespace llvm
-
-#endif //EVENT_LISTENER_COMMON_H
diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index 32d20ea..d7038fd 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -13,13 +13,16 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/ValueHandle.h" @@ -44,16 +47,22 @@ STATISTIC(NumGlobals , "Number of global vars initialized"); ExecutionEngine *(*ExecutionEngine::MCJITCtor)( std::unique_ptr<Module> M, std::string *ErrorStr, - std::unique_ptr<RTDyldMemoryManager> MCJMM, + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, std::unique_ptr<TargetMachine> TM) = nullptr; + +ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)( + std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + 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) { + : LazyFunctionCreator(nullptr) { CompilingLazily = false; GVCompilationDisabled = false; SymbolSearchingDisabled = false; @@ -137,45 +146,60 @@ 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; } -void *ExecutionEngineState::RemoveMapping(const GlobalValue *ToUnmap) { - GlobalAddressMapTy::iterator I = GlobalAddressMap.find(ToUnmap); - void *OldVal; +uint64_t ExecutionEngineState::RemoveMapping(StringRef Name) { + GlobalAddressMapTy::iterator I = GlobalAddressMap.find(Name); + uint64_t OldVal; // FIXME: This is silly, we shouldn't end up with a mapping -> 0 in the // GlobalAddressMap. if (I == GlobalAddressMap.end()) - OldVal = nullptr; + OldVal = 0; else { + GlobalAddressReverseMap.erase(I->second); OldVal = I->second; GlobalAddressMap.erase(I); } - GlobalAddressReverseMap.erase(OldVal); return OldVal; } +std::string ExecutionEngine::getMangledName(const GlobalValue *GV) { + MutexGuard locked(lock); + Mangler Mang(DL); + SmallString<128> FullName; + Mang.getNameWithPrefix(FullName, GV->getName()); + return FullName.str(); +} + void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) { MutexGuard locked(lock); + addGlobalMapping(getMangledName(GV), (uint64_t) Addr); +} + +void ExecutionEngine::addGlobalMapping(StringRef Name, uint64_t Addr) { + MutexGuard locked(lock); + + assert(!Name.empty() && "Empty GlobalMapping symbol name!"); - DEBUG(dbgs() << "JIT: Map \'" << GV->getName() - << "\' to [" << Addr << "]\n";); - void *&CurVal = EEState.getGlobalAddressMap()[GV]; + DEBUG(dbgs() << "JIT: Map \'" << Name << "\' to [" << Addr << "]\n";); + uint64_t &CurVal = EEState.getGlobalAddressMap()[Name]; assert((!CurVal || !Addr) && "GlobalMapping already established!"); CurVal = Addr; // If we are using the reverse mapping, add it too. if (!EEState.getGlobalAddressReverseMap().empty()) { - AssertingVH<const GlobalValue> &V = - EEState.getGlobalAddressReverseMap()[Addr]; - assert((!V || !GV) && "GlobalMapping already established!"); - V = GV; + std::string &V = EEState.getGlobalAddressReverseMap()[CurVal]; + assert((!V.empty() || !Name.empty()) && + "GlobalMapping already established!"); + V = Name; } } @@ -190,13 +214,19 @@ void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) { MutexGuard locked(lock); for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) - EEState.RemoveMapping(FI); + EEState.RemoveMapping(getMangledName(FI)); for (Module::global_iterator GI = M->global_begin(), GE = M->global_end(); GI != GE; ++GI) - EEState.RemoveMapping(GI); + EEState.RemoveMapping(getMangledName(GI)); } -void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) { +uint64_t ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, + void *Addr) { + MutexGuard locked(lock); + return updateGlobalMapping(getMangledName(GV), (uint64_t) Addr); +} + +uint64_t ExecutionEngine::updateGlobalMapping(StringRef Name, uint64_t Addr) { MutexGuard locked(lock); ExecutionEngineState::GlobalAddressMapTy &Map = @@ -204,10 +234,10 @@ void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) { // Deleting from the mapping? if (!Addr) - return EEState.RemoveMapping(GV); + return EEState.RemoveMapping(Name); - void *&CurVal = Map[GV]; - void *OldVal = CurVal; + uint64_t &CurVal = Map[Name]; + uint64_t OldVal = CurVal; if (CurVal && !EEState.getGlobalAddressReverseMap().empty()) EEState.getGlobalAddressReverseMap().erase(CurVal); @@ -215,20 +245,35 @@ void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) { // If we are using the reverse mapping, add it too. if (!EEState.getGlobalAddressReverseMap().empty()) { - AssertingVH<const GlobalValue> &V = - EEState.getGlobalAddressReverseMap()[Addr]; - assert((!V || !GV) && "GlobalMapping already established!"); - V = GV; + std::string &V = EEState.getGlobalAddressReverseMap()[CurVal]; + assert((!V.empty() || !Name.empty()) && + "GlobalMapping already established!"); + V = Name; } return OldVal; } -void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) { +uint64_t ExecutionEngine::getAddressToGlobalIfAvailable(StringRef S) { MutexGuard locked(lock); - + uint64_t Address = 0; ExecutionEngineState::GlobalAddressMapTy::iterator I = - EEState.getGlobalAddressMap().find(GV); - return I != EEState.getGlobalAddressMap().end() ? I->second : nullptr; + EEState.getGlobalAddressMap().find(S); + if (I != EEState.getGlobalAddressMap().end()) + Address = I->second; + return Address; +} + + +void *ExecutionEngine::getPointerToGlobalIfAvailable(StringRef S) { + MutexGuard locked(lock); + if (void* Address = (void *) getAddressToGlobalIfAvailable(S)) + return Address; + return nullptr; +} + +void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) { + MutexGuard locked(lock); + return getPointerToGlobalIfAvailable(getMangledName(GV)); } const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) { @@ -237,15 +282,25 @@ const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) { // If we haven't computed the reverse mapping yet, do so first. if (EEState.getGlobalAddressReverseMap().empty()) { for (ExecutionEngineState::GlobalAddressMapTy::iterator - I = EEState.getGlobalAddressMap().begin(), - E = EEState.getGlobalAddressMap().end(); I != E; ++I) + I = EEState.getGlobalAddressMap().begin(), + E = EEState.getGlobalAddressMap().end(); I != E; ++I) { + StringRef Name = I->first(); + uint64_t Addr = I->second; EEState.getGlobalAddressReverseMap().insert(std::make_pair( - I->second, I->first)); + Addr, Name)); + } } - std::map<void *, AssertingVH<const GlobalValue> >::iterator I = - EEState.getGlobalAddressReverseMap().find(Addr); - return I != EEState.getGlobalAddressReverseMap().end() ? I->second : nullptr; + std::map<uint64_t, std::string>::iterator I = + EEState.getGlobalAddressReverseMap().find((uint64_t) Addr); + + if (I != EEState.getGlobalAddressReverseMap().end()) { + StringRef Name = I->second; + for (unsigned i = 0, e = Modules.size(); i != e; ++i) + if (GlobalValue *GV = Modules[i]->getNamedValue(Name)) + return GV; + } + return nullptr; } namespace { @@ -393,35 +448,42 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn, return runFunction(Fn, GVArgs).IntVal.getZExtValue(); } +EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {} + EngineBuilder::EngineBuilder(std::unique_ptr<Module> M) - : M(std::move(M)), MCJMM(nullptr) { - InitEngine(); + : M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr), + OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr), + 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. +#ifndef NDEBUG + VerifyModules = true; +#else + VerifyModules = false; +#endif } -EngineBuilder::~EngineBuilder() {} +EngineBuilder::~EngineBuilder() = default; EngineBuilder &EngineBuilder::setMCJITMemoryManager( std::unique_ptr<RTDyldMemoryManager> mcjmm) { - MCJMM = std::move(mcjmm); + auto SharedMM = std::shared_ptr<RTDyldMemoryManager>(std::move(mcjmm)); + MemMgr = SharedMM; + Resolver = SharedMM; return *this; } -void EngineBuilder::InitEngine() { - WhichEngine = EngineKind::Either; - ErrorStr = nullptr; - OptLevel = CodeGenOpt::Default; - MCJMM = nullptr; - Options = TargetOptions(); - RelocModel = Reloc::Default; - CMModel = CodeModel::JITDefault; +EngineBuilder& +EngineBuilder::setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM) { + MemMgr = std::shared_ptr<MCJITMemoryManager>(std::move(MM)); + return *this; +} -// IR module verification is enabled by default in debug builds, and disabled -// by default in release builds. -#ifndef NDEBUG - VerifyModules = true; -#else - VerifyModules = false; -#endif +EngineBuilder& +EngineBuilder::setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR) { + Resolver = std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(SR)); + return *this; } ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { @@ -435,7 +497,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { // If the user specified a memory manager but didn't specify which engine to // create, we assume they only want the JIT, and we fail if they only want // the interpreter. - if (MCJMM) { + if (MemMgr) { if (WhichEngine & EngineKind::JIT) WhichEngine = EngineKind::JIT; else { @@ -456,9 +518,15 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { } ExecutionEngine *EE = nullptr; - if (ExecutionEngine::MCJITCtor) - EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MCJMM), - std::move(TheTM)); + if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) { + EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MemMgr), + std::move(Resolver), + std::move(TheTM)); + EE->addModule(std::move(M)); + } else if (ExecutionEngine::MCJITCtor) + EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr), + std::move(Resolver), std::move(TheTM)); + if (EE) { EE->setVerifyModules(VerifyModules); return EE; @@ -488,7 +556,7 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) { return getPointerToFunction(F); MutexGuard locked(lock); - if (void *P = EEState.getGlobalAddressMap()[GV]) + if (void* P = getPointerToGlobalIfAvailable(GV)) return P; // Global variable might have been added since interpreter started. @@ -498,7 +566,7 @@ void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) { else llvm_unreachable("Global hasn't had an address allocated yet!"); - return EEState.getGlobalAddressMap()[GV]; + return getPointerToGlobalIfAvailable(GV); } /// \brief Converts a Constant* into a GenericValue, including handling of @@ -1270,25 +1338,3 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { NumInitBytes += (unsigned)GVSize; ++NumGlobals; } - -ExecutionEngineState::ExecutionEngineState(ExecutionEngine &EE) - : EE(EE), GlobalAddressMap(this) { -} - -sys::Mutex * -ExecutionEngineState::AddressMapConfig::getMutex(ExecutionEngineState *EES) { - return &EES->EE.lock; -} - -void ExecutionEngineState::AddressMapConfig::onDelete(ExecutionEngineState *EES, - const GlobalValue *Old) { - void *OldVal = EES->GlobalAddressMap.lookup(Old); - EES->GlobalAddressReverseMap.erase(OldVal); -} - -void ExecutionEngineState::AddressMapConfig::onRAUW(ExecutionEngineState *, - const GlobalValue *, - const GlobalValue *) { - llvm_unreachable("The ExecutionEngine doesn't know how to handle a" - " RAUW on a value it has a global mapping for."); -} diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp index aaa53f0..ce1ab59 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -177,11 +177,22 @@ LLVMBool LLVMCreateMCJITCompilerForModule( memcpy(&options, PassedOptions, SizeOfPassedOptions); TargetOptions targetOptions; - targetOptions.NoFramePointerElim = options.NoFramePointerElim; targetOptions.EnableFastISel = options.EnableFastISel; + std::unique_ptr<Module> Mod(unwrap(M)); + + if (Mod) + // Set function attribute "no-frame-pointer-elim" based on + // NoFramePointerElim. + for (auto &F : *Mod) { + auto Attrs = F.getAttributes(); + auto Value = options.NoFramePointerElim ? "true" : "false"; + Attrs = Attrs.addAttribute(F.getContext(), AttributeSet::FunctionIndex, + "no-frame-pointer-elim", Value); + F.setAttributes(Attrs); + } std::string Error; - EngineBuilder builder(std::unique_ptr<Module>(unwrap(M))); + EngineBuilder builder(std::move(Mod)); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&Error) .setOptLevel((CodeGenOpt::Level)options.OptLevel) @@ -351,7 +362,7 @@ class SimpleBindingMemoryManager : public RTDyldMemoryManager { public: SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions, void *Opaque); - virtual ~SimpleBindingMemoryManager(); + ~SimpleBindingMemoryManager() override; uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, diff --git a/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp b/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp index 8ef878c..1ab6203 100644 --- a/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp @@ -103,7 +103,7 @@ public: /// Unregisters each object that was previously registered and releases all /// internal resources. - virtual ~GDBJITRegistrationListener(); + ~GDBJITRegistrationListener() override; /// Creates an entry in the JIT registry for the buffer @p Object, /// which must contain an object file in executable memory with any diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index ee9096b..ec67019 100644 --- a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -13,11 +13,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Config/config.h" -#include "EventListenerCommon.h" #include "IntelJITEventsWrapper.h" #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" @@ -29,7 +29,6 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -using namespace llvm::jitprofiling; using namespace llvm::object; #define DEBUG_TYPE "amplifier-jit-event-listener" @@ -41,7 +40,6 @@ class IntelJITEventListener : public JITEventListener { std::unique_ptr<IntelJITEventsWrapper> Wrapper; MethodIDMap MethodIDs; - FilenameCache Filenames; typedef SmallVector<const void *, 64> MethodAddressVector; typedef DenseMap<const void *, MethodAddressVector> ObjectMap; @@ -105,7 +103,7 @@ void IntelJITEventListener::NotifyObjectEmitted( // Get the address of the object image for use as a unique identifier const void* ObjData = DebugObj.getData().data(); - DIContext* Context = DIContext::getDWARFContext(DebugObj); + DIContext* Context = new DWARFContextInMemory(DebugObj); MethodAddressVector Functions; // Use symbol info to iterate functions in the object. diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c index 7b507de..e966889 100644 --- a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/jitprofiling.c +++ b/contrib/llvm/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/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp index 93bb2d1..a26740b 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cmath> using namespace llvm; @@ -315,7 +316,7 @@ void Interpreter::visitICmpInst(ICmpInst &I) { #define IMPLEMENT_VECTOR_FCMP(OP) \ case Type::VectorTyID: \ - if(dyn_cast<VectorType>(Ty)->getElementType()->isFloatTy()) { \ + if (cast<VectorType>(Ty)->getElementType()->isFloatTy()) { \ IMPLEMENT_VECTOR_FCMP_T(OP, Float); \ } else { \ IMPLEMENT_VECTOR_FCMP_T(OP, Double); \ @@ -362,7 +363,7 @@ static GenericValue executeFCMP_OEQ(GenericValue Src1, GenericValue Src2, #define MASK_VECTOR_NANS(TY, X,Y, FLAG) \ if (TY->isVectorTy()) { \ - if (dyn_cast<VectorType>(TY)->getElementType()->isFloatTy()) { \ + if (cast<VectorType>(TY)->getElementType()->isFloatTy()) { \ MASK_VECTOR_NANS_T(X, Y, Float, FLAG) \ } else { \ MASK_VECTOR_NANS_T(X, Y, Double, FLAG) \ @@ -464,14 +465,14 @@ static GenericValue executeFCMP_OGT(GenericValue Src1, GenericValue Src2, return Dest; \ } -#define IMPLEMENT_VECTOR_UNORDERED(TY, X,Y, _FUNC) \ - if (TY->isVectorTy()) { \ - GenericValue DestMask = Dest; \ - Dest = _FUNC(Src1, Src2, Ty); \ - for( size_t _i=0; _i<Src1.AggregateVal.size(); _i++) \ - if (DestMask.AggregateVal[_i].IntVal == true) \ - Dest.AggregateVal[_i].IntVal = APInt(1,true); \ - return Dest; \ +#define IMPLEMENT_VECTOR_UNORDERED(TY, X, Y, FUNC) \ + if (TY->isVectorTy()) { \ + GenericValue DestMask = Dest; \ + Dest = FUNC(Src1, Src2, Ty); \ + for (size_t _i = 0; _i < Src1.AggregateVal.size(); _i++) \ + if (DestMask.AggregateVal[_i].IntVal == true) \ + Dest.AggregateVal[_i].IntVal = APInt(1, true); \ + return Dest; \ } static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2, @@ -535,7 +536,7 @@ static GenericValue executeFCMP_ORD(GenericValue Src1, GenericValue Src2, if(Ty->isVectorTy()) { assert(Src1.AggregateVal.size() == Src2.AggregateVal.size()); Dest.AggregateVal.resize( Src1.AggregateVal.size() ); - if(dyn_cast<VectorType>(Ty)->getElementType()->isFloatTy()) { + if (cast<VectorType>(Ty)->getElementType()->isFloatTy()) { for( size_t _i=0;_i<Src1.AggregateVal.size();_i++) Dest.AggregateVal[_i].IntVal = APInt(1, ( (Src1.AggregateVal[_i].FloatVal == @@ -566,7 +567,7 @@ static GenericValue executeFCMP_UNO(GenericValue Src1, GenericValue Src2, if(Ty->isVectorTy()) { assert(Src1.AggregateVal.size() == Src2.AggregateVal.size()); Dest.AggregateVal.resize( Src1.AggregateVal.size() ); - if(dyn_cast<VectorType>(Ty)->getElementType()->isFloatTy()) { + if (cast<VectorType>(Ty)->getElementType()->isFloatTy()) { for( size_t _i=0;_i<Src1.AggregateVal.size();_i++) Dest.AggregateVal[_i].IntVal = APInt(1, ( (Src1.AggregateVal[_i].FloatVal != @@ -712,10 +713,10 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) { // Macros to choose appropriate TY: float or double and run operation // execution #define FLOAT_VECTOR_OP(OP) { \ - if (dyn_cast<VectorType>(Ty)->getElementType()->isFloatTy()) \ + if (cast<VectorType>(Ty)->getElementType()->isFloatTy()) \ FLOAT_VECTOR_FUNCTION(OP, FloatVal) \ else { \ - if (dyn_cast<VectorType>(Ty)->getElementType()->isDoubleTy()) \ + if (cast<VectorType>(Ty)->getElementType()->isDoubleTy()) \ FLOAT_VECTOR_FUNCTION(OP, DoubleVal) \ else { \ dbgs() << "Unhandled type for OP instruction: " << *Ty << "\n"; \ @@ -744,12 +745,12 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) { case Instruction::FMul: FLOAT_VECTOR_OP(*) break; case Instruction::FDiv: FLOAT_VECTOR_OP(/) break; case Instruction::FRem: - if (dyn_cast<VectorType>(Ty)->getElementType()->isFloatTy()) + if (cast<VectorType>(Ty)->getElementType()->isFloatTy()) for (unsigned i = 0; i < R.AggregateVal.size(); ++i) R.AggregateVal[i].FloatVal = fmod(Src1.AggregateVal[i].FloatVal, Src2.AggregateVal[i].FloatVal); else { - if (dyn_cast<VectorType>(Ty)->getElementType()->isDoubleTy()) + if (cast<VectorType>(Ty)->getElementType()->isDoubleTy()) for (unsigned i = 0; i < R.AggregateVal.size(); ++i) R.AggregateVal[i].DoubleVal = fmod(Src1.AggregateVal[i].DoubleVal, Src2.AggregateVal[i].DoubleVal); diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index b022101..e2fe065 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -95,16 +95,15 @@ static ExFunc lookupFunction(const Function *F) { FunctionType *FT = F->getFunctionType(); for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i) ExtName += getTypeID(FT->getContainedType(i)); - ExtName += "_" + F->getName().str(); + ExtName += ("_" + F->getName()).str(); sys::ScopedLock Writer(*FunctionsLock); ExFunc FnPtr = (*FuncNames)[ExtName]; if (!FnPtr) - FnPtr = (*FuncNames)["lle_X_" + F->getName().str()]; + FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()]; if (!FnPtr) // Try calling a generic function... if it exists... - FnPtr = (ExFunc)(intptr_t) - sys::DynamicLibrary::SearchForAddressOfSymbol("lle_X_" + - F->getName().str()); + FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol( + ("lle_X_" + F->getName()).str()); if (FnPtr) ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later return FnPtr; diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index 2be9c59..0dc0463 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -108,7 +108,7 @@ class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> { public: explicit Interpreter(std::unique_ptr<Module> M); - ~Interpreter(); + ~Interpreter() override; /// runAtExitHandlers - Run any functions registered by the program's calls to /// atexit(3), which we intercept and store in AtExitHandlers. diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index f2d53f5..7e37afe 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "MCJIT.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/MCJIT.h" @@ -15,18 +16,16 @@ #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/Object/ObjectFile.h" -#include "llvm/PassManager.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; @@ -43,26 +42,35 @@ static struct RegisterJIT { extern "C" void LLVMLinkInMCJIT() { } -ExecutionEngine *MCJIT::createJIT(std::unique_ptr<Module> M, - std::string *ErrorStr, - std::unique_ptr<RTDyldMemoryManager> MemMgr, - std::unique_ptr<TargetMachine> TM) { +ExecutionEngine* +MCJIT::createJIT(std::unique_ptr<Module> M, + std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + 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); - std::unique_ptr<RTDyldMemoryManager> MM = std::move(MemMgr); - if (!MM) - MM = std::unique_ptr<SectionMemoryManager>(new SectionMemoryManager()); + if (!MemMgr || !Resolver) { + auto RTDyldMM = std::make_shared<SectionMemoryManager>(); + if (!MemMgr) + MemMgr = RTDyldMM; + if (!Resolver) + Resolver = RTDyldMM; + } - return new MCJIT(std::move(M), std::move(TM), std::move(MM)); + return new MCJIT(std::move(M), std::move(TM), std::move(MemMgr), + std::move(Resolver)); } MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, - std::unique_ptr<RTDyldMemoryManager> MM) + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver) : ExecutionEngine(std::move(M)), TM(std::move(tm)), Ctx(nullptr), - MemMgr(this, std::move(MM)), Dyld(&MemMgr), ObjCache(nullptr) { + MemMgr(std::move(MemMgr)), Resolver(*this, std::move(Resolver)), + Dyld(*this->MemMgr, this->Resolver), 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 @@ -77,7 +85,7 @@ 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()); } @@ -137,10 +145,9 @@ std::unique_ptr<MemoryBuffer> MCJIT::emitObject(Module *M) { // MCJIT instance, since these conditions are tested by our caller, // generateCodeForModule. - PassManager PM; + legacy::PassManager PM; - M->setDataLayout(TM->getSubtargetImpl()->getDataLayout()); - PM.add(new DataLayoutPass()); + M->setDataLayout(*TM->getDataLayout()); // The RuntimeDyld will take ownership of this shortly SmallVector<char, 4096> ObjBufferSV; @@ -224,7 +231,7 @@ void MCJIT::finalizeLoadedModules() { Dyld.registerEHFrames(); // Set page permissions. - MemMgr.finalizeMemory(); + MemMgr->finalizeMemory(); } // FIXME: Rename this. @@ -256,11 +263,11 @@ void MCJIT::finalizeModule(Module *M) { finalizeLoadedModules(); } -uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) { - Mangler Mang(TM->getSubtargetImpl()->getDataLayout()); +RuntimeDyld::SymbolInfo MCJIT::findExistingSymbol(const std::string &Name) { + Mangler Mang(TM->getDataLayout()); SmallString<128> FullName; Mang.getNameWithPrefix(FullName, Name); - return Dyld.getSymbolLoadAddress(FullName); + return Dyld.getSymbol(FullName); } Module *MCJIT::findModuleForSymbol(const std::string &Name, @@ -287,14 +294,17 @@ Module *MCJIT::findModuleForSymbol(const std::string &Name, } uint64_t MCJIT::getSymbolAddress(const std::string &Name, - bool CheckFunctionsOnly) -{ + bool CheckFunctionsOnly) { + return findSymbol(Name, CheckFunctionsOnly).getAddress(); +} + +RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, + bool CheckFunctionsOnly) { MutexGuard locked(lock); // First, check to see if we already have this symbol. - uint64_t Addr = getExistingSymbolAddress(Name); - if (Addr) - return Addr; + if (auto Sym = findExistingSymbol(Name)) + return Sym; for (object::OwningBinary<object::Archive> &OB : Archives) { object::Archive *A = OB.getBinary(); @@ -313,9 +323,8 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name, // This causes the object file to be loaded. addObjectFile(std::move(OF)); // The address should be here now. - Addr = getExistingSymbolAddress(Name); - if (Addr) - return Addr; + if (auto Sym = findExistingSymbol(Name)) + return Sym; } } } @@ -326,15 +335,18 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name, generateCodeForModule(M); // Check the RuntimeDyld table again, it should be there now. - return getExistingSymbolAddress(Name); + return findExistingSymbol(Name); } // If a LazyFunctionCreator is installed, use it to get/create the function. // FIXME: Should we instead have a LazySymbolCreator callback? - if (LazyFunctionCreator) - Addr = (uint64_t)LazyFunctionCreator(Name); + if (LazyFunctionCreator) { + auto Addr = static_cast<uint64_t>( + reinterpret_cast<uintptr_t>(LazyFunctionCreator(Name))); + return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported); + } - return Addr; + return nullptr; } uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) { @@ -357,7 +369,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); @@ -386,7 +398,7 @@ void *MCJIT::getPointerToFunction(Function *F) { // // This is the accessor for the target address, so make sure to check the // load address of the symbol, not the local address. - return (void*)Dyld.getSymbolLoadAddress(Name); + return (void*)Dyld.getSymbol(Name).getAddress(); } void MCJIT::runStaticConstructorsDestructorsInModulePtrSet( @@ -410,7 +422,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; @@ -530,7 +543,9 @@ GenericValue MCJIT::runFunction(Function *F, void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) { if (!isSymbolSearchingDisabled()) { - void *ptr = MemMgr.getPointerToNamedFunction(Name, false); + void *ptr = + reinterpret_cast<void*>( + static_cast<uintptr_t>(Resolver.findSymbol(Name).getAddress())); if (ptr) return ptr; } @@ -568,7 +583,7 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) { 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, L); } @@ -580,15 +595,16 @@ void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { L->NotifyFreeingObject(Obj); } -uint64_t LinkingMemoryManager::getSymbolAddress(const std::string &Name) { - uint64_t Result = ParentEngine->getSymbolAddress(Name, false); +RuntimeDyld::SymbolInfo +LinkingSymbolResolver::findSymbol(const std::string &Name) { + auto Result = ParentEngine.findSymbol(Name, false); // If the symbols wasn't found and it begins with an underscore, try again // without the underscore. if (!Result && Name[0] == '_') - Result = ParentEngine->getSymbolAddress(Name.substr(1), false); + Result = ParentEngine.findSymbol(Name.substr(1), false); if (Result) return Result; - if (ParentEngine->isSymbolSearchingDisabled()) - return 0; - return ClientMM->getSymbolAddress(Name); + if (ParentEngine.isSymbolSearchingDisabled()) + return nullptr; + return ClientResolver->findSymbol(Name); } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h index f55dd60..59e9949 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -10,12 +10,13 @@ #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H #define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H -#include "ObjectBuffer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Module.h" @@ -26,59 +27,23 @@ class MCJIT; // functions across modules that it owns. It aggregates the memory manager // that is passed in to the MCJIT constructor and defers most functionality // to that object. -class LinkingMemoryManager : public RTDyldMemoryManager { +class LinkingSymbolResolver : public RuntimeDyld::SymbolResolver { public: - LinkingMemoryManager(MCJIT *Parent, - std::unique_ptr<RTDyldMemoryManager> MM) - : ParentEngine(Parent), ClientMM(std::move(MM)) {} + LinkingSymbolResolver(MCJIT &Parent, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver) + : ParentEngine(Parent), ClientResolver(std::move(Resolver)) {} - uint64_t getSymbolAddress(const std::string &Name) override; + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override; - // Functions deferred to client memory manager - uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - StringRef SectionName) override { - return ClientMM->allocateCodeSection(Size, Alignment, SectionID, SectionName); - } - - uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName, - bool IsReadOnly) override { - return ClientMM->allocateDataSection(Size, Alignment, - SectionID, SectionName, IsReadOnly); - } - - void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, - uintptr_t DataSizeRW) override { - return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); - } - - bool needsToReserveAllocationSpace() override { - return ClientMM->needsToReserveAllocationSpace(); - } - - void notifyObjectLoaded(ExecutionEngine *EE, - const object::ObjectFile &Obj) override { - ClientMM->notifyObjectLoaded(EE, Obj); - } - - void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, - size_t Size) override { - ClientMM->registerEHFrames(Addr, LoadAddr, Size); - } - - void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, - size_t Size) override { - ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); - } - - bool finalizeMemory(std::string *ErrMsg = nullptr) override { - return ClientMM->finalizeMemory(ErrMsg); + // MCJIT doesn't support logical dylibs. + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) override { + return nullptr; } private: - MCJIT *ParentEngine; - std::unique_ptr<RTDyldMemoryManager> ClientMM; + MCJIT &ParentEngine; + std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver; }; // About Module states: added->loaded->finalized. @@ -103,7 +68,8 @@ private: class MCJIT : public ExecutionEngine { MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, - std::unique_ptr<RTDyldMemoryManager> MemMgr); + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver); typedef llvm::SmallPtrSet<Module *, 4> ModulePtrSet; @@ -214,7 +180,8 @@ class MCJIT : public ExecutionEngine { std::unique_ptr<TargetMachine> TM; MCContext *Ctx; - LinkingMemoryManager MemMgr; + std::shared_ptr<MCJITMemoryManager> MemMgr; + LinkingSymbolResolver Resolver; RuntimeDyld Dyld; std::vector<JITEventListener*> EventListeners; @@ -238,7 +205,7 @@ class MCJIT : public ExecutionEngine { ModulePtrSet::iterator E); public: - ~MCJIT(); + ~MCJIT() override; /// @name ExecutionEngine interface implementation /// @{ @@ -324,17 +291,22 @@ public: MCJITCtor = createJIT; } - static ExecutionEngine *createJIT(std::unique_ptr<Module> M, - std::string *ErrorStr, - std::unique_ptr<RTDyldMemoryManager> MemMgr, - std::unique_ptr<TargetMachine> TM); + static ExecutionEngine* + createJIT(std::unique_ptr<Module> M, + std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + std::unique_ptr<TargetMachine> TM); // @} + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name, + bool CheckFunctionsOnly); + // DEPRECATED - Please use findSymbol instead. // This is not directly exposed via the ExecutionEngine API, but it is // used by the LinkingMemoryManager. uint64_t getSymbolAddress(const std::string &Name, - bool CheckFunctionsOnly); + bool CheckFunctionsOnly); protected: /// emitObject -- Generate a JITed object in memory from the specified module @@ -348,7 +320,7 @@ protected: const RuntimeDyld::LoadedObjectInfo &L); void NotifyFreeingObject(const object::ObjectFile& Obj); - uint64_t getExistingSymbolAddress(const std::string &Name); + RuntimeDyld::SymbolInfo findExistingSymbol(const std::string &Name); Module *findModuleForSymbol(const std::string &Name, bool CheckFunctionsOnly); }; diff --git a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp index 9ab4003..23e7662 100644 --- a/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp +++ b/contrib/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Config/config.h" -#include "EventListenerCommon.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/OProfileWrapper.h" @@ -28,7 +27,6 @@ #include <fcntl.h> using namespace llvm; -using namespace llvm::jitprofiling; using namespace llvm::object; #define DEBUG_TYPE "oprofile-jit-event-listener" diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp new file mode 100644 index 0000000..b7220db --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -0,0 +1,102 @@ +//===---- ExecutionUtils.cpp - Utilities for executing functions 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/ExecutionEngine/Orc/ExecutionUtils.h" + +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Module.h" + +namespace llvm { +namespace orc { + +CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) + : InitList( + GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), + I((InitList && End) ? InitList->getNumOperands() : 0) { +} + +bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { + assert(InitList == Other.InitList && "Incomparable iterators."); + return I == Other.I; +} + +bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { + return !(*this == Other); +} + +CtorDtorIterator& CtorDtorIterator::operator++() { + ++I; + return *this; +} + +CtorDtorIterator CtorDtorIterator::operator++(int) { + CtorDtorIterator Temp = *this; + ++I; + return Temp; +} + +CtorDtorIterator::Element CtorDtorIterator::operator*() const { + ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); + assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); + + Constant *FuncC = CS->getOperand(1); + Function *Func = nullptr; + + // Extract function pointer, pulling off any casts. + while (FuncC) { + if (Function *F = dyn_cast_or_null<Function>(FuncC)) { + Func = F; + break; + } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { + if (CE->isCast()) + FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0)); + else + break; + } else { + // This isn't anything we recognize. Bail out with Func left set to null. + break; + } + } + + ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); + Value *Data = CS->getOperand(2); + return Element(Priority->getZExtValue(), Func, Data); +} + +iterator_range<CtorDtorIterator> getConstructors(const Module &M) { + const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); + return make_range(CtorDtorIterator(CtorsList, false), + CtorDtorIterator(CtorsList, true)); +} + +iterator_range<CtorDtorIterator> getDestructors(const Module &M) { + const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); + return make_range(CtorDtorIterator(DtorsList, false), + CtorDtorIterator(DtorsList, true)); +} + +void LocalCXXRuntimeOverrides::runDestructors() { + auto& CXXDestructorDataPairs = DSOHandleOverride; + for (auto &P : CXXDestructorDataPairs) + P.first(P.second); + CXXDestructorDataPairs.clear(); +} + +int LocalCXXRuntimeOverrides::CXAAtExitOverride(DestructorPtr Destructor, + void *Arg, void *DSOHandle) { + auto& CXXDestructorDataPairs = + *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); + CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); + return 0; +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp new file mode 100644 index 0000000..4ed8730 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -0,0 +1,183 @@ +//===---- 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/STLExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include <set> +#include <sstream> + +namespace llvm { +namespace orc { + +Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr) { + Constant *AddrIntVal = + ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr); + Constant *AddrPtrVal = + ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal, + PointerType::get(&FT, 0)); + return AddrPtrVal; +} + +GlobalVariable* createImplPointer(PointerType &PT, Module &M, + const Twine &Name, Constant *Initializer) { + if (!Initializer) + Initializer = Constant::getNullValue(&PT); + auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage, + Initializer, Name, nullptr, + GlobalValue::NotThreadLocal, 0, true); + IP->setVisibility(GlobalValue::HiddenVisibility); + return IP; +} + +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(); + Call->setAttributes(F.getAttributes()); + if (F.getReturnType()->isVoidTy()) + Builder.CreateRetVoid(); + else + Builder.CreateRet(Call); +} + +// Utility class for renaming global values and functions during partitioning. +class GlobalRenamer { +public: + + static bool needsRenaming(const Value &New) { + if (!New.hasName() || New.getName().startswith("\01L")) + return true; + return false; + } + + const std::string& getRename(const Value &Orig) { + // See if we have a name for this global. + { + auto I = Names.find(&Orig); + if (I != Names.end()) + return I->second; + } + + // Nope. Create a new one. + // FIXME: Use a more robust uniquing scheme. (This may blow up if the user + // writes a "__orc_anon[[:digit:]]* method). + unsigned ID = Names.size(); + std::ostringstream NameStream; + NameStream << "__orc_anon" << ID++; + auto I = Names.insert(std::make_pair(&Orig, NameStream.str())); + return I.first->second; + } +private: + DenseMap<const Value*, std::string> Names; +}; + +static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) { + if (V.hasLocalLinkage()) { + if (R.needsRenaming(V)) + V.setName(R.getRename(V)); + V.setLinkage(GlobalValue::ExternalLinkage); + V.setVisibility(GlobalValue::HiddenVisibility); + } + V.setUnnamedAddr(false); + assert(!R.needsRenaming(V) && "Invalid global name."); +} + +void makeAllSymbolsExternallyAccessible(Module &M) { + GlobalRenamer Renamer; + + for (auto &F : M) + raiseVisibilityOnValue(F, Renamer); + + for (auto &GV : M.globals()) + raiseVisibilityOnValue(GV, Renamer); +} + +Function* cloneFunctionDecl(Module &Dst, const Function &F, + ValueToValueMapTy *VMap) { + assert(F.getParent() != &Dst && "Can't copy decl over existing function."); + Function *NewF = + Function::Create(cast<FunctionType>(F.getType()->getElementType()), + F.getLinkage(), F.getName(), &Dst); + NewF->copyAttributesFrom(&F); + + if (VMap) { + (*VMap)[&F] = NewF; + auto NewArgI = NewF->arg_begin(); + for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE; + ++ArgI, ++NewArgI) + (*VMap)[ArgI] = NewArgI; + } + + return NewF; +} + +void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap, + ValueMaterializer *Materializer, + Function *NewF) { + assert(!OrigF.isDeclaration() && "Nothing to move"); + if (!NewF) + NewF = cast<Function>(VMap[&OrigF]); + else + assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap."); + assert(NewF && "Function mapping missing from VMap."); + assert(NewF->getParent() != OrigF.getParent() && + "moveFunctionBody should only be used to move bodies between " + "modules."); + + SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned. + CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns, + "", nullptr, nullptr, Materializer); + OrigF.deleteBody(); +} + +GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, + ValueToValueMapTy *VMap) { + assert(GV.getParent() != &Dst && "Can't copy decl over existing global var."); + GlobalVariable *NewGV = new GlobalVariable( + Dst, GV.getType()->getElementType(), GV.isConstant(), + GV.getLinkage(), nullptr, GV.getName(), nullptr, + GV.getThreadLocalMode(), GV.getType()->getAddressSpace()); + NewGV->copyAttributesFrom(&GV); + if (VMap) + (*VMap)[&GV] = NewGV; + return NewGV; +} + +void moveGlobalVariableInitializer(GlobalVariable &OrigGV, + ValueToValueMapTy &VMap, + ValueMaterializer *Materializer, + GlobalVariable *NewGV) { + assert(OrigGV.hasInitializer() && "Nothing to move"); + if (!NewGV) + NewGV = cast<GlobalVariable>(VMap[&OrigGV]); + else + assert(VMap[&OrigGV] == NewGV && + "Incorrect global variable mapping in VMap."); + assert(NewGV->getParent() != OrigGV.getParent() && + "moveGlobalVariable should only be used to move initializers between " + "modules"); + + NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None, + nullptr, Materializer)); +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp new file mode 100644 index 0000000..48fd31e --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h new file mode 100644 index 0000000..4023344 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -0,0 +1,356 @@ +//===---- 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 { + + // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that + // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are + // expecting - see finalizeMemory. + class MCJITReplacementMemMgr : public MCJITMemoryManager { + public: + MCJITReplacementMemMgr(OrcMCJITReplacement &M, + std::shared_ptr<MCJITMemoryManager> ClientMM) + : M(M), ClientMM(std::move(ClientMM)) {} + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override { + uint8_t *Addr = + ClientMM->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 = ClientMM->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 ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, + DataSizeRW); + } + + bool needsToReserveAllocationSpace() override { + return ClientMM->needsToReserveAllocationSpace(); + } + + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override { + return ClientMM->registerEHFrames(Addr, LoadAddr, Size); + } + + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override { + return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); + } + + void notifyObjectLoaded(ExecutionEngine *EE, + const object::ObjectFile &O) override { + return ClientMM->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 ClientMM->finalizeMemory(ErrMsg); + return false; + } + + private: + OrcMCJITReplacement &M; + std::shared_ptr<MCJITMemoryManager> ClientMM; + }; + + class LinkingResolver : public RuntimeDyld::SymbolResolver { + public: + LinkingResolver(OrcMCJITReplacement &M) : M(M) {} + + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { + return M.findMangledSymbol(Name); + } + + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) override { + return M.ClientResolver->findSymbolInLogicalDylib(Name); + } + + private: + OrcMCJITReplacement &M; + }; + +private: + + static ExecutionEngine * + createOrcMCJITReplacement(std::string *ErrorMsg, + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver, + std::unique_ptr<TargetMachine> TM) { + return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver), + std::move(TM)); + } + +public: + static void Register() { + OrcMCJITReplacementCtor = createOrcMCJITReplacement; + } + + OrcMCJITReplacement( + std::shared_ptr<MCJITMemoryManager> MemMgr, + std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver, + std::unique_ptr<TargetMachine> TM) + : TM(std::move(TM)), MemMgr(*this, std::move(MemMgr)), + Resolver(*this), ClientResolver(std::move(ClientResolver)), + Mang(this->TM->getDataLayout()), + NotifyObjectLoaded(*this), NotifyFinalized(*this), + ObjectLayer(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().isDefault()) + M->setDataLayout(*getDataLayout()); + + Modules.push_back(std::move(M)); + std::vector<Module *> Ms; + Ms.push_back(&*Modules.back()); + LazyEmitLayer.addModuleSet(std::move(Ms), &MemMgr, &Resolver); + } + + 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), &MemMgr, &Resolver); + } + + 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), &MemMgr, &Resolver); + + 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 findSymbol(Name).getAddress(); + } + + RuntimeDyld::SymbolInfo findSymbol(StringRef Name) { + return findMangledSymbol(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: + + RuntimeDyld::SymbolInfo findMangledSymbol(StringRef Name) { + if (auto Sym = LazyEmitLayer.findSymbol(Name, false)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + if (auto Sym = ClientResolver->findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + if (auto Sym = scanArchives(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + + return nullptr; + } + + JITSymbol 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), &MemMgr, &Resolver); + if (auto Sym = ObjectLayer.findSymbol(Name, true)) + return Sym; + } + } + } + return nullptr; + } + + 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.MemMgr.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; + MCJITReplacementMemMgr MemMgr; + LinkingResolver Resolver; + std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver; + 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/contrib/llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp b/contrib/llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp new file mode 100644 index 0000000..258868a --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp @@ -0,0 +1,138 @@ +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h" +#include <array> + +using namespace llvm::orc; + +namespace { + +uint64_t executeCompileCallback(JITCompileCallbackManagerBase *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 &JCBM) { + + // Trampoline code-sequence length, used to get trampoline address from return + // address. + const unsigned X86_64_TrampolineLength = 6; + + // List of x86-64 GPRs to save. Note - RBP saved separately below. + std::array<const char *, 14> GPRs = {{ + "rax", "rbx", "rcx", "rdx", + "rsi", "rdi", "r8", "r9", + "r10", "r11", "r12", "r13", + "r14", "r15" + }}; + + // Address of the executeCompileCallback function. + uint64_t CallbackAddr = + static_cast<uint64_t>( + reinterpret_cast<uintptr_t>(executeCompileCallback)); + + std::ostringstream AsmStream; + Triple TT(M.getTargetTriple()); + + // Switch to text section. + 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"; + + // Bake in a pointer to the callback manager immediately before the + // start of the resolver function. + AsmStream << "jit_callback_manager_addr:\n" + << " .quad " << &JCBM << "\n"; + + // Start the resolver function. + AsmStream << ResolverBlockName << ":\n" + << " pushq %rbp\n" + << " movq %rsp, %rbp\n"; + + // Store the GPRs. + for (const auto &GPR : GPRs) + AsmStream << " pushq %" << GPR << "\n"; + + // Store floating-point state with FXSAVE. + // Note: We need to keep the stack 16-byte aligned, so if we've emitted an odd + // number of 64-bit pushes so far (GPRs.size() plus 1 for RBP) then add + // an extra 64 bits of padding to the FXSave area. + unsigned Padding = (GPRs.size() + 1) % 2 ? 8 : 0; + unsigned FXSaveSize = 512 + Padding; + AsmStream << " subq $" << FXSaveSize << ", %rsp\n" + << " fxsave64 (%rsp)\n" + + // Load callback manager address, compute trampoline address, call JIT. + << " lea jit_callback_manager_addr(%rip), %rdi\n" + << " movq (%rdi), %rdi\n" + << " movq 0x8(%rbp), %rsi\n" + << " subq $" << X86_64_TrampolineLength << ", %rsi\n" + << " movabsq $" << CallbackAddr << ", %rax\n" + << " callq *%rax\n" + + // Replace the return to the trampoline with the return address of the + // compiled function body. + << " movq %rax, 0x8(%rbp)\n" + + // Restore the floating point state. + << " fxrstor64 (%rsp)\n" + << " addq $" << FXSaveSize << ", %rsp\n"; + + for (const auto &GPR : make_range(GPRs.rbegin(), GPRs.rend())) + AsmStream << " popq %" << GPR << "\n"; + + // Restore original RBP and return to compiled function body. + AsmStream << " popq %rbp\n" + << " 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/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 304014e..24a3ec1 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -13,10 +13,12 @@ #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "RuntimeDyldCheckerImpl.h" +#include "RuntimeDyldCOFF.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldMachO.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MutexGuard.h" @@ -55,7 +57,8 @@ static void dumpSectionMemory(const SectionEntry &S, StringRef State) { unsigned BytesRemaining = S.Size; if (StartPadding) { - dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr & ~(ColsPerRow - 1)) << ":"; + dbgs() << "\n" << format("0x%016" PRIx64, + LoadAddr & ~(uint64_t)(ColsPerRow - 1)) << ":"; while (StartPadding--) dbgs() << " "; } @@ -90,7 +93,7 @@ void RuntimeDyldImpl::resolveRelocations() { // entry provides the section to which the relocation will be applied. uint64_t Addr = Sections[i].LoadAddress; DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t" - << format("0x%x", Addr) << "\n"); + << format("%p", (uintptr_t)Addr) << "\n"); DEBUG(dumpSectionMemory(Sections[i], "before relocations")); resolveRelocationList(Relocations[i], Addr); DEBUG(dumpSectionMemory(Sections[i], "after relocations")); @@ -149,68 +152,65 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager - if (MemMgr->needsToReserveAllocationSpace()) { + if (MemMgr.needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW); - MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + MemMgr.reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments - CommonSymbolMap CommonSymbols; - // Maximum required total memory to allocate all common symbols - uint64_t CommonSize = 0; + CommonSymbolList CommonSymbols; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - object::SymbolRef::Type SymType; - StringRef Name; - Check(I->getType(SymType)); - Check(I->getName(Name)); - uint32_t Flags = I->getFlags(); bool IsCommon = Flags & SymbolRef::SF_Common; - if (IsCommon) { - // Add the common symbols to a list. We'll allocate them all below. - if (!GlobalSymbolTable.count(Name)) { - uint32_t Align; - Check(I->getAlignment(Align)); - uint64_t Size = 0; - Check(I->getSize(Size)); - CommonSize += Size + Align; - CommonSymbols[*I] = CommonSymbolInfo(Size, Align); - } - } else { + if (IsCommon) + CommonSymbols.push_back(*I); + else { + object::SymbolRef::Type SymType; + Check(I->getType(SymType)); + if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { + + StringRef Name; uint64_t SectOffset; - StringRef SectionData; - section_iterator SI = Obj.section_end(); + Check(I->getName(Name)); Check(getOffset(*I, SectOffset)); + section_iterator SI = Obj.section_end(); Check(I->getSection(SI)); if (SI == Obj.section_end()) continue; + StringRef SectionData; Check(SI->getContents(SectionData)); bool IsCode = SI->isText(); unsigned SectionID = findOrEmitSection(Obj, *SI, IsCode, LocalSections); - DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << " SID: " << SectionID); - GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name + << " SID: " << SectionID << " Offset: " + << format("%p", (uintptr_t)SectOffset) + << " flags: " << Flags << "\n"); + JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; + if (Flags & SymbolRef::SF_Weak) + RTDyldSymFlags |= JITSymbolFlags::Weak; + if (Flags & SymbolRef::SF_Exported) + RTDyldSymFlags |= JITSymbolFlags::Exported; + GlobalSymbolTable[Name] = + SymbolTableEntry(SectionID, SectOffset, RTDyldSymFlags); } } - DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols - if (CommonSize != 0) - emitCommonSymbols(Obj, CommonSymbols, CommonSize, GlobalSymbolTable); + emitCommonSymbols(Obj, CommonSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); @@ -220,6 +220,9 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { StubMap Stubs; section_iterator RelocatedSection = SI->getRelocatedSection(); + if (RelocatedSection == SE) + continue; + relocation_iterator I = SI->relocation_begin(); relocation_iterator E = SI->relocation_end(); @@ -267,6 +270,20 @@ static bool isRequiredForExecution(const SectionRef &Section) { const ObjectFile *Obj = Section.getObject(); if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) return ELFObj->getSectionFlags(Section) & ELF::SHF_ALLOC; + if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) { + const coff_section *CoffSection = COFFObj->getCOFFSection(Section); + // Avoid loading zero-sized COFF sections. + // In PE files, VirtualSize gives the section size, and SizeOfRawData + // may be zero for sections with content. In Obj files, SizeOfRawData + // gives the section size, and VirtualSize is always zero. Hence + // the need to check for both cases below. + bool HasContent = (CoffSection->VirtualSize > 0) + || (CoffSection->SizeOfRawData > 0); + bool IsDiscardable = CoffSection->Characteristics & + (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO); + return HasContent && !IsDiscardable; + } + assert(isa<MachOObjectFile>(Obj)); return true; } @@ -276,6 +293,15 @@ static bool isReadOnlyData(const SectionRef &Section) { if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) return !(ELFObj->getSectionFlags(Section) & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) + return ((COFFObj->getCOFFSection(Section)->Characteristics & + (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ + | COFF::IMAGE_SCN_MEM_WRITE)) + == + (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ)); + assert(isa<MachOObjectFile>(Obj)); return false; } @@ -284,6 +310,9 @@ static bool isZeroInit(const SectionRef &Section) { const ObjectFile *Obj = Section.getObject(); if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj)) return ELFObj->getSectionType(Section) == ELF::SHT_NOBITS; + if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) + return COFFObj->getCOFFSection(Section)->Characteristics & + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; auto *MachO = cast<MachOObjectFile>(Obj); unsigned SectionType = MachO->getSectionType(Section); @@ -332,19 +361,20 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, if (Name == ".eh_frame") SectionSize += 4; - if (SectionSize > 0) { - // save the total size of the section - if (IsCode) { - CodeSectionSizes.push_back(SectionSize); - } else if (IsReadOnly) { - ROSectionSizes.push_back(SectionSize); - } else { - RWSectionSizes.push_back(SectionSize); - } - // update the max alignment - if (Alignment > MaxAlignment) { - MaxAlignment = Alignment; - } + if (!SectionSize) + SectionSize = 1; + + if (IsCode) { + CodeSectionSizes.push_back(SectionSize); + } else if (IsReadOnly) { + ROSectionSizes.push_back(SectionSize); + } else { + RWSectionSizes.push_back(SectionSize); + } + + // update the max alignment + if (Alignment > MaxAlignment) { + MaxAlignment = Alignment; } } } @@ -442,38 +472,73 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, - SymbolTableMap &SymbolTable) { + CommonSymbolList &CommonSymbols) { + if (CommonSymbols.empty()) + return; + + uint64_t CommonSize = 0; + CommonSymbolList SymbolsToAllocate; + + DEBUG(dbgs() << "Processing common symbols...\n"); + + for (const auto &Sym : CommonSymbols) { + StringRef Name; + Check(Sym.getName(Name)); + + // Skip common symbols already elsewhere. + if (GlobalSymbolTable.count(Name) || + Resolver.findSymbolInLogicalDylib(Name)) { + DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name + << "'\n"); + continue; + } + + uint32_t Align = 0; + uint64_t Size = 0; + Check(Sym.getAlignment(Align)); + Check(Sym.getSize(Size)); + + CommonSize += Align + Size; + SymbolsToAllocate.push_back(Sym); + } + // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void *), - SectionID, StringRef(), false); + uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, sizeof(void *), + SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; - Sections.push_back(SectionEntry("<common symbols>", Addr, TotalSize, 0)); - memset(Addr, 0, TotalSize); + Sections.push_back(SectionEntry("<common symbols>", Addr, CommonSize, 0)); + memset(Addr, 0, CommonSize); DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: " - << format("%p", Addr) << " DataSize: " << TotalSize << "\n"); + << format("%p", Addr) << " DataSize: " << CommonSize << "\n"); // Assign the address of each symbol - for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(), - itEnd = CommonSymbols.end(); it != itEnd; ++it) { - uint64_t Size = it->second.first; - uint64_t Align = it->second.second; + for (auto &Sym : SymbolsToAllocate) { + uint32_t Align; + uint64_t Size; StringRef Name; - it->first.getName(Name); + Check(Sym.getAlignment(Align)); + Check(Sym.getSize(Size)); + Check(Sym.getName(Name)); if (Align) { // This symbol has an alignment requirement. uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align); Addr += AlignOffset; Offset += AlignOffset; - DEBUG(dbgs() << "Allocating common symbol " << Name << " address " - << format("%p\n", Addr)); } - SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); + uint32_t Flags = Sym.getFlags(); + JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None; + if (Flags & SymbolRef::SF_Weak) + RTDyldSymFlags |= JITSymbolFlags::Weak; + if (Flags & SymbolRef::SF_Exported) + RTDyldSymFlags |= JITSymbolFlags::Exported; + DEBUG(dbgs() << "Allocating common symbol " << Name << " address " + << format("%p", Addr) << "\n"); + GlobalSymbolTable[Name] = + SymbolTableEntry(SectionID, Offset, RTDyldSymFlags); Offset += Size; Addr += Size; } @@ -483,7 +548,6 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode) { StringRef data; - Check(Section.getContents(data)); uint64_t Alignment64 = Section.getAlignment(); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; @@ -510,21 +574,26 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, uint8_t *Addr; const char *pData = nullptr; + // In either case, set the location of the unrelocated section in memory, + // since we still process relocations for it even if we're not applying them. + Check(Section.getContents(data)); + // Virtual sections have no data in the object image, so leave pData = 0 + if (!IsVirtual) + pData = data.data(); + // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { Allocate = DataSize + PaddingSize + StubBufSize; - Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, - Name) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, - Name, IsReadOnly); + if (!Allocate) + Allocate = 1; + Addr = IsCode ? MemMgr.allocateCodeSection(Allocate, Alignment, SectionID, + Name) + : MemMgr.allocateDataSection(Allocate, Alignment, SectionID, + Name, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); - // Virtual sections have no data in the object image, so leave pData = 0 - if (!IsVirtual) - pData = data.data(); - // Zero-initialize or copy the data from the image if (IsZeroInit || IsVirtual) memset(Addr, 0, DataSize); @@ -589,14 +658,15 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, // Relocation by symbol. If the symbol is found in the global symbol table, // create an appropriate section relocation. Otherwise, add it to // ExternalSymbolRelocations. - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(SymbolName); + RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(SymbolName); if (Loc == GlobalSymbolTable.end()) { ExternalSymbolRelocations[SymbolName].push_back(RE); } else { // Copy the RE since we want to modify its addend. RelocationEntry RECopy = RE; - RECopy.Addend += Loc->second.second; - Relocations[Loc->second.first].push_back(RECopy); + const auto &SymInfo = Loc->second; + RECopy.Addend += SymInfo.getOffset(); + Relocations[SymInfo.getSectionID()].push_back(RECopy); } } @@ -721,11 +791,11 @@ void RuntimeDyldImpl::resolveExternalSymbols() { resolveRelocationList(Relocs, 0); } else { uint64_t Addr = 0; - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { - // This is an external symbol, try to get its address from - // MemoryManager. - Addr = MemMgr->getSymbolAddress(Name.data()); + // This is an external symbol, try to get its address from the symbol + // resolver. + Addr = Resolver.findSymbol(Name.data()).getAddress(); // The call to getSymbolAddress may have caused additional modules to // be loaded, which may have added new entries to the // ExternalSymbolRelocations map. Consquently, we need to update our @@ -736,8 +806,9 @@ void RuntimeDyldImpl::resolveExternalSymbols() { } else { // We found the symbol in our global table. It was probably in a // Module that we loaded previously. - SymbolLoc SymLoc = Loc->second; - Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second; + const auto &SymInfo = Loc->second; + Addr = getSectionLoadAddress(SymInfo.getSectionID()) + + SymInfo.getOffset(); } // FIXME: Implement error handling that doesn't kill the host program! @@ -745,7 +816,6 @@ void RuntimeDyldImpl::resolveExternalSymbols() { report_fatal_error("Program used external function '" + Name + "' which could not be resolved!"); - updateGOTEntries(Name, Addr); DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t" << format("0x%lx", Addr) << "\n"); // This list may have been updated when we called getSymbolAddress, so @@ -770,7 +840,12 @@ uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( return 0; } -RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { +void RuntimeDyld::MemoryManager::anchor() {} +void RuntimeDyld::SymbolResolver::anchor() {} + +RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : MemMgr(MemMgr), Resolver(Resolver) { // FIXME: There's a potential issue lurking here if a single instance of // RuntimeDyld is used to load multiple objects. The current implementation // associates a single memory manager with a RuntimeDyld instance. Even @@ -778,26 +853,40 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { // they share a single memory manager. This can become a problem when page // permissions are applied. Dyld = nullptr; - MM = mm; ProcessAllSections = false; Checker = nullptr; } RuntimeDyld::~RuntimeDyld() {} +static std::unique_ptr<RuntimeDyldCOFF> +createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldCOFF> Dyld = + RuntimeDyldCOFF::create(Arch, MM, Resolver); + Dyld->setProcessAllSections(ProcessAllSections); + Dyld->setRuntimeDyldChecker(Checker); + return Dyld; +} + static std::unique_ptr<RuntimeDyldELF> -createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections, - RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM)); +createRuntimeDyldELF(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM, Resolver)); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; } static std::unique_ptr<RuntimeDyldMachO> -createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM, - bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr<RuntimeDyldMachO> Dyld(RuntimeDyldMachO::create(Arch, MM)); +createRuntimeDyldMachO(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, + RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr<RuntimeDyldMachO> Dyld = + RuntimeDyldMachO::create(Arch, MM, Resolver); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; @@ -807,10 +896,14 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> RuntimeDyld::loadObject(const ObjectFile &Obj) { if (!Dyld) { if (Obj.isELF()) - Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); + Dyld = createRuntimeDyldELF(MemMgr, Resolver, ProcessAllSections, Checker); else if (Obj.isMachO()) Dyld = createRuntimeDyldMachO( - static_cast<Triple::ArchType>(Obj.getArch()), MM, + static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver, + ProcessAllSections, Checker); + else if (Obj.isCOFF()) + Dyld = createRuntimeDyldCOFF( + static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver, ProcessAllSections, Checker); else report_fatal_error("Incompatible object format!"); @@ -822,16 +915,16 @@ RuntimeDyld::loadObject(const ObjectFile &Obj) { return Dyld->loadObject(Obj); } -void *RuntimeDyld::getSymbolAddress(StringRef Name) const { +void *RuntimeDyld::getSymbolLocalAddress(StringRef Name) const { if (!Dyld) return nullptr; - return Dyld->getSymbolAddress(Name); + return Dyld->getSymbolLocalAddress(Name); } -uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) const { +RuntimeDyld::SymbolInfo RuntimeDyld::getSymbol(StringRef Name) const { if (!Dyld) - return 0; - return Dyld->getSymbolLoadAddress(Name); + return nullptr; + return Dyld->getSymbol(Name); } void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp new file mode 100644 index 0000000..c8d3d22 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -0,0 +1,88 @@ +//===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of COFF support for the MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#include "RuntimeDyldCOFF.h" +#include "Targets/RuntimeDyldCOFFX86_64.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ObjectFile.h" + +using namespace llvm; +using namespace llvm::object; + +#define DEBUG_TYPE "dyld" + +namespace { + +class LoadedCOFFObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper<LoadedCOFFObjectInfo> { +public: + LoadedCOFFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary<ObjectFile> + getObjectForDebug(const ObjectFile &Obj) const override { + return OwningBinary<ObjectFile>(); + } +}; +} + +namespace llvm { + +std::unique_ptr<RuntimeDyldCOFF> +llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { + switch (Arch) { + default: + llvm_unreachable("Unsupported target for RuntimeDyldCOFF."); + break; + case Triple::x86_64: + return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver); + } +} + +std::unique_ptr<RuntimeDyld::LoadedObjectInfo> +RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique<LoadedCOFFObjectInfo>(*this, SectionStartIdx, + SectionEndIdx); +} + +uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) { + uint64_t Address; + if (Sym.getAddress(Address)) + return UnknownAddressOrSize; + + if (Address == UnknownAddressOrSize) + return UnknownAddressOrSize; + + const ObjectFile *Obj = Sym.getObject(); + section_iterator SecI(Obj->section_end()); + if (Sym.getSection(SecI)) + return UnknownAddressOrSize; + + if (SecI == Obj->section_end()) + return UnknownAddressOrSize; + + uint64_t SectionAddress = SecI->getAddress(); + return Address - SectionAddress; +} + +bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isCOFF(); +} + +} // namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h new file mode 100644 index 0000000..32b8fa2 --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -0,0 +1,50 @@ +//===-- RuntimeDyldCOFF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// COFF support for MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_RUNTIME_DYLD_COFF_H +#define LLVM_RUNTIME_DYLD_COFF_H + +#include "RuntimeDyldImpl.h" +#include "llvm/ADT/DenseMap.h" + +#define DEBUG_TYPE "dyld" + +using namespace llvm; + +namespace llvm { + +// Common base class for COFF dynamic linker support. +// Concrete subclasses for each target can be found in ./Targets. +class RuntimeDyldCOFF : public RuntimeDyldImpl { + +public: + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> + loadObject(const object::ObjectFile &Obj) override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; + + static std::unique_ptr<RuntimeDyldCOFF> + create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); + +protected: + RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} + uint64_t getSymbolOffset(const SymbolRef &Sym); +}; + +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index f3e5c77..957571b 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -260,9 +260,7 @@ private: << "'. Instruction has only " << format("%i", Inst.getNumOperands()) << " operands.\nInstruction is:\n "; - Inst.dump_pretty(ErrMsgStream, - Checker.Disassembler->getContext().getAsmInfo(), - Checker.InstPrinter); + Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter); return std::make_pair(EvalResult(ErrMsgStream.str()), ""); } @@ -272,9 +270,7 @@ private: raw_string_ostream ErrMsgStream(ErrMsg); ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '" << Symbol << "' is not an immediate.\nInstruction is:\n "; - Inst.dump_pretty(ErrMsgStream, - Checker.Disassembler->getContext().getAsmInfo(), - Checker.InstPrinter); + Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter); return std::make_pair(EvalResult(ErrMsgStream.str()), ""); } @@ -314,7 +310,7 @@ private: ""); uint64_t SymbolAddr = PCtx.IsInsideLoad - ? Checker.getSymbolLinkerAddr(Symbol) + ? Checker.getSymbolLocalAddr(Symbol) : Checker.getSymbolRemoteAddr(Symbol); uint64_t NextPC = SymbolAddr + InstSize; @@ -441,7 +437,7 @@ private: // The value for the symbol depends on the context we're evaluating in: // Inside a load this is the address in the linker's memory, outside a // load it's the address in the target processes memory. - uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLinkerAddr(Symbol) + uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLocalAddr(Symbol) : Checker.getSymbolRemoteAddr(Symbol); // Looks like a plain symbol reference. @@ -731,18 +727,18 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, } bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const { - return getRTDyld().getSymbolAddress(Symbol) != nullptr; + return getRTDyld().getSymbolLocalAddress(Symbol) != nullptr; } -uint64_t RuntimeDyldCheckerImpl::getSymbolLinkerAddr(StringRef Symbol) const { +uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const { return static_cast<uint64_t>( - reinterpret_cast<uintptr_t>(getRTDyld().getSymbolAddress(Symbol))); + reinterpret_cast<uintptr_t>(getRTDyld().getSymbolLocalAddress(Symbol))); } uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { - if (uint64_t InternalSymbolAddr = getRTDyld().getSymbolLoadAddress(Symbol)) - return InternalSymbolAddr; - return getRTDyld().MemMgr->getSymbolAddress(Symbol); + if (auto InternalSymbol = getRTDyld().getSymbol(Symbol)) + return InternalSymbol.getAddress(); + return getRTDyld().Resolver.findSymbol(Symbol).getAddress(); } uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, @@ -850,14 +846,16 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor( StringRef RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const { - RuntimeDyldImpl::SymbolTableMap::const_iterator pos = + RTDyldSymbolTable::const_iterator pos = getRTDyld().GlobalSymbolTable.find(Name); if (pos == getRTDyld().GlobalSymbolTable.end()) return StringRef(); - RuntimeDyldImpl::SymbolLoc Loc = pos->second; - uint8_t *SectionAddr = getRTDyld().getSectionAddress(Loc.first); - return StringRef(reinterpret_cast<const char *>(SectionAddr) + Loc.second, - getRTDyld().Sections[Loc.first].Size - Loc.second); + const auto &SymInfo = pos->second; + uint8_t *SectionAddr = getRTDyld().getSectionAddress(SymInfo.getSectionID()); + return StringRef(reinterpret_cast<const char *>(SectionAddr) + + SymInfo.getOffset(), + getRTDyld().Sections[SymInfo.getSectionID()].Size - + SymInfo.getOffset()); } void RuntimeDyldCheckerImpl::registerSection( @@ -887,9 +885,10 @@ void RuntimeDyldCheckerImpl::registerStubMap( // If this is a (Section, Offset) pair, do a reverse lookup in the // global symbol table to find the name. for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) { - if (GSTEntry.second.first == StubMapEntry.first.SectionID && - GSTEntry.second.second == - static_cast<uint64_t>(StubMapEntry.first.Offset)) { + const auto &SymInfo = GSTEntry.second; + if (SymInfo.getSectionID() == StubMapEntry.first.SectionID && + SymInfo.getOffset() == + static_cast<uint64_t>(StubMapEntry.first.Offset)) { SymbolName = GSTEntry.first(); break; } @@ -930,6 +929,6 @@ bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, std::pair<uint64_t, std::string> RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName, - bool LinkerAddress) { - return Impl->getSectionAddr(FileName, SectionName, LinkerAddress); + bool LocalAddress) { + return Impl->getSectionAddr(FileName, SectionName, LocalAddress); } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h index de20c1e..69d2a7d 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h @@ -19,6 +19,7 @@ class RuntimeDyldCheckerImpl { friend class RuntimeDyldChecker; friend class RuntimeDyldImpl; friend class RuntimeDyldCheckerExprEval; + friend class RuntimeDyldELF; public: RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler, @@ -42,7 +43,7 @@ private: RuntimeDyldImpl &getRTDyld() const { return *RTDyld.Dyld; } bool isSymbolValid(StringRef Symbol) const; - uint64_t getSymbolLinkerAddr(StringRef Symbol) const; + uint64_t getSymbolLocalAddr(StringRef Symbol) const; uint64_t getSymbolRemoteAddr(StringRef Symbol) const; uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 2664a10..95421b3 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldELF.h" +#include "RuntimeDyldCheckerImpl.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -103,11 +104,12 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef, sym->st_value = static_cast<addr_type>(Addr); } -class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo { +class LoadedELFObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper<LoadedELFObjectInfo> { public: LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, unsigned EndIdx) - : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} OwningBinary<ObjectFile> getObjectForDebug(const ObjectFile &Obj) const override; @@ -183,32 +185,30 @@ LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { namespace llvm { -RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} +RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0), CurrentGOTIndex(0) {} RuntimeDyldELF::~RuntimeDyldELF() {} void RuntimeDyldELF::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { SID EHFrameSID = UnregisteredEHFrameSections[i]; uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); RegisteredEHFrameSections.push_back(EHFrameSID); } UnregisteredEHFrameSections.clear(); } void RuntimeDyldELF::deregisterEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) { SID EHFrameSID = RegisteredEHFrameSections[i]; uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); } RegisteredEHFrameSections.clear(); } @@ -247,40 +247,18 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, << format("%p\n", Section.Address + Offset)); break; } - case ELF::R_X86_64_GOTPCREL: { - // findGOTEntry returns the 'G + GOT' part of the relocation calculation - // based on the load/target address of the GOT (not the current/local addr). - uint64_t GOTAddr = findGOTEntry(Value, SymOffset); - uint64_t FinalAddress = Section.LoadAddress + Offset; - // The processRelocationRef method combines the symbol offset and the addend - // and in most cases that's what we want. For this relocation type, we need - // the raw addend, so we subtract the symbol offset to get it. - int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress; - assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); - int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); - support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset; - break; - } case ELF::R_X86_64_PC32: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle32_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); uint64_t FinalAddress = Section.LoadAddress + Offset; - int64_t RealOffset = Placeholder + Value + Addend - FinalAddress; - assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); + int64_t RealOffset = Value + Addend - FinalAddress; + assert(isInt<32>(RealOffset)); int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset; break; } case ELF::R_X86_64_PC64: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle64_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); uint64_t FinalAddress = Section.LoadAddress + Offset; - support::ulittle64_t::ref(Section.Address + Offset) = - Placeholder + Value + Addend - FinalAddress; + int64_t RealOffset = Value + Addend - FinalAddress; + support::ulittle64_t::ref(Section.Address + Offset) = RealOffset; break; } } @@ -291,21 +269,12 @@ void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, uint32_t Type, int32_t Addend) { switch (Type) { case ELF::R_386_32: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle32_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); - support::ulittle32_t::ref(Section.Address + Offset) = - Placeholder + Value + Addend; + support::ulittle32_t::ref(Section.Address + Offset) = Value + Addend; break; } case ELF::R_386_PC32: { - // Get the placeholder value from the generated object since - // a previous relocation attempt may have overwritten the loaded version - support::ulittle32_t::ref Placeholder( - (void *)(Section.ObjAddress + Offset)); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); - uint32_t RealOffset = Placeholder + Value + Addend - FinalAddress; + uint32_t RealOffset = Value + Addend - FinalAddress; support::ulittle32_t::ref(Section.Address + Offset) = RealOffset; break; } @@ -354,8 +323,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, uint64_t BranchImm = Value + Addend - FinalAddress; // "Check that -2^27 <= result < 2^27". - assert(-(1LL << 27) <= static_cast<int64_t>(BranchImm) && - static_cast<int64_t>(BranchImm) < (1LL << 27)); + assert(isInt<28>(BranchImm)); // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. @@ -418,9 +386,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, ((Value + Addend) & ~0xfffULL) - (FinalAddress & ~0xfffULL); // Check that -2^32 <= X < 2^32 - assert(static_cast<int64_t>(Result) >= (-1LL << 32) && - static_cast<int64_t>(Result) < (1LL << 32) && - "overflow check failed for relocation"); + assert(isInt<33>(Result) && "overflow check failed for relocation"); // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. @@ -462,8 +428,6 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend) { // TODO: Add Thumb relocations. - uint32_t *Placeholder = - reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); Value += Addend; @@ -480,39 +444,27 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, case ELF::R_ARM_NONE: break; - // Write a 32bit value to relocation address, taking into account the - // implicit addend encoded in the target. case ELF::R_ARM_PREL31: case ELF::R_ARM_TARGET1: case ELF::R_ARM_ABS32: - *TargetPtr = *Placeholder + Value; + *TargetPtr = Value; break; - // Write first 16 bit of 32 bit value to the mov instruction. - // Last 4 bit should be shifted. + // Write first 16 bit of 32 bit value to the mov instruction. + // Last 4 bit should be shifted. case ELF::R_ARM_MOVW_ABS_NC: - // We are not expecting any other addend in the relocation address. - // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2 - // non-contiguous fields. - assert((*Placeholder & 0x000F0FFF) == 0); - Value = Value & 0xFFFF; - *TargetPtr = *Placeholder | (Value & 0xFFF); - *TargetPtr |= ((Value >> 12) & 0xF) << 16; - break; - // Write last 16 bit of 32 bit value to the mov instruction. - // Last 4 bit should be shifted. case ELF::R_ARM_MOVT_ABS: - // We are not expecting any other addend in the relocation address. - // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC. - assert((*Placeholder & 0x000F0FFF) == 0); - - Value = (Value >> 16) & 0xFFFF; - *TargetPtr = *Placeholder | (Value & 0xFFF); + if (Type == ELF::R_ARM_MOVW_ABS_NC) + Value = Value & 0xFFFF; + else if (Type == ELF::R_ARM_MOVT_ABS) + Value = (Value >> 16) & 0xFFFF; + *TargetPtr &= ~0x000F0FFF; + *TargetPtr |= Value & 0xFFF; *TargetPtr |= ((Value >> 12) & 0xF) << 16; break; - // Write 24 bit relative value to the branch instruction. + // Write 24 bit relative value to the branch instruction. case ELF::R_ARM_PC24: // Fall through. case ELF::R_ARM_CALL: // Fall through. - case ELF::R_ARM_JUMP24: { + case ELF::R_ARM_JUMP24: int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8); RelValue = (RelValue & 0x03FFFFFC) >> 2; assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE); @@ -520,21 +472,11 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section, *TargetPtr |= RelValue; break; } - case ELF::R_ARM_PRIVATE_0: - // This relocation is reserved by the ARM ELF ABI for internal use. We - // appropriate it here to act as an R_ARM_ABS32 without any addend for use - // in the stubs created during JIT (which can't put an addend into the - // original object file). - *TargetPtr = Value; - break; - } } void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend) { - uint32_t *Placeholder = - reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset); uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset); Value += Addend; @@ -549,30 +491,17 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, llvm_unreachable("Not implemented relocation type!"); break; case ELF::R_MIPS_32: - *TargetPtr = Value + (*Placeholder); + *TargetPtr = Value; break; case ELF::R_MIPS_26: - *TargetPtr = ((*Placeholder) & 0xfc000000) | ((Value & 0x0fffffff) >> 2); + *TargetPtr = ((*TargetPtr) & 0xfc000000) | ((Value & 0x0fffffff) >> 2); break; case ELF::R_MIPS_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. - Value += ((*Placeholder) & 0x0000ffff) << 16; *TargetPtr = - ((*Placeholder) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); + ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); break; case ELF::R_MIPS_LO16: - Value += ((*Placeholder) & 0x0000ffff); - *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff); - break; - case ELF::R_MIPS_UNUSED1: - // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2 - // are used for internal JIT purpose. These relocations are similar to - // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into - // account. - *TargetPtr = - ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); - break; - case ELF::R_MIPS_UNUSED2: *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); break; } @@ -898,6 +827,18 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, } } +void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const { + return (void*)(Sections[SectionID].ObjAddress + Offset); +} + +void RuntimeDyldELF::processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value) { + RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); +} + relocation_iterator RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &Obj, @@ -920,15 +861,16 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( SymbolRef::Type SymType = SymbolRef::ST_Unknown; // Search for the symbol in the global symbol table - SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); + RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end(); if (Symbol != Obj.symbol_end()) { gsi = GlobalSymbolTable.find(TargetName.data()); Symbol->getType(SymType); } if (gsi != GlobalSymbolTable.end()) { - Value.SectionID = gsi->second.first; - Value.Offset = gsi->second.second; - Value.Addend = gsi->second.second + Addend; + const auto &SymInfo = gsi->second; + Value.SectionID = SymInfo.getSectionID(); + Value.Offset = SymInfo.getOffset(); + Value.Addend = SymInfo.getOffset() + Addend; } else { switch (SymType) { case SymbolRef::ST_Debug: { @@ -1014,80 +956,103 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( 0); Section.StubOffset += getMaxStubSize(); } - } else if (Arch == Triple::arm && - (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL || - RelType == ELF::R_ARM_JUMP24)) { - // This is an ARM branch relocation, need to use a stub function. - DEBUG(dbgs() << "\t\tThis is an ARM branch relocation."); - SectionEntry &Section = Sections[SectionID]; + } else if (Arch == Triple::arm) { + if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL || + RelType == ELF::R_ARM_JUMP24) { + // This is an ARM branch relocation, need to use a stub function. + DEBUG(dbgs() << "\t\tThis is an ARM branch relocation."); + SectionEntry &Section = Sections[SectionID]; - // Look for an existing stub. - StubMap::const_iterator i = Stubs.find(Value); - if (i != Stubs.end()) { - resolveRelocation(Section, Offset, (uint64_t)Section.Address + i->second, - RelType, 0); - DEBUG(dbgs() << " Stub function found\n"); - } else { - // Create a new stub function. - DEBUG(dbgs() << " Create a new stub function\n"); - Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = + // Look for an existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + resolveRelocation(Section, Offset, (uint64_t)Section.Address + i->second, + RelType, 0); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); - RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, - ELF::R_ARM_PRIVATE_0, Value.Addend); - if (Value.SymbolName) - addRelocationForSymbol(RE, Value.SymbolName); - else - addRelocationForSection(RE, Value.SectionID); - - resolveRelocation(Section, Offset, - (uint64_t)Section.Address + Section.StubOffset, RelType, - 0); - Section.StubOffset += getMaxStubSize(); + RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, + ELF::R_ARM_ABS32, Value.Addend); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + + resolveRelocation(Section, Offset, + (uint64_t)Section.Address + Section.StubOffset, RelType, + 0); + Section.StubOffset += getMaxStubSize(); + } + } else { + uint32_t *Placeholder = + reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset)); + if (RelType == ELF::R_ARM_PREL31 || RelType == ELF::R_ARM_TARGET1 || + RelType == ELF::R_ARM_ABS32) { + Value.Addend += *Placeholder; + } else if (RelType == ELF::R_ARM_MOVW_ABS_NC || RelType == ELF::R_ARM_MOVT_ABS) { + // See ELF for ARM documentation + Value.Addend += (int16_t)((*Placeholder & 0xFFF) | (((*Placeholder >> 16) & 0xF) << 12)); + } + processSimpleRelocation(SectionID, Offset, RelType, Value); } - } else if ((Arch == Triple::mipsel || Arch == Triple::mips) && - RelType == ELF::R_MIPS_26) { - // This is an Mips branch relocation, need to use a stub function. - DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); - SectionEntry &Section = Sections[SectionID]; - uint8_t *Target = Section.Address + Offset; - uint32_t *TargetAddress = (uint32_t *)Target; + } else if ((Arch == Triple::mipsel || Arch == Triple::mips)) { + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset)); + if (RelType == ELF::R_MIPS_26) { + // This is an Mips branch relocation, need to use a stub function. + DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); + SectionEntry &Section = Sections[SectionID]; - // Extract the addend from the instruction. - uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2; + // Extract the addend from the instruction. + // We shift up by two since the Value will be down shifted again + // when applying the relocation. + uint32_t Addend = ((*Placeholder) & 0x03ffffff) << 2; - Value.Addend += Addend; + Value.Addend += Addend; - // Look up for existing stub. - StubMap::const_iterator i = Stubs.find(Value); - if (i != Stubs.end()) { - RelocationEntry RE(SectionID, Offset, RelType, i->second); - addRelocationForSection(RE, SectionID); - DEBUG(dbgs() << " Stub function found\n"); - } else { - // Create a new stub function. - DEBUG(dbgs() << " Create a new stub function\n"); - Stubs[Value] = Section.StubOffset; - uint8_t *StubTargetAddr = + // Look up for existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + RelocationEntry RE(SectionID, Offset, RelType, i->second); + addRelocationForSection(RE, SectionID); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); - // Creating Hi and Lo relocations for the filled stub instructions. - RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, - ELF::R_MIPS_UNUSED1, Value.Addend); - RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 4, - ELF::R_MIPS_UNUSED2, Value.Addend); + // Creating Hi and Lo relocations for the filled stub instructions. + RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 4, + ELF::R_MIPS_LO16, Value.Addend); - if (Value.SymbolName) { - addRelocationForSymbol(REHi, Value.SymbolName); - addRelocationForSymbol(RELo, Value.SymbolName); - } else { - addRelocationForSection(REHi, Value.SectionID); - addRelocationForSection(RELo, Value.SectionID); - } + if (Value.SymbolName) { + addRelocationForSymbol(REHi, Value.SymbolName); + addRelocationForSymbol(RELo, Value.SymbolName); + } + else { + addRelocationForSection(REHi, Value.SectionID); + addRelocationForSection(RELo, Value.SectionID); + } - RelocationEntry RE(SectionID, Offset, RelType, Section.StubOffset); - addRelocationForSection(RE, SectionID); - Section.StubOffset += getMaxStubSize(); + RelocationEntry RE(SectionID, Offset, RelType, Section.StubOffset); + addRelocationForSection(RE, SectionID); + Section.StubOffset += getMaxStubSize(); + } + } else { + if (RelType == ELF::R_MIPS_HI16) + Value.Addend += ((*Placeholder) & 0x0000ffff) << 16; + else if (RelType == ELF::R_MIPS_LO16) + Value.Addend += ((*Placeholder) & 0x0000ffff); + else if (RelType == ELF::R_MIPS_32) + Value.Addend += *Placeholder; + processSimpleRelocation(SectionID, Offset, RelType, Value); } } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { if (RelType == ELF::R_PPC64_REL24) { @@ -1127,7 +1092,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( RangeOverflow = true; } } - if (SymType == SymbolRef::ST_Unknown || RangeOverflow == true) { + if (SymType == SymbolRef::ST_Unknown || RangeOverflow) { // It is an external symbol (SymbolRef::ST_Unknown) or within a range // larger than 24-bits. StubMap::const_iterator i = Stubs.find(Value); @@ -1286,93 +1251,95 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( Addend); else resolveRelocation(Section, Offset, StubAddress, RelType, Addend); - } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_PLT32) { - // The way the PLT relocations normally work is that the linker allocates - // the - // PLT and this relocation makes a PC-relative call into the PLT. The PLT - // entry will then jump to an address provided by the GOT. On first call, - // the - // GOT address will point back into PLT code that resolves the symbol. After - // the first call, the GOT entry points to the actual function. - // - // For local functions we're ignoring all of that here and just replacing - // the PLT32 relocation type with PC32, which will translate the relocation - // into a PC-relative call directly to the function. For external symbols we - // can't be sure the function will be within 2^32 bytes of the call site, so - // we need to create a stub, which calls into the GOT. This case is - // equivalent to the usual PLT implementation except that we use the stub - // mechanism in RuntimeDyld (which puts stubs at the end of the section) - // rather than allocating a PLT section. - if (Value.SymbolName) { - // This is a call to an external function. - // Look for an existing stub. - SectionEntry &Section = Sections[SectionID]; - StubMap::const_iterator i = Stubs.find(Value); - uintptr_t StubAddress; - if (i != Stubs.end()) { + } else if (Arch == Triple::x86_64) { + if (RelType == ELF::R_X86_64_PLT32) { + // The way the PLT relocations normally work is that the linker allocates + // the + // PLT and this relocation makes a PC-relative call into the PLT. The PLT + // entry will then jump to an address provided by the GOT. On first call, + // the + // GOT address will point back into PLT code that resolves the symbol. After + // the first call, the GOT entry points to the actual function. + // + // For local functions we're ignoring all of that here and just replacing + // the PLT32 relocation type with PC32, which will translate the relocation + // into a PC-relative call directly to the function. For external symbols we + // can't be sure the function will be within 2^32 bytes of the call site, so + // we need to create a stub, which calls into the GOT. This case is + // equivalent to the usual PLT implementation except that we use the stub + // mechanism in RuntimeDyld (which puts stubs at the end of the section) + // rather than allocating a PLT section. + if (Value.SymbolName) { + // This is a call to an external function. + // Look for an existing stub. + SectionEntry &Section = Sections[SectionID]; + StubMap::const_iterator i = Stubs.find(Value); + uintptr_t StubAddress; + if (i != Stubs.end()) { StubAddress = uintptr_t(Section.Address) + i->second; DEBUG(dbgs() << " Stub function found\n"); - } else { + } else { // Create a new stub function (equivalent to a PLT entry). DEBUG(dbgs() << " Create a new stub function\n"); uintptr_t BaseAddress = uintptr_t(Section.Address); uintptr_t StubAlignment = getStubAlignment(); StubAddress = (BaseAddress + Section.StubOffset + StubAlignment - 1) & - -StubAlignment; + -StubAlignment; unsigned StubOffset = StubAddress - BaseAddress; Stubs[Value] = StubOffset; createStubFunction((uint8_t *)StubAddress); - // Create a GOT entry for the external function. - GOTEntries.push_back(Value); - - // Make our stub function a relative call to the GOT entry. - RelocationEntry RE(SectionID, StubOffset + 2, ELF::R_X86_64_GOTPCREL, - -4); - addRelocationForSymbol(RE, Value.SymbolName); - // Bump our stub offset counter Section.StubOffset = StubOffset + getMaxStubSize(); + + // Allocate a GOT Entry + uint64_t GOTOffset = allocateGOTEntries(SectionID, 1); + + // The load of the GOT address has an addend of -4 + resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4); + + // Fill in the value of the symbol we're targeting into the GOT + addRelocationForSymbol(computeGOTOffsetRE(SectionID,GOTOffset,0,ELF::R_X86_64_64), + Value.SymbolName); + } + + // Make the target call a call into the stub table. + resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32, + Addend); + } else { + RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend, + Value.Offset); + addRelocationForSection(RE, Value.SectionID); } + } else if (RelType == ELF::R_X86_64_GOTPCREL) { + uint64_t GOTOffset = allocateGOTEntries(SectionID, 1); + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend); - // Make the target call a call into the stub table. - resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32, - Addend); + // Fill in the value of the symbol we're targeting into the GOT + RelocationEntry RE = computeGOTOffsetRE(SectionID, GOTOffset, Value.Offset, ELF::R_X86_64_64); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } else if (RelType == ELF::R_X86_64_PC32) { + Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); + processSimpleRelocation(SectionID, Offset, RelType, Value); + } else if (RelType == ELF::R_X86_64_PC64) { + Value.Addend += support::ulittle64_t::ref(computePlaceholderAddress(SectionID, Offset)); + processSimpleRelocation(SectionID, Offset, RelType, Value); } else { - RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend, - Value.Offset); - addRelocationForSection(RE, Value.SectionID); + processSimpleRelocation(SectionID, Offset, RelType, Value); } } else { - if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) { - GOTEntries.push_back(Value); + if (Arch == Triple::x86) { + Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); } - RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset); - if (Value.SymbolName) - addRelocationForSymbol(RE, Value.SymbolName); - else - addRelocationForSection(RE, Value.SectionID); + processSimpleRelocation(SectionID, Offset, RelType, Value); } return ++RelI; } -void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) { - - SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator it; - SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator end = GOTs.end(); - - for (it = GOTs.begin(); it != end; ++it) { - GOTRelocations &GOTEntries = it->second; - for (int i = 0, e = GOTEntries.size(); i != e; ++i) { - if (GOTEntries[i].SymbolName != nullptr && - GOTEntries[i].SymbolName == Name) { - GOTEntries[i].Offset = Addr; - } - } - } -} - size_t RuntimeDyldELF::getGOTEntrySize() { // We don't use the GOT in all of these cases, but it's essentially free // to put them all here. @@ -1399,83 +1366,53 @@ size_t RuntimeDyldELF::getGOTEntrySize() { return Result; } -uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { - - const size_t GOTEntrySize = getGOTEntrySize(); - - SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator it; - SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator end = - GOTs.end(); - - int GOTIndex = -1; - for (it = GOTs.begin(); it != end; ++it) { - SID GOTSectionID = it->first; - const GOTRelocations &GOTEntries = it->second; - - // Find the matching entry in our vector. - uint64_t SymbolOffset = 0; - for (int i = 0, e = GOTEntries.size(); i != e; ++i) { - if (!GOTEntries[i].SymbolName) { - if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress && - GOTEntries[i].Offset == Offset) { - GOTIndex = i; - SymbolOffset = GOTEntries[i].Offset; - break; - } - } else { - // GOT entries for external symbols use the addend as the address when - // the external symbol has been resolved. - if (GOTEntries[i].Offset == LoadAddress) { - GOTIndex = i; - // Don't use the Addend here. The relocation handler will use it. - break; - } - } - } - - if (GOTIndex != -1) { - if (GOTEntrySize == sizeof(uint64_t)) { - uint64_t *LocalGOTAddr = (uint64_t *)getSectionAddress(GOTSectionID); - // Fill in this entry with the address of the symbol being referenced. - LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset; - } else { - uint32_t *LocalGOTAddr = (uint32_t *)getSectionAddress(GOTSectionID); - // Fill in this entry with the address of the symbol being referenced. - LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset); - } - - // Calculate the load address of this entry - return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize); - } +uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned no) +{ + (void)SectionID; // The GOT Section is the same for all section in the object file + if (GOTSectionID == 0) { + GOTSectionID = Sections.size(); + // Reserve a section id. We'll allocate the section later + // once we know the total size + Sections.push_back(SectionEntry(".got", 0, 0, 0)); } + uint64_t StartOffset = CurrentGOTIndex * getGOTEntrySize(); + CurrentGOTIndex += no; + return StartOffset; +} + +void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, uint64_t GOTOffset) +{ + // Fill in the relative address of the GOT Entry into the stub + RelocationEntry GOTRE(SectionID, Offset, ELF::R_X86_64_PC32, GOTOffset); + addRelocationForSection(GOTRE, GOTSectionID); +} - assert(GOTIndex != -1 && "Unable to find requested GOT entry."); - return 0; +RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID, uint64_t GOTOffset, uint64_t SymbolOffset, + uint32_t Type) +{ + (void)SectionID; // The GOT Section is the same for all section in the object file + return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset); } void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { // If necessary, allocate the global offset table - if (MemMgr) { - // Allocate the GOT if necessary - size_t numGOTEntries = GOTEntries.size(); - if (numGOTEntries != 0) { - // Allocate memory for the section - unsigned SectionID = Sections.size(); - size_t TotalSize = numGOTEntries * getGOTEntrySize(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(), - SectionID, ".got", false); - if (!Addr) - report_fatal_error("Unable to allocate memory for GOT!"); - - GOTs.push_back(std::make_pair(SectionID, GOTEntries)); - Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0)); - // For now, initialize all GOT entries to zero. We'll fill them in as - // needed when GOT-based relocations are applied. - memset(Addr, 0, TotalSize); - } - } else { - report_fatal_error("Unable to allocate memory for GOT!"); + if (GOTSectionID != 0) { + // Allocate memory for the section + size_t TotalSize = CurrentGOTIndex * getGOTEntrySize(); + uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(), + GOTSectionID, ".got", false); + if (!Addr) + report_fatal_error("Unable to allocate memory for GOT!"); + + Sections[GOTSectionID] = SectionEntry(".got", Addr, TotalSize, 0); + + if (Checker) + Checker->registerSection(Obj.getFileName(), GOTSectionID); + + // For now, initialize all GOT entries to zero. We'll fill them in as + // needed when GOT-based relocations are applied. + memset(Addr, 0, TotalSize); } // Look for and record the EH frame section. @@ -1489,6 +1426,9 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, break; } } + + GOTSectionID = 0; + CurrentGOTIndex = 0; } bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index b4414b0..9a4a863 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -20,16 +20,6 @@ using namespace llvm; namespace llvm { -namespace { -// Helper for extensive error checking in debug builds. -std::error_code Check(std::error_code Err) { - if (Err) { - report_fatal_error(Err.message()); - } - return Err; -} - -} // end anonymous namespace class RuntimeDyldELF : public RuntimeDyldImpl { @@ -90,16 +80,39 @@ class RuntimeDyldELF : public RuntimeDyldImpl { ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); size_t getGOTEntrySize(); - void updateGOTEntries(StringRef Name, uint64_t Addr) override; + SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } + + // Allocate no GOT entries for use in the given section. + uint64_t allocateGOTEntries(unsigned SectionID, unsigned no); + + // Resolve the relvative address of GOTOffset in Section ID and place + // it at the given Offset + void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, + uint64_t GOTOffset); + + // For a GOT entry referenced from SectionID, compute a relocation entry + // that will place the final resolved value in the GOT slot + RelocationEntry computeGOTOffsetRE(unsigned SectionID, + uint64_t GOTOffset, + uint64_t SymbolOffset, + unsigned Type); + + // Compute the address in memory where we can find the placeholder + void *computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const; + + // Split out common case for createing the RelocationEntry for when the relocation requires + // no particular advanced processing. + void processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value); + + // The tentative ID for the GOT section + unsigned GOTSectionID; - // Relocation entries for symbols whose position-independent offset is - // updated in a global offset table. - typedef SmallVector<RelocationValueRef, 2> GOTRelocations; - GOTRelocations GOTEntries; // List of entries requiring finalization. - SmallVector<std::pair<SID, GOTRelocations>, 8> GOTs; // Allocated tables. + // Records the current number of allocated slots in the GOT + // (This would be equivalent to GOTEntries.size() were it not for relocations + // that consume more than one slot) + unsigned CurrentGOTIndex; // When a module is loaded we save the SectionID of the EH frame section // in a table until we receive a request to register all unregistered @@ -108,8 +121,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector<SID, 2> RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm); - virtual ~RuntimeDyldELF(); + RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); + ~RuntimeDyldELF() override; std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &O) override; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 2f3e3a8..90e61a5 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/Object/ObjectFile.h" @@ -36,6 +37,14 @@ using namespace llvm::object; namespace llvm { + // Helper for extensive error checking in debug builds. +inline std::error_code Check(std::error_code Err) { + if (Err) { + report_fatal_error(Err.message()); + } + return Err; +} + class Twine; /// SectionEntry - represents a section emitted into memory by the dynamic @@ -43,7 +52,7 @@ class Twine; class SectionEntry { public: /// Name - section name. - StringRef Name; + std::string Name; /// Address - address in the linker's memory where the section resides. uint8_t *Address; @@ -156,12 +165,34 @@ public: } }; +/// @brief Symbol info for RuntimeDyld. +class SymbolTableEntry : public JITSymbolBase { +public: + SymbolTableEntry() + : JITSymbolBase(JITSymbolFlags::None), Offset(0), SectionID(0) {} + + SymbolTableEntry(unsigned SectionID, uint64_t Offset, JITSymbolFlags Flags) + : JITSymbolBase(Flags), Offset(Offset), SectionID(SectionID) {} + + unsigned getSectionID() const { return SectionID; } + uint64_t getOffset() const { return Offset; } + +private: + uint64_t Offset; + unsigned SectionID; +}; + +typedef StringMap<SymbolTableEntry> RTDyldSymbolTable; + class RuntimeDyldImpl { friend class RuntimeDyld::LoadedObjectInfo; friend class RuntimeDyldCheckerImpl; protected: // The MemoryManager to load objects into. - RTDyldMemoryManager *MemMgr; + RuntimeDyld::MemoryManager &MemMgr; + + // The symbol resolver to use for external symbols. + RuntimeDyld::SymbolResolver &Resolver; // Attached RuntimeDyldChecker instance. Null if no instance attached. RuntimeDyldCheckerImpl *Checker; @@ -172,22 +203,17 @@ protected: SectionList Sections; typedef unsigned SID; // Type for SectionIDs -#define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) +#define RTDYLD_INVALID_SECTION_ID ((RuntimeDyldImpl::SID)(-1)) // Keep a map of sections from object file to the SectionID which // references it. typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; - // A global symbol table for symbols from all loaded modules. Maps the - // symbol name to a (SectionID, offset in section) pair. - typedef std::pair<unsigned, uintptr_t> SymbolLoc; - typedef StringMap<SymbolLoc> SymbolTableMap; - SymbolTableMap GlobalSymbolTable; + // A global symbol table for symbols from all loaded modules. + RTDyldSymbolTable GlobalSymbolTable; - // Pair representing the size and alignment requirement for a common symbol. - typedef std::pair<unsigned, unsigned> CommonSymbolInfo; // Keep a map of common symbols to their info pairs - typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap; + typedef std::vector<SymbolRef> CommonSymbolList; // For each symbol, keep a list of relocations based on it. Anytime // its address is reassigned (the JIT re-compiled the function, e.g.), @@ -287,9 +313,7 @@ protected: /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. - void emitCommonSymbols(const ObjectFile &Obj, - const CommonSymbolMap &CommonSymbols, - uint64_t TotalSize, SymbolTableMap &SymbolTable); + void emitCommonSymbols(const ObjectFile &Obj, CommonSymbolList &CommonSymbols); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be @@ -337,10 +361,6 @@ protected: /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); - /// \brief Update GOT entries for external symbols. - // The base class does nothing. ELF overrides this. - virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {} - // \brief Compute an upper bound of the memory that is required to load all // sections void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, @@ -354,8 +374,10 @@ protected: std::pair<unsigned, unsigned> loadObjectImpl(const object::ObjectFile &Obj); public: - RuntimeDyldImpl(RTDyldMemoryManager *mm) - : MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) { + RuntimeDyldImpl(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : MemMgr(MemMgr), Resolver(Resolver), Checker(nullptr), + ProcessAllSections(false), HasError(false) { } virtual ~RuntimeDyldImpl(); @@ -371,24 +393,26 @@ public: virtual std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &Obj) = 0; - uint8_t* getSymbolAddress(StringRef Name) const { + uint8_t* getSymbolLocalAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); if (pos == GlobalSymbolTable.end()) return nullptr; - SymbolLoc Loc = pos->second; - return getSectionAddress(Loc.first) + Loc.second; + const auto &SymInfo = pos->second; + return getSectionAddress(SymInfo.getSectionID()) + SymInfo.getOffset(); } - uint64_t getSymbolLoadAddress(StringRef Name) const { + RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); + RTDyldSymbolTable::const_iterator pos = GlobalSymbolTable.find(Name); if (pos == GlobalSymbolTable.end()) - return 0; - SymbolLoc Loc = pos->second; - return getSectionLoadAddress(Loc.first) + Loc.second; + return nullptr; + const auto &SymEntry = pos->second; + uint64_t TargetAddr = + getSectionLoadAddress(SymEntry.getSectionID()) + SymEntry.getOffset(); + return RuntimeDyld::SymbolInfo(TargetAddr, SymEntry.getFlags()); } void resolveRelocations(); diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index d75be28..d4a680d 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -26,11 +26,12 @@ using namespace llvm::object; namespace { -class LoadedMachOObjectInfo : public RuntimeDyld::LoadedObjectInfo { +class LoadedMachOObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> { public: LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, unsigned EndIdx) - : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} OwningBinary<ObjectFile> getObjectForDebug(const ObjectFile &Obj) const override { @@ -64,17 +65,18 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); - SymbolTableMap::const_iterator SI = + RTDyldSymbolTable::const_iterator SI = GlobalSymbolTable.find(TargetName.data()); if (SI != GlobalSymbolTable.end()) { - Value.SectionID = SI->second.first; - Value.Offset = SI->second.second + RE.Addend; + const auto &SymInfo = SI->second; + Value.SectionID = SymInfo.getSectionID(); + Value.Offset = SymInfo.getOffset() + RE.Addend; } else { Value.SymbolName = TargetName.data(); Value.Offset = RE.Addend; } } else { - SectionRef Sec = Obj.getRelocationSection(RelInfo); + SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); bool IsCode = Sec.isText(); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr = Sec.getAddress(); @@ -252,8 +254,6 @@ static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { template <typename Impl> void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || @@ -276,22 +276,28 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { P = processFDE(P, DeltaForText, DeltaForEH); } while (P != End); - MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, - EHFrame->Size); + MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, + EHFrame->Size); } UnregisteredEHFrameSections.clear(); } std::unique_ptr<RuntimeDyldMachO> -RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); break; - case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM); - case Triple::aarch64: return make_unique<RuntimeDyldMachOAArch64>(MM); - case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM); - case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM); + case Triple::arm: + return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver); + case Triple::aarch64: + return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver); + case Triple::x86: + return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver); + case Triple::x86_64: + return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver); } } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index f8bfc03..45a94ba 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -49,7 +49,9 @@ protected: // EH frame sections with the memory manager. SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections; - RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldMachO(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} /// This convenience method uses memcpy to extract a contiguous addend (the /// addend size and offset are taken from the corresponding fields of the RE). @@ -114,8 +116,10 @@ protected: public: /// Create a RuntimeDyldMachO instance for the given target architecture. - static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch, - RTDyldMemoryManager *mm); + static std::unique_ptr<RuntimeDyldMachO> + create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); std::unique_ptr<RuntimeDyld::LoadedObjectInfo> loadObject(const object::ObjectFile &O) override; @@ -142,7 +146,9 @@ private: int64_t DeltaForEH); public: - RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {} + RuntimeDyldMachOCRTPBase(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachO(MemMgr, Resolver) {} void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h new file mode 100644 index 0000000..478665e --- /dev/null +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -0,0 +1,216 @@ +//===-- RuntimeDyldCOFFX86_64.h --- COFF/X86_64 specific code ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// COFF x86_x64 support for MC-JIT runtime dynamic linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H + +#include "llvm/Object/COFF.h" +#include "llvm/Support/COFF.h" +#include "../RuntimeDyldCOFF.h" + +#define DEBUG_TYPE "dyld" + +namespace llvm { + +class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF { + +private: + // When a module is loaded we save the SectionID of the unwind + // sections in a table until we receive a request to register all + // unregisteredEH frame sections with the memory manager. + SmallVector<SID, 2> UnregisteredEHFrameSections; + SmallVector<SID, 2> RegisteredEHFrameSections; + +public: + RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldCOFF(MM, Resolver) {} + + unsigned getMaxStubSize() override { + return 6; // 2-byte jmp instruction + 32-bit relative address + } + + // The target location for the relocation is described by RE.SectionID and + // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each + // SectionEntry has three members describing its location. + // SectionEntry::Address is the address at which the section has been loaded + // into memory in the current (host) process. SectionEntry::LoadAddress is + // the address that the section will have in the target process. + // SectionEntry::ObjAddress is the address of the bits for this section in the + // original emitted object image (also in the current address space). + // + // Relocations will be applied as if the section were loaded at + // SectionEntry::LoadAddress, but they will be applied at an address based + // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer + // to Target memory contents if they are required for value calculations. + // + // The Value parameter here is the load address of the symbol for the + // relocation to be applied. For relocations which refer to symbols in the + // current object Value will be the LoadAddress of the section in which + // the symbol resides (RE.Addend provides additional information about the + // symbol location). For external symbols, Value will be the address of the + // symbol in the target address space. + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { + const SectionEntry &Section = Sections[RE.SectionID]; + uint8_t *Target = Section.Address + RE.Offset; + + switch (RE.RelType) { + + case COFF::IMAGE_REL_AMD64_REL32: + case COFF::IMAGE_REL_AMD64_REL32_1: + case COFF::IMAGE_REL_AMD64_REL32_2: + case COFF::IMAGE_REL_AMD64_REL32_3: + case COFF::IMAGE_REL_AMD64_REL32_4: + case COFF::IMAGE_REL_AMD64_REL32_5: { + uint32_t *TargetAddress = (uint32_t *)Target; + uint64_t FinalAddress = Section.LoadAddress + RE.Offset; + // Delta is the distance from the start of the reloc to the end of the + // instruction with the reloc. + uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32); + Value -= FinalAddress + Delta; + uint64_t Result = Value + RE.Addend; + assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow"); + assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow"); + *TargetAddress = Result; + break; + } + + case COFF::IMAGE_REL_AMD64_ADDR32NB: { + // Note ADDR32NB requires a well-established notion of + // image base. This address must be less than or equal + // to every section's load address, and all sections must be + // within a 32 bit offset from the base. + // + // For now we just set these to zero. + uint32_t *TargetAddress = (uint32_t *)Target; + *TargetAddress = 0; + break; + } + + case COFF::IMAGE_REL_AMD64_ADDR64: { + uint64_t *TargetAddress = (uint64_t *)Target; + *TargetAddress = Value + RE.Addend; + break; + } + + default: + llvm_unreachable("Relocation type not implemented yet!"); + break; + } + } + + relocation_iterator processRelocationRef(unsigned SectionID, + relocation_iterator RelI, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { + // If possible, find the symbol referred to in the relocation, + // and the section that contains it. + symbol_iterator Symbol = RelI->getSymbol(); + if (Symbol == Obj.symbol_end()) + report_fatal_error("Unknown symbol in relocation"); + section_iterator SecI(Obj.section_end()); + Symbol->getSection(SecI); + // If there is no section, this must be an external reference. + const bool IsExtern = SecI == Obj.section_end(); + + // Determine the Addend used to adjust the relocation value. + uint64_t RelType; + Check(RelI->getType(RelType)); + uint64_t Offset; + Check(RelI->getOffset(Offset)); + uint64_t Addend = 0; + SectionEntry &Section = Sections[SectionID]; + uintptr_t ObjTarget = Section.ObjAddress + Offset; + + switch (RelType) { + + case COFF::IMAGE_REL_AMD64_REL32: + case COFF::IMAGE_REL_AMD64_REL32_1: + case COFF::IMAGE_REL_AMD64_REL32_2: + case COFF::IMAGE_REL_AMD64_REL32_3: + case COFF::IMAGE_REL_AMD64_REL32_4: + case COFF::IMAGE_REL_AMD64_REL32_5: + case COFF::IMAGE_REL_AMD64_ADDR32NB: { + uint32_t *Displacement = (uint32_t *)ObjTarget; + Addend = *Displacement; + break; + } + + case COFF::IMAGE_REL_AMD64_ADDR64: { + uint64_t *Displacement = (uint64_t *)ObjTarget; + Addend = *Displacement; + break; + } + + default: + break; + } + + StringRef TargetName; + Symbol->getName(TargetName); + + DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset + << " RelType: " << RelType << " TargetName: " << TargetName + << " Addend " << Addend << "\n"); + + if (IsExtern) { + RelocationEntry RE(SectionID, Offset, RelType, Addend); + addRelocationForSymbol(RE, TargetName); + } else { + bool IsCode = SecI->isText(); + unsigned TargetSectionID = + findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID); + uint64_t TargetOffset = getSymbolOffset(*Symbol); + RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend); + addRelocationForSection(RE, TargetSectionID); + } + + return ++RelI; + } + + unsigned getStubAlignment() override { return 1; } + void registerEHFrames() override { + for (auto const &EHFrameSID : UnregisteredEHFrameSections) { + uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; + uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; + size_t EHFrameSize = Sections[EHFrameSID].Size; + MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + RegisteredEHFrameSections.push_back(EHFrameSID); + } + UnregisteredEHFrameSections.clear(); + } + void deregisterEHFrames() override { + // Stub + } + void finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) override { + // Look for and record the EH frame section IDs. + for (const auto &SectionPair : SectionMap) { + const SectionRef &Section = SectionPair.first; + StringRef Name; + Check(Section.getName(Name)); + // Note unwind info is split across .pdata and .xdata, so this + // may not be sufficiently general for all users. + if (Name == ".xdata") { + UnregisteredEHFrameSections.push_back(SectionPair.second); + } + } + } +}; + +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index 196fa62..99fd6e3 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -23,8 +23,9 @@ public: typedef uint64_t TargetPtrT; - RuntimeDyldMachOAArch64(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 09e430e..09e51f2 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -25,7 +25,9 @@ public: typedef uint32_t TargetPtrT; - RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 67d7027..053f90c 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -22,8 +22,9 @@ public: typedef uint32_t TargetPtrT; - RuntimeDyldMachOI386(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 0; } diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 0734017..4b3b01b 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -22,8 +22,9 @@ public: typedef uint64_t TargetPtrT; - RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/contrib/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp index 5986084..5986084 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp +++ b/contrib/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp diff --git a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp index e6679cf..57f6e08 100644 --- a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp +++ b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp @@ -49,21 +49,19 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple, // Adjust the triple to match what the user requested. const Target *TheTarget = nullptr; if (!MArch.empty()) { - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - if (MArch == it->getName()) { - TheTarget = &*it; - break; - } - } + auto I = std::find_if( + TargetRegistry::targets().begin(), TargetRegistry::targets().end(), + [&](const Target &T) { return MArch == T.getName(); }); - if (!TheTarget) { + if (I == TargetRegistry::targets().end()) { if (ErrorStr) *ErrorStr = "No available targets are compatible with this -march, " "see -version for the available targets.\n"; return nullptr; } + TheTarget = &*I; + // Adjust the triple to match (if known), otherwise stick with the // requested/host triple. Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); |