OSDN Git Service

Newly load sibling library from the same directory.
[android-x86/external-swiftshader.git] / src / Common / SharedLibrary.hpp
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>
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)
70         inline void *loadLibrary(const char *path)
71         {
72                 return (void*)LoadLibrary(path);
73         }
74
75         inline void *getLibraryHandle(const char *path)
76         {
77                 HMODULE module = NULL;
78                 GetModuleHandleEx(0, path, &module);
79                 return (void*)module;
80         }
81
82         inline void freeLibrary(void *library)
83         {
84                 FreeLibrary((HMODULE)library);
85         }
86
87         inline void *getProcAddress(void *library, const char *name)
88         {
89                 return (void*)GetProcAddress((HMODULE)library, name);
90         }
91
92         inline std::string getLibraryDirectoryFromSymbol(void* symbol)
93         {
94                 HMODULE module = NULL;
95                 GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)symbol, &module);
96                 char filename[1024];
97                 if(module && (GetModuleFileName(module, filename, sizeof(filename)) != 0))
98                 {
99                         std::string directory(filename);
100                         return directory.substr(0, directory.find_last_of("\\/") + 1).c_str();
101                 }
102                 else
103                 {
104                         return "";
105                 }
106         }
107 #else
108         inline void *loadLibrary(const char *path)
109         {
110                 return dlopen(path, RTLD_LAZY | RTLD_LOCAL);
111         }
112
113         inline void *getLibraryHandle(const char *path)
114         {
115                 #ifdef __ANDROID__
116                         // bionic doesn't support RTLD_NOLOAD before L
117                         return dlopen(path, RTLD_NOW | RTLD_LOCAL);
118                 #else
119                         void *resident = dlopen(path, RTLD_LAZY | RTLD_NOLOAD | RTLD_LOCAL);
120
121                         if(resident)
122                         {
123                                 return dlopen(path, RTLD_LAZY | RTLD_LOCAL);   // Increment reference count
124                         }
125
126                         return nullptr;
127                 #endif
128         }
129
130         inline void freeLibrary(void *library)
131         {
132                 if(library)
133                 {
134                         dlclose(library);
135                 }
136         }
137
138         inline void *getProcAddress(void *library, const char *name)
139         {
140                 void *symbol = dlsym(library, name);
141
142                 if(!symbol)
143                 {
144                         const char *reason = dlerror();   // Silence the error
145                         (void)reason;
146                 }
147
148                 return symbol;
149         }
150
151         inline std::string getLibraryDirectoryFromSymbol(void* symbol)
152         {
153                 Dl_info dl_info;
154                 if(dladdr(symbol, &dl_info) != 0)
155                 {
156                         std::string directory(dl_info.dli_fname);
157                         return directory.substr(0, directory.find_last_of("\\/") + 1).c_str();
158                 }
159                 else
160                 {
161                         return "";
162                 }
163         }
164 #endif
165
166 #endif   // SharedLibrary_hpp