aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/EventListenerCommon.h68
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp176
-rw-r--r--lib/ExecutionEngine/ExecutionEngineBindings.cpp2
-rw-r--r--lib/ExecutionEngine/GDBRegistrationListener.cpp2
-rw-r--r--lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp3
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp16
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp9
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h2
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp84
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.h84
-rw-r--r--lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp2
-rw-r--r--lib/ExecutionEngine/Orc/Android.mk1
-rw-r--r--lib/ExecutionEngine/Orc/CMakeLists.txt1
-rw-r--r--lib/ExecutionEngine/Orc/ExecutionUtils.cpp102
-rw-r--r--lib/ExecutionEngine/Orc/IndirectionUtils.cpp63
-rw-r--r--lib/ExecutionEngine/Orc/OrcMCJITReplacement.h124
-rw-r--r--lib/ExecutionEngine/Orc/OrcTargetSupport.cpp100
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp95
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp6
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h10
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp2
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h1
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp198
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h35
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h18
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp52
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h14
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h8
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h5
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h4
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h5
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h5
32 files changed, 727 insertions, 570 deletions
diff --git a/lib/ExecutionEngine/EventListenerCommon.h b/lib/ExecutionEngine/EventListenerCommon.h
deleted file mode 100644
index 6453099..0000000
--- a/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/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index c586ba7..d7038fd 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -18,9 +18,11 @@
#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"
@@ -45,11 +47,13 @@ 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::unique_ptr<RTDyldMemoryManager> OrcJMM,
+ 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,
@@ -58,8 +62,7 @@ ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
void JITEventListener::anchor() {}
ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M)
- : EEState(*this),
- LazyFunctionCreator(nullptr) {
+ : LazyFunctionCreator(nullptr) {
CompilingLazily = false;
GVCompilationDisabled = false;
SymbolSearchingDisabled = false;
@@ -151,38 +154,52 @@ Function *ExecutionEngine::FindFunctionNamed(const char *FnName) {
}
-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;
}
}
@@ -197,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));
+}
+
+uint64_t ExecutionEngine::updateGlobalMapping(const GlobalValue *GV,
+ void *Addr) {
+ MutexGuard locked(lock);
+ return updateGlobalMapping(getMangledName(GV), (uint64_t) Addr);
}
-void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
+uint64_t ExecutionEngine::updateGlobalMapping(StringRef Name, uint64_t Addr) {
MutexGuard locked(lock);
ExecutionEngineState::GlobalAddressMapTy &Map =
@@ -211,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);
@@ -222,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) {
@@ -244,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 {
@@ -404,8 +452,9 @@ EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {}
EngineBuilder::EngineBuilder(std::unique_ptr<Module> M)
: M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr),
- OptLevel(CodeGenOpt::Default), MCJMM(nullptr), RelocModel(Reloc::Default),
- CMModel(CodeModel::JITDefault), UseOrcMCJITReplacement(false) {
+ 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
@@ -419,7 +468,21 @@ 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;
+}
+
+EngineBuilder&
+EngineBuilder::setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM) {
+ MemMgr = std::shared_ptr<MCJITMemoryManager>(std::move(MM));
+ return *this;
+}
+
+EngineBuilder&
+EngineBuilder::setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR) {
+ Resolver = std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(SR));
return *this;
}
@@ -434,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,12 +519,13 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
ExecutionEngine *EE = nullptr;
if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) {
- EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MCJMM),
+ 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(MCJMM),
- std::move(TheTM));
+ EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr),
+ std::move(Resolver), std::move(TheTM));
if (EE) {
EE->setVerifyModules(VerifyModules);
@@ -492,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.
@@ -502,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
@@ -1274,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/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
index aaa53f0..22ff311 100644
--- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp
+++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
@@ -351,7 +351,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/lib/ExecutionEngine/GDBRegistrationListener.cpp b/lib/ExecutionEngine/GDBRegistrationListener.cpp
index 8ef878c..1ab6203 100644
--- a/lib/ExecutionEngine/GDBRegistrationListener.cpp
+++ b/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/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
index aa32452..4135900 100644
--- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
+++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Config/config.h"
-#include "EventListenerCommon.h"
#include "IntelJITEventsWrapper.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -29,7 +28,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 +39,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;
diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp
index 2e8eb16..a26740b 100644
--- a/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -316,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); \
@@ -363,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) \
@@ -536,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 ==
@@ -567,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 !=
@@ -713,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"; \
@@ -745,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/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index b022101..e2fe065 100644
--- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/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/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h
index 2be9c59..0dc0463 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/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/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
index 20b8553..7e37afe 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp
+++ b/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"
@@ -41,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
@@ -221,7 +231,7 @@ void MCJIT::finalizeLoadedModules() {
Dyld.registerEHFrames();
// Set page permissions.
- MemMgr.finalizeMemory();
+ MemMgr->finalizeMemory();
}
// FIXME: Rename this.
@@ -253,11 +263,11 @@ void MCJIT::finalizeModule(Module *M) {
finalizeLoadedModules();
}
-uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) {
+RuntimeDyld::SymbolInfo MCJIT::findExistingSymbol(const std::string &Name) {
Mangler Mang(TM->getDataLayout());
SmallString<128> FullName;
Mang.getNameWithPrefix(FullName, Name);
- return Dyld.getSymbol(FullName).getAddress();
+ return Dyld.getSymbol(FullName);
}
Module *MCJIT::findModuleForSymbol(const std::string &Name,
@@ -284,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();
@@ -310,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;
}
}
}
@@ -323,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) {
@@ -528,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;
}
@@ -566,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);
}
@@ -578,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/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h
index de4a8f6..59e9949 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.h
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.h
@@ -16,6 +16,7 @@
#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/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp b/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp
index 9ab4003..23e7662 100644
--- a/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp
+++ b/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/lib/ExecutionEngine/Orc/Android.mk b/lib/ExecutionEngine/Orc/Android.mk
index 61c1daf..f28f359 100644
--- a/lib/ExecutionEngine/Orc/Android.mk
+++ b/lib/ExecutionEngine/Orc/Android.mk
@@ -6,6 +6,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
CloneSubModule.cpp \
+ ExecutionUtils.cpp \
IndirectionUtils.cpp \
OrcMCJITReplacement.cpp \
OrcTargetSupport.cpp
diff --git a/lib/ExecutionEngine/Orc/CMakeLists.txt b/lib/ExecutionEngine/Orc/CMakeLists.txt
index b0a8445..b38b459 100644
--- a/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -1,5 +1,6 @@
add_llvm_library(LLVMOrcJIT
CloneSubModule.cpp
+ ExecutionUtils.cpp
IndirectionUtils.cpp
OrcMCJITReplacement.cpp
OrcTargetSupport.cpp
diff --git a/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
new file mode 100644
index 0000000..b7220db
--- /dev/null
+++ b/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/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
index 8cf490f..ebeedef 100644
--- a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
+++ b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -14,17 +14,25 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/IRBuilder.h"
#include <set>
+#include <sstream>
namespace llvm {
namespace orc {
-GlobalVariable* createImplPointer(Function &F, const Twine &Name,
- Constant *Initializer) {
- assert(F.getParent() && "Function isn't in a module.");
+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(F.getType());
- Module &M = *F.getParent();
- return new GlobalVariable(M, F.getType(), false, GlobalValue::ExternalLinkage,
+ Initializer = Constant::getNullValue(&PT);
+ return new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
Initializer, Name, nullptr,
GlobalValue::NotThreadLocal, 0, true);
}
@@ -44,8 +52,41 @@ void makeStub(Function &F, GlobalVariable &ImplPointer) {
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;
+};
+
void partition(Module &M, const ModulePartitionMap &PMap) {
+ GlobalRenamer Renamer;
+
for (auto &KVPair : PMap) {
auto ExtractGlobalVars =
@@ -54,20 +95,26 @@ void partition(Module &M, const ModulePartitionMap &PMap) {
if (KVPair.second.count(&Orig)) {
copyGVInitializer(New, Orig, VMap);
}
- if (New.getLinkage() == GlobalValue::PrivateLinkage) {
+ if (New.hasLocalLinkage()) {
+ if (Renamer.needsRenaming(New))
+ New.setName(Renamer.getRename(Orig));
New.setLinkage(GlobalValue::ExternalLinkage);
New.setVisibility(GlobalValue::HiddenVisibility);
}
+ assert(!Renamer.needsRenaming(New) && "Invalid global name.");
};
auto ExtractFunctions =
[&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
if (KVPair.second.count(&Orig))
copyFunctionBody(New, Orig, VMap);
- if (New.getLinkage() == GlobalValue::InternalLinkage) {
+ if (New.hasLocalLinkage()) {
+ if (Renamer.needsRenaming(New))
+ New.setName(Renamer.getRename(Orig));
New.setLinkage(GlobalValue::ExternalLinkage);
New.setVisibility(GlobalValue::HiddenVisibility);
}
+ assert(!Renamer.needsRenaming(New) && "Invalid function name.");
};
CloneSubModule(*KVPair.first, M, ExtractGlobalVars, ExtractFunctions,
diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
index 00e39bb..4023344 100644
--- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
+++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
@@ -26,15 +26,21 @@ namespace orc {
class OrcMCJITReplacement : public ExecutionEngine {
- class ForwardingRTDyldMM : public RTDyldMemoryManager {
+ // 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:
- ForwardingRTDyldMM(OrcMCJITReplacement &M) : M(M) {}
+ 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 =
- M.MM->allocateCodeSection(Size, Alignment, SectionID, SectionName);
+ ClientMM->allocateCodeSection(Size, Alignment, SectionID,
+ SectionName);
M.SectionsAllocatedSinceLastLoad.insert(Addr);
return Addr;
}
@@ -42,43 +48,35 @@ class OrcMCJITReplacement : public ExecutionEngine {
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override {
- uint8_t *Addr = M.MM->allocateDataSection(Size, Alignment, SectionID,
- SectionName, IsReadOnly);
+ 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 M.MM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
+ return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO,
+ DataSizeRW);
}
bool needsToReserveAllocationSpace() override {
- return M.MM->needsToReserveAllocationSpace();
+ return ClientMM->needsToReserveAllocationSpace();
}
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {
- return M.MM->registerEHFrames(Addr, LoadAddr, Size);
+ return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
}
void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {
- return M.MM->deregisterEHFrames(Addr, LoadAddr, Size);
- }
-
- uint64_t getSymbolAddress(const std::string &Name) override {
- return M.getSymbolAddressWithoutMangling(Name);
- }
-
- void *getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure = true) override {
- return M.MM->getPointerToNamedFunction(Name, AbortOnFailure);
+ return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size);
}
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &O) override {
- return M.MM->notifyObjectLoaded(EE, O);
+ return ClientMM->notifyObjectLoaded(EE, O);
}
bool finalizeMemory(std::string *ErrMsg = nullptr) override {
@@ -96,21 +94,41 @@ class OrcMCJITReplacement : public ExecutionEngine {
// get more than one set of objects loaded but not yet finalized is if
// they were loaded during relocation of another set.
if (M.UnfinalizedSections.size() == 1)
- return M.MM->finalizeMemory(ErrMsg);
+ return 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::unique_ptr<RTDyldMemoryManager> OrcJMM,
+ std::shared_ptr<MCJITMemoryManager> MemMgr,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) {
- return new OrcMCJITReplacement(std::move(OrcJMM), std::move(TM));
+ return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
+ std::move(TM));
}
public:
@@ -118,12 +136,15 @@ public:
OrcMCJITReplacementCtor = createOrcMCJITReplacement;
}
- OrcMCJITReplacement(std::unique_ptr<RTDyldMemoryManager> MM,
- std::unique_ptr<TargetMachine> TM)
- : TM(std::move(TM)), MM(std::move(MM)), Mang(this->TM->getDataLayout()),
+ 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(ObjectLayerT::CreateRTDyldMMFtor(), NotifyObjectLoaded,
- NotifyFinalized),
+ ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
LazyEmitLayer(CompileLayer) {
setDataLayout(this->TM->getDataLayout());
@@ -139,15 +160,13 @@ public:
Modules.push_back(std::move(M));
std::vector<Module *> Ms;
Ms.push_back(&*Modules.back());
- LazyEmitLayer.addModuleSet(std::move(Ms),
- llvm::make_unique<ForwardingRTDyldMM>(*this));
+ 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),
- llvm::make_unique<ForwardingRTDyldMM>(*this));
+ ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
}
void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
@@ -157,8 +176,7 @@ public:
std::vector<std::unique_ptr<object::ObjectFile>> Objs;
Objs.push_back(std::move(Obj));
auto H =
- ObjectLayer.addObjectSet(std::move(Objs),
- llvm::make_unique<ForwardingRTDyldMM>(*this));
+ ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
std::vector<std::unique_ptr<MemoryBuffer>> Bufs;
Bufs.push_back(std::move(Buf));
@@ -170,7 +188,11 @@ public:
}
uint64_t getSymbolAddress(StringRef Name) {
- return getSymbolAddressWithoutMangling(Mangle(Name));
+ return findSymbol(Name).getAddress();
+ }
+
+ RuntimeDyld::SymbolInfo findSymbol(StringRef Name) {
+ return findMangledSymbol(Mangle(Name));
}
void finalizeObject() override {
@@ -214,18 +236,19 @@ public:
}
private:
- uint64_t getSymbolAddressWithoutMangling(StringRef Name) {
- if (uint64_t Addr = LazyEmitLayer.findSymbol(Name, false).getAddress())
- return Addr;
- if (uint64_t Addr = MM->getSymbolAddress(Name))
- return Addr;
- if (uint64_t Addr = scanArchives(Name))
- return Addr;
- return 0;
+ 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;
}
- uint64_t scanArchives(StringRef Name) {
+ JITSymbol scanArchives(StringRef Name) {
for (object::OwningBinary<object::Archive> &OB : Archives) {
object::Archive *A = OB.getBinary();
// Look for our symbols in each Archive
@@ -241,14 +264,13 @@ private:
std::vector<std::unique_ptr<object::ObjectFile>> ObjSet;
ObjSet.push_back(std::unique_ptr<object::ObjectFile>(
static_cast<object::ObjectFile *>(ChildBin.release())));
- ObjectLayer.addObjectSet(
- std::move(ObjSet), llvm::make_unique<ForwardingRTDyldMM>(*this));
- if (uint64_t Addr = ObjectLayer.findSymbol(Name, true).getAddress())
- return Addr;
+ ObjectLayer.addObjectSet(std::move(ObjSet), &MemMgr, &Resolver);
+ if (auto Sym = ObjectLayer.findSymbol(Name, true))
+ return Sym;
}
}
}
- return 0;
+ return nullptr;
}
class NotifyObjectLoadedT {
@@ -267,7 +289,7 @@ private:
assert(Objects.size() == Infos.size() &&
"Incorrect number of Infos for Objects.");
for (unsigned I = 0; I < Objects.size(); ++I)
- M.MM->notifyObjectLoaded(&M, *Objects[I]);
+ M.MemMgr.notifyObjectLoaded(&M, *Objects[I]);
};
private:
@@ -299,7 +321,9 @@ private:
typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
std::unique_ptr<TargetMachine> TM;
- std::unique_ptr<RTDyldMemoryManager> MM;
+ MCJITReplacementMemMgr MemMgr;
+ LinkingResolver Resolver;
+ std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver;
Mangler Mang;
NotifyObjectLoadedT NotifyObjectLoaded;
diff --git a/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp b/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp
index 6fe5301..fc56e67 100644
--- a/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp
+++ b/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp
@@ -6,39 +6,6 @@ using namespace llvm::orc;
namespace {
-std::array<const char *, 12> X86GPRsToSave = {{
- "rbp", "rbx", "r12", "r13", "r14", "r15", // Callee saved.
- "rdi", "rsi", "rdx", "rcx", "r8", "r9", // Int args.
-}};
-
-std::array<const char *, 8> X86XMMsToSave = {{
- "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" // FP args
-}};
-
-template <typename OStream> unsigned saveX86Regs(OStream &OS) {
- for (const auto &GPR : X86GPRsToSave)
- OS << " pushq %" << GPR << "\n";
-
- OS << " subq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n";
-
- for (unsigned i = 0; i < X86XMMsToSave.size(); ++i)
- OS << " movdqu %" << X86XMMsToSave[i] << ", "
- << (16 * (X86XMMsToSave.size() - i - 1)) << "(%rsp)\n";
-
- return (8 * X86GPRsToSave.size()) + (16 * X86XMMsToSave.size());
-}
-
-template <typename OStream> void restoreX86Regs(OStream &OS) {
- for (unsigned i = 0; i < X86XMMsToSave.size(); ++i)
- OS << " movdqu " << (16 * i) << "(%rsp), %"
- << X86XMMsToSave[(X86XMMsToSave.size() - i - 1)] << "\n";
- OS << " addq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n";
-
- for (unsigned i = 0; i < X86GPRsToSave.size(); ++i)
- OS << " popq %" << X86GPRsToSave[X86GPRsToSave.size() - i - 1] << "\n";
-}
-
-template <typename TargetT>
uint64_t executeCompileCallback(JITCompileCallbackManagerBase *JCBM,
TargetAddress CallbackID) {
return JCBM->executeCompileCallback(CallbackID);
@@ -53,14 +20,28 @@ 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;
- auto CallbackPtr = executeCompileCallback<OrcX86_64>;
+
+ // 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>(CallbackPtr));
+ 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";
@@ -68,24 +49,51 @@ void OrcX86_64::insertResolverBlock(
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"
- << ResolverBlockName << ":\n";
-
- uint64_t ReturnAddrOffset = saveX86Regs(AsmStream);
-
- // Compute index, load object address, and call JIT.
- AsmStream << " leaq jit_callback_manager_addr(%rip), %rdi\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"
+ << " fxsave (%rsp)\n"
+
+ // Load callback manager address, compute trampoline address, call JIT.
+ << " lea jit_callback_manager_addr(%rip), %rdi\n"
<< " movq (%rdi), %rdi\n"
- << " movq " << ReturnAddrOffset << "(%rsp), %rsi\n"
+ << " movq 0x8(%rbp), %rsi\n"
<< " subq $" << X86_64_TrampolineLength << ", %rsi\n"
<< " movabsq $" << CallbackAddr << ", %rax\n"
<< " callq *%rax\n"
- << " movq %rax, " << ReturnAddrOffset << "(%rsp)\n";
- restoreX86Regs(AsmStream);
+ // 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.
+ << " fxrstor (%rsp)\n"
+ << " addq $" << FXSaveSize << ", %rsp\n";
+
+ for (const auto &GPR : make_range(GPRs.rbegin(), GPRs.rend()))
+ AsmStream << " popq %" << GPR << "\n";
- AsmStream << " retq\n";
+ // Restore original RBP and return to compiled function body.
+ AsmStream << " popq %rbp\n"
+ << " retq\n";
M.appendModuleInlineAsm(AsmStream.str());
}
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index a0ed7cf..a13ecb7 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -57,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() << " ";
}
@@ -92,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"));
@@ -151,10 +152,10 @@ 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
@@ -360,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;
}
}
}
@@ -485,7 +487,7 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
// Skip common symbols already elsewhere.
if (GlobalSymbolTable.count(Name) ||
- MemMgr->getSymbolAddressInLogicalDylib(Name)) {
+ Resolver.findSymbolInLogicalDylib(Name)) {
DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name
<< "'\n");
continue;
@@ -502,8 +504,8 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
// Allocate memory for the section
unsigned SectionID = Sections.size();
- uint8_t *Addr = MemMgr->allocateDataSection(CommonSize, sizeof(void *),
- SectionID, StringRef(), false);
+ uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, sizeof(void *),
+ SectionID, StringRef(), false);
if (!Addr)
report_fatal_error("Unable to allocate memory for common symbols!");
uint64_t Offset = 0;
@@ -577,10 +579,12 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
if (IsRequired) {
Check(Section.getContents(data));
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!");
@@ -787,9 +791,9 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
uint64_t Addr = 0;
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
@@ -810,7 +814,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
@@ -835,7 +838,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
@@ -843,7 +851,6 @@ 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;
}
@@ -851,27 +858,33 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
RuntimeDyld::~RuntimeDyld() {}
static std::unique_ptr<RuntimeDyldCOFF>
-createRuntimeDyldCOFF(Triple::ArchType Arch, RTDyldMemoryManager *MM,
+createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
+ RuntimeDyld::SymbolResolver &Resolver,
bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) {
- std::unique_ptr<RuntimeDyldCOFF> Dyld(RuntimeDyldCOFF::create(Arch, MM));
+ 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;
@@ -881,14 +894,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()), MM,
+ static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver,
ProcessAllSections, Checker);
else
report_fatal_error("Incompatible object format!");
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
index 56bcb8e..8055d55 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
@@ -40,13 +40,15 @@ public:
namespace llvm {
std::unique_ptr<RuntimeDyldCOFF>
-llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
+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>(MM);
+ return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
}
}
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h
index 681a3e5..32b8fa2 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h
@@ -31,11 +31,15 @@ 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,
- RTDyldMemoryManager *MM);
+
+ static std::unique_ptr<RuntimeDyldCOFF>
+ create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver);
protected:
- RuntimeDyldCOFF(RTDyldMemoryManager *MM) : RuntimeDyldImpl(MM) {}
+ RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldImpl(MemMgr, Resolver) {}
uint64_t getSymbolOffset(const SymbolRef &Sym);
};
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
index c991408..957571b 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
@@ -738,7 +738,7 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
return InternalSymbol.getAddress();
- return getRTDyld().MemMgr->getSymbolAddress(Symbol);
+ return getRTDyld().Resolver.findSymbol(Symbol).getAddress();
}
uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
index e8d299a..69d2a7d 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
@@ -19,6 +19,7 @@ class RuntimeDyldCheckerImpl {
friend class RuntimeDyldChecker;
friend class RuntimeDyldImpl;
friend class RuntimeDyldCheckerExprEval;
+ friend class RuntimeDyldELF;
public:
RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 6278170..bbffdfb 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "RuntimeDyldELF.h"
+#include "RuntimeDyldCheckerImpl.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -183,32 +184,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,27 +246,16 @@ 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;
+ int64_t RealOffset = Value + Addend - FinalAddress;
+ // Don't add the placeholder if this is a stub
+ if (Offset < Section.Size)
+ RealOffset += Placeholder;
assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset;
@@ -279,8 +267,10 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
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;
+ if (Offset < Section.Size)
+ RealOffset += Placeholder;
+ support::ulittle64_t::ref(Section.Address + Offset) = RealOffset;
break;
}
}
@@ -1325,16 +1315,18 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
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.
@@ -1345,10 +1337,17 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
Value.Offset);
addRelocationForSection(RE, Value.SectionID);
}
+ } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) {
+ uint64_t GOTOffset = allocateGOTEntries(SectionID, 1);
+ resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + 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 (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) {
- GOTEntries.push_back(Value);
- }
RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, Value.Offset);
if (Value.SymbolName)
addRelocationForSymbol(RE, Value.SymbolName);
@@ -1358,22 +1357,6 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
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.
@@ -1400,83 +1383,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;
+}
- assert(GOTIndex != -1 && "Unable to find requested GOT entry.");
- return 0;
+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);
+}
+
+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.
@@ -1490,6 +1443,9 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
break;
}
}
+
+ GOTSectionID = 0;
+ CurrentGOTIndex = 0;
}
bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
index 71260d0..590d26a 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -80,16 +80,32 @@ 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]; }
- // 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.
+ // 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);
+
+ // The tentative ID for the GOT section
+ unsigned GOTSectionID;
+
+ // 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
@@ -98,8 +114,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
SmallVector<SID, 2> RegisteredEHFrameSections;
public:
- RuntimeDyldELF(RTDyldMemoryManager *mm);
- virtual ~RuntimeDyldELF();
+ RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver);
+ ~RuntimeDyldELF() override;
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
loadObject(const object::ObjectFile &O) override;
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index 05060dd..ee51a75 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
#include "llvm/Object/ObjectFile.h"
@@ -51,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;
@@ -188,7 +189,10 @@ class RuntimeDyldImpl {
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;
@@ -357,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,
@@ -374,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();
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
index 2d39662..675063c 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
@@ -178,25 +178,30 @@ bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
}
template <typename Impl>
-void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &ObjImg,
+void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) {
unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
- ObjSectionToIDMap::iterator i, e;
- for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {
- const SectionRef &Section = i->first;
+ for (const auto &Section : Obj.sections()) {
StringRef Name;
Section.getName(Name);
- if (Name == "__eh_frame")
- EHFrameSID = i->second;
- else if (Name == "__text")
- TextSID = i->second;
+
+ // Force emission of the __text, __eh_frame, and __gcc_except_tab sections
+ // if they're present. Otherwise call down to the impl to handle other
+ // sections that have already been emitted.
+ if (Name == "__text")
+ TextSID = findOrEmitSection(Obj, Section, true, SectionMap);
+ else if (Name == "__eh_frame")
+ EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap);
else if (Name == "__gcc_except_tab")
- ExceptTabSID = i->second;
- else
- impl().finalizeSection(ObjImg, i->second, Section);
+ ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap);
+ else {
+ auto I = SectionMap.find(Section);
+ if (I != SectionMap.end())
+ impl().finalizeSection(Obj, I->second, Section);
+ }
}
UnregisteredEHFrameSections.push_back(
EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
@@ -239,7 +244,8 @@ unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(unsigned char *P,
}
static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {
- int64_t ObjDistance = A->ObjAddress - B->ObjAddress;
+ int64_t ObjDistance =
+ static_cast<int64_t>(A->ObjAddress) - static_cast<int64_t>(B->ObjAddress);
int64_t MemDistance = A->LoadAddress - B->LoadAddress;
return ObjDistance - MemDistance;
}
@@ -247,8 +253,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 ||
@@ -271,22 +275,28 @@ void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
P = processFDE(P, DeltaForText, DeltaForEH);
} while (P != End);
- MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress,
- EHFrame->Size);
+ MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress,
+ EHFrame->Size);
}
UnregisteredEHFrameSections.clear();
}
std::unique_ptr<RuntimeDyldMachO>
-RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) {
+RuntimeDyldMachO::create(Triple::ArchType Arch,
+ RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver) {
switch (Arch) {
default:
llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
break;
- case Triple::arm: return make_unique<RuntimeDyldMachOARM>(MM);
- case Triple::aarch64: return make_unique<RuntimeDyldMachOAArch64>(MM);
- case Triple::x86: return make_unique<RuntimeDyldMachOI386>(MM);
- case Triple::x86_64: return make_unique<RuntimeDyldMachOX86_64>(MM);
+ case Triple::arm:
+ return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
+ case Triple::aarch64:
+ return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
+ case Triple::x86:
+ return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
+ case Triple::x86_64:
+ return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);
}
}
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
index f8bfc03..45a94ba 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -49,7 +49,9 @@ protected:
// EH frame sections with the memory manager.
SmallVector<EHFrameRelatedSections, 2> UnregisteredEHFrameSections;
- RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
+ RuntimeDyldMachO(RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldImpl(MemMgr, Resolver) {}
/// This convenience method uses memcpy to extract a contiguous addend (the
/// addend size and offset are taken from the corresponding fields of the RE).
@@ -114,8 +116,10 @@ protected:
public:
/// Create a RuntimeDyldMachO instance for the given target architecture.
- static std::unique_ptr<RuntimeDyldMachO> create(Triple::ArchType Arch,
- RTDyldMemoryManager *mm);
+ static std::unique_ptr<RuntimeDyldMachO>
+ create(Triple::ArchType Arch,
+ RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver);
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
loadObject(const object::ObjectFile &O) override;
@@ -142,7 +146,9 @@ private:
int64_t DeltaForEH);
public:
- RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {}
+ RuntimeDyldMachOCRTPBase(RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldMachO(MemMgr, Resolver) {}
void finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) override;
diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
index ce2f4a2..cd534a1 100644
--- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
+++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
@@ -32,7 +32,9 @@ private:
SmallVector<SID, 2> RegisteredEHFrameSections;
public:
- RuntimeDyldCOFFX86_64(RTDyldMemoryManager *MM) : RuntimeDyldCOFF(MM) {}
+ RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldCOFF(MM, Resolver) {}
unsigned getMaxStubSize() override {
return 6; // 2-byte jmp instruction + 32-bit relative address
@@ -177,13 +179,11 @@ public:
unsigned getStubAlignment() override { return 1; }
void registerEHFrames() override {
- if (!MemMgr)
- return;
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);
+ MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
RegisteredEHFrameSections.push_back(EHFrameSID);
}
UnregisteredEHFrameSections.clear();
diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
index 196fa62..99fd6e3 100644
--- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
+++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h
@@ -23,8 +23,9 @@ public:
typedef uint64_t TargetPtrT;
- RuntimeDyldMachOAArch64(RTDyldMemoryManager *MM)
- : RuntimeDyldMachOCRTPBase(MM) {}
+ RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
unsigned getMaxStubSize() override { return 8; }
diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
index 09e430e..09e51f2 100644
--- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
+++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
@@ -25,7 +25,9 @@ public:
typedef uint32_t TargetPtrT;
- RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {}
+ RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
unsigned getMaxStubSize() override { return 8; }
diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
index 67d7027..053f90c 100644
--- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
+++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
@@ -22,8 +22,9 @@ public:
typedef uint32_t TargetPtrT;
- RuntimeDyldMachOI386(RTDyldMemoryManager *MM)
- : RuntimeDyldMachOCRTPBase(MM) {}
+ RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
unsigned getMaxStubSize() override { return 0; }
diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h
index 0734017..4b3b01b 100644
--- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h
+++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h
@@ -22,8 +22,9 @@ public:
typedef uint64_t TargetPtrT;
- RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM)
- : RuntimeDyldMachOCRTPBase(MM) {}
+ RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
unsigned getMaxStubSize() override { return 8; }