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