Revert "Refactor DynamicLibrary so searching for a symbol will have a defined order"
authorFrederich Munch <colsebas@hotmail.com>
Mon, 24 Apr 2017 20:16:01 +0000 (20:16 +0000)
committerFrederich Munch <colsebas@hotmail.com>
Mon, 24 Apr 2017 20:16:01 +0000 (20:16 +0000)
The i686-mingw32-RA-on-linux bot is still having errors.

This reverts commit r301236.

llvm-svn: 301240

llvm/include/llvm/Support/DynamicLibrary.h
llvm/lib/Support/CMakeLists.txt
llvm/lib/Support/DynamicLibrary.cpp
llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp [new file with mode: 0644]
llvm/lib/Support/Unix/DynamicLibrary.inc [deleted file]
llvm/lib/Support/Windows/DynamicLibrary.inc
llvm/unittests/Support/CMakeLists.txt
llvm/unittests/Support/DynamicLibrary/CMakeLists.txt [deleted file]
llvm/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp [deleted file]
llvm/unittests/Support/DynamicLibrary/PipSqueak.cxx [deleted file]
llvm/unittests/Support/DynamicLibrary/PipSqueak.h [deleted file]

index a8874a1..aa9bb89 100644 (file)
@@ -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
index 63c4400..491614b 100644 (file)
@@ -130,6 +130,7 @@ add_llvm_library(LLVMSupport
   Process.cpp
   Program.cpp
   RWMutex.cpp
+  SearchForAddressOfSpecialSymbol.cpp
   Signals.cpp
   TargetRegistry.cpp
   ThreadLocal.cpp
index 1541a57..22fb3f2 100644 (file)
 #include "llvm/Support/Mutex.h"
 #include <cstdio>
 #include <cstring>
-#include <vector>
 
+// 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;
+
+void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
+                                          void *symbolValue) {
+  SmartScopedLock<true> lock(*SymbolsMutex);
+  (*ExplicitSymbols)[symbolName] = symbolValue;
+}
+
+char llvm::sys::DynamicLibrary::Invalid = 0;
+
+#ifdef LLVM_ON_WIN32
+
+#include "Windows/DynamicLibrary.inc"
+
+#else
+
+#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
+#include <dlfcn.h>
 using namespace llvm;
 using namespace llvm::sys;
 
-// All methods for HandleSet should be used holding SymbolsMutex.
-class DynamicLibrary::HandleSet {
-  typedef std::vector<void *> HandleList;
-  HandleList Handles;
-  void *Process;
-
-public:
-  static void *DLOpen(const char *Filename, std::string *Err);
-  static void DLClose(void *Handle);
-  static void *DLSym(void *Handle, const char *Symbol);
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//===          independent code.
+//===----------------------------------------------------------------------===//
 
-  HandleSet() : Process(nullptr) {}
-  ~HandleSet();
+static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles;
 
-  HandleList::iterator Find(void *Handle) {
-    return std::find(Handles.begin(), Handles.end(), Handle);
-  }
+DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
+                                                   std::string *errMsg) {
+  SmartScopedLock<true> lock(*SymbolsMutex);
 
-  bool Contains(void *Handle) {
-    return Handle == Process || Find(Handle) != Handles.end();
+  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);
-}
+  // First check symbols added via AddSymbol().
+  if (ExplicitSymbols.isConstructed()) {
+    StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
 
-void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
-  if (!isValid())
-    return nullptr;
-  return HandleSet::DLSym(Data, SymbolName);
-}
+    if (i != ExplicitSymbols->end())
+      return i->second;
+  }
 
-void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
-  {
-    SmartScopedLock<true> Lock(*SymbolsMutex);
+#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
 
-    // First check symbols added via AddSymbol().
-    if (ExplicitSymbols.isConstructed()) {
-      StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
+  if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
+    return Result;
 
-      if (i != ExplicitSymbols->end())
-        return i->second;
-    }
+// This macro returns the address of a well-known, explicit symbol
+#define EXPLICIT_SYMBOL(SYM) \
+   if (!strcmp(symbolName, #SYM)) return &SYM
 
-    // Now search the libraries.
-    if (OpenedHandles.isConstructed()) {
-      if (void *Ptr = OpenedHandles->Lookup(SymbolName))
-        return Ptr;
-    }
+// 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 charFilename) {
   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
 }
 
diff --git a/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp b/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp
new file mode 100644 (file)
index 0000000..55f3320
--- /dev/null
@@ -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
diff --git a/llvm/lib/Support/Unix/DynamicLibrary.inc b/llvm/lib/Support/Unix/DynamicLibrary.inc
deleted file mode 100644 (file)
index a0110e7..0000000
+++ /dev/null
@@ -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;
-}
index c15c762..709499d 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #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;
 
-DynamicLibrary::HandleSet::~HandleSet() {
-  for (void *Handle : Handles)
-    FreeLibrary(HMODULE(Handle));
+static bool loadDebugHelp(void) {
+  HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
+  if (hLib) {
+    fEnumerateLoadedModules = (fpEnumerateLoadedModules)
+      ::GetProcAddress(hLib, "EnumerateLoadedModules64");
+  }
+  return fEnumerateLoadedModules != 0;
+}
 
-  // 'Process' should not be released on Windows.
-  assert((!Process || Process==this) && "Bad Handle");
+static BOOL CALLBACK
+ELM_Callback(PCSTR ModuleName, DWORD64 ModuleBase,
+             ULONG ModuleSize, PVOID UserContext) {
+  OpenedHandles->insert((HMODULE)ModuleBase);
+  return TRUE;
 }
 
-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);
+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);
 
-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;
+  return DynamicLibrary(a_handle);
 }
 
-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(void *Handle, const char *Symbol) {
 #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 *SymbolName) {
 #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);
+}
+
 }
index 1f67710..a7be18b 100644 (file)
@@ -67,5 +67,3 @@ add_llvm_unittest(SupportTests
 
 # ManagedStatic.cpp uses <pthread>.
 target_link_libraries(SupportTests ${LLVM_PTHREAD_LIB})
-
-add_subdirectory(DynamicLibrary)
diff --git a/llvm/unittests/Support/DynamicLibrary/CMakeLists.txt b/llvm/unittests/Support/DynamicLibrary/CMakeLists.txt
deleted file mode 100644 (file)
index f0e945e..0000000
+++ /dev/null
@@ -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)
diff --git a/llvm/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp b/llvm/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
deleted file mode 100644 (file)
index 793cd62..0000000
+++ /dev/null
@@ -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
diff --git a/llvm/unittests/Support/DynamicLibrary/PipSqueak.cxx b/llvm/unittests/Support/DynamicLibrary/PipSqueak.cxx
deleted file mode 100644 (file)
index 1de8523..0000000
+++ /dev/null
@@ -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"; }
diff --git a/llvm/unittests/Support/DynamicLibrary/PipSqueak.h b/llvm/unittests/Support/DynamicLibrary/PipSqueak.h
deleted file mode 100644 (file)
index e6a859d..0000000
+++ /dev/null
@@ -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