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