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