]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Allow tools to provide some statistics in suppression list produced at the end
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 17 Oct 2013 22:10:41 +0000 (22:10 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 17 Oct 2013 22:10:41 +0000 (22:10 +0000)
Option -v outputs a list of used suppressions. This only gives
the nr of times a suppression was used.
For a leak search, this only gives the nr of loss records that
have been suppressed, but it does not give additional needed details
to understand more precisely what has been suppressed
(i.e. nr of blocks and nr of bytes).

=> Add in the tool interface update_extra_suppression_use and
print_extra_suppression_info functions to allow the tool to record
additioonal use statistics for a suppression. These statistics
can be done depending on the error (and its data) which is suppressed.

Use this in memcheck for the leak suppressions, to maintain and output
the nr of blocks and bytes suppressed by a suppression during
the last leak search.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13651

18 files changed:
NEWS
coregrind/m_errormgr.c
coregrind/m_tooliface.c
coregrind/pub_core_tooliface.h
docs/xml/manual-core.xml
drd/drd_error.c
exp-sgcheck/pc_common.c
exp-sgcheck/pc_common.h
exp-sgcheck/pc_main.c
helgrind/hg_errors.c
helgrind/hg_errors.h
helgrind/hg_main.c
include/pub_tool_tooliface.h
memcheck/docs/mc-manual.xml
memcheck/mc_errors.c
memcheck/mc_include.h
memcheck/mc_leakcheck.c
memcheck/mc_main.c

diff --git a/NEWS b/NEWS
index 1e435c1c55db86c9cf64f4700e2422ce916536f1..dccbefe32d412a8199addb6d617f0fffd235afd2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,12 @@ Release 3.9.0 (?? ?????? 201?)
     for 'use after free' errors or to decrease Valgrind memory and/or cpu usage
     by recording less information for heap blocks.
 
+  - The list of used suppressions (shown when giving the -v option)
+    now shows for the leak suppressions how many blocks and bytes were
+    suppressed during the last leak search for each suppression.
+    The suppression count for a leak suppression shows the total nr
+    of loss records which were suppressed by this suppression.
+
 * ==================== OTHER CHANGES ====================
 
   - Option --merge-recursive-frames=<number> tells Valgrind to
@@ -63,6 +69,9 @@ Release 3.9.0 (?? ?????? 201?)
     'v.do expensive_sanity_check_general' that checks the sanity
     of various Valgrind aspects, including the Valgrind heap.
 
+  - The list of used suppressions (shown when giving the -v option)
+    now gives the filename and linenr where the suppression is defined.
+
   - remote debuginfo server + overhaul of debuginfo reading
 
   - some fixes for OSX 10.8
index 106bb8cd63d6ddf8ce5d633e9d897dac3b66f825..091fce5d6e7782e6fc3cf4f31cb2b60ee3f915a7 100644 (file)
@@ -913,12 +913,19 @@ static Bool show_used_suppressions ( void )
                                  "  </pair>\n",
                                  su->count, su->sname );
       } else {
+         HChar       xtra[256]; /* assumed big enough (is overrun-safe) */
+         Bool        anyXtra;
          // blank line before the first shown suppression, if any
          if (!any_supp)
             VG_(dmsg)("\n");
-         VG_(dmsg)("used_suppression: %6d %s %s:%d\n", su->count, su->sname,
+         VG_(memset)(xtra, 0, sizeof(xtra));
+         anyXtra = VG_TDICT_CALL(tool_print_extra_suppression_use,
+                                 su, xtra, sizeof(xtra));
+         vg_assert(xtra[sizeof(xtra)-1] == 0);
+         VG_(dmsg)("used_suppression: %6d %s %s:%d%s%s\n", su->count, su->sname,
                    VG_(clo_suppressions)[su->clo_suppressions_i],
-                   su->sname_lineno);
+                   su->sname_lineno,
+                   anyXtra ? " " : "", xtra);
       }
       any_supp = True;
    }
