[PATCH] glibc malloc hooks for gwmem-check

Alexander Malysh <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi together,

please find attached patch that adds support for glibc malloc hooks and so
make it possible to debug memory problems in external libraries.

Comments?

-- 
Thanks,
Alex
gwmem-check-glibc-hook.patch (text/x-diff, 6.5 KB)
Index: gwlib/thread.h
===================================================================
RCS file: /home/cvs/gateway/gwlib/thread.h,v
retrieving revision 1.23
diff -a -u -p -r1.23 thread.h
--- gwlib/thread.h	22 Jan 2004 14:08:25 -0000	1.23
+++ gwlib/thread.h	2 Feb 2005 17:04:02 -0000
@@ -85,6 +85,25 @@ typedef struct {
 #endif
 } Mutex;
 
+#ifdef MUTEX_STATS
+#define GW_MUTEX_INITIALIZER            \
+{                                       \
+    .mutex = PTHREAD_MUTEX_INITIALIZER, \
+    .owner = -1,                        \
+    .dynamic = 0,                       \
+    .filename = __FILE__,               \
+    .lineno = __LINE__,                 \
+    .locks = 0,                         \
+    .collisions = 0,                    \
+}
+#else
+#define GW_MUTEX_INITIALIZER            \
+{                                       \
+    .mutex = PTHREAD_MUTEX_INITIALIZER, \
+    .owner = -1,                        \
+    .dynamic = 0,                       \
+}
+#endif
 
 /*
  * Create a Mutex.
Index: gwlib/gwmem-check.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/gwmem-check.c,v
retrieving revision 1.27
diff -a -u -p -r1.27 gwmem-check.c
--- gwlib/gwmem-check.c	21 Jan 2005 13:50:46 -0000	1.27
+++ gwlib/gwmem-check.c	2 Feb 2005 17:04:02 -0000
@@ -131,7 +131,7 @@ static int slow = 0;
 /* We have to use a static mutex here, because otherwise the mutex_create
  * call would try to allocate memory with gw_malloc before we're
  * initialized. */
-static Mutex gwmem_lock;
+static Mutex gwmem_lock = GW_MUTEX_INITIALIZER;
 
 struct location
 {
@@ -192,6 +192,76 @@ static long highest_total_size;
 /* Current sum of allocated areas */
 static long total_size;
 
+
+/* glibc malloc debugging */
+#ifdef __GLIBC__
+#include <malloc.h>
+static void *gw_check_malloc_hook(size_t, const void*);
+static void gw_check_free_hook(void*, const void*);
+static void *gw_check_realloc_hook(void*, size_t, const void*);
+static void switch_to_gw_hook(void);
+static void init_gw_hook(void);
+
+static void *(*old_malloc_hook)(size_t, const void*);
+static void (*old_free_hook)(void*, const void*);
+static void *(*old_realloc_hook)(void*, size_t, const void*);
+
+void (*__malloc_initialize_hook)(void) = init_gw_hook;
+
+static pthread_mutex_t hook_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void init_gw_hook(void)
+{
+    gw_check_init_mem(1);
+    old_malloc_hook = __malloc_hook;
+    __malloc_hook = gw_check_malloc_hook;
+    old_free_hook = __free_hook;
+    __free_hook = gw_check_free_hook;
+    old_realloc_hook = __realloc_hook;
+    __realloc_hook = gw_check_realloc_hook;
+}
+
+static void switch_to_gw_hook(void)
+{
+    old_malloc_hook = __malloc_hook;
+    __malloc_hook = gw_check_malloc_hook;
+    old_free_hook = __free_hook;
+    __free_hook = gw_check_free_hook;
+    old_realloc_hook = __realloc_hook;
+    __realloc_hook = gw_check_realloc_hook;
+    pthread_mutex_unlock(&hook_lock);
+}
+
+static void switch_to_glibc_hook(void)
+{
+    pthread_mutex_lock(&hook_lock);
+    /* restore old hoocks */
+    __malloc_hook = old_malloc_hook;
+    __free_hook = old_free_hook;
+    __realloc_hook = old_realloc_hook;
+}
+
+
+static void *gw_check_malloc_hook(size_t size, const void *caller)
+{
+    return gw_check_malloc(size, "?", 0, "?");
+}
+
+static void gw_check_free_hook(void *p, const void *caller)
+{
+    gw_check_free(p, "?", 0, "?");
+}
+
+static void *gw_check_realloc_hook(void *ptr, size_t size, const void *caller)
+{
+    return gw_check_realloc(ptr, size, "?", 0, "?");
+}
+#else
+#define switch_to_glibc_hook() do{}while(0)
+#define switch_to_gw_hook() do{}while(0)
+#endif /* __GLIBC__ */
+
+
 /* Static functions */
 
 static inline void lock(void)
@@ -341,7 +411,10 @@ static void dump_area(struct area *area)
 #if HAVE_BACKTRACE
     {
         size_t i;
-        char **strings = backtrace_symbols(area->frames, area->frame_size);
+        char **strings;
+        switch_to_glibc_hook();
+        strings = backtrace_symbols(area->frames, area->frame_size);
+        switch_to_gw_hook();
         debug("gwlib.gwmem", 0, "Backtrace of last malloc/realloc:");
         for (i = 0; i < area->frame_size; i++) {
             if (strings != NULL)
@@ -349,7 +422,9 @@ static void dump_area(struct area *area)
             else
                 debug("gwlib.gwmem", 0, "%p", area->frames[i]);
         }
+        switch_to_glibc_hook();
         free(strings);
+        switch_to_gw_hook();
     }
 #endif
 }
