Test step one of patch series.

git-svn-id: http://root.cern.ch/svn/root/trunk@47269 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
Axel Naumann 2012-11-14 15:03:52 +00:00
parent 6ed50f2718
commit 785d0248b6

View File

@ -2,93 +2,8 @@ Index: include/llvm/Support/DynamicLibrary.h
=================================================================== ===================================================================
--- include/llvm/Support/DynamicLibrary.h (revision 167609) --- include/llvm/Support/DynamicLibrary.h (revision 167609)
+++ include/llvm/Support/DynamicLibrary.h (working copy) +++ include/llvm/Support/DynamicLibrary.h (working copy)
@@ -48,14 +48,19 @@ namespace sys { @@ -91,6 +91,13 @@ namespace sys {
/// Returns true if the object refers to a valid library. return SearchForAddressOfSymbol(symbolName.c_str());
bool isValid() { return Data != &Invalid; }
- /// Searches through the library for the symbol \p symbolName. If it is
+ /// Searches through the library for the symbol \p SymbolName. If it is
/// found, the address of that symbol is returned. If not, NULL is returned.
/// Note that NULL will also be returned if the library failed to load.
/// Use isValid() to distinguish these cases if it is important.
/// Note that this will \e not search symbols explicitly registered by
/// AddSymbol().
- void *getAddressOfSymbol(const char *symbolName);
+ void *getAddressOfSymbol(const char *SymbolName);
+ /// Unload the dynamic library. \p *errMsg will be set to an error message
+ /// if the library fails to unload. Returns true on success.
+ ///
+ bool Unload(std::string *ErrMsg = 0);
+
/// This function permanently loads the dynamic library at the given path.
/// The library will only be unloaded when the program terminates.
/// This returns a valid DynamicLibrary instance on success and an invalid
@@ -64,8 +69,10 @@ namespace sys {
///
/// It is safe to call this function multiple times for the same library.
/// @brief Open a dynamic library permanently.
- static DynamicLibrary getPermanentLibrary(const char *filename,
- std::string *errMsg = 0);
+ static DynamicLibrary getPermanentLibrary(const char *Filename,
+ std::string *ErrMsg = 0) {
+ return getLibrary(Filename, true /*permanent*/, ErrMsg);
+ }
/// This function permanently loads the dynamic library at the given path.
/// Use this instead of getPermanentLibrary() when you won't need to get
@@ -77,25 +84,58 @@ namespace sys {
return !getPermanentLibrary(Filename, ErrMsg).isValid();
}
- /// This function will search through all previously loaded dynamic
- /// libraries for the symbol \p symbolName. If it is found, the address of
- /// that symbol is returned. If not, null is returned. Note that this will
- /// search permanently loaded libraries (getPermanentLibrary()) as well
- /// as explicitly registered symbols (AddSymbol()).
- /// @throws std::string on error.
- /// @brief Search through libraries for address of a symbol
- static void *SearchForAddressOfSymbol(const char *symbolName);
+ /// This function loads the dynamic library at the given path. If
+ /// !permanent, the library can be unloaded by UnloadLibrary().
+ /// 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.
+ ///
+ /// It is safe to call this function multiple times for the same library.
+ /// @brief Open a dynamic library.
+ static DynamicLibrary getLibrary(const char *Filename,
+ bool Permanent = false,
+ std::string *ErrMsg = 0);
+ /// This function loads the dynamic library at the given path. If
+ /// !permanent, the library can be unloaded by UnloadLibrary().
+ /// Use this instead of getLibrary() when you won't need to get
+ /// symbols from the library itself.
+ ///
+ /// It is safe to call this function multiple times for the same library.
+ static bool LoadLibrary(const char *Filename, bool Permanent = false,
+ std::string *ErrMsg = 0) {
+ return !getLibrary(Filename, Permanent, ErrMsg).isValid();
+ }
+
+ /// Unload the dynamic library at the given path. \p *errMsg will be
+ /// set to an error message if the library fails to unload. Returns
+ /// true on success.
+ ///
+ static bool Unload(const char *Filename, std::string *ErrMsg = 0);
+
+ /// Search through all previously loaded dynamic libraries and explicitly
+ /// registered symbols (AddSymbol()) for the symbol \p symbolName. If it is
+ /// found, the address of that symbol is returned. If not, null is returned.
+ /// @brief Search through libraries and added symbols for address of a symbol
+ static void *SearchForAddressOfSymbol(const char *SymbolName);
+
/// @brief Convenience function for C++ophiles.
- static void *SearchForAddressOfSymbol(const std::string &symbolName) {
- return SearchForAddressOfSymbol(symbolName.c_str());
+ static void *SearchForAddressOfSymbol(const std::string &SymbolName) {
+ return SearchForAddressOfSymbol(SymbolName.c_str());
} }
+ /// This function will search through all previously loaded dynamic + /// This function will search through all previously loaded dynamic
@ -101,31 +16,289 @@ Index: include/llvm/Support/DynamicLibrary.h
/// This functions permanently adds the symbol \p symbolName with the /// This functions permanently adds the symbol \p symbolName with the
/// value \p symbolValue. These symbols are searched before any /// value \p symbolValue. These symbols are searched before any
/// libraries. /// libraries.
/// @brief Add searchable symbol/value pair. Index: lib/Support/DynamicLibrary.cpp
- static void AddSymbol(StringRef symbolName, void *symbolValue); ===================================================================
+ static void AddSymbol(StringRef SymbolName, void *SymbolValue); --- lib/Support/DynamicLibrary.cpp (revision 167609)
}; +++ lib/Support/DynamicLibrary.cpp (working copy)
@@ -9,7 +9,7 @@
//
// This header file implements the operating system DynamicLibrary concept.
//
-// FIXME: This file leaks ExplicitSymbols and OpenedHandles!
+// FIXME: This file leaks OpenedHandles!
//
//===----------------------------------------------------------------------===//
} // End sys namespace @@ -21,11 +21,45 @@
#include <cstdio>
#include <cstring>
-// Collection of symbol name/value pairs to be searched prior to any libraries.
-static llvm::StringMap<void *> *ExplicitSymbols = 0;
+using namespace llvm;
+using namespace llvm::sys;
+
+// Platform-specific implementations are required to define these function.
+// They do not need to be reentrant; locking is done by the caller.
+// Open the shared library called filename and return its handle. If filename
+// is NULL, return a handle for searching symbols in the whole process.
+static void *OpenLibraryImpl(const char *Filename, std::string *ErrMsg);
+// Close the shared library.
+static bool CloseLibraryImpl(void *DlHandle, std::string *ErrMsg);
+// Get the address of the symbol named symname from the library with dlhandle.
+// Global is true if this is part of a search spanning all OpenedHandles.
+static void *GetAddressOfSymbolImpl(void *DlHandle, const char *SymbolName,
+ bool Global);
+// Inject special platform symbols into the map of explicitly defined symbols.
+static void PopulateSpecialSymbolsImpl(StringMap<void *>& SymMap);
+
namespace {
+struct SpecialSymbolHolder {
+ SpecialSymbolHolder() {
+ PopulateSpecialSymbolsImpl(Map);
+ }
+
+ // Symbol name/value pairs to be searched prior to any libraries.
+ StringMap<void *> Map;
+};
+
+}
+
+// Platform specific symbols, searched after libraries
+static SpecialSymbolHolder *SpecialSymbols = 0;
+
+// User provided symbols, searched before libraries
+static StringMap<void *> *ExplicitSymbols = 0;
+
+namespace {
+
struct ExplicitSymbolsDeleter {
~ExplicitSymbolsDeleter() {
delete ExplicitSymbols;
@@ -42,148 +76,98 @@ static llvm::sys::SmartMutex<true>& getMutex() {
return HandlesMutex;
}
-void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
- void *symbolValue) {
- SmartScopedLock<true> lock(getMutex());
- if (ExplicitSymbols == 0)
- ExplicitSymbols = new llvm::StringMap<void*>();
- (*ExplicitSymbols)[symbolName] = symbolValue;
-}
-
char llvm::sys::DynamicLibrary::Invalid = 0;
-#ifdef LLVM_ON_WIN32
+static DenseSet<void *> *OpenedHandles;
-#include "Windows/DynamicLibrary.inc"
-
-#else
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-using namespace llvm;
-using namespace llvm::sys;
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-static DenseSet<void *> *OpenedHandles = 0;
-
-DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
- std::string *errMsg) {
+DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *Filename,
+ std::string *ErrMsg) {
SmartScopedLock<true> lock(getMutex());
- void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
- if (handle == 0) {
- if (errMsg) *errMsg = dlerror();
+ void *Handle = OpenLibraryImpl(Filename, ErrMsg);
+ if (Handle == 0) {
return DynamicLibrary();
}
-
-#ifdef __CYGWIN__
- // Cygwin searches symbols only in the main
- // with the handle of dlopen(NULL, RTLD_GLOBAL).
- if (filename == NULL)
- handle = RTLD_DEFAULT;
-#endif
-
if (OpenedHandles == 0)
OpenedHandles = new DenseSet<void *>();
// 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);
+ if (OpenedHandles->insert(Handle).second)
+ CloseLibraryImpl(Handle, 0);
- return DynamicLibrary(handle);
-}
+ return DynamicLibrary(Handle);
+}
-void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
- if (!isValid())
- return NULL;
- return dlsym(Data, symbolName);
+void llvm::sys::DynamicLibrary::AddSymbol(StringRef SymbolName,
+ void *SymbolValue) {
+ SmartScopedLock<true> lock(getMutex());
+ if (ExplicitSymbols == 0)
+ ExplicitSymbols = new StringMap<void *>();
+ (*ExplicitSymbols)[SymbolName] = SymbolValue;
}
-#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 GetAddressOfSymbolImpl(Data, SymbolName, false /*Global*/);
}
-void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
+void *DynamicLibrary::SearchForLibrarySymbol(const char *SymbolName) {
+ if (OpenedHandles) {
+ for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
+ E = OpenedHandles->end(); I != E; ++I) {
+ void *ptr = GetAddressOfSymbolImpl(*I, SymbolName, true /*Global*/);
+ if (ptr) {
+ return ptr;
+ }
+ }
+ }
return NULL;
}
-#endif
-
-namespace llvm {
-void *SearchForAddressOfSpecialSymbol(const char* symbolName);
-}
-
-void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
+void* DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
SmartScopedLock<true> Lock(getMutex());
// First check symbols added via AddSymbol().
if (ExplicitSymbols) {
- StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
+ StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
if (i != ExplicitSymbols->end())
return i->second;
}
-#if HAVE_DLFCN_H
// Now search the libraries.
- if (OpenedHandles) {
- 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 *ptr = SearchForLibrarySymbol(SymbolName))
+ return ptr;
- if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
- return Result;
+ // Finally check platform specific symbols.
+ if (SpecialSymbols) {
+ StringMap<void *>::iterator i = SpecialSymbols->Map.find(SymbolName);
-// 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);
+ if (i != SpecialSymbols->Map.end())
+ return i->second;
}
-#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 0;
}
+#ifdef LLVM_ON_WIN32
+#include "Windows/DynamicLibrary.inc"
+#elif HAVE_DLFCN_H
+#include "Unix/DynamicLibrary.inc"
+#else
+
+void *OpenLibraryImpl(const char *, std::string *errMsg) {
+ if (errMsg) *errMsg = "dlopen() not supported on this platform";
+ return NULL;
+ }
+bool CloseLibraryImpl(void *, std::string *ErrMsg) {
+ if (errMsg) *errMsg = "dlclose() not supported on this platform";
+ retun false;
+}
+void *GetAddressOfSymbolImpl(void *, const char *, bool) {
+ return NULL;
+}
+void PopulateSpecialSymbolsImpl(StringMap<void *>&) {
+}
+
#endif // LLVM_ON_WIN32
Index: lib/Support/CMakeLists.txt
===================================================================
--- lib/Support/CMakeLists.txt (revision 167609)
+++ lib/Support/CMakeLists.txt (working copy)
@@ -80,6 +80,7 @@ add_llvm_library(LLVMSupport
Threading.cpp
TimeValue.cpp
Valgrind.cpp
+ Unix/DynamicLibrary.inc
Unix/Host.inc
Unix/Memory.inc
Unix/Mutex.inc
Index: lib/Support/Windows/DynamicLibrary.inc Index: lib/Support/Windows/DynamicLibrary.inc
=================================================================== ===================================================================
--- lib/Support/Windows/DynamicLibrary.inc (revision 167609) --- lib/Support/Windows/DynamicLibrary.inc (revision 167609)
+++ lib/Support/Windows/DynamicLibrary.inc (working copy) +++ lib/Support/Windows/DynamicLibrary.inc (working copy)
@@ -1,4 +1,4 @@ @@ -31,16 +31,8 @@
-//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===//
+//===- Windows/DynamicLibrary.cpp - Win32 DL Implementation -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/DenseSet.h"
#include "Windows.h"
#ifdef __MINGW32__
@@ -31,16 +32,8 @@
#pragma comment(lib, "dbghelp.lib") #pragma comment(lib, "dbghelp.lib")
#endif #endif
@ -143,22 +316,12 @@ Index: lib/Support/Windows/DynamicLibrary.inc
extern "C" { extern "C" {
static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName,
@@ -48,6 +41,8 @@ extern "C" { @@ -63,49 +55,61 @@ extern "C" {
ULONG ModuleSize,
PVOID UserContext)
{
+ static DenseSet<HMODULE> ProcessDynLibs;
+
// Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded
// into the process.
if (stricmp(ModuleName, "msvci70") != 0 &&
@@ -63,49 +58,60 @@ extern "C" {
#endif #endif
stricmp(ModuleName, "msvcrt20") != 0 && stricmp(ModuleName, "msvcrt20") != 0 &&
stricmp(ModuleName, "msvcrt40") != 0) { stricmp(ModuleName, "msvcrt40") != 0) {
- OpenedHandles->insert((HMODULE)ModuleBase); - OpenedHandles->insert((HMODULE)ModuleBase);
+ if (ProcessDynLibs.insert((HMODULE)ModuleBase).second) + OpenedHandles->insert[(HMODULE)ModuleBase];
+ ++(*OpenedHandles)[(HMODULE)ModuleBase];
} }
return TRUE; return TRUE;
} }
@ -175,7 +338,7 @@ Index: lib/Support/Windows/DynamicLibrary.inc
// When no file is specified, enumerate all DLLs and EXEs in the process. // When no file is specified, enumerate all DLLs and EXEs in the process.
if (OpenedHandles == 0) if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<HMODULE>(); - OpenedHandles = new DenseSet<HMODULE>();
+ OpenedHandles = new DenseMap<void *, unsigned>(); + OpenedHandles = new DenseSet<void *>();
EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0); EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0);
// Dummy library that represents "search all handles". // Dummy library that represents "search all handles".
@ -190,13 +353,13 @@ Index: lib/Support/Windows/DynamicLibrary.inc
if (a_handle == 0) { if (a_handle == 0) {
- MakeErrMsg(errMsg, std::string(filename) + ": Can't open : "); - MakeErrMsg(errMsg, std::string(filename) + ": Can't open : ");
- return DynamicLibrary(); - return DynamicLibrary();
+ MakeErrMsg(ErrMsg, std::string(Filename) + ": Can't open : "); + MakeErrMsg(errMsg, std::string(Filename) + ": Can't open : ");
+ return NULL; + return NULL;
} }
- if (OpenedHandles == 0) - if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<HMODULE>(); - OpenedHandles = new DenseSet<HMODULE>();
+ return (void *) a_handle; + return (void *)a_handle;
+} +}
- // If we've already loaded this library, FreeLibrary() the handle in order to - // If we've already loaded this library, FreeLibrary() the handle in order to
@ -205,7 +368,7 @@ Index: lib/Support/Windows/DynamicLibrary.inc
- FreeLibrary(a_handle); - FreeLibrary(a_handle);
+bool CloseLibraryImpl(void *DlHandle, std::string *ErrMsg) { +bool CloseLibraryImpl(void *DlHandle, std::string *ErrMsg) {
+ if (!FreeLibrary((HMODULE)DlHandle)) { + if (!FreeLibrary((HMODULE)DlHandle)) {
+ MakeErrMsg(ErrMsg, "Cannot free DLL: "); + MakeErrMsg(ErrMsg, std::string(Filename) + ": Cannot close: ");
+ return false; + return false;
+ } + }
+ return true; + return true;
@ -227,34 +390,34 @@ Index: lib/Support/Windows/DynamicLibrary.inc
+ return (void *)(intptr_t) GetProcAddress((HMODULE)DlHandle, SymbolName); + return (void *)(intptr_t) GetProcAddress((HMODULE)DlHandle, SymbolName);
} }
-// Stack probing routines are in the support library (e.g. libgcc), but we don't // Stack probing routines are in the support library (e.g. libgcc), but we don't
-// have dynamic linking on windows. Provide a hook. // have dynamic linking on windows. Provide a hook.
#define EXPLICIT_SYMBOL(SYM) \ #define EXPLICIT_SYMBOL(SYM) \
- extern "C" { extern void *SYM; } - extern "C" { extern void *SYM; }
+ extern "C" void *SYM; + extern "C" void *SYM;
#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
#include "explicit_symbols.inc" #include "explicit_symbols.inc"
@@ -113,51 +119,14 @@ extern "C" { @@ -113,51 +117,13 @@ extern "C" {
#undef EXPLICIT_SYMBOL #undef EXPLICIT_SYMBOL
#undef EXPLICIT_SYMBOL2 #undef EXPLICIT_SYMBOL2
-void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { -void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
- SmartScopedLock<true> Lock(getMutex()); - SmartScopedLock<true> Lock(getMutex());
+void PopulateSpecialSymbolsImpl(StringMap<void *>& SymMap) { +void PopulateSpecialSymbolsImpl(StringMap<void *>& SymMap) {
- // First check symbols added via AddSymbol().
- if (ExplicitSymbols) {
- StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
+#define EXPLICIT_SYMBOL(SYM) \ +#define EXPLICIT_SYMBOL(SYM) \
+ SymMap[#SYM] = &SYM; + SymMap[#SYM] = &SYM;
+#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) +#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
- // First check symbols added via AddSymbol().
- if (ExplicitSymbols) {
- StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
+#include "explicit_symbols.inc"
- if (i != ExplicitSymbols->end()) - if (i != ExplicitSymbols->end())
- return i->second; - return i->second;
- } - }
+#include "explicit_symbols.inc" -
- // Now search the libraries. - // Now search the libraries.
- if (OpenedHandles) { - if (OpenedHandles) {
- for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(), - for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(),
@ -294,18 +457,69 @@ Index: lib/Support/Windows/DynamicLibrary.inc
- -
- -
-} -}
Index: lib/Support/CMakeLists.txt Index: lib/Support/SearchForAddressOfSpecialSymbol.cpp
=================================================================== ===================================================================
--- lib/Support/CMakeLists.txt (revision 167609) --- lib/Support/SearchForAddressOfSpecialSymbol.cpp (revision 167609)
+++ lib/Support/CMakeLists.txt (working copy) +++ lib/Support/SearchForAddressOfSpecialSymbol.cpp (working copy)
@@ -80,6 +80,7 @@ add_llvm_library(LLVMSupport @@ -1,58 +0,0 @@
Threading.cpp -//===- SearchForAddressOfSpecialSymbol.cpp - Function addresses -*- C++ -*-===//
TimeValue.cpp -//
Valgrind.cpp -// The LLVM Compiler Infrastructure
+ Unix/DynamicLibrary.inc -//
Unix/Host.inc -// This file is distributed under the University of Illinois Open Source
Unix/Memory.inc -// License. See LICENSE.TXT for details.
Unix/Mutex.inc -//
-//===----------------------------------------------------------------------===//
-//
-// 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 0;
-}
-
-namespace llvm {
-void *SearchForAddressOfSpecialSymbol(const char* symbolName) {
- return DoSearch(symbolName);
-}
-} // namespace llvm
Index: lib/Support/Unix/DynamicLibrary.inc Index: lib/Support/Unix/DynamicLibrary.inc
=================================================================== ===================================================================
--- lib/Support/Unix/DynamicLibrary.inc (revision 0) --- lib/Support/Unix/DynamicLibrary.inc (revision 0)
@ -429,403 +643,3 @@ Index: lib/Support/Unix/DynamicLibrary.inc
+ +
+#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL
+} +}
Index: lib/Support/SearchForAddressOfSpecialSymbol.cpp
===================================================================
--- lib/Support/SearchForAddressOfSpecialSymbol.cpp (revision 167609)
+++ lib/Support/SearchForAddressOfSpecialSymbol.cpp (working copy)
@@ -1,58 +0,0 @@
-//===- 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 0;
-}
-
-namespace llvm {
-void *SearchForAddressOfSpecialSymbol(const char* symbolName) {
- return DoSearch(symbolName);
-}
-} // namespace llvm
Index: lib/Support/DynamicLibrary.cpp
===================================================================
--- lib/Support/DynamicLibrary.cpp (revision 167609)
+++ lib/Support/DynamicLibrary.cpp (working copy)
@@ -14,176 +14,226 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Config/config.h"
#include <cstdio>
#include <cstring>
-// Collection of symbol name/value pairs to be searched prior to any libraries.
-static llvm::StringMap<void *> *ExplicitSymbols = 0;
+using namespace llvm;
+using namespace llvm::sys;
+// Platform-specific implementations are required to define these function.
+// They do not need to be reentrant; locking is done by the caller.
+
+// Open the shared library called filename and return its handle. If filename
+// is NULL, return a handle for searching symbols in the whole process.
+static void *OpenLibraryImpl(const char *Filename, std::string *ErrMsg);
+// Close the shared library.
+static bool CloseLibraryImpl(void *DlHandle, std::string *ErrMsg);
+// Get the address of the symbol named symname from the library with dlhandle.
+// Global is true if this is part of a search spanning all OpenedHandles.
+static void *GetAddressOfSymbolImpl(void *DlHandle, const char *SymbolName,
+ bool Global);
+// Inject special platform symbols into the map of explicitly defined symbols.
+static void PopulateSpecialSymbolsImpl(StringMap<void *>& SymMap);
+
namespace {
+struct SpecialSymbolHolder {
+ SpecialSymbolHolder() {
+ PopulateSpecialSymbolsImpl(Map);
+ }
+ // Symbol name/value pairs to be searched prior to any libraries.
+ StringMap<void *> Map;
+};
+}
+// Platform specific symbols, searched after libraries
+static SpecialSymbolHolder *SpecialSymbols = 0;
+
+// User provided symbols, searched before libraries
+static StringMap<void *> *ExplicitSymbols = 0;
+
+namespace {
struct ExplicitSymbolsDeleter {
~ExplicitSymbolsDeleter() {
delete ExplicitSymbols;
}
};
-
}
-
static ExplicitSymbolsDeleter Dummy;
-
static llvm::sys::SmartMutex<true>& getMutex() {
static llvm::sys::SmartMutex<true> HandlesMutex;
return HandlesMutex;
}
-void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
- void *symbolValue) {
- SmartScopedLock<true> lock(getMutex());
- if (ExplicitSymbols == 0)
- ExplicitSymbols = new llvm::StringMap<void*>();
- (*ExplicitSymbols)[symbolName] = symbolValue;
-}
-
char llvm::sys::DynamicLibrary::Invalid = 0;
-#ifdef LLVM_ON_WIN32
+static DenseMap<void *, unsigned> *OpenedHandles;
+static const unsigned PermanentRefCount = (unsigned)-1;
-#include "Windows/DynamicLibrary.inc"
+DynamicLibrary DynamicLibrary::getLibrary(const char *Filename, bool Permanent,
+ std::string *ErrMsg) {
+ SmartScopedLock<true> lock(getMutex());
-#else
+ void *Handle = OpenLibraryImpl(Filename, ErrMsg);
+ if (Handle == 0) {
+ return DynamicLibrary();
+ }
+ if (OpenedHandles == 0)
+ OpenedHandles = new DenseMap<void *, unsigned>();
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-using namespace llvm;
-using namespace llvm::sys;
+ // If we've already loaded this library, dlclose() the handle in order to
+ // keep the internal refcount at +1.
+ unsigned &RefCount = (*OpenedHandles)[Handle];
+ if (RefCount > 0)
+ CloseLibraryImpl(Handle, 0);
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
+ if (Permanent)
+ RefCount = PermanentRefCount;
+ else
+ ++RefCount;
-static DenseSet<void *> *OpenedHandles = 0;
+ return DynamicLibrary(Handle);
+}
-DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
- std::string *errMsg) {
- SmartScopedLock<true> lock(getMutex());
+static bool UnloadHandle(void *DlHandle, std::string *ErrMsg) {
+ // Caller must lock!
- void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
- if (handle == 0) {
- if (errMsg) *errMsg = dlerror();
- return DynamicLibrary();
+ if (!DlHandle) {
+ if (ErrMsg)
+ *ErrMsg = "Cannot unload invalid DynamicLibrary.";
+ return false;
}
-#ifdef __CYGWIN__
- // Cygwin searches symbols only in the main
- // with the handle of dlopen(NULL, RTLD_GLOBAL).
- if (filename == NULL)
- handle = RTLD_DEFAULT;
-#endif
+ assert(OpenedHandles && "No dynamic libraries have been loaded.");
- if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<void *>();
+ SmartScopedLock<true> Lock(getMutex());
- // 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);
+ DenseMap<void *, unsigned>::iterator I = OpenedHandles->find(DlHandle);
+ if (I == OpenedHandles->end()) {
+ if (ErrMsg)
+ *ErrMsg = "DynamicLibrary has already been closed";
+ return false;
+ }
+ if (I->second == PermanentRefCount) {
+ if (ErrMsg)
+ *ErrMsg = std::string("Cannot close permanent library.");
+ return false;
+ }
+ --I->second;
+ if (I->second == 0)
+ return CloseLibraryImpl(DlHandle, ErrMsg);
- return DynamicLibrary(handle);
+ // Ref count not yet 0, but no error.
+ return true;
}
-void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
- if (!isValid())
- return NULL;
- return dlsym(Data, symbolName);
-}
+bool DynamicLibrary::Unload(const char *Filename, std::string *ErrMsg) {
+ if (!OpenedHandles) {
+ if (ErrMsg)
+ *ErrMsg = "No dynamic libraries have been loaded.";
+ return false;
+ }
-#else
+ SmartScopedLock<true> Lock(getMutex());
+ void *DlHandle = OpenLibraryImpl(Filename, ErrMsg);
+ if (!DlHandle) {
+ if (ErrMsg) {
+ // The error message from OpenLibraryImpl() will complain about
+ // not being able to open the library which is confusing for a
+ // call to Unload().
+ *ErrMsg = std::string("Cannot find dynamic library ") + Filename;
+ }
+ return false;
+ }
-using namespace llvm;
-using namespace llvm::sys;
+ return UnloadHandle(DlHandle, ErrMsg);
+}
-DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
- std::string *errMsg) {
- if (errMsg) *errMsg = "dlopen() not supported on this platform";
- return DynamicLibrary();
+bool DynamicLibrary::Unload(std::string *ErrMsg) {
+ return UnloadHandle(Data, ErrMsg);
}
-void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
- return NULL;
+void llvm::sys::DynamicLibrary::AddSymbol(StringRef SymbolName,
+ void *SymbolValue) {
+ SmartScopedLock<true> lock(getMutex());
+ if (ExplicitSymbols == 0)
+ ExplicitSymbols = new StringMap<void *>();
+ (*ExplicitSymbols)[SymbolName] = SymbolValue;
}
-#endif
+void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
+ return GetAddressOfSymbolImpl(Data, SymbolName, false /*Global*/);
+}
-namespace llvm {
-void *SearchForAddressOfSpecialSymbol(const char* symbolName);
+void *DynamicLibrary::SearchForLibrarySymbol(const char *SymbolName) {
+ if (OpenedHandles) {
+ for (DenseMap<void *, unsigned>::iterator I = OpenedHandles->begin(),
+ E = OpenedHandles->end(); I != E; ++I) {
+ void *ptr = GetAddressOfSymbolImpl(I->first, SymbolName, true /*Global*/);
+ if (ptr) {
+ return ptr;
+ }
+ }
+ }
+ return NULL;
}
-void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
+void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
SmartScopedLock<true> Lock(getMutex());
// First check symbols added via AddSymbol().
if (ExplicitSymbols) {
- StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
+ StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
if (i != ExplicitSymbols->end())
return i->second;
}
-#if HAVE_DLFCN_H
// Now search the libraries.
- if (OpenedHandles) {
- 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;
- }
- }
+ if (void *ptr = SearchForLibrarySymbol(SymbolName))
+ return ptr;
+
+ // Finally check platform specific symbols.
+ if (SpecialSymbols) {
+ StringMap<void *>::iterator i = SpecialSymbols->Map.find(SymbolName);
+
+ if (i != SpecialSymbols->Map.end())
+ return i->second;
}
-#endif
- if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
- return Result;
+ return 0;
+}
-// 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);
- }
+#ifdef LLVM_ON_WIN32
+
+#include "Windows/DynamicLibrary.inc"
+
#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 0;
+#if HAVE_DLFCN_H
+#include "Unix/DynamicLibrary.inc"
+#else
+
+void *OpenLibraryImpl(const char *, std::string *errMsg) {
+ if (errMsg) *errMsg = "dlopen() not supported on this platform";
+ return NULL;
}
+bool CloseLibraryImpl(void *, std::string *ErrMsg) {
+ if (errMsg) *errMsg = "dlclose() not supported on this platform";
+ retun false;
+}
+void *GetAddressOfSymbolImpl(void *, const char *, bool) {
+ return NULL;
+}
+void PopulateSpecialSymbolsImpl(StringMap<void *>&) {
+}
+#endif
+
+
#endif // LLVM_ON_WIN32