Implement --keep-stacktraces=alloc|free|alloc-and-free|alloc-then-free|none

The option --keep-stacktraces controls which stack trace(s) to keep for
malloc'd and/or free'd blocks. This can be used to obtain more information
for 'use after free' errors or to decrease Valgrind memory and/or cpu usage
by recording less information for heap blocks.

This fixes 312913 Dangling pointers error should also report the alloc
stack trace.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13223 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h
index f9f07bf..29a0968 100644
--- a/memcheck/mc_include.h
+++ b/memcheck/mc_include.h
@@ -67,10 +67,25 @@
       Addr         data;            // Address of the actual block.
       SizeT        szB : (sizeof(SizeT)*8)-2; // Size requested; 30 or 62 bits.
       MC_AllocKind allockind : 2;   // Which operation did the allocation.
-      ExeContext*  where;           // Where it was allocated.
+      ExeContext*  where[0];
+      /* Variable-length array. The size depends on MC_(clo_keep_stacktraces).
+         This array optionally stores the alloc and/or free stack trace. */
    }
    MC_Chunk;
 
+/* Returns the execontext where the MC_Chunk was allocated/freed.
+   Returns VG_(null_ExeContext)() if the execontext has not been recorded (due
+   to MC_(clo_keep_stacktraces) and/or because block not yet freed). */
+ExeContext* MC_(allocated_at) (MC_Chunk*);
+ExeContext* MC_(freed_at) (MC_Chunk*);
+
+/* Records and sets execontext according to MC_(clo_keep_stacktraces) */
+void  MC_(set_allocated_at) (ThreadId, MC_Chunk*);
+void  MC_(set_freed_at) (ThreadId, MC_Chunk*);
+
+/* number of pointers needed according to MC_(clo_keep_stacktraces). */
+UInt MC_(n_where_pointers) (void);
+
 /* Memory pool.  Nb: first two fields must match core's VgHashNode. */
 typedef
    struct _MC_Mempool {
@@ -492,6 +507,20 @@
 extern Int MC_(clo_malloc_fill);
 extern Int MC_(clo_free_fill);
 
+/* Which stack trace(s) to keep for malloc'd/free'd client blocks?
+   For each client block, the stack traces where it was allocated
+   and/or freed are optionally kept depending on MC_(clo_keep_stacktraces). */
+typedef
+   enum {                 // keep alloc stack trace ?  keep free stack trace ?
+      KS_none,            // never                     never
+      KS_alloc,           // always                    never
+      KS_free,            // never                     always
+      KS_alloc_then_free, // when still malloc'd       when free'd
+      KS_alloc_and_free,  // always                    always
+   }
+   KeepStacktraces;
+extern KeepStacktraces MC_(clo_keep_stacktraces);
+
 /* Indicates the level of instrumentation/checking done by Memcheck.
 
    1 = No undefined value checking, Addrcheck-style behaviour only: