From adc2d256eb980e3c105e73d0afd58fcc19df2356 Mon Sep 17 00:00:00 2001
From: Tiago Vignatti <tiago.vignatti@nokia.com>
Date: Mon, 8 Mar 2010 12:35:52 -0300
Subject: [PATCH] dix: add memory allocation wrapping functions for profiling

We are using ld's --wrap scheme.

To put this in action, you should define compiler flags like
"-Wl,--wrap,malloc -Wl,--wrap,realloc -Wl,--wrap,free" in configuration time.

Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
---
There're other ways to bypass malloc/free (using __malloc_hook, dynamic
linker's LD_PRELOAD mechanism, etc), but I found this the most convenient and
easy to deal. I'm sure one would suggest something else...

I faced a weird and nasty bug that doesn't let me to use ErrorF to print,
segfaulting in some memcpy() function. So I had to almost copy and paste
xorg_backtrace() here and use fprint instead. Sigh.

 dix/dixutils.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dix.h  |    5 ++++
 2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/dix/dixutils.c b/dix/dixutils.c
index 8278d44..49332df 100644
--- a/dix/dixutils.c
+++ b/dix/dixutils.c
@@ -882,3 +882,68 @@ InitCallbackManager(void)
     numCallbackListsToCleanup = 0;
     listsToCleanup = NULL;
 }
+
+/*
+ * Memory allocation wrapping functions using ld's --wrap scheme.
+ *
+ * To put this in action, you should define CFLAGS="-Wl,--wrap,malloc
+ * -Wl,--wrap,realloc -Wl,--wrap,free" in autoconf time.
+ */
+#include <execinfo.h>
+#include <dlfcn.h>
+
+void *__real_malloc(size_t size);
+void *__real_realloc(void *ptr, size_t size);
+void __real_free(void *ptr);
+
+static
+void print_bt(void)
+{
+    void *array[64];
+    const char *mod;
+    int size, i;
+    Dl_info info;
+    size = backtrace(array, 64);
+    for (i = 0; i < size; i++) {
+        dladdr(array[i], &info);
+        mod = (info.dli_fname && *info.dli_fname) ? info.dli_fname : "(vdso)";
+
+        /* try to cut off unuseful info */
+        if (info.dli_saddr && !strstr(info.dli_sname, "__libc_") &&
+            !strstr(info.dli_sname, "__wrap_malloc") &&
+            !strstr(info.dli_sname, "__wrap_free"))
+            fprintf(stderr, "%d: %s (%s+0x%lx) [%p]\n", i, mod,
+                info.dli_sname, (long unsigned int)((char *) array[i] -
+                (char *) info.dli_saddr), array[i]);
+    }
+    fprintf(stderr, "\n");
+
+}
+
+void *__wrap_malloc(size_t size)
+{
+    void *ptr = __real_malloc(size);
+    fprintf(stderr, "malloc(%d) = %p\n", size, ptr);
+    print_bt();
+
+    return ptr;
+}
+
+void *__wrap_realloc(void *ptr, size_t size)
+{
+    void *_ptr = __real_realloc(ptr, size);
+    fprintf(stderr, "realloc(%d) = %p\n", size, _ptr);
+    print_bt();
+
+    return _ptr;
+}
+
+
+/* the wrapper for free() */
+void __wrap_free(void *ptr)
+{
+    fprintf(stderr, "free(%p)\n", ptr);
+    print_bt();
+
+    __real_free(ptr);
+}
diff --git a/include/dix.h b/include/dix.h
index 6505fd0..7052307 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -622,4 +622,9 @@ extern _X_EXPORT ClientPtr LookupClient(
     XID id,
     ClientPtr client);
 
+/* memory allocation wrapping functions */
+extern void *__wrap_malloc(size_t size);
+extern void *__wrap_realloc(void *ptr, size_t size);
+extern void __wrap_free(void *ptr);
+
 #endif /* DIX_H */
-- 
1.6.3.3

