Implement gdbsrv "v.info stats" command giving statistics for valgrind core + tools

* addition of VG_(needs_print_stats) in pub_tool_tooliface.h
* use the above in memcheck and helgrind
* output valgrind stats and calls print_stats in server.c



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13760
This commit is contained in:
Philippe Waroquiers 2013-12-15 20:24:43 +00:00
parent 7d40b140ac
commit 492a8ae2a2
9 changed files with 211 additions and 151 deletions

5
NEWS
View File

@ -11,6 +11,11 @@ Release 3.10.0 (?? ?????? 201?)
* ==================== OTHER CHANGES ====================
* New and modified GDB server monitor features:
- A new monitor command "v.info stats" that shows various valgrind core and tool
statistics.
* ==================== FIXED BUGS ====================
The following bugs have been fixed or resolved. Note that "n-i-bz"

View File

@ -30,6 +30,7 @@
#include "pub_core_execontext.h"
#include "pub_core_syswrap.h" // VG_(show_open_fds)
#include "pub_core_scheduler.h"
#include "pub_core_transtab.h"
unsigned long cont_thread;
unsigned long general_thread;
@ -216,6 +217,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
" (with aspacemgr arg, also shows valgrind segments on log ouput)\n"
" v.info exectxt : show stacktraces and stats of all execontexts\n"
" v.info scheduler : show valgrind thread state and stacktrace\n"
" v.info stats : show various valgrind and tool stats\n"
" v.set debuglog <level> : set valgrind debug log level to <level>\n"
" v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>\n"
" (default traceflags 0b00100000 : show after instrumentation)\n"
@ -288,7 +290,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
wcmd = strtok_r (NULL, " ", &ssaveptr);
switch (kwdid = VG_(keyword_id)
("all_errors n_errs_found last_error gdbserver_status memory"
" scheduler open_fds exectxt",
" scheduler stats open_fds exectxt",
wcmd, kwd_report_all)) {
case -2:
case -1:
@ -311,6 +313,8 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
VG_(gdbserver_status_output)();
break;
case 4: /* memory */
VG_(printf) ("%llu bytes have already been allocated.\n",
VG_(am_get_anonsize_total)());
VG_(print_all_arena_stats) ();
if (VG_(clo_profile_heap))
VG_(print_arena_cc_analysis) ();
@ -332,7 +336,18 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
VG_(show_sched_status) ();
ret = 1;
break;
case 6: /* open_fds */
case 6: /* stats */
VG_(print_translation_stats)();
VG_(print_tt_tc_stats)();
VG_(print_scheduler_stats)();
VG_(print_ExeContext_stats)( False /* with_stacktraces */ );
VG_(print_errormgr_stats)();
if (VG_(needs).print_stats) {
VG_TDICT_CALL(tool_print_stats);
}
ret = 1;
break;
case 7: /* open_fds */
if (VG_(clo_track_fds))
VG_(show_open_fds) ("");
else
@ -341,7 +356,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
" to show open fds\n");
ret = 1;
break;
case 7: /* exectxt */
case 8: /* exectxt */
VG_(print_ExeContext_stats) (True /* with_stacktraces */);
ret = 1;
break;

View File

