X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=dispatch%2Fglproc_gl.cpp;h=2516dab81c441e685a5797096a53c032056567b7;hb=abaef29db0cf1a3e2adb0c254886162368b1645a;hp=27b3ef7dc86706c45c1a9cd290726a73104a5cfd;hpb=4f242f43bf4b3c8f5daadc4496c0e84ae55117b3;p=apitrace diff --git a/dispatch/glproc_gl.cpp b/dispatch/glproc_gl.cpp index 27b3ef7..2516dab 100644 --- a/dispatch/glproc_gl.cpp +++ b/dispatch/glproc_gl.cpp @@ -29,7 +29,7 @@ #if !defined(_WIN32) #include // for symlink -#include +#include "dlopen.hpp" #endif @@ -37,9 +37,9 @@ * Handle to the true OpenGL library. */ #if defined(_WIN32) -HINSTANCE __libGlHandle = NULL; +HMODULE _libGlHandle = NULL; #else -void *__libGlHandle = NULL; +void *_libGlHandle = NULL; #endif @@ -47,9 +47,9 @@ void *__libGlHandle = NULL; #if defined(_WIN32) void * -__getPublicProcAddress(const char *procName) +_getPublicProcAddress(const char *procName) { - if (!__libGlHandle) { + if (!_libGlHandle) { char szDll[MAX_PATH] = {0}; if (!GetSystemDirectoryA(szDll, MAX_PATH)) { @@ -58,20 +58,20 @@ __getPublicProcAddress(const char *procName) strcat(szDll, "\\\\opengl32.dll"); - __libGlHandle = LoadLibraryA(szDll); - if (!__libGlHandle) { + _libGlHandle = LoadLibraryA(szDll); + if (!_libGlHandle) { os::log("apitrace: error: couldn't load %s\n", szDll); return NULL; } } - return (void *)GetProcAddress(__libGlHandle, procName); + return (void *)GetProcAddress(_libGlHandle, procName); } void * -__getPrivateProcAddress(const char *procName) { - return (void *)__wglGetProcAddress(procName); +_getPrivateProcAddress(const char *procName) { + return (void *)_wglGetProcAddress(procName); } @@ -87,11 +87,11 @@ static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework /* * Lookup a libGL symbol */ -void * __libgl_sym(const char *symbol) +void * _libgl_sym(const char *symbol) { void *result; - if (!__libGlHandle) { + if (!_libGlHandle) { /* * Unfortunately we can't just dlopen the true dynamic library because * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for @@ -103,75 +103,123 @@ void * __libgl_sym(const char *symbol) if (mktemp(temp_filename) != NULL) { if (symlink(libgl_filename, temp_filename) == 0) { - __libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST); + _libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST); remove(temp_filename); } } - if (!__libGlHandle) { + if (!_libGlHandle) { os::log("apitrace: error: couldn't load %s\n", libgl_filename); os::abort(); return NULL; } } - result = dlsym(__libGlHandle, symbol); + result = dlsym(_libGlHandle, symbol); - if (resullt && result == dlsym(RTLD_SELF, symbol)) { +#if 0 + if (result && result == dlsym(RTLD_SELF, symbol)) { os::log("apitrace: error: symbol lookup recursion\n"); os::abort(); return NULL; } +#endif return result; } void * -__getPublicProcAddress(const char *procName) +_getPublicProcAddress(const char *procName) { - return __libgl_sym(procName); + return _libgl_sym(procName); } void * -__getPrivateProcAddress(const char *procName) +_getPrivateProcAddress(const char *procName) { - return __libgl_sym(procName); + return _libgl_sym(procName); } #else +static inline void +logSymbol(const char *name, void *ptr) { + if (0) { + if (ptr) { + Dl_info info; + if (ptr && dladdr(ptr, &info)) { + os::log("apitrace: %s -> \"%s\"\n", name, info.dli_fname); + } + } else { + os::log("apitrace: %s -> NULL\n", name); + } + } +} + + +#ifdef __GLIBC__ +extern "C" void * __libc_dlsym(void *, const char *); +#endif + + /* - * Invoke the true dlopen() function. + * 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 void * -__dlopen(const char *filename, int flag) +static inline void * +_dlsym(void *handle, const char *symbol) { - typedef void * (*PFNDLOPEN)(const char *, int); - static PFNDLOPEN dlopen_ptr = NULL; + void *result; - if (!dlopen_ptr) { - dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen"); - if (!dlopen_ptr) { - os::log("apitrace: error: dlsym(RTLD_NEXT, \"dlopen\") failed\n"); +#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); } - return dlopen_ptr(filename, flag); + result = dlsym_ptr(handle, symbol); +#else + result = dlsym(handle, symbol); +#endif + + return result; } /* * Lookup a libGL symbol */ -void * __libgl_sym(const char *symbol) +void * _libgl_sym(const char *symbol) { void *result; - if (!__libGlHandle) { + if (!_libGlHandle) { /* * The app doesn't directly link against libGL.so, nor does it directly * dlopen it. So we have to load it ourselves. @@ -186,7 +234,7 @@ void * __libgl_sym(const char *symbol) result = dlsym(RTLD_NEXT, symbol); if (result) { - __libGlHandle = RTLD_NEXT; + _libGlHandle = RTLD_NEXT; return result; } @@ -200,27 +248,31 @@ void * __libgl_sym(const char *symbol) * exposes symbols to it. */ - __libGlHandle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY); - if (!__libGlHandle) { + _libGlHandle = _dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY); + if (!_libGlHandle) { os::log("apitrace: error: couldn't find libGL.so\n"); return NULL; } } - return dlsym(__libGlHandle, symbol); + result = _dlsym(_libGlHandle, symbol); + + logSymbol(symbol, result); + + return result; } void * -__getPublicProcAddress(const char *procName) +_getPublicProcAddress(const char *procName) { - return __libgl_sym(procName); + return _libgl_sym(procName); } void * -__getPrivateProcAddress(const char *procName) +_getPrivateProcAddress(const char *procName) { - return (void *)__glXGetProcAddressARB((const GLubyte *)procName); + return (void *)_glXGetProcAddressARB((const GLubyte *)procName); }