shows places pointing inside <len> (default 1) bytes at <addr>
(with len 1, only shows "start pointers" pointing exactly to <addr>,
with len > 1, will also show "interior pointers")
+ xtmemory [<filename>]
+ dump xtree memory profile in <filename> (default xtmemory.kcg)
general valgrind monitor commands:
help [debug] : monitor command help. With debug: + debugging commands
v.wait [<ms>] : sleep <ms> (default 0) then continue
shows places pointing inside <len> (default 1) bytes at <addr>
(with len 1, only shows "start pointers" pointing exactly to <addr>,
with len > 1, will also show "interior pointers")
+ xtmemory [<filename>]
+ dump xtree memory profile in <filename> (default xtmemory.kcg)
monitor command request to kill this process
void MC_(make_mem_defined) ( Addr a, SizeT len );
void MC_(copy_address_range_state) ( Addr src, Addr dst, SizeT len );
+void MC_(xtmemory_report) ( const HChar* filename, Bool fini );
+
void MC_(print_malloc_stats) ( void );
/* nr of free operations done */
SizeT MC_(get_cmalloc_n_frees) ( void );
#include "pub_tool_replacemalloc.h"
#include "pub_tool_tooliface.h"
#include "pub_tool_threadstate.h"
+#include "pub_tool_xarray.h"
+#include "pub_tool_xtree.h"
+#include "pub_tool_xtmemory.h"
#include "mc_include.h"
#include "memcheck.h" /* for client requests */
" shows places pointing inside <len> (default 1) bytes at <addr>\n"
" (with len 1, only shows \"start pointers\" pointing exactly to <addr>,\n"
" with len > 1, will also show \"interior pointers\")\n"
+" xtmemory [<filename>]\n"
+" dump xtree memory profile in <filename> (default xtmemory.kcg)\n"
"\n");
}
command. This ensures a shorter abbreviation for the user. */
switch (VG_(keyword_id)
("help get_vbits leak_check make_memory check_memory "
- "block_list who_points_at xb",
+ "block_list who_points_at xb xtmemory",
wcmd, kwd_report_duplicated_matches)) {
case -2: /* multiple matches */
return True;
return True;
}
+ case 8: { /* xtmemory */
+ HChar* filename;
+ filename = VG_(strtok_r) (NULL, " ", &ssaveptr);
+ MC_(xtmemory_report)(filename, False);
+ return True;
+ }
+
default:
tl_assert(0);
return False;
/* Do not check definedness of guest state if --undef-value-errors=no */
if (MC_(clo_mc_level) >= 2)
VG_(track_pre_reg_read) ( mc_pre_reg_read );
+
+ if (VG_(clo_xtree_memory) == Vg_XTMemory_Full) {
+ if (MC_(clo_keep_stacktraces) == KS_none
+ || MC_(clo_keep_stacktraces) == KS_free)
+ VG_(fmsg_bad_option)("--keep-stacktraces",
+ "To use --xtree-memory=full, you must"
+ " keep at least the alloc stacktrace\n");
+ // Activate full xtree memory profiling.
+ VG_(XTMemory_Full_init)(VG_(XT_filter_1top_and_maybe_below_main));
+ }
+
}
static void print_SM_info(const HChar* type, Int n_SMs)
static void mc_fini ( Int exitcode )
{
+ MC_(xtmemory_report) (VG_(clo_xtree_memory_file), True);
MC_(print_malloc_stats)();
if (MC_(clo_leak_check) != LC_Off) {
#include "pub_tool_libcbase.h"
#include "pub_tool_libcassert.h"
#include "pub_tool_libcprint.h"
+#include "pub_tool_libcproc.h"
#include "pub_tool_mallocfree.h"
#include "pub_tool_options.h"
#include "pub_tool_replacemalloc.h"
#include "pub_tool_threadstate.h"
#include "pub_tool_tooliface.h" // Needed for mc_include.h
#include "pub_tool_stacktrace.h" // For VG_(get_and_pp_StackTrace)
+#include "pub_tool_xarray.h"
+#include "pub_tool_xtree.h"
+#include "pub_tool_xtmemory.h"
#include "mc_include.h"
default: tl_assert (0);
}
mc->where[0] = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
+ if (UNLIKELY(VG_(clo_xtree_memory) == Vg_XTMemory_Full))
+ VG_(XTMemory_Full_alloc)(mc->szB, mc->where[0]);
}
void MC_(set_freed_at) (ThreadId tid, MC_Chunk* mc)
{
- UInt pos;
+ Int pos;
+ ExeContext* ec_free;
+
switch (MC_(clo_keep_stacktraces)) {
case KS_none: return;
- case KS_alloc: return;
+ case KS_alloc: pos = -1; break;
case KS_free: pos = 0; break;
case KS_alloc_then_free: pos = 0; break;
case KS_alloc_and_free: pos = 1; break;
default: tl_assert (0);
}
- mc->where[pos] = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
+ /* We need the execontext for the free operation, either to store
+ it in the mc chunk and/or for full xtree memory profiling.
+ Note: we are guaranteed to find the ec_alloc in mc->where[0], as
+ mc_post_clo_init verifies the consistency of --xtree-memory and
+ --keep-stacktraces. */
+ ec_free = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
+ if (UNLIKELY(VG_(clo_xtree_memory) == Vg_XTMemory_Full))
+ VG_(XTMemory_Full_free)(mc->szB, mc->where[0], ec_free);
+ if (pos >= 0)
+ mc->where[pos] = ec_free;
}
UInt MC_(n_where_pointers) (void)
if (oldSizeB == newSizeB)
return;
+ if (UNLIKELY(VG_(clo_xtree_memory) == Vg_XTMemory_Full))
+ VG_(XTMemory_Full_resize_in_place)(oldSizeB, newSizeB, mc->where[0]);
+
mc->szB = newSizeB;
if (newSizeB < oldSizeB) {
MC_(make_mem_noaccess)( p + newSizeB, oldSizeB - newSizeB + rzB );
return True;
}
+static void xtmemory_report_next_block(XT_Allocs* xta, ExeContext** ec_alloc)
+{
+ MC_Chunk* mc = VG_(HT_Next)(MC_(malloc_list));
+ if (mc) {
+ xta->nbytes = mc->szB;
+ xta->nblocks = 1;
+ *ec_alloc = MC_(allocated_at)(mc);
+ } else
+ xta->nblocks = 0;
+}
+
+void MC_(xtmemory_report) ( const HChar* filename, Bool fini )
+{
+ // Make xtmemory_report_next_block ready to be called.
+ VG_(HT_ResetIter)(MC_(malloc_list));
+
+ VG_(XTMemory_report)(filename, fini, xtmemory_report_next_block,
+ VG_(XT_filter_1top_and_maybe_below_main));
+}
/*------------------------------------------------------------*/
/*--- Statistics printing ---*/