@ -92,6 +92,7 @@ VgNeeds VG_(needs) = {
.client_requests = False,
.syscall_wrapper = False,
.sanity_checks = False,
.print_stats = False,
.var_info = False,
.malloc_replacement = False,
.xml_output = False,
@ -294,6 +295,14 @@ void VG_(needs_sanity_checks)(
VG_(tdict).tool_expensive_sanity_check = expen;
}
void VG_(needs_print_stats) (
void (*print_stats)(void)
)
{
VG_(needs).print_stats = True;
VG_(tdict).tool_print_stats = print_stats;
}
void VG_(needs_malloc_replacement)(
void* (*malloc) ( ThreadId, SizeT ),
void* (*__builtin_new) ( ThreadId, SizeT ),

View File

@ -88,6 +88,7 @@ typedef
Bool client_requests;
Bool syscall_wrapper;
Bool sanity_checks;
Bool print_stats;
Bool var_info;
Bool malloc_replacement;
Bool xml_output;
@ -149,6 +150,9 @@ typedef struct {
Bool (*tool_cheap_sanity_check)(void);
Bool (*tool_expensive_sanity_check)(void);
// VG_(needs).print_stats
void (*tool_print_stats)(void);
// VG_(needs).malloc_replacement
void* (*tool_malloc) (ThreadId, SizeT);
void* (*tool___builtin_new) (ThreadId, SizeT);

View File

@ -1435,6 +1435,13 @@ problems or bugs.</para>
</para>
</listitem>
<listitem>
<para><varname>v.info stats</varname> shows various valgrind core and
tool statistics. With this, Valgrind and tool statistics can
be examined while running, even without option <option>--stats=yes</option>.
</para>
</listitem>
<listitem>
<para><varname>v.set debuglog &lt;intvalue&gt;</varname> sets the
Valgrind debug log level to &lt;intvalue&gt;. This allows to

View File

@ -62,6 +62,7 @@ debugging valgrind internals monitor commands:
(with aspacemgr arg, also shows valgrind segments on log ouput)
v.info exectxt : show stacktraces and stats of all execontexts
v.info scheduler : show valgrind thread state and stacktrace
v.info stats : show various valgrind and tool stats
v.set debuglog <level> : set valgrind debug log level to <level>
v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>
(default traceflags 0b00100000 : show after instrumentation)

View File

@ -5133,28 +5133,8 @@ static void hg_print_debug_usage ( void )
);
}
static void hg_fini ( Int exitcode )
static void hg_print_stats (void)
{
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
VG_(message)(Vg_UserMsg,
"For counts of detected and suppressed errors, "
"rerun with: -v\n");
}
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)
&& HG_(clo_history_level) >= 2) {
VG_(umsg)(
"Use --history-level=approx or =none to gain increased speed, at\n" );
VG_(umsg)(
"the cost of reduced accuracy of conflicting-access information\n");
}
if (SHOW_DATA_STRUCTURES)
pp_everything( PP_ALL, "SK_(fini)" );
if (HG_(clo_sanity_flags))
all__sanity_check("SK_(fini)");
if (VG_(clo_stats)) {
if (1) {
VG_(printf)("\n");
@ -5211,8 +5191,32 @@ static void hg_fini ( Int exitcode )
VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks);
VG_(printf)("\n");
libhb_shutdown(True);
libhb_shutdown(True); // This in fact only print stats.
}
static void hg_fini ( Int exitcode )
{
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
VG_(message)(Vg_UserMsg,
"For counts of detected and suppressed errors, "
"rerun with: -v\n");
}
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)
&& HG_(clo_history_level) >= 2) {
VG_(umsg)(
"Use --history-level=approx or =none to gain increased speed, at\n" );
VG_(umsg)(
"the cost of reduced accuracy of conflicting-access information\n");
}
if (SHOW_DATA_STRUCTURES)
pp_everything( PP_ALL, "SK_(fini)" );
if (HG_(clo_sanity_flags))
all__sanity_check("SK_(fini)");
if (VG_(clo_stats))
hg_print_stats();
}
/* FIXME: move these somewhere sane */
@ -5305,6 +5309,8 @@ static void hg_pre_clo_init ( void )
//VG_(needs_sanity_checks) (hg_cheap_sanity_check,
// hg_expensive_sanity_check);
VG_(needs_print_stats) (hg_print_stats);
VG_(needs_malloc_replacement) (hg_cli__malloc,
hg_cli____builtin_new,
hg_cli____builtin_vec_new,

View File

@ -451,6 +451,13 @@ extern void VG_(needs_sanity_checks) (
Bool(*expensive_sanity_check)(void)
);
/* Can the tool produce stats during execution? */
extern void VG_(needs_print_stats) (
// Print out tool status. Note that the stats at end of execution
// should be output by the VG_(basic_tool_funcs) "fini" function.
void (*print_stats)(void)
);
/* Do we need to see variable type and location information? */
extern void VG_(needs_var_info) ( void );

View File

@ -6539,44 +6539,8 @@ static void print_SM_info(const HChar* type, Int n_SMs)
n_SMs * sizeof(SecMap) / (1024 * 1024UL) );
}
static void mc_fini ( Int exitcode )
static void mc_print_stats (void)
{
MC_(print_malloc_stats)();
if (MC_(clo_leak_check) != LC_Off) {
LeakCheckParams lcp;
lcp.mode = MC_(clo_leak_check);
lcp.show_leak_kinds = MC_(clo_show_leak_kinds);
lcp.heuristics = MC_(clo_leak_check_heuristics);
lcp.errors_for_leak_kinds = MC_(clo_error_for_leak_kinds);
lcp.deltamode = LCD_Any;
lcp.max_loss_records_output = 999999999;
lcp.requested_by_monitor_command = False;
MC_(detect_memory_leaks)(1/*bogus ThreadId*/, &lcp);
} else {
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
VG_(umsg)(
"For a detailed leak analysis, rerun with: --leak-check=full\n"
"\n"
);
}
}
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
VG_(message)(Vg_UserMsg,
"For counts of detected and suppressed errors, rerun with: -v\n");
}
if (MC_(any_value_errors) && !VG_(clo_xml) && VG_(clo_verbosity) >= 1
&& MC_(clo_mc_level) == 2) {
VG_(message)(Vg_UserMsg,
"Use --track-origins=yes to see where "
"uninitialised values come from\n");
}
done_prof_mem();
if (VG_(clo_stats)) {
SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
VG_(message)(Vg_DebugMsg,
@ -6666,6 +6630,47 @@ static void mc_fini ( Int exitcode )
}
}
static void mc_fini ( Int exitcode )
{
MC_(print_malloc_stats)();
if (MC_(clo_leak_check) != LC_Off) {
LeakCheckParams lcp;
lcp.mode = MC_(clo_leak_check);
lcp.show_leak_kinds = MC_(clo_show_leak_kinds);
lcp.heuristics = MC_(clo_leak_check_heuristics);
lcp.errors_for_leak_kinds = MC_(clo_error_for_leak_kinds);
lcp.deltamode = LCD_Any;
lcp.max_loss_records_output = 999999999;
lcp.requested_by_monitor_command = False;
MC_(detect_memory_leaks)(1/*bogus ThreadId*/, &lcp);
} else {
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
VG_(umsg)(
"For a detailed leak analysis, rerun with: --leak-check=full\n"
"\n"
);
}
}
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
VG_(message)(Vg_UserMsg,
"For counts of detected and suppressed errors, rerun with: -v\n");
}
if (MC_(any_value_errors) && !VG_(clo_xml) && VG_(clo_verbosity) >= 1
&& MC_(clo_mc_level) == 2) {
VG_(message)(Vg_UserMsg,
"Use --track-origins=yes to see where "
"uninitialised values come from\n");
}
done_prof_mem();
if (VG_(clo_stats))
mc_print_stats();
if (0) {
VG_(message)(Vg_DebugMsg,
"------ Valgrind's client block stats follow ---------------\n" );
@ -6726,6 +6731,7 @@ static void mc_pre_clo_init(void)
VG_(needs_client_requests) (mc_handle_client_request);
VG_(needs_sanity_checks) (mc_cheap_sanity_check,
mc_expensive_sanity_check);
VG_(needs_print_stats) (mc_print_stats);
VG_(needs_malloc_replacement) (MC_(malloc),
MC_(__builtin_new),
MC_(__builtin_vec_new),