diff -Naur -X leaktracer.dontdiff leaktracer.orig/leak-analyze leaktracer.all/leak-analyze
--- leaktracer.orig/leak-analyze	2003-11-18 05:42:21.000000000 -0800
+++ leaktracer.all/leak-analyze	2005-08-10 16:07:25.000000000 -0700
@@ -6,54 +6,231 @@
 # This program is Public Domain
 use IO::Handle;
 
-die "You must supply at least one argument.\n" unless $#ARGV >= 0;
-
-$ExeFile = shift @ARGV;
-$LeaksFile = $#ARGV >= 0 ? shift @ARGV : "leak.out";
-open (LEAKS, $LeaksFile) or die "Could not open leaks data file $LeaksFile: $!";
-
-if ($#ARGV >= 0) {
-    $BreakOn = shift @ARGV;
-    # Rest in @ARGV are program arguments
-}
-
-$n = $u = 0;
-while (<LEAKS>) {
-    chop;
-    next if (m/^\s*#/);
-    #             1       2          3       4          5      6            7
-    #if (/^\s*L\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)\s+(\d+)/) {
-    # Allocations, which have not been freed or deallocations which have not
-    # been allocated.
-    #              1      2           3
-    if (/^\s*L\s+(0x)?([0-9a-f]+)\s+(\d+)/) {
-        $addr="$2";  # ",$4,$6";
-        $u++ if not exists $Type{$addr};
-        $Count{$addr}++;
-	$Size{$addr} += $3; # $7;
-	$Type{$addr} = "Leak";
-        $n++;
-    }
-    elsif (/^\s*D\s+(0x)?([0-9a-f]+)/) {
-        $addr="$2";  # ",$4,$6";
-        $u++ if not exists $Type{$addr};
-        $Count{$addr}++;
-	$Type{$addr} = "delete on not allocated memory";
-        $n++;
-    }
-    # allocations/deallocations with other errornous conditions
-    #              1      2        3         4        5
-    elsif (/^\s*([SO])\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)/) {
-	$addrs = "$3,$5,$1";
-	$AllocDealloc{$addrs} = ("$1" =~ m/S/) 
-	    ? "Different allocation schemes" 
-	    : "This Memory was overwritten";
-    }
+$DEFAULT_STACK_DEPTH = 1;
+$DEFAULT_LIST_SIZE = 2;
+$DEFAULT_GDB_COMPLAINTS = 0;
+$DEFAULT_THRESHOLD = 0;
+
+
+sub usage()
+	{
+	print STDERR << "EOF";
+
+usage: $0 [options] binary [leaksfile] [program args]
+
+where:
+  binary          : binary you are debugging
+  leaksfile       : leak.out file generated by running binary with LeakCheck
+  program args    : program arguments for the binary
+  options
+    -s            : order output by size [default NOT]
+    -f depth      : frame depth [default $DEFAULT_STACK_DEPTH]
+    -l listsize   : number of lines shown per frame [default $DEFAULT_LIST_SIZE]
+    -c complaints : gdb complaints [default $DEFAULT_GDB_COMPLAINTS]
+    -d altLF      : diff to alternative leaksfile [default NOT]
+    -t threshold  : only report leaks > threshold [default $DEFAULT_THRESHOLD]
+    -D            : debug mode [default NOT]
+    -h            : this usage
+
+  example: $0 -s -d 3 -D
+
+EOF
+  exit;
+	}
+
+
+# default options
+$order = "none";
+$debug = 0;
+if ( exists $ENV{LEAKTRACE_DEPTH} ) {
+	$stack_depth = $ENV{LEAKTRACE_DEPTH};
+} else {
+	$stack_depth = $DEFAULT_STACK_DEPTH;
 }
+$list_size = $DEFAULT_LIST_SIZE;
+$complaints = $DEFAULT_GDB_COMPLAINTS;
+$diff_leaksfile = "";
+$threshold = $DEFAULT_THRESHOLD;
+$LeaksFile = "leak.out";
+$ExeFile = "";
+$BreakOn = "";
+
+
+# command-line options processing
+sub init()
+	{
+	use Getopt::Std;
+	my $opt_string = 'sf:l:c:d:t:Dh';
+	getopts( "$opt_string", \%opt ) or usage();
+	usage() if $opt{h};
+
+	$order = "size" if $opt{s};
+	$stack_depth = $opt{f} if $opt{f};
+	$list_size = $opt{l} if $opt{l};
+	$complaints = $opt{c} if $opt{c};
+	$diff_leaksfile = $opt{d} if $opt{d};
+	$threshold = $opt{t} if $opt{t};
+	$debug = 1 if $opt{D};
+
+
+	$ExeFile = shift @ARGV or die "Need a valid binary file (try -h for help)";
+	$LeaksFile = $#ARGV >= 0 ? shift @ARGV : "leak.out";
+	# Rest in @ARGV are program arguments
+	if ($#ARGV >= 0) {
+		$BreakOn = shift @ARGV;
+	}
+
+	if ( $debug == 1 )
+		{
+		if ( $order == "size" )
+			{
+			print STDERR "ordering: size\n";
+			}
+		print STDERR "stack_depth is $stack_depth\n";
+		print STDERR "list_size is $list_size\n";
+		print STDERR "complaints is $complaints\n";
+		if (defined($diff_leaksfile) and ($diff_leaksfile ne ""))
+			{
+			print STDERR "diff leaksfile to $diff_leaksfile\n";
+			}
+		print STDERR "threshold is $threshold\n";
+		print STDERR "binary is $ExeFile\n";
+		print STDERR "leaksfile is $LeaksFile\n";
+		}
+	}
+
+
+sub read_leaksfile 
+	{
+	my ($LeaksFiler, $nr, $ur, $Countr, $Sizer, $Typer, $AllocDeallocr) = @_;
+
+	open (LEAKS, $$LeaksFiler) or die "Could not open leaks data file $$LeaksFiler: $!";
+
+	$$nr = $$ur = 0;
+	while (<LEAKS>)
+		{
+		chop;
+		next if (m/^\s*#/);
+		#             1       2          3       4          5      6            7
+		#if (/^\s*L\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)\s+(\d+)/) {}
+		# Allocations, which have not been freed or deallocations which have not
+		# been allocated.
+		#              1      2           3
+		if (/^\s*L\s+(0x)?([0-9a-f]+)\s+(\d+)/)
+			{
+			$addrs="$2";  # ",$4,$6";
+			$tmp_size = $3; # $7;
+			$naddr = 0;
+			while (<LEAKS>)
+				{
+				if (/^\s*l\s+(0x)?([0-9a-f]+)\s+(\d+)/)
+					{
+					if ( ++$naddr >= $stack_depth )
+						{
+						last;
+						}
+					$addrs = "$addrs,$2";  # ",$4,$6";
+					}
+				else
+					{
+					last;
+					}
+				}
+			$$ur++ if not exists $$Typer{$addrs};
+			$$Countr{$addrs}++;
+
+			$$Sizer{$addrs} += $tmp_size;
+			$$Typer{$addrs} = "Leak";
+			$n++;
+			}
+		elsif (/^\s*D\s+(0x)?([0-9a-f]+)/)
+			{
+			$addrs="$2";  # ",$4,$6";
+			$naddr = 0;
+			while (<LEAKS>)
+				{
+				if (/^\s*d\s+(0x)?([0-9a-f]+)/)
+					{
+					if ( ++$naddr >= $stack_depth )
+						{
+						last;
+						}
+					$addrs = "$addrs,$2";  # ",$4,$6";
+					}
+				else
+					{
+					last;
+					}
+				}
+			$$ur++ if not exists $$Typer{$addrs};
+			$$Countr{$addrs}++;
+			$$Typer{$addrs} = "delete on not allocated memory";
+			$$n++;
+			}
+		# allocations/deallocations with other erroneous conditions
+		#              1      2        3         4        5
+		elsif (/^\s*([SO])\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)/)
+			{
+			$addrs = "$3,$5";
+			$tmp_type = $1;
+			$naddr = 0;
+			while (<LEAKS>)
+				{
+				if (/^\s*([so])\s+(0x)?([0-9a-f]+)\s+(0x)?([0-9a-f]+)/)
+					{
+					if ( ++$naddr >= $stack_depth )
+						{
+						last;
+						}
+					$addrs = "$addrs,$3,$5";
+					}
+				else
+					{
+				last;
+					}
+				}
+			$addrs = "$addrs,$tmp_type";
+			$$AllocDeallocr{$addrs} = ("$tmp_type" =~ m/S/)
+					? "Different allocation schemes" 
+					: "This Memory was overwritten";
+		}
+	}
+
+	close (LEAKS);
+	}
+
+
+
+
+init();
+
+read_leaksfile (\$LeaksFile, \$n, \$u, \%Count, \%Size, \%Type, \%AllocDealloc);
+
+print STDERR "Gathered $n ($u unique) points of data on $LeaksFile.\n";
+
+
+if (defined($diff_leaksfile) and ($diff_leaksfile ne ""))
+	{
+	read_leaksfile (\$diff_leaksfile, \$n2, \$u2, \%Count2, \%Size2, \%Type2, \%AllocDealloc2);
+
+	# delete all common leaks with same size
+	@keys = sort keys %Type2;
+	foreach (@keys)
+		{
+		$addrs = $_;
+		if ( (exists $Type{$addrs}) and ($Size{$addrs} == $Size2{$addrs}) )
+			{
+			delete ($Type{$addrs});
+			delete ($Count{$addrs});
+			delete ($Size{$addrs});
+			}
+		}
+	}
+
+
+
 
-print STDERR "Gathered $n ($u unique) points of data.\n";
 
-close (LEAKS);
 
 
 # Instead of using -batch, we just run things as usual. with -batch,
@@ -61,34 +238,65 @@
 open (PIPE, "|gdb -q  $ExeFile") or die "Cannot start gdb";
 #open (PIPE, "|cat");
 
-# Change set listsize 2 to something else to show more lines
-print PIPE "set prompt\nset complaints 1000\nset height 0\n";
+
+print PIPE "set prompt\nset complaints $complaints\nset height 0\n";
 
 # Optionally, run the program
-if (defined($BreakOn)) {
+if (defined($BreakOn) and ($BreakOn ne "")) {
     print PIPE "break $BreakOn\n";
     print PIPE "run ", join(" ", @ARGV), " \n";
 }
 
 
-print PIPE "set listsize 2\n";
+print PIPE "set listsize $list_size\n";
 foreach (sort keys %AllocDealloc) {
     print PIPE "echo \\n#-- Alloc: $AllocDealloc{$_}\\nalloc here :\n";
     @addrs = split(/,/,$_);
-    print PIPE "l *0x" . (shift @addrs) . "\necho ..free here :\n";
+    while () {
+        $the_addr = (shift @addrs);
+        if ( ($the_addr =~ /S/) || ($the_addr =~ /O/) ) {
+            push @free, $the_addr;
+            last;
+        }
+        print PIPE "l *0x" . $the_addr . "\n";
+        print PIPE "set listsize 1\n";
+        push @free, (shift @addrs);
+    }
+    print PIPE "echo ..free here :\n";
     print PIPE "set listsize 1\n";
-    print PIPE "l *0x" . (shift @addrs) . "\n";
+    while (1) {
+        $the_addr = (shift @free);
+        if ( ($the_addr =~ /S/) || ($the_addr =~ /O/) ) {
+            last;
+        }
+        print PIPE "l *0x" . $the_addr . "\n";
+        print PIPE "set listsize 1\n";
+    }
 }
 
-foreach (sort keys %Type) {
-    print PIPE "echo \\n#-- $Type{$_}: counted $Count{$_}x";
+if ( $order eq "size" ) {
+	@keys = sort { $Size{$b} <=> $Size{$a} } keys %Type
+} else {
+	@keys = sort keys %Type;
+}
+foreach (@keys) {
+    if ($Size{$_} < $threshold) {
+        next;
+    }
+    print PIPE "echo \\n#-- $Type{$_} at 0x$_: counted $Count{$_}x";
     if ($Size{$_} > 0) {
-	print PIPE " / total Size: $Size{$_}";
+        print PIPE " / total Size: $Size{$_}";
     }
+
     print PIPE "\\n\n";
     @addrs = split(/,/,$_);
-    print PIPE "set listsize 2\n";
+    print PIPE "set listsize $list_size\n";
     print PIPE "l *0x" . (shift @addrs) . "\n";
+    while ($#addrs >= 0) {
+        $the_address = (shift @addrs);
+        print PIPE "l *0x" . $the_address . "\n";
+        print PIPE "set listsize 1\n";
+    }
     #print PIPE "echo ..called from :\n";
     #print PIPE "set listsize 1\n";
     # gdb bails out, if it cannot find an address.
@@ -96,7 +304,7 @@
     #print PIPE "l *0x" . (shift @addrs) . "\n";
 }
 
-if (defined($BreakOn)) {
+if (defined($BreakOn) and ($BreakOn ne "")) {
     print PIPE "kill\n";
 }
 
diff -Naur -X leaktracer.dontdiff leaktracer.orig/LeakTracer.cc leaktracer.all/LeakTracer.cc
--- leaktracer.orig/LeakTracer.cc	2003-11-18 05:42:21.000000000 -0800
+++ leaktracer.all/LeakTracer.cc	2005-08-09 21:49:09.000000000 -0700
@@ -8,6 +8,14 @@
  * This program is Public Domain
  */
 
+#define TRACE_MALLOC 			// enable tracing of malloc/free/calloc/realloc
+#define TRACE_FREE
+#define TRACE_CALLOC
+#define TRACE_REALLOC
+
+//#define TRACE(arg) fprintf arg
+#define TRACE(arg)
+
 #ifdef THREAD_SAVE
 #define _THREAD_SAVE
 #include <pthread.h>
@@ -23,15 +31,25 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <errno.h>
+#include <dlfcn.h>
+#include <assert.h>
 
+/**
+ * dynamic call interfaces to memory allocation functions in libc.so
+ */
+static void* (*lt_malloc)(size_t size);
+static void  (*lt_free)(void* ptr);
+static void* (*lt_realloc)(void *ptr, size_t size);
+static void* (*lt_calloc)(size_t nmemb, size_t size);
 
 /*
  * underlying allocation, de-allocation used within 
  * this tool
  */
-#define LT_MALLOC  malloc
-#define LT_FREE    free
-#define LT_REALLOC realloc
+#define LT_MALLOC  (*lt_malloc)
+#define LT_FREE    (*lt_free)
+#define LT_REALLOC (*lt_realloc)
+#define LT_CALLOC  (*lt_calloc)
 
 /*
  * prime number for the address lookup hash table.
@@ -57,7 +75,11 @@
  *   <ftp://ftp.perens.com/pub/ElectricFence/>
  */
 #define MAGIC "\xAA\xBB\xCC\xDD"
+#ifdef MAGIC
 #define MAGIC_SIZE (sizeof(MAGIC)-1)
+#else
+#define MAGIC_SIZE 0
+#endif
 
 /**
  * on 'new', initialize the memory with this value.
@@ -86,13 +108,49 @@
  */
 #define INITIALSIZE 32768
 
+
+/**
+ * Defines for writing diachronic leak reports (without exiting)
+ */
+#define WRITE_LEAK_REPORT 0xffffffff
+#define TEMPORAL_LEAK_REPORT "/tmp/leaktracer.tmpdump"
+#define SWAP(a,b) { FILE* t = a; a = b; b = t; }
+
+
+/**
+ * substitutes for __builtin_frame_address() and __builtin_return_address() 
+ * (they only work with a const parameter)
+ */
+#define GET_EBP(reg) __asm __volatile("mov %%ebp, %%eax": "=a" (reg));
+
+#define GET_FRAME_ADDRESS(level,ebp)     \
+{                                        \
+	GET_EBP(ebp);                          \
+	for ( int _i = 0; _i < level; _i++ ) { \
+		/* dereference %ebp */               \
+		ebp = *((void **)ebp);               \
+	}                                      \
+}
+
+
+#define GET_RETURN_ADDRESS(level,ra)     \
+{                                        \
+	void *_ebp;                            \
+	GET_FRAME_ADDRESS (level, _ebp);       \
+                                         \
+	/* dereference 4(%ebp) */              \
+	ra = *((void **)(((char *)_ebp)+4));   \
+}
+
+
 static class LeakTracer {
+public:
 	struct Leak {
-		const void *addr;
-		size_t      size;
-		const void *allocAddr;
-		bool        type;
-		int         nextBucket;
+		const void  *addr;
+		size_t       size;
+		const void **allocAddr;
+		bool         type;	// true == normal, false == []
+		int          nextBucket;
 	};
 	
 	int  newCount;      // how many memory blocks do we have
@@ -101,16 +159,19 @@
 	int  currentAllocated; // currentAllocatedMemory
 	int  maxAllocated;     // maximum Allocated
 	unsigned long totalAllocations; // total number of allocations. stats.
-	unsigned int  abortOn;  // resons to abort program (see abortReason_t)
+	unsigned int  abortOn;  // reasons to abort program (see abortReason_t)
+	int  stack_depth;  // stack depth recorded (number of callers)
 
+
+public:
 	/**
 	 * Have we been initialized yet?  We depend on this being
 	 * false before constructor has been called!  
 	 */
-	bool initialized;	
+	bool initialized;
 	bool destroyed;		// Has our destructor been called?
 
-
+private:
 	FILE *report;       // filedescriptor to write to
 
 	/**
@@ -136,6 +197,7 @@
 
 public:
 	LeakTracer() {
+		TRACE((stderr,"LeakTracer\n"));
 		initialize();
 	}
 	
@@ -144,8 +206,7 @@
 		if (initialized)
 			return;
 
-		//		fprintf(stderr, "LeakTracer::initialize()\n");
-		initialized = true;
+		TRACE((stderr, "LeakTracer::initialize()\n"));
 		newCount = 0;
 		leaksCount = 0;
 		firstFreeSpot = 1; // index '0' is special
@@ -157,6 +218,49 @@
 		leaks = 0;
 		leakHash = 0;
 
+		if (!lt_calloc)
+		{
+			TRACE((stderr, "initialize: dlsym(lt_calloc)\n"));
+			lt_calloc = (void*(*)(size_t, size_t))dlsym(RTLD_NEXT, "calloc");
+			TRACE((stderr, "initialize: lt_calloc=%p\n", lt_calloc));
+			if (!lt_calloc) {
+				fprintf(stderr, "LeakTracer: could not resolve 'calloc' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+
+		if (!lt_malloc)
+		{
+			lt_malloc = (void*(*)(size_t))dlsym(RTLD_NEXT, "malloc");
+			TRACE((stderr, "initialize: lt_malloc=%p\n", lt_malloc));
+			if (!lt_malloc) {
+				fprintf(stderr, "LeakTracer: could not resolve 'malloc' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+
+		if (!lt_free)
+		{
+			lt_free = (void(*)(void*))dlsym(RTLD_NEXT, "free");
+			TRACE((stderr, "initialize: lt_free=%p\n", lt_free));
+			if (!lt_free) {
+				fprintf(stderr, "LeakTracer: could not resolve 'free' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+
+		if (!lt_realloc)
+		{
+			lt_realloc = (void*(*)(void*,size_t))dlsym(RTLD_NEXT, "realloc");
+			TRACE((stderr, "initialize: lt_realloc=%p\n", lt_realloc));
+			if (!lt_realloc) {
+				fprintf(stderr, "LeakTracer: could not resolve 'realloc' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+
+		// initialize trace file
+		
 		char uniqFilename[256];
 		const char *filename = getenv("LEAKTRACE_FILE") ? : "leak.out";
 		struct stat dummy;
@@ -184,10 +288,19 @@
 				report = stderr;
 			}
 		}
-		
+
+		// get the stack depth
+		stack_depth = 10;  // default value
+		if ( ( getenv("LEAKTRACE_DEPTH") != NULL ) ) {
+			char *endptr;
+			int num = strtol(getenv("LEAKTRACE_DEPTH"), &endptr, 10);
+			if ( endptr == NULL )
+				stack_depth = num;
+		}
+		fprintf(report, "# stack depth of %d levels\n", stack_depth);
+
 		time_t t = time(NULL);
 		fprintf (report, "# starting %s", ctime(&t));
-
 		leakHash = (int*) LT_MALLOC(SOME_PRIME * sizeof(int));
 		memset ((void*) leakHash, 0x00, SOME_PRIME * sizeof(int));
 
@@ -232,13 +345,17 @@
 		fprintf(report, "# not thread save; if you use threads, recompile with -DTHREAD_SAVE\n");
 #endif
 		fflush(report);
+
+		TRACE((stderr, "LeakTracer::initialized\n"));
+		initialized = true;
 	}
 	
 	/*
 	 * the workhorses:
 	 */
-	void *registerAlloc(size_t size, bool type);
-	void  registerFree (void *p, bool type);
+	void *registerAlloc(size_t size, bool type, unsigned caller_stack);
+	void  registerFree (void *p, bool type, unsigned caller_stack);
+	void *registerRealloc (void *p, size_t size, bool type);
 
 	/**
 	 * write a hexdump of the given area.
@@ -251,7 +368,7 @@
 	void progAbort(abortReason_t reason) {
 		if (abortOn & reason) {
 			fprintf(report, "# abort; DUMP of current state\n");
-                        fprintf(stderr, "LeakTracer aborting program\n");
+			fprintf(stderr, "LeakTracer aborting program due to reason %d\n", reason);
 			writeLeakReport();
 			fclose(report);
 			abort();
@@ -266,34 +383,66 @@
 	void writeLeakReport();
 
 	~LeakTracer() {
-	    //		fprintf(stderr, "LeakTracer::destroy()\n");
+		TRACE((stderr, "~LeakTracer\n"));
 		time_t t = time(NULL);
 		fprintf (report, "# finished %s", ctime(&t));
 		writeLeakReport();
 		fclose(report);
-		free(leaks);
+		for (int i = 0; i < leaksCount; i ++)
+			LT_FREE (leaks[i].allocAddr);
+		LT_FREE(leaks);
 #ifdef THREAD_SAVE
 		pthread_mutex_destroy(&mutex);
 #endif
+		TRACE((stderr, "~LeakTracer: destroyed"));
 		destroyed = true;
 	}
 } leakTracer;
 
-void* LeakTracer::registerAlloc (size_t size, bool type) {
-	initialize();
 
-	//	fprintf(stderr, "LeakTracer::registerAlloc()\n");
+
+void* LeakTracer::registerAlloc (size_t size, bool type, unsigned caller_stack) {
+	TRACE((stderr, "LeakTracer::registerAlloc(%d, %d, %d)\n", size, type, caller_stack));
+
+	if ( size == WRITE_LEAK_REPORT ) {
+		/* temporal dump */
+		int tmpfd = open (TEMPORAL_LEAK_REPORT, 
+				O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE);
+		if ( tmpfd < 0 ) {
+			fprintf (stderr, "ERROR opening the temporal dump file (%s)\n", 
+					TEMPORAL_LEAK_REPORT);
+			writeLeakReport();
+			fclose(report);
+			_exit (1);
+		}
+
+		/* swap descriptors */
+		FILE* tmp = fdopen(tmpfd, "w");
+		SWAP(report,tmp);
+
+		/* dump results */
+		time_t t = time(NULL);
+		fprintf (tmp, "# temporal dump finished %s", ctime(&t));
+		writeLeakReport();
+		SWAP(report,tmp);
+		close (tmpfd);
+		return NULL;
+	}
+
+	initialize();
 
 	if (destroyed) {
 		fprintf(stderr, "Oops, registerAlloc called after destruction of LeakTracer (size=%d)\n", size);
 		return LT_MALLOC(size);
 	}
 
-
 	void *p = LT_MALLOC(size + MAGIC_SIZE);
+
 	// Need to call the new-handler
 	if (!p) {
 		fprintf(report, "LeakTracer malloc %m\n");
+		writeLeakReport();
+		fclose(report);
 		_exit (1);
 	}
 
@@ -307,7 +456,7 @@
 	 * the magic value is a special pattern which does not need
 	 * to be uniform.
 	 */
-        memcpy((char*)p+size, MAGIC, MAGIC_SIZE);
+	memcpy((char*)p+size, MAGIC, MAGIC_SIZE);
 #endif
 
 #ifdef THREAD_SAVE
@@ -326,12 +475,28 @@
 				leaks[i].addr = p;
 				leaks[i].size = size;
 				leaks[i].type = type;
-				leaks[i].allocAddr=__builtin_return_address(1);
+				for (int j = 0; j < stack_depth; j++)
+					leaks[i].allocAddr[j] = 0;
+				for (int j = 0; j < stack_depth; j++) {
+					void *addr;
+					if (caller_stack == 1) 
+						GET_FRAME_ADDRESS((j+1),addr)
+					else
+						GET_FRAME_ADDRESS((j+2),addr);
+					if ( addr == NULL )
+						break;
+					if (caller_stack == 1) 
+						GET_RETURN_ADDRESS((j+1),addr)
+					else
+						GET_RETURN_ADDRESS((j+2),addr);
+					leaks[i].allocAddr[j] = addr;
+				}
 				firstFreeSpot = i+1;
 				// allow to lookup our index fast.
 				int *hashPos = &leakHash[ ADDR_HASH(p) ];
 				leaks[i].nextBucket = *hashPos;
 				*hashPos = i;
+				TRACE((stderr, "registerAlloc returning %p\n", p));
 #ifdef THREAD_SAVE
 				pthread_mutex_unlock(&mutex);
 #endif
@@ -346,6 +511,8 @@
 					  sizeof(Leak) * new_leaksCount);
 		if (!leaks) {
 			fprintf(report, "# LeakTracer realloc failed: %m\n");
+			writeLeakReport();
+			fclose(report);
 			_exit(1);
 		}
 		else {
@@ -353,9 +520,14 @@
 				new_leaksCount);
 			fflush(report);
 		}
-		memset(leaks+leaksCount, 0x00,
-		       sizeof(Leak) * (new_leaksCount-leaksCount));
+		memset(leaks+leaksCount, 0x00, sizeof(Leak) * (new_leaksCount-leaksCount));
 		leaksCount = new_leaksCount;
+
+		// allocate space for the number of callers
+		for (int i = 0; i < leaksCount; i++)
+			leaks[i].allocAddr = (const void **) LT_MALLOC (stack_depth *
+					sizeof(const void *));
+		fprintf(report, "# stack depth now %d\n", stack_depth);
 	}
 }
 
