Index: /branches/jch-memory/psLib/src/sys/psMemory.c
===================================================================
--- /branches/jch-memory/psLib/src/sys/psMemory.c	(revision 10997)
+++ /branches/jch-memory/psLib/src/sys/psMemory.c	(revision 10998)
@@ -10,9 +10,13 @@
 *  @author Joshua Hoblitt, University of Hawaii
 *
-*  @version $Revision: 1.88.2.21 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2007-01-05 21:26:52 $
+*  @version $Revision: 1.88.2.22 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-09 22:23:05 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
 
 #define PS_ALLOW_MALLOC                    // we're allowed to call malloc()
@@ -23,4 +27,8 @@
 #include <string.h>
 #include <assert.h>
+
+#if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+# include <execinfo.h>
+#endif
 
 #include "psMemory.h"
@@ -424,4 +432,19 @@
     memBlock->func = func;
 
+    #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+    #define BACKTRACE_BUFFER_SIZE 32
+    // psMemBlock.func is a 'const char *', so basically we're going to abuse
+    // that and treat it as a void ** to carry around backtrace information.
+    // psMemBlock is not ifdef'd to make sure that psMemBlock is always the
+    // same size & layout reguardless of the pslib .so that's being linked
+    // against
+    void **bt = malloc(BACKTRACE_BUFFER_SIZE * sizeof(void *));
+    if (bt == NULL) {
+        PS_MEM_ABORT(__func__, "Failed to allocate memmory for backtrace buffer: %zd bytes at %s (%s:%d)", 32 * sizeof(void *), func, file, lineno);
+    }
+    *(size_t *)&memBlock->backtraceSize = backtrace(bt, BACKTRACE_BUFFER_SIZE);
+    *(void ***)&memBlock->backtrace = bt;
+    #endif // ifdef HAVE_BACKTRACE
+
     // free function
     memBlock->freeFunc = NULL;
@@ -548,5 +571,10 @@
     MUTEX_LOCK(&memBlockListMutex);
 
-    for (psMemBlock *memBlock = topBlock; memBlock != NULL; memBlock = memBlock->nextBlock) {
+    // find the very first memblock
+    psMemBlock *memBlock = NULL;
+    for (memBlock = topBlock; memBlock->nextBlock != NULL; memBlock = memBlock->nextBlock) { }
+
+    // iterate through the block list starting with the oldest block
+    for (; memBlock != NULL; memBlock = memBlock->previousBlock) {
         if ( (memBlock->refCounter > 0) &&
                 ( (persistence) || (!persistence && !memBlock->persistent) ) &&
@@ -557,8 +585,45 @@
             if (fd != NULL) {
                 if (nleak == 1) {
-                    fprintf(fd, "   %20s:line ID\n", "file");
+                    fprintf(fd, "# func at (file:line)  ID: X\n");
                 }
 
-                fprintf(fd, "   %20s:%-4d %lu\n", memBlock->file, (int)memBlock->lineno, (unsigned long)memBlock->id);
+                fprintf(fd, "%s at (%s:%d)  ID: %lu", memBlock->func, memBlock->file, (int)memBlock->lineno, (unsigned long)memBlock->id);
+                #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE)
+
+                size_t size = memBlock->backtraceSize;
+                char **strings = backtrace_symbols((void *const *)memBlock->backtrace, size);
+
+                fprintf(fd, "  Alloc Call Depth: %zd\n", size);
+
+                for (int i = 0; i < size; i++) {
+                    // always ident
+                    int ident = 4;  // initial indent
+                    ident += 2 * i; // nesting depth
+                    fprintf(fd, "%*s", ident, "");
+
+                    // if the caller was an anon function then strchr won't
+                    // find a '(' in the string and will return NULL
+                    char *caller = caller = strchr(strings[i], '(');
+                    if (caller) {
+                        // skip over the '('
+                        caller++;
+                        // find the end of the symbol name
+                        size_t callerLength = abs(strchr(caller, '+') - caller);
+                        // print just the symbol name
+                        for (int i = 0; i < callerLength; i++) {
+                            fputc(caller[i],fd);
+                        }
+                        fprintf(fd, "\n");
+                    } else {
+                        fprintf(fd, "(unknown)\n");
+                    }
+                }
+
+                free (strings);
+                #else // ifdef HAVE_BACKTRACE
+                // \n after "Memory Block ID"
+                fprintf(fd, "\n");
+                #endif // ifdef HAVE_BACKTRACE
+
             }
         }
Index: /branches/jch-memory/psLib/src/sys/psMemory.h
===================================================================
--- /branches/jch-memory/psLib/src/sys/psMemory.h	(revision 10997)
+++ /branches/jch-memory/psLib/src/sys/psMemory.h	(revision 10998)
@@ -14,6 +14,6 @@
  *  @ingroup MemoryManagement
  *
- *  @version $Revision: 1.61.2.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-01-05 22:30:08 $
+ *  @version $Revision: 1.61.2.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-09 22:23:05 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -82,4 +82,10 @@
     const unsigned int lineno;         ///< set from __LINE__ in e.g. p_psAlloc
     const char *func;                  ///< set from __func__
+    #ifdef HAVE_BACKTRACE
+
+    const void **backtrace;                  ///< set from backtrace()
+    const size_t backtraceSize;              ///< set from bracktrace()
+    #endif // ifdef HAVE_BACKTRACE
+
     psReferenceCount refCounter;       ///< how many times pointer is referenced
     bool persistent;                   ///< marks if this non-user persistent data like error stack, etc.
Index: /trunk/psLib/configure.ac
===================================================================
--- /trunk/psLib/configure.ac	(revision 10997)
+++ /trunk/psLib/configure.ac	(revision 10998)
@@ -81,4 +81,13 @@
    [tests=false])
 AM_CONDITIONAL(BUILD_TESTS, test x$tests = xtrue)
+
+dnl turn on mem leak backtracing 
+AC_ARG_ENABLE(backtrace,
+  [AS_HELP_STRING(--enable-backtrace, enable memory allocation backtracing)],
+  [AC_MSG_RESULT(memory allocation backtracing enabled)
+    AC_DEFINE([PS_MEM_BACKTRACE], 1, [Define to 1 if you want memory backtracing])
+  ]
+)
+AC_CHECK_FUNCS_ONCE([backtrace])
 
 AC_LANG(C)
