From 01c117797c27e03ea573b49c364d5869b4d04dd8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Fri, 13 Jan 2012 11:33:03 +0000 Subject: [PATCH] Trace apps that dlopen("libEGL") and friends. --- egltrace.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ glproc_egl.cpp | 1 + 2 files changed, 79 insertions(+) diff --git a/egltrace.py b/egltrace.py index 8fa313a..27edc5a 100644 --- a/egltrace.py +++ b/egltrace.py @@ -110,3 +110,81 @@ if __name__ == '__main__': print ' return procPtr;' print '}' print + print r''' + + +/* + * Invoke the true dlopen() function. + */ +static void *__dlopen(const char *filename, int flag) +{ + typedef void * (*PFNDLOPEN)(const char *, int); + static PFNDLOPEN dlopen_ptr = NULL; + + if (!dlopen_ptr) { + dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen"); + if (!dlopen_ptr) { + os::log("apitrace: error: dlsym(RTLD_NEXT, \"dlopen\") failed\n"); + return NULL; + } + } + + return dlopen_ptr(filename, flag); +} + + +/* + * Several applications, such as Quake3, use dlopen("libGL.so.1"), but + * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore + * we need to intercept the dlopen() call here, and redirect to our wrapper + * shared object. + */ +extern "C" PUBLIC +void * dlopen(const char *filename, int flag) +{ + bool intercept = false; + + if (filename) { + intercept = + strcmp(filename, "libEGL.so") == 0 || + strcmp(filename, "libEGL.so.1") == 0 || + strcmp(filename, "libGLESv1_CM.so") == 0 || + strcmp(filename, "libGLESv1_CM.so.1") == 0 || + strcmp(filename, "libGLESv2.so") == 0 || + strcmp(filename, "libGLESv2.so.2") == 0 || + strcmp(filename, "libGL.so") == 0 || + strcmp(filename, "libGL.so.1") == 0; + + if (intercept) { + os::log("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag); + + /* The current dispatch implementation relies on core entry-points to be globally available, so force this. + * + * TODO: A better approach would be note down the entry points here and + * use them latter. Another alternative would be to reopen the library + * with RTLD_NOLOAD | RTLD_GLOBAL. + */ + flag &= ~RTLD_LOCAL; + flag |= RTLD_GLOBAL; + } + } + + void *handle = __dlopen(filename, flag); + + if (intercept) { + // Get the file path for our shared object, and use it instead + static int dummy = 0xdeedbeef; + Dl_info info; + if (dladdr(&dummy, &info)) { + handle = __dlopen(info.dli_fname, flag); + } else { + os::log("apitrace: warning: dladdr() failed\n"); + } + } + + return handle; +} + + + +''' diff --git a/glproc_egl.cpp b/glproc_egl.cpp index 4ceb2ff..7ba7b5c 100644 --- a/glproc_egl.cpp +++ b/glproc_egl.cpp @@ -37,6 +37,7 @@ /* * Handle to the true OpenGL library. + * XXX: Not really used yet. */ #if defined(_WIN32) HINSTANCE __libGlHandle = NULL; -- 2.7.4