@@ -375,89 +547,175 @@
 	fprintf(report, "\n");
 }
 
-void LeakTracer::registerFree (void *p, bool type) {
+void LeakTracer::registerFree (void *p, bool type, unsigned caller_stack) {
+	TRACE((stderr, "LeakTracer::registerFree(%p, %d, %d)\n", p, type, caller_stack));
+
 	initialize();
 
 	if (p == NULL)
 		return;
 
 	if (destroyed) {
-		fprintf(stderr, "Oops, allocation destruction of LeakTracer (p=%p)\n", p);
-		return;
+		fprintf(stderr, "Oops, registerFree called after destruction of LeakTracer (p=%p)\n", p);
+		return LT_FREE(p);
 	}
 
 #ifdef THREAD_SAVE
 	pthread_mutex_lock(&mutex);
 #endif
-	int *lastPointer = &leakHash[ ADDR_HASH(p) ];
-	int i = *lastPointer;
-
-	while (i != 0 && leaks[i].addr != p) {
-		lastPointer = &leaks[i].nextBucket;
-		i = *lastPointer;
-	}
+	if (leaks) {
 
-	if (leaks[i].addr == p) {
-		*lastPointer = leaks[i].nextBucket; // detach.
-		newCount--;
-		leaks[i].addr = NULL;
-		currentAllocated -= leaks[i].size;
-		if (i < firstFreeSpot)
-			firstFreeSpot = i;
-
-		if (leaks[i].type != type) {
-			fprintf(report, 
-				"S %10p %10p  # new%s but delete%s "
-				"; size %d\n",
-				leaks[i].allocAddr,
-				__builtin_return_address(1),
-				((!type) ? "[]" : " normal"),
-				((type) ? "[]" : " normal"),
-				leaks[i].size);
-			
-			progAbort( NEW_DELETE_MISMATCH );
+		int *lastPointer = &leakHash[ ADDR_HASH(p) ];
+		int i = *lastPointer;
+		
+		while (i != 0 && leaks[i].addr != p) {
+			lastPointer = &leaks[i].nextBucket;
+			i = *lastPointer;
 		}
+		
+		if (leaks[i].addr == p) {
+			*lastPointer = leaks[i].nextBucket; // detach.
+			newCount--;
+			leaks[i].addr = NULL;
+			currentAllocated -= leaks[i].size;
+			if (i < firstFreeSpot)
+				firstFreeSpot = i;
+			
+			if (leaks[i].type != type) {
+				for (int j = 0; j < stack_depth; j++) {
+					void *addr;
+					if ( leaks[i].allocAddr[j] == 0 )
+						break;
+					if (caller_stack == 1)
+						GET_RETURN_ADDRESS((j+1),addr)
+					else
+						GET_RETURN_ADDRESS((j+2),addr);
+					fprintf(report, 
+							"%c %10p %10p  # new%s but delete%s "
+							"; size %d\n",
+							( j == 0 ) ? 'S' : 's',
+							leaks[i].allocAddr[j],
+							addr,
+							((!type) ? "[]" : " normal"),
+							((type) ? "[]" : " normal"),
+							leaks[i].size);
+				}
+				fprintf(report, "#\n");
+
+				progAbort( NEW_DELETE_MISMATCH );
+			}
 #ifdef MAGIC
-		if (memcmp((char*)p + leaks[i].size, MAGIC, MAGIC_SIZE)) {
-			fprintf(report, "O %10p %10p  "
-				"# memory overwritten beyond allocated"
-				" %d bytes\n",
-				leaks[i].allocAddr,
-				__builtin_return_address(1),
-				leaks[i].size);
-			fprintf(report, "# %d byte beyond area:\n",
-				MAGIC_SIZE);
-			hexdump((unsigned char*)p+leaks[i].size,
-				MAGIC_SIZE);
-			progAbort( OVERWRITE_MEMORY );
-		}
+			if (memcmp((char*)p + leaks[i].size, MAGIC, MAGIC_SIZE)) {
+				for (int j = 0; j < stack_depth; j++) {
+					void *addr;
+					if ( leaks[i].allocAddr[j] == 0 )
+						break;
+					if (caller_stack == 1)
+						GET_RETURN_ADDRESS((j+1),addr)
+					else
+						GET_RETURN_ADDRESS((j+2),addr);
+					fprintf(report, "%c %10p %10p "
+							"# memory overwritten beyond allocated"
+							" %d bytes\n",
+							( j == 0 ) ? 'O' : 'o',
+							leaks[i].allocAddr[j],
+							addr,
+							leaks[i].size);
+					fprintf(report, "# %d byte beyond area:\n",
+						MAGIC_SIZE);
+					hexdump((unsigned char*)p+leaks[i].size,
+						MAGIC_SIZE);
+					progAbort( OVERWRITE_MEMORY );
+				}
+				fprintf(report, "#\n");
+			}
 #endif
-
+			
 #ifdef THREAD_SAVE
 #  ifdef MEMCLEAN
-		int allocationSize = leaks[i].size;
+			int allocationSize = leaks[i].size;
 #  endif
-		pthread_mutex_unlock(&mutex);
+			pthread_mutex_unlock(&mutex);
 #else
-#define             allocationSize leaks[i].size
+#define                 allocationSize leaks[i].size
 #endif
 
 #ifdef MEMCLEAN
-		// set it to some garbage value.
-		memset((unsigned char*)p, MEMCLEAN, allocationSize + MAGIC_SIZE);
+			// set it to some garbage value.
+			memset((unsigned char*)p, MEMCLEAN, allocationSize + MAGIC_SIZE);
 #endif
-		LT_FREE(p);
-		return;
+			return LT_FREE(p);
+		}
 	}
-
 #ifdef THREAD_SAVE
 	pthread_mutex_unlock(&mutex);
 #endif
-	fprintf(report, "D %10p             # delete non alloc or twice pointer %10p\n", 
-		__builtin_return_address(1), p);
+	for (int j = 0; j < stack_depth; j++) {
+		void *addr;
+		if (caller_stack == 1)
+			GET_RETURN_ADDRESS((j+1),addr)
+		else
+			GET_RETURN_ADDRESS((j+2),addr);
+		fprintf(report, 
+				"%c %10p             # delete non alloc or twice pointer %10p\n",
+				( j == 0 ) ? 'D' : 'd',
+				addr,
+				p);
+	}
+	fprintf(report, "#\n");
+
 	progAbort( DELETE_NONEXISTENT );
 }
 
+void* LeakTracer::registerRealloc (void* p, size_t size, bool type) {
+	TRACE((stderr, "LeakTracer::registerRealloc(%p, %d, %d)\n", p, size, type));
+
+	initialize();
+
+	if (destroyed) {
+		fprintf(stderr, "Oops, registerRealloc called after destruction of LeakTracer (size=%d, p=%p)\n", size, p);
+		return LT_REALLOC(p,size);
+	}
+
+	if (!p)
+		return registerAlloc(size, false, 2);
+
+	void* new_p = NULL;
+	int  old_size = -1;
+	
+#ifdef THREAD_SAVE
+	pthread_mutex_lock(&mutex);
+#endif
+	int *lastPointer = &leakHash[ ADDR_HASH(p) ];
+	int i = *lastPointer;
+
+	while (i != 0 && leaks[i].addr != p) {
+		lastPointer = &leaks[i].nextBucket;
+		i = *lastPointer;
+	}
+	if (leaks[i].addr == p)
+		old_size = leaks[i].size;
+#ifdef THREAD_SAVE
+	pthread_mutex_unlock(&mutex);
+#endif
+	if (old_size >= 0) {
+		if ((int) size > old_size) {
+			new_p = registerAlloc(size, type, 2);
+			if (new_p) {
+				memcpy(new_p, p, old_size);
+				registerFree(p, type, 2);
+			}
+		}
+		else
+			new_p = p;
+	}
+	else {
+		fprintf(report, "D %10p             # realloc non alloc or twice pointer %10p\n", 
+			__builtin_return_address(1), p);
+		progAbort( DELETE_NONEXISTENT );
+	}
+	return new_p;
+}
 
 void LeakTracer::writeLeakReport() {
 	initialize();
@@ -467,16 +725,31 @@
 		fprintf(report, "# %10s | %9s  # Pointer Addr\n",
 			"from new @", "size");
 	}
-	for (int i = 0; i <  leaksCount; i++)
+	for (int i = 0; i < leaksCount; i++)
 		if (leaks[i].addr != NULL) {
-			// This ought to be 64-bit safe?
-			fprintf(report, "L %10p   %9ld  # %p\n",
-				leaks[i].allocAddr,
-				(long) leaks[i].size,
-				leaks[i].addr);
+			for (int j = 0; j < stack_depth; j++) {
+				if ( leaks[i].allocAddr[j] == 0 )
+					break;
+				// This ought to be 64-bit safe?
+				fprintf(report, "%c %10p   %9ld  # %p\n",
+						( j == 0 ) ? 'L' : 'l',
+						leaks[i].allocAddr[j],
+						(long) leaks[i].size,
+						leaks[i].addr);
+			}
+			if ( leaks[i].allocAddr[0] != 0 )
+				fprintf(report, "#\n");
 		}
-	fprintf(report, "# total allocation requests: %6ld ; max. mem used"
-		" %d kBytes\n", totalAllocations, maxAllocated / 1024);
+
+	if ( totalAllocations == 0 )
+		{
+		fprintf(report, "# ------ WARNING: no allocations requested ------\n");
+		fprintf(stderr, "# ------ WARNING: no allocations requested ------\n");
+		}
+	else
+		fprintf(report, "# total allocation requests: %6ld ; max. mem used"
+				" %d kBytes\n", totalAllocations, maxAllocated / 1024);
+
 	fprintf(report, "# leak %6d Bytes\t:-%c\n", currentAllocated,
 		(currentAllocated == 0) ? ')' : '(');
 	if (currentAllocated > 50 * 1024) {
@@ -488,27 +761,150 @@
 /** -- The actual new/delete operators -- **/
 
 void* operator new(size_t size) {
-	return leakTracer.registerAlloc(size,false);
+	TRACE((stderr, "new\n"));
+	return leakTracer.registerAlloc(size,false,1);
 }
 
 
 void* operator new[] (size_t size) {
-	return leakTracer.registerAlloc(size,true);
+	TRACE((stderr, "new[]\n"));
+	return leakTracer.registerAlloc(size,true,1);
 }
 
 
 void operator delete (void *p) {
-	leakTracer.registerFree(p,false);
+	TRACE((stderr, "delete(%p)\n",p));
+	leakTracer.registerFree(p,false,1);
 }
 
 
 void operator delete[] (void *p) {
-	leakTracer.registerFree(p,true);
+	TRACE((stderr, "delete[](%p)\n",p));
+	leakTracer.registerFree(p,true,1);
 }
 
+/** -- libc memory operators -- **/
+void *malloc(size_t size)
+{
+	TRACE((stderr, "malloc(%d)\n",size));
+#ifdef TRACE_MALLOC	
+	if (leakTracer.initialized)
+		return leakTracer.registerAlloc(size,false,1);
+	else
+#endif
+	{
+		if (!lt_malloc)
+		{
+			lt_malloc = (void*(*)(size_t))dlsym(RTLD_NEXT, "malloc");
+			TRACE((stderr, "malloc: lt_malloc=%p\n", lt_malloc));
+			if (!lt_malloc) {
+				fprintf(stderr, "LeakTracer: could not resolve 'malloc' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+		if (lt_malloc)
+			return LT_MALLOC(size);
+		else
+		{
+			TRACE((stderr, "assert(lt_malloc) failed\n"));
+			return NULL;
+		}
+	}
+}
+
+void  free(void* ptr)
+{
+	TRACE((stderr, "free(%p)\n", ptr));
+#ifdef TRACE_FREE
+	if (leakTracer.initialized)
+		leakTracer.registerFree(ptr,false,1);
+	else
+#endif
+	{
+		if (!lt_free)
+		{
+			lt_free = (void(*)(void*))dlsym(RTLD_NEXT, "free");
+			TRACE((stderr, "free: lt_free=%p\n", lt_free));
+			if (!lt_free) {
+				fprintf(stderr, "LeakTracer: could not resolve 'free' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+
+		if (lt_free)
+			return LT_FREE(ptr);
+		else
+		{
+			TRACE((stderr, "assert(lt_free) failed\n"));
+			return;
+		}
+		
+	}
+
+}
+void* realloc(void *ptr, size_t size)
+{
+	TRACE((stderr, "realloc(%p,%d)\n", ptr, size));
+#ifdef TRACE_REALLOC
+	if (leakTracer.initialized)
+		return leakTracer.registerRealloc(ptr,size,false);
+	else
+#endif
+	{
+		if (!lt_realloc)
+		{
+			lt_realloc = (void*(*)(void*,size_t))dlsym(RTLD_NEXT, "realloc");
+			TRACE((stderr, "realloc: lt_realloc=%p\n", lt_realloc));
+			if (!lt_realloc) {
+				fprintf(stderr, "LeakTracer: could not resolve 'realloc' in 'libc.so': %s\n", dlerror());
+				exit(1);
+			}
+		}
+		if (lt_realloc)
+			return LT_REALLOC(ptr, size);
+		else
+		{
+			TRACE((stderr, "assert(lt_realloc) failed\n"));
+			return NULL;
+		}
+	}
+}
+
+void* calloc(size_t nmemb, size_t size)
+{
+	TRACE((stderr, "calloc(%d,%d)\n",nmemb, size));
+#ifdef TRACE_CALLOC
+	if (leakTracer.initialized)
+	{
+		size_t total = nmemb * size;
+		void * ptr = leakTracer.registerAlloc(total,false,1);
+		if (ptr)
+		{
+			TRACE((stderr,"memset(%p, 0, %d)\n", ptr, total));
+			memset (ptr, 0, total);
+		}
+		return ptr;
+	}
+	else
+#endif
+	{
+		if (lt_calloc)
+			return LT_CALLOC(nmemb, size);
+		else
+		{
+
+			// The problem is that malloc or calloc call dlsym, which in turn
+			// (through _dlerror_run) call calloc and thus end up in endless
+			// recursion. Fortunately, in _dlerror_run nothing bad happens if
+			// calloc returns NULL,	because dlsym(_dlerror_run() will use
+			// a static buffer 
+			TRACE((stderr, "assert(lt_calloc) failed\n"));
+			return NULL;
+		}
+	}
+}
 /* Emacs: 
  * Local variables:
  * c-basic-offset: 8
  * End:
- * vi:set tabstop=8 shiftwidth=8 nowrap: 
  */
diff -Naur -X leaktracer.dontdiff leaktracer.orig/test.cc leaktracer.all/test.cc
--- leaktracer.orig/test.cc	2003-11-18 05:42:21.000000000 -0800
+++ leaktracer.all/test.cc	2005-08-09 12:28:50.000000000 -0700
@@ -1,7 +1,10 @@
 // Small leaky test program
+#include <stdlib.h>
 
-void foo() {
+
+void leak_word() {
     int *x = new int;
+    (void) x;
 }
 
 int main() {
@@ -10,8 +13,11 @@
     q[4] = 'x';                 // MAGIC overrun
     // Commenting out should make this abort
     // delete q;
-    foo();
-    foo();
+    leak_word();
+    leak_word();
+    int *y = (int *)malloc(16 * sizeof(int));
+    (void) y;
+
     delete z;
-    delete z;   // delete value twice
+    //delete z;   // delete value twice
 }
