[PATCH] Improve Android tracing instructions

Alexander Monakov amonakov at ispras.ru
Fri May 3 10:24:53 PDT 2013


Hello,

On Thu, May 2, 2013 at 3:13 AM, Rajib Nath <rknath at ucsd.edu> wrote:
> We have changed the init.rc file to preload egltrace.so before zygote

You didn't really need to do that.

> adb shell am start -a android.intent.action.MAIN -n
> com.imangi.templerun2/com.unity3d.player.UnityPlayerNativeActivity

Can you explain how to obtain proper "am start" incantations for arbitrary apps?

> The app gets started. However we always get a empty tracefile.

The problem here is that Unity3D loads OpenGL libraries dynamically
via dlopen, so the egltrace.so interposer needs to interpose dlopen.
The attached patch should fix it for you.

Jose, can you have a look at the patch and consider for inclusion?
I've decided to keep the _dlopen name as is to minimize noise in the
patch. Thanks.

Alexander
-------------- next part --------------
From e63fadcd1d29e62c86fc8e8ae729caf68de08aba Mon Sep 17 00:00:00 2001
From: Alexander Monakov <amonakov at ispras.ru>
Date: Fri, 3 May 2013 21:03:27 +0400
Subject: [PATCH] Implement interposing of dlopen on Android

Consolidate all implementations of unredirected dlopen in one place.

Use unredirected dlopen is glproc_egl.cpp as done in glproc_gl.cpp.

Check that tracing is enabled before redirecting dlopen.
---
 dispatch/glproc_egl.cpp  | 10 ++++----
 dispatch/glproc_gl.cpp   | 22 +----------------
 dispatch/real-dlopen.hpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++
 wrappers/egltrace.py     | 31 ++----------------------
 4 files changed, 69 insertions(+), 56 deletions(-)
 create mode 100644 dispatch/real-dlopen.hpp

diff --git a/dispatch/glproc_egl.cpp b/dispatch/glproc_egl.cpp
index 5f93b14..3d80373 100644
--- a/dispatch/glproc_egl.cpp
+++ b/dispatch/glproc_egl.cpp
@@ -28,10 +28,8 @@
 
 
 #if !defined(_WIN32)
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE // for dladdr
-#endif
 #include <dlfcn.h>
+#include "real-dlopen.hpp"
 #endif
 
 
@@ -82,7 +80,7 @@ _getPublicProcAddress(const char *procName)
     if (procName[0] == 'e' && procName[1] == 'g' && procName[2] == 'l') {
         static void *libEGL = NULL;
         if (!libEGL) {
-            libEGL = dlopen("libEGL.so", RTLD_LOCAL | RTLD_LAZY);
+            libEGL = _dlopen("libEGL.so", RTLD_LOCAL | RTLD_LAZY);
             if (!libEGL) {
                 return NULL;
             }
@@ -96,7 +94,7 @@ _getPublicProcAddress(const char *procName)
 
         static void *libGLESv2 = NULL;
         if (!libGLESv2) {
-            libGLESv2 = dlopen("libGLESv2.so", RTLD_LOCAL | RTLD_LAZY);
+            libGLESv2 = _dlopen("libGLESv2.so", RTLD_LOCAL | RTLD_LAZY);
         }
         if (libGLESv2) {
             sym = dlsym(libGLESv2, procName);
@@ -107,7 +105,7 @@ _getPublicProcAddress(const char *procName)
 
         static void *libGLESv1 = NULL;
         if (!libGLESv1) {
-            libGLESv1 = dlopen("libGLESv1_CM.so", RTLD_LOCAL | RTLD_LAZY);
+            libGLESv1 = _dlopen("libGLESv1_CM.so", RTLD_LOCAL | RTLD_LAZY);
         }
         if (libGLESv1) {
             sym = dlsym(libGLESv1, procName);
diff --git a/dispatch/glproc_gl.cpp b/dispatch/glproc_gl.cpp
index 8e1216f..292ee3c 100644
--- a/dispatch/glproc_gl.cpp
+++ b/dispatch/glproc_gl.cpp
@@ -30,6 +30,7 @@
 #if !defined(_WIN32)
 #include <unistd.h> // for symlink
 #include <dlfcn.h>
+#include "real-dlopen.hpp"
 #endif
 
 
@@ -146,27 +147,6 @@ _getPrivateProcAddress(const char *procName)
 
 
 /*
- * 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);
-}
-
-
-/*
  * Lookup a libGL symbol
  */
 void * _libgl_sym(const char *symbol)
diff --git a/dispatch/real-dlopen.hpp b/dispatch/real-dlopen.hpp
new file mode 100644
index 0000000..853f497
--- /dev/null
+++ b/dispatch/real-dlopen.hpp
@@ -0,0 +1,62 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Provides access to real dlopen, as tracing libraries interpose it.
+ */
+
+#ifndef _REAL_DLOPEN_HPP_
+#define _REAL_DLOPEN_HPP_
+
+#include "os.hpp"
+
+/*
+ * Invoke the true dlopen() function.
+ */
+static void *_dlopen(const char *filename, int flag)
+{
+    typedef void * (*PFN_DLOPEN)(const char *, int);
+    static PFN_DLOPEN dlopen_ptr = NULL;
+
+    if (!dlopen_ptr) {
+#ifdef ANDROID
+        /* Android does not have dlopen in libdl.so; instead, the
+         * implementation is available in the dynamic linker itself.
+         * Oddly enough, we still can interpose it, but need to use
+         * RTLD_DEFAULT to get pointer to the original function.  */
+        dlopen_ptr = (PFN_DLOPEN)dlsym(RTLD_DEFAULT, "dlopen");
+#else
+        dlopen_ptr = (PFN_DLOPEN)dlsym(RTLD_NEXT, "dlopen");
+#endif
+        if (!dlopen_ptr) {
+            os::log("apitrace: error: failed to look up real dlopen\n");
+            return NULL;
+        }
+    }
+
+    return dlopen_ptr(filename, flag);
+}
+
+#endif /* _REAL_DLOPEN_HPP_ */
diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py
index 0c7ebb6..36587b7 100644
--- a/wrappers/egltrace.py
+++ b/wrappers/egltrace.py
@@ -113,6 +113,7 @@ if __name__ == '__main__':
     print '#include <stdlib.h>'
     print '#include <string.h>'
     print '#include <dlfcn.h>'
+    print '#include "real-dlopen.hpp"'
     print
     print '#include "trace_writer_local.hpp"'
     print
@@ -137,31 +138,6 @@ if __name__ == '__main__':
     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 * (*PFN_DLOPEN)(const char *, int);
-    static PFN_DLOPEN dlopen_ptr = NULL;
-
-    if (!dlopen_ptr) {
-        dlopen_ptr = (PFN_DLOPEN)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
@@ -174,7 +150,7 @@ void * dlopen(const char *filename, int flag)
 {
     bool intercept = false;
 
-    if (filename) {
+    if (filename && trace::isTracingEnabled()) {
         intercept =
             strcmp(filename, "libEGL.so") == 0 ||
             strcmp(filename, "libEGL.so.1") == 0 ||
@@ -216,9 +192,6 @@ void * dlopen(const char *filename, int flag)
 }
 
 
-#endif /* !ANDROID */
-
-
 #if defined(ANDROID)
 
 /*
-- 
1.8.2.1


More information about the apitrace mailing list