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 //
10447762daSMichael J. Spencer //  This header file implements the operating system DynamicLibrary concept.
11447762daSMichael J. Spencer //
12a19917daSJordy Rose // FIXME: This file leaks ExplicitSymbols and OpenedHandles!
13447762daSMichael J. Spencer //
14447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
15447762daSMichael J. Spencer 
16447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h"
17*8a8cd2baSChandler Carruth #include "llvm-c/Support.h"
18ed0881b2SChandler Carruth #include "llvm/ADT/DenseSet.h"
19ed0881b2SChandler Carruth #include "llvm/ADT/StringMap.h"
20447762daSMichael J. Spencer #include "llvm/Config/config.h"
21*8a8cd2baSChandler Carruth #include "llvm/Support/ManagedStatic.h"
22ed0881b2SChandler Carruth #include "llvm/Support/Mutex.h"
23447762daSMichael J. Spencer #include <cstdio>
24447762daSMichael J. Spencer #include <cstring>
25447762daSMichael J. Spencer 
26447762daSMichael J. Spencer // Collection of symbol name/value pairs to be searched prior to any libraries.
2757093e88SFilip Pizlo static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols;
2857093e88SFilip Pizlo static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex;
29a19917daSJordy Rose 
30a19917daSJordy Rose void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
31447762daSMichael J. Spencer                                           void *symbolValue) {
3257093e88SFilip Pizlo   SmartScopedLock<true> lock(*SymbolsMutex);
33447762daSMichael J. Spencer   (*ExplicitSymbols)[symbolName] = symbolValue;
34447762daSMichael J. Spencer }
35447762daSMichael J. Spencer 
3604bc405aSJordy Rose char llvm::sys::DynamicLibrary::Invalid = 0;
3704bc405aSJordy Rose 
38447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32
39447762daSMichael J. Spencer 
40447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc"
41447762daSMichael J. Spencer 
42447762daSMichael J. Spencer #else
43447762daSMichael J. Spencer 
44447762daSMichael J. Spencer #if HAVE_DLFCN_H
45447762daSMichael J. Spencer #include <dlfcn.h>
46447762daSMichael J. Spencer using namespace llvm;
47447762daSMichael J. Spencer using namespace llvm::sys;
48447762daSMichael J. Spencer 
49447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
50447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system
51447762daSMichael J. Spencer //===          independent code.
52447762daSMichael J. Spencer //===----------------------------------------------------------------------===//
53447762daSMichael J. Spencer 
54a19917daSJordy Rose static DenseSet<void *> *OpenedHandles = 0;
55447762daSMichael J. Spencer 
56a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
57a19917daSJordy Rose                                                    std::string *errMsg) {
5857093e88SFilip Pizlo   SmartScopedLock<true> lock(*SymbolsMutex);
595765f4c2SJordy Rose 
60a19917daSJordy Rose   void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
61a19917daSJordy Rose   if (handle == 0) {
62a19917daSJordy Rose     if (errMsg) *errMsg = dlerror();
63a19917daSJordy Rose     return DynamicLibrary();
64447762daSMichael J. Spencer   }
65447762daSMichael J. Spencer 
66447762daSMichael J. Spencer #ifdef __CYGWIN__
67447762daSMichael J. Spencer   // Cygwin searches symbols only in the main
68447762daSMichael J. Spencer   // with the handle of dlopen(NULL, RTLD_GLOBAL).
69a19917daSJordy Rose   if (filename == NULL)
70a19917daSJordy Rose     handle = RTLD_DEFAULT;
71447762daSMichael J. Spencer #endif
72a19917daSJordy Rose 
73447762daSMichael J. Spencer   if (OpenedHandles == 0)
74a19917daSJordy Rose     OpenedHandles = new DenseSet<void *>();
75a19917daSJordy Rose 
76a19917daSJordy Rose   // If we've already loaded this library, dlclose() the handle in order to
77a19917daSJordy Rose   // keep the internal refcount at +1.
78a19917daSJordy Rose   if (!OpenedHandles->insert(handle).second)
79a19917daSJordy Rose     dlclose(handle);
80a19917daSJordy Rose 
81a19917daSJordy Rose   return DynamicLibrary(handle);
82447762daSMichael J. Spencer }
83a19917daSJordy Rose 
84a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
85a19917daSJordy Rose   if (!isValid())
86a19917daSJordy Rose     return NULL;
87a19917daSJordy Rose   return dlsym(Data, symbolName);
88a19917daSJordy Rose }
89a19917daSJordy Rose 
90447762daSMichael J. Spencer #else
91447762daSMichael J. Spencer 
92447762daSMichael J. Spencer using namespace llvm;
93447762daSMichael J. Spencer using namespace llvm::sys;
94447762daSMichael J. Spencer 
95a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
96a19917daSJordy Rose                                                    std::string *errMsg) {
97a19917daSJordy Rose   if (errMsg) *errMsg = "dlopen() not supported on this platform";
98a19917daSJordy Rose   return DynamicLibrary();
99447762daSMichael J. Spencer }
100a19917daSJordy Rose 
101a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
102a19917daSJordy Rose   return NULL;
103a19917daSJordy Rose }
104a19917daSJordy Rose 
105447762daSMichael J. Spencer #endif
106447762daSMichael J. Spencer 
107447762daSMichael J. Spencer namespace llvm {
108447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName);
109447762daSMichael J. Spencer }
110447762daSMichael J. Spencer 
111447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
11257093e88SFilip Pizlo   SmartScopedLock<true> Lock(*SymbolsMutex);
113a19917daSJordy Rose 
114447762daSMichael J. Spencer   // First check symbols added via AddSymbol().
11557093e88SFilip Pizlo   if (ExplicitSymbols.isConstructed()) {
116a19917daSJordy Rose     StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
117447762daSMichael J. Spencer 
118a19917daSJordy Rose     if (i != ExplicitSymbols->end())
119a19917daSJordy Rose       return i->second;
120447762daSMichael J. Spencer   }
121447762daSMichael J. Spencer 
122447762daSMichael J. Spencer #if HAVE_DLFCN_H
123447762daSMichael J. Spencer   // Now search the libraries.
124447762daSMichael J. Spencer   if (OpenedHandles) {
125a19917daSJordy Rose     for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
126447762daSMichael J. Spencer          E = OpenedHandles->end(); I != E; ++I) {
127447762daSMichael J. Spencer       //lt_ptr ptr = lt_dlsym(*I, symbolName);
128447762daSMichael J. Spencer       void *ptr = dlsym(*I, symbolName);
129447762daSMichael J. Spencer       if (ptr) {
130447762daSMichael J. Spencer         return ptr;
131447762daSMichael J. Spencer       }
132447762daSMichael J. Spencer     }
133447762daSMichael J. Spencer   }
134447762daSMichael J. Spencer #endif
135447762daSMichael J. Spencer 
136447762daSMichael J. Spencer   if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
137447762daSMichael J. Spencer     return Result;
138447762daSMichael J. Spencer 
139447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol
140447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \
141447762daSMichael J. Spencer    if (!strcmp(symbolName, #SYM)) return &SYM
142447762daSMichael J. Spencer 
143447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both
144447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we
145447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
146c439a426SEvgeniy Stepanov #if defined(__linux__) and !defined(__ANDROID__)
147447762daSMichael J. Spencer   {
148447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stderr);
149447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdout);
150447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdin);
151447762daSMichael J. Spencer   }
152447762daSMichael J. Spencer #else
153447762daSMichael J. Spencer   // For everything else, we want to check to make sure the symbol isn't defined
154447762daSMichael J. Spencer   // as a macro before using EXPLICIT_SYMBOL.
155447762daSMichael J. Spencer   {
156447762daSMichael J. Spencer #ifndef stdin
157447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdin);
158447762daSMichael J. Spencer #endif
159447762daSMichael J. Spencer #ifndef stdout
160447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stdout);
161447762daSMichael J. Spencer #endif
162447762daSMichael J. Spencer #ifndef stderr
163447762daSMichael J. Spencer     EXPLICIT_SYMBOL(stderr);
164447762daSMichael J. Spencer #endif
165447762daSMichael J. Spencer   }
166447762daSMichael J. Spencer #endif
167447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL
168447762daSMichael J. Spencer 
169447762daSMichael J. Spencer   return 0;
170447762daSMichael J. Spencer }
171447762daSMichael J. Spencer 
172447762daSMichael J. Spencer #endif // LLVM_ON_WIN32
17334ddbf1aSPeter Zotov 
17434ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
17534ddbf1aSPeter Zotov // C API.
17634ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
17734ddbf1aSPeter Zotov 
17834ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
179671fe2eeSPeter Zotov   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
18034ddbf1aSPeter Zotov }
181