X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=egltrace.py;h=e16367a7fa1ac927424d4a27893833ff89b09de1;hb=a5b476eb4eed9b06e22f4a80b16251aea243207d;hp=1148924d7e58447adcb80a2526ca1d26abc1ab7d;hpb=e64ba4980c20ba52f6b3a88bc817623052e6d0a8;p=apitrace diff --git a/egltrace.py b/egltrace.py index 1148924..e16367a 100644 --- a/egltrace.py +++ b/egltrace.py @@ -42,12 +42,12 @@ from dispatch import function_pointer_type, function_pointer_value class EglTracer(GlTracer): - def is_public_function(self, function): + def isFunctionPublic(self, function): # The symbols visible in libEGL.so can vary, so expose them all return True - def trace_function_impl_body(self, function): - GlTracer.trace_function_impl_body(self, function) + def traceFunctionImplBody(self, function): + GlTracer.traceFunctionImplBody(self, function) if function.name == 'eglMakeCurrent': print ' // update the profile' @@ -64,8 +64,8 @@ class EglTracer(GlTracer): print ' tr->profile = PROFILE_ES2;' print ' }' - def wrap_ret(self, function, instance): - GlTracer.wrap_ret(self, function, instance) + def wrapRet(self, function, instance): + GlTracer.wrapRet(self, function, instance) if function.name == "eglGetProcAddress": print ' %s = __unwrap_proc_addr(procname, %s);' % (instance, instance) @@ -76,7 +76,7 @@ if __name__ == '__main__': print '#include ' print '#include ' print - print '#include "trace_writer.hpp"' + print '#include "trace_writer_local.hpp"' print print '// To validate our prototypes' print '#define GL_GLEXT_PROTOTYPES' @@ -89,9 +89,9 @@ if __name__ == '__main__': print api = API() - api.add_api(eglapi) - api.add_api(glapi) - api.add_api(glesapi) + api.addApi(eglapi) + api.addApi(glapi) + api.addApi(glesapi) tracer = EglTracer() tracer.trace_api(api) @@ -112,21 +112,79 @@ if __name__ == '__main__': print print r''' + /* - * Lookup a EGL or GLES symbol + * Invoke the true dlopen() function. */ -void * __libegl_sym(const char *symbol) +static void *__dlopen(const char *filename, int flag) { - void *proc; + 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); +} - /* Always try dlsym before eglGetProcAddress as spec 3.10 says - * implementation may choose to also export extension functions - * publicly. - */ - proc = dlsym(RTLD_NEXT, symbol); - if (!proc && symbol[0] == 'g' && symbol[1] == 'l') - proc = (void *) __eglGetProcAddress(symbol); - return proc; +/* + * 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; } + + + '''