cling/patches/llvm_dynlib_reshuffle.diff
Axel Naumann b288115cb2 Forgot Unix/DynamicLibrary.inc again...
git-svn-id: http://root.cern.ch/svn/root/trunk@47275 27541ba8-7e3a-0410-8455-c3a389f83636
2012-11-14 16:02:59 +00:00

646 lines
20 KiB
Diff

Index: include/llvm/Support/DynamicLibrary.h
===================================================================
--- include/llvm/Support/DynamicLibrary.h (revision 167609)
+++ include/llvm/Support/DynamicLibrary.h (working copy)
@@ -91,6 +91,13 @@ namespace sys {
return SearchForAddressOfSymbol(symbolName.c_str());
}
+ /// This function will search through all previously loaded dynamic
+ /// libraries for the symbol \p symbolName, but not through explicitly
+ /// provided symbols (AddSymbol()). If it is found, the address of
+ /// that symbol is returned. If not, null is returned.
+ /// @brief Search through libraries for address of a symbol
+ static void *SearchForLibrarySymbol(const char *SymbolName);
+
/// This functions permanently adds the symbol \p symbolName with the
/// value \p symbolValue. These symbols are searched before any
/// libraries.
Index: lib/Support/Unix/DynamicLibrary.inc
===================================================================
--- lib/Support/Unix/DynamicLibrary.inc (revision 0)
+++ lib/Support/Unix/DynamicLibrary.inc (revision 0)
@@ -0,0 +1,118 @@
+//===--- 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 dlsym specific implementation of DynamicLibrary.
+//
+//===----------------------------------------------------------------------===//
+
+#include <dlfcn.h>
+
+static void MakeDlErrMsg(std::string *ErrMsg) {
+ if (ErrMsg) {
+ *ErrMsg = dlerror();
+ } else {
+ // Flush error state whether or not ErrMsg is provided.
+ dlerror();
+ }
+}
+
+void *OpenLibraryImpl(const char *Filename, std::string *ErrMsg) {
+ void *Handle = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL);
+ if (Handle == 0) {
+ MakeDlErrMsg(ErrMsg);
+ return NULL;
+ }
+
+#ifdef __CYGWIN__
+ // Cygwin searches symbols only in the main
+ // with the handle of dlopen(NULL, RTLD_GLOBAL).
+ if (Filename == NULL)
+ Handle = RTLD_DEFAULT;
+#endif
+ return Handle;
+}
+
+bool CloseLibraryImpl(void *DlHandle, std::string *ErrMsg) {
+ if (dlclose(DlHandle)) {
+ MakeDlErrMsg(ErrMsg);
+ return false;
+ }
+ return true;
+}
+
+void *GetAddressOfSymbolImpl(void *DlHandle, const char *SymbolName,
+ bool /*Global*/) {
+ return dlsym(DlHandle, SymbolName);
+}
+
+#include <string.h>
+
+// Must declare the symbols in the global namespace.
+void PopulateSpecialSymbolsImpl(StringMap<void *>& SymMap) {
+// This macro returns the address of a well-known, explicit symbol
+#define EXPLICIT_SYMBOL(SYM) \
+ SymMap[#SYM] = &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
+
+#define EXPLICIT_SYMBOL(SYM) \
+ extern "C" void *SYM; symMap[#SYM] = &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
+}
Index: lib/Support/DynamicLibrary.cpp
===================================================================
--- 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!
//
//===----------------------------------------------------------------------===//
@@ -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/Windows/DynamicLibrary.inc
===================================================================
--- lib/Support/Windows/DynamicLibrary.inc (revision 167609)
+++ lib/Support/Windows/DynamicLibrary.inc (working copy)
@@ -31,16 +31,8 @@
#pragma comment(lib, "dbghelp.lib")
#endif
-namespace llvm {
-using namespace sys;
+using namespace llvm;
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Win32 specific code
-//=== and must not be UNIX code.
-//===----------------------------------------------------------------------===//
-
-static DenseSet<HMODULE> *OpenedHandles;
-
extern "C" {
static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName,
@@ -63,49 +55,61 @@ extern "C" {
#endif
stricmp(ModuleName, "msvcrt20") != 0 &&
stricmp(ModuleName, "msvcrt40") != 0) {
- OpenedHandles->insert((HMODULE)ModuleBase);
+ OpenedHandles->insert((HMODULE)ModuleBase);
}
return TRUE;
}
-}
+} // extern "C"
-DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
- std::string *errMsg) {
- SmartScopedLock<true> lock(getMutex());
-
- if (!filename) {
+void *OpenLibraryImpl(const char *Filename, std::string *ErrMsg) {
+ if (!Filename) {
// When no file is specified, enumerate all DLLs and EXEs in the process.
if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<HMODULE>();
+ OpenedHandles = new DenseSet<void *>();
EnumerateLoadedModules(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 &OpenedHandles;
}
- HMODULE a_handle = LoadLibrary(filename);
+ HMODULE a_handle = LoadLibrary(Filename);
if (a_handle == 0) {
- MakeErrMsg(errMsg, std::string(filename) + ": Can't open : ");
- return DynamicLibrary();
+ MakeErrMsg(ErrMsg, std::string(Filename) + ": Can't open : ");
+ return NULL;
}
- if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<HMODULE>();
+ return (void *)a_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);
+bool CloseLibraryImpl(void *DlHandle, std::string *ErrMsg) {
+ if (!FreeLibrary((HMODULE)DlHandle)) {
+ MakeErrMsg(ErrMsg, "Cannot free DLL: ");
+ return false;
+ }
+ return true;
+}
- return DynamicLibrary(a_handle);
+void *GetAddressOfSymbolImpl(void *DlHandle, const char *SymbolName,
+ bool Global) {
+ if (DlHandle == &OpenedHandles) {
+ // Dummy library that represents "search all handles".
+ if (Global) {
+ // All libraries are already being searched, do not recurse.
+ return 0;
+ } else {
+ // Perform a global symbol search through all libraries.
+ DynamicLibrary::SearchForLibrarySymbol(SymbolName);
+ }
+ }
+ return (void *)(intptr_t) GetProcAddress((HMODULE)DlHandle, SymbolName);
}
// Stack probing routines are in the support library (e.g. libgcc), but we don't
// have dynamic linking on windows. Provide a hook.
#define EXPLICIT_SYMBOL(SYM) \
- extern "C" { extern void *SYM; }
+ extern "C" void *SYM;
#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
#include "explicit_symbols.inc"
@@ -113,51 +117,13 @@ extern "C" {
#undef EXPLICIT_SYMBOL
#undef EXPLICIT_SYMBOL2
-void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
- SmartScopedLock<true> Lock(getMutex());
+void PopulateSpecialSymbolsImpl(StringMap<void *>& SymMap) {
+#define EXPLICIT_SYMBOL(SYM) \
+ SymMap[#SYM] = &SYM;
+#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())
- return i->second;
- }
-
- // Now search the libraries.
- if (OpenedHandles) {
- 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)) return (void*)&SYM;
- #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \
- if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO;
-
- {
- #include "explicit_symbols.inc"
- }
-
- #undef EXPLICIT_SYMBOL
- #undef EXPLICIT_SYMBOL2
-
- return 0;
+#undef EXPLICIT_SYMBOL
+#undef EXPLICIT_SYMBOL2
}
-
-
-void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
- if (!isValid())
- return NULL;
- if (Data == &OpenedHandles)
- return SearchForAddressOfSymbol(symbolName);
- return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName);
-}
-
-
-}
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/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