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