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 
24447762daSMichael J. Spencer // Collection of symbol name/value pairs to be searched prior to any libraries.
2557093e88SFilip Pizlo static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols;
2657093e88SFilip Pizlo static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex;
27a19917daSJordy Rose 
28a19917daSJordy Rose void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
29447762daSMichael J. Spencer                                           void *symbolValue) {
3057093e88SFilip Pizlo   SmartScopedLock<true> lock(*SymbolsMutex);
31447762daSMichael J. Spencer   (*ExplicitSymbols)[symbolName] = symbolValue;
32447762daSMichael J. Spencer }
33447762daSMichael J. Spencer 
3404bc405aSJordy Rose char llvm::sys::DynamicLibrary::Invalid = 0;
3504bc405aSJordy Rose 
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 
425d92bc5bSPavel Labath #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
43447762daSMichael J. Spencer #include <dlfcn.h>
44447762daSMichael J. Spencer using namespace llvm;
45447762daSMichael J. Spencer using namespace llvm::sys;
46447762daSMichael J. Spencer 
47447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
48447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system
49447762daSMichael J. Spencer //===          independent code.
50447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
51447762daSMichael J. Spencer 
52*59e5a644SVassil Vassilev static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles;
53447762daSMichael J. Spencer 
54a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
55a19917daSJordy Rose                                                    std::string *errMsg) {
5657093e88SFilip Pizlo   SmartScopedLock<true> lock(*SymbolsMutex);
5774a46c24SZachary Turner 
5874a46c24SZachary Turner   void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
598d399f87SCraig Topper   if (!handle) {
60a19917daSJordy Rose     if (errMsg) *errMsg = dlerror();
61a19917daSJordy Rose     return DynamicLibrary();
62447762daSMichael J. Spencer   }
63447762daSMichael J. Spencer 
64447762daSMichael J. Spencer #ifdef __CYGWIN__
65447762daSMichael J. Spencer   // Cygwin searches symbols only in the main
66447762daSMichael J. Spencer   // with the handle of dlopen(NULL, RTLD_GLOBAL).
678d399f87SCraig Topper   if (!filename)
68a19917daSJordy Rose     handle = RTLD_DEFAULT;
69447762daSMichael J. Spencer #endif
70a19917daSJordy Rose 
71a19917daSJordy Rose   // If we've already loaded this library, dlclose() the handle in order to
72a19917daSJordy Rose   // keep the internal refcount at +1.
73a19917daSJordy Rose   if (!OpenedHandles->insert(handle).second)
74a19917daSJordy Rose     dlclose(handle);
75a19917daSJordy Rose 
76a19917daSJordy Rose   return DynamicLibrary(handle);
77447762daSMichael J. Spencer }
78a19917daSJordy Rose 
79a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
80a19917daSJordy Rose   if (!isValid())
81c10719f5SCraig Topper     return nullptr;
82a19917daSJordy Rose   return dlsym(Data, symbolName);
83a19917daSJordy Rose }
84a19917daSJordy Rose 
85447762daSMichael J. Spencer #else
86447762daSMichael J. Spencer 
87447762daSMichael J. Spencer using namespace llvm;
88447762daSMichael J. Spencer using namespace llvm::sys;
89447762daSMichael J. Spencer 
90a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
91a19917daSJordy Rose                                                    std::string *errMsg) {
92a19917daSJordy Rose   if (errMsg) *errMsg = "dlopen() not supported on this platform";
93a19917daSJordy Rose   return DynamicLibrary();
94447762daSMichael J. Spencer }
95a19917daSJordy Rose 
96a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
97a19917daSJordy Rose   return NULL;
98a19917daSJordy Rose }
99a19917daSJordy Rose 
100447762daSMichael J. Spencer #endif
101447762daSMichael J. Spencer 
102447762daSMichael J. Spencer namespace llvm {
103447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName);
104447762daSMichael J. Spencer }
105447762daSMichael J. Spencer 
106447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
10757093e88SFilip Pizlo   SmartScopedLock<true> Lock(*SymbolsMutex);
108a19917daSJordy Rose 
109447762daSMichael J. Spencer   // First check symbols added via AddSymbol().
11057093e88SFilip Pizlo   if (ExplicitSymbols.isConstructed()) {
111a19917daSJordy Rose     StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
112447762daSMichael J. Spencer 
113a19917daSJordy Rose     if (i != ExplicitSymbols->end())
114a19917daSJordy Rose       return i->second;
115447762daSMichael J. Spencer   }
116447762daSMichael J. Spencer 
1175d92bc5bSPavel Labath #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
118447762daSMichael J. Spencer   // Now search the libraries.
119*59e5a644SVassil Vassilev   if (OpenedHandles.isConstructed()) {
120a19917daSJordy Rose     for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
121447762daSMichael J. Spencer          E = OpenedHandles->end(); I != E; ++I) {
122447762daSMichael J. Spencer       //lt_ptr ptr = lt_dlsym(*I, symbolName);
123447762daSMichael J. Spencer       void *ptr = dlsym(*I, symbolName);
124447762daSMichael J. Spencer       if (ptr) {
125447762daSMichael J. Spencer         return ptr;
126447762daSMichael J. Spencer       }
127447762daSMichael J. Spencer     }
128447762daSMichael J. Spencer   }
129447762daSMichael J. Spencer #endif
130447762daSMichael J. Spencer 
131447762daSMichael J. Spencer   if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
132447762daSMichael J. Spencer     return Result;
133447762daSMichael J. Spencer 
134447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol
135447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \
136447762daSMichael J. Spencer    if (!strcmp(symbolName, #SYM)) return &SYM
137447762daSMichael J. Spencer 
138447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both
139447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we
140447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
141c439a426SEvgeniy Stepanov #if defined(__linux__) and !defined(__ANDROID__)
142447762daSMichael J. Spencer   {
143447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stderr);
144447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdout);
145447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdin);
146447762daSMichael J. Spencer   }
147447762daSMichael J. Spencer #else
148447762daSMichael J. Spencer   // For everything else, we want to check to make sure the symbol isn't defined
149447762daSMichael J. Spencer   // as a macro before using EXPLICIT_SYMBOL.
150447762daSMichael J. Spencer   {
151447762daSMichael J. Spencer #ifndef stdin
152447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdin);
153447762daSMichael J. Spencer #endif
154447762daSMichael J. Spencer #ifndef stdout
155447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdout);
156447762daSMichael J. Spencer #endif
157447762daSMichael J. Spencer #ifndef stderr
158447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stderr);
159447762daSMichael J. Spencer #endif
160447762daSMichael J. Spencer   }
161447762daSMichael J. Spencer #endif
162447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL
163447762daSMichael J. Spencer 
164c10719f5SCraig Topper   return nullptr;
165447762daSMichael J. Spencer }
166447762daSMichael J. Spencer 
167447762daSMichael J. Spencer #endif // LLVM_ON_WIN32
16834ddbf1aSPeter Zotov 
16934ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
17034ddbf1aSPeter Zotov // C API.
17134ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
17234ddbf1aSPeter Zotov 
17334ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
174671fe2eeSPeter Zotov   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
17534ddbf1aSPeter Zotov }
176af79f3dbSEli Bendersky 
177af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
178af79f3dbSEli Bendersky   return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
179af79f3dbSEli Bendersky }
180af79f3dbSEli Bendersky 
181af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
182af79f3dbSEli Bendersky   return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
183af79f3dbSEli Bendersky }
184af79f3dbSEli Bendersky 
185