Index: include/llvm/Support/DynamicLibrary.h =================================================================== --- include/llvm/Support/DynamicLibrary.h +++ include/llvm/Support/DynamicLibrary.h @@ -65,8 +65,19 @@ /// /// It is safe to call this function multiple times for the same library. /// @brief Open a dynamic library permanently. - static DynamicLibrary getPermanentLibrary(const char *filename, - std::string *errMsg = nullptr); + /// @param Filename The path to the library. + /// @param ErrMsg Any error encountered will be stored here. + /// @param RTLocal Open with RTLD_LOCAL flag on platforms supporting dlopen, + /// otherwise ignored. + static DynamicLibrary getPermanentLibrary(const char *Filename, + std::string *ErrMsg = nullptr, + bool RTLocal = false); + + /// @brief Convenience function for using RTLocal without error reporting. + static DynamicLibrary getPermanentLibrary(const char *Filename, + bool RTLocal) { + return getPermanentLibrary(Filename, nullptr, RTLocal); + } /// Registers an externally loaded library. The library will be unloaded /// when the program terminates. Index: lib/Support/DynamicLibrary.cpp =================================================================== --- lib/Support/DynamicLibrary.cpp +++ lib/Support/DynamicLibrary.cpp @@ -33,7 +33,7 @@ void *Process; public: - static void *DLOpen(const char *Filename, std::string *Err); + static void *DLOpen(const char *Filename, std::string *Err, bool Local); static void DLClose(void *Handle); static void *DLSym(void *Handle, const char *Symbol); @@ -141,12 +141,12 @@ } DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, - std::string *Err) { + std::string *Err, bool Lcl) { // Force OpenedHandles to be added into the ManagedStatic list before any // ManagedStatic can be added from static constructors in HandleSet::DLOpen. HandleSet& HS = *OpenedHandles; - void *Handle = HandleSet::DLOpen(FileName, Err); + void *Handle = HandleSet::DLOpen(FileName, Err, Lcl); if (Handle != &Invalid) { SmartScopedLock Lock(*SymbolsMutex); HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); Index: lib/Support/Unix/DynamicLibrary.inc =================================================================== --- lib/Support/Unix/DynamicLibrary.inc +++ lib/Support/Unix/DynamicLibrary.inc @@ -25,10 +25,12 @@ DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker; } -void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) { - void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL); +void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err, + bool Local) { + void *Handle = ::dlopen(File, RTLD_LAZY | (Local ? RTLD_LOCAL : RTLD_GLOBAL)); if (!Handle) { - if (Err) *Err = ::dlerror(); + if (Err) + *Err = ::dlerror(); return &DynamicLibrary::Invalid; } Index: lib/Support/Windows/DynamicLibrary.inc =================================================================== --- lib/Support/Windows/DynamicLibrary.inc +++ lib/Support/Windows/DynamicLibrary.inc @@ -32,7 +32,8 @@ 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, + bool /*Local*/) { // Create the instance and return it to be the *Process* handle // simillar to dlopen(NULL, RTLD_LAZY|RTLD_GLOBAL) if (!File) Index: unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp =================================================================== --- unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp +++ unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp @@ -58,12 +58,12 @@ std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; } -TEST(DynamicLibrary, Overload) { +static void TestOverload(bool RTLocal = false) { { std::string Err; llvm_shutdown_obj Shutdown; DynamicLibrary DL = - DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); + DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err, RTLocal); EXPECT_TRUE(DL.isValid()); EXPECT_TRUE(Err.empty()); @@ -88,11 +88,37 @@ EXPECT_TRUE(GS != nullptr && GS == &TestA); EXPECT_EQ(StdString(GS()), "ProcessCall"); - // Test overloading by forcing library priority when searching for a symbol - DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedFirst; - GS = FuncPtr(DynamicLibrary::SearchForAddressOfSymbol("TestA")); - EXPECT_TRUE(GS != nullptr && GS != &TestA); - EXPECT_EQ(StdString(GS()), "LibCall"); + // Test overloading by forcing a priority when searching for a symbol + if (RTLocal) { + // SetStrings un-resolved because RTLocal + SetStrings SS = FuncPtr( + DynamicLibrary::SearchForAddressOfSymbol("SetStrings")); + EXPECT_TRUE(SS == nullptr); + + DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedLast; + + // SetStrings now resolved because SO_LoadedLast + SS = FuncPtr( + DynamicLibrary::SearchForAddressOfSymbol("SetStrings")); + EXPECT_TRUE(SS != nullptr); + + // TestA resolved from Process first + GS = FuncPtr(DynamicLibrary::SearchForAddressOfSymbol("TestA")); + EXPECT_TRUE(GS != nullptr && GS == &TestA); + EXPECT_EQ(StdString(GS()), "ProcessCall"); + } else { + // SetStrings resolved because DynamicLibrary::getPermanentLibrary(nullptr) + SetStrings SS = FuncPtr( + DynamicLibrary::SearchForAddressOfSymbol("SetStrings")); + EXPECT_TRUE(SS != nullptr); + + DynamicLibrary::SearchOrder = DynamicLibrary::SO_LoadedFirst; + + // TestA resolved from Library first + GS = FuncPtr(DynamicLibrary::SearchForAddressOfSymbol("TestA")); + EXPECT_TRUE(GS != nullptr && GS != &TestA); + EXPECT_EQ(StdString(GS()), "LibCall"); + } DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA)); GS = FuncPtr(DL.getAddressOfSymbol("TestA")); @@ -109,6 +135,16 @@ EXPECT_TRUE(DynamicLibrary::SearchOrder == DynamicLibrary::SO_Linker); } +TEST(DynamicLibrary, Overload) { + TestOverload(); +} + +#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) +TEST(DynamicLibrary, RTLocal) { + TestOverload(true); +} +#endif + TEST(DynamicLibrary, Shutdown) { std::string A, B; {