aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp b/contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp
new file mode 100644
index 000000000000..531c035ab926
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp
@@ -0,0 +1,253 @@
+//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the operating system DynamicLibrary concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm-c/Support.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Mutex.h"
+#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 = nullptr;
+
+public:
+ static void *DLOpen(const char *Filename, std::string *Err);
+ static void DLClose(void *Handle);
+ static void *DLSym(void *Handle, const char *Symbol);
+
+ HandleSet() = default;
+ ~HandleSet();
+
+ HandleList::iterator Find(void *Handle) { return find(Handles, Handle); }
+
+ bool Contains(void *Handle) {
+ return Handle == Process || Find(Handle) != Handles.end();
+ }
+
+ bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true,
+ bool AllowDuplicates = false) {
+#ifdef _WIN32
+ assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
+#endif
+ assert((!AllowDuplicates || !CanClose) &&
+ "CanClose must be false if AllowDuplicates is true.");
+
+ if (LLVM_LIKELY(!IsProcess)) {
+ if (!AllowDuplicates && Find(Handle) != Handles.end()) {
+ if (CanClose)
+ DLClose(Handle);
+ return false;
+ }
+ Handles.push_back(Handle);
+ } else {
+#ifndef _WIN32
+ if (Process) {
+ if (CanClose)
+ DLClose(Process);
+ if (Process == Handle)
+ return false;
+ }
+#endif
+ Process = Handle;
+ }
+ return true;
+ }
+
+ void CloseLibrary(void *Handle) {
+ DLClose(Handle);
+ HandleList::iterator it = Find(Handle);
+ if (it != Handles.end()) {
+ Handles.erase(it);
+ }
+ }
+
+ void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
+ if (Order & SO_LoadOrder) {
+ for (void *Handle : Handles) {
+ if (void *Ptr = DLSym(Handle, Symbol))
+ return Ptr;
+ }
+ } else {
+ for (void *Handle : llvm::reverse(Handles)) {
+ if (void *Ptr = DLSym(Handle, Symbol))
+ return Ptr;
+ }
+ }
+ return nullptr;
+ }
+
+ void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
+ assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
+ "Invalid Ordering");
+
+ if (!Process || (Order & SO_LoadedFirst)) {
+ if (void *Ptr = LibLookup(Symbol, Order))
+ return Ptr;
+ }
+ if (Process) {
+ // Use OS facilities to search the current binary and all loaded libs.
+ if (void *Ptr = DLSym(Process, Symbol))
+ return Ptr;
+
+ // Search any libs that might have been skipped because of RTLD_LOCAL.
+ if (Order & SO_LoadedLast) {
+ if (void *Ptr = LibLookup(Symbol, Order))
+ return Ptr;
+ }
+ }
+ return nullptr;
+ }
+};
+
+namespace {
+
+struct Globals {
+ // Collection of symbol name/value pairs to be searched prior to any
+ // libraries.
+ llvm::StringMap<void *> ExplicitSymbols;
+ // Collections of known library handles.
+ DynamicLibrary::HandleSet OpenedHandles;
+ DynamicLibrary::HandleSet OpenedTemporaryHandles;
+ // Lock for ExplicitSymbols, OpenedHandles, and OpenedTemporaryHandles.
+ llvm::sys::SmartMutex<true> SymbolsMutex;
+};
+
+Globals &getGlobals() {
+ static Globals G;
+ return G;
+}
+
+} // namespace
+
+#ifdef _WIN32
+
+#include "Windows/DynamicLibrary.inc"
+
+#else
+
+#include "Unix/DynamicLibrary.inc"
+
+#endif
+
+char DynamicLibrary::Invalid;
+DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
+ DynamicLibrary::SO_Linker;
+
+namespace llvm {
+void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
+ return DoSearch(SymbolName); // DynamicLibrary.inc
+}
+} // namespace llvm
+
+void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
+ auto &G = getGlobals();
+ SmartScopedLock<true> Lock(G.SymbolsMutex);
+ G.ExplicitSymbols[SymbolName] = SymbolValue;
+}
+
+DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
+ std::string *Err) {
+ auto &G = getGlobals();
+ void *Handle = HandleSet::DLOpen(FileName, Err);
+ if (Handle != &Invalid) {
+ SmartScopedLock<true> Lock(G.SymbolsMutex);
+ G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
+ }
+
+ return DynamicLibrary(Handle);
+}
+
+DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
+ std::string *Err) {
+ auto &G = getGlobals();
+ SmartScopedLock<true> Lock(G.SymbolsMutex);
+ // If we've already loaded this library, tell the caller.
+ if (!G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ false,
+ /*CanClose*/ false))
+ *Err = "Library already loaded";
+
+ return DynamicLibrary(Handle);
+}
+
+DynamicLibrary DynamicLibrary::getLibrary(const char *FileName,
+ std::string *Err) {
+ assert(FileName && "Use getPermanentLibrary() for opening process handle");
+ void *Handle = HandleSet::DLOpen(FileName, Err);
+ if (Handle != &Invalid) {
+ auto &G = getGlobals();
+ SmartScopedLock<true> Lock(G.SymbolsMutex);
+ G.OpenedTemporaryHandles.AddLibrary(Handle, /*IsProcess*/ false,
+ /*CanClose*/ false,
+ /*AllowDuplicates*/ true);
+ }
+ return DynamicLibrary(Handle);
+}
+
+void DynamicLibrary::closeLibrary(DynamicLibrary &Lib) {
+ auto &G = getGlobals();
+ SmartScopedLock<true> Lock(G.SymbolsMutex);
+ if (Lib.isValid()) {
+ G.OpenedTemporaryHandles.CloseLibrary(Lib.Data);
+ Lib.Data = &Invalid;
+ }
+}
+
+void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
+ if (!isValid())
+ return nullptr;
+ return HandleSet::DLSym(Data, SymbolName);
+}
+
+void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
+ {
+ auto &G = getGlobals();
+ SmartScopedLock<true> Lock(G.SymbolsMutex);
+
+ // First check symbols added via AddSymbol().
+ StringMap<void *>::iterator i = G.ExplicitSymbols.find(SymbolName);
+
+ if (i != G.ExplicitSymbols.end())
+ return i->second;
+
+ // Now search the libraries.
+ if (void *Ptr = G.OpenedHandles.Lookup(SymbolName, SearchOrder))
+ return Ptr;
+ if (void *Ptr = G.OpenedTemporaryHandles.Lookup(SymbolName, SearchOrder))
+ return Ptr;
+ }
+
+ return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
+}
+
+//===----------------------------------------------------------------------===//
+// C API.
+//===----------------------------------------------------------------------===//
+
+LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
+ return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
+}
+
+void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
+ return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
+}
+
+void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
+ return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
+}