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 std::string getModuleDirectory();
31
32 template<int n>
loadLibrary(const std::string & libraryDirectory,const char * (& names)[n],const char * mustContainSymbol=nullptr)33 void *loadLibrary(const std::string &libraryDirectory, const char *(&names)[n], const char *mustContainSymbol = nullptr)
34 {
35 for(const char *libraryName : names)
36 {
37 std::string libraryPath = libraryDirectory + libraryName;
38 void *library = getLibraryHandle(libraryPath.c_str());
39
40 if(library)
41 {
42 if(!mustContainSymbol || getProcAddress(library, mustContainSymbol))
43 {
44 return library;
45 }
46
47 freeLibrary(library);
48 }
49 }
50
51 for(const char *libraryName : names)
52 {
53 std::string libraryPath = libraryDirectory + libraryName;
54 void *library = loadLibrary(libraryPath.c_str());
55
56 if(library)
57 {
58 if(!mustContainSymbol || getProcAddress(library, mustContainSymbol))
59 {
60 return library;
61 }
62
63 freeLibrary(library);
64 }
65 }
66
67 return nullptr;
68 }
69
70 #if defined(_WIN32)
loadLibrary(const char * path)71 inline void *loadLibrary(const char *path)
72 {
73 return (void*)LoadLibrary(path);
74 }
75
getLibraryHandle(const char * path)76 inline void *getLibraryHandle(const char *path)
77 {
78 HMODULE module = NULL;
79 GetModuleHandleEx(0, path, &module);
80 return (void*)module;
81 }
82
freeLibrary(void * library)83 inline void freeLibrary(void *library)
84 {
85 FreeLibrary((HMODULE)library);
86 }
87
getProcAddress(void * library,const char * name)88 inline void *getProcAddress(void *library, const char *name)
89 {
90 return (void*)GetProcAddress((HMODULE)library, name);
91 }
92 #else
loadLibrary(const char * path)93 inline void *loadLibrary(const char *path)
94 {
95 return dlopen(path, RTLD_LAZY | RTLD_LOCAL);
96 }
97
getLibraryHandle(const char * path)98 inline void *getLibraryHandle(const char *path)
99 {
100 #ifdef __ANDROID__
101 // bionic doesn't support RTLD_NOLOAD before L
102 return dlopen(path, RTLD_NOW | RTLD_LOCAL);
103 #else
104 void *resident = dlopen(path, RTLD_LAZY | RTLD_NOLOAD | RTLD_LOCAL);
105
106 if(resident)
107 {
108 return dlopen(path, RTLD_LAZY | RTLD_LOCAL); // Increment reference count
109 }
110
111 return nullptr;
112 #endif
113 }
114
freeLibrary(void * library)115 inline void freeLibrary(void *library)
116 {
117 if(library)
118 {
119 dlclose(library);
120 }
121 }
122
getProcAddress(void * library,const char * name)123 inline void *getProcAddress(void *library, const char *name)
124 {
125 void *symbol = dlsym(library, name);
126
127 if(!symbol)
128 {
129 const char *reason = dlerror(); // Silence the error
130 (void)reason;
131 }
132
133 return symbol;
134 }
135 #endif
136
137 #endif // SharedLibrary_hpp
138