Hallo together,

attached you can find a patch that adds backtrace support to gwmem-check.
w/o backtrace is this module really hard to use.

Comments and votes please!

-- 
Thanks,
Alex
Index: gwlib/gwmem-check.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/gwmem-check.c,v
retrieving revision 1.26
diff -a -u -p -r1.26 gwmem-check.c
--- gwlib/gwmem-check.c	22 Jan 2004 14:08:25 -0000	1.26
+++ gwlib/gwmem-check.c	20 Jan 2005 13:56:45 -0000
@@ -85,12 +85,17 @@
  * after it's been freed.
  * 
  * Richard Braakman
+ * Alexander Malysh (added backtrace support)
  */
 
+#include "gw-config.h"
 
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
+#if HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
 
 #include "gwlib.h"
 
@@ -146,6 +151,10 @@ struct area
     struct location allocator;     /* Caller that alloced area */
     struct location reallocator;   /* Caller that last realloced area */
     struct location claimer;       /* Owner of area, set by caller */
+#if HAVE_BACKTRACE
+    void *frames[10]; /* 10 callers should be sufficient */
+    size_t frame_size;
+#endif
 };
 
 /* Number of bytes to reserve on either side of each allocated area,
@@ -153,7 +162,8 @@ struct area
  * enough to hold a long. */
 #define MARKER_SIZE 16
 
-#define MAX_TAB_SIZE (1024*1024L)
+/* 100 MB */
+#define MAX_TAB_SIZE (100*1024*1024L)
 #define MAX_ALLOCATIONS ((long) (MAX_TAB_SIZE/sizeof(struct area)))
 
 /* Freed areas are thrown into the free ring.  They are not released
@@ -184,12 +194,12 @@ static long total_size;
 
 /* Static functions */
 
-static void lock(void)
+static inline void lock(void)
 {
     mutex_lock(&gwmem_lock);
 }
 
-static void unlock(void)
+static inline void unlock(void)
 {
     mutex_unlock(&gwmem_lock);
 }
@@ -241,7 +251,7 @@ static int untouched(unsigned char *p, s
 }
 
 /* Fill the end marker for this area */
-static void endmark(unsigned char *p, size_t size)
+static inline void endmark(unsigned char *p, size_t size)
 {
     fill(p + size, MARKER_SIZE, END_MARK_PATTERN);
 }
@@ -320,7 +330,7 @@ static void dump_area(struct area *area)
         unsigned char *p;
         char buf[MAX_DUMP * 3 + 1];
 
-    	p = area->area;
+        p = area->area;
         buf[0] = '\0';
         for (i = 0; i < area->area_size && i < MAX_DUMP; ++i)
             sprintf(strchr(buf, '\0'), "%02x ", p[i]);
@@ -328,6 +338,20 @@ static void dump_area(struct area *area)
         debug("gwlib.gwmem", 0, "Contents of area (first %d bytes):", MAX_DUMP);
         debug("gwlib.gwmem", 0, "  %s", buf);
     }
+#if HAVE_BACKTRACE
+    {
+        size_t i;
+        char **strings = backtrace_symbols(area->frames, area->frame_size);
+        debug("gwlib.gwmem", 0, "Backtrace of last malloc/realloc:");
+        for (i = 0; i < area->frame_size; i++) {
+            if (strings != NULL)
+                debug("gwlib.gwmem", 0, "%s", strings[i]);
+            else
+                debug("gwlib.gwmem", 0, "%p", area->frames[i]);
+        }
+        free(strings);
+    }
+#endif
 }
 
 static struct area *find_area(unsigned char *p)
@@ -408,6 +432,9 @@ static struct area *record_allocation(un
     area->allocator.filename = filename;
     area->allocator.lineno = lineno;
     area->allocator.function = function;
+#if HAVE_BACKTRACE
+    area->frame_size = backtrace(area->frames, sizeof(area->frames) / sizeof(void*));
+#endif
 
     startmark(area->area, num_allocations);
     endmark(area->area, area->area_size);

Reply via email to