/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/DynamicLibrary.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file implements the operating system DynamicLibrary concept. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/Support/DynamicLibrary.h" |
15 | | #include "llvm-c/Support.h" |
16 | | #include "llvm/ADT/DenseSet.h" |
17 | | #include "llvm/ADT/STLExtras.h" |
18 | | #include "llvm/ADT/StringMap.h" |
19 | | #include "llvm/Config/config.h" |
20 | | #include "llvm/Support/ManagedStatic.h" |
21 | | #include "llvm/Support/Mutex.h" |
22 | | #include <cstdio> |
23 | | #include <cstring> |
24 | | #include <vector> |
25 | | |
26 | | using namespace llvm; |
27 | | using namespace llvm::sys; |
28 | | |
29 | | // All methods for HandleSet should be used holding SymbolsMutex. |
30 | | class DynamicLibrary::HandleSet { |
31 | | typedef std::vector<void *> HandleList; |
32 | | HandleList Handles; |
33 | | void *Process; |
34 | | |
35 | | public: |
36 | | static void *DLOpen(const char *Filename, std::string *Err); |
37 | | static void DLClose(void *Handle); |
38 | | static void *DLSym(void *Handle, const char *Symbol); |
39 | | |
40 | 348 | HandleSet() : Process(nullptr) {} |
41 | | ~HandleSet(); |
42 | | |
43 | 100 | HandleList::iterator Find(void *Handle) { |
44 | 100 | return std::find(Handles.begin(), Handles.end(), Handle); |
45 | 100 | } |
46 | | |
47 | 0 | bool Contains(void *Handle) { |
48 | 0 | return Handle == Process || Find(Handle) != Handles.end(); |
49 | 0 | } |
50 | | |
51 | 474 | bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) { |
52 | | #ifdef LLVM_ON_WIN32 |
53 | | assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle."); |
54 | | #endif |
55 | | |
56 | 474 | if (LLVM_LIKELY474 (!IsProcess)) { |
57 | 100 | if (Find(Handle) != Handles.end()100 ) { |
58 | 0 | if (CanClose) |
59 | 0 | DLClose(Handle); |
60 | 0 | return false; |
61 | 0 | } |
62 | 100 | Handles.push_back(Handle); |
63 | 474 | } else { |
64 | 374 | #ifndef LLVM_ON_WIN32 |
65 | 374 | if (Process374 ) { |
66 | 124 | if (CanClose) |
67 | 124 | DLClose(Process); |
68 | 124 | if (Process == Handle) |
69 | 124 | return false; |
70 | 250 | } |
71 | 250 | #endif |
72 | 250 | Process = Handle; |
73 | 250 | } |
74 | 350 | return true; |
75 | 474 | } |
76 | | |
77 | 6 | void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { |
78 | 6 | if (Order & SO_LoadOrder6 ) { |
79 | 0 | for (void *Handle : Handles) { |
80 | 0 | if (void *Ptr = DLSym(Handle, Symbol)) |
81 | 0 | return Ptr; |
82 | 6 | } |
83 | 0 | } else { |
84 | 6 | for (void *Handle : llvm::reverse(Handles)) { |
85 | 6 | if (void *Ptr = DLSym(Handle, Symbol)) |
86 | 6 | return Ptr; |
87 | 0 | } |
88 | 6 | } |
89 | 0 | return nullptr; |
90 | 0 | } |
91 | | |
92 | 252 | void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { |
93 | 252 | assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) && |
94 | 252 | "Invalid Ordering"); |
95 | 252 | |
96 | 252 | if (!Process || 252 (Order & SO_LoadedFirst)247 ) { |
97 | 6 | if (void *Ptr = LibLookup(Symbol, Order)) |
98 | 6 | return Ptr; |
99 | 246 | } |
100 | 246 | if (246 Process246 ) { |
101 | 246 | // Use OS facilities to search the current binary and all loaded libs. |
102 | 246 | if (void *Ptr = DLSym(Process, Symbol)) |
103 | 226 | return Ptr; |
104 | 20 | |
105 | 20 | // Search any libs that might have been skipped because of RTLD_LOCAL. |
106 | 20 | if (20 Order & SO_LoadedLast20 ) { |
107 | 0 | if (void *Ptr = LibLookup(Symbol, Order)) |
108 | 0 | return Ptr; |
109 | 20 | } |
110 | 246 | } |
111 | 20 | return nullptr; |
112 | 20 | } |
113 | | }; |
114 | | |
115 | | namespace { |
116 | | // Collection of symbol name/value pairs to be searched prior to any libraries. |
117 | | static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols; |
118 | | // Collection of known library handles. |
119 | | static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles; |
120 | | // Lock for ExplicitSymbols and OpenedHandles. |
121 | | static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex; |
122 | | } |
123 | | |
124 | | #ifdef LLVM_ON_WIN32 |
125 | | |
126 | | #include "Windows/DynamicLibrary.inc" |
127 | | |
128 | | #else |
129 | | |
130 | | #include "Unix/DynamicLibrary.inc" |
131 | | |
132 | | #endif |
133 | | |
134 | | char DynamicLibrary::Invalid; |
135 | | DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder = |
136 | | DynamicLibrary::SO_Linker; |
137 | | |
138 | | namespace llvm { |
139 | 22 | void *SearchForAddressOfSpecialSymbol(const char *SymbolName) { |
140 | 22 | return DoSearch(SymbolName); // DynamicLibrary.inc |
141 | 22 | } |
142 | | } |
143 | | |
144 | 3 | void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) { |
145 | 3 | SmartScopedLock<true> Lock(*SymbolsMutex); |
146 | 3 | (*ExplicitSymbols)[SymbolName] = SymbolValue; |
147 | 3 | } |
148 | | |
149 | | DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, |
150 | 474 | std::string *Err) { |
151 | 474 | // Force OpenedHandles to be added into the ManagedStatic list before any |
152 | 474 | // ManagedStatic can be added from static constructors in HandleSet::DLOpen. |
153 | 474 | HandleSet& HS = *OpenedHandles; |
154 | 474 | |
155 | 474 | void *Handle = HandleSet::DLOpen(FileName, Err); |
156 | 474 | if (Handle != &Invalid474 ) { |
157 | 474 | SmartScopedLock<true> Lock(*SymbolsMutex); |
158 | 474 | HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); |
159 | 474 | } |
160 | 474 | |
161 | 474 | return DynamicLibrary(Handle); |
162 | 474 | } |
163 | | |
164 | | DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle, |
165 | 0 | std::string *Err) { |
166 | 0 | SmartScopedLock<true> Lock(*SymbolsMutex); |
167 | 0 | // If we've already loaded this library, tell the caller. |
168 | 0 | if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false)) |
169 | 0 | *Err = "Library already loaded"; |
170 | 0 |
|
171 | 0 | return DynamicLibrary(Handle); |
172 | 0 | } |
173 | | |
174 | 3 | void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) { |
175 | 3 | if (!isValid()) |
176 | 0 | return nullptr; |
177 | 3 | return HandleSet::DLSym(Data, SymbolName); |
178 | 3 | } |
179 | | |
180 | 256 | void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { |
181 | 256 | { |
182 | 256 | SmartScopedLock<true> Lock(*SymbolsMutex); |
183 | 256 | |
184 | 256 | // First check symbols added via AddSymbol(). |
185 | 256 | if (ExplicitSymbols.isConstructed()256 ) { |
186 | 2 | StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName); |
187 | 2 | |
188 | 2 | if (i != ExplicitSymbols->end()) |
189 | 2 | return i->second; |
190 | 254 | } |
191 | 254 | |
192 | 254 | // Now search the libraries. |
193 | 254 | if (254 OpenedHandles.isConstructed()254 ) { |
194 | 252 | if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder)) |
195 | 232 | return Ptr; |
196 | 22 | } |
197 | 22 | } |
198 | 22 | |
199 | 22 | return llvm::SearchForAddressOfSpecialSymbol(SymbolName); |
200 | 22 | } |
201 | | |
202 | | //===----------------------------------------------------------------------===// |
203 | | // C API. |
204 | | //===----------------------------------------------------------------------===// |
205 | | |
206 | 0 | LLVMBool LLVMLoadLibraryPermanently(const char *Filename) { |
207 | 0 | return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); |
208 | 0 | } |
209 | | |
210 | 0 | void *LLVMSearchForAddressOfSymbol(const char *symbolName) { |
211 | 0 | return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); |
212 | 0 | } |
213 | | |
214 | 0 | void LLVMAddSymbol(const char *symbolName, void *symbolValue) { |
215 | 0 | return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); |
216 | 0 | } |