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