1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #ifndef SharedLibrary_hpp |
16 | #define SharedLibrary_hpp |
17 | |
18 | #if defined(_WIN32) |
19 | #include <Windows.h> |
20 | #else |
21 | #include <dlfcn.h> |
22 | #endif |
23 | |
24 | #include <string> |
25 | |
26 | void *getLibraryHandle(const char *path); |
27 | void *loadLibrary(const char *path); |
28 | void freeLibrary(void *library); |
29 | void *getProcAddress(void *library, const char *name); |
30 | |
31 | template<int n> |
32 | void *loadLibrary(const std::string &libraryDirectory, const char *(&names)[n], const char *mustContainSymbol = nullptr) |
33 | { |
34 | for(const char *libraryName : names) |
35 | { |
36 | std::string libraryPath = libraryDirectory + libraryName; |
37 | void *library = getLibraryHandle(libraryPath.c_str()); |
38 | |
39 | if(library) |
40 | { |
41 | if(!mustContainSymbol || getProcAddress(library, mustContainSymbol)) |
42 | { |
43 | return library; |
44 | } |
45 | |
46 | freeLibrary(library); |
47 | } |
48 | } |
49 | |
50 | for(const char *libraryName : names) |
51 | { |
52 | std::string libraryPath = libraryDirectory + libraryName; |
53 | void *library = loadLibrary(libraryPath.c_str()); |
54 | |
55 | if(library) |
56 | { |
57 | if(!mustContainSymbol || getProcAddress(library, mustContainSymbol)) |
58 | { |
59 | return library; |
60 | } |
61 | |
62 | freeLibrary(library); |
63 | } |
64 | } |
65 | |
66 | return nullptr; |
67 | } |
68 | |
69 | #if defined(_WIN32) |
70 | inline void *loadLibrary(const char *path) |
71 | { |
72 | return (void*)LoadLibrary(path); |
73 | } |
74 | |
75 | inline void *getLibraryHandle(const char *path) |
76 | { |
77 | HMODULE module = NULL; |
78 | GetModuleHandleEx(0, path, &module); |
79 | return (void*)module; |
80 | } |
81 | |
82 | inline void freeLibrary(void *library) |
83 | { |
84 | FreeLibrary((HMODULE)library); |
85 | } |
86 | |
87 | inline void *getProcAddress(void *library, const char *name) |
88 | { |
89 | return (void*)GetProcAddress((HMODULE)library, name); |
90 | } |
91 | |
92 | inline std::string getModuleDirectory() |
93 | { |
94 | static int dummy_symbol = 0; |
95 | |
96 | HMODULE module = NULL; |
97 | GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&dummy_symbol, &module); |
98 | |
99 | char filename[1024]; |
100 | if(module && (GetModuleFileName(module, filename, sizeof(filename)) != 0)) |
101 | { |
102 | std::string directory(filename); |
103 | return directory.substr(0, directory.find_last_of("\\/" ) + 1).c_str(); |
104 | } |
105 | else |
106 | { |
107 | return "" ; |
108 | } |
109 | } |
110 | #else |
111 | inline void *loadLibrary(const char *path) |
112 | { |
113 | return dlopen(path, RTLD_LAZY | RTLD_LOCAL); |
114 | } |
115 | |
116 | inline void *getLibraryHandle(const char *path) |
117 | { |
118 | #ifdef __ANDROID__ |
119 | // bionic doesn't support RTLD_NOLOAD before L |
120 | return dlopen(path, RTLD_NOW | RTLD_LOCAL); |
121 | #else |
122 | void *resident = dlopen(path, RTLD_LAZY | RTLD_NOLOAD | RTLD_LOCAL); |
123 | |
124 | if(resident) |
125 | { |
126 | return dlopen(path, RTLD_LAZY | RTLD_LOCAL); // Increment reference count |
127 | } |
128 | |
129 | return nullptr; |
130 | #endif |
131 | } |
132 | |
133 | inline void freeLibrary(void *library) |
134 | { |
135 | if(library) |
136 | { |
137 | dlclose(library); |
138 | } |
139 | } |
140 | |
141 | inline void *getProcAddress(void *library, const char *name) |
142 | { |
143 | void *symbol = dlsym(library, name); |
144 | |
145 | if(!symbol) |
146 | { |
147 | const char *reason = dlerror(); // Silence the error |
148 | (void)reason; |
149 | } |
150 | |
151 | return symbol; |
152 | } |
153 | |
154 | inline std::string getModuleDirectory() |
155 | { |
156 | static int dummy_symbol = 0; |
157 | |
158 | Dl_info dl_info; |
159 | if(dladdr(&dummy_symbol, &dl_info) != 0) |
160 | { |
161 | std::string directory(dl_info.dli_fname); |
162 | return directory.substr(0, directory.find_last_of("\\/" ) + 1).c_str(); |
163 | } |
164 | else |
165 | { |
166 | return "" ; |
167 | } |
168 | } |
169 | #endif |
170 | |
171 | #endif // SharedLibrary_hpp |
172 | |