• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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