aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorAndrew Kaylor <andrew.kaylor@intel.com>2013-10-01 01:47:35 +0000
committerAndrew Kaylor <andrew.kaylor@intel.com>2013-10-01 01:47:35 +0000
commit8e9ec015348c5419b905c2ca6e39534429eda073 (patch)
treeef91e4612da9faa32322d7f2d4c33d71bc584334 /lib/ExecutionEngine
parent451c71d67b1dd324dcd76d771cf05bf7721bdc59 (diff)
downloadexternal_llvm-8e9ec015348c5419b905c2ca6e39534429eda073.zip
external_llvm-8e9ec015348c5419b905c2ca6e39534429eda073.tar.gz
external_llvm-8e9ec015348c5419b905c2ca6e39534429eda073.tar.bz2
Adding multiple module support for MCJIT.
Tests to follow. PIC with small code model and EH frame handling will not work with multiple modules. There are also some rough edges to be smoothed out for remote target support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191722 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.cpp265
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.h98
-rw-r--r--lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp6
-rw-r--r--lib/ExecutionEngine/RTDyldMemoryManager.cpp40
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp56
5 files changed, 366 insertions, 99 deletions
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
index 09dd924..9eaff4d 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp
@@ -18,6 +18,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
@@ -53,37 +54,45 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM,
bool AllocateGVsWithCode)
- : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM),
- IsLoaded(false), M(m), ObjCache(0) {
+ : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(this, MM), Dyld(&MemMgr),
+ ObjCache(0) {
+ ModuleStates[m] = ModuleAdded;
setDataLayout(TM->getDataLayout());
}
MCJIT::~MCJIT() {
- if (LoadedObject)
- NotifyFreeingObject(*LoadedObject.get());
- delete MemMgr;
+ LoadedObjectMap::iterator it, end = LoadedObjects.end();
+ for (it = LoadedObjects.begin(); it != end; ++it) {
+ ObjectImage *Obj = it->second;
+ if (Obj) {
+ NotifyFreeingObject(*Obj);
+ delete Obj;
+ }
+ }
+ LoadedObjects.clear();
delete TM;
}
+void MCJIT::addModule(Module *M) {
+ Modules.push_back(M);
+ ModuleStates[M] = MCJITModuleState();
+}
+
void MCJIT::setObjectCache(ObjectCache* NewCache) {
ObjCache = NewCache;
}
-ObjectBufferStream* MCJIT::emitObject(Module *m) {
- /// Currently, MCJIT only supports a single module and the module passed to
- /// this function call is expected to be the contained module. The module
- /// is passed as a parameter here to prepare for multiple module support in
- /// the future.
- assert(M == m);
+ObjectBufferStream* MCJIT::emitObject(Module *M) {
+ // This must be a module which has already been added to this MCJIT instance.
+ assert(std::find(Modules.begin(), Modules.end(), M) != Modules.end());
+ assert(ModuleStates.find(M) != ModuleStates.end());
// Get a thread lock to make sure we aren't trying to compile multiple times
MutexGuard locked(lock);
- // FIXME: Track compilation state on a per-module basis when multiple modules
- // are supported.
// Re-compilation is not supported
- assert(!IsLoaded);
+ assert(!ModuleStates[M].hasBeenEmitted());
PassManager PM;
@@ -99,7 +108,7 @@ ObjectBufferStream* MCJIT::emitObject(Module *m) {
}
// Initialize passes.
- PM.run(*m);
+ PM.run(*M);
// Flush the output buffer to get the generated code into memory
CompiledObject->flush();
@@ -109,21 +118,22 @@ ObjectBufferStream* MCJIT::emitObject(Module *m) {
// MemoryBuffer is a thin wrapper around the actual memory, so it's OK
// to create a temporary object here and delete it after the call.
OwningPtr<MemoryBuffer> MB(CompiledObject->getMemBuffer());
- ObjCache->notifyObjectCompiled(m, MB.get());
+ ObjCache->notifyObjectCompiled(M, MB.get());
}
return CompiledObject.take();
}
-void MCJIT::loadObject(Module *M) {
+void MCJIT::generateCodeForModule(Module *M) {
+ // This must be a module which has already been added to this MCJIT instance.
+ assert(std::find(Modules.begin(), Modules.end(), M) != Modules.end());
+ assert(ModuleStates.find(M) != ModuleStates.end());
// Get a thread lock to make sure we aren't trying to load multiple times
MutexGuard locked(lock);
- // FIXME: Track compilation state on a per-module basis when multiple modules
- // are supported.
// Re-compilation is not supported
- if (IsLoaded)
+ if (ModuleStates[M].hasBeenLoaded())
return;
OwningPtr<ObjectBuffer> ObjectToLoad;
@@ -141,59 +151,190 @@ void MCJIT::loadObject(Module *M) {
}
// Load the object into the dynamic linker.
- // handing off ownership of the buffer
- LoadedObject.reset(Dyld.loadObject(ObjectToLoad.take()));
+ // MCJIT now owns the ObjectImage pointer (via its LoadedObjects map).
+ ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.take());
+ LoadedObjects[M] = LoadedObject;
if (!LoadedObject)
report_fatal_error(Dyld.getErrorString());
- // Resolve any relocations.
- Dyld.resolveRelocations();
-
// FIXME: Make this optional, maybe even move it to a JIT event listener
LoadedObject->registerWithDebugger();
NotifyObjectEmitted(*LoadedObject);
- // FIXME: Add support for per-module compilation state
- IsLoaded = true;
+ ModuleStates[M] = ModuleLoaded;
+}
+
+void MCJIT::finalizeLoadedModules() {
+ // Resolve any outstanding relocations.
+ Dyld.resolveRelocations();
+
+ // Register EH frame data for any module we own which has been loaded
+ SmallVector<Module *, 1>::iterator end = Modules.end();
+ SmallVector<Module *, 1>::iterator it;
+ for (it = Modules.begin(); it != end; ++it) {
+ Module *M = *it;
+ assert(ModuleStates.find(M) != ModuleStates.end());
+
+ if (ModuleStates[M].hasBeenLoaded() &&
+ !ModuleStates[M].hasBeenFinalized()) {
+ // FIXME: This should be module specific!
+ StringRef EHData = Dyld.getEHFrameSection();
+ if (!EHData.empty())
+ MemMgr.registerEHFrames(EHData);
+ ModuleStates[M] = ModuleFinalized;
+ }
+ }
+
+ // Set page permissions.
+ MemMgr.finalizeMemory();
}
-// FIXME: Add a parameter to identify which object is being finalized when
-// MCJIT supports multiple modules.
-// FIXME: Provide a way to separate code emission, relocations and page
-// protection in the interface.
+// FIXME: Rename this.
void MCJIT::finalizeObject() {
- // If the module hasn't been compiled, just do that.
- if (!IsLoaded) {
- // If the call to Dyld.resolveRelocations() is removed from loadObject()
- // we'll need to do that here.
- loadObject(M);
- } else {
- // Resolve any relocations.
- Dyld.resolveRelocations();
+ // FIXME: This is a temporary hack to get around problems with calling
+ // finalize multiple times.
+ bool finalizeNeeded = false;
+ SmallVector<Module *, 1>::iterator end = Modules.end();
+ SmallVector<Module *, 1>::iterator it;
+ for (it = Modules.begin(); it != end; ++it) {
+ Module *M = *it;
+ assert(ModuleStates.find(M) != ModuleStates.end());
+ if (!ModuleStates[M].hasBeenFinalized())
+ finalizeNeeded = true;
+
+ // I don't really like this, but the C API depends on this behavior.
+ // I suppose it's OK for a deprecated function.
+ if (!ModuleStates[M].hasBeenLoaded())
+ generateCodeForModule(M);
+ }
+ if (!finalizeNeeded)
+ return;
+
+ // Resolve any outstanding relocations.
+ Dyld.resolveRelocations();
+
+ // Register EH frame data for any module we own which has been loaded
+ for (it = Modules.begin(); it != end; ++it) {
+ Module *M = *it;
+ assert(ModuleStates.find(M) != ModuleStates.end());
+
+ if (ModuleStates[M].hasBeenLoaded() &&
+ !ModuleStates[M].hasBeenFinalized()) {
+ // FIXME: This should be module specific!
+ StringRef EHData = Dyld.getEHFrameSection();
+ if (!EHData.empty())
+ MemMgr.registerEHFrames(EHData);
+ ModuleStates[M] = ModuleFinalized;
+ }
}
+ // Set page permissions.
+ MemMgr.finalizeMemory();
+}
+
+void MCJIT::finalizeModule(Module *M) {
+ // This must be a module which has already been added to this MCJIT instance.
+ assert(std::find(Modules.begin(), Modules.end(), M) != Modules.end());
+ assert(ModuleStates.find(M) != ModuleStates.end());
+
+ if (ModuleStates[M].hasBeenFinalized())
+ return;
+
+ // If the module hasn't been compiled, just do that.
+ if (!ModuleStates[M].hasBeenLoaded())
+ generateCodeForModule(M);
+
+ // Resolve any outstanding relocations.
+ Dyld.resolveRelocations();
+
+ // FIXME: Should this be module specific?
StringRef EHData = Dyld.getEHFrameSection();
if (!EHData.empty())
- MemMgr->registerEHFrames(EHData);
+ MemMgr.registerEHFrames(EHData);
// Set page permissions.
- MemMgr->finalizeMemory();
+ MemMgr.finalizeMemory();
+
+ ModuleStates[M] = ModuleFinalized;
}
void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
report_fatal_error("not yet implemented");
}
-void *MCJIT::getPointerToFunction(Function *F) {
- // FIXME: This should really return a uint64_t since it's a pointer in the
- // target address space, not our local address space. That's part of the
- // ExecutionEngine interface, though. Fix that when the old JIT finally
- // dies.
+uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) {
+ // Check with the RuntimeDyld to see if we already have this symbol.
+ if (Name[0] == '\1')
+ return Dyld.getSymbolLoadAddress(Name.substr(1));
+ return Dyld.getSymbolLoadAddress((TM->getMCAsmInfo()->getGlobalPrefix()
+ + Name));
+}
+
+Module *MCJIT::findModuleForSymbol(const std::string &Name,
+ bool CheckFunctionsOnly) {
+ // If it hasn't already been generated, see if it's in one of our modules.
+ SmallVector<Module *, 1>::iterator end = Modules.end();
+ SmallVector<Module *, 1>::iterator it;
+ for (it = Modules.begin(); it != end; ++it) {
+ Module *M = *it;
+ Function *F = M->getFunction(Name);
+ if (F && !F->empty())
+ return M;
+ if (!CheckFunctionsOnly) {
+ GlobalVariable *G = M->getGlobalVariable(Name);
+ if (G)
+ return M;
+ // FIXME: Do we need to worry about global aliases?
+ }
+ }
+ // We didn't find the symbol in any of our modules.
+ return NULL;
+}
+
+uint64_t MCJIT::getSymbolAddress(const std::string &Name,
+ bool CheckFunctionsOnly)
+{
+ // First, check to see if we already have this symbol.
+ uint64_t Addr = getExistingSymbolAddress(Name);
+ if (Addr)
+ return Addr;
+
+ // If it hasn't already been generated, see if it's in one of our modules.
+ Module *M = findModuleForSymbol(Name, CheckFunctionsOnly);
+ if (!M)
+ return 0;
+
+ // If this is in one of our modules, generate code for that module.
+ assert(ModuleStates.find(M) != ModuleStates.end());
+ // If the module code has already been generated, we won't find the symbol.
+ if (ModuleStates[M].hasBeenLoaded())
+ return 0;
- // FIXME: Add support for per-module compilation state
- if (!IsLoaded)
- loadObject(M);
+ // FIXME: We probably need to make sure we aren't in the process of
+ // loading or finalizing this module.
+ generateCodeForModule(M);
+
+ // Check the RuntimeDyld table again, it should be there now.
+ return getExistingSymbolAddress(Name);
+}
+
+uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) {
+ uint64_t Result = getSymbolAddress(Name, false);
+ if (Result != 0)
+ finalizeLoadedModules();
+ return Result;
+}
+
+uint64_t MCJIT::getFunctionAddress(const std::string &Name) {
+ uint64_t Result = getSymbolAddress(Name, true);
+ if (Result != 0)
+ finalizeLoadedModules();
+ return Result;
+}
+
+// Deprecated. Use getFunctionAddress instead.
+void *MCJIT::getPointerToFunction(Function *F) {
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
bool AbortOnFailure = !F->hasExternalWeakLinkage();
@@ -202,6 +343,17 @@ void *MCJIT::getPointerToFunction(Function *F) {
return Addr;
}
+ // If this function doesn't belong to one of our modules, we're done.
+ Module *M = F->getParent();
+ if (std::find(Modules.begin(), Modules.end(), M) == Modules.end())
+ return NULL;
+
+ assert(ModuleStates.find(M) != ModuleStates.end());
+
+ // Make sure the relevant module has been compiled and loaded.
+ if (!ModuleStates[M].hasBeenLoaded())
+ generateCodeForModule(M);
+
// FIXME: Should the Dyld be retaining module information? Probably not.
// FIXME: Should we be using the mangler for this? Probably.
//
@@ -324,12 +476,8 @@ GenericValue MCJIT::runFunction(Function *F,
void *MCJIT::getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure) {
- // FIXME: Add support for per-module compilation state
- if (!IsLoaded)
- loadObject(M);
-
- if (!isSymbolSearchingDisabled() && MemMgr) {
- void *ptr = MemMgr->getPointerToNamedFunction(Name, false);
+ if (!isSymbolSearchingDisabled()) {
+ void *ptr = MemMgr.getPointerToNamedFunction(Name, false);
if (ptr)
return ptr;
}
@@ -375,3 +523,10 @@ void MCJIT::NotifyFreeingObject(const ObjectImage& Obj) {
EventListeners[I]->NotifyFreeingObject(Obj);
}
}
+
+uint64_t LinkingMemoryManager::getSymbolAddress(const std::string &Name) {
+ uint64_t Result = ParentEngine->getSymbolAddress(Name, false);
+ if (Result)
+ return Result;
+ return ClientMM->getSymbolAddress(Name);
+}
diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h
index a899d4f..5fb2eeb 100644
--- a/lib/ExecutionEngine/MCJIT/MCJIT.h
+++ b/lib/ExecutionEngine/MCJIT/MCJIT.h
@@ -10,15 +10,53 @@
#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H
#define LLVM_LIB_EXECUTIONENGINE_MCJIT_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/ObjectImage.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/PassManager.h"
namespace llvm {
-class ObjectImage;
+class MCJIT;
+
+// This is a helper class that the MCJIT execution engine uses for linking
+// 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 {
+public:
+ LinkingMemoryManager(MCJIT *Parent, RTDyldMemoryManager *MM)
+ : ParentEngine(Parent), ClientMM(MM) {}
+
+ virtual uint64_t getSymbolAddress(const std::string &Name);
+
+ // Functions deferred to client memory manager
+ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID) {
+ return ClientMM->allocateCodeSection(Size, Alignment, SectionID);
+ }
+
+ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, bool IsReadOnly) {
+ return ClientMM->allocateDataSection(Size, Alignment,
+ SectionID, IsReadOnly);
+ }
+
+ virtual void registerEHFrames(StringRef SectionData) {
+ ClientMM->registerEHFrames(SectionData);
+ }
+
+ virtual bool finalizeMemory(std::string *ErrMsg = 0) {
+ return ClientMM->finalizeMemory(ErrMsg);
+ }
+
+private:
+ MCJIT *ParentEngine;
+ OwningPtr<RTDyldMemoryManager> ClientMM;
+};
// FIXME: This makes all kinds of horrible assumptions for the time being,
// like only having one module, not needing to worry about multi-threading,
@@ -28,16 +66,40 @@ class MCJIT : public ExecutionEngine {
MCJIT(Module *M, TargetMachine *tm, RTDyldMemoryManager *MemMgr,
bool AllocateGVsWithCode);
+ enum ModuleState {
+ ModuleAdded,
+ ModuleEmitted,
+ ModuleLoading,
+ ModuleLoaded,
+ ModuleFinalizing,
+ ModuleFinalized
+ };
+
+ class MCJITModuleState {
+ public:
+ MCJITModuleState() : State(ModuleAdded) {}
+
+ MCJITModuleState & operator=(ModuleState s) { State = s; return *this; }
+ bool hasBeenEmitted() { return State != ModuleAdded; }
+ bool hasBeenLoaded() { return State != ModuleAdded &&
+ State != ModuleEmitted; }
+ bool hasBeenFinalized() { return State == ModuleFinalized; }
+
+ private:
+ ModuleState State;
+ };
+
TargetMachine *TM;
MCContext *Ctx;
- RTDyldMemoryManager *MemMgr;
+ LinkingMemoryManager MemMgr;
RuntimeDyld Dyld;
SmallVector<JITEventListener*, 2> EventListeners;
- // FIXME: Add support for multiple modules
- bool IsLoaded;
- Module *M;
- OwningPtr<ObjectImage> LoadedObject;
+ typedef DenseMap<Module *, MCJITModuleState> ModuleStateMap;
+ ModuleStateMap ModuleStates;
+
+ typedef DenseMap<Module *, ObjectImage *> LoadedObjectMap;
+ LoadedObjectMap LoadedObjects;
// An optional ObjectCache to be notified of compiled objects and used to
// perform lookup of pre-compiled code to avoid re-compilation.
@@ -48,10 +110,13 @@ public:
/// @name ExecutionEngine interface implementation
/// @{
+ virtual void addModule(Module *M);
/// Sets the object manager that MCJIT should use to avoid compilation.
virtual void setObjectCache(ObjectCache *manager);
+ virtual void generateCodeForModule(Module *M);
+
/// finalizeObject - ensure the module is fully processed and is usable.
///
/// It is the user-level function for completing the process of making the
@@ -59,7 +124,10 @@ public:
/// object have been relocated using mapSectionAddress. When this method is
/// called the MCJIT execution engine will reapply relocations for a loaded
/// object.
+ /// FIXME: Do we really need both of these?
virtual void finalizeObject();
+ virtual void finalizeModule(Module *);
+ void finalizeLoadedModules();
virtual void *getPointerToBasicBlock(BasicBlock *BB);
@@ -91,10 +159,15 @@ public:
uint64_t TargetAddress) {
Dyld.mapSectionAddress(LocalAddress, TargetAddress);
}
-
virtual void RegisterJITEventListener(JITEventListener *L);
virtual void UnregisterJITEventListener(JITEventListener *L);
+ // If successful, these function will implicitly finalize all loaded objects.
+ // To get a function address within MCJIT without causing a finalize, use
+ // getSymbolAddress.
+ virtual uint64_t getGlobalValueAddress(const std::string &Name);
+ virtual uint64_t getFunctionAddress(const std::string &Name);
+
/// @}
/// @name (Private) Registration Interfaces
/// @{
@@ -111,6 +184,11 @@ public:
// @}
+ // 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);
+
protected:
/// emitObject -- Generate a JITed object in memory from the specified module
/// Currently, MCJIT only supports a single module and the module passed to
@@ -119,10 +197,12 @@ protected:
/// the future.
ObjectBufferStream* emitObject(Module *M);
- void loadObject(Module *M);
-
void NotifyObjectEmitted(const ObjectImage& Obj);
void NotifyFreeingObject(const ObjectImage& Obj);
+
+ uint64_t getExistingSymbolAddress(const std::string &Name);
+ Module *findModuleForSymbol(const std::string &Name,
+ bool CheckFunctionsOnly);
};
} // End llvm namespace
diff --git a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
index 650832e..5469c83 100644
--- a/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
+++ b/lib/ExecutionEngine/MCJIT/SectionMemoryManager.cpp
@@ -105,6 +105,9 @@ bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
// FIXME: Should in-progress permissions be reverted if an error occurs?
error_code ec;
+ // Don't allow free memory blocks to be used after setting protection flags.
+ CodeMem.FreeMem.clear();
+
// Make code memory executable.
ec = applyMemoryGroupPermissions(CodeMem,
sys::Memory::MF_READ | sys::Memory::MF_EXEC);
@@ -115,6 +118,9 @@ bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
return true;
}
+ // Don't allow free memory blocks to be used after setting protection flags.
+ RODataMem.FreeMem.clear();
+
// Make read-only data memory read-only.
ec = applyMemoryGroupPermissions(RODataMem,
sys::Memory::MF_READ | sys::Memory::MF_EXEC);
diff --git a/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RTDyldMemoryManager.cpp
index c5500df..de38b38 100644
--- a/lib/ExecutionEngine/RTDyldMemoryManager.cpp
+++ b/lib/ExecutionEngine/RTDyldMemoryManager.cpp
@@ -68,8 +68,10 @@ static int jit_noop() {
return 0;
}
-void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure) {
+uint64_t RTDyldMemoryManager::getSymbolAddress(const std::string &Name) {
+ // This implementation assumes that the host program is the target.
+ // Clients generating code for a remote target should implement their own
+ // memory manager.
#if defined(__linux__)
//===--------------------------------------------------------------------===//
// Function stubs that are invoked instead of certain library calls
@@ -80,14 +82,14 @@ void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
- if (Name == "stat") return (void*)(intptr_t)&stat;
- if (Name == "fstat") return (void*)(intptr_t)&fstat;
- if (Name == "lstat") return (void*)(intptr_t)&lstat;
- if (Name == "stat64") return (void*)(intptr_t)&stat64;
- if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
- if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
- if (Name == "atexit") return (void*)(intptr_t)&atexit;
- if (Name == "mknod") return (void*)(intptr_t)&mknod;
+ if (Name == "stat") return (uint64_t)&stat;
+ if (Name == "fstat") return (uint64_t)&fstat;
+ if (Name == "lstat") return (uint64_t)&lstat;
+ if (Name == "stat64") return (uint64_t)&stat64;
+ if (Name == "fstat64") return (uint64_t)&fstat64;
+ if (Name == "lstat64") return (uint64_t)&lstat64;
+ if (Name == "atexit") return (uint64_t)&atexit;
+ if (Name == "mknod") return (uint64_t)&mknod;
#endif // __linux__
// We should not invoke parent's ctors/dtors from generated main()!
@@ -96,23 +98,31 @@ void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
// (and register wrong callee's dtors with atexit(3)).
// We expect ExecutionEngine::runStaticConstructorsDestructors()
// is called before ExecutionEngine::runFunctionAsMain() is called.
- if (Name == "__main") return (void*)(intptr_t)&jit_noop;
+ if (Name == "__main") return (uint64_t)&jit_noop;
const char *NameStr = Name.c_str();
void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
- if (Ptr) return Ptr;
+ if (Ptr)
+ return (uint64_t)Ptr;
// If it wasn't found and if it starts with an underscore ('_') character,
// try again without the underscore.
if (NameStr[0] == '_') {
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
- if (Ptr) return Ptr;
+ if (Ptr)
+ return (uint64_t)Ptr;
}
+ return 0;
+}
- if (AbortOnFailure)
+void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure) {
+ uint64_t Addr = getSymbolAddress(Name);
+
+ if (!Addr && AbortOnFailure)
report_fatal_error("Program used external function '" + Name +
"' which could not be resolved!");
- return 0;
+ return (void*)Addr;
}
} // namespace llvm
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index d36126a..89c04dd 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -49,6 +49,7 @@ void RuntimeDyldImpl::resolveRelocations() {
<< "\t" << format("%p", (uint8_t *)Addr)
<< "\n");
resolveRelocationList(Relocations[i], Addr);
+ Relocations.erase(i);
}
}
@@ -464,31 +465,42 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
}
void RuntimeDyldImpl::resolveExternalSymbols() {
- StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin(),
- e = ExternalSymbolRelocations.end();
- for (; i != e; i++) {
+ while(!ExternalSymbolRelocations.empty()) {
+ StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
+
StringRef Name = i->first();
RelocationList &Relocs = i->second;
- SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name);
- if (Loc == GlobalSymbolTable.end()) {
- if (Name.size() == 0) {
- // This is an absolute symbol, use an address of zero.
- DEBUG(dbgs() << "Resolving absolute relocations." << "\n");
- resolveRelocationList(Relocs, 0);
+ if (Name.size() == 0) {
+ // This is an absolute symbol, use an address of zero.
+ DEBUG(dbgs() << "Resolving absolute relocations." << "\n");
+ resolveRelocationList(Relocs, 0);
+ } else {
+ uint64_t Addr = 0;
+ SymbolTableMap::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());
} else {
- // This is an external symbol, try to get its address from
- // MemoryManager.
- uint8_t *Addr = (uint8_t*) MemMgr->getPointerToNamedFunction(Name.data(),
- true);
- updateGOTEntries(Name, (uint64_t)Addr);
- DEBUG(dbgs() << "Resolving relocations Name: " << Name
- << "\t" << format("%p", Addr)
- << "\n");
- resolveRelocationList(Relocs, (uintptr_t)Addr);
+ // We found the symbol in our global table. It was probably in a
+ // Module that we loaded previously.
+ SymbolLoc SymLoc = GlobalSymbolTable.lookup(Name);
+ Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second;
}
- } else {
- report_fatal_error("Expected external symbol");
+
+ // FIXME: Implement error handling that doesn't kill the host program!
+ if (!Addr)
+ 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");
+ resolveRelocationList(Relocs, Addr);
}
+
+ ExternalSymbolRelocations.erase(i->first());
}
}
@@ -550,10 +562,14 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
}
void *RuntimeDyld::getSymbolAddress(StringRef Name) {
+ if (!Dyld)
+ return NULL;
return Dyld->getSymbolAddress(Name);
}
uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) {
+ if (!Dyld)
+ return 0;
return Dyld->getSymbolLoadAddress(Name);
}