Index: include/llvm/ExecutionEngine/RTDyldMemoryManager.h =================================================================== --- include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -17,6 +17,7 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm-c/ExecutionEngine.h" #include #include @@ -57,8 +58,12 @@ // for the varying types of objects to be allocated. class RTDyldMemoryManager : public MCJITMemoryManager, public JITSymbolResolver { +protected: + sys::DynamicLibrary::SearchOrder SearchOrder; public: - RTDyldMemoryManager() = default; + RTDyldMemoryManager( + sys::DynamicLibrary::SearchOrder SO = sys::DynamicLibrary::SO_Linker) + : SearchOrder(SO) {} RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; void operator=(const RTDyldMemoryManager&) = delete; ~RTDyldMemoryManager() override; @@ -69,19 +74,25 @@ /// Deregister EH frames in the current proces. static void deregisterEHFramesInProcess(uint8_t *Addr, size_t Size); + void setSymbolResolutionOrder(sys::DynamicLibrary::SearchOrder SO) { + SearchOrder = SO; + } + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; void deregisterEHFrames() override; /// This method returns the address of the specified function or variable in /// the current process. - static uint64_t getSymbolAddressInProcess(const std::string &Name); + static uint64_t getSymbolAddressInProcess( + const std::string &Name, + sys::DynamicLibrary::SearchOrder SO = sys::DynamicLibrary::SO_Linker); /// Legacy symbol lookup - DEPRECATED! Please override findSymbol instead. /// /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. virtual uint64_t getSymbolAddress(const std::string &Name) { - return getSymbolAddressInProcess(Name); + return getSymbolAddressInProcess(Name, SearchOrder); } /// This method returns a RuntimeDyld::SymbolInfo for the specified function Index: include/llvm/ExecutionEngine/SectionMemoryManager.h =================================================================== --- include/llvm/ExecutionEngine/SectionMemoryManager.h +++ include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -40,7 +40,9 @@ /// directly. Clients of MCJIT should call MCJIT::finalizeObject. class SectionMemoryManager : public RTDyldMemoryManager { public: - SectionMemoryManager() = default; + SectionMemoryManager( + sys::DynamicLibrary::SearchOrder SO = sys::DynamicLibrary::SO_Linker) + : RTDyldMemoryManager(SO) {} SectionMemoryManager(const SectionMemoryManager&) = delete; void operator=(const SectionMemoryManager&) = delete; ~SectionMemoryManager() override; Index: include/llvm/Support/DynamicLibrary.h =================================================================== --- include/llvm/Support/DynamicLibrary.h +++ include/llvm/Support/DynamicLibrary.h @@ -88,6 +88,17 @@ return !getPermanentLibrary(Filename, ErrMsg).isValid(); } + enum SearchOrder { + /// 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 usefull to search libraries with RTLD_LOCAL have been added. + SO_LoadedLast, + }; /// This function will search through all previously loaded dynamic /// 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 @@ -95,11 +106,13 @@ /// 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); + static void *SearchForAddressOfSymbol(const char *SymbolName, + SearchOrder SO = SO_Linker); /// @brief Convenience function for C++ophiles. - static void *SearchForAddressOfSymbol(const std::string &symbolName) { - return SearchForAddressOfSymbol(symbolName.c_str()); + static void *SearchForAddressOfSymbol(const std::string &symbolName, + SearchOrder SO = SO_Linker) { + return SearchForAddressOfSymbol(symbolName.c_str(), SO); } /// This functions permanently adds the symbol \p symbolName with the Index: lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -225,11 +225,11 @@ extern "C" LLVM_ATTRIBUTE_WEAK void __morestack(); #endif -uint64_t -RTDyldMemoryManager::getSymbolAddressInProcess(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. +uint64_t RTDyldMemoryManager::getSymbolAddressInProcess( + const std::string &Name, sys::DynamicLibrary::SearchOrder SO) { +// 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__) && defined(__GLIBC__) //===--------------------------------------------------------------------===// // Function stubs that are invoked instead of certain library calls @@ -284,7 +284,7 @@ ++NameStr; #endif - return (uint64_t)sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + return (uint64_t)sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr, SO); } void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name, Index: lib/Support/DynamicLibrary.cpp =================================================================== --- lib/Support/DynamicLibrary.cpp +++ lib/Support/DynamicLibrary.cpp @@ -74,18 +74,27 @@ } void *Lookup(const char *Symbol) { - // Process handle gets first try. + // 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; + } + + void *Lookup(const char *Symbol, DynamicLibrary::SearchOrder Order) { + if (!Process || Order == DynamicLibrary::SO_LoadedFirst) { + if (void *Ptr = Lookup(Symbol)) + return Ptr; + } if (Process) { + // Use OS facilities to search the current binary and all loaded libs. if (void *Ptr = DLSym(Process, Symbol)) return Ptr; -#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)) + + // Search any libs that might have been skipped because of RTLD_LOCAL. + if (Order == DynamicLibrary::SO_LoadedLast) { + if (void *Ptr = Lookup(Symbol)) return Ptr; } } @@ -151,7 +160,8 @@ return HandleSet::DLSym(Data, SymbolName); } -void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { +void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName, + SearchOrder Order) { { SmartScopedLock Lock(*SymbolsMutex); @@ -165,7 +175,7 @@ // Now search the libraries. if (OpenedHandles.isConstructed()) { - if (void *Ptr = OpenedHandles->Lookup(SymbolName)) + if (void *Ptr = OpenedHandles->Lookup(SymbolName, Order)) return Ptr; } }