X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=egltrace.py;h=5d5c7593a9f51b8663b901e9fe969786d7fa2115;hb=4644dc65e83c56ba0bb577f57cd20e7419f3ade4;hp=de90799bf1ccc35056d94f50886e04efec3cc986;hpb=1cfd89b2bb73c94340d61936a72bec346c3ca22d;p=apitrace diff --git a/egltrace.py b/egltrace.py index de90799..5d5c759 100644 --- a/egltrace.py +++ b/egltrace.py @@ -42,30 +42,30 @@ 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' print ' if (ctx != EGL_NO_CONTEXT) {' print ' EGLint api = EGL_OPENGL_ES_API, version = 1;' - print ' tracer_context *tr = __get_context();' + print ' gltrace::Context *tr = gltrace::getContext();' print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);' print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &version);' print ' if (api == EGL_OPENGL_API)' - print ' tr->profile = PROFILE_COMPAT;' + print ' tr->profile = gltrace::PROFILE_COMPAT;' print ' else if (version == 1)' - print ' tr->profile = PROFILE_ES1;' + print ' tr->profile = gltrace::PROFILE_ES1;' print ' else' - print ' tr->profile = PROFILE_ES2;' + print ' tr->profile = gltrace::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) @@ -110,3 +110,90 @@ if __name__ == '__main__': print ' return procPtr;' print '}' print + print r''' + + +/* + * Android does not support LD_PRELOAD. + */ +#if !defined(ANDROID) + + +/* + * 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; +} + + +#endif /* !ANDROID */ + + + +'''