1447762daSMichael J. Spencer //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
2447762daSMichael J. Spencer //
3447762daSMichael J. Spencer //                     The LLVM Compiler Infrastructure
4447762daSMichael J. Spencer //
5447762daSMichael J. Spencer // This file is distributed under the University of Illinois Open Source
6447762daSMichael J. Spencer // License. See LICENSE.TXT for details.
7447762daSMichael J. Spencer //
8447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
9447762daSMichael J. Spencer //
10cfe341f5SHans Wennborg //  This file implements the operating system DynamicLibrary concept.
11447762daSMichael J. Spencer //
12447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
13447762daSMichael J. Spencer 
14447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h"
158a8cd2baSChandler Carruth #include "llvm-c/Support.h"
16ed0881b2SChandler Carruth #include "llvm/ADT/DenseSet.h"
17ed0881b2SChandler Carruth #include "llvm/ADT/StringMap.h"
18447762daSMichael J. Spencer #include "llvm/Config/config.h"
198a8cd2baSChandler Carruth #include "llvm/Support/ManagedStatic.h"
20ed0881b2SChandler Carruth #include "llvm/Support/Mutex.h"
21447762daSMichael J. Spencer #include <cstdio>
22447762daSMichael J. Spencer #include <cstring>
23*70c377a3SFrederich Munch #include <vector>
24447762daSMichael J. Spencer 
25*70c377a3SFrederich Munch using namespace llvm;
26*70c377a3SFrederich Munch using namespace llvm::sys;
27b8c236a6SFrederich Munch 
28*70c377a3SFrederich Munch // All methods for HandleSet should be used holding SymbolsMutex.
29*70c377a3SFrederich Munch class DynamicLibrary::HandleSet {
30*70c377a3SFrederich Munch   typedef std::vector<void *> HandleList;
31*70c377a3SFrederich Munch   HandleList Handles;
32*70c377a3SFrederich Munch   void *Process;
33*70c377a3SFrederich Munch 
34*70c377a3SFrederich Munch public:
35*70c377a3SFrederich Munch   static void *DLOpen(const char *Filename, std::string *Err);
36*70c377a3SFrederich Munch   static void DLClose(void *Handle);
37*70c377a3SFrederich Munch   static void *DLSym(void *Handle, const char *Symbol);
38*70c377a3SFrederich Munch 
39*70c377a3SFrederich Munch   HandleSet() : Process(nullptr) {}
40*70c377a3SFrederich Munch   ~HandleSet();
41*70c377a3SFrederich Munch 
42*70c377a3SFrederich Munch   HandleList::iterator Find(void *Handle) {
43*70c377a3SFrederich Munch     return std::find(Handles.begin(), Handles.end(), Handle);
449f40457dSFrederich Munch   }
4504bc405aSJordy Rose 
46*70c377a3SFrederich Munch   bool Contains(void *Handle) {
47*70c377a3SFrederich Munch     return Handle == Process || Find(Handle) != Handles.end();
48*70c377a3SFrederich Munch   }
49*70c377a3SFrederich Munch 
50*70c377a3SFrederich Munch   bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
51*70c377a3SFrederich Munch #ifdef LLVM_ON_WIN32
52*70c377a3SFrederich Munch     assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
53*70c377a3SFrederich Munch #endif
54*70c377a3SFrederich Munch 
55*70c377a3SFrederich Munch     if (LLVM_LIKELY(!IsProcess)) {
56*70c377a3SFrederich Munch       if (Find(Handle) != Handles.end()) {
57*70c377a3SFrederich Munch         if (CanClose)
58*70c377a3SFrederich Munch           DLClose(Handle);
59*70c377a3SFrederich Munch         return false;
60*70c377a3SFrederich Munch       }
61*70c377a3SFrederich Munch       Handles.push_back(Handle);
62*70c377a3SFrederich Munch     } else {
63*70c377a3SFrederich Munch #ifndef LLVM_ON_WIN32
64*70c377a3SFrederich Munch       if (Process) {
65*70c377a3SFrederich Munch         if (CanClose)
66*70c377a3SFrederich Munch           DLClose(Process);
67*70c377a3SFrederich Munch         if (Process == Handle)
68*70c377a3SFrederich Munch           return false;
69*70c377a3SFrederich Munch       }
70*70c377a3SFrederich Munch #endif
71*70c377a3SFrederich Munch       Process = Handle;
72*70c377a3SFrederich Munch     }
73*70c377a3SFrederich Munch     return true;
74*70c377a3SFrederich Munch   }
75*70c377a3SFrederich Munch 
76*70c377a3SFrederich Munch   void *Lookup(const char *Symbol) {
77*70c377a3SFrederich Munch     // Process handle gets first try.
78*70c377a3SFrederich Munch     if (Process) {
79*70c377a3SFrederich Munch       if (void *Ptr = DLSym(Process, Symbol))
80*70c377a3SFrederich Munch         return Ptr;
81*70c377a3SFrederich Munch #ifndef NDEBUG
82*70c377a3SFrederich Munch       for (void *Handle : Handles)
83*70c377a3SFrederich Munch         assert(!DLSym(Handle, Symbol) && "Symbol exists in non process handle");
84*70c377a3SFrederich Munch #endif
85*70c377a3SFrederich Munch     } else {
86*70c377a3SFrederich Munch       // Iterate in reverse, so newer libraries/symbols override older.
87*70c377a3SFrederich Munch       for (auto &&I = Handles.rbegin(), E = Handles.rend(); I != E; ++I) {
88*70c377a3SFrederich Munch         if (void *Ptr = DLSym(*I, Symbol))
89*70c377a3SFrederich Munch           return Ptr;
90*70c377a3SFrederich Munch       }
91*70c377a3SFrederich Munch     }
92*70c377a3SFrederich Munch     return nullptr;
93*70c377a3SFrederich Munch   }
94*70c377a3SFrederich Munch };
95*70c377a3SFrederich Munch 
96*70c377a3SFrederich Munch namespace {
97*70c377a3SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries.
98*70c377a3SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
99*70c377a3SFrederich Munch // Collection of known library handles.
100*70c377a3SFrederich Munch static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
101*70c377a3SFrederich Munch // Lock for ExplicitSymbols and OpenedHandles.
102*70c377a3SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
103*70c377a3SFrederich Munch }
104b8c236a6SFrederich Munch 
105447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32
106447762daSMichael J. Spencer 
107447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc"
108447762daSMichael J. Spencer 
109447762daSMichael J. Spencer #else
110447762daSMichael J. Spencer 
111*70c377a3SFrederich Munch #include "Unix/DynamicLibrary.inc"
112a19917daSJordy Rose 
113447762daSMichael J. Spencer #endif
114447762daSMichael J. Spencer 
115*70c377a3SFrederich Munch char DynamicLibrary::Invalid;
116*70c377a3SFrederich Munch 
117447762daSMichael J. Spencer namespace llvm {
118*70c377a3SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
119*70c377a3SFrederich Munch   return DoSearch(SymbolName); // DynamicLibrary.inc
120*70c377a3SFrederich Munch }
121447762daSMichael J. Spencer }
122447762daSMichael J. Spencer 
123*70c377a3SFrederich Munch void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
124*70c377a3SFrederich Munch   SmartScopedLock<true> Lock(*SymbolsMutex);
125*70c377a3SFrederich Munch   (*ExplicitSymbols)[SymbolName] = SymbolValue;
126*70c377a3SFrederich Munch }
127*70c377a3SFrederich Munch 
128*70c377a3SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
129*70c377a3SFrederich Munch                                                    std::string *Err) {
130*70c377a3SFrederich Munch   SmartScopedLock<true> Lock(*SymbolsMutex);
131*70c377a3SFrederich Munch   void *Handle = HandleSet::DLOpen(FileName, Err);
132*70c377a3SFrederich Munch   if (Handle != &Invalid)
133*70c377a3SFrederich Munch     OpenedHandles->AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
134*70c377a3SFrederich Munch 
135*70c377a3SFrederich Munch   return DynamicLibrary(Handle);
136*70c377a3SFrederich Munch }
137*70c377a3SFrederich Munch 
138*70c377a3SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
139*70c377a3SFrederich Munch                                                    std::string *Err) {
140*70c377a3SFrederich Munch   SmartScopedLock<true> Lock(*SymbolsMutex);
141*70c377a3SFrederich Munch   // If we've already loaded this library, tell the caller.
142*70c377a3SFrederich Munch   if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
143*70c377a3SFrederich Munch     *Err = "Library already loaded";
144*70c377a3SFrederich Munch 
145*70c377a3SFrederich Munch   return DynamicLibrary(Handle);
146*70c377a3SFrederich Munch }
147*70c377a3SFrederich Munch 
148*70c377a3SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
149*70c377a3SFrederich Munch   if (!isValid())
150*70c377a3SFrederich Munch     return nullptr;
151*70c377a3SFrederich Munch   return HandleSet::DLSym(Data, SymbolName);
152*70c377a3SFrederich Munch }
153*70c377a3SFrederich Munch 
154*70c377a3SFrederich Munch void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
155*70c377a3SFrederich Munch   {
15657093e88SFilip Pizlo     SmartScopedLock<true> Lock(*SymbolsMutex);
157a19917daSJordy Rose 
158447762daSMichael J. Spencer     // First check symbols added via AddSymbol().
15957093e88SFilip Pizlo     if (ExplicitSymbols.isConstructed()) {
160*70c377a3SFrederich Munch       StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
161447762daSMichael J. Spencer 
162a19917daSJordy Rose       if (i != ExplicitSymbols->end())
163a19917daSJordy Rose         return i->second;
164447762daSMichael J. Spencer     }
165447762daSMichael J. Spencer 
166447762daSMichael J. Spencer     // Now search the libraries.
16759e5a644SVassil Vassilev     if (OpenedHandles.isConstructed()) {
168*70c377a3SFrederich Munch       if (void *Ptr = OpenedHandles->Lookup(SymbolName))
169*70c377a3SFrederich Munch         return Ptr;
170447762daSMichael J. Spencer     }
171447762daSMichael J. Spencer   }
172447762daSMichael J. Spencer 
173*70c377a3SFrederich Munch   return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
174*70c377a3SFrederich Munch }
17534ddbf1aSPeter Zotov 
17634ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
17734ddbf1aSPeter Zotov // C API.
17834ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
17934ddbf1aSPeter Zotov 
18034ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
181671fe2eeSPeter Zotov   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
18234ddbf1aSPeter Zotov }
183af79f3dbSEli Bendersky 
184af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
185af79f3dbSEli Bendersky   return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
186af79f3dbSEli Bendersky }
187af79f3dbSEli Bendersky 
188af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
189af79f3dbSEli Bendersky   return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
190af79f3dbSEli Bendersky }
191