Revert "Refactor DynamicLibrary so searching for a symbol will have a defined order.”
The changes are causing the i686-mingw32 build to fail.

This reverts commit r301153, and the changes for a separate warning on i686-mingw32 in r301155  and r301156.

llvm-svn: 301157
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 63c4400..491614b 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -130,6 +130,7 @@
   Process.cpp
   Program.cpp
   RWMutex.cpp
+  SearchForAddressOfSpecialSymbol.cpp
   Signals.cpp
   TargetRegistry.cpp
   ThreadLocal.cpp
diff --git a/llvm/lib/Support/DynamicLibrary.cpp b/llvm/lib/Support/DynamicLibrary.cpp
index 1541a57..22fb3f2 100644
--- a/llvm/lib/Support/DynamicLibrary.cpp
+++ b/llvm/lib/Support/DynamicLibrary.cpp
@@ -20,164 +20,169 @@
 #include "llvm/Support/Mutex.h"
 #include <cstdio>
 #include <cstring>
-#include <vector>
 
-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);
-
-  HandleSet() : Process(nullptr) {}
-  ~HandleSet();
-
-  HandleList::iterator Find(void *Handle) {
-    return std::find(Handles.begin(), Handles.end(), Handle);
-  }
-
-  bool Contains(void *Handle) {
-    return Handle == Process || Find(Handle) != Handles.end();
-  }
-
-  bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
-#ifdef LLVM_ON_WIN32
-    assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
-#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;
-  }
-
-  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;
-  }
-};
-
-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;
+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
 
-#include "Unix/DynamicLibrary.inc"
+#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();
+  }
+
+#ifdef __CYGWIN__
+  // Cygwin searches symbols only in the main
+  // with the handle of dlopen(NULL, RTLD_GLOBAL).
+  if (!filename)
+    handle = RTLD_DEFAULT;
+#endif
+
+  // 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);
+
+  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();
+  }
+
+  return DynamicLibrary(handle);
+}
+
+void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
+  if (!isValid())
+    return nullptr;
+  return dlsym(Data, symbolName);
+}
+
+#else
+
+using namespace llvm;
+using namespace llvm::sys;
+
+DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
+                                                   std::string *errMsg) {
+  if (errMsg) *errMsg = "dlopen() not supported on this platform";
+  return DynamicLibrary();
+}
+
+void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
+  return NULL;
+}
 
 #endif
 
-char DynamicLibrary::Invalid;
-
 namespace llvm {
-void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
-  return DoSearch(SymbolName); // DynamicLibrary.inc
-}
+void *SearchForAddressOfSpecialSymbol(const char* symbolName);
 }
 
-void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
+void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
   SmartScopedLock<true> Lock(*SymbolsMutex);
-  (*ExplicitSymbols)[SymbolName] = SymbolValue;
-}
 
-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);
+  // First check symbols added via AddSymbol().
+  if (ExplicitSymbols.isConstructed()) {
+    StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
 
-  return DynamicLibrary(Handle);
-}
-
-DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
-                                                   std::string *Err) {
-  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);
-
-      if (i != ExplicitSymbols->end())
-        return i->second;
-    }
-
-    // Now search the libraries.
-    if (OpenedHandles.isConstructed()) {
-      if (void *Ptr = OpenedHandles->Lookup(SymbolName))
-        return Ptr;
-    }
+    if (i != ExplicitSymbols->end())
+      return i->second;
   }
 
-  return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
+#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
+
+  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 nullptr;
 }
 
+#endif // LLVM_ON_WIN32
+
 //===----------------------------------------------------------------------===//
 // C API.
 //===----------------------------------------------------------------------===//
 
-LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
+LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
 }
 
diff --git a/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp b/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp
new file mode 100644
index 0000000..55f3320
--- /dev/null
+++ b/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp
@@ -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
index a0110e7..0000000
--- a/llvm/lib/Support/Unix/DynamicLibrary.inc
+++ /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;
-}
diff --git a/llvm/lib/Support/Windows/DynamicLibrary.inc b/llvm/lib/Support/Windows/DynamicLibrary.inc
index b43ae54..709499de 100644
--- a/llvm/lib/Support/Windows/DynamicLibrary.inc
+++ b/llvm/lib/Support/Windows/DynamicLibrary.inc
@@ -16,140 +16,93 @@
 #ifdef __MINGW32__
  #include <imagehlp.h>
 #else
- #include <Psapi.h>
+ #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));
-
-  // '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);
-
-  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;
+static bool loadDebugHelp(void) {
+  HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
+  if (hLib) {
+    fEnumerateLoadedModules = (fpEnumerateLoadedModules)
+      ::GetProcAddress(hLib, "EnumerateLoadedModules64");
   }
-
-  HMODULE Handle = LoadLibraryW(FileUnicode.data());
-  if (Handle == NULL) {
-    MakeErrMsg(Err, std::string(File) + ": Can't open");
-    return &DynamicLibrary::Invalid;
-  }
-
-  return reinterpret_cast<void*>(Handle);
+  return fEnumerateLoadedModules != 0;
 }
 
-static DynamicLibrary::HandleSet *IsOpenedHandlesInstance(void *Handle) {
-  if (!OpenedHandles.isConstructed())
-    return nullptr;
-  DynamicLibrary::HandleSet &Inst = *OpenedHandles;
-  return Handle == &Inst ? &Inst : nullptr;
+static BOOL CALLBACK
+ELM_Callback(PCSTR ModuleName, DWORD64 ModuleBase,
+             ULONG ModuleSize, PVOID UserContext) {
+  OpenedHandles->insert((HMODULE)ModuleBase);
+  return TRUE;
 }
 
-void DynamicLibrary::HandleSet::DLClose(void *Handle) {
-  if (HandleSet* HS = IsOpenedHandlesInstance(Handle))
-    HS->Process = nullptr; // Just drop the *Process* handle.
-  else
-    FreeLibrary((HMODULE)Handle);
-}
+sys::DynamicLibrary
+sys::DynamicLibrary::getPermanentLibrary(const char *filename,
+                                         std::string *errMsg) {
+  SmartScopedLock<true> lock(*SymbolsMutex);
 
-static bool GetProcessModules(HANDLE H, DWORD &Bytes, HMODULE *Data = nullptr) {
-#ifdef _WIN64
-  const DWORD Flags = LIST_MODULES_64BIT;
-#else
-  const DWORD Flags = LIST_MODULES_32BIT;
-#endif
-
-  if (!EnumProcessModulesEx(H, Data, Bytes, &Bytes, Flags)) {
-    std::string Err;
-    if (MakeErrMsg(&Err, "EnumProcessModulesEx 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);
+  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();
+      }
     }
+
+    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);
   }
-  return nullptr;
+
+  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();
+  }
+
+  HMODULE a_handle = LoadLibraryW(filenameUnicode.data());
+
+  if (a_handle == 0) {
+    MakeErrMsg(errMsg, std::string(filename) + ": Can't open");
+    return DynamicLibrary();
+  }
+
+  // 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);
 }
 
+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 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.
@@ -176,18 +129,38 @@
 #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
@@ -201,5 +174,15 @@
 #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);
+}
+
 }