From: Philippe Waroquiers Date: Fri, 11 Nov 2016 14:36:36 +0000 (+0000) Subject: Support for xtree memory profiling and xtmemory gdbsrv monitor command in memcheck X-Git-Tag: svn/VALGRIND_3_13_0~293 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b10e381272c53dffcee21eb10e1a8cda9b040c66;p=thirdparty%2Fvalgrind.git Support for xtree memory profiling and xtmemory gdbsrv monitor command in memcheck * memcheck will produce xtree memory profiling according to the options --xtree-memory. * addition of the xtmemory gdbserver monitor command. (this is the second real xtree functional difference) git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16128 --- diff --git a/gdbserver_tests/mchelp.stdoutB.exp b/gdbserver_tests/mchelp.stdoutB.exp index 6d6bdb146b..742181f2c5 100644 --- a/gdbserver_tests/mchelp.stdoutB.exp +++ b/gdbserver_tests/mchelp.stdoutB.exp @@ -52,6 +52,8 @@ memcheck monitor commands: shows places pointing inside (default 1) bytes at (with len 1, only shows "start pointers" pointing exactly to , with len > 1, will also show "interior pointers") + xtmemory [] + dump xtree memory profile in (default xtmemory.kcg) general valgrind monitor commands: help [debug] : monitor command help. With debug: + debugging commands v.wait [] : sleep (default 0) then continue @@ -121,4 +123,6 @@ memcheck monitor commands: shows places pointing inside (default 1) bytes at (with len 1, only shows "start pointers" pointing exactly to , with len > 1, will also show "interior pointers") + xtmemory [] + dump xtree memory profile in (default xtmemory.kcg) monitor command request to kill this process diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h index d36ea0ba1e..fc2d4b7823 100644 --- a/memcheck/mc_include.h +++ b/memcheck/mc_include.h @@ -144,6 +144,8 @@ void MC_(make_mem_undefined_w_otag)( Addr a, SizeT len, UInt otag ); 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 ); diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index 30fa0084e9..1303b934b4 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -47,6 +47,9 @@ #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 */ @@ -6400,6 +6403,8 @@ static void print_monitor_help ( void ) " shows places pointing inside (default 1) bytes at \n" " (with len 1, only shows \"start pointers\" pointing exactly to ,\n" " with len > 1, will also show \"interior pointers\")\n" +" xtmemory []\n" +" dump xtree memory profile in (default xtmemory.kcg)\n" "\n"); } @@ -6515,7 +6520,7 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) 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; @@ -6874,6 +6879,13 @@ static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) 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; @@ -7889,6 +7901,17 @@ static void mc_post_clo_init ( void ) /* 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) @@ -7997,6 +8020,7 @@ static void mc_print_stats (void) 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) { diff --git a/memcheck/mc_malloc_wrappers.c b/memcheck/mc_malloc_wrappers.c index f488178524..e11fb23850 100644 --- a/memcheck/mc_malloc_wrappers.c +++ b/memcheck/mc_malloc_wrappers.c @@ -36,12 +36,16 @@ #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" @@ -303,20 +307,33 @@ void MC_(set_allocated_at) (ThreadId tid, MC_Chunk* mc) 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) @@ -651,6 +668,9 @@ void MC_(handle_resizeInPlace)(ThreadId tid, Addr p, 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 ); @@ -1117,6 +1137,25 @@ Bool MC_(mempool_exists)(Addr pool) 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 ---*/