diff --git a/renderdoc/Makefile b/renderdoc/Makefile index c6ed78ab4..9f42b60fb 100644 --- a/renderdoc/Makefile +++ b/renderdoc/Makefile @@ -38,6 +38,7 @@ os/os_specific.o \ 3rdparty/tinyexr/tinyexr.o \ os/linux/linux_libentry.o \ os/linux/linux_callstack.o \ +os/linux/linux_hook.o \ os/linux/linux_network.o \ os/linux/linux_process.o \ os/linux/linux_stringio.o \ diff --git a/renderdoc/driver/gl/gl_hooks_linux.cpp b/renderdoc/driver/gl/gl_hooks_linux.cpp index 92ff72324..6837d66cb 100644 --- a/renderdoc/driver/gl/gl_hooks_linux.cpp +++ b/renderdoc/driver/gl/gl_hooks_linux.cpp @@ -276,11 +276,20 @@ class OpenGLHook : LibraryHook delete m_GLDriver; } + static void libHooked(void *realLib) + { + libGLdlsymHandle = realLib; + OpenGLHook::glhooks.CreateHooks(NULL); + } + bool CreateHooks(const char *libName) { if(!m_EnabledHooks) return false; + if(libName) + LinuxHookLibrary("libGL.so", &libHooked); + bool success = SetupHooks(GL); if(!success) return false; @@ -816,27 +825,6 @@ __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *f) return glXGetProcAddress(f); } -typedef void* (*DLOPENPROC)(const char*,int); -DLOPENPROC realdlopen = NULL; - -__attribute__ ((visibility ("default"))) -void *dlopen(const char *filename, int flag) -{ - if(realdlopen == NULL) realdlopen = (DLOPENPROC)dlsym(RTLD_NEXT, "dlopen"); - - void *ret = realdlopen(filename, flag); - - if(filename && ret && strstr(filename, "libGL.so")) - { - RDCDEBUG("Redirecting dlopen to ourselves"); - libGLdlsymHandle = ret; - OpenGLHook::glhooks.CreateHooks("libGL.so"); - ret = realdlopen("librenderdoc.so", flag); - } - - return ret; -} - bool OpenGLHook::PopulateHooks() { bool success = true; diff --git a/renderdoc/hooks/hooks.h b/renderdoc/hooks/hooks.h index 426734f87..0a5468f93 100644 --- a/renderdoc/hooks/hooks.h +++ b/renderdoc/hooks/hooks.h @@ -76,6 +76,8 @@ class Hook #elif defined(LINUX) +#include "os/linux/linux_hook.h" + // just need this for dlsym #include diff --git a/renderdoc/os/linux/linux_hook.cpp b/renderdoc/os/linux/linux_hook.cpp new file mode 100644 index 000000000..9a8d95ca8 --- /dev/null +++ b/renderdoc/os/linux/linux_hook.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2015 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "os/os_specific.h" + +#include "linux_hook.h" + +#include "serialise/string_utils.h" +#include "common/threading.h" + +#include +#include + +#include +#include + +// need to lock around use of realdlopen and libraryHooks +Threading::CriticalSection libLock; + +static std::map libraryHooks; + +void LinuxHookLibrary(const char *name, dlopenCallback cb) +{ + SCOPED_LOCK(libLock); + libraryHooks[name] = cb; +} + +typedef void* (*DLOPENPROC)(const char*,int); +DLOPENPROC realdlopen = NULL; + +__attribute__ ((visibility ("default"))) +void *dlopen(const char *filename, int flag) +{ + SCOPED_LOCK(libLock); + if(realdlopen == NULL) realdlopen = (DLOPENPROC)dlsym(RTLD_NEXT, "dlopen"); + + void *ret = realdlopen(filename, flag); + + if(filename && ret) + { + for(auto it = libraryHooks.begin(); it != libraryHooks.end(); ++it) + { + if(strstr(filename, it->first.c_str())) + { + RDCDEBUG("Redirecting dlopen to ourselves for %s", filename); + + it->second(ret); + + ret = realdlopen("librenderdoc.so", flag); + } + } + } + + return ret; +} + diff --git a/renderdoc/os/linux/linux_hook.h b/renderdoc/os/linux/linux_hook.h new file mode 100644 index 000000000..b36ea5865 --- /dev/null +++ b/renderdoc/os/linux/linux_hook.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2015 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +typedef void (*dlopenCallback)(void *realLib); + +// if this name is dlopen'd, the real library will be passed +// to the callback and librenderdoc.so will be returned to user code +void LinuxHookLibrary(const char *name, dlopenCallback cb); diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index b63f1ef6b..1614b6648 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -291,6 +291,9 @@ true + + true + true @@ -383,4 +386,4 @@ - \ No newline at end of file + diff --git a/renderdoc/renderdoc.vcxproj.filters b/renderdoc/renderdoc.vcxproj.filters index 1b9f8a073..9d0d69979 100644 --- a/renderdoc/renderdoc.vcxproj.filters +++ b/renderdoc/renderdoc.vcxproj.filters @@ -329,6 +329,9 @@ OS\Linux + + OS\Linux + OS\Linux @@ -424,4 +427,4 @@ Resources - \ No newline at end of file +