}
// Various stats
- if (VG_(clo_verbosity) > 1) {
+ if (VG_(clo_stats)) {
Int debug_lookups = full_debugs + fn_debugs +
file_line_debugs + no_debugs;
if (VG_(clo_verbosity) == 0) return;
/* Hash table stats */
- if (VG_(clo_verbosity) > 1) {
+ if (VG_(clo_stats)) {
int BB_lookups =
CLG_(stat).full_debug_BBs +
CLG_(stat).fn_name_debug_BBs +
for (su = suppressions; su != NULL; su = su->next) {
if (su->count <= 0)
continue;
- any_supp = True;
if (VG_(clo_xml)) {
VG_(printf_xml_no_f_c)( " <pair>\n"
" <count>%d</count>\n"
" </pair>\n",
su->count, su->sname );
} else {
- VG_(dmsg)("supp: %6d %s\n", su->count, su->sname);
+ // blank line before the first shown suppression, if any
+ if (!any_supp)
+ VG_(dmsg)("\n");
+ VG_(dmsg)("used_suppression: %6d %s\n", su->count, su->sname);
}
+ any_supp = True;
}
if (VG_(clo_xml))
if (VG_(clo_verbosity) <= 1)
return;
+ // We do the following only at -v or above, and only in non-XML
+ // mode
+
/* Print the contexts in order of increasing error count. */
for (i = 0; i < n_err_contexts; i++) {
n_min = (1 << 30) - 1;
p_min->count = 1 << 30;
}
- if (n_supp_contexts > 0)
- VG_(umsg)("\n");
any_supp = show_used_suppressions();
- if (n_err_contexts > 0) {
- if (any_supp)
- VG_(umsg)("\n");
- VG_(umsg)("IN SUMMARY: "
- "%d errors from %d contexts (suppressed: %d from %d)\n",
- n_errs_found, n_err_contexts, n_errs_suppressed,
- n_supp_contexts );
+ if (any_supp)
VG_(umsg)("\n");
- }
+ // reprint this, so users don't have to scroll way up to find
+ // the first printing
+ VG_(umsg)("ERROR SUMMARY: "
+ "%d errors from %d contexts (suppressed: %d from %d)\n",
+ n_errs_found, n_err_contexts, n_errs_suppressed,
+ n_supp_contexts );
}
" --help-debug show this message, plus debugging options\n"
" --version show version\n"
" -q --quiet run silently; only print error msgs\n"
-" -v --verbose be more verbose, incl counts of errors\n"
+" -v --verbose be more verbose -- show misc extra info\n"
" --trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]\n"
" --child-silent-after-fork=no|yes omit child output between fork & exec? [no]\n"
" --track-fds=no|yes track open file descriptors? [no]\n"
Char* usage2 =
"\n"
" debugging options for all Valgrind tools:\n"
+" --stats=no|yes show tool and core statistics [no]\n"
" -d show verbose debugging output\n"
" --sanity-level=<number> level of sanity checking to do [1]\n"
" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
VG_STREQ(arg, "--quiet"))
VG_(clo_verbosity)--;
+ else if VG_BOOL_CLO(arg, "--stats", VG_(clo_stats)) {}
else if VG_BOOL_CLO(arg, "--xml", VG_(clo_xml)) {}
else if VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach)) {}
else if VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle)) {}
if (VG_(clo_track_fds))
VG_(show_open_fds)();
- /* ** HACK ALERT ** HACK ALERT ** HACK ALERT ** HACK ALERT ** */
- if (VG_(clo_xml)) {
- /* THIS IS WHAT WE SHOULD CHANGE IT TO */
- /* For the moment, do it like this (the "right way") in XML
- mode, so that output is as described in XML Protocol 4. */
- /* A good test is memcheck/tests/amd64/defcfaexpr; ensure
- the output does not change */
- VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
-
- /* Show the error counts. */
- if (VG_(needs).core_errors || VG_(needs).tool_errors) {
- VG_(printf_xml)( "\n" );
- VG_(show_error_counts_as_XML)();
- VG_(printf_xml)( "\n" );
- }
+ /* Call the tool's finalisation function. This makes Memcheck's
+ leak checker run, and possibly chuck a bunch of leak errors into
+ the error management machinery. */
+ VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
- /* In XML mode, this merely prints the used suppressions. */
- if (VG_(needs).core_errors || VG_(needs).tool_errors)
- VG_(show_all_errors)();
-
- } else {
- /* THIS IS WHAT IT HAS ALWAYS BEEN,
- resulting in https://bugs.kde.org/show_bug.cgi?id=186790 */
- if (VG_(needs).core_errors || VG_(needs).tool_errors)
- VG_(show_all_errors)();
-
- VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
+ /* Show the error counts. */
+ if (VG_(needs).core_errors || VG_(needs).tool_errors) {
+ VG_(printf_xml)( "\n" );
+ VG_(show_error_counts_as_XML)();
+ VG_(printf_xml)( "\n" );
}
- /* END ** HACK ALERT ** HACK ALERT ** HACK ALERT ** HACK ALERT ** */
+
+ /* In XML mode, this merely prints the used suppressions. */
+ if (VG_(needs).core_errors || VG_(needs).tool_errors)
+ VG_(show_all_errors)();
if (VG_(clo_xml)) {
VG_(printf_xml)("\n");
VG_(sanity_check_general)( True /*include expensive checks*/ );
- if (VG_(clo_verbosity) > 1)
+ if (VG_(clo_stats))
print_all_stats();
/* Show a profile of the heap(s) at shutdown. Optionally, first
Int VG_(clo_gen_suppressions) = 0;
Int VG_(clo_sanity_level) = 1;
Int VG_(clo_verbosity) = 1;
+Bool VG_(clo_stats) = False;
Bool VG_(clo_xml) = False;
HChar* VG_(clo_xml_user_comment) = NULL;
Bool VG_(clo_demangle) = True;
static void DRD_(fini)(Int exitcode)
{
// thread_print_all();
- if (VG_(clo_verbosity) > 1 || DRD_(s_print_stats))
+ 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_stats) || DRD_(s_print_stats))
{
ULong pu = DRD_(thread_get_update_conflict_set_count)();
ULong pu_seg_cr = DRD_(thread_get_update_conflict_set_new_sg_count)();
-e "s/[@\$*]* (drd_pthread_intercepts.c:/ (drd_pthread_intercepts.c:/" \
-e "s/ (\([a-zA-Z_]*\.c\):[0-9]*)/ (\1:?)/" \
-e "s/ (\([a-zA-Z_]*\.h\):[0-9]*)/ (\1:?)/" \
--e "s/ (\([a-zA-Z_]*\.cpp\):[0-9]*)/ (\1:?)/" |
+-e "s/ (\([a-zA-Z_]*\.cpp\):[0-9]*)/ (\1:?)/" \
+-e "/^For counts of detected and suppressed errors, rerun with: -v$/d" |
# Remove the message that more than hundred errors have been detected
# (consists of two lines) and also the empty line above it.
void h_fini ( Int exitcode )
{
- if (VG_(clo_verbosity) >= 2) {
+ 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_stats)) {
VG_(message)(Vg_DebugMsg,
" h_: %'10llu client allocs, %'10llu client frees\n",
stats__client_mallocs, stats__client_frees);
void sg_fini(Int exitcode)
{
- if (VG_(clo_verbosity) >= 2) {
+ if (VG_(clo_stats)) {
VG_(message)(Vg_DebugMsg,
" sg_: %'llu total accesses, of which:\n", stats__total_accesses);
VG_(message)(Vg_DebugMsg,
# Anonymise paths like "__libc_start_main (../foo/bar/libc-quux.c:129)"
sed "s/__libc_\(.*\) (.*)$/__libc_\1 (...libc...)/" |
-# Remove preambly stuff
+# Remove preambly stuff; also postambly stuff
sed \
-e "/^exp-ptrcheck, a heap, stack & global array overrun detector\.$/d" \
-e "/^NOTE: This is an Experimental-Class Valgrind Tool.$/d" \
--e "/^Copyright (C) 2003-200., and GNU GPL'd, by OpenWorks Ltd et al.$/d" |
+-e "/^Copyright (C) 2003-200., and GNU GPL'd, by OpenWorks Ltd et al.$/d" \
+-e "/^For counts of detected and suppressed errors, rerun with: -v$/d" |
# Tidy up in cases where glibc (+ libdl + libpthread + ld) have
# been built with debugging information, hence source locs are present.
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_verbosity) >= 2) {
+ if (VG_(clo_stats)) {
if (1) {
VG_(printf)("\n");
# Anonymise addresses
$dir/../../tests/filter_addresses |
-# Remove "Helgrind, ..." line and the following copyright line.
-sed "/^Helgrind, a thread error detector/ , /./ d" |
+# Remove "Helgrind, ..." line and the following copyright line;
+# also the standard postamble (does such a word exist?)
+sed \
+ -e "/^Helgrind, a thread error detector/ , /./ d" \
+ -e "/^For counts of detected and suppressed errors, rerun with: -v$/d" \
+ -e "/^Use --history-level=approx or =none to gain increased speed, at$/d" \
+ -e "/^the cost of reduced accuracy of conflicting-access information$/d" |
# Anonymise line numbers in hg_intercepts.c
sed "s/hg_intercepts.c:[0-9]*/hg_intercepts.c:.../g" |
/* Verbosity level: 0 = silent, 1 (default), > 1 = more verbose. */
extern Int VG_(clo_verbosity);
+/* Show tool and core statistics */
+extern Bool VG_(clo_stats);
+
/* Emit all messages as XML? default: NO */
/* If clo_xml is set, various other options are set in a non-default
way. See vg_main.c and mc_main.c. */
VG_(dmsg)("Massif: " format, ##args); \
}
+// Used for printing stats when clo_stats == True.
+#define STATS(format, args...) \
+ if (VG_(clo_stats)) { \
+ VG_(dmsg)("Massif: " format, ##args); \
+ }
+
//------------------------------------------------------------//
//--- Statistics ---//
//------------------------------------------------------------//
// Stats
tl_assert(n_xpts > 0); // always have alloc_xpt
- VERB(1, "heap allocs: %u\n", n_heap_allocs);
- VERB(1, "heap reallocs: %u\n", n_heap_reallocs);
- VERB(1, "heap frees: %u\n", n_heap_frees);
- VERB(1, "ignored heap allocs: %u\n", n_ignored_heap_allocs);
- VERB(1, "ignored heap frees: %u\n", n_ignored_heap_frees);
- VERB(1, "ignored heap reallocs: %u\n", n_ignored_heap_reallocs);
- VERB(1, "stack allocs: %u\n", n_stack_allocs);
- VERB(1, "stack frees: %u\n", n_stack_frees);
- VERB(1, "XPts: %u\n", n_xpts);
- VERB(1, "top-XPts: %u (%d%%)\n",
+ STATS("heap allocs: %u\n", n_heap_allocs);
+ STATS("heap reallocs: %u\n", n_heap_reallocs);
+ STATS("heap frees: %u\n", n_heap_frees);
+ STATS("ignored heap allocs: %u\n", n_ignored_heap_allocs);
+ STATS("ignored heap frees: %u\n", n_ignored_heap_frees);
+ STATS("ignored heap reallocs: %u\n", n_ignored_heap_reallocs);
+ STATS("stack allocs: %u\n", n_stack_allocs);
+ STATS("stack frees: %u\n", n_stack_frees);
+ STATS("XPts: %u\n", n_xpts);
+ STATS("top-XPts: %u (%d%%)\n",
alloc_xpt->n_children,
( n_xpts ? alloc_xpt->n_children * 100 / n_xpts : 0));
- VERB(1, "XPt init expansions: %u\n", n_xpt_init_expansions);
- VERB(1, "XPt later expansions: %u\n", n_xpt_later_expansions);
- VERB(1, "SXPt allocs: %u\n", n_sxpt_allocs);
- VERB(1, "SXPt frees: %u\n", n_sxpt_frees);
- VERB(1, "skipped snapshots: %u\n", n_skipped_snapshots);
- VERB(1, "real snapshots: %u\n", n_real_snapshots);
- VERB(1, "detailed snapshots: %u\n", n_detailed_snapshots);
- VERB(1, "peak snapshots: %u\n", n_peak_snapshots);
- VERB(1, "cullings: %u\n", n_cullings);
- VERB(1, "XCon redos: %u\n", n_XCon_redos);
+ STATS("XPt init expansions: %u\n", n_xpt_init_expansions);
+ STATS("XPt later expansions: %u\n", n_xpt_later_expansions);
+ STATS("SXPt allocs: %u\n", n_sxpt_allocs);
+ STATS("SXPt frees: %u\n", n_sxpt_frees);
+ STATS("skipped snapshots: %u\n", n_skipped_snapshots);
+ STATS("real snapshots: %u\n", n_real_snapshots);
+ STATS("detailed snapshots: %u\n", n_detailed_snapshots);
+ STATS("peak snapshots: %u\n", n_peak_snapshots);
+ STATS("cullings: %u\n", n_cullings);
+ STATS("XCon redos: %u\n", n_XCon_redos);
}
prog: culling1
-vgopts: -v -v --stacks=no --time-unit=B --heap-admin=16 --massif-out-file=massif.out
+vgopts: -v -v --stats=yes --stacks=no --time-unit=B --heap-admin=16 --massif-out-file=massif.out
vgopts: --ignore-fn=__part_load_locale --ignore-fn=__time_load_locale --ignore-fn=dwarf2_unwind_dyld_add_image_hook --ignore-fn=get_or_create_key_element
stderr_filter: filter_verbose
cleanup: rm massif.out
prog: culling2
-vgopts: -v -v --stacks=no --time-unit=B --heap-admin=16 --massif-out-file=massif.out
+vgopts: -v -v --stats=yes --stacks=no --time-unit=B --heap-admin=16 --massif-out-file=massif.out
vgopts: --ignore-fn=__part_load_locale --ignore-fn=__time_load_locale --ignore-fn=dwarf2_unwind_dyld_add_image_hook --ignore-fn=get_or_create_key_element
stderr_filter: filter_verbose
cleanup: rm massif.out
prog: deep
-vgopts: --stacks=no --time-unit=B --alloc-fn=a6 --alloc-fn=a7 --alloc-fn=a8 --alloc-fn=a9 --alloc-fn=a10 --alloc-fn=a11 --alloc-fn=a12 -v -v --depth=8 --massif-out-file=massif.out
+vgopts: --stats=yes --stacks=no --time-unit=B --alloc-fn=a6 --alloc-fn=a7 --alloc-fn=a8 --alloc-fn=a9 --alloc-fn=a10 --alloc-fn=a11 --alloc-fn=a12 -v -v --depth=8 --massif-out-file=massif.out
vgopts: --ignore-fn=__part_load_locale --ignore-fn=__time_load_locale --ignore-fn=dwarf2_unwind_dyld_add_image_hook --ignore-fn=get_or_create_key_element
stderr_filter: filter_verbose
post: perl ../../massif/ms_print massif.out | ../../tests/filter_addresses
prog: deep
-vgopts: --stacks=no --time-unit=B --alloc-fn=a3 --alloc-fn=a4 --alloc-fn=a5 --alloc-fn=a6 --alloc-fn=a7 --alloc-fn=a8 --alloc-fn=a9 --alloc-fn=a10 --alloc-fn=a11 --alloc-fn=a12 -v -v --depth=8 --massif-out-file=massif.out
+vgopts: --stacks=no --time-unit=B --alloc-fn=a3 --alloc-fn=a4 --alloc-fn=a5 --alloc-fn=a6 --alloc-fn=a7 --alloc-fn=a8 --alloc-fn=a9 --alloc-fn=a10 --alloc-fn=a11 --alloc-fn=a12 -v -v --stats=yes --depth=8 --massif-out-file=massif.out
vgopts: --ignore-fn=__part_load_locale --ignore-fn=__time_load_locale --ignore-fn=dwarf2_unwind_dyld_add_image_hook --ignore-fn=get_or_create_key_element
stderr_filter: filter_verbose
post: perl ../../massif/ms_print massif.out | ../../tests/filter_addresses
prog: peak
-vgopts: --stacks=no --time-unit=B -v -v --peak-inaccuracy=10.0 --heap-admin=128 --massif-out-file=massif.out
+vgopts: --stacks=no --time-unit=B -v -v --stats=yes --peak-inaccuracy=10.0 --heap-admin=128 --massif-out-file=massif.out
vgopts: --ignore-fn=__part_load_locale --ignore-fn=__time_load_locale --ignore-fn=dwarf2_unwind_dyld_add_image_hook --ignore-fn=get_or_create_key_element
stderr_filter: filter_verbose
post: perl ../../massif/ms_print massif.out | ../../tests/filter_addresses
prog: realloc
-vgopts: -v -v --stacks=no --heap-admin=0 --time-unit=B --threshold=0 --massif-out-file=massif.out
+vgopts: -v -v --stats=yes --stacks=no --heap-admin=0 --time-unit=B --threshold=0 --massif-out-file=massif.out
vgopts: --ignore-fn=__part_load_locale --ignore-fn=__time_load_locale --ignore-fn=dwarf2_unwind_dyld_add_image_hook --ignore-fn=get_or_create_key_element
stderr_filter: filter_verbose
post: perl ../../massif/ms_print --threshold=0 massif.out | ../../tests/filter_addresses
if (lc_n_chunks == 0) {
tl_assert(lc_chunks == NULL);
if (VG_(clo_verbosity) >= 1 && !VG_(clo_xml)) {
+ VG_(umsg)("\n");
VG_(umsg)("All heap blocks were freed -- no leaks are possible.\n");
}
return;
lc_markstack_top = -1;
// Verbosity.
- if (VG_(clo_verbosity) > 0 && !VG_(clo_xml))
- VG_(umsg)( "searching for pointers to %'d not-freed blocks.\n",
+ if (VG_(clo_verbosity) > 1 && !VG_(clo_xml)) {
+ VG_(umsg)( "\n" );
+ VG_(umsg)( "Searching for pointers to %'d not-freed blocks.\n",
lc_n_chunks );
+ }
// Scan the memory root-set, pushing onto the mark stack any blocks
// pointed to.
// from the root-set has been traced.
lc_process_markstack(/*clique*/-1);
- if (VG_(clo_verbosity) > 0 && !VG_(clo_xml))
- VG_(umsg)("checked %'lu bytes.\n", lc_scanned_szB);
+ if (VG_(clo_verbosity) > 1 && !VG_(clo_xml))
+ VG_(umsg)("Checked %'lu bytes.\n", lc_scanned_szB);
// Trace all the leaked blocks to determine which are directly leaked and
// which are indirectly leaked. For each Unreached block, push it onto
{
MC_(print_malloc_stats)();
- if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
- if (MC_(clo_leak_check) == LC_Off)
- VG_(message)(Vg_UserMsg,
- "For a detailed leak analysis, rerun with: --leak-check=yes\n");
+ if (MC_(clo_leak_check) != LC_Off) {
+ MC_(detect_memory_leaks)(1/*bogus ThreadId*/, MC_(clo_leak_check));
+ }
+ if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)
+ && MC_(clo_leak_check) == LC_Off) {
VG_(message)(Vg_UserMsg,
- "For counts of detected errors, rerun with: -v\n");
+ "For a detailed leak analysis, rerun with: --leak-check=yes\n");
}
+ if (VG_(clo_verbosity) >= 1 && !VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, "\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) {
"uninitialised values come from\n");
}
- if (MC_(clo_leak_check) != LC_Off)
- MC_(detect_memory_leaks)(1/*bogus ThreadId*/, MC_(clo_leak_check));
-
done_prof_mem();
- if (VG_(clo_verbosity) > 1) {
+ if (VG_(clo_stats)) {
SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
VG_(message)(Vg_DebugMsg,
nbytes += (ULong)mc->szB;
}
- VG_(message)(Vg_UserMsg,
- "malloc/free: in use at exit: %'llu bytes in %'lu blocks.\n",
+ VG_(umsg)(
+ "HEAP SUMMARY:\n"
+ );
+ VG_(umsg)(
+ " in use at exit: %'llu bytes in %'lu blocks.\n",
nbytes, nblocks
);
- VG_(message)(Vg_UserMsg,
- "malloc/free: %'lu allocs, %'lu frees, %'llu bytes allocated.\n",
+ VG_(umsg)(
+ " total heap usage: %'lu allocs, %'lu frees, "
+ "%'llu bytes allocated.\n",
cmalloc_n_mallocs,
cmalloc_n_frees, cmalloc_bs_mallocd
);
- if (VG_(clo_verbosity) > 1)
- VG_(message)(Vg_UserMsg, "\n");
}
/*--------------------------------------------------------------------*/
#! /bin/sh
./filter_stderr |
-sed -e "s/malloc\/free: in use at exit: [0-9,]* bytes in [0-9,]* blocks./malloc\/free: in use at exit: ... bytes in ... blocks./" \
- -e "s/malloc.free: [0-9,]* allocs, [0-9,]* frees, [0-9,]* bytes allocated./malloc\/free: ... allocs, ... frees, ... bytes allocated./"
+sed -e "s/in use at exit: [0-9,]* bytes in [0-9,]* blocks./in use at exit: ... bytes in ... blocks./" \
+ -e "s/total heap usage: [0-9,]* allocs, [0-9,]* frees, [0-9,]* bytes allocated./total heap usage: ... allocs, ... frees, ... bytes allocated./"
--help-debug show this message, plus debugging options
--version show version
-q --quiet run silently; only print error msgs
- -v --verbose be more verbose, incl counts of errors
+ -v --verbose be more verbose -- show misc extra info
--trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]
--child-silent-after-fork=no|yes omit child output between fork & exec? [no]
--track-fds=no|yes track open file descriptors? [no]
--help-debug show this message, plus debugging options
--version show version
-q --quiet run silently; only print error msgs
- -v --verbose be more verbose, incl counts of errors
+ -v --verbose be more verbose -- show misc extra info
--trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]
--child-silent-after-fork=no|yes omit child output between fork & exec? [no]
--track-fds=no|yes track open file descriptors? [no]
(none)
debugging options for all Valgrind tools:
+ --stats=no|yes show tool and core statistics [no]
-d show verbose debugging output
--sanity-level=<number> level of sanity checking to do [1]
--trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]