diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/llvm12/lib/Support/DynamicLibrary.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/llvm12/lib/Support/DynamicLibrary.cpp')
-rw-r--r-- | contrib/libs/llvm12/lib/Support/DynamicLibrary.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/lib/Support/DynamicLibrary.cpp b/contrib/libs/llvm12/lib/Support/DynamicLibrary.cpp new file mode 100644 index 0000000000..bdf7462367 --- /dev/null +++ b/contrib/libs/llvm12/lib/Support/DynamicLibrary.cpp @@ -0,0 +1,213 @@ +//===-- 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/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Config/config.h" +#include "llvm/Support/ManagedStatic.h" +#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 find(Handles, Handle); } + + bool Contains(void *Handle) { + return Handle == Process || Find(Handle) != Handles.end(); + } + + bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) { +#ifdef _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 _WIN32 + if (Process) { + if (CanClose) + DLClose(Process); + if (Process == Handle) + return false; + } +#endif + Process = Handle; + } + return true; + } + + 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 { +// 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; +} + +#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 +} +} + +void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) { + SmartScopedLock<true> Lock(*SymbolsMutex); + (*ExplicitSymbols)[SymbolName] = SymbolValue; +} + +DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, + std::string *Err) { + // Force OpenedHandles to be added into the ManagedStatic list before any + // ManagedStatic can be added from static constructors in HandleSet::DLOpen. + HandleSet& HS = *OpenedHandles; + + void *Handle = HandleSet::DLOpen(FileName, Err); + if (Handle != &Invalid) { + SmartScopedLock<true> Lock(*SymbolsMutex); + HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); + } + + 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, 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); +} |