brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 61566d3 Raw
254 lines · cpp
1//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements the operating system DynamicLibrary concept.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/Support/DynamicLibrary.h"14#include "llvm-c/Support.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/StringMap.h"17#include "llvm/Config/config.h"18#include "llvm/Support/Mutex.h"19#include <vector>20 21using namespace llvm;22using namespace llvm::sys;23 24// All methods for HandleSet should be used holding SymbolsMutex.25class DynamicLibrary::HandleSet {26  using HandleList = std::vector<void *>;27  HandleList Handles;28  void *Process = &Invalid;29 30public:31  static void *DLOpen(const char *Filename, std::string *Err);32  static void DLClose(void *Handle);33  static void *DLSym(void *Handle, const char *Symbol);34 35  HandleSet() = default;36  ~HandleSet();37 38  HandleList::iterator Find(void *Handle) { return find(Handles, Handle); }39 40  bool Contains(void *Handle) {41    return Handle == Process || Find(Handle) != Handles.end();42  }43 44  bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true,45                  bool AllowDuplicates = false) {46#ifdef _WIN3247    assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");48#endif49    assert((!AllowDuplicates || !CanClose) &&50           "CanClose must be false if AllowDuplicates is true.");51 52    if (LLVM_LIKELY(!IsProcess)) {53      if (!AllowDuplicates && Find(Handle) != Handles.end()) {54        if (CanClose)55          DLClose(Handle);56        return false;57      }58      Handles.push_back(Handle);59    } else {60#ifndef _WIN3261      if (Process != &Invalid) {62        if (CanClose)63          DLClose(Process);64        if (Process == Handle)65          return false;66      }67#endif68      Process = Handle;69    }70    return true;71  }72 73  void CloseLibrary(void *Handle) {74    DLClose(Handle);75    HandleList::iterator it = Find(Handle);76    if (it != Handles.end()) {77      Handles.erase(it);78    }79  }80 81  void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {82    if (Order & SO_LoadOrder) {83      for (void *Handle : Handles) {84        if (void *Ptr = DLSym(Handle, Symbol))85          return Ptr;86      }87    } else {88      for (void *Handle : llvm::reverse(Handles)) {89        if (void *Ptr = DLSym(Handle, Symbol))90          return Ptr;91      }92    }93    return nullptr;94  }95 96  void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {97    assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&98           "Invalid Ordering");99 100    if (Process == &Invalid || (Order & SO_LoadedFirst)) {101      if (void *Ptr = LibLookup(Symbol, Order))102        return Ptr;103    }104    if (Process != &Invalid) {105      // Use OS facilities to search the current binary and all loaded libs.106      if (void *Ptr = DLSym(Process, Symbol))107        return Ptr;108 109      // Search any libs that might have been skipped because of RTLD_LOCAL.110      if (Order & SO_LoadedLast) {111        if (void *Ptr = LibLookup(Symbol, Order))112          return Ptr;113      }114    }115    return nullptr;116  }117};118 119namespace {120 121struct Globals {122  // Collection of symbol name/value pairs to be searched prior to any123  // libraries.124  llvm::StringMap<void *> ExplicitSymbols;125  // Collections of known library handles.126  DynamicLibrary::HandleSet OpenedHandles;127  DynamicLibrary::HandleSet OpenedTemporaryHandles;128  // Lock for ExplicitSymbols, OpenedHandles, and OpenedTemporaryHandles.129  llvm::sys::SmartMutex<true> SymbolsMutex;130};131 132Globals &getGlobals() {133  static Globals G;134  return G;135}136 137} // namespace138 139#ifdef _WIN32140 141#include "Windows/DynamicLibrary.inc"142 143#else144 145#include "Unix/DynamicLibrary.inc"146 147#endif148 149char DynamicLibrary::Invalid;150DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =151    DynamicLibrary::SO_Linker;152 153namespace llvm {154void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {155  return DoSearch(SymbolName); // DynamicLibrary.inc156}157} // namespace llvm158 159void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {160  auto &G = getGlobals();161  SmartScopedLock<true> Lock(G.SymbolsMutex);162  G.ExplicitSymbols[SymbolName] = SymbolValue;163}164 165DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,166                                                   std::string *Err) {167  auto &G = getGlobals();168  void *Handle = HandleSet::DLOpen(FileName, Err);169  if (Handle != &Invalid) {170    SmartScopedLock<true> Lock(G.SymbolsMutex);171    G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);172  }173 174  return DynamicLibrary(Handle);175}176 177DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,178                                                   std::string *Err) {179  auto &G = getGlobals();180  SmartScopedLock<true> Lock(G.SymbolsMutex);181  // If we've already loaded this library, tell the caller.182  if (!G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ false,183                                  /*CanClose*/ false))184    *Err = "Library already loaded";185 186  return DynamicLibrary(Handle);187}188 189DynamicLibrary DynamicLibrary::getLibrary(const char *FileName,190                                          std::string *Err) {191  assert(FileName && "Use getPermanentLibrary() for opening process handle");192  void *Handle = HandleSet::DLOpen(FileName, Err);193  if (Handle != &Invalid) {194    auto &G = getGlobals();195    SmartScopedLock<true> Lock(G.SymbolsMutex);196    G.OpenedTemporaryHandles.AddLibrary(Handle, /*IsProcess*/ false,197                                        /*CanClose*/ false,198                                        /*AllowDuplicates*/ true);199  }200  return DynamicLibrary(Handle);201}202 203void DynamicLibrary::closeLibrary(DynamicLibrary &Lib) {204  auto &G = getGlobals();205  SmartScopedLock<true> Lock(G.SymbolsMutex);206  if (Lib.isValid()) {207    G.OpenedTemporaryHandles.CloseLibrary(Lib.Data);208    Lib.Data = &Invalid;209  }210}211 212void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {213  if (!isValid())214    return nullptr;215  return HandleSet::DLSym(Data, SymbolName);216}217 218void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {219  {220    auto &G = getGlobals();221    SmartScopedLock<true> Lock(G.SymbolsMutex);222 223    // First check symbols added via AddSymbol().224    StringMap<void *>::iterator i = G.ExplicitSymbols.find(SymbolName);225 226    if (i != G.ExplicitSymbols.end())227      return i->second;228 229    // Now search the libraries.230    if (void *Ptr = G.OpenedHandles.Lookup(SymbolName, SearchOrder))231      return Ptr;232    if (void *Ptr = G.OpenedTemporaryHandles.Lookup(SymbolName, SearchOrder))233      return Ptr;234  }235 236  return llvm::SearchForAddressOfSpecialSymbol(SymbolName);237}238 239//===----------------------------------------------------------------------===//240// C API.241//===----------------------------------------------------------------------===//242 243LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {244  return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);245}246 247void *LLVMSearchForAddressOfSymbol(const char *symbolName) {248  return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);249}250 251void LLVMAddSymbol(const char *symbolName, void *symbolValue) {252  return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);253}254