@@ -1659,8 +1666,9 @@ static Supp* is_suppressible_error ( Error* err )
    /* Conceptually, ip2fo contains an array of function names and an array of
       object names, corresponding to the array of IP of err->where.
       These names are just computed 'on demand' (so once maximum),
-      then stored (efficiently, avoiding too many allocs) in ip2fo to be re-usable
-      for the matching of the same IP with the next suppression pattern. 
+      then stored (efficiently, avoiding too many allocs) in ip2fo to be
+      re-usable for the matching of the same IP with the next suppression
+      pattern. 
 
       VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
       of its arguments. It will then pass it to the function
@@ -1687,7 +1695,10 @@ static Supp* is_suppressible_error ( Error* err )
       em_supplist_cmps++;
       if (supp_matches_error(su, err) 
           && supp_matches_callers(&ip2fo, su)) {
-         /* got a match.  Move this entry to the head of the list
+         /* got a match.  */
+         /* Inform the tool that err is suppressed by su. */
+         (void)VG_TDICT_CALL(tool_update_extra_suppression_use, err, su);
+         /* Move this entry to the head of the list
             in the hope of making future searches cheaper. */
          if (su_prev) {
             vg_assert(su_prev->next == su);
index bcf825530dc35ad6a5dfb6db1cd36c98a3cbdcff..24f0b3abe081f34d2ac54d8fa0597bfbcb700d3c 100644 (file)
@@ -234,7 +234,9 @@ void VG_(needs_tool_errors)(
    Bool (*read_extra) (Int, HChar**, SizeT*, Int*, Supp*),
    Bool (*matches)    (Error*, Supp*),
    const HChar* (*name) (Error*),
-   Bool (*get_xtra_si)(Error*,/*OUT*/HChar*,Int)
+   Bool (*get_xtra_si)(Error*,/*OUT*/HChar*,Int),
+   Bool (*print_xtra_su)(Supp*,/*OUT*/HChar*,Int),
+   void (*update_xtra_su)(Error*, Supp*)
 )
 {
    VG_(needs).tool_errors = True;
@@ -248,6 +250,8 @@ void VG_(needs_tool_errors)(
    VG_(tdict).tool_error_matches_suppression    = matches;
    VG_(tdict).tool_get_error_name               = name;
    VG_(tdict).tool_get_extra_suppression_info   = get_xtra_si;
+   VG_(tdict).tool_print_extra_suppression_use  = print_xtra_su;
+   VG_(tdict).tool_update_extra_suppression_use = update_xtra_su;
 }
 
 void VG_(needs_command_line_options)(
index 0946bff3dea79413c07e92cf6263d2b13fc6c4c7..bc11ffd002ea0948cfa344398f77de6481a9b586 100644 (file)
@@ -127,6 +127,8 @@ typedef struct {
    Bool  (*tool_error_matches_suppression)   (Error*, Supp*);
    const HChar* (*tool_get_error_name)       (Error*);
    Bool  (*tool_get_extra_suppression_info)  (Error*,/*OUT*/HChar*,Int);
+   Bool  (*tool_print_extra_suppression_use) (Supp*,/*OUT*/HChar*,Int);
+   void  (*tool_update_extra_suppression_use) (Error*, Supp*);
 
    // VG_(needs).superblock_discards
    void (*tool_discard_superblock_info)(Addr64, VexGuestExtents);
index 9e2708aeed8155a716bd020c13dfc11531090c46..4de9a04fa0ed73fe55a0f71ab4520c180d702cf3 100644 (file)
@@ -384,14 +384,17 @@ suppression mechanism is designed to allow precise yet flexible
 specification of errors to suppress.</para>
 
 <para>If you use the <option>-v</option> option, at the end of execution,
-Valgrind prints out one line for each used suppression, giving its name
-and the number of times it got used.  Here's the suppressions used by a
-run of <computeroutput>valgrind --tool=memcheck ls -l</computeroutput>:</para>
+Valgrind prints out one line for each used suppression, giving the number of times
+it got used, its name and the filename and line number where the suppression is
+defined. Depending on the suppression kind, the filename and line number are optionally
+followed by additional information (such as the number of blocks and bytes suppressed
+by a memcheck leak suppression). Here's the suppressions used by a
+run of <computeroutput>valgrind -v --tool=memcheck ls -l</computeroutput>:</para>
 
 <programlisting><![CDATA[
---27579-- supp: 1 socketcall.connect(serv_addr)/__libc_connect/__nscd_getgrgid_r
---27579-- supp: 1 socketcall.connect(serv_addr)/__libc_connect/__nscd_getpwuid_r
---27579-- supp: 6 strrchr/_dl_map_object_from_fd/_dl_map_object]]></programlisting>
+--1610-- used_suppression:      2 dl-hack3-cond-1 /usr/lib/valgrind/default.supp:1234
+--1610-- used_suppression:      2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a /usr/lib/valgrind/default.supp:1234
+]]></programlisting>
 
 <para>Multiple suppressions files are allowed.  By default, Valgrind
 uses <filename>$PREFIX/lib/valgrind/default.supp</filename>.  You can
index 8e8117412245d83202eccf15f5fa0662c9cf354e..12bfeff4915b6109970b2c69b04425cfeaf417f9 100644 (file)
@@ -608,6 +608,19 @@ Bool drd_get_extra_suppression_info(Error* e,
    return False;
 }
 
+static
+Bool drd_print_extra_suppression_use(Supp* su,
+                                     /*OUT*/HChar* buf, Int nBuf)
+{
+   return False;
+}
+
+static
+void  drd_update_extra_suppresion_use(Error* e, Supp* supp)
+{
+   return;
+}
+
 /** Tell the Valgrind core about DRD's error handlers. */
 void DRD_(register_error_handlers)(void)
 {
@@ -620,5 +633,7 @@ void DRD_(register_error_handlers)(void)
                           drd_read_extra_suppression_info,
                           drd_error_matches_suppression,
                           drd_get_error_name,
-                          drd_get_extra_suppression_info);
+                          drd_get_extra_suppression_info,
+                          drd_print_extra_suppression_use,
+                          drd_update_extra_suppresion_use);
 }
