forked from OSchip/llvm-project
Remove dlsym stubs, with Nate Begeman's permission.
llvm-svn: 86606
This commit is contained in:
parent
1218b804fb
commit
8483f12ac5
|
@ -91,7 +91,6 @@ class ExecutionEngine {
|
||||||
bool CompilingLazily;
|
bool CompilingLazily;
|
||||||
bool GVCompilationDisabled;
|
bool GVCompilationDisabled;
|
||||||
bool SymbolSearchingDisabled;
|
bool SymbolSearchingDisabled;
|
||||||
bool DlsymStubsEnabled;
|
|
||||||
|
|
||||||
friend class EngineBuilder; // To allow access to JITCtor and InterpCtor.
|
friend class EngineBuilder; // To allow access to JITCtor and InterpCtor.
|
||||||
|
|
||||||
|
@ -370,14 +369,6 @@ public:
|
||||||
return SymbolSearchingDisabled;
|
return SymbolSearchingDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EnableDlsymStubs -
|
|
||||||
void EnableDlsymStubs(bool Enabled = true) {
|
|
||||||
DlsymStubsEnabled = Enabled;
|
|
||||||
}
|
|
||||||
bool areDlsymStubsEnabled() const {
|
|
||||||
return DlsymStubsEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// InstallLazyFunctionCreator - If an unknown function is needed, the
|
/// InstallLazyFunctionCreator - If an unknown function is needed, the
|
||||||
/// specified function pointer is invoked to create it. If it returns null,
|
/// specified function pointer is invoked to create it. If it returns null,
|
||||||
/// the JIT will abort.
|
/// the JIT will abort.
|
||||||
|
|
|
@ -71,17 +71,6 @@ public:
|
||||||
/// return a pointer to its base.
|
/// return a pointer to its base.
|
||||||
virtual uint8_t *getGOTBase() const = 0;
|
virtual uint8_t *getGOTBase() const = 0;
|
||||||
|
|
||||||
/// SetDlsymTable - If the JIT must be able to relocate stubs after they have
|
|
||||||
/// been emitted, potentially because they are being copied to a process
|
|
||||||
/// where external symbols live at different addresses than in the JITing
|
|
||||||
/// process, allocate a table with sufficient information to do so.
|
|
||||||
virtual void SetDlsymTable(void *ptr) = 0;
|
|
||||||
|
|
||||||
/// getDlsymTable - If this is managing a table of entries so that stubs to
|
|
||||||
/// external symbols can be later relocated, this method should return a
|
|
||||||
/// pointer to it.
|
|
||||||
virtual void *getDlsymTable() const = 0;
|
|
||||||
|
|
||||||
/// NeedsExactSize - If the memory manager requires to know the size of the
|
/// NeedsExactSize - If the memory manager requires to know the size of the
|
||||||
/// objects to be emitted
|
/// objects to be emitted
|
||||||
bool NeedsExactSize() const {
|
bool NeedsExactSize() const {
|
||||||
|
|
|
@ -52,7 +52,6 @@ ExecutionEngine::ExecutionEngine(ModuleProvider *P)
|
||||||
CompilingLazily = false;
|
CompilingLazily = false;
|
||||||
GVCompilationDisabled = false;
|
GVCompilationDisabled = false;
|
||||||
SymbolSearchingDisabled = false;
|
SymbolSearchingDisabled = false;
|
||||||
DlsymStubsEnabled = false;
|
|
||||||
Modules.push_back(P);
|
Modules.push_back(P);
|
||||||
assert(P && "ModuleProvider is null?");
|
assert(P && "ModuleProvider is null?");
|
||||||
}
|
}
|
||||||
|
|
|
@ -613,11 +613,6 @@ void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) {
|
||||||
// the stub with real address of the function.
|
// the stub with real address of the function.
|
||||||
updateFunctionStub(PF);
|
updateFunctionStub(PF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the JIT is configured to emit info so that dlsym can be used to
|
|
||||||
// rewrite stubs to external globals, do so now.
|
|
||||||
if (areDlsymStubsEnabled() && !isCompilingLazily())
|
|
||||||
updateDlsymStubTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getPointerToFunction - This method is used to get the address of the
|
/// getPointerToFunction - This method is used to get the address of the
|
||||||
|
@ -660,8 +655,7 @@ void *JIT::getPointerToFunction(Function *F) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
|
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
|
||||||
bool AbortOnFailure =
|
bool AbortOnFailure = !F->hasExternalWeakLinkage();
|
||||||
!areDlsymStubsEnabled() && !F->hasExternalWeakLinkage();
|
|
||||||
void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
|
void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
|
||||||
addGlobalMapping(F, Addr);
|
addGlobalMapping(F, Addr);
|
||||||
return Addr;
|
return Addr;
|
||||||
|
@ -690,7 +684,7 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
|
||||||
return (void*)&__dso_handle;
|
return (void*)&__dso_handle;
|
||||||
#endif
|
#endif
|
||||||
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName());
|
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName());
|
||||||
if (Ptr == 0 && !areDlsymStubsEnabled()) {
|
if (Ptr == 0) {
|
||||||
llvm_report_error("Could not resolve external global address: "
|
llvm_report_error("Could not resolve external global address: "
|
||||||
+GV->getName());
|
+GV->getName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,6 @@ private:
|
||||||
TargetMachine &tm);
|
TargetMachine &tm);
|
||||||
void runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked);
|
void runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked);
|
||||||
void updateFunctionStub(Function *F);
|
void updateFunctionStub(Function *F);
|
||||||
void updateDlsymStubTable();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -369,10 +369,6 @@ namespace {
|
||||||
// the stub is unused.
|
// the stub is unused.
|
||||||
DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs;
|
DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs;
|
||||||
|
|
||||||
// ExtFnStubs - A map of external function names to stubs which have entries
|
|
||||||
// in the JITResolver's ExternalFnToStubMap.
|
|
||||||
StringMap<void *> ExtFnStubs;
|
|
||||||
|
|
||||||
DebugLocTuple PrevDLT;
|
DebugLocTuple PrevDLT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -461,10 +457,6 @@ namespace {
|
||||||
/// deallocateMemForFunction to also remove stubs no longer referenced.
|
/// deallocateMemForFunction to also remove stubs no longer referenced.
|
||||||
void AddStubToCurrentFunction(void *Stub);
|
void AddStubToCurrentFunction(void *Stub);
|
||||||
|
|
||||||
/// getExternalFnStubs - Accessor for the JIT to find stubs emitted for
|
|
||||||
/// MachineRelocations that reference external functions by name.
|
|
||||||
const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; }
|
|
||||||
|
|
||||||
virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn);
|
virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn);
|
||||||
|
|
||||||
virtual void emitLabel(uint64_t LabelID) {
|
virtual void emitLabel(uint64_t LabelID) {
|
||||||
|
@ -536,10 +528,8 @@ void *JITResolver::getFunctionStub(Function *F) {
|
||||||
Actual = TheJIT->getPointerToFunction(F);
|
Actual = TheJIT->getPointerToFunction(F);
|
||||||
|
|
||||||
// If we resolved the symbol to a null address (eg. a weak external)
|
// If we resolved the symbol to a null address (eg. a weak external)
|
||||||
// don't emit a stub. Return a null pointer to the application. If dlsym
|
// don't emit a stub. Return a null pointer to the application.
|
||||||
// stubs are enabled, not being able to resolve the address is not
|
if (!Actual) return 0;
|
||||||
// meaningful.
|
|
||||||
if (!Actual && !TheJIT->areDlsymStubsEnabled()) return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Codegen a new stub, calling the lazy resolver or the actual address of the
|
// Codegen a new stub, calling the lazy resolver or the actual address of the
|
||||||
|
@ -758,10 +748,9 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
|
||||||
if (ResultPtr) return ResultPtr;
|
if (ResultPtr) return ResultPtr;
|
||||||
|
|
||||||
// If this is an external function pointer, we can force the JIT to
|
// If this is an external function pointer, we can force the JIT to
|
||||||
// 'compile' it, which really just adds it to the map. In dlsym mode,
|
// 'compile' it, which really just adds it to the map.
|
||||||
// external functions are forced through a stub, regardless of reloc type.
|
|
||||||
if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode() &&
|
if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode() &&
|
||||||
!MayNeedFarStub && !TheJIT->areDlsymStubsEnabled())
|
!MayNeedFarStub)
|
||||||
return TheJIT->getPointerToFunction(F);
|
return TheJIT->getPointerToFunction(F);
|
||||||
|
|
||||||
// Okay, the function has not been compiled yet, if the target callback
|
// Okay, the function has not been compiled yet, if the target callback
|
||||||
|
@ -1112,16 +1101,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
||||||
|
|
||||||
// If the target REALLY wants a stub for this function, emit it now.
|
// If the target REALLY wants a stub for this function, emit it now.
|
||||||
if (MR.mayNeedFarStub()) {
|
if (MR.mayNeedFarStub()) {
|
||||||
if (!TheJIT->areDlsymStubsEnabled()) {
|
|
||||||
ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
|
ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
|
||||||
} else {
|
|
||||||
void *&Stub = ExtFnStubs[MR.getExternalSymbol()];
|
|
||||||
if (!Stub) {
|
|
||||||
Stub = Resolver.getExternalFunctionStub((void *)&Stub);
|
|
||||||
AddStubToCurrentFunction(Stub);
|
|
||||||
}
|
|
||||||
ResultPtr = Stub;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (MR.isGlobalValue()) {
|
} else if (MR.isGlobalValue()) {
|
||||||
ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
|
ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
|
||||||
|
@ -1335,19 +1315,10 @@ void JITEmitter::deallocateMemForFunction(const Function *F) {
|
||||||
StubFnRefs.erase(Stub);
|
StubFnRefs.erase(Stub);
|
||||||
|
|
||||||
// Invalidate the stub. If it is a GV stub, update the JIT's global
|
// Invalidate the stub. If it is a GV stub, update the JIT's global
|
||||||
// mapping for that GV to zero, otherwise, search the string map of
|
// mapping for that GV to zero.
|
||||||
// external function names to stubs and remove the entry for this stub.
|
|
||||||
GlobalValue *GV = Resolver.invalidateStub(Stub);
|
GlobalValue *GV = Resolver.invalidateStub(Stub);
|
||||||
if (GV) {
|
if (GV) {
|
||||||
TheJIT->updateGlobalMapping(GV, 0);
|
TheJIT->updateGlobalMapping(GV, 0);
|
||||||
} else {
|
|
||||||
for (StringMapIterator<void*> i = ExtFnStubs.begin(),
|
|
||||||
e = ExtFnStubs.end(); i != e; ++i) {
|
|
||||||
if (i->second == Stub) {
|
|
||||||
ExtFnStubs.erase(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1588,92 +1559,6 @@ void JIT::updateFunctionStub(Function *F) {
|
||||||
getJITInfo().emitFunctionStubAtAddr(F, Addr, Stub, *getCodeEmitter());
|
getJITInfo().emitFunctionStubAtAddr(F, Addr, Stub, *getCodeEmitter());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// updateDlsymStubTable - Emit the data necessary to relocate the stubs
|
|
||||||
/// that were emitted during code generation.
|
|
||||||
///
|
|
||||||
void JIT::updateDlsymStubTable() {
|
|
||||||
assert(isa<JITEmitter>(JCE) && "Unexpected MCE?");
|
|
||||||
JITEmitter *JE = cast<JITEmitter>(getCodeEmitter());
|
|
||||||
|
|
||||||
SmallVector<GlobalValue*, 8> GVs;
|
|
||||||
SmallVector<void*, 8> Ptrs;
|
|
||||||
const StringMap<void *> &ExtFns = JE->getExternalFnStubs();
|
|
||||||
|
|
||||||
JE->getJITResolver().getRelocatableGVs(GVs, Ptrs);
|
|
||||||
|
|
||||||
unsigned nStubs = GVs.size() + ExtFns.size();
|
|
||||||
|
|
||||||
// If there are no relocatable stubs, return.
|
|
||||||
if (nStubs == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If there are no new relocatable stubs, return.
|
|
||||||
void *CurTable = JE->getMemMgr()->getDlsymTable();
|
|
||||||
if (CurTable && (*(unsigned *)CurTable == nStubs))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Calculate the size of the stub info
|
|
||||||
unsigned offset = 4 + 4 * nStubs + sizeof(intptr_t) * nStubs;
|
|
||||||
|
|
||||||
SmallVector<unsigned, 8> Offsets;
|
|
||||||
for (unsigned i = 0; i != GVs.size(); ++i) {
|
|
||||||
Offsets.push_back(offset);
|
|
||||||
offset += GVs[i]->getName().size() + 1;
|
|
||||||
}
|
|
||||||
for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
|
|
||||||
i != e; ++i) {
|
|
||||||
Offsets.push_back(offset);
|
|
||||||
offset += strlen(i->first()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate space for the new "stub", which contains the dlsym table.
|
|
||||||
JE->startGVStub(0, offset, 4);
|
|
||||||
|
|
||||||
// Emit the number of records
|
|
||||||
JE->emitInt32(nStubs);
|
|
||||||
|
|
||||||
// Emit the string offsets
|
|
||||||
for (unsigned i = 0; i != nStubs; ++i)
|
|
||||||
JE->emitInt32(Offsets[i]);
|
|
||||||
|
|
||||||
// Emit the pointers. Verify that they are at least 2-byte aligned, and set
|
|
||||||
// the low bit to 0 == GV, 1 == Function, so that the client code doing the
|
|
||||||
// relocation can write the relocated pointer at the appropriate place in
|
|
||||||
// the stub.
|
|
||||||
for (unsigned i = 0; i != GVs.size(); ++i) {
|
|
||||||
intptr_t Ptr = (intptr_t)Ptrs[i];
|
|
||||||
assert((Ptr & 1) == 0 && "Stub pointers must be at least 2-byte aligned!");
|
|
||||||
|
|
||||||
if (isa<Function>(GVs[i]))
|
|
||||||
Ptr |= (intptr_t)1;
|
|
||||||
|
|
||||||
if (sizeof(Ptr) == 8)
|
|
||||||
JE->emitInt64(Ptr);
|
|
||||||
else
|
|
||||||
JE->emitInt32(Ptr);
|
|
||||||
}
|
|
||||||
for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
|
|
||||||
i != e; ++i) {
|
|
||||||
intptr_t Ptr = (intptr_t)i->second | 1;
|
|
||||||
|
|
||||||
if (sizeof(Ptr) == 8)
|
|
||||||
JE->emitInt64(Ptr);
|
|
||||||
else
|
|
||||||
JE->emitInt32(Ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit the strings.
|
|
||||||
for (unsigned i = 0; i != GVs.size(); ++i)
|
|
||||||
JE->emitString(GVs[i]->getName());
|
|
||||||
for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
|
|
||||||
i != e; ++i)
|
|
||||||
JE->emitString(i->first());
|
|
||||||
|
|
||||||
// Tell the JIT memory manager where it is. The JIT Memory Manager will
|
|
||||||
// deallocate space for the old one, if one existed.
|
|
||||||
JE->getMemMgr()->SetDlsymTable(JE->finishGVStub(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// freeMachineCodeForFunction - release machine code memory for given Function.
|
/// freeMachineCodeForFunction - release machine code memory for given Function.
|
||||||
///
|
///
|
||||||
void JIT::freeMachineCodeForFunction(Function *F) {
|
void JIT::freeMachineCodeForFunction(Function *F) {
|
||||||
|
|
|
@ -296,7 +296,6 @@ namespace {
|
||||||
MemoryRangeHeader *CurBlock;
|
MemoryRangeHeader *CurBlock;
|
||||||
|
|
||||||
uint8_t *GOTBase; // Target Specific reserved memory
|
uint8_t *GOTBase; // Target Specific reserved memory
|
||||||
void *DlsymTable; // Stub external symbol information
|
|
||||||
public:
|
public:
|
||||||
DefaultJITMemoryManager();
|
DefaultJITMemoryManager();
|
||||||
~DefaultJITMemoryManager();
|
~DefaultJITMemoryManager();
|
||||||
|
@ -318,7 +317,6 @@ namespace {
|
||||||
static const size_t DefaultSizeThreshold;
|
static const size_t DefaultSizeThreshold;
|
||||||
|
|
||||||
void AllocateGOT();
|
void AllocateGOT();
|
||||||
void SetDlsymTable(void *);
|
|
||||||
|
|
||||||
// Testing methods.
|
// Testing methods.
|
||||||
virtual bool CheckInvariants(std::string &ErrorStr);
|
virtual bool CheckInvariants(std::string &ErrorStr);
|
||||||
|
@ -469,10 +467,6 @@ namespace {
|
||||||
return GOTBase;
|
return GOTBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getDlsymTable() const {
|
|
||||||
return DlsymTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocateBlock(void *Block) {
|
void deallocateBlock(void *Block) {
|
||||||
// Find the block that is allocated for this function.
|
// Find the block that is allocated for this function.
|
||||||
MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
|
MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
|
||||||
|
@ -599,7 +593,6 @@ DefaultJITMemoryManager::DefaultJITMemoryManager()
|
||||||
FreeMemoryList = Mem0;
|
FreeMemoryList = Mem0;
|
||||||
|
|
||||||
GOTBase = NULL;
|
GOTBase = NULL;
|
||||||
DlsymTable = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultJITMemoryManager::AllocateGOT() {
|
void DefaultJITMemoryManager::AllocateGOT() {
|
||||||
|
@ -608,10 +601,6 @@ void DefaultJITMemoryManager::AllocateGOT() {
|
||||||
HasGOT = true;
|
HasGOT = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultJITMemoryManager::SetDlsymTable(void *ptr) {
|
|
||||||
DlsymTable = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultJITMemoryManager::~DefaultJITMemoryManager() {
|
DefaultJITMemoryManager::~DefaultJITMemoryManager() {
|
||||||
for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i)
|
for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i)
|
||||||
sys::Memory::ReleaseRWX(CodeSlabs[i]);
|
sys::Memory::ReleaseRWX(CodeSlabs[i]);
|
||||||
|
|
|
@ -68,8 +68,6 @@ public:
|
||||||
virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); }
|
virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); }
|
||||||
virtual void AllocateGOT() { Base->AllocateGOT(); }
|
virtual void AllocateGOT() { Base->AllocateGOT(); }
|
||||||
virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); }
|
virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); }
|
||||||
virtual void SetDlsymTable(void *ptr) { Base->SetDlsymTable(ptr); }
|
|
||||||
virtual void *getDlsymTable() const { return Base->getDlsymTable(); }
|
|
||||||
struct StartFunctionBodyCall {
|
struct StartFunctionBodyCall {
|
||||||
StartFunctionBodyCall(uint8_t *Result, const Function *F,
|
StartFunctionBodyCall(uint8_t *Result, const Function *F,
|
||||||
uintptr_t ActualSize, uintptr_t ActualSizeResult)
|
uintptr_t ActualSize, uintptr_t ActualSizeResult)
|
||||||
|
@ -303,7 +301,6 @@ TEST_F(JITTest, FarCallToKnownFunction) {
|
||||||
ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
|
ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
|
||||||
Builder.CreateRet(result);
|
Builder.CreateRet(result);
|
||||||
|
|
||||||
TheJIT->EnableDlsymStubs(false);
|
|
||||||
TheJIT->DisableLazyCompilation(true);
|
TheJIT->DisableLazyCompilation(true);
|
||||||
int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
|
int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
|
||||||
(intptr_t)TheJIT->getPointerToFunction(TestFunction));
|
(intptr_t)TheJIT->getPointerToFunction(TestFunction));
|
||||||
|
|
Loading…
Reference in New Issue