OSDN Git Service

Load sibling libraries from the same directory
[android-x86/external-swiftshader.git] / src / Common / SharedLibrary.hpp
index adaa7fc..85e5e7d 100644 (file)
-// SwiftShader Software Renderer\r
-//\r
-// Copyright(c) 2005-2012 TransGaming Inc.\r
-//\r
-// All rights reserved. No part of this software may be copied, distributed, transmitted,\r
-// transcribed, stored in a retrieval system, translated into any human or computer\r
-// language by any means, or disclosed to third parties without the explicit written\r
-// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express\r
-// or implied, including but not limited to any patent rights, are granted to you.\r
-//\r
-\r
-#if defined(_WIN32)\r
-       #include <Windows.h>\r
-#else\r
-       #include <dlfcn.h>\r
-#endif\r
-\r
-void *getLibraryHandle(const char *path);\r
-void *loadLibrary(const char *path);\r
-\r
-template<int n>\r
-void *loadLibrary(const char *(&names)[n])\r
-{\r
-       for(int i = 0; i < n; i++)\r
-       {\r
-               void *library = getLibraryHandle(names[i]);\r
-\r
-               if(library)\r
-               {\r
-                       return library;\r
-               }\r
-       }\r
-\r
-       for(int i = 0; i < n; i++)\r
-       {\r
-               void *library = loadLibrary(names[i]);\r
-\r
-               if(library)\r
-               {\r
-                       return library;\r
-               }\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-#if defined(_WIN32)\r
-       inline void *loadLibrary(const char *path)\r
-       {\r
-               return (void*)LoadLibrary(path);\r
-       }\r
-\r
-       inline void *getLibraryHandle(const char *path)\r
-       {\r
-               HMODULE module = 0;\r
-               GetModuleHandleEx(0, path, &module);\r
-               return (void*)module;\r
-       }\r
-\r
-       inline void freeLibrary(void *library)\r
-       {\r
-               FreeLibrary((HMODULE)library);\r
-       }\r
-\r
-       inline void *getProcAddress(void *library, const char *name)\r
-       {\r
-               return (void*)GetProcAddress((HMODULE)library, name);\r
-       }\r
-#else\r
-       inline void *loadLibrary(const char *path)\r
-       {\r
-               return dlopen(path, RTLD_LAZY);\r
-       }\r
-\r
-       inline void *getLibraryHandle(const char *path)\r
-       {\r
-               #ifdef __ANDROID__\r
-                       // bionic doesn't support RTLD_NOLOAD before L\r
-                       return dlopen(path, RTLD_NOW);\r
-               #else\r
-                       void *resident = dlopen(path, RTLD_LAZY | RTLD_NOLOAD);\r
-\r
-                       if(resident)\r
-                       {\r
-                               return dlopen(path, RTLD_LAZY);   // Increment reference count\r
-                       }\r
-\r
-                       return 0;\r
-               #endif\r
-       }\r
-\r
-    inline void freeLibrary(void *library)\r
-    {\r
-        if(library)\r
-        {\r
-            dlclose(library);\r
-        }\r
-    }\r
-\r
-       inline void *getProcAddress(void *library, const char *name)\r
-       {\r
-               return library ? dlsym(library, name) : 0;\r
-       }\r
-#endif\r
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SharedLibrary_hpp
+#define SharedLibrary_hpp
+
+#if defined(_WIN32)
+       #include <Windows.h>
+#else
+       #include <dlfcn.h>
+#endif
+
+#include <string>
+
+void *getLibraryHandle(const char *path);
+void *loadLibrary(const char *path);
+void freeLibrary(void *library);
+void *getProcAddress(void *library, const char *name);
+
+template<int n>
+void *loadLibrary(const std::string &libraryDirectory, const char *(&names)[n], const char *mustContainSymbol = nullptr)
+{
+       if(!libraryDirectory.empty())
+       {
+               for(int i = 0; i < n; i++)
+               {
+                       std::string nameWithPath = libraryDirectory + names[i];
+                       void *library = getLibraryHandle(nameWithPath.c_str());
+
+                       if(library)
+                       {
+                               if(!mustContainSymbol || getProcAddress(library, mustContainSymbol))
+                               {
+                                       return library;
+                               }
+
+                               freeLibrary(library);
+                       }
+               }
+       }
+
+       for(int i = 0; i < n; i++)
+       {
+               void *library = getLibraryHandle(names[i]);
+
+               if(library)
+               {
+                       if(!mustContainSymbol || getProcAddress(library, mustContainSymbol))
+                       {
+                               return library;
+                       }
+
+                       freeLibrary(library);
+               }
+       }
+
+       for(int i = 0; i < n; i++)
+       {
+               void *library = loadLibrary(names[i]);
+
+               if(library)
+               {
+                       if(!mustContainSymbol || getProcAddress(library, mustContainSymbol))
+                       {
+                               return library;
+                       }
+
+                       freeLibrary(library);
+               }
+       }
+
+       return nullptr;
+}
+
+#if defined(_WIN32)
+       inline void *loadLibrary(const char *path)
+       {
+               return (void*)LoadLibrary(path);
+       }
+
+       inline void *getLibraryHandle(const char *path)
+       {
+               HMODULE module = NULL;
+               GetModuleHandleEx(0, path, &module);
+               return (void*)module;
+       }
+
+       inline void freeLibrary(void *library)
+       {
+               FreeLibrary((HMODULE)library);
+       }
+
+       inline void *getProcAddress(void *library, const char *name)
+       {
+               return (void*)GetProcAddress((HMODULE)library, name);
+       }
+
+       inline std::string getLibraryDirectoryFromSymbol(void* symbol)
+       {
+               HMODULE module = NULL;
+               GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)symbol, &module);
+               char filename[1024];
+               if(module && (GetModuleFileName(module, filename, sizeof(filename)) != 0))
+               {
+                       std::string directory(filename);
+                       return directory.substr(0, directory.find_last_of("\\/") + 1).c_str();
+               }
+               else
+               {
+                       return "";
+               }
+       }
+#else
+       inline void *loadLibrary(const char *path)
+       {
+               return dlopen(path, RTLD_LAZY | RTLD_LOCAL);
+       }
+
+       inline void *getLibraryHandle(const char *path)
+       {
+               #ifdef __ANDROID__
+                       // bionic doesn't support RTLD_NOLOAD before L
+                       return dlopen(path, RTLD_NOW | RTLD_LOCAL);
+               #else
+                       void *resident = dlopen(path, RTLD_LAZY | RTLD_NOLOAD | RTLD_LOCAL);
+
+                       if(resident)
+                       {
+                               return dlopen(path, RTLD_LAZY | RTLD_LOCAL);   // Increment reference count
+                       }
+
+                       return nullptr;
+               #endif
+       }
+
+       inline void freeLibrary(void *library)
+       {
+               if(library)
+               {
+                       dlclose(library);
+               }
+       }
+
+       inline void *getProcAddress(void *library, const char *name)
+       {
+               void *symbol = dlsym(library, name);
+
+               if(!symbol)
+               {
+                       const char *reason = dlerror();   // Silence the error
+                       (void)reason;
+               }
+
+               return symbol;
+       }
+
+       inline std::string getLibraryDirectoryFromSymbol(void* symbol)
+       {
+               Dl_info dl_info;
+               if(dladdr(symbol, &dl_info) != 0)
+               {
+                       std::string directory(dl_info.dli_fname);
+                       return directory.substr(0, directory.find_last_of("\\/") + 1).c_str();
+               }
+               else
+               {
+                       return "";
+               }
+       }
+#endif
+
+#endif   // SharedLibrary_hpp