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>
loadLibrary(const std::string & libraryDirectory,const char * (& names)[n],const char * mustContainSymbol=nullptr)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)
loadLibrary(const char * path)70 inline void *loadLibrary(const char *path)
71 {
72 return (void*)LoadLibrary(path);
73 }
74
getLibraryHandle(const char * path)75 inline void *getLibraryHandle(const char *path)
76 {
77 HMODULE module = NULL;
78 GetModuleHandleEx(0, path, &module);
79 return (void*)module;
80 }
81
freeLibrary(void * library)82 inline void freeLibrary(void *library)
83 {
84 FreeLibrary((HMODULE)library);
85 }
86
getProcAddress(void * library,const char * name)87 inline void *getProcAddress(void *library, const char *name)
88 {
89 return (void*)GetProcAddress((HMODULE)library, name);
90 }
91
getModuleDirectory()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
loadLibrary(const char * path)111 inline void *loadLibrary(const char *path)
112 {
113 return dlopen(path, RTLD_LAZY | RTLD_LOCAL);
114 }
115
getLibraryHandle(const char * path)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
freeLibrary(void * library)133 inline void freeLibrary(void *library)
134 {
135 if(library)
136 {
137 dlclose(library);
138 }
139 }
140
getProcAddress(void * library,const char * name)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
getModuleDirectory()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