Index: include/llvm/Support/DynamicLibrary.h =================================================================== --- include/llvm/Support/DynamicLibrary.h +++ include/llvm/Support/DynamicLibrary.h @@ -93,9 +93,17 @@ /// that symbol is returned. If not, null is returned. Note that this will /// search permanently loaded libraries (getPermanentLibrary()) as well /// as explicitly registered symbols (AddSymbol()). + /// /// @throws std::string on error. /// @brief Search through libraries for address of a symbol - static void *SearchForAddressOfSymbol(const char *symbolName); + /// \param LongSearch On Unix it is possible to use addPermanentLibrary + /// to load a library handle that has been opened with RTLD_LOCAL. In this + /// case passing true for LongSearch will allow the symbol to be found. + /// This avoids a 2x penalty for symbol lookup in more common cases where + /// RTLD_LOCAL has not been used or if DynamicLibrary::getPermanentLibrary + /// is solely used to load libraries. + static void *SearchForAddressOfSymbol(const char *SymbolName, + bool LongSearch = false); /// @brief Convenience function for C++ophiles. static void *SearchForAddressOfSymbol(const std::string &symbolName) { Index: lib/Support/DynamicLibrary.cpp =================================================================== --- lib/Support/DynamicLibrary.cpp +++ lib/Support/DynamicLibrary.cpp @@ -73,21 +73,32 @@ return true; } - void *Lookup(const char *Symbol) { + void *Lookup(const char *Symbol, bool LongSearch) { // Process handle gets first try. if (Process) { if (void *Ptr = DLSym(Process, Symbol)) return Ptr; + +#ifdef LLVM_ON_WIN32 + // On Windows all loaded modules will have been searched at this point. + // Double check in Debug builds then exit. #ifndef NDEBUG for (void *Handle : Handles) assert(!DLSym(Handle, Symbol) && "Symbol exists in non process handle"); #endif - } 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 nullptr; +#else + // On Unix there is a possibility of a Handles containing a library opened + // with RTLD_LOCAL and having it's symbols hidden from lookup via dlsym + if (!LongSearch) + return nullptr; +#endif + } + + // 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 nullptr; } @@ -151,7 +162,8 @@ return HandleSet::DLSym(Data, SymbolName); } -void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { +void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName, + bool LongSearch) { { SmartScopedLock Lock(*SymbolsMutex); @@ -165,7 +177,7 @@ // Now search the libraries. if (OpenedHandles.isConstructed()) { - if (void *Ptr = OpenedHandles->Lookup(SymbolName)) + if (void *Ptr = OpenedHandles->Lookup(SymbolName, LongSearch)) return Ptr; } }