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*9f40457dSFrederich Munch #include <vector>
24447762daSMichael J. Spencer 
25*9f40457dSFrederich Munch using namespace llvm;
26*9f40457dSFrederich Munch using namespace llvm::sys;
27a19917daSJordy Rose 
28*9f40457dSFrederich Munch // All methods for HandleSet should be used holding SymbolsMutex.
29*9f40457dSFrederich Munch class DynamicLibrary::HandleSet {
30*9f40457dSFrederich Munch   typedef std::vector<void *> HandleList;
31*9f40457dSFrederich Munch   HandleList Handles;
32*9f40457dSFrederich Munch   void *Process;
33*9f40457dSFrederich Munch 
34*9f40457dSFrederich Munch public:
35*9f40457dSFrederich Munch   static void *DLOpen(const char *Filename, std::string *Err);
36*9f40457dSFrederich Munch   static void DLClose(void *Handle);
37*9f40457dSFrederich Munch   static void *DLSym(void *Handle, const char *Symbol);
38*9f40457dSFrederich Munch 
39*9f40457dSFrederich Munch   HandleSet() : Process(nullptr) {}
40*9f40457dSFrederich Munch   ~HandleSet();
41*9f40457dSFrederich Munch 
42*9f40457dSFrederich Munch   HandleList::iterator Find(void *Handle) {
43*9f40457dSFrederich Munch     return std::find(Handles.begin(), Handles.end(), Handle);
44447762daSMichael J. Spencer   }
45447762daSMichael J. Spencer 
46*9f40457dSFrederich Munch   bool Contains(void *Handle) {
47*9f40457dSFrederich Munch     return Handle == Process || Find(Handle) != Handles.end();
48*9f40457dSFrederich Munch   }
49*9f40457dSFrederich Munch 
50*9f40457dSFrederich Munch   bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
51*9f40457dSFrederich Munch #ifdef LLVM_ON_WIN32
52*9f40457dSFrederich Munch     assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
53*9f40457dSFrederich Munch #endif
54*9f40457dSFrederich Munch 
55*9f40457dSFrederich Munch     if (LLVM_LIKELY(!IsProcess)) {
56*9f40457dSFrederich Munch       if (Find(Handle) != Handles.end()) {
57*9f40457dSFrederich Munch         if (CanClose)
58*9f40457dSFrederich Munch           DLClose(Handle);
59*9f40457dSFrederich Munch         return false;
60*9f40457dSFrederich Munch       }
61*9f40457dSFrederich Munch       Handles.push_back(Handle);
62*9f40457dSFrederich Munch     } else {
63*9f40457dSFrederich Munch #ifndef LLVM_ON_WIN32
64*9f40457dSFrederich Munch       if (Process) {
65*9f40457dSFrederich Munch         if (CanClose)
66*9f40457dSFrederich Munch           DLClose(Process);
67*9f40457dSFrederich Munch         if (Process == Handle)
68*9f40457dSFrederich Munch           return false;
69*9f40457dSFrederich Munch       }
70*9f40457dSFrederich Munch #endif
71*9f40457dSFrederich Munch       Process = Handle;
72*9f40457dSFrederich Munch     }
73*9f40457dSFrederich Munch     return true;
74*9f40457dSFrederich Munch   }
75*9f40457dSFrederich Munch 
76*9f40457dSFrederich Munch   void *Lookup(const char *Symbol) {
77*9f40457dSFrederich Munch     // Process handle gets first try.
78*9f40457dSFrederich Munch     if (Process) {
79*9f40457dSFrederich Munch       if (void *Ptr = DLSym(Process, Symbol))
80*9f40457dSFrederich Munch         return Ptr;
81*9f40457dSFrederich Munch #ifndef NDEBUG
82*9f40457dSFrederich Munch       for (void *Handle : Handles)
83*9f40457dSFrederich Munch         assert(!DLSym(Handle, Symbol) && "Symbol exists in non process handle");
84*9f40457dSFrederich Munch #endif
85*9f40457dSFrederich Munch     } else {
86*9f40457dSFrederich Munch       // Iterate in reverse, so newer libraries/symbols override older.
87*9f40457dSFrederich Munch       for (auto &&I = Handles.rbegin(), E = Handles.rend(); I != E; ++I) {
88*9f40457dSFrederich Munch         if (void *Ptr = DLSym(*I, Symbol))
89*9f40457dSFrederich Munch           return Ptr;
90*9f40457dSFrederich Munch       }
91*9f40457dSFrederich Munch     }
92*9f40457dSFrederich Munch     return nullptr;
93*9f40457dSFrederich Munch   }
94*9f40457dSFrederich Munch };
95*9f40457dSFrederich Munch 
96*9f40457dSFrederich Munch namespace {
97*9f40457dSFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries.
98*9f40457dSFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
99*9f40457dSFrederich Munch // Collection of known library handles.
100*9f40457dSFrederich Munch static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
101*9f40457dSFrederich Munch // Lock for ExplicitSymbols and OpenedHandles.
102*9f40457dSFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
103*9f40457dSFrederich Munch }
10404bc405aSJordy Rose 
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*9f40457dSFrederich Munch #include "Unix/DynamicLibrary.inc"
112a19917daSJordy Rose 
113447762daSMichael J. Spencer #endif
114447762daSMichael J. Spencer 
115*9f40457dSFrederich Munch char DynamicLibrary::Invalid;
116*9f40457dSFrederich Munch 
117447762daSMichael J. Spencer namespace llvm {
118*9f40457dSFrederich Munch void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
119*9f40457dSFrederich Munch   return DoSearch(SymbolName); // DynamicLibrary.inc
120*9f40457dSFrederich Munch }
121447762daSMichael J. Spencer }
122447762daSMichael J. Spencer 
123*9f40457dSFrederich Munch void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
124*9f40457dSFrederich Munch   SmartScopedLock<true> Lock(*SymbolsMutex);
125*9f40457dSFrederich Munch   (*ExplicitSymbols)[SymbolName] = SymbolValue;
126*9f40457dSFrederich Munch }
127*9f40457dSFrederich Munch 
128*9f40457dSFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
129*9f40457dSFrederich Munch                                                    std::string *Err) {
130*9f40457dSFrederich Munch   SmartScopedLock<true> Lock(*SymbolsMutex);
131*9f40457dSFrederich Munch   void *Handle = HandleSet::DLOpen(FileName, Err);
132*9f40457dSFrederich Munch   if (Handle != &Invalid)
133*9f40457dSFrederich Munch     OpenedHandles->AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
134*9f40457dSFrederich Munch 
135*9f40457dSFrederich Munch   return DynamicLibrary(Handle);
136*9f40457dSFrederich Munch }
137*9f40457dSFrederich Munch 
138*9f40457dSFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
139*9f40457dSFrederich Munch                                                    std::string *Err) {
140*9f40457dSFrederich Munch   SmartScopedLock<true> Lock(*SymbolsMutex);
141*9f40457dSFrederich Munch   // If we've already loaded this library, tell the caller.
142*9f40457dSFrederich Munch   if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
143*9f40457dSFrederich Munch     *Err = "Library already loaded";
144*9f40457dSFrederich Munch 
145*9f40457dSFrederich Munch   return DynamicLibrary(Handle);
146*9f40457dSFrederich Munch }
147*9f40457dSFrederich Munch 
148*9f40457dSFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
149*9f40457dSFrederich Munch   if (!isValid())
150*9f40457dSFrederich Munch     return nullptr;
151*9f40457dSFrederich Munch   return HandleSet::DLSym(Data, SymbolName);
152*9f40457dSFrederich Munch }
153*9f40457dSFrederich Munch 
154*9f40457dSFrederich Munch void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
155*9f40457dSFrederich Munch   {
15657093e88SFilip Pizlo     SmartScopedLock<true> Lock(*SymbolsMutex);
157a19917daSJordy Rose 
158447762daSMichael J. Spencer     // First check symbols added via AddSymbol().
15957093e88SFilip Pizlo     if (ExplicitSymbols.isConstructed()) {
160*9f40457dSFrederich 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*9f40457dSFrederich Munch       if (void *Ptr = OpenedHandles->Lookup(SymbolName))
169*9f40457dSFrederich Munch         return Ptr;
170447762daSMichael J. Spencer     }
171447762daSMichael J. Spencer   }
172447762daSMichael J. Spencer 
173*9f40457dSFrederich Munch   return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
174*9f40457dSFrederich 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