diff options
-rw-r--r-- | dispatch/glproc_gl.cpp | 54 | ||||
-rw-r--r-- | wrappers/CMakeLists.txt | 2 | ||||
-rw-r--r-- | wrappers/dlsym.cpp | 79 |
3 files changed, 82 insertions, 53 deletions
diff --git a/dispatch/glproc_gl.cpp b/dispatch/glproc_gl.cpp index 0ced2f95..fdbea05c 100644 --- a/dispatch/glproc_gl.cpp +++ b/dispatch/glproc_gl.cpp @@ -160,58 +160,6 @@ logSymbol(const char *name, void *ptr) { } -#ifdef __GLIBC__ -extern "C" void * __libc_dlsym(void *, const char *); -#endif - - -/* - * Protect against dlsym interception. - * - * We implement the whole API, so we don't need to intercept dlsym -- dlopen is - * enough. However we need to protect against other dynamic libraries - * intercepting dlsym, to prevent infinite recursion, - * - * In particular the Steam Community Overlay advertises dlsym. See also - * http://lists.freedesktop.org/archives/apitrace/2013-March/000573.html - */ -static inline void * -_dlsym(void *handle, const char *symbol) -{ - void *result; - -#ifdef __GLIBC__ - /* - * We rely on glibc's internal __libc_dlsym. See also - * http://www.linuxforu.com/2011/08/lets-hook-a-library-function/ - * - * Use use it to obtain the true dlsym. We don't use __libc_dlsym directly - * because it does not support things such as RTLD_NEXT. - */ - typedef void * (*PFN_DLSYM)(void *, const char *); - static PFN_DLSYM dlsym_ptr = NULL; - if (!dlsym_ptr) { - void *libdl_handle = _dlopen("libdl.so.2", RTLD_LOCAL | RTLD_NOW); - if (libdl_handle) { - dlsym_ptr = (PFN_DLSYM)__libc_dlsym(libdl_handle, "dlsym"); - } - if (!dlsym_ptr) { - os::log("apitrace: error: failed to look up real dlsym\n"); - return NULL; - } - - logSymbol("dlsym", (void*)dlsym_ptr); - } - - result = dlsym_ptr(handle, symbol); -#else - result = dlsym(handle, symbol); -#endif - - return result; -} - - /* * Lookup a libGL symbol */ @@ -255,7 +203,7 @@ void * _libgl_sym(const char *symbol) } } - result = _dlsym(_libGlHandle, symbol); + result = dlsym(_libGlHandle, symbol); logSymbol(symbol, result); diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt index 36a77a4d..ed1757d5 100644 --- a/wrappers/CMakeLists.txt +++ b/wrappers/CMakeLists.txt @@ -390,6 +390,7 @@ elseif (X11_FOUND) glxtrace.cpp glcaps.cpp gltrace_state.cpp + dlsym.cpp ) add_dependencies (glxtrace glproc) @@ -438,6 +439,7 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE) glcaps.cpp gltrace_state.cpp ${CMAKE_SOURCE_DIR}/helpers/eglsize.cpp + dlsym.cpp ) add_dependencies (egltrace glproc) diff --git a/wrappers/dlsym.cpp b/wrappers/dlsym.cpp new file mode 100644 index 00000000..118110f2 --- /dev/null +++ b/wrappers/dlsym.cpp @@ -0,0 +1,79 @@ +/************************************************************************** + * + * Copyright 2014 VMware, Inc. + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * 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.hpp" + + +#ifdef __GLIBC__ + + +#include <dlfcn.h> + +extern "C" void * __libc_dlopen_mode(const char * filename, int flag); +extern "C" void * __libc_dlsym(void * handle, const char * symbol); + + +/* + * Protect against dlsym interception. + * + * We implement the whole API, so we don't need to intercept dlsym -- dlopen is + * enough. However we need to protect against other dynamic libraries + * intercepting dlsym, to prevent infinite recursion, + * + * In particular the Steam Community Overlay exports dlsym. See also + * http://lists.freedesktop.org/archives/apitrace/2013-March/000573.html + */ +PRIVATE +void * +dlsym(void * handle, const char * symbol) +{ + /* + * We rely on glibc's internal __libc_dlsym. See also + * http://www.linuxforu.com/2011/08/lets-hook-a-library-function/ + * + * Use use it to obtain the true dlsym. We don't use __libc_dlsym directly + * because it does not support things such as RTLD_NEXT. + */ + typedef void * (*PFN_DLSYM)(void *, const char *); + static PFN_DLSYM dlsym_ptr = NULL; + if (!dlsym_ptr) { + void *libdl_handle = __libc_dlopen_mode("libdl.so.2", RTLD_LOCAL | RTLD_NOW); + if (libdl_handle) { + dlsym_ptr = (PFN_DLSYM)__libc_dlsym(libdl_handle, "dlsym"); + } + if (!dlsym_ptr) { + os::log("apitrace: error: failed to look up real dlsym\n"); + return NULL; + } + } + + return dlsym_ptr(handle, symbol); +} + + + +#endif /* __GLIBC__ */ |