From c9e80096b66c0d6609e8bedb61f55814a6eca21d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sat, 23 Apr 2011 10:46:21 +0100 Subject: [PATCH] Provide an alternative tracing mechanism based on LD_LIBRARY_PATH. Still a bit flaky because everybody, even DRI drivers, are trying to dlopen("libGL.so"). --- README | 23 ++++++++++++++++++++--- glxtrace.py | 39 ++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/README b/README index 37ecc4a..f0b8bf2 100644 --- a/README +++ b/README @@ -89,7 +89,7 @@ http://www.cmake.org/Wiki/CmakeMingw for detailed instructions. == Linux == -* Run the application you want to trace as +Run the application you want to trace as LD_PRELOAD=/path/to/glxtrace.so /path/to/application @@ -97,15 +97,32 @@ and it will generate a trace named "application.trace" in the current directory. You can specify the written trace filename by setting the TRACE_FILE envirnment variable before running. -* View the trace with +View the trace with /path/to/tracedump application.trace | less -R -* Replay the trace with +Replay the trace with /path/to/glretrace application.trace +The LD_PRELOAD mechanism should work with most applications. There are some +applications, e.g., Unigine Heaven, which global function pointers with the +same name as GL entrypoints, living in a shared object that wasn't linked with +-Bsymbolic flag, so relocations to those globals function pointers get +overwritten with the address to our wrapper library, and the application will +segfault when trying to write to them. For these applications it is possible +to trace by using glxtrace.so as an ordinary libGL.so and injecting into +LD_LIBRARY_PATH: + + ln -s glxtrace.so libGL.so + ln -s glxtrace.so libGL.so.1 + ln -s glxtrace.so libGL.so.1.2 + export LD_LIBRARY_PATH=/path/to/directory/where/glxtrace/is:$LD_LIBRARY_PATH + export TRACE_LIBGL=/path/to/real/libGL.so.1 + /path/to/application + + == Windows == * Copy opengl32.dll, d3d8.dll, or d3d9.dll from build/wrappers directory to the diff --git a/glxtrace.py b/glxtrace.py index 7a3574b..78d6146 100644 --- a/glxtrace.py +++ b/glxtrace.py @@ -90,6 +90,9 @@ if __name__ == '__main__': print r''' +/* + * Handle to the true libGL.so + */ static void *libgl_handle = NULL; @@ -126,7 +129,9 @@ void * dlopen(const char *filename, int flag) handle = __dlopen(filename, flag); - if (filename && handle) { + const char * libgl_filename = getenv("TRACE_LIBGL"); + + if (filename && handle && !libgl_filename) { if (0) { OS::DebugMessage("warning: dlopen(\"%s\", 0x%x)\n", filename, flag); } @@ -134,6 +139,7 @@ void * dlopen(const char *filename, int flag) // FIXME: handle absolute paths and other versions if (strcmp(filename, "libGL.so") == 0 || strcmp(filename, "libGL.so.1") == 0) { + // Use the true libGL.so handle instead of RTLD_NEXT from now on libgl_handle = handle; @@ -162,19 +168,34 @@ static void * __dlsym(const char *symbol) if (!libgl_handle) { /* - * Try to use whatever libGL.so the library is linked against. + * The app doesn't directly link against libGL.so, nor does it directly + * dlopen it. So we have to load it ourselves. */ - result = dlsym(RTLD_NEXT, symbol); - if (result) { - libgl_handle = RTLD_NEXT; - return result; + + const char * libgl_filename = getenv("TRACE_LIBGL"); + + if (!libgl_filename) { + /* + * Try to use whatever libGL.so the library is linked against. + */ + + result = dlsym(RTLD_NEXT, symbol); + if (result) { + libgl_handle = RTLD_NEXT; + return result; + } + + libgl_filename = "libGL.so.1"; } /* - * The app doesn't directly link against libGL.so, nor does it directly - * dlopen it. So we have to load it ourselves. + * It would have been preferable to use RTLD_LOCAL to ensure that the + * application can never access libGL.so symbols directly, but this + * won't work, given libGL.so often loads a driver specific SO and + * exposes symbols to it. */ - libgl_handle = __dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); + + libgl_handle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY); if (!libgl_handle) { OS::DebugMessage("error: couldn't find libGL.so\n"); return NULL; -- 2.7.4