[llvm] r301240 - Revert "Refactor DynamicLibrary so searching for a symbol will have a defined order"
Bill Seurer via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 25 13:00:26 PDT 2017
It looks like this revision may be causing a test case failure on
ppc64le:
http://lab.llvm.org:8011/builders/clang-ppc64le-linux-multistage/builds/2053
******************** TEST 'LLVM-Unit ::
Support/DynamicLibrary/DynamicLibraryTests/DynamicLibrary.Shutdown'
FAILED ********************
Note: Google Test filter = DynamicLibrary.Shutdown
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from DynamicLibrary
[ RUN ] DynamicLibrary.Shutdown
/home/buildbots/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp:117:
Failure
Expected: A
Which is: ""
To be equal to: "Global::~Global"
/home/buildbots/ppc64le-clang-multistage-test/clang-ppc64le-multistage/llvm/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp:118:
Failure
Expected: B
Which is: "Local::Local"
To be equal to: "Local::~Local"
[ FAILED ] DynamicLibrary.Shutdown (11 ms)
[----------] 1 test from DynamicLibrary (11 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (11 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] DynamicLibrary.Shutdown
1 FAILED TEST
I haven't been able to reproduce this on another machine, though.
On 04/24/2017 03:16 PM, Frederich Munch via llvm-commits wrote:
> Author: marsupial
> Date: Mon Apr 24 15:16:01 2017
> New Revision: 301240
>
> URL: http://llvm.org/viewvc/llvm-project?rev=301240&view=rev
> Log:
> Revert "Refactor DynamicLibrary so searching for a symbol will have a defined order"
> The i686-mingw32-RA-on-linux bot is still having errors.
>
> This reverts commit r301236.
>
> Added:
> llvm/trunk/lib/Support/SearchForAddressOfSpecialSymbol.cpp
> Removed:
> llvm/trunk/lib/Support/Unix/DynamicLibrary.inc
> llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt
> llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
> llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx
> llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h
> Modified:
> llvm/trunk/include/llvm/Support/DynamicLibrary.h
> llvm/trunk/lib/Support/CMakeLists.txt
> llvm/trunk/lib/Support/DynamicLibrary.cpp
> llvm/trunk/lib/Support/Windows/DynamicLibrary.inc
> llvm/trunk/unittests/Support/CMakeLists.txt
>
> Modified: llvm/trunk/include/llvm/Support/DynamicLibrary.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/DynamicLibrary.h?rev=301240&r1=301239&r2=301240&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/DynamicLibrary.h (original)
> +++ llvm/trunk/include/llvm/Support/DynamicLibrary.h Mon Apr 24 15:16:01 2017
> @@ -58,7 +58,7 @@ namespace sys {
> void *getAddressOfSymbol(const char *symbolName);
>
> /// This function permanently loads the dynamic library at the given path.
> - /// The library will only be unloaded when llvm_shutdown() is called.
> + /// The library will only be unloaded when the program terminates.
> /// This returns a valid DynamicLibrary instance on success and an invalid
> /// instance on failure (see isValid()). \p *errMsg will only be modified
> /// if the library fails to load.
> @@ -71,8 +71,7 @@ namespace sys {
> /// Registers an externally loaded library. The library will be unloaded
> /// when the program terminates.
> ///
> - /// It is safe to call this function multiple times for the same library,
> - /// though ownership is only taken if there was no error.
> + /// It is safe to call this function multiple times for the same library.
> ///
> /// \returns An empty \p DynamicLibrary if the library was already loaded.
> static DynamicLibrary addPermanentLibrary(void *handle,
> @@ -107,8 +106,6 @@ namespace sys {
> /// libraries.
> /// @brief Add searchable symbol/value pair.
> static void AddSymbol(StringRef symbolName, void *symbolValue);
> -
> - class HandleSet;
> };
>
> } // End sys namespace
>
> Modified: llvm/trunk/lib/Support/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=301240&r1=301239&r2=301240&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Support/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Support/CMakeLists.txt Mon Apr 24 15:16:01 2017
> @@ -130,6 +130,7 @@ add_llvm_library(LLVMSupport
> Process.cpp
> Program.cpp
> RWMutex.cpp
> + SearchForAddressOfSpecialSymbol.cpp
> Signals.cpp
> TargetRegistry.cpp
> ThreadLocal.cpp
>
> Modified: llvm/trunk/lib/Support/DynamicLibrary.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/DynamicLibrary.cpp?rev=301240&r1=301239&r2=301240&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Support/DynamicLibrary.cpp (original)
> +++ llvm/trunk/lib/Support/DynamicLibrary.cpp Mon Apr 24 15:16:01 2017
> @@ -20,164 +20,169 @@
> #include "llvm/Support/Mutex.h"
> #include <cstdio>
> #include <cstring>
> -#include <vector>
>
> -using namespace llvm;
> -using namespace llvm::sys;
> +// Collection of symbol name/value pairs to be searched prior to any libraries.
> +static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols;
> +static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex;
>
> -// All methods for HandleSet should be used holding SymbolsMutex.
> -class DynamicLibrary::HandleSet {
> - typedef std::vector<void *> HandleList;
> - HandleList Handles;
> - void *Process;
> +void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
> + void *symbolValue) {
> + SmartScopedLock<true> lock(*SymbolsMutex);
> + (*ExplicitSymbols)[symbolName] = symbolValue;
> +}
>
> -public:
> - static void *DLOpen(const char *Filename, std::string *Err);
> - static void DLClose(void *Handle);
> - static void *DLSym(void *Handle, const char *Symbol);
> +char llvm::sys::DynamicLibrary::Invalid = 0;
>
> - HandleSet() : Process(nullptr) {}
> - ~HandleSet();
> +#ifdef LLVM_ON_WIN32
>
> - HandleList::iterator Find(void *Handle) {
> - return std::find(Handles.begin(), Handles.end(), Handle);
> - }
> +#include "Windows/DynamicLibrary.inc"
> +
> +#else
>
> - bool Contains(void *Handle) {
> - return Handle == Process || Find(Handle) != Handles.end();
> +#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
> +#include <dlfcn.h>
> +using namespace llvm;
> +using namespace llvm::sys;
> +
> +//===----------------------------------------------------------------------===//
> +//=== WARNING: Implementation here must contain only TRULY operating system
> +//=== independent code.
> +//===----------------------------------------------------------------------===//
> +
> +static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles;
> +
> +DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
> + std::string *errMsg) {
> + SmartScopedLock<true> lock(*SymbolsMutex);
> +
> + void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
> + if (!handle) {
> + if (errMsg) *errMsg = dlerror();
> + return DynamicLibrary();
> }
>
> - bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
> -#ifdef LLVM_ON_WIN32
> - assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
> +#ifdef __CYGWIN__
> + // Cygwin searches symbols only in the main
> + // with the handle of dlopen(NULL, RTLD_GLOBAL).
> + if (!filename)
> + handle = RTLD_DEFAULT;
> #endif
>
> - if (LLVM_LIKELY(!IsProcess)) {
> - if (Find(Handle) != Handles.end()) {
> - if (CanClose)
> - DLClose(Handle);
> - return false;
> - }
> - Handles.push_back(Handle);
> - } else {
> -#ifndef LLVM_ON_WIN32
> - if (Process) {
> - if (CanClose)
> - DLClose(Process);
> - if (Process == Handle)
> - return false;
> - }
> -#endif
> - Process = Handle;
> - }
> - return true;
> - }
> + // If we've already loaded this library, dlclose() the handle in order to
> + // keep the internal refcount at +1.
> + if (!OpenedHandles->insert(handle).second)
> + dlclose(handle);
>
> - void *Lookup(const char *Symbol) {
> - // Process handle gets first try.
> - if (Process) {
> - 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))
> - return Ptr;
> - }
> - }
> - return nullptr;
> + return DynamicLibrary(handle);
> +}
> +
> +DynamicLibrary DynamicLibrary::addPermanentLibrary(void *handle,
> + std::string *errMsg) {
> + SmartScopedLock<true> lock(*SymbolsMutex);
> + // If we've already loaded this library, tell the caller.
> + if (!OpenedHandles->insert(handle).second) {
> + if (errMsg) *errMsg = "Library already loaded";
> + return DynamicLibrary();
> }
> -};
>
> -namespace {
> -// Collection of symbol name/value pairs to be searched prior to any libraries.
> -static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
> -// Collection of known library handles.
> -static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
> -// Lock for ExplicitSymbols and OpenedHandles.
> -static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
> + return DynamicLibrary(handle);
> }
>
> -#ifdef LLVM_ON_WIN32
> -
> -#include "Windows/DynamicLibrary.inc"
> +void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
> + if (!isValid())
> + return nullptr;
> + return dlsym(Data, symbolName);
> +}
>
> #else
>
> -#include "Unix/DynamicLibrary.inc"
> -
> -#endif
> -
> -char DynamicLibrary::Invalid;
> +using namespace llvm;
> +using namespace llvm::sys;
>
> -namespace llvm {
> -void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
> - return DoSearch(SymbolName); // DynamicLibrary.inc
> -}
> +DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
> + std::string *errMsg) {
> + if (errMsg) *errMsg = "dlopen() not supported on this platform";
> + return DynamicLibrary();
> }
>
> -void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
> - SmartScopedLock<true> Lock(*SymbolsMutex);
> - (*ExplicitSymbols)[SymbolName] = SymbolValue;
> +void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
> + return NULL;
> }
>
> -DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
> - std::string *Err) {
> - SmartScopedLock<true> Lock(*SymbolsMutex);
> - void *Handle = HandleSet::DLOpen(FileName, Err);
> - if (Handle != &Invalid)
> - OpenedHandles->AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
> +#endif
>
> - return DynamicLibrary(Handle);
> +namespace llvm {
> +void *SearchForAddressOfSpecialSymbol(const char* symbolName);
> }
>
> -DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
> - std::string *Err) {
> +void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
> SmartScopedLock<true> Lock(*SymbolsMutex);
> - // If we've already loaded this library, tell the caller.
> - if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
> - *Err = "Library already loaded";
> -
> - return DynamicLibrary(Handle);
> -}
> -
> -void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
> - if (!isValid())
> - return nullptr;
> - return HandleSet::DLSym(Data, SymbolName);
> -}
>
> -void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
> - {
> - SmartScopedLock<true> Lock(*SymbolsMutex);
> + // First check symbols added via AddSymbol().
> + if (ExplicitSymbols.isConstructed()) {
> + StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
>
> - // First check symbols added via AddSymbol().
> - if (ExplicitSymbols.isConstructed()) {
> - StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
> + if (i != ExplicitSymbols->end())
> + return i->second;
> + }
>
> - if (i != ExplicitSymbols->end())
> - return i->second;
> +#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
> + // Now search the libraries.
> + if (OpenedHandles.isConstructed()) {
> + for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
> + E = OpenedHandles->end(); I != E; ++I) {
> + //lt_ptr ptr = lt_dlsym(*I, symbolName);
> + void *ptr = dlsym(*I, symbolName);
> + if (ptr) {
> + return ptr;
> + }
> }
> + }
> +#endif
>
> - // Now search the libraries.
> - if (OpenedHandles.isConstructed()) {
> - if (void *Ptr = OpenedHandles->Lookup(SymbolName))
> - return Ptr;
> - }
> + if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
> + return Result;
> +
> +// This macro returns the address of a well-known, explicit symbol
> +#define EXPLICIT_SYMBOL(SYM) \
> + if (!strcmp(symbolName, #SYM)) return &SYM
> +
> +// On linux we have a weird situation. The stderr/out/in symbols are both
> +// macros and global variables because of standards requirements. So, we
> +// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
> +#if defined(__linux__) and !defined(__ANDROID__)
> + {
> + EXPLICIT_SYMBOL(stderr);
> + EXPLICIT_SYMBOL(stdout);
> + EXPLICIT_SYMBOL(stdin);
> }
> +#else
> + // For everything else, we want to check to make sure the symbol isn't defined
> + // as a macro before using EXPLICIT_SYMBOL.
> + {
> +#ifndef stdin
> + EXPLICIT_SYMBOL(stdin);
> +#endif
> +#ifndef stdout
> + EXPLICIT_SYMBOL(stdout);
> +#endif
> +#ifndef stderr
> + EXPLICIT_SYMBOL(stderr);
> +#endif
> + }
> +#endif
> +#undef EXPLICIT_SYMBOL
>
> - return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
> + return nullptr;
> }
>
> +#endif // LLVM_ON_WIN32
> +
> //===----------------------------------------------------------------------===//
> // C API.
> //===----------------------------------------------------------------------===//
>
> -LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
> +LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
> return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
> }
>
>
> Added: llvm/trunk/lib/Support/SearchForAddressOfSpecialSymbol.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/SearchForAddressOfSpecialSymbol.cpp?rev=301240&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Support/SearchForAddressOfSpecialSymbol.cpp (added)
> +++ llvm/trunk/lib/Support/SearchForAddressOfSpecialSymbol.cpp Mon Apr 24 15:16:01 2017
> @@ -0,0 +1,58 @@
> +//===- SearchForAddressOfSpecialSymbol.cpp - Function addresses -*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file pulls the addresses of certain symbols out of the linker. It must
> +// include as few header files as possible because it declares the symbols as
> +// void*, which would conflict with the actual symbol type if any header
> +// declared it.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include <string.h>
> +
> +// Must declare the symbols in the global namespace.
> +static void *DoSearch(const char* symbolName) {
> +#define EXPLICIT_SYMBOL(SYM) \
> + extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
> +
> + // If this is darwin, it has some funky issues, try to solve them here. Some
> + // important symbols are marked 'private external' which doesn't allow
> + // SearchForAddressOfSymbol to find them. As such, we special case them here,
> + // there is only a small handful of them.
> +
> +#ifdef __APPLE__
> + {
> + // __eprintf is sometimes used for assert() handling on x86.
> + //
> + // FIXME: Currently disabled when using Clang, as we don't always have our
> + // runtime support libraries available.
> +#ifndef __clang__
> +#ifdef __i386__
> + EXPLICIT_SYMBOL(__eprintf);
> +#endif
> +#endif
> + }
> +#endif
> +
> +#ifdef __CYGWIN__
> + {
> + EXPLICIT_SYMBOL(_alloca);
> + EXPLICIT_SYMBOL(__main);
> + }
> +#endif
> +
> +#undef EXPLICIT_SYMBOL
> + return nullptr;
> +}
> +
> +namespace llvm {
> +void *SearchForAddressOfSpecialSymbol(const char* symbolName) {
> + return DoSearch(symbolName);
> +}
> +} // namespace llvm
>
> Removed: llvm/trunk/lib/Support/Unix/DynamicLibrary.inc
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/DynamicLibrary.inc?rev=301239&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Support/Unix/DynamicLibrary.inc (original)
> +++ llvm/trunk/lib/Support/Unix/DynamicLibrary.inc (removed)
> @@ -1,131 +0,0 @@
> -//===- Unix/DynamicLibrary.cpp - Unix DL Implementation ---------*- C++ -*-===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// This file provides the UNIX specific implementation of DynamicLibrary.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
> -#include <dlfcn.h>
> -
> -DynamicLibrary::HandleSet::~HandleSet() {
> - for (void *Handle : Handles)
> - ::dlclose(Handle);
> - if (Process)
> - ::dlclose(Process);
> -}
> -
> -void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
> - void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL);
> - if (!Handle) {
> - if (Err) *Err = ::dlerror();
> - return &DynamicLibrary::Invalid;
> - }
> -
> -#ifdef __CYGWIN__
> - // Cygwin searches symbols only in the main
> - // with the handle of dlopen(NULL, RTLD_GLOBAL).
> - if (!Filename)
> - Handle = RTLD_DEFAULT;
> -#endif
> -
> - return Handle;
> -}
> -
> -void DynamicLibrary::HandleSet::DLClose(void *Handle) {
> - ::dlclose(Handle);
> -}
> -
> -void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
> - return ::dlsym(Handle, Symbol);
> -}
> -
> -#else // !HAVE_DLOPEN
> -
> -DynamicLibrary::HandleSet::~HandleSet() {}
> -
> -void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
> - if (Err) *Err = "dlopen() not supported on this platform";
> - return &Invalid;
> -}
> -
> -void DynamicLibrary::HandleSet::DLClose(void *Handle) {
> -}
> -
> -void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
> - return nullptr;
> -}
> -
> -#endif
> -
> -// Must declare the symbols in the global namespace.
> -static void *DoSearch(const char* SymbolName) {
> -#define EXPLICIT_SYMBOL(SYM) \
> - extern void *SYM; if (!strcmp(SymbolName, #SYM)) return &SYM
> -
> - // If this is darwin, it has some funky issues, try to solve them here. Some
> - // important symbols are marked 'private external' which doesn't allow
> - // SearchForAddressOfSymbol to find them. As such, we special case them here,
> - // there is only a small handful of them.
> -
> -#ifdef __APPLE__
> - {
> - // __eprintf is sometimes used for assert() handling on x86.
> - //
> - // FIXME: Currently disabled when using Clang, as we don't always have our
> - // runtime support libraries available.
> -#ifndef __clang__
> -#ifdef __i386__
> - EXPLICIT_SYMBOL(__eprintf);
> -#endif
> -#endif
> - }
> -#endif
> -
> -#ifdef __CYGWIN__
> - {
> - EXPLICIT_SYMBOL(_alloca);
> - EXPLICIT_SYMBOL(__main);
> - }
> -#endif
> -
> -#undef EXPLICIT_SYMBOL
> -
> -// This macro returns the address of a well-known, explicit symbol
> -#define EXPLICIT_SYMBOL(SYM) \
> - if (!strcmp(SymbolName, #SYM)) return &SYM
> -
> -// On linux we have a weird situation. The stderr/out/in symbols are both
> -// macros and global variables because of standards requirements. So, we
> -// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
> -#if defined(__linux__) and !defined(__ANDROID__)
> - {
> - EXPLICIT_SYMBOL(stderr);
> - EXPLICIT_SYMBOL(stdout);
> - EXPLICIT_SYMBOL(stdin);
> - }
> -#else
> - // For everything else, we want to check to make sure the symbol isn't defined
> - // as a macro before using EXPLICIT_SYMBOL.
> - {
> -#ifndef stdin
> - EXPLICIT_SYMBOL(stdin);
> -#endif
> -#ifndef stdout
> - EXPLICIT_SYMBOL(stdout);
> -#endif
> -#ifndef stderr
> - EXPLICIT_SYMBOL(stderr);
> -#endif
> - }
> -#endif
> -#undef EXPLICIT_SYMBOL
> -
> - return nullptr;
> -}
>
> Modified: llvm/trunk/lib/Support/Windows/DynamicLibrary.inc
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/DynamicLibrary.inc?rev=301240&r1=301239&r2=301240&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Support/Windows/DynamicLibrary.inc (original)
> +++ llvm/trunk/lib/Support/Windows/DynamicLibrary.inc Mon Apr 24 15:16:01 2017
> @@ -12,139 +12,97 @@
> //===----------------------------------------------------------------------===//
>
> #include "WindowsSupport.h"
> -#include "llvm/Support/raw_ostream.h"
>
> -#include <Psapi.h>
> +#ifdef __MINGW32__
> + #include <imagehlp.h>
> +#else
> + #include <dbghelp.h>
> +#endif
> +
> +#ifdef _MSC_VER
> + #include <ntverp.h>
> +#endif
> +
> +namespace llvm {
>
> //===----------------------------------------------------------------------===//
> //=== WARNING: Implementation here must contain only Win32 specific code
> //=== and must not be UNIX code.
> //===----------------------------------------------------------------------===//
>
> +typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
> +static fpEnumerateLoadedModules fEnumerateLoadedModules;
> +static llvm::ManagedStatic<DenseSet<HMODULE> > OpenedHandles;
> +
> +static bool loadDebugHelp(void) {
> + HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
> + if (hLib) {
> + fEnumerateLoadedModules = (fpEnumerateLoadedModules)
> + ::GetProcAddress(hLib, "EnumerateLoadedModules64");
> + }
> + return fEnumerateLoadedModules != 0;
> +}
>
> -DynamicLibrary::HandleSet::~HandleSet() {
> - for (void *Handle : Handles)
> - FreeLibrary(HMODULE(Handle));
> -
> - // 'Process' should not be released on Windows.
> - assert((!Process || Process==this) && "Bad Handle");
> -}
> -
> -void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
> - // Create the instance and return it to be the *Process* handle
> - // simillar to dlopen(NULL, RTLD_LAZY|RTLD_GLOBAL)
> - if (!File)
> - return &(*OpenedHandles);
> +static BOOL CALLBACK
> +ELM_Callback(PCSTR ModuleName, DWORD64 ModuleBase,
> + ULONG ModuleSize, PVOID UserContext) {
> + OpenedHandles->insert((HMODULE)ModuleBase);
> + return TRUE;
> +}
> +
> +sys::DynamicLibrary
> +sys::DynamicLibrary::getPermanentLibrary(const char *filename,
> + std::string *errMsg) {
> + SmartScopedLock<true> lock(*SymbolsMutex);
> +
> + if (!filename) {
> + // When no file is specified, enumerate all DLLs and EXEs in the process.
> + if (!fEnumerateLoadedModules) {
> + if (!loadDebugHelp()) {
> + assert(false && "These APIs should always be available");
> + return DynamicLibrary();
> + }
> + }
>
> - SmallVector<wchar_t, MAX_PATH> FileUnicode;
> - if (std::error_code ec = windows::UTF8ToUTF16(File, FileUnicode)) {
> - SetLastError(ec.value());
> - MakeErrMsg(Err, std::string(File) + ": Can't convert to UTF-16");
> - return &DynamicLibrary::Invalid;
> + fEnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0);
> + // Dummy library that represents "search all handles".
> + // This is mostly to ensure that the return value still shows up as "valid".
> + return DynamicLibrary(&OpenedHandles);
> }
>
> - HMODULE Handle = LoadLibraryW(FileUnicode.data());
> - if (Handle == NULL) {
> - MakeErrMsg(Err, std::string(File) + ": Can't open");
> - return &DynamicLibrary::Invalid;
> + SmallVector<wchar_t, MAX_PATH> filenameUnicode;
> + if (std::error_code ec = windows::UTF8ToUTF16(filename, filenameUnicode)) {
> + SetLastError(ec.value());
> + MakeErrMsg(errMsg, std::string(filename) + ": Can't convert to UTF-16");
> + return DynamicLibrary();
> }
>
> - return reinterpret_cast<void*>(Handle);
> -}
> + HMODULE a_handle = LoadLibraryW(filenameUnicode.data());
>
> -static DynamicLibrary::HandleSet *IsOpenedHandlesInstance(void *Handle) {
> - if (!OpenedHandles.isConstructed())
> - return nullptr;
> - DynamicLibrary::HandleSet &Inst = *OpenedHandles;
> - return Handle == &Inst ? &Inst : nullptr;
> -}
> + if (a_handle == 0) {
> + MakeErrMsg(errMsg, std::string(filename) + ": Can't open");
> + return DynamicLibrary();
> + }
>
> -void DynamicLibrary::HandleSet::DLClose(void *Handle) {
> - if (HandleSet* HS = IsOpenedHandlesInstance(Handle))
> - HS->Process = nullptr; // Just drop the *Process* handle.
> - else
> - FreeLibrary((HMODULE)Handle);
> + // If we've already loaded this library, FreeLibrary() the handle in order to
> + // keep the internal refcount at +1.
> + if (!OpenedHandles->insert(a_handle).second)
> + FreeLibrary(a_handle);
> +
> + return DynamicLibrary(a_handle);
> }
>
> -static bool GetProcessModules(HANDLE H, DWORD &Bytes, HMODULE *Data = nullptr) {
> - // EnumProcessModules will fail on Windows 64 while MingW-32 doesn't have
> - // EnumProcessModulesEx.
> - if (
> -#ifdef _WIN64
> - !EnumProcessModulesEx(H, Data, Bytes, &Bytes, LIST_MODULES_64BIT)
> -#else
> - !EnumProcessModules(H, Data, Bytes, &Bytes)
> -#endif
> - ) {
> - std::string Err;
> - if (MakeErrMsg(&Err, "EnumProcessModules failure"))
> - llvm::errs() << Err << "\n";
> - return false;
> - }
> - return true;
> -}
> -
> -void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
> - HandleSet* HS = IsOpenedHandlesInstance(Handle);
> - if (!HS)
> - return (void *)uintptr_t(GetProcAddress((HMODULE)Handle, Symbol));
> -
> - // Could have done a dlclose on the *Process* handle
> - if (!HS->Process)
> - return nullptr;
> -
> - // Trials indicate EnumProcessModulesEx is consistantly faster than using
> - // EnumerateLoadedModules64 or CreateToolhelp32Snapshot.
> - //
> - // | Handles | DbgHelp.dll | CreateSnapshot | EnumProcessModulesEx
> - // |=========|=============|========================================
> - // | 37 | 0.0000585 * | 0.0003031 | 0.0000152
> - // | 1020 | 0.0026310 * | 0.0121598 | 0.0002683
> - // | 2084 | 0.0149418 * | 0.0369936 | 0.0005610
> - //
> - // * Not including the load time of Dbghelp.dll (~.005 sec)
> - //
> - // There's still a case to somehow cache the result of EnumProcessModulesEx
> - // across invocations, but the complication of doing that properly...
> - // Possibly using LdrRegisterDllNotification to invalidate the cache?
> -
> - DWORD Bytes = 0;
> - HMODULE Self = HMODULE(GetCurrentProcess());
> - if (!GetProcessModules(Self, Bytes))
> - return nullptr;
> -
> - // Get the most recent list in case any modules added/removed between calls
> - // to EnumProcessModulesEx that gets the amount of, then copies the HMODULES.
> - // MSDN is pretty clear that if the module list changes during the call to
> - // EnumProcessModulesEx the results should not be used.
> - std::vector<HMODULE> Handles;
> - do {
> - assert(Bytes && ((Bytes % sizeof(HMODULE)) == 0) &&
> - "Should have at least one module and be aligned");
> - Handles.resize(Bytes / sizeof(HMODULE));
> - if (!GetProcessModules(Self, Bytes, Handles.data()))
> - return nullptr;
> - } while (Bytes != (Handles.size() * sizeof(HMODULE)));
> -
> - // Try EXE first, mirroring what dlsym(dlopen(NULL)) does.
> - if (FARPROC Ptr = GetProcAddress(HMODULE(Handles.front()), Symbol))
> - return (void *) uintptr_t(Ptr);
> -
> - if (Handles.size() > 1) {
> - // This is different behaviour than what Posix dlsym(dlopen(NULL)) does.
> - // Doing that here is causing real problems for the JIT where msvc.dll
> - // and ucrt.dll can define the same symbols. The runtime linker will choose
> - // symbols from ucrt.dll first, but iterating NOT in reverse here would
> - // mean that the msvc.dll versions would be returned.
> -
> - for (auto I = Handles.rbegin(), E = Handles.rend()-1; I != E; ++I) {
> - if (FARPROC Ptr = GetProcAddress(HMODULE(*I), Symbol))
> - return (void *) uintptr_t(Ptr);
> - }
> +sys::DynamicLibrary
> +sys::DynamicLibrary::addPermanentLibrary(void *handle, std::string *errMsg) {
> + SmartScopedLock<true> lock(*SymbolsMutex);
> + // If we've already loaded this library, tell the caller.
> + if (!OpenedHandles->insert((HMODULE)handle).second) {
> + MakeErrMsg(errMsg, "Library already loaded");
> + return DynamicLibrary();
> }
> - return nullptr;
> -}
>
> + return DynamicLibrary(handle);
> +}
>
> // Stack probing routines are in the support library (e.g. libgcc), but we don't
> // have dynamic linking on windows. Provide a hook.
> @@ -171,18 +129,38 @@ void *DynamicLibrary::HandleSet::DLSym(v
> #undef INLINE_DEF_SYMBOL1
> #undef INLINE_DEF_SYMBOL2
>
> -static void *DoSearch(const char *SymbolName) {
> +void *sys::DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
> + SmartScopedLock<true> Lock(*SymbolsMutex);
> +
> + // First check symbols added via AddSymbol().
> + if (ExplicitSymbols.isConstructed()) {
> + StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
> +
> + if (i != ExplicitSymbols->end())
> + return i->second;
> + }
> +
> + // Now search the libraries.
> + if (OpenedHandles.isConstructed()) {
> + for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(),
> + E = OpenedHandles->end(); I != E; ++I) {
> + FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
> + if (ptr) {
> + return (void *)(intptr_t)ptr;
> + }
> + }
> + }
>
> #define EXPLICIT_SYMBOL(SYM) \
> - if (!strcmp(SymbolName, #SYM)) \
> + if (!strcmp(symbolName, #SYM)) \
> return (void *)&SYM;
> #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \
> - if (!strcmp(SymbolName, #SYMFROM)) \
> + if (!strcmp(symbolName, #SYMFROM)) \
> return (void *)&SYMTO;
>
> #ifdef _M_IX86
> #define INLINE_DEF_SYMBOL1(TYP, SYM) \
> - if (!strcmp(SymbolName, #SYM)) \
> + if (!strcmp(symbolName, #SYM)) \
> return (void *)&inline_##SYM;
> #define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM)
> #endif
> @@ -196,5 +174,15 @@ static void *DoSearch(const char *Symbol
> #undef INLINE_DEF_SYMBOL1
> #undef INLINE_DEF_SYMBOL2
>
> - return nullptr;
> + return 0;
> +}
> +
> +void *sys::DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
> + if (!isValid())
> + return NULL;
> + if (Data == &OpenedHandles)
> + return SearchForAddressOfSymbol(symbolName);
> + return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName);
> +}
> +
> }
>
> Modified: llvm/trunk/unittests/Support/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=301240&r1=301239&r2=301240&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/Support/CMakeLists.txt (original)
> +++ llvm/trunk/unittests/Support/CMakeLists.txt Mon Apr 24 15:16:01 2017
> @@ -67,5 +67,3 @@ add_llvm_unittest(SupportTests
>
> # ManagedStatic.cpp uses <pthread>.
> target_link_libraries(SupportTests ${LLVM_PTHREAD_LIB})
> -
> -add_subdirectory(DynamicLibrary)
>
> Removed: llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt?rev=301239&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt (original)
> +++ llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt (removed)
> @@ -1,19 +0,0 @@
> -set(LLVM_LINK_COMPONENTS Support)
> -
> -add_llvm_unittest(DynamicLibraryTests DynamicLibraryTest.cpp)
> -
> -export_executable_symbols(DynamicLibraryTests)
> -
> -add_library(PipSqueak SHARED PipSqueak.cxx)
> -
> -set_output_directory(PipSqueak
> - BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
> - LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
> - )
> -
> -set_target_properties(PipSqueak
> - PROPERTIES PREFIX ""
> - SUFFIX ".so"
> - )
> -
> -add_dependencies(DynamicLibraryTests PipSqueak)
>
> Removed: llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp?rev=301239&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp (original)
> +++ llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp (removed)
> @@ -1,133 +0,0 @@
> -//===- llvm/unittest/Support/DynamicLibrary/DynamicLibraryTest.cpp --------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "llvm/Config/config.h"
> -#include "llvm/Support/DynamicLibrary.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/ManagedStatic.h"
> -#include "llvm/Support/Path.h"
> -#include "gtest/gtest.h"
> -
> -#include "PipSqueak.h"
> -#include <string>
> -
> -using namespace llvm;
> -using namespace llvm::sys;
> -
> -extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "ProcessCall"; }
> -
> -std::string LibPath() {
> - std::string Path =
> - fs::getMainExecutable("DynamicLibraryTests", (void *)&TestA);
> - llvm::SmallString<256> Buf(path::parent_path(Path));
> - path::append(Buf, "PipSqueak.so");
> - return Buf.str();
> -}
> -
> -#if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN))
> -
> -typedef void (*SetStrings)(std::string &GStr, std::string &LStr);
> -typedef const char *(*GetString)();
> -
> -template <class T> static T FuncPtr(void *Ptr) {
> - union {
> - T F;
> - void *P;
> - } Tmp;
> - Tmp.P = Ptr;
> - return Tmp.F;
> -}
> -template <class T> static void* PtrFunc(T *Func) {
> - union {
> - T *F;
> - void *P;
> - } Tmp;
> - Tmp.F = Func;
> - return Tmp.P;
> -}
> -
> -static const char *OverloadTestA() { return "OverloadCall"; }
> -
> -std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; }
> -
> -TEST(DynamicLibrary, Overload) {
> - {
> - std::string Err;
> - llvm_shutdown_obj Shutdown;
> - DynamicLibrary DL =
> - DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
> - EXPECT_TRUE(DL.isValid());
> - EXPECT_TRUE(Err.empty());
> -
> - GetString GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
> - EXPECT_TRUE(GS != nullptr && GS != &TestA);
> - EXPECT_EQ(StdString(GS()), "LibCall");
> -
> - GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
> - EXPECT_TRUE(GS != nullptr && GS != &TestA);
> - EXPECT_EQ(StdString(GS()), "LibCall");
> -
> - DL = DynamicLibrary::getPermanentLibrary(nullptr, &Err);
> - EXPECT_TRUE(DL.isValid());
> - EXPECT_TRUE(Err.empty());
> -
> - GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
> - EXPECT_TRUE(GS != nullptr && GS == &TestA);
> - EXPECT_EQ(StdString(GS()), "ProcessCall");
> -
> - GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
> - EXPECT_TRUE(GS != nullptr && GS == &TestA);
> - EXPECT_EQ(StdString(GS()), "ProcessCall");
> -
> - DynamicLibrary::AddSymbol("TestA", PtrFunc(&OverloadTestA));
> - GS = FuncPtr<GetString>(DL.getAddressOfSymbol("TestA"));
> - EXPECT_TRUE(GS != nullptr && GS != &OverloadTestA);
> -
> - GS = FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol("TestA"));
> - EXPECT_TRUE(GS != nullptr && GS == &OverloadTestA);
> - EXPECT_EQ(StdString(GS()), "OverloadCall");
> - }
> - EXPECT_TRUE(FuncPtr<GetString>(DynamicLibrary::SearchForAddressOfSymbol(
> - "TestA")) == nullptr);
> -}
> -
> -TEST(DynamicLibrary, Shutdown) {
> - std::string A, B;
> - {
> - std::string Err;
> - llvm_shutdown_obj Shutdown;
> - DynamicLibrary DL =
> - DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
> - EXPECT_TRUE(DL.isValid());
> - EXPECT_TRUE(Err.empty());
> -
> - SetStrings SS = FuncPtr<SetStrings>(
> - DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
> - EXPECT_TRUE(SS != nullptr);
> -
> - SS(A, B);
> - EXPECT_EQ(B, "Local::Local");
> - }
> - EXPECT_EQ(A, "Global::~Global");
> - EXPECT_EQ(B, "Local::~Local");
> - EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol(
> - "SetStrings")) == nullptr);
> -}
> -
> -#else
> -
> -TEST(DynamicLibrary, Unsupported) {
> - std::string Err;
> - DynamicLibrary DL =
> - DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
> - EXPECT_FALSE(DL.isValid());
> - EXPECT_EQ(Err, "dlopen() not supported on this platform");
> -}
> -
> -#endif
>
> Removed: llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx?rev=301239&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx (original)
> +++ llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx (removed)
> @@ -1,36 +0,0 @@
> -//===- llvm/unittest/Support/DynamicLibrary/PipSqueak.cxx -----------------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "PipSqueak.h"
> -#include <string>
> -
> -struct Global {
> - std::string *Str;
> - Global() : Str(nullptr) {}
> - ~Global() {
> - if (Str)
> - *Str = "Global::~Global";
> - }
> -};
> -
> -struct Local {
> - std::string &Str;
> - Local(std::string &S) : Str(S) { Str = "Local::Local"; }
> - ~Local() { Str = "Local::~Local"; }
> -};
> -
> -static Global Glb;
> -
> -extern "C" PIPSQUEAK_EXPORT void SetStrings(std::string &GStr,
> - std::string &LStr) {
> - static Local Lcl(LStr);
> - Glb.Str = &GStr;
> -}
> -
> -extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "LibCall"; }
>
> Removed: llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h?rev=301239&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h (original)
> +++ llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h (removed)
> @@ -1,19 +0,0 @@
> -//===- llvm/unittest/Support/DynamicLibrary/PipSqueak.h -------------------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef LLVM_PIPSQUEAK_H
> -#define LLVM_PIPSQUEAK_H
> -
> -#ifdef _WIN32
> -#define PIPSQUEAK_EXPORT __declspec(dllexport)
> -#else
> -#define PIPSQUEAK_EXPORT
> -#endif
> -
> -#endif
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
--
-Bill Seurer
More information about the llvm-commits
mailing list