-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathDynamicLibraryManager.h
224 lines (195 loc) · 8.48 KB
/
DynamicLibraryManager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <[email protected]>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
#ifndef CPPINTEROP_DYNAMIC_LIBRARY_MANAGER_H
#define CPPINTEROP_DYNAMIC_LIBRARY_MANAGER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
namespace Cpp {
class Dyld;
class InterpreterCallbacks;
///\brief A helper class managing dynamic shared objects.
///
class DynamicLibraryManager {
public:
///\brief Describes the result of loading a library.
///
enum LoadLibResult {
kLoadLibSuccess, ///< library loaded successfully
kLoadLibAlreadyLoaded, ///< library was already loaded
kLoadLibNotFound, ///< library was not found
kLoadLibLoadError, ///< loading the library failed
kLoadLibNumResults
};
/// Describes the library search paths.
struct SearchPathInfo {
/// The search path.
///
std::string Path;
/// True if the Path is on the LD_LIBRARY_PATH.
///
bool IsUser;
bool operator==(const SearchPathInfo& Other) const {
return IsUser == Other.IsUser && Path == Other.Path;
}
};
using SearchPathInfos = llvm::SmallVector<SearchPathInfo, 32>;
private:
typedef void* DyLibHandle;
typedef llvm::DenseMap<DyLibHandle, std::string> DyLibs;
///\brief DynamicLibraries loaded by this Interpreter.
///
DyLibs m_DyLibs;
llvm::StringSet<> m_LoadedLibraries;
///\brief System's include path, get initialized at construction time.
///
SearchPathInfos m_SearchPaths;
InterpreterCallbacks* m_Callbacks = nullptr;
Dyld* m_Dyld = nullptr;
///\brief Concatenates current include paths and the system include paths
/// and performs a lookup for the filename.
/// See more information for RPATH and RUNPATH:
/// https://en.wikipedia.org/wiki/Rpath
///\param[in] libStem - The filename being looked up
///\param[in] RPath - RPATH as provided by loader library, searching for
/// libStem \param[in] RunPath - RUNPATH as provided by loader library,
/// searching for libStem \param[in] libLoader - The library that loads
/// libStem. Use "" for main program.
///
///\returns the canonical path to the file or empty string if not found
///
std::string
lookupLibInPaths(llvm::StringRef libStem,
llvm::SmallVector<llvm::StringRef, 2> RPath = {},
llvm::SmallVector<llvm::StringRef, 2> RunPath = {},
llvm::StringRef libLoader = "") const;
///\brief Concatenates current include paths and the system include paths
/// and performs a lookup for the filename. If still not found it tries to
/// add the platform-specific extensions (such as so, dll, dylib) and
/// retries the lookup (from lookupLibInPaths)
/// See more information for RPATH and RUNPATH:
/// https://en.wikipedia.org/wiki/Rpath
///\param[in] filename - The filename being looked up
///\param[in] RPath - RPATH as provided by loader library, searching for
/// libStem \param[in] RunPath - RUNPATH as provided by loader library,
/// searching for libStem \param[in] libLoader - The library that loads
/// libStem. Use "" for main program.
///
///\returns the canonical path to the file or empty string if not found
///
std::string
lookupLibMaybeAddExt(llvm::StringRef filename,
llvm::SmallVector<llvm::StringRef, 2> RPath = {},
llvm::SmallVector<llvm::StringRef, 2> RunPath = {},
llvm::StringRef libLoader = "") const;
/// On a success returns to full path to a shared object that holds the
/// symbol pointed by func.
///
static std::string getSymbolLocation(void* func);
public:
DynamicLibraryManager();
~DynamicLibraryManager();
DynamicLibraryManager(const DynamicLibraryManager&) = delete;
DynamicLibraryManager& operator=(const DynamicLibraryManager&) = delete;
InterpreterCallbacks* getCallbacks() { return m_Callbacks; }
const InterpreterCallbacks* getCallbacks() const { return m_Callbacks; }
void setCallbacks(InterpreterCallbacks* C) { m_Callbacks = C; }
///\brief Returns the system include paths.
///
///\returns System include paths.
///
const SearchPathInfos& getSearchPaths() const { return m_SearchPaths; }
void addSearchPath(llvm::StringRef dir, bool isUser = true,
bool prepend = false) {
if (!dir.empty()) {
for (auto& item : m_SearchPaths)
if (dir == item.Path)
return;
auto pos = prepend ? m_SearchPaths.begin() : m_SearchPaths.end();
m_SearchPaths.insert(pos, SearchPathInfo{dir.str(), isUser});
}
}
///\brief Looks up a library taking into account the current include paths
/// and the system include paths.
/// See more information for RPATH and RUNPATH:
/// https://en.wikipedia.org/wiki/Rpath
///\param[in] libStem - The filename being looked up
///\param[in] RPath - RPATH as provided by loader library, searching for
/// libStem \param[in] RunPath - RUNPATH as provided by loader library,
/// searching for libStem \param[in] libLoader - The library that loads
/// libStem. Use "" for main program. \param[in] variateLibStem - If this
/// param is true, and libStem is "L", then
/// we search for "L", "libL", "L.so", "libL.so"", etc.
///
///\returns the canonical path to the file or empty string if not found
///
std::string lookupLibrary(llvm::StringRef libStem,
llvm::SmallVector<llvm::StringRef, 2> RPath = {},
llvm::SmallVector<llvm::StringRef, 2> RunPath = {},
llvm::StringRef libLoader = "",
bool variateLibStem = true) const;
///\brief Loads a shared library.
///
///\param [in] libStem - The file to load.
///\param [in] permanent - If false, the file can be unloaded later.
///\param [in] resolved - Whether libStem is an absolute path or resolved
/// from a previous call to DynamicLibraryManager::lookupLibrary
///
///\returns kLoadLibSuccess on success, kLoadLibAlreadyLoaded if the library
/// was already loaded, kLoadLibError if the library cannot be found or any
/// other error was encountered.
///
LoadLibResult loadLibrary(llvm::StringRef, bool permanent,
bool resolved = false);
void unloadLibrary(llvm::StringRef libStem);
///\brief Returns true if the file was a dynamic library and it was already
/// loaded.
///
bool isLibraryLoaded(llvm::StringRef fullPath) const;
/// Initialize the dyld.
///
///\param [in] shouldPermanentlyIgnore - a callback deciding if a library
/// should be ignored from the result set. Useful for ignoring
/// dangerous libraries such as the ones overriding malloc.
///
void
initializeDyld(std::function<bool(llvm::StringRef)> shouldPermanentlyIgnore);
/// Find the first not-yet-loaded shared object that contains the symbol
///
///\param[in] mangledName - the mangled name to look for.
///\param[in] searchSystem - whether to descend into system libraries.
///
///\returns the library name if found, and empty string otherwise.
///
std::string searchLibrariesForSymbol(llvm::StringRef mangledName,
bool searchSystem = true) const;
void dump(llvm::raw_ostream* S = nullptr) const;
/// On a success returns to full path to a shared object that holds the
/// symbol pointed by func.
///
template <class T> static std::string getSymbolLocation(T func) {
static_assert(std::is_pointer<T>::value, "Must be a function pointer!");
return getSymbolLocation(reinterpret_cast<void*>(func));
}
static std::string normalizePath(llvm::StringRef path);
/// Returns true if file is a shared library.
///
///\param[in] libFullPath - the full path to file.
///
///\param[out] exists - sets if the file exists. Useful to distinguish if it
/// is a library but of incompatible file format.
///
static bool isSharedLibrary(llvm::StringRef libFullPath,
bool* exists = nullptr);
};
} // end namespace Cpp
#endif // CPPINTEROP_DYNAMIC_LIBRARY_MANAGER_H