index f7b8006e1b2c0cc8b019447171e2243e33df6d87..1ea878415222c9c2bbbee5744173809aa4dd7a90 100644 (file)
@@ -793,6 +793,16 @@ Bool pc_get_extra_suppression_info ( Error* err,
    }
 }
 
+Bool pc_print_extra_suppression_use ( Supp* su,
+                                      /*OUT*/HChar* buf, Int nBuf )
+{
+   return False;
+}
+
+void pc_update_extra_suppression_use (Error* err, Supp* su)
+{
+   return;
+}
 
 /*--------------------------------------------------------------------*/
 /*--- end                                              pc_common.c ---*/
index 418f8b48a6e8c552d90dace700667715cf6d6466..3a0fb5ac17a196fd31fed054d272263e17dea042 100644 (file)
@@ -58,6 +58,9 @@ Bool pc_error_matches_suppression (Error* err, Supp* su);
 const HChar* pc_get_error_name ( Error* err );
 Bool pc_get_extra_suppression_info ( Error* err,
                                      /*OUT*/HChar* buf, Int nBuf );
+Bool pc_print_extra_suppression_use ( Supp* su,
+                                      /*OUT*/HChar* buf, Int nBuf );
+void pc_update_extra_suppression_use (Error* err, Supp* su);
 
 extern Bool h_clo_partial_loads_ok;
 /* extern Bool h_clo_lossage_check; */
index 5cfd94cf80e649dd36a09bdd91e0f4194812b1e9..84c1fce78a36673aa669c9cb89ee5e64b8907627 100644 (file)
@@ -105,7 +105,9 @@ static void pc_pre_clo_init(void)
                                  pc_read_extra_suppression_info,
                                  pc_error_matches_suppression,
                                  pc_get_error_name,
-                                 pc_get_extra_suppression_info);
+                                 pc_get_extra_suppression_info,
+                                 pc_print_extra_suppression_use,
+                                 pc_update_extra_suppression_use);
 
    VG_(needs_xml_output)        ();
 
