1f4a2713aSLionel Sambuc //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc //  This file implements the operating system DynamicLibrary concept.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc // FIXME: This file leaks ExplicitSymbols and OpenedHandles!
13f4a2713aSLionel Sambuc //
14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc #include "llvm/Support/DynamicLibrary.h"
17*0a6a1f1dSLionel Sambuc #include "llvm-c/Support.h"
18f4a2713aSLionel Sambuc #include "llvm/ADT/DenseSet.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/StringMap.h"
20f4a2713aSLionel Sambuc #include "llvm/Config/config.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
22f4a2713aSLionel Sambuc #include "llvm/Support/Mutex.h"
23f4a2713aSLionel Sambuc #include <cstdio>
24f4a2713aSLionel Sambuc #include <cstring>
25f4a2713aSLionel Sambuc 
26f4a2713aSLionel Sambuc // Collection of symbol name/value pairs to be searched prior to any libraries.
27f4a2713aSLionel Sambuc static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols;
28f4a2713aSLionel Sambuc static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex;
29f4a2713aSLionel Sambuc 
AddSymbol(StringRef symbolName,void * symbolValue)30f4a2713aSLionel Sambuc void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
31f4a2713aSLionel Sambuc                                           void *symbolValue) {
32f4a2713aSLionel Sambuc   SmartScopedLock<true> lock(*SymbolsMutex);
33f4a2713aSLionel Sambuc   (*ExplicitSymbols)[symbolName] = symbolValue;
34f4a2713aSLionel Sambuc }
35f4a2713aSLionel Sambuc 
36f4a2713aSLionel Sambuc char llvm::sys::DynamicLibrary::Invalid = 0;
37f4a2713aSLionel Sambuc 
38f4a2713aSLionel Sambuc #ifdef LLVM_ON_WIN32
39f4a2713aSLionel Sambuc 
40f4a2713aSLionel Sambuc #include "Windows/DynamicLibrary.inc"
41f4a2713aSLionel Sambuc 
42f4a2713aSLionel Sambuc #else
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc #if HAVE_DLFCN_H
45f4a2713aSLionel Sambuc #include <dlfcn.h>
46f4a2713aSLionel Sambuc using namespace llvm;
47f4a2713aSLionel Sambuc using namespace llvm::sys;
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
50f4a2713aSLionel Sambuc //=== WARNING: Implementation here must contain only TRULY operating system
51f4a2713aSLionel Sambuc //===          independent code.
52f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
53f4a2713aSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc static DenseSet<void *> *OpenedHandles = nullptr;
55f4a2713aSLionel Sambuc 
getPermanentLibrary(const char * filename,std::string * errMsg)56f4a2713aSLionel Sambuc DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
57f4a2713aSLionel Sambuc                                                    std::string *errMsg) {
58f4a2713aSLionel Sambuc   SmartScopedLock<true> lock(*SymbolsMutex);
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc   void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
61*0a6a1f1dSLionel Sambuc   if (!handle) {
62f4a2713aSLionel Sambuc     if (errMsg) *errMsg = dlerror();
63f4a2713aSLionel Sambuc     return DynamicLibrary();
64f4a2713aSLionel Sambuc   }
65f4a2713aSLionel Sambuc 
66f4a2713aSLionel Sambuc #ifdef __CYGWIN__
67f4a2713aSLionel Sambuc   // Cygwin searches symbols only in the main
68f4a2713aSLionel Sambuc   // with the handle of dlopen(NULL, RTLD_GLOBAL).
69*0a6a1f1dSLionel Sambuc   if (!filename)
70f4a2713aSLionel Sambuc     handle = RTLD_DEFAULT;
71f4a2713aSLionel Sambuc #endif
72f4a2713aSLionel Sambuc 
73*0a6a1f1dSLionel Sambuc   if (!OpenedHandles)
74f4a2713aSLionel Sambuc     OpenedHandles = new DenseSet<void *>();
75f4a2713aSLionel Sambuc 
76f4a2713aSLionel Sambuc   // If we've already loaded this library, dlclose() the handle in order to
77f4a2713aSLionel Sambuc   // keep the internal refcount at +1.
78f4a2713aSLionel Sambuc   if (!OpenedHandles->insert(handle).second)
79f4a2713aSLionel Sambuc     dlclose(handle);
80f4a2713aSLionel Sambuc 
81f4a2713aSLionel Sambuc   return DynamicLibrary(handle);
82f4a2713aSLionel Sambuc }
83f4a2713aSLionel Sambuc 
getAddressOfSymbol(const char * symbolName)84f4a2713aSLionel Sambuc void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
85f4a2713aSLionel Sambuc   if (!isValid())
86*0a6a1f1dSLionel Sambuc     return nullptr;
87f4a2713aSLionel Sambuc   return dlsym(Data, symbolName);
88f4a2713aSLionel Sambuc }
89f4a2713aSLionel Sambuc 
90f4a2713aSLionel Sambuc #else
91f4a2713aSLionel Sambuc 
92f4a2713aSLionel Sambuc using namespace llvm;
93f4a2713aSLionel Sambuc using namespace llvm::sys;
94f4a2713aSLionel Sambuc 
getPermanentLibrary(const char * filename,std::string * errMsg)95f4a2713aSLionel Sambuc DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
96f4a2713aSLionel Sambuc                                                    std::string *errMsg) {
97f4a2713aSLionel Sambuc   if (errMsg) *errMsg = "dlopen() not supported on this platform";
98f4a2713aSLionel Sambuc   return DynamicLibrary();
99f4a2713aSLionel Sambuc }
100f4a2713aSLionel Sambuc 
getAddressOfSymbol(const char * symbolName)101f4a2713aSLionel Sambuc void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
102f4a2713aSLionel Sambuc   return NULL;
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc 
105f4a2713aSLionel Sambuc #endif
106f4a2713aSLionel Sambuc 
107f4a2713aSLionel Sambuc namespace llvm {
108f4a2713aSLionel Sambuc void *SearchForAddressOfSpecialSymbol(const char* symbolName);
109f4a2713aSLionel Sambuc }
110f4a2713aSLionel Sambuc 
SearchForAddressOfSymbol(const char * symbolName)111f4a2713aSLionel Sambuc void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
112f4a2713aSLionel Sambuc   SmartScopedLock<true> Lock(*SymbolsMutex);
113f4a2713aSLionel Sambuc 
114f4a2713aSLionel Sambuc   // First check symbols added via AddSymbol().
115f4a2713aSLionel Sambuc   if (ExplicitSymbols.isConstructed()) {
116f4a2713aSLionel Sambuc     StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
117f4a2713aSLionel Sambuc 
118f4a2713aSLionel Sambuc     if (i != ExplicitSymbols->end())
119f4a2713aSLionel Sambuc       return i->second;
120f4a2713aSLionel Sambuc   }
121f4a2713aSLionel Sambuc 
122f4a2713aSLionel Sambuc #if HAVE_DLFCN_H
123f4a2713aSLionel Sambuc   // Now search the libraries.
124f4a2713aSLionel Sambuc   if (OpenedHandles) {
125f4a2713aSLionel Sambuc     for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
126f4a2713aSLionel Sambuc          E = OpenedHandles->end(); I != E; ++I) {
127f4a2713aSLionel Sambuc       //lt_ptr ptr = lt_dlsym(*I, symbolName);
128f4a2713aSLionel Sambuc       void *ptr = dlsym(*I, symbolName);
129f4a2713aSLionel Sambuc       if (ptr) {
130f4a2713aSLionel Sambuc         return ptr;
131f4a2713aSLionel Sambuc       }
132f4a2713aSLionel Sambuc     }
133f4a2713aSLionel Sambuc   }
134f4a2713aSLionel Sambuc #endif
135f4a2713aSLionel Sambuc 
136f4a2713aSLionel Sambuc   if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
137f4a2713aSLionel Sambuc     return Result;
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc // This macro returns the address of a well-known, explicit symbol
140f4a2713aSLionel Sambuc #define EXPLICIT_SYMBOL(SYM) \
141f4a2713aSLionel Sambuc    if (!strcmp(symbolName, #SYM)) return &SYM
142f4a2713aSLionel Sambuc 
143f4a2713aSLionel Sambuc // On linux we have a weird situation. The stderr/out/in symbols are both
144f4a2713aSLionel Sambuc // macros and global variables because of standards requirements. So, we
145f4a2713aSLionel Sambuc // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
146f4a2713aSLionel Sambuc #if defined(__linux__) and !defined(__ANDROID__)
147f4a2713aSLionel Sambuc   {
148f4a2713aSLionel Sambuc     EXPLICIT_SYMBOL(stderr);
149f4a2713aSLionel Sambuc     EXPLICIT_SYMBOL(stdout);
150f4a2713aSLionel Sambuc     EXPLICIT_SYMBOL(stdin);
151f4a2713aSLionel Sambuc   }
152f4a2713aSLionel Sambuc #else
153f4a2713aSLionel Sambuc   // For everything else, we want to check to make sure the symbol isn't defined
154f4a2713aSLionel Sambuc   // as a macro before using EXPLICIT_SYMBOL.
155f4a2713aSLionel Sambuc   {
156f4a2713aSLionel Sambuc #ifndef stdin
157f4a2713aSLionel Sambuc     EXPLICIT_SYMBOL(stdin);
158f4a2713aSLionel Sambuc #endif
159f4a2713aSLionel Sambuc #ifndef stdout
160f4a2713aSLionel Sambuc     EXPLICIT_SYMBOL(stdout);
161f4a2713aSLionel Sambuc #endif
162f4a2713aSLionel Sambuc #ifndef stderr
163f4a2713aSLionel Sambuc     EXPLICIT_SYMBOL(stderr);
164f4a2713aSLionel Sambuc #endif
165f4a2713aSLionel Sambuc   }
166f4a2713aSLionel Sambuc #endif
167f4a2713aSLionel Sambuc #undef EXPLICIT_SYMBOL
168f4a2713aSLionel Sambuc 
169*0a6a1f1dSLionel Sambuc   return nullptr;
170f4a2713aSLionel Sambuc }
171f4a2713aSLionel Sambuc 
172f4a2713aSLionel Sambuc #endif // LLVM_ON_WIN32
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
175f4a2713aSLionel Sambuc // C API.
176f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
177f4a2713aSLionel Sambuc 
LLVMLoadLibraryPermanently(const char * Filename)178f4a2713aSLionel Sambuc LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
179f4a2713aSLionel Sambuc   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
180f4a2713aSLionel Sambuc }
181