forked from OSchip/llvm-project
Allow clients to specify search order of DynamicLibraries.
Summary: Different JITs and other clients of LLVM may have different needs in how symbol resolution should occur. Reviewers: v.g.vassilev, lhames, karies Reviewed By: v.g.vassilev Subscribers: pcanal, llvm-commits Differential Revision: https://reviews.llvm.org/D33529 llvm-svn: 307849
This commit is contained in:
parent
5680b0ca9f
commit
5fdd2cbae8
|
@ -88,6 +88,22 @@ namespace sys {
|
||||||
return !getPermanentLibrary(Filename, ErrMsg).isValid();
|
return !getPermanentLibrary(Filename, ErrMsg).isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SearchOrdering {
|
||||||
|
/// SO_Linker - Search as a call to dlsym(dlopen(NULL)) would when
|
||||||
|
/// DynamicLibrary::getPermanentLibrary(NULL) has been called or
|
||||||
|
/// search the list of explcitly loaded symbols if not.
|
||||||
|
SO_Linker,
|
||||||
|
/// SO_LoadedFirst - Search all loaded libraries, then as SO_Linker would.
|
||||||
|
SO_LoadedFirst,
|
||||||
|
/// SO_LoadedLast - Search as SO_Linker would, then loaded libraries.
|
||||||
|
/// Only useful to search if libraries with RTLD_LOCAL have been added.
|
||||||
|
SO_LoadedLast,
|
||||||
|
/// SO_LoadOrder - Or this in to search libraries in the ordered loaded.
|
||||||
|
/// The default bahaviour is to search loaded libraries in reverse.
|
||||||
|
SO_LoadOrder = 4
|
||||||
|
};
|
||||||
|
static SearchOrdering SearchOrder; // = SO_Linker
|
||||||
|
|
||||||
/// This function will search through all previously loaded dynamic
|
/// This function will search through all previously loaded dynamic
|
||||||
/// libraries for the symbol \p symbolName. If it is found, the address of
|
/// libraries for the symbol \p symbolName. If it is found, the address of
|
||||||
/// that symbol is returned. If not, null is returned. Note that this will
|
/// that symbol is returned. If not, null is returned. Note that this will
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "llvm/Support/DynamicLibrary.h"
|
#include "llvm/Support/DynamicLibrary.h"
|
||||||
#include "llvm-c/Support.h"
|
#include "llvm-c/Support.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
#include "llvm/Config/config.h"
|
#include "llvm/Config/config.h"
|
||||||
#include "llvm/Support/ManagedStatic.h"
|
#include "llvm/Support/ManagedStatic.h"
|
||||||
|
@ -73,19 +74,37 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Lookup(const char *Symbol) {
|
void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
|
||||||
// Process handle gets first try.
|
if (Order & SO_LoadOrder) {
|
||||||
|
for (void *Handle : Handles) {
|
||||||
|
if (void *Ptr = DLSym(Handle, Symbol))
|
||||||
|
return Ptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (void *Handle : llvm::reverse(Handles)) {
|
||||||
|
if (void *Ptr = DLSym(Handle, Symbol))
|
||||||
|
return Ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
|
||||||
|
assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
|
||||||
|
"Invalid Ordering");
|
||||||
|
|
||||||
|
if (!Process || (Order & SO_LoadedFirst)) {
|
||||||
|
if (void *Ptr = LibLookup(Symbol, Order))
|
||||||
|
return Ptr;
|
||||||
|
}
|
||||||
if (Process) {
|
if (Process) {
|
||||||
|
// Use OS facilities to search the current binary and all loaded libs.
|
||||||
if (void *Ptr = DLSym(Process, Symbol))
|
if (void *Ptr = DLSym(Process, Symbol))
|
||||||
return Ptr;
|
return Ptr;
|
||||||
#ifndef NDEBUG
|
|
||||||
for (void *Handle : Handles)
|
// Search any libs that might have been skipped because of RTLD_LOCAL.
|
||||||
assert(!DLSym(Handle, Symbol) && "Symbol exists in non process handle");
|
if (Order & SO_LoadedLast) {
|
||||||
#endif
|
if (void *Ptr = LibLookup(Symbol, Order))
|
||||||
} else {
|
|
||||||
// Iterate in reverse, so newer libraries/symbols override older.
|
|
||||||
for (auto &&I = Handles.rbegin(), E = Handles.rend(); I != E; ++I) {
|
|
||||||
if (void *Ptr = DLSym(*I, Symbol))
|
|
||||||
return Ptr;
|
return Ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,6 +132,8 @@ static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char DynamicLibrary::Invalid;
|
char DynamicLibrary::Invalid;
|
||||||
|
DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
|
||||||
|
DynamicLibrary::SO_Linker;
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
|
void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
|
||||||
|
@ -170,7 +191,7 @@ void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
|
||||||
|
|
||||||
// Now search the libraries.
|
// Now search the libraries.
|
||||||
if (OpenedHandles.isConstructed()) {
|
if (OpenedHandles.isConstructed()) {
|
||||||
if (void *Ptr = OpenedHandles->Lookup(SymbolName))
|
if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
|
||||||
return Ptr;
|
return Ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ DynamicLibrary::HandleSet::~HandleSet() {
|
||||||
::dlclose(Handle);
|
::dlclose(Handle);
|
||||||
if (Process)
|
if (Process)
|
||||||
::dlclose(Process);
|
::dlclose(Process);
|
||||||
|
|
||||||
|
// llvm_shutdown called, Return to default
|
||||||
|
DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
|
void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
|
||||||
|
|
|
@ -28,6 +28,8 @@ DynamicLibrary::HandleSet::~HandleSet() {
|
||||||
|
|
||||||
// 'Process' should not be released on Windows.
|
// 'Process' should not be released on Windows.
|
||||||
assert((!Process || Process==this) && "Bad Handle");
|
assert((!Process || Process==this) && "Bad Handle");
|
||||||
|
// llvm_shutdown called, Return to default
|
||||||
|
DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
|
void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ TEST(DynamicLibrary, Overload) {
|
||||||
EXPECT_TRUE(DL.isValid());
|
EXPECT_TRUE(DL.isValid());
|
||||||
EXPECT_TRUE(Err.empty());
|
EXPECT_TRUE(Err.empty());
|
||||||
|
|
||||||
|
// Test overloading local symbols does not occur by default
|
||||||
GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
|
GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
|
||||||
EXPECT_TRUE(GS != nullptr && GS == &TestA);
|
EXPECT_TRUE(GS != nullptr && GS == &TestA);
|
||||||
EXPECT_EQ(StdString(GS()), "ProcessCall");
|
EXPECT_EQ(StdString(GS()), "ProcessCall");
|
||||||
|
@ -85,6 +86,12 @@ TEST(DynamicLibrary, Overload) {
|
||||||
EXPECT_TRUE(GS != nullptr && GS == &TestA);
|
EXPECT_TRUE(GS != nullptr && GS == &TestA);
|
||||||
EXPECT_EQ(StdString(GS()), "ProcessCall");
|
EXPECT_EQ(StdString(GS()), "ProcessCall");
|
||||||
|
|
||||||
|
// Test overloading by forcing library priority when searching for a symbol
|
||||||
|
DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedFirst;
|
||||||
|
GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
|
||||||
|
EXPECT_TRUE(GS != nullptr && GS != &TestA);
|
||||||
|
EXPECT_EQ(StdString(GS()), "LibCall");
|
||||||
|
|
||||||
DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));
|
DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));
|
||||||
GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
|
GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
|
||||||
EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA);
|
EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA);
|
||||||
|
@ -95,6 +102,9 @@ TEST(DynamicLibrary, Overload) {
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol(
|
EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol(
|
||||||
"TestA")) == nullptr);
|
"TestA")) == nullptr);
|
||||||
|
|
||||||
|
// Check serach ordering is reset to default after call to llvm_shutdown
|
||||||
|
EXPECT_TRUE(DynamicLibrary::SearchOrder == DynamicLibrary::SO_Linker);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DynamicLibrary, Shutdown) {
|
TEST(DynamicLibrary, Shutdown) {
|
||||||
|
|
Loading…
Reference in New Issue