@@ -415,7 +490,7 @@ static void change_total_size(long chang
 }
 
 static struct area *record_allocation(unsigned char *p, size_t size,
-                                                  const char *filename, long lineno, const char *function)
+                                      const char *filename, long lineno, const char *function)
 {
     struct area *area;
     static struct area empty_area;
@@ -433,7 +508,9 @@ static struct area *record_allocation(un
     area->allocator.lineno = lineno;
     area->allocator.function = function;
 #if HAVE_BACKTRACE
+    switch_to_glibc_hook();
     area->frame_size = backtrace(area->frames, sizeof(area->frames) / sizeof(void*));
+    switch_to_gw_hook();
 #endif
 
     startmark(area->area, num_allocations);
@@ -468,7 +545,9 @@ static void drop_from_free_ring(long ind
         error(0, "Freed area %p has been tampered with.", area->area);
         dump_area(area);
     }
+    switch_to_glibc_hook();
     free((unsigned char *)area->area - MARKER_SIZE);
+    switch_to_gw_hook();
 }
 
 static void put_on_free_ring(struct area *area)
@@ -499,15 +578,12 @@ static void free_area(struct area *area)
 
 void gw_check_init_mem(int slow_flag)
 {
-    mutex_init_static(&gwmem_lock);
     slow = slow_flag;
     initialized = 1;
 }
 
 void gw_check_shutdown(void)
 {
-    mutex_destroy(&gwmem_lock);
-    initialized = 0;
 }
 
 void *gw_check_malloc(size_t size, const char *filename, long lineno,
@@ -520,7 +596,9 @@ void *gw_check_malloc(size_t size, const
     /* ANSI C89 says malloc(0) is implementation-defined.  Avoid it. */
     gw_assert(size > 0);
 
+    switch_to_glibc_hook();
     p = malloc(size + 2 * MARKER_SIZE);
+    switch_to_gw_hook();
     if (p == NULL)
         panic(errno, "Memory allocation of %d bytes failed.", size);
     p += MARKER_SIZE;
@@ -567,7 +645,9 @@ void *gw_check_realloc(void *p, size_t s
         unsigned char *new_p;
 
         new_size = round_pow2(size + 2 * MARKER_SIZE);
+        switch_to_glibc_hook();
         new_p = malloc(new_size);
+        switch_to_gw_hook();
         new_size -= 2 * MARKER_SIZE;
         new_p += MARKER_SIZE;
         memcpy(new_p, p, area->area_size);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.