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>
23447762daSMichael J. Spencer 
2470c377a3SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries.
2570c377a3SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols;
2670c377a3SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex;
27*fd96d5e1SFrederich Munch 
28*fd96d5e1SFrederich Munch void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
29*fd96d5e1SFrederich Munch                                           void *symbolValue) {
30*fd96d5e1SFrederich Munch   SmartScopedLock<true> lock(*SymbolsMutex);
31*fd96d5e1SFrederich Munch   (*ExplicitSymbols)[symbolName] = symbolValue;
3270c377a3SFrederich Munch }
33b8c236a6SFrederich Munch 
34*fd96d5e1SFrederich Munch char llvm::sys::DynamicLibrary::Invalid = 0;
35*fd96d5e1SFrederich Munch 
36447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32
37447762daSMichael J. Spencer 
38447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc"
39447762daSMichael J. Spencer 
40447762daSMichael J. Spencer #else
41447762daSMichael J. Spencer 
42*fd96d5e1SFrederich Munch #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
43*fd96d5e1SFrederich Munch #include <dlfcn.h>
44*fd96d5e1SFrederich Munch using namespace llvm;
45*fd96d5e1SFrederich Munch using namespace llvm::sys;
46*fd96d5e1SFrederich Munch 
47*fd96d5e1SFrederich Munch //===----------------------------------------------------------------------===//
48*fd96d5e1SFrederich Munch //=== WARNING: Implementation here must contain only TRULY operating system
49*fd96d5e1SFrederich Munch //===          independent code.
50*fd96d5e1SFrederich Munch //===----------------------------------------------------------------------===//
51*fd96d5e1SFrederich Munch 
52*fd96d5e1SFrederich Munch static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles;
53*fd96d5e1SFrederich Munch 
54*fd96d5e1SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
55*fd96d5e1SFrederich Munch                                                    std::string *errMsg) {
56*fd96d5e1SFrederich Munch   SmartScopedLock<true> lock(*SymbolsMutex);
57*fd96d5e1SFrederich Munch 
58*fd96d5e1SFrederich Munch   void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
59*fd96d5e1SFrederich Munch   if (!handle) {
60*fd96d5e1SFrederich Munch     if (errMsg) *errMsg = dlerror();
61*fd96d5e1SFrederich Munch     return DynamicLibrary();
62*fd96d5e1SFrederich Munch   }
63*fd96d5e1SFrederich Munch 
64*fd96d5e1SFrederich Munch #ifdef __CYGWIN__
65*fd96d5e1SFrederich Munch   // Cygwin searches symbols only in the main
66*fd96d5e1SFrederich Munch   // with the handle of dlopen(NULL, RTLD_GLOBAL).
67*fd96d5e1SFrederich Munch   if (!filename)
68*fd96d5e1SFrederich Munch     handle = RTLD_DEFAULT;
69*fd96d5e1SFrederich Munch #endif
70*fd96d5e1SFrederich Munch 
71*fd96d5e1SFrederich Munch   // If we've already loaded this library, dlclose() the handle in order to
72*fd96d5e1SFrederich Munch   // keep the internal refcount at +1.
73*fd96d5e1SFrederich Munch   if (!OpenedHandles->insert(handle).second)
74*fd96d5e1SFrederich Munch     dlclose(handle);
75*fd96d5e1SFrederich Munch 
76*fd96d5e1SFrederich Munch   return DynamicLibrary(handle);
77*fd96d5e1SFrederich Munch }
78*fd96d5e1SFrederich Munch 
79*fd96d5e1SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *handle,
80*fd96d5e1SFrederich Munch                                                    std::string *errMsg) {
81*fd96d5e1SFrederich Munch   SmartScopedLock<true> lock(*SymbolsMutex);
82*fd96d5e1SFrederich Munch   // If we've already loaded this library, tell the caller.
83*fd96d5e1SFrederich Munch   if (!OpenedHandles->insert(handle).second) {
84*fd96d5e1SFrederich Munch     if (errMsg) *errMsg = "Library already loaded";
85*fd96d5e1SFrederich Munch     return DynamicLibrary();
86*fd96d5e1SFrederich Munch   }
87*fd96d5e1SFrederich Munch 
88*fd96d5e1SFrederich Munch   return DynamicLibrary(handle);
89*fd96d5e1SFrederich Munch }
90*fd96d5e1SFrederich Munch 
91*fd96d5e1SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
92*fd96d5e1SFrederich Munch   if (!isValid())
93*fd96d5e1SFrederich Munch     return nullptr;
94*fd96d5e1SFrederich Munch   return dlsym(Data, symbolName);
95*fd96d5e1SFrederich Munch }
96*fd96d5e1SFrederich Munch 
97*fd96d5e1SFrederich Munch #else
98*fd96d5e1SFrederich Munch 
99*fd96d5e1SFrederich Munch using namespace llvm;
100*fd96d5e1SFrederich Munch using namespace llvm::sys;
101*fd96d5e1SFrederich Munch 
102*fd96d5e1SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
103*fd96d5e1SFrederich Munch                                                    std::string *errMsg) {
104*fd96d5e1SFrederich Munch   if (errMsg) *errMsg = "dlopen() not supported on this platform";
105*fd96d5e1SFrederich Munch   return DynamicLibrary();
106*fd96d5e1SFrederich Munch }
107*fd96d5e1SFrederich Munch 
108*fd96d5e1SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
109*fd96d5e1SFrederich Munch   return NULL;
110*fd96d5e1SFrederich Munch }
111a19917daSJordy Rose 
112447762daSMichael J. Spencer #endif
113447762daSMichael J. Spencer 
114447762daSMichael J. Spencer namespace llvm {
115*fd96d5e1SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char* symbolName);
116447762daSMichael J. Spencer }
117447762daSMichael J. Spencer 
118*fd96d5e1SFrederich Munch void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
11957093e88SFilip Pizlo   SmartScopedLock<true> Lock(*SymbolsMutex);
120a19917daSJordy Rose 
121447762daSMichael J. Spencer   // First check symbols added via AddSymbol().
12257093e88SFilip Pizlo   if (ExplicitSymbols.isConstructed()) {
123*fd96d5e1SFrederich Munch     StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
124447762daSMichael J. Spencer 
125a19917daSJordy Rose     if (i != ExplicitSymbols->end())
126a19917daSJordy Rose       return i->second;
127447762daSMichael J. Spencer   }
128447762daSMichael J. Spencer 
129*fd96d5e1SFrederich Munch #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
130447762daSMichael J. Spencer   // Now search the libraries.
13159e5a644SVassil Vassilev   if (OpenedHandles.isConstructed()) {
132*fd96d5e1SFrederich Munch     for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
133*fd96d5e1SFrederich Munch          E = OpenedHandles->end(); I != E; ++I) {
134*fd96d5e1SFrederich Munch       //lt_ptr ptr = lt_dlsym(*I, symbolName);
135*fd96d5e1SFrederich Munch       void *ptr = dlsym(*I, symbolName);
136*fd96d5e1SFrederich Munch       if (ptr) {
137*fd96d5e1SFrederich Munch         return ptr;
138447762daSMichael J. Spencer       }
139447762daSMichael J. Spencer     }
140*fd96d5e1SFrederich Munch   }
141*fd96d5e1SFrederich Munch #endif
142*fd96d5e1SFrederich Munch 
143*fd96d5e1SFrederich Munch   if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
144*fd96d5e1SFrederich Munch     return Result;
145*fd96d5e1SFrederich Munch 
146*fd96d5e1SFrederich Munch // This macro returns the address of a well-known, explicit symbol
147*fd96d5e1SFrederich Munch #define EXPLICIT_SYMBOL(SYM) \
148*fd96d5e1SFrederich Munch    if (!strcmp(symbolName, #SYM)) return &SYM
149*fd96d5e1SFrederich Munch 
150*fd96d5e1SFrederich Munch // On linux we have a weird situation. The stderr/out/in symbols are both
151*fd96d5e1SFrederich Munch // macros and global variables because of standards requirements. So, we
152*fd96d5e1SFrederich Munch // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
153*fd96d5e1SFrederich Munch #if defined(__linux__) and !defined(__ANDROID__)
154*fd96d5e1SFrederich Munch   {
155*fd96d5e1SFrederich Munch     EXPLICIT_SYMBOL(stderr);
156*fd96d5e1SFrederich Munch     EXPLICIT_SYMBOL(stdout);
157*fd96d5e1SFrederich Munch     EXPLICIT_SYMBOL(stdin);
158*fd96d5e1SFrederich Munch   }
159*fd96d5e1SFrederich Munch #else
160*fd96d5e1SFrederich Munch   // For everything else, we want to check to make sure the symbol isn't defined
161*fd96d5e1SFrederich Munch   // as a macro before using EXPLICIT_SYMBOL.
162*fd96d5e1SFrederich Munch   {
163*fd96d5e1SFrederich Munch #ifndef stdin
164*fd96d5e1SFrederich Munch     EXPLICIT_SYMBOL(stdin);
165*fd96d5e1SFrederich Munch #endif
166*fd96d5e1SFrederich Munch #ifndef stdout
167*fd96d5e1SFrederich Munch     EXPLICIT_SYMBOL(stdout);
168*fd96d5e1SFrederich Munch #endif
169*fd96d5e1SFrederich Munch #ifndef stderr
170*fd96d5e1SFrederich Munch     EXPLICIT_SYMBOL(stderr);
171*fd96d5e1SFrederich Munch #endif
172*fd96d5e1SFrederich Munch   }
173*fd96d5e1SFrederich Munch #endif
174*fd96d5e1SFrederich Munch #undef EXPLICIT_SYMBOL
175*fd96d5e1SFrederich Munch 
176*fd96d5e1SFrederich Munch   return nullptr;
177*fd96d5e1SFrederich Munch }
178447762daSMichael J. Spencer 
179*fd96d5e1SFrederich Munch #endif // LLVM_ON_WIN32
18034ddbf1aSPeter Zotov 
18134ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
18234ddbf1aSPeter Zotov // C API.
18334ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
18434ddbf1aSPeter Zotov 
18534ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
186671fe2eeSPeter Zotov   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
18734ddbf1aSPeter Zotov }
188af79f3dbSEli Bendersky 
189af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
190af79f3dbSEli Bendersky   return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
191af79f3dbSEli Bendersky }
192af79f3dbSEli Bendersky 
193af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
194af79f3dbSEli Bendersky   return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
195af79f3dbSEli Bendersky }
196