blob: df0e061809d860000d0a76d5ad06efd31f84db07 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
sewardj267100d2005-04-24 12:33:12 +00003/*--- Management of error messages. m_errormgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
sewardj4d474d02008-02-11 11:34:59 +000010 Copyright (C) 2000-2008 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
njn24a6efb2005-06-20 03:36:51 +000033#include "pub_core_threadstate.h" // For VG_N_THREADS
njn75b65aa2005-06-19 19:25:44 +000034#include "pub_core_debugger.h"
njnea27e462005-05-31 02:38:09 +000035#include "pub_core_debuginfo.h"
njnd2b17112005-04-19 04:10:25 +000036#include "pub_core_errormgr.h"
njnd01fef72005-03-25 23:35:48 +000037#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000038#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000039#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000040#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000041#include "pub_core_libcprint.h"
njn24a6efb2005-06-20 03:36:51 +000042#include "pub_core_libcproc.h" // For VG_(getpid)()
sewardjd7a02db2008-12-12 08:07:49 +000043#include "pub_core_seqmatch.h"
njnaf1d7df2005-06-11 01:31:52 +000044#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000045#include "pub_core_options.h"
njnd0d7c1f2005-06-21 00:33:19 +000046#include "pub_core_stacktrace.h"
njn43b9a8a2005-05-10 04:37:01 +000047#include "pub_core_tooliface.h"
njn24a6efb2005-06-20 03:36:51 +000048#include "pub_core_translate.h" // for VG_(translate)()
sewardjde4a1d02002-03-22 01:27:54 +000049
50/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000051/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000052/*------------------------------------------------------------*/
53
njn14319cc2005-03-13 06:26:22 +000054/* After this many different unsuppressed errors have been observed,
55 be more conservative about collecting new ones. */
sewardj1d1a2262005-10-20 01:57:29 +000056#define M_COLLECT_ERRORS_SLOWLY_AFTER 100
njn14319cc2005-03-13 06:26:22 +000057
58/* After this many different unsuppressed errors have been observed,
59 stop collecting errors at all, and tell the user their program is
60 evidently a steaming pile of camel dung. */
sewardj1d1a2262005-10-20 01:57:29 +000061#define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
njn14319cc2005-03-13 06:26:22 +000062
63/* After this many total errors have been observed, stop collecting
64 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
sewardj513646f2006-05-12 23:12:30 +000065#define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
njn14319cc2005-03-13 06:26:22 +000066
sewardjde4a1d02002-03-22 01:27:54 +000067/* The list of error contexts found, both suppressed and unsuppressed.
68 Initially empty, and grows as errors are detected. */
njn695c16e2005-03-27 03:40:28 +000069static Error* errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000070
71/* The list of suppression directives, as read from the specified
sewardj8a7d4e42006-10-17 01:41:17 +000072 suppressions file. Note that the list gets rearranged as a result
73 of the searches done by is_suppressible_error(). */
njn695c16e2005-03-27 03:40:28 +000074static Supp* suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000075
76/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000077static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000078
79/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000080static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000081
82/* forwards ... */
njn810086f2002-11-14 12:42:47 +000083static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000084
sewardjb5f6f512005-03-10 23:59:00 +000085static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000086
sewardj8a7d4e42006-10-17 01:41:17 +000087/* Stats: number of searches of the error list initiated. */
88static UWord em_errlist_searches = 0;
89
90/* Stats: number of comparisons done during error list
91 searching. */
92static UWord em_errlist_cmps = 0;
93
94/* Stats: number of searches of the suppression list initiated. */
95static UWord em_supplist_searches = 0;
96
97/* Stats: number of comparisons done during suppression list
98 searching. */
99static UWord em_supplist_cmps = 0;
100
sewardjde4a1d02002-03-22 01:27:54 +0000101/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +0000102/*--- Error type ---*/
103/*------------------------------------------------------------*/
104
nethercote4a184902004-08-02 12:21:09 +0000105/* Errors. Extensible (via the 'extra' field). Tools can use a normal
njn02bc4b82005-05-15 17:28:26 +0000106 enum (with element values in the normal range (0..)) for 'ekind'.
nethercote4a184902004-08-02 12:21:09 +0000107 Functions for getting/setting the tool-relevant fields are in
njnc7561b92005-06-19 01:24:32 +0000108 include/pub_tool_errormgr.h.
nethercote4a184902004-08-02 12:21:09 +0000109
110 When errors are found and recorded with VG_(maybe_record_error)(), all
111 the tool must do is pass in the four parameters; core will
112 allocate/initialise the error record.
113*/
114struct _Error {
115 struct _Error* next;
sewardjdbada272005-07-02 21:16:30 +0000116 // Unique tag. This gives the error a unique identity (handle) by
117 // which it can be referred to afterwords. Currently only used for
118 // XML printing.
119 UInt unique;
nethercote4a184902004-08-02 12:21:09 +0000120 // NULL if unsuppressed; or ptr to suppression record.
121 Supp* supp;
122 Int count;
nethercote4a184902004-08-02 12:21:09 +0000123
124 // The tool-specific part
sewardjb8b79ad2008-03-03 01:35:41 +0000125 ThreadId tid; // Initialised by core
nethercote4a184902004-08-02 12:21:09 +0000126 ExeContext* where; // Initialised by core
njnd2b17112005-04-19 04:10:25 +0000127 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
nethercote4a184902004-08-02 12:21:09 +0000128 Addr addr; // Used frequently
129 Char* string; // Used frequently
130 void* extra; // For any tool-specific extras
131};
132
sewardjb8b79ad2008-03-03 01:35:41 +0000133
nethercote4a184902004-08-02 12:21:09 +0000134ExeContext* VG_(get_error_where) ( Error* err )
135{
136 return err->where;
137}
138
139ErrorKind VG_(get_error_kind) ( Error* err )
140{
141 return err->ekind;
142}
143
144Addr VG_(get_error_address) ( Error* err )
145{
146 return err->addr;
147}
148
149Char* VG_(get_error_string) ( Error* err )
150{
151 return err->string;
152}
153
154void* VG_(get_error_extra) ( Error* err )
155{
156 return err->extra;
157}
158
nethercotef2b11482004-08-02 12:36:01 +0000159UInt VG_(get_n_errs_found)( void )
160{
161 return n_errs_found;
162}
163
nethercote4a184902004-08-02 12:21:09 +0000164/*------------------------------------------------------------*/
165/*--- Suppression type ---*/
166/*------------------------------------------------------------*/
167
168/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
169 * effectively extend it by defining their own enums in the (0..) range. */
170typedef
171 enum {
njna86f29e2006-12-14 02:55:58 +0000172 // Nb: thread errors are a relic of the time when Valgrind's core
173 // could detect them. This example is left commented-out as an
174 // example should new core errors ever be added.
175 ThreadSupp = -1, /* Matches ThreadErr */
nethercote4a184902004-08-02 12:21:09 +0000176 }
177 CoreSuppKind;
178
sewardjb5f6f512005-03-10 23:59:00 +0000179/* Max number of callers for context in a suppression. */
180#define VG_MAX_SUPP_CALLERS 24
181
nethercote4a184902004-08-02 12:21:09 +0000182/* For each caller specified for a suppression, record the nature of
183 the caller name. Not of interest to tools. */
184typedef
185 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000186 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000187 ObjName, /* Name is of an shared object file. */
sewardj5e519302008-11-03 23:10:25 +0000188 FunName, /* Name is of a function. */
189 DotDotDot /* Frame-level wildcard */
nethercote4a184902004-08-02 12:21:09 +0000190 }
191 SuppLocTy;
192
sewardjb5f6f512005-03-10 23:59:00 +0000193typedef
194 struct {
195 SuppLocTy ty;
sewardj5e519302008-11-03 23:10:25 +0000196 Char* name; /* NULL for NoName and DotDotDot */
sewardjb5f6f512005-03-10 23:59:00 +0000197 }
198 SuppLoc;
199
nethercote4a184902004-08-02 12:21:09 +0000200/* Suppressions. Tools can get/set tool-relevant parts with functions
njnc7561b92005-06-19 01:24:32 +0000201 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000202 Tools can use a normal enum (with element values in the normal range
njn02bc4b82005-05-15 17:28:26 +0000203 (0..)) for 'skind'. */
nethercote4a184902004-08-02 12:21:09 +0000204struct _Supp {
205 struct _Supp* next;
206 Int count; // The number of times this error has been suppressed.
207 Char* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000208
209 // Length of 'callers'
210 Int n_callers;
211 // Array of callers, for matching stack traces. First one (name of fn
212 // where err occurs) is mandatory; rest are optional.
213 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000214
215 /* The tool-specific part */
216 SuppKind skind; // What kind of suppression. Must use the range (0..).
217 Char* string; // String -- use is optional. NULL by default.
218 void* extra; // Anything else -- use is optional. NULL by default.
219};
220
221SuppKind VG_(get_supp_kind) ( Supp* su )
222{
223 return su->skind;
224}
225
226Char* VG_(get_supp_string) ( Supp* su )
227{
228 return su->string;
229}
230
231void* VG_(get_supp_extra) ( Supp* su )
232{
233 return su->extra;
234}
235
236
237void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
238{
239 su->skind = skind;
240}
241
242void VG_(set_supp_string) ( Supp* su, Char* string )
243{
244 su->string = string;
245}
246
247void VG_(set_supp_extra) ( Supp* su, void* extra )
248{
249 su->extra = extra;
250}
251
252
253/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000254/*--- Helper fns ---*/
255/*------------------------------------------------------------*/
256
njn0087c502005-07-01 04:15:36 +0000257// Only show core errors if the tool wants to, we're not running with -q,
258// and were not outputting XML.
259Bool VG_(showing_core_errors)(void)
260{
261 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
262}
263
sewardjc6f43dd2007-04-07 14:46:13 +0000264/* Compare errors, to detect duplicates. */
njn810086f2002-11-14 12:42:47 +0000265static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000266{
njn810086f2002-11-14 12:42:47 +0000267 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000268 return False;
njn25e49d8e72002-09-23 09:36:25 +0000269 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000270 return False;
271
njn810086f2002-11-14 12:42:47 +0000272 switch (e1->ekind) {
njna86f29e2006-12-14 02:55:58 +0000273 //(example code, see comment on CoreSuppKind above)
274 //case ThreadErr:
275 // vg_assert(VG_(needs).core_errors);
276 // return <something>
sewardjde4a1d02002-03-22 01:27:54 +0000277 default:
njn51d827b2005-05-09 01:02:08 +0000278 if (VG_(needs).tool_errors) {
279 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
280 } else {
njn95ec8702004-11-22 16:46:13 +0000281 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000282 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000283 e1->ekind);
njn67993252004-11-22 18:02:32 +0000284 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000285 }
sewardjde4a1d02002-03-22 01:27:54 +0000286 }
287}
288
njnb0eb66e2005-07-10 16:57:24 +0000289static void pp_Error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000290{
sewardj71bc3cb2005-05-19 00:25:45 +0000291 if (VG_(clo_xml)) {
292 VG_(message)(Vg_UserMsg, "<error>");
sewardjdbada272005-07-02 21:16:30 +0000293 VG_(message)(Vg_UserMsg, " <unique>0x%x</unique>",
294 err->unique);
sewardj71bc3cb2005-05-19 00:25:45 +0000295 VG_(message)(Vg_UserMsg, " <tid>%d</tid>", err->tid);
296 }
297
298 if (!VG_(clo_xml)) {
sewardjadb102f2007-11-09 23:21:44 +0000299 if (VG_(tdict).tool_show_ThreadIDs_for_errors
300 && err->tid > 0 && err->tid != last_tid_printed) {
sewardj71bc3cb2005-05-19 00:25:45 +0000301 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
302 last_tid_printed = err->tid;
303 }
sewardjb5f6f512005-03-10 23:59:00 +0000304 }
njn25e49d8e72002-09-23 09:36:25 +0000305
njn810086f2002-11-14 12:42:47 +0000306 switch (err->ekind) {
njna86f29e2006-12-14 02:55:58 +0000307 //(example code, see comment on CoreSuppKind above)
308 //case ThreadErr:
309 // vg_assert(VG_(needs).core_errors);
310 // VG_(tm_error_print)(err);
311 // break;
sewardjde4a1d02002-03-22 01:27:54 +0000312 default:
njn95ec8702004-11-22 16:46:13 +0000313 if (VG_(needs).tool_errors)
njn51d827b2005-05-09 01:02:08 +0000314 VG_TDICT_CALL( tool_pp_Error, err );
njn25e49d8e72002-09-23 09:36:25 +0000315 else {
njn95ec8702004-11-22 16:46:13 +0000316 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000317 "probably needs to be set?\n",
njn810086f2002-11-14 12:42:47 +0000318 err->ekind);
njn67993252004-11-22 18:02:32 +0000319 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000320 }
sewardjde4a1d02002-03-22 01:27:54 +0000321 }
sewardj71bc3cb2005-05-19 00:25:45 +0000322
323 if (VG_(clo_xml))
324 VG_(message)(Vg_UserMsg, "</error>");
sewardjde4a1d02002-03-22 01:27:54 +0000325}
326
nethercote04d0fbc2004-01-26 16:48:06 +0000327/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000328 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000329Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000330{
331 Char ch, ch2;
332 Int res;
333
njn43c799e2003-04-08 00:08:52 +0000334 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000335 return False;
336
337 VG_(message)(Vg_UserMsg, "");
338
339 again:
340 VG_(printf)(
341 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000342 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
343 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000344 );
345
sewardj6024b212003-07-13 10:54:33 +0000346 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000347 if (res != 1) goto ioerror;
348 /* res == 1 */
349 if (ch == '\n') return False;
350 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
351 && ch != 'C' && ch != 'c') goto again;
352
sewardj6024b212003-07-13 10:54:33 +0000353 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000354 if (res != 1) goto ioerror;
355 if (ch2 != '\n') goto again;
356
njn43c799e2003-04-08 00:08:52 +0000357 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000358 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000359 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000360 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000361 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000362 vg_assert(ch == 'c' || ch == 'C');
363
364 ioerror:
njn43c799e2003-04-08 00:08:52 +0000365 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000366 return False;
367}
368
369
sewardjb5f6f512005-03-10 23:59:00 +0000370/* Construct an error */
njn25e49d8e72002-09-23 09:36:25 +0000371static __inline__
njn72718642003-07-24 08:45:32 +0000372void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
373 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000374{
sewardjdbada272005-07-02 21:16:30 +0000375 /* DO NOT MAKE unique_counter NON-STATIC */
376 static UInt unique_counter = 0;
377
njnca82cc02004-11-22 17:18:48 +0000378 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000379
njn810086f2002-11-14 12:42:47 +0000380 /* Core-only parts */
sewardjdbada272005-07-02 21:16:30 +0000381 err->unique = unique_counter++;
njn25e49d8e72002-09-23 09:36:25 +0000382 err->next = NULL;
383 err->supp = NULL;
384 err->count = 1;
njn72718642003-07-24 08:45:32 +0000385 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000386 if (NULL == where)
sewardjadb102f2007-11-09 23:21:44 +0000387 err->where = VG_(record_ExeContext)( tid, 0 );
njn43c799e2003-04-08 00:08:52 +0000388 else
389 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000390
nethercote996901a2004-08-03 13:29:09 +0000391 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000392 err->ekind = ekind;
393 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000394 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000395 err->string = s;
396
njn25e49d8e72002-09-23 09:36:25 +0000397 /* sanity... */
njn72718642003-07-24 08:45:32 +0000398 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000399}
400
njn83f9e792005-06-11 05:04:09 +0000401#define ERRTXT_LEN 4096
402
njnf4261312005-03-20 23:45:36 +0000403static void printSuppForIp(UInt n, Addr ip)
404{
njn83f9e792005-06-11 05:04:09 +0000405 static UChar buf[ERRTXT_LEN];
njnf4261312005-03-20 23:45:36 +0000406
sewardj39745be2006-12-06 03:35:38 +0000407 if ( VG_(get_fnname_Z_demangle_only) (ip, buf, ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000408 VG_(printf)(" fun:%s\n", buf);
njn83f9e792005-06-11 05:04:09 +0000409 } else if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000410 VG_(printf)(" obj:%s\n", buf);
411 } else {
njn966d6632005-08-18 15:49:21 +0000412 VG_(printf)(" obj:*\n");
njnf4261312005-03-20 23:45:36 +0000413 }
414}
415
nethercote10d481a2004-01-25 20:33:53 +0000416static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000417{
njn43c799e2003-04-08 00:08:52 +0000418 ExeContext* ec = VG_(get_error_where)(err);
419 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000420
sewardjb5f6f512005-03-10 23:59:00 +0000421 /* At most VG_MAX_SUPP_CALLERS names */
422 if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
njn43c799e2003-04-08 00:08:52 +0000423 vg_assert(stop_at > 0);
424
njna86f29e2006-12-14 02:55:58 +0000425 //(example code, see comment on CoreSuppKind above)
426 if (0) {
427 //if (0) ThreadErr == err->ekind) {
428 // VG_(printf)("{\n");
429 // VG_(printf)(" <insert a suppression name here>\n");
430 // VG_(printf)(" core:Thread\n");
njn6a230532003-07-21 10:38:23 +0000431
432 } else {
njn51d827b2005-05-09 01:02:08 +0000433 Char* name = VG_TDICT_CALL(tool_get_error_name, err);
njn6a230532003-07-21 10:38:23 +0000434 if (NULL == name) {
435 VG_(message)(Vg_UserMsg,
njnf7ba7032005-12-19 19:40:12 +0000436 "(%s does not allow error to be suppressed)",
437 VG_(details).name);
njn6a230532003-07-21 10:38:23 +0000438 return;
439 }
njnf7ba7032005-12-19 19:40:12 +0000440 VG_(printf)("{\n");
441 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000442 VG_(printf)(" %s:%s\n", VG_(details).name, name);
njn51d827b2005-05-09 01:02:08 +0000443 VG_TDICT_CALL(tool_print_extra_suppression_info, err);
njn6a230532003-07-21 10:38:23 +0000444 }
njn43c799e2003-04-08 00:08:52 +0000445
njnf4261312005-03-20 23:45:36 +0000446 // Print stack trace elements
sewardj7cf4e6b2008-05-01 20:24:26 +0000447 VG_(apply_StackTrace)(printSuppForIp,
448 VG_(get_ExeContext_StackTrace)(ec), stop_at);
njn43c799e2003-04-08 00:08:52 +0000449
450 VG_(printf)("}\n");
451}
452
njnb4aee052003-04-15 14:09:58 +0000453static
nethercote04d0fbc2004-01-26 16:48:06 +0000454void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000455{
sewardjd153fae2005-01-10 17:24:47 +0000456 Bool still_noisy = True;
457
nethercote04d0fbc2004-01-26 16:48:06 +0000458 /* Perhaps we want a debugger attach at this point? */
459 if (allow_db_attach &&
njnd2b17112005-04-19 04:10:25 +0000460 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
461 {
sewardj7d7ddd22007-11-19 02:01:01 +0000462 if (0) VG_(printf)("starting debugger\n");
nethercote04d0fbc2004-01-26 16:48:06 +0000463 VG_(start_debugger)( err->tid );
njnd2b17112005-04-19 04:10:25 +0000464 }
njn43c799e2003-04-08 00:08:52 +0000465 /* Or maybe we want to generate the error's suppression? */
sewardjd153fae2005-01-10 17:24:47 +0000466 if (VG_(clo_gen_suppressions) == 2
467 || (VG_(clo_gen_suppressions) == 1
njnd2b17112005-04-19 04:10:25 +0000468 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
sewardjd153fae2005-01-10 17:24:47 +0000469 ) {
nethercote42602b12004-01-25 19:30:29 +0000470 gen_suppression(err);
njn43c799e2003-04-08 00:08:52 +0000471 }
sewardjc0c67032006-06-25 12:18:20 +0000472 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
473 VG_(clo_gen_suppressions) = 0;
njn43c799e2003-04-08 00:08:52 +0000474}
475
476/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
477 just for pretty printing purposes. */
478static Bool is_first_shown_context = True;
479
njnfb289bc2007-01-12 23:59:50 +0000480static Int n_errs_shown = 0;
481
njn25e49d8e72002-09-23 09:36:25 +0000482/* Top-level entry point to the error management subsystem.
483 All detected errors are notified here; this routine decides if/when the
484 user should see the error. */
njn72718642003-07-24 08:45:32 +0000485void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000486 ErrorKind ekind, Addr a, Char* s, void* extra )
487{
njn810086f2002-11-14 12:42:47 +0000488 Error err;
489 Error* p;
490 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000491 UInt extra_size;
njn695c16e2005-03-27 03:40:28 +0000492 VgRes exe_res = Vg_MedRes;
493 static Bool stopping_message = False;
494 static Bool slowdown_message = False;
sewardjde4a1d02002-03-22 01:27:54 +0000495
njn14319cc2005-03-13 06:26:22 +0000496 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
497 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000498 have been found, just refuse to collect any more. This stops
499 the burden of the error-management system becoming excessive in
500 extremely buggy programs, although it does make it pretty
501 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000502 if (VG_(clo_error_limit)
njn695c16e2005-03-27 03:40:28 +0000503 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
sewardj8a051722005-06-30 00:10:16 +0000504 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
505 && !VG_(clo_xml)) {
sewardjde4a1d02002-03-22 01:27:54 +0000506 if (!stopping_message) {
507 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000508
njn695c16e2005-03-27 03:40:28 +0000509 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardjf2537be2002-04-24 21:03:47 +0000510 VG_(message)(Vg_UserMsg,
511 "More than %d different errors detected. "
512 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000513 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000514 } else {
515 VG_(message)(Vg_UserMsg,
516 "More than %d total errors detected. "
517 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000518 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000519 }
520
sewardjde4a1d02002-03-22 01:27:54 +0000521 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000522 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000523 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000524 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000525 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000526 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000527 VG_(message)(Vg_UserMsg,
528 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000529 VG_(message)(Vg_UserMsg, "");
530 stopping_message = True;
531 }
532 return;
533 }
534
njn14319cc2005-03-13 06:26:22 +0000535 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000536 been found, be much more conservative about collecting new
537 ones. */
sewardj8a051722005-06-30 00:10:16 +0000538 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
539 && !VG_(clo_xml)) {
njn25e49d8e72002-09-23 09:36:25 +0000540 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000541 if (!slowdown_message) {
542 VG_(message)(Vg_UserMsg, "");
543 VG_(message)(Vg_UserMsg,
544 "More than %d errors detected. Subsequent errors",
njn14319cc2005-03-13 06:26:22 +0000545 M_COLLECT_ERRORS_SLOWLY_AFTER);
sewardjde4a1d02002-03-22 01:27:54 +0000546 VG_(message)(Vg_UserMsg,
547 "will still be recorded, but in less detail than before.");
548 slowdown_message = True;
549 }
550 }
551
njn25e49d8e72002-09-23 09:36:25 +0000552 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000553 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000554
555 /* First, see if we've got an error record matching this one. */
sewardj8a7d4e42006-10-17 01:41:17 +0000556 em_errlist_searches++;
557 p = errors;
558 p_prev = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000559 while (p != NULL) {
sewardj8a7d4e42006-10-17 01:41:17 +0000560 em_errlist_cmps++;
njn810086f2002-11-14 12:42:47 +0000561 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000562 /* Found it. */
563 p->count++;
564 if (p->supp != NULL) {
565 /* Deal correctly with suppressed errors. */
566 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000567 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000568 } else {
nethercotef2b11482004-08-02 12:36:01 +0000569 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000570 }
571
572 /* Move p to the front of the list so that future searches
573 for it are faster. */
574 if (p_prev != NULL) {
575 vg_assert(p_prev->next == p);
njn695c16e2005-03-27 03:40:28 +0000576 p_prev->next = p->next;
577 p->next = errors;
578 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000579 }
sewardj7ebf7c32003-07-24 21:29:40 +0000580
sewardjde4a1d02002-03-22 01:27:54 +0000581 return;
582 }
583 p_prev = p;
584 p = p->next;
585 }
586
587 /* Didn't see it. Copy and add. */
588
njn43c799e2003-04-08 00:08:52 +0000589 /* OK, we're really going to collect it. The context is on the stack and
590 will disappear shortly, so we must copy it. First do the main
njn02bc4b82005-05-15 17:28:26 +0000591 (non-'extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000592
njn02bc4b82005-05-15 17:28:26 +0000593 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
njn51d827b2005-05-09 01:02:08 +0000594 is for when there are more details to fill in which take time to work
595 out but don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000596 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000597 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000598
njn02bc4b82005-05-15 17:28:26 +0000599 Then, if there is an 'extra' part, copy it too, using the size that
njn51d827b2005-05-09 01:02:08 +0000600 VG_(tdict).tool_update_extra returned. Also allow for people using
601 the void* extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000602 */
603
604 /* copy main part */
sewardj9c606bd2008-09-18 18:12:50 +0000605 p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000606 *p = err;
njn43c799e2003-04-08 00:08:52 +0000607
njn02bc4b82005-05-15 17:28:26 +0000608 /* update 'extra' */
sewardjb5f6f512005-03-10 23:59:00 +0000609 switch (ekind) {
njna86f29e2006-12-14 02:55:58 +0000610 //(example code, see comment on CoreSuppKind above)
611 //case ThreadErr:
612 // vg_assert(VG_(needs).core_errors);
613 // extra_size = <something>
614 // break;
sewardjb5f6f512005-03-10 23:59:00 +0000615 default:
616 vg_assert(VG_(needs).tool_errors);
njn51d827b2005-05-09 01:02:08 +0000617 extra_size = VG_TDICT_CALL(tool_update_extra, p);
sewardjb5f6f512005-03-10 23:59:00 +0000618 break;
619 }
njn43c799e2003-04-08 00:08:52 +0000620
njn02bc4b82005-05-15 17:28:26 +0000621 /* copy block pointed to by 'extra', if there is one */
sewardjb5f6f512005-03-10 23:59:00 +0000622 if (NULL != p->extra && 0 != extra_size) {
sewardj9c606bd2008-09-18 18:12:50 +0000623 void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
sewardjb5f6f512005-03-10 23:59:00 +0000624 VG_(memcpy)(new_extra, p->extra, extra_size);
625 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000626 }
627
njn695c16e2005-03-27 03:40:28 +0000628 p->next = errors;
njn25e49d8e72002-09-23 09:36:25 +0000629 p->supp = is_suppressible_error(&err);
njn695c16e2005-03-27 03:40:28 +0000630 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000631 if (p->supp == NULL) {
nethercotef2b11482004-08-02 12:36:01 +0000632 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000633 if (!is_first_shown_context)
634 VG_(message)(Vg_UserMsg, "");
njnb0eb66e2005-07-10 16:57:24 +0000635 pp_Error(p);
sewardjde4a1d02002-03-22 01:27:54 +0000636 is_first_shown_context = False;
njn695c16e2005-03-27 03:40:28 +0000637 n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000638 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000639 } else {
nethercotef2b11482004-08-02 12:36:01 +0000640 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000641 p->supp->count++;
642 }
643}
644
njn43c799e2003-04-08 00:08:52 +0000645/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000646 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000647 guaranteed to only happen once. This avoids all the recording and
648 comparing stuff. But they can be suppressed; returns True if it is
njn02bc4b82005-05-15 17:28:26 +0000649 suppressed. Bool 'print_error' dictates whether to print the error.
650 Bool 'count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000651*/
njn72718642003-07-24 08:45:32 +0000652Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000653 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000654 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000655{
njnfb289bc2007-01-12 23:59:50 +0000656 Error err;
657 Supp *su;
njn43c799e2003-04-08 00:08:52 +0000658
659 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000660 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000661
662 /* Unless it's suppressed, we're going to show it. Don't need to make
663 a copy, because it's only temporary anyway.
664
njn02bc4b82005-05-15 17:28:26 +0000665 Then update the 'extra' part with VG_(tdict).tool_update_extra),
njn51d827b2005-05-09 01:02:08 +0000666 because that can have an affect on whether it's suppressed. Ignore
667 the size return value of VG_(tdict).tool_update_extra, because we're
njn02bc4b82005-05-15 17:28:26 +0000668 not copying 'extra'. */
njn51d827b2005-05-09 01:02:08 +0000669 (void)VG_TDICT_CALL(tool_update_extra, &err);
njn43c799e2003-04-08 00:08:52 +0000670
njnfb289bc2007-01-12 23:59:50 +0000671 su = is_suppressible_error(&err);
672 if (NULL == su) {
njn47363ab2003-04-21 13:24:40 +0000673 if (count_error)
nethercotef2b11482004-08-02 12:36:01 +0000674 n_errs_found++;
njn43c799e2003-04-08 00:08:52 +0000675
676 if (print_error) {
677 if (!is_first_shown_context)
678 VG_(message)(Vg_UserMsg, "");
njnb0eb66e2005-07-10 16:57:24 +0000679 pp_Error(&err);
njn43c799e2003-04-08 00:08:52 +0000680 is_first_shown_context = False;
njnfb289bc2007-01-12 23:59:50 +0000681 n_errs_shown++;
682 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000683 }
njn43c799e2003-04-08 00:08:52 +0000684 return False;
685
686 } else {
nethercotef2b11482004-08-02 12:36:01 +0000687 n_errs_suppressed++;
njnfb289bc2007-01-12 23:59:50 +0000688 su->count++;
njn43c799e2003-04-08 00:08:52 +0000689 return True;
690 }
691}
692
sewardjde4a1d02002-03-22 01:27:54 +0000693
sewardjde4a1d02002-03-22 01:27:54 +0000694/*------------------------------------------------------------*/
695/*--- Exported fns ---*/
696/*------------------------------------------------------------*/
697
sewardj71bc3cb2005-05-19 00:25:45 +0000698/* Show the used suppressions. Returns False if no suppression
699 got used. */
700static Bool show_used_suppressions ( void )
701{
702 Supp *su;
703 Bool any_supp;
704
sewardj7c9e57c2005-05-24 14:21:45 +0000705 if (VG_(clo_xml))
706 VG_(message)(Vg_DebugMsg, "<suppcounts>");
707
sewardj71bc3cb2005-05-19 00:25:45 +0000708 any_supp = False;
709 for (su = suppressions; su != NULL; su = su->next) {
710 if (su->count <= 0)
711 continue;
712 any_supp = True;
713 if (VG_(clo_xml)) {
barta0b6b2c2008-07-07 06:49:24 +0000714 VG_(message_no_f_c)(Vg_DebugMsg,
715 " <pair>\n"
716 " <count>%d</count>\n"
717 " <name>%t</name>\n"
718 " </pair>",
719 su->count, su->sname);
sewardj71bc3cb2005-05-19 00:25:45 +0000720 } else {
sewardj8a7d4e42006-10-17 01:41:17 +0000721 VG_(message)(Vg_DebugMsg, "supp: %6d %s", su->count, su->sname);
sewardj71bc3cb2005-05-19 00:25:45 +0000722 }
723 }
724
sewardj7c9e57c2005-05-24 14:21:45 +0000725 if (VG_(clo_xml))
sewardj8665d8e2005-06-01 17:35:23 +0000726 VG_(message)(Vg_DebugMsg, "</suppcounts>");
sewardj7c9e57c2005-05-24 14:21:45 +0000727
sewardj71bc3cb2005-05-19 00:25:45 +0000728 return any_supp;
729}
730
731
sewardj9f297ca2005-05-20 02:29:52 +0000732/* Show all the errors that occurred, and possibly also the
733 suppressions used. */
sewardjde4a1d02002-03-22 01:27:54 +0000734void VG_(show_all_errors) ( void )
735{
njn810086f2002-11-14 12:42:47 +0000736 Int i, n_min;
737 Int n_err_contexts, n_supp_contexts;
738 Error *p, *p_min;
739 Supp *su;
740 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000741
742 if (VG_(clo_verbosity) == 0)
743 return;
744
745 n_err_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000746 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000747 if (p->supp == NULL)
748 n_err_contexts++;
749 }
750
751 n_supp_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000752 for (su = suppressions; su != NULL; su = su->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000753 if (su->count > 0)
754 n_supp_contexts++;
755 }
sewardj71bc3cb2005-05-19 00:25:45 +0000756
757 /* If we're printing XML, just show the suppressions and stop.
758 */
759 if (VG_(clo_xml)) {
760 (void)show_used_suppressions();
761 return;
762 }
763
764 /* We only get here if not printing XML. */
sewardjde4a1d02002-03-22 01:27:54 +0000765 VG_(message)(Vg_UserMsg,
766 "ERROR SUMMARY: "
767 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000768 n_errs_found, n_err_contexts,
769 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000770
771 if (VG_(clo_verbosity) <= 1)
772 return;
773
774 /* Print the contexts in order of increasing error count. */
775 for (i = 0; i < n_err_contexts; i++) {
776 n_min = (1 << 30) - 1;
777 p_min = NULL;
njn695c16e2005-03-27 03:40:28 +0000778 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000779 if (p->supp != NULL) continue;
780 if (p->count < n_min) {
781 n_min = p->count;
782 p_min = p;
783 }
784 }
njn67993252004-11-22 18:02:32 +0000785 if (p_min == NULL) VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000786
787 VG_(message)(Vg_UserMsg, "");
788 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
789 p_min->count,
790 i+1, n_err_contexts);
njnb0eb66e2005-07-10 16:57:24 +0000791 pp_Error( p_min );
sewardjde4a1d02002-03-22 01:27:54 +0000792
793 if ((i+1 == VG_(clo_dump_error))) {
sewardj7cf4e6b2008-05-01 20:24:26 +0000794 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
sewardjfa8ec112005-01-19 11:55:34 +0000795 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
njn394213a2005-06-19 18:38:24 +0000796 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
sewardj0ec07f32006-01-12 12:32:32 +0000797 /*bbs_done*/0,
798 /*allow redir?*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000799 }
800
801 p_min->count = 1 << 30;
802 }
803
804 if (n_supp_contexts > 0)
805 VG_(message)(Vg_DebugMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +0000806 any_supp = show_used_suppressions();
sewardjde4a1d02002-03-22 01:27:54 +0000807
808 if (n_err_contexts > 0) {
809 if (any_supp)
810 VG_(message)(Vg_UserMsg, "");
811 VG_(message)(Vg_UserMsg,
812 "IN SUMMARY: "
813 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000814 n_errs_found, n_err_contexts, n_errs_suppressed,
sewardjde4a1d02002-03-22 01:27:54 +0000815 n_supp_contexts );
816 VG_(message)(Vg_UserMsg, "");
817 }
818}
819
sewardj9f297ca2005-05-20 02:29:52 +0000820
821/* Show occurrence counts of all errors, in XML form. */
822void VG_(show_error_counts_as_XML) ( void )
823{
824 Error* err;
825 VG_(message)(Vg_UserMsg, "<errorcounts>");
826 for (err = errors; err != NULL; err = err->next) {
827 if (err->supp != NULL)
828 continue;
829 if (err->count <= 0)
830 continue;
831 VG_(message)(
sewardj753673f2005-08-09 22:03:08 +0000832 Vg_UserMsg, " <pair>\n"
833 " <count>%d</count>\n"
cerion3a24e722005-08-09 22:34:18 +0000834 " <unique>0x%x</unique>\n"
sewardj753673f2005-08-09 22:03:08 +0000835 " </pair>",
sewardj39618202005-08-09 21:50:18 +0000836 err->count, err->unique
sewardj9f297ca2005-05-20 02:29:52 +0000837 );
838 }
839 VG_(message)(Vg_UserMsg, "</errorcounts>");
840}
841
842
sewardjde4a1d02002-03-22 01:27:54 +0000843/*------------------------------------------------------------*/
sewardjd7a02db2008-12-12 08:07:49 +0000844/*--- Suppression parsing ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000845/*------------------------------------------------------------*/
846
sewardj8a7d4e42006-10-17 01:41:17 +0000847/* Get the next char from fd into *out_buf. Returns 1 if success,
848 0 if eof or < 0 if error. */
849
850static Int get_char ( Int fd, Char* out_buf )
851{
852 Int r;
sewardj89c5bd82008-10-23 10:15:37 +0000853 static Char buf[256];
sewardj8a7d4e42006-10-17 01:41:17 +0000854 static Int buf_size = 0;
855 static Int buf_used = 0;
sewardj89c5bd82008-10-23 10:15:37 +0000856 vg_assert(buf_size >= 0 && buf_size <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +0000857 vg_assert(buf_used >= 0 && buf_used <= buf_size);
858 if (buf_used == buf_size) {
sewardj89c5bd82008-10-23 10:15:37 +0000859 r = VG_(read)(fd, buf, 256);
sewardj8a7d4e42006-10-17 01:41:17 +0000860 if (r < 0) return r; /* read failed */
sewardj89c5bd82008-10-23 10:15:37 +0000861 vg_assert(r >= 0 && r <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +0000862 buf_size = r;
863 buf_used = 0;
864 }
865 if (buf_size == 0)
866 return 0; /* eof */
sewardj89c5bd82008-10-23 10:15:37 +0000867 vg_assert(buf_size >= 0 && buf_size <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +0000868 vg_assert(buf_used >= 0 && buf_used < buf_size);
869 *out_buf = buf[buf_used];
870 buf_used++;
871 return 1;
872}
873
874
sewardjde4a1d02002-03-22 01:27:54 +0000875/* Get a non-blank, non-comment line of at most nBuf chars from fd.
876 Skips leading spaces on the line. Return True if EOF was hit instead.
877*/
njn4ba5a792002-09-30 10:23:54 +0000878Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000879{
880 Char ch;
881 Int n, i;
882 while (True) {
883 /* First, read until a non-blank char appears. */
884 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +0000885 n = get_char(fd, &ch);
njn0c0f32a2005-03-26 04:14:01 +0000886 if (n == 1 && !VG_(isspace)(ch)) break;
sewardj8a7d4e42006-10-17 01:41:17 +0000887 if (n <= 0) return True;
sewardjde4a1d02002-03-22 01:27:54 +0000888 }
889
890 /* Now, read the line into buf. */
891 i = 0;
892 buf[i++] = ch; buf[i] = 0;
893 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +0000894 n = get_char(fd, &ch);
895 if (n <= 0) return False; /* the next call will return True */
sewardjde4a1d02002-03-22 01:27:54 +0000896 if (ch == '\n') break;
897 if (i > 0 && i == nBuf-1) i--;
898 buf[i++] = ch; buf[i] = 0;
899 }
njn0c0f32a2005-03-26 04:14:01 +0000900 while (i > 1 && VG_(isspace)(buf[i-1])) {
sewardjde4a1d02002-03-22 01:27:54 +0000901 i--; buf[i] = 0;
902 };
903
njn02bc4b82005-05-15 17:28:26 +0000904 /* VG_(printf)("The line is '%s'\n", buf); */
sewardjde4a1d02002-03-22 01:27:54 +0000905 /* Ok, we have a line. If a non-comment line, return.
906 If a comment line, start all over again. */
907 if (buf[0] != '#') return False;
908 }
909}
910
911
912/* *p_caller contains the raw name of a caller, supposedly either
913 fun:some_function_name or
914 obj:some_object_name.
915 Set *p_ty accordingly and advance *p_caller over the descriptor
916 (fun: or obj:) part.
917 Returns False if failed.
918*/
sewardjb5f6f512005-03-10 23:59:00 +0000919static Bool setLocationTy ( SuppLoc* p )
sewardjde4a1d02002-03-22 01:27:54 +0000920{
sewardjb5f6f512005-03-10 23:59:00 +0000921 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
922 p->name += 4;
923 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +0000924 return True;
925 }
sewardjb5f6f512005-03-10 23:59:00 +0000926 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
927 p->name += 4;
928 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +0000929 return True;
930 }
sewardj5e519302008-11-03 23:10:25 +0000931 if (VG_(strcmp)(p->name, "...") == 0) {
932 p->name = NULL;
933 p->ty = DotDotDot;
934 return True;
935 }
936 VG_(printf)("location should be \"...\", or should start "
937 "with \"fun:\" or \"obj:\"\n");
sewardjde4a1d02002-03-22 01:27:54 +0000938 return False;
939}
940
941
nethercote7cc9c232004-01-21 15:08:04 +0000942/* Look for "tool" in a string like "tool1,tool2,tool3" */
sewardjd7a02db2008-12-12 08:07:49 +0000943static Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000944{
945 Bool found;
946 Char *s = NULL; /* Shut gcc up */
947 Int len = VG_(strlen)(name);
948
949 found = (NULL != (s = VG_(strstr)(names, name)) &&
950 (s == names || *(s-1) == ',') &&
951 (*(s+len) == ',' || *(s+len) == '\0')
952 );
953
954 return found;
955}
956
njn695c16e2005-03-27 03:40:28 +0000957/* Read suppressions from the file specified in VG_(clo_suppressions)
sewardjde4a1d02002-03-22 01:27:54 +0000958 and place them in the suppressions list. If there's any difficulty
959 doing this, just give up -- there's no point in trying to recover.
960*/
sewardjde4a1d02002-03-22 01:27:54 +0000961static void load_one_suppressions_file ( Char* filename )
962{
963# define N_BUF 200
sewardj92645592005-07-23 09:18:34 +0000964 SysRes sres;
sewardj5e519302008-11-03 23:10:25 +0000965 Int fd, i, j, lineno = 0;
sewardj92645592005-07-23 09:18:34 +0000966 Bool eof;
967 Char buf[N_BUF+1];
968 Char* tool_names;
969 Char* supp_name;
970 Char* err_str = NULL;
sewardjb5f6f512005-03-10 23:59:00 +0000971 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +0000972
sewardj92645592005-07-23 09:18:34 +0000973 fd = -1;
974 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
975 if (sres.isError) {
sewardjf349d552005-11-14 17:01:01 +0000976 if (VG_(clo_xml))
977 VG_(message)(Vg_UserMsg, "</valgrindoutput>\n");
sewardj5e519302008-11-03 23:10:25 +0000978 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file \"%s\"",
sewardjde4a1d02002-03-22 01:27:54 +0000979 filename );
980 VG_(exit)(1);
981 }
sewardj8a7d4e42006-10-17 01:41:17 +0000982 fd = sres.res;
sewardjde4a1d02002-03-22 01:27:54 +0000983
sewardj92645592005-07-23 09:18:34 +0000984# define BOMB(S) { err_str = S; goto syntax_error; }
sewardjb5f6f512005-03-10 23:59:00 +0000985
sewardjde4a1d02002-03-22 01:27:54 +0000986 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000987 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000988 Supp* supp;
sewardj9c606bd2008-09-18 18:12:50 +0000989 supp = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
990 sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000991 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000992
993 // Initialise temporary reading-in buffer.
994 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
995 tmp_callers[i].ty = NoName;
996 tmp_callers[i].name = NULL;
997 }
998
njn810086f2002-11-14 12:42:47 +0000999 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001000
njn4ba5a792002-09-30 10:23:54 +00001001 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardj5e519302008-11-03 23:10:25 +00001002 lineno++;
sewardjde4a1d02002-03-22 01:27:54 +00001003 if (eof) break;
1004
sewardjb5f6f512005-03-10 23:59:00 +00001005 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +00001006
njn4ba5a792002-09-30 10:23:54 +00001007 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardj5e519302008-11-03 23:10:25 +00001008 lineno++;
sewardjb5f6f512005-03-10 23:59:00 +00001009
1010 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1011
sewardj9c606bd2008-09-18 18:12:50 +00001012 supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
sewardjde4a1d02002-03-22 01:27:54 +00001013
njn4ba5a792002-09-30 10:23:54 +00001014 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardj5e519302008-11-03 23:10:25 +00001015 lineno++;
njn25e49d8e72002-09-23 09:36:25 +00001016
sewardjb5f6f512005-03-10 23:59:00 +00001017 if (eof) BOMB("unexpected end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +00001018
njn94065fd2004-11-22 19:26:27 +00001019 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +00001020 i = 0;
1021 while (True) {
1022 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +00001023 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +00001024 i++;
njn25e49d8e72002-09-23 09:36:25 +00001025 }
njnc40c3a82002-10-02 11:02:27 +00001026 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1027
nethercote7cc9c232004-01-21 15:08:04 +00001028 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +00001029 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +00001030
nethercote7cc9c232004-01-21 15:08:04 +00001031 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +00001032 {
sewardjb5f6f512005-03-10 23:59:00 +00001033 // A core suppression
njna86f29e2006-12-14 02:55:58 +00001034 //(example code, see comment on CoreSuppKind above)
1035 //if (VG_STREQ(supp_name, "Thread"))
1036 // supp->skind = ThreadSupp;
1037 //else
sewardjb5f6f512005-03-10 23:59:00 +00001038 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +00001039 }
njn95ec8702004-11-22 16:46:13 +00001040 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +00001041 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +00001042 {
sewardjb5f6f512005-03-10 23:59:00 +00001043 // A tool suppression
njn51d827b2005-05-09 01:02:08 +00001044 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +00001045 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +00001046 } else {
1047 BOMB("unknown tool suppression type");
1048 }
njnc40c3a82002-10-02 11:02:27 +00001049 }
njn25e49d8e72002-09-23 09:36:25 +00001050 else {
sewardjb5f6f512005-03-10 23:59:00 +00001051 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +00001052 while (True) {
njn4ba5a792002-09-30 10:23:54 +00001053 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardj5e519302008-11-03 23:10:25 +00001054 lineno++;
sewardjb5f6f512005-03-10 23:59:00 +00001055 if (eof) BOMB("unexpected end-of-file");
njn43c799e2003-04-08 00:08:52 +00001056 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +00001057 break;
1058 }
1059 continue;
sewardjde4a1d02002-03-22 01:27:54 +00001060 }
1061
njn95ec8702004-11-22 16:46:13 +00001062 if (VG_(needs).tool_errors &&
sewardjd7a02db2008-12-12 08:07:49 +00001063 !VG_TDICT_CALL(tool_read_extra_suppression_info,
1064 fd, buf, N_BUF, supp))
sewardjb5f6f512005-03-10 23:59:00 +00001065 {
1066 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +00001067 }
1068
sewardj5e519302008-11-03 23:10:25 +00001069 /* the main frame-descriptor reading loop */
sewardjb5f6f512005-03-10 23:59:00 +00001070 i = 0;
1071 while (True) {
1072 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardj5e519302008-11-03 23:10:25 +00001073 lineno++;
sewardjb5f6f512005-03-10 23:59:00 +00001074 if (eof)
1075 BOMB("unexpected end-of-file");
1076 if (VG_STREQ(buf, "}")) {
1077 if (i > 0) {
1078 break;
1079 } else {
1080 BOMB("missing stack trace");
1081 }
1082 }
1083 if (i == VG_MAX_SUPP_CALLERS)
1084 BOMB("too many callers in stack trace");
1085 if (i > 0 && i >= VG_(clo_backtrace_size))
1086 break;
sewardj9c606bd2008-09-18 18:12:50 +00001087 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE,
1088 "errormgr.losf.3", buf);
sewardjb5f6f512005-03-10 23:59:00 +00001089 if (!setLocationTy(&(tmp_callers[i])))
sewardj5e519302008-11-03 23:10:25 +00001090 BOMB("location should be \"...\", or should start "
1091 "with \"fun:\" or \"obj:\"");
sewardjb5f6f512005-03-10 23:59:00 +00001092 i++;
1093 }
1094
1095 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1096 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +00001097 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +00001098 do {
1099 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardj5e519302008-11-03 23:10:25 +00001100 lineno++;
sewardjb5f6f512005-03-10 23:59:00 +00001101 } while (!eof && !VG_STREQ(buf, "}"));
1102 }
1103
sewardj5e519302008-11-03 23:10:25 +00001104 // Reject entries which are entirely composed of frame
1105 // level wildcards.
1106 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1107 for (j = 0; j < i; j++) {
1108 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
1109 break;
1110 vg_assert(tmp_callers[j].ty == DotDotDot);
1111 }
1112 vg_assert(j >= 0 && j <= i);
1113 if (j == i) {
1114 // we didn't find any non-"..." entries
1115 BOMB("suppression must contain at least one location "
1116 "line which is not \"...\"");
1117 }
1118
sewardjb5f6f512005-03-10 23:59:00 +00001119 // Copy tmp_callers[] into supp->callers[]
1120 supp->n_callers = i;
sewardj9c606bd2008-09-18 18:12:50 +00001121 supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
1122 i*sizeof(SuppLoc));
sewardjb5f6f512005-03-10 23:59:00 +00001123 for (i = 0; i < supp->n_callers; i++) {
1124 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +00001125 }
1126
njn695c16e2005-03-27 03:40:28 +00001127 supp->next = suppressions;
1128 suppressions = supp;
sewardjde4a1d02002-03-22 01:27:54 +00001129 }
sewardjde4a1d02002-03-22 01:27:54 +00001130 VG_(close)(fd);
1131 return;
1132
1133 syntax_error:
sewardjf349d552005-11-14 17:01:01 +00001134 if (VG_(clo_xml))
1135 VG_(message)(Vg_UserMsg, "</valgrindoutput>\n");
sewardjb5f6f512005-03-10 23:59:00 +00001136 VG_(message)(Vg_UserMsg,
sewardj9a0132d2008-11-04 11:29:19 +00001137 "FATAL: in suppressions file \"%s\" near line %d:",
sewardj5e519302008-11-03 23:10:25 +00001138 filename, lineno );
1139 VG_(message)(Vg_UserMsg,
1140 " %s", err_str );
sewardjb5f6f512005-03-10 23:59:00 +00001141
sewardjde4a1d02002-03-22 01:27:54 +00001142 VG_(close)(fd);
1143 VG_(message)(Vg_UserMsg, "exiting now.");
nethercote8ed8a892004-11-08 13:24:25 +00001144 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001145
sewardjb5f6f512005-03-10 23:59:00 +00001146# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +00001147# undef N_BUF
1148}
1149
1150
1151void VG_(load_suppressions) ( void )
1152{
1153 Int i;
njn695c16e2005-03-27 03:40:28 +00001154 suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001155 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1156 if (VG_(clo_verbosity) > 1) {
njn3f04d242005-03-20 18:21:14 +00001157 VG_(message)(Vg_DebugMsg, "Reading suppressions file: %s",
1158 VG_(clo_suppressions)[i] );
sewardjde4a1d02002-03-22 01:27:54 +00001159 }
1160 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1161 }
1162}
1163
sewardjd7a02db2008-12-12 08:07:49 +00001164
1165/*------------------------------------------------------------*/
1166/*--- Matching errors to suppressions ---*/
1167/*------------------------------------------------------------*/
1168
1169/* Parameterising functions for the use of VG_(generic_match) in
1170 suppression-vs-error matching. The suppression frames (SuppLoc)
1171 play the role of 'pattern'-element, and the error frames (IPs,
1172 hence simply Addrs) play the role of 'input'. In short then, we're
1173 matching a sequence of Addrs against a pattern composed of a
1174 sequence of SuppLocs.
1175*/
1176static Bool supploc_IsStar ( void* supplocV )
1177{
1178 SuppLoc* supploc = (SuppLoc*)supplocV;
1179 return supploc->ty == DotDotDot;
1180}
1181
1182static Bool supploc_IsQuery ( void* supplocV )
1183{
1184 return False; /* there's no '?' equivalent in the supp syntax */
1185}
1186
1187static Bool supp_pattEQinp ( void* supplocV, void* addrV )
1188{
1189 SuppLoc* supploc = (SuppLoc*)supplocV; /* PATTERN */
1190 Addr ip = *(Addr*)addrV; /* INPUT */
1191
1192 Char caller_name[ERRTXT_LEN];
1193 caller_name[0] = 0;
1194
1195 /* So, does this IP address match this suppression-line? */
1196 switch (supploc->ty) {
1197 case DotDotDot:
1198 /* supp_pattEQinp is a callback from VG_(generic_match). As
1199 per the spec thereof (see include/pub_tool_seqmatch.h), we
1200 should never get called with a pattern value for which the
1201 _IsStar or _IsQuery function would return True. Hence
1202 this can't happen. */
1203 vg_assert(0);
1204 case ObjName:
1205 /* Get the object name into 'caller_name', or "???"
1206 if unknown. */
1207 if (!VG_(get_objname)(ip, caller_name, ERRTXT_LEN))
1208 VG_(strcpy)(caller_name, "???");
1209 break;
1210 case FunName:
1211 /* Get the function name into 'caller_name', or "???"
1212 if unknown. */
1213 // Nb: mangled names used in suppressions. Do, though,
1214 // Z-demangle them, since otherwise it's possible to wind
1215 // up comparing "malloc" in the suppression against
1216 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1217 // two of them need to be made to match.
1218 if (!VG_(get_fnname_Z_demangle_only)(ip, caller_name, ERRTXT_LEN))
1219 VG_(strcpy)(caller_name, "???");
1220 break;
1221 default:
1222 vg_assert(0);
1223 }
1224
1225 /* So now we have the function or object name in caller_name, and
1226 the pattern (at the character level) to match against is in
1227 supploc->name. Hence (and leading to a re-entrant call of
1228 VG_(generic_match)): */
1229 return VG_(string_match)(supploc->name, caller_name);
1230}
1231
1232/////////////////////////////////////////////////////
1233
1234static Bool supp_matches_callers(Error* err, Supp* su)
1235{
1236 /* Unwrap the args and set up the correct parameterisation of
1237 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1238 supp_pattEQinp. */
1239 /* note, StackTrace === Addr* */
1240 StackTrace ips = VG_(get_ExeContext_StackTrace)(err->where);
1241 UWord n_ips = VG_(get_ExeContext_n_ips)(err->where);
1242 SuppLoc* supps = su->callers;
1243 UWord n_supps = su->n_callers;
1244 UWord szbPatt = sizeof(SuppLoc);
1245 UWord szbInput = sizeof(Addr);
1246 Bool matchAll = False; /* we just want to match a prefix */
1247 return
1248 VG_(generic_match)(
1249 matchAll,
1250 /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
1251 /*INPUT*/ips, szbInput, n_ips, 0/*initial Ix*/,
1252 supploc_IsStar, supploc_IsQuery, supp_pattEQinp
1253 );
1254}
1255
1256/////////////////////////////////////////////////////
1257
sewardjb5f6f512005-03-10 23:59:00 +00001258static
njn810086f2002-11-14 12:42:47 +00001259Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +00001260{
njn810086f2002-11-14 12:42:47 +00001261 switch (su->skind) {
njna86f29e2006-12-14 02:55:58 +00001262 //(example code, see comment on CoreSuppKind above)
1263 //case ThreadSupp:
1264 // return (err->ekind == ThreadErr);
njn25e49d8e72002-09-23 09:36:25 +00001265 default:
njn95ec8702004-11-22 16:46:13 +00001266 if (VG_(needs).tool_errors) {
njn51d827b2005-05-09 01:02:08 +00001267 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
njn25e49d8e72002-09-23 09:36:25 +00001268 } else {
1269 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +00001270 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +00001271 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +00001272 err->ekind);
njn67993252004-11-22 18:02:32 +00001273 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +00001274 }
1275 }
1276}
1277
sewardjd7a02db2008-12-12 08:07:49 +00001278/////////////////////////////////////////////////////
sewardj5e519302008-11-03 23:10:25 +00001279
njn810086f2002-11-14 12:42:47 +00001280/* Does an error context match a suppression? ie is this a suppressible
1281 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001282 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001283*/
njn810086f2002-11-14 12:42:47 +00001284static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001285{
njn810086f2002-11-14 12:42:47 +00001286 Supp* su;
sewardj8a7d4e42006-10-17 01:41:17 +00001287 Supp* su_prev;
1288
1289 /* stats gathering */
1290 em_supplist_searches++;
sewardjde4a1d02002-03-22 01:27:54 +00001291
sewardjde4a1d02002-03-22 01:27:54 +00001292 /* See if the error context matches any suppression. */
sewardj8a7d4e42006-10-17 01:41:17 +00001293 su_prev = NULL;
njn695c16e2005-03-27 03:40:28 +00001294 for (su = suppressions; su != NULL; su = su->next) {
sewardj8a7d4e42006-10-17 01:41:17 +00001295 em_supplist_cmps++;
1296 if (supp_matches_error(su, err) && supp_matches_callers(err, su)) {
1297 /* got a match. Move this entry to the head of the list
1298 in the hope of making future searches cheaper. */
1299 if (su_prev) {
1300 vg_assert(su_prev->next == su);
1301 su_prev->next = su->next;
1302 su->next = suppressions;
1303 suppressions = su;
1304 }
njn25e49d8e72002-09-23 09:36:25 +00001305 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001306 }
sewardj8a7d4e42006-10-17 01:41:17 +00001307 su_prev = su;
sewardjde4a1d02002-03-22 01:27:54 +00001308 }
njn25e49d8e72002-09-23 09:36:25 +00001309 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001310}
1311
sewardj8a7d4e42006-10-17 01:41:17 +00001312/* Show accumulated error-list and suppression-list search stats.
1313*/
1314void VG_(print_errormgr_stats) ( void )
1315{
1316 VG_(message)(Vg_DebugMsg,
barta0b6b2c2008-07-07 06:49:24 +00001317 " errormgr: %'lu supplist searches, %'lu comparisons during search",
sewardj8a7d4e42006-10-17 01:41:17 +00001318 em_supplist_searches, em_supplist_cmps
1319 );
1320 VG_(message)(Vg_DebugMsg,
barta0b6b2c2008-07-07 06:49:24 +00001321 " errormgr: %'lu errlist searches, %'lu comparisons during search",
sewardj8a7d4e42006-10-17 01:41:17 +00001322 em_errlist_searches, em_errlist_cmps
1323 );
1324}
1325
sewardjde4a1d02002-03-22 01:27:54 +00001326/*--------------------------------------------------------------------*/
njneb8896b2005-06-04 20:03:55 +00001327/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001328/*--------------------------------------------------------------------*/