index ffa31025cbc027b0f38771c55b137fc7442ca0f0..45ba4c81edb0db596b54094ac72804d0684712ff 100644 (file)
@@ -1396,6 +1396,19 @@ Bool HG_(get_extra_suppression_info) ( Error* err,
    return False;
 }
 
+Bool HG_(print_extra_suppression_use) ( Supp* su,
+                                        /*OUT*/HChar* buf, Int nBuf )
+{
+   /* Do nothing */
+   return False;
+}
+
+void HG_(update_extra_suppression_use) ( Error* err, Supp* su )
+{
+   /* Do nothing */
+   return;
+}
+
 
 /*--------------------------------------------------------------------*/
 /*--- end                                              hg_errors.c ---*/
index 03d88c19fcb0b5ffd49e658df6243a7b8ff6fd4c..a73fa151aa4f763fd149a8d04e35f5144bf194e8 100644 (file)
@@ -46,6 +46,9 @@ Bool  HG_(error_matches_suppression) ( Error* err, Supp* su );
 const HChar* HG_(get_error_name) ( Error* err );
 Bool  HG_(get_extra_suppression_info) ( Error* err,
                                         /*OUT*/HChar* buf, Int nBuf );
+Bool  HG_(print_extra_suppression_use) ( Supp* su,
+                                         /*OUT*/HChar* buf, Int nBuf );
+void  HG_(update_extra_suppression_use) ( Error* err, Supp* su );
 
 /* Functions for recording various kinds of errors. */
 void HG_(record_error_Race) ( Thread* thr, 
index 3d241bf9fa3966446d926f97754e71b3f9ae2841..40fbbe3fd8ea5be16e33df40b9808f1d2dc2f7a3 100644 (file)
@@ -5286,7 +5286,9 @@ static void hg_pre_clo_init ( void )
                                    HG_(read_extra_suppression_info),
                                    HG_(error_matches_suppression),
                                    HG_(get_error_name),
-                                   HG_(get_extra_suppression_info));
+                                   HG_(get_extra_suppression_info),
+                                   HG_(print_extra_suppression_use),
+                                   HG_(update_extra_suppression_use));
 
    VG_(needs_xml_output)          ();
 
index 3d43be8a54410c7622037187ba772d2abeeb5ddd..3d6fc9880e8459cce07868ca1e95af85003c7887 100644 (file)
@@ -343,7 +343,20 @@ extern void VG_(needs_tool_errors) (
    // do nothing, and return False.  This function is the inverse of
    // VG_(tdict).tool_read_extra_suppression_info().
    Bool (*print_extra_suppression_info)(Error* err,
-                                        /*OUT*/HChar* buf, Int nBuf)
+                                        /*OUT*/HChar* buf, Int nBuf),
+
+   // This is similar to print_extra_suppression_info, but is used
+   // to print information such as additional statistical counters
+   // as part of the used suppression list produced by -v.
+   Bool (*print_extra_suppression_use)(Supp* su,
+                                       /*OUT*/HChar* buf, Int nBuf),
+
+   // Called by error mgr once it has been established that err
+   // is suppressed by su. update_extra_suppression_use typically
+   // can be used to update suppression extra information such as
+   // some statistical counters that will be printed by
+   // print_extra_suppression_use.
+   void (*update_extra_suppression_use)(Error* err, Supp* su)
 );
 
 /* Is information kept by the tool about specific instructions or
index 4c6f862e8bfbacdd4f6be8e5216157f060f08f37..304407e4f24fe9d931f7da41893841d476fa4e4e 100644 (file)
@@ -1166,11 +1166,28 @@ leak kinds are matched by this suppression entry.
 <computeroutput>&lt;set&gt;</computeroutput> is specified similarly
 to the option <option>--show-leak-kinds</option>.
 If this optional extra line is not present, the suppression entry will match
-all leak kinds.
-</para>
+all leak kinds. </para>
 
 <para>The other memcheck error kinds do not have extra lines.</para>
 
+<para>
+If you give the <option>-v</option> option, Valgrind will print
+the list of used suppressions at the end of the execution.
+For a leak suppression, this output gives the number of different
+loss records that matches the suppression, the number of bytes
+and blocks suppressed by the suppressions.
+In case several leak searches are done, the number of bytes and blocks
+are reset to 0 before a new leak search. Note that the number of different
+loss records is not reset to 0.
+<para>In the example below, in the last leak search, 7 blocks and 96 bytes have
+been suppressed by the <option>some_leak_suppression</option>
+suppression. </para>
+<programlisting><![CDATA[
+--21041-- used_suppression:     10 some_other_leak_suppression s.supp:14 suppressed: 12,400 bytes in 1 blocks
+--21041-- used_suppression:     39 some_leak_suppression s.supp:2 suppressed: 96 bytes in 7 blocks
+]]></programlisting>
+</para>
+
 <para>The first line of the calling context: for <varname>ValueN</varname>
 and <varname>AddrN</varname> errors, it is either the name of the function
 in which the error occurred, or, failing that, the full path of the
index b9aa00a39edb11210c7f3d61a0491d9b3d692c4d..b4b82a83f42163ca67209439871c8757cddc1716 100644 (file)
@@ -1532,6 +1532,14 @@ typedef struct _MC_LeakSuppExtra MC_LeakSuppExtra;
 
 struct _MC_LeakSuppExtra {
    UInt match_leak_kinds;
+
+   /* Maintains nr of blocks and bytes suppressed with this suppression
+      during the leak search identified by leak_search_gen.
+      blocks_suppressed and bytes_suppressed are reset to 0 when
+      used the first time during a leak search. */
+   SizeT blocks_suppressed;
+   SizeT bytes_suppressed;
+   UInt  leak_search_gen;
 };
 
 Bool MC_(read_extra_suppression_info) ( Int fd, HChar** bufpp,
@@ -1549,6 +1557,9 @@ Bool MC_(read_extra_suppression_info) ( Int fd, HChar** bufpp,
       MC_LeakSuppExtra* lse;
       lse = VG_(malloc)("mc.resi.2", sizeof(MC_LeakSuppExtra));
       lse->match_leak_kinds = RallS;
+      lse->blocks_suppressed = 0;
+      lse->bytes_suppressed = 0;
+      lse->leak_search_gen = 0;
       VG_(set_supp_extra)(su, lse); // By default, all kinds will match.
       eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
       if (eof) return True; // old LeakSupp style, no match-leak-kinds line.
@@ -1617,6 +1628,13 @@ Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
       case LeakSupp:
          if (ekind == Err_Leak) {
             MC_LeakSuppExtra* lse = (MC_LeakSuppExtra*) VG_(get_supp_extra)(su);
+            if (lse->leak_search_gen != MC_(leak_search_gen)) {
+               // First time we see this suppression during this leak search.
+               // => reset the counters to 0.
+               lse->blocks_suppressed = 0;
+               lse->bytes_suppressed = 0;
+               lse->leak_search_gen = MC_(leak_search_gen);
+            }
             return RiS(extra->Err.Leak.lr->key.state, lse->match_leak_kinds);
          } else
             return False;
@@ -1695,6 +1713,37 @@ Bool MC_(get_extra_suppression_info) ( Error* err,
    }
 }
 
+Bool MC_(print_extra_suppression_use) ( Supp *su,
+                                        /*OUT*/HChar *buf, Int nBuf )
+{
+   if (VG_(get_supp_kind)(su) == LeakSupp) {
+      MC_LeakSuppExtra *lse = (MC_LeakSuppExtra*) VG_(get_supp_extra) (su);
+
+      if (lse->leak_search_gen == MC_(leak_search_gen)
+          && lse->blocks_suppressed > 0) {
+         VG_(snprintf) (buf, nBuf-1, 
+                        "suppressed: %'lu bytes in %'lu blocks",
+                        lse->bytes_suppressed,
+                        lse->blocks_suppressed);
+         return True;
+      } else
+         return False;
+   } else
+      return False;
+}
+
+void MC_(update_extra_suppression_use) ( Error* err, Supp* su)
+{
+   if (VG_(get_supp_kind)(su) == LeakSupp) {
+      MC_LeakSuppExtra *lse = (MC_LeakSuppExtra*) VG_(get_supp_extra) (su);
+      MC_Error* extra = VG_(get_error_extra)(err);
+
+      tl_assert (lse->leak_search_gen = MC_(leak_search_gen));
+      lse->blocks_suppressed += extra->Err.Leak.lr->num_blocks;
+      lse->bytes_suppressed 
+         += extra->Err.Leak.lr->szB + extra->Err.Leak.lr->indirect_szB;
+   }
+}
 
 /*--------------------------------------------------------------------*/
 /*--- end                                              mc_errors.c ---*/
index 46e824d148e2b8f357175eec4c2ba707023ba122..a1c9a3d54bec73fa7d7c092abb1ff3fb2c904e3b 100644 (file)
@@ -351,6 +351,10 @@ typedef
 
 void MC_(detect_memory_leaks) ( ThreadId tid, LeakCheckParams * lcp);
 
+// Each time a leak search is done, the leak search generation
+// MC_(leak_search_gen) is incremented.
+extern UInt MC_(leak_search_gen);
+
 // maintains the lcp.deltamode given in the last call to detect_memory_leaks
 extern LeakCheckDeltaMode MC_(detect_memory_leaks_last_delta_mode);
 
@@ -404,6 +408,9 @@ Bool MC_(error_matches_suppression) ( Error* err, Supp* su );
 
 Bool MC_(get_extra_suppression_info) ( Error* err,
                                        /*OUT*/HChar* buf, Int nBuf );
+Bool MC_(print_extra_suppression_use) ( Supp* su,
+                                        /*OUT*/HChar* buf, Int nBuf );
+void MC_(update_extra_suppression_use) ( Error* err, Supp* su );
 
 const HChar* MC_(get_error_name) ( Error* err );
 
index af0bfcf169a8332357bed1ac6c137d064211118c..8bfd02ae9debc5f04b6e2f9116c97557ecf2ae95 100644 (file)
@@ -474,6 +474,10 @@ static UInt detect_memory_leaks_last_heuristics;
 // The below avoids replicating the delta_mode in each LossRecord.
 LeakCheckDeltaMode MC_(detect_memory_leaks_last_delta_mode);
 
+// Each leak search run increments the below generation counter.
+// A used suppression during a leak search will contain this
+// generation number.
+UInt MC_(leak_search_gen);
 
 // Records chunks that are currently being processed.  Each element in the
 // stack is an index into lc_chunks and lc_extras.  Its size is
@@ -1646,7 +1650,7 @@ void MC_(detect_memory_leaks) ( ThreadId tid, LeakCheckParams* lcp)
    // before checking for (smaller) page skipping.
    tl_assert((SM_SIZE % VKI_PAGE_SIZE) == 0);
 
-
+   MC_(leak_search_gen)++;
    MC_(detect_memory_leaks_last_delta_mode) = lcp->deltamode;
    detect_memory_leaks_last_heuristics = lcp->heuristics;
 
index c3891b8270e1ff4d78efd0cf02ec639e7ec4444f..f6e1e01020bf27179b578308b5ad40a818044364 100644 (file)
@@ -6699,7 +6699,9 @@ static void mc_pre_clo_init(void)
                                    MC_(read_extra_suppression_info),
                                    MC_(error_matches_suppression),
                                    MC_(get_error_name),
-                                   MC_(get_extra_suppression_info));
+                                   MC_(get_extra_suppression_info),
+                                   MC_(print_extra_suppression_use),
+                                   MC_(update_extra_suppression_use));
    VG_(needs_libc_freeres)        ();
    VG_(needs_command_line_options)(mc_process_cmd_line_options,
                                    mc_print_usage,