blob: 0e99234b6872bf213819736158a03b0dacb5fc86 [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
sewardj03f8d3f2012-08-05 15:46:46 +000010 Copyright (C) 2000-2012 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"
sewardj6c591e12011-04-11 16:17:51 +000033#include "pub_core_libcsetjmp.h"
njn24a6efb2005-06-20 03:36:51 +000034#include "pub_core_threadstate.h" // For VG_N_THREADS
njn75b65aa2005-06-19 19:25:44 +000035#include "pub_core_debugger.h"
njnea27e462005-05-31 02:38:09 +000036#include "pub_core_debuginfo.h"
njnd2b17112005-04-19 04:10:25 +000037#include "pub_core_errormgr.h"
njnd01fef72005-03-25 23:35:48 +000038#include "pub_core_execontext.h"
sewardj3b290482011-05-06 21:02:55 +000039#include "pub_core_gdbserver.h"
njn97405b22005-06-02 03:39:33 +000040#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000041#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000042#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000043#include "pub_core_libcprint.h"
njn24a6efb2005-06-20 03:36:51 +000044#include "pub_core_libcproc.h" // For VG_(getpid)()
sewardjd7a02db2008-12-12 08:07:49 +000045#include "pub_core_seqmatch.h"
njnaf1d7df2005-06-11 01:31:52 +000046#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000047#include "pub_core_options.h"
njnd0d7c1f2005-06-21 00:33:19 +000048#include "pub_core_stacktrace.h"
njn43b9a8a2005-05-10 04:37:01 +000049#include "pub_core_tooliface.h"
njn24a6efb2005-06-20 03:36:51 +000050#include "pub_core_translate.h" // for VG_(translate)()
sewardj588adef2009-08-15 22:41:51 +000051#include "pub_core_xarray.h" // VG_(xaprintf) et al
sewardjde4a1d02002-03-22 01:27:54 +000052
53/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000054/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000055/*------------------------------------------------------------*/
56
njn14319cc2005-03-13 06:26:22 +000057/* After this many different unsuppressed errors have been observed,
58 be more conservative about collecting new ones. */
sewardj1d1a2262005-10-20 01:57:29 +000059#define M_COLLECT_ERRORS_SLOWLY_AFTER 100
njn14319cc2005-03-13 06:26:22 +000060
61/* After this many different unsuppressed errors have been observed,
62 stop collecting errors at all, and tell the user their program is
63 evidently a steaming pile of camel dung. */
sewardj1d1a2262005-10-20 01:57:29 +000064#define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
njn14319cc2005-03-13 06:26:22 +000065
66/* After this many total errors have been observed, stop collecting
67 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
sewardj513646f2006-05-12 23:12:30 +000068#define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
njn14319cc2005-03-13 06:26:22 +000069
sewardjde4a1d02002-03-22 01:27:54 +000070/* The list of error contexts found, both suppressed and unsuppressed.
71 Initially empty, and grows as errors are detected. */
njn695c16e2005-03-27 03:40:28 +000072static Error* errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000073
74/* The list of suppression directives, as read from the specified
sewardj8a7d4e42006-10-17 01:41:17 +000075 suppressions file. Note that the list gets rearranged as a result
76 of the searches done by is_suppressible_error(). */
njn695c16e2005-03-27 03:40:28 +000077static Supp* suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000078
79/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000080static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000081
82/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000083static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000084
philippebaf69642012-02-15 22:29:30 +000085/* Running count of errors shown. */
86static UInt n_errs_shown = 0;
87
njn606a4ae2009-08-11 00:52:40 +000088/* Running count of unsuppressed error contexts. */
89static UInt n_err_contexts = 0;
90
91/* Running count of suppressed error contexts. */
92static UInt n_supp_contexts = 0;
93
94
sewardjde4a1d02002-03-22 01:27:54 +000095/* forwards ... */
njn810086f2002-11-14 12:42:47 +000096static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000097
sewardjb5f6f512005-03-10 23:59:00 +000098static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000099
sewardj8a7d4e42006-10-17 01:41:17 +0000100/* Stats: number of searches of the error list initiated. */
101static UWord em_errlist_searches = 0;
102
103/* Stats: number of comparisons done during error list
104 searching. */
105static UWord em_errlist_cmps = 0;
106
107/* Stats: number of searches of the suppression list initiated. */
108static UWord em_supplist_searches = 0;
109
110/* Stats: number of comparisons done during suppression list
111 searching. */
112static UWord em_supplist_cmps = 0;
113
sewardjde4a1d02002-03-22 01:27:54 +0000114/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +0000115/*--- Error type ---*/
116/*------------------------------------------------------------*/
117
nethercote4a184902004-08-02 12:21:09 +0000118/* Errors. Extensible (via the 'extra' field). Tools can use a normal
njn02bc4b82005-05-15 17:28:26 +0000119 enum (with element values in the normal range (0..)) for 'ekind'.
nethercote4a184902004-08-02 12:21:09 +0000120 Functions for getting/setting the tool-relevant fields are in
njnc7561b92005-06-19 01:24:32 +0000121 include/pub_tool_errormgr.h.
nethercote4a184902004-08-02 12:21:09 +0000122
123 When errors are found and recorded with VG_(maybe_record_error)(), all
124 the tool must do is pass in the four parameters; core will
125 allocate/initialise the error record.
126*/
127struct _Error {
128 struct _Error* next;
sewardjdbada272005-07-02 21:16:30 +0000129 // Unique tag. This gives the error a unique identity (handle) by
130 // which it can be referred to afterwords. Currently only used for
131 // XML printing.
132 UInt unique;
nethercote4a184902004-08-02 12:21:09 +0000133 // NULL if unsuppressed; or ptr to suppression record.
134 Supp* supp;
135 Int count;
nethercote4a184902004-08-02 12:21:09 +0000136
137 // The tool-specific part
sewardjb8b79ad2008-03-03 01:35:41 +0000138 ThreadId tid; // Initialised by core
nethercote4a184902004-08-02 12:21:09 +0000139 ExeContext* where; // Initialised by core
njnd2b17112005-04-19 04:10:25 +0000140 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
nethercote4a184902004-08-02 12:21:09 +0000141 Addr addr; // Used frequently
floriane543f302012-10-21 19:43:43 +0000142 const HChar* string; // Used frequently
nethercote4a184902004-08-02 12:21:09 +0000143 void* extra; // For any tool-specific extras
144};
145
sewardjb8b79ad2008-03-03 01:35:41 +0000146
nethercote4a184902004-08-02 12:21:09 +0000147ExeContext* VG_(get_error_where) ( Error* err )
148{
149 return err->where;
150}
151
152ErrorKind VG_(get_error_kind) ( Error* err )
153{
154 return err->ekind;
155}
156
157Addr VG_(get_error_address) ( Error* err )
158{
159 return err->addr;
160}
161
floriane543f302012-10-21 19:43:43 +0000162const HChar* VG_(get_error_string) ( Error* err )
nethercote4a184902004-08-02 12:21:09 +0000163{
164 return err->string;
165}
166
167void* VG_(get_error_extra) ( Error* err )
168{
169 return err->extra;
170}
171
nethercotef2b11482004-08-02 12:36:01 +0000172UInt VG_(get_n_errs_found)( void )
173{
174 return n_errs_found;
175}
176
philippebaf69642012-02-15 22:29:30 +0000177UInt VG_(get_n_errs_shown)( void )
178{
179 return n_errs_shown;
180}
181
nethercote4a184902004-08-02 12:21:09 +0000182/*------------------------------------------------------------*/
183/*--- Suppression type ---*/
184/*------------------------------------------------------------*/
185
186/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
187 * effectively extend it by defining their own enums in the (0..) range. */
188typedef
189 enum {
njna86f29e2006-12-14 02:55:58 +0000190 // Nb: thread errors are a relic of the time when Valgrind's core
191 // could detect them. This example is left commented-out as an
192 // example should new core errors ever be added.
193 ThreadSupp = -1, /* Matches ThreadErr */
nethercote4a184902004-08-02 12:21:09 +0000194 }
195 CoreSuppKind;
196
sewardjb5f6f512005-03-10 23:59:00 +0000197/* Max number of callers for context in a suppression. */
198#define VG_MAX_SUPP_CALLERS 24
199
nethercote4a184902004-08-02 12:21:09 +0000200/* For each caller specified for a suppression, record the nature of
201 the caller name. Not of interest to tools. */
202typedef
203 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000204 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000205 ObjName, /* Name is of an shared object file. */
sewardj5e519302008-11-03 23:10:25 +0000206 FunName, /* Name is of a function. */
207 DotDotDot /* Frame-level wildcard */
nethercote4a184902004-08-02 12:21:09 +0000208 }
209 SuppLocTy;
210
sewardjb5f6f512005-03-10 23:59:00 +0000211typedef
212 struct {
213 SuppLocTy ty;
philippe2c5c05e2012-07-26 21:37:36 +0000214 Bool name_is_simple_str; /* True if name is a string without
215 '?' and '*' wildcard characters. */
florian19f91bb2012-11-10 22:29:54 +0000216 HChar* name; /* NULL for NoName and DotDotDot */
sewardjb5f6f512005-03-10 23:59:00 +0000217 }
218 SuppLoc;
219
nethercote4a184902004-08-02 12:21:09 +0000220/* Suppressions. Tools can get/set tool-relevant parts with functions
njnc7561b92005-06-19 01:24:32 +0000221 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000222 Tools can use a normal enum (with element values in the normal range
njn02bc4b82005-05-15 17:28:26 +0000223 (0..)) for 'skind'. */
nethercote4a184902004-08-02 12:21:09 +0000224struct _Supp {
225 struct _Supp* next;
226 Int count; // The number of times this error has been suppressed.
florian19f91bb2012-11-10 22:29:54 +0000227 HChar* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000228
229 // Length of 'callers'
230 Int n_callers;
231 // Array of callers, for matching stack traces. First one (name of fn
232 // where err occurs) is mandatory; rest are optional.
233 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000234
235 /* The tool-specific part */
236 SuppKind skind; // What kind of suppression. Must use the range (0..).
florian19f91bb2012-11-10 22:29:54 +0000237 HChar* string; // String -- use is optional. NULL by default.
nethercote4a184902004-08-02 12:21:09 +0000238 void* extra; // Anything else -- use is optional. NULL by default.
239};
240
241SuppKind VG_(get_supp_kind) ( Supp* su )
242{
243 return su->skind;
244}
245
florian19f91bb2012-11-10 22:29:54 +0000246HChar* VG_(get_supp_string) ( Supp* su )
nethercote4a184902004-08-02 12:21:09 +0000247{
248 return su->string;
249}
250
251void* VG_(get_supp_extra) ( Supp* su )
252{
253 return su->extra;
254}
255
256
257void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
258{
259 su->skind = skind;
260}
261
florian19f91bb2012-11-10 22:29:54 +0000262void VG_(set_supp_string) ( Supp* su, HChar* string )
nethercote4a184902004-08-02 12:21:09 +0000263{
264 su->string = string;
265}
266
267void VG_(set_supp_extra) ( Supp* su, void* extra )
268{
269 su->extra = extra;
270}
271
272
273/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000274/*--- Helper fns ---*/
275/*------------------------------------------------------------*/
276
njn0087c502005-07-01 04:15:36 +0000277// Only show core errors if the tool wants to, we're not running with -q,
278// and were not outputting XML.
279Bool VG_(showing_core_errors)(void)
280{
281 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
282}
283
sewardj738856f2009-07-15 14:48:32 +0000284/* Compare errors, to detect duplicates.
285*/
njn810086f2002-11-14 12:42:47 +0000286static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000287{
njn810086f2002-11-14 12:42:47 +0000288 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000289 return False;
njn25e49d8e72002-09-23 09:36:25 +0000290 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000291 return False;
292
njn810086f2002-11-14 12:42:47 +0000293 switch (e1->ekind) {
njna86f29e2006-12-14 02:55:58 +0000294 //(example code, see comment on CoreSuppKind above)
295 //case ThreadErr:
296 // vg_assert(VG_(needs).core_errors);
297 // return <something>
sewardjde4a1d02002-03-22 01:27:54 +0000298 default:
njn51d827b2005-05-09 01:02:08 +0000299 if (VG_(needs).tool_errors) {
300 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
301 } else {
njn95ec8702004-11-22 16:46:13 +0000302 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000303 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000304 e1->ekind);
njn67993252004-11-22 18:02:32 +0000305 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000306 }
sewardjde4a1d02002-03-22 01:27:54 +0000307 }
308}
309
sewardj738856f2009-07-15 14:48:32 +0000310
sewardj588adef2009-08-15 22:41:51 +0000311/* Helper functions for suppression generation: print a single line of
312 a suppression pseudo-stack-trace, either in XML or text mode. It's
313 important that the behaviour of these two functions exactly
314 corresponds.
sewardj738856f2009-07-15 14:48:32 +0000315*/
316#define ERRTXT_LEN 4096
317
sewardj588adef2009-08-15 22:41:51 +0000318static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque)
sewardjde4a1d02002-03-22 01:27:54 +0000319{
florian19f91bb2012-11-10 22:29:54 +0000320 static HChar buf[ERRTXT_LEN];
sewardj738856f2009-07-15 14:48:32 +0000321 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
bartb3af9cf2011-10-06 19:08:37 +0000322 VG_(printf_xml)(" <sframe> <fun>%pS</fun> </sframe>\n", buf);
sewardj588adef2009-08-15 22:41:51 +0000323 } else
324 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
bartb3af9cf2011-10-06 19:08:37 +0000325 VG_(printf_xml)(" <sframe> <obj>%pS</obj> </sframe>\n", buf);
sewardj738856f2009-07-15 14:48:32 +0000326 } else {
bartb3af9cf2011-10-06 19:08:37 +0000327 VG_(printf_xml)(" <sframe> <obj>*</obj> </sframe>\n");
sewardjde4a1d02002-03-22 01:27:54 +0000328 }
329}
330
sewardj588adef2009-08-15 22:41:51 +0000331static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV)
332{
florian19f91bb2012-11-10 22:29:54 +0000333 static HChar buf[ERRTXT_LEN];
sewardj588adef2009-08-15 22:41:51 +0000334 XArray* /* of HChar */ text = (XArray*)textV;
335 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
336 VG_(xaprintf)(text, " fun:%s\n", buf);
337 } else
338 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
339 VG_(xaprintf)(text, " obj:%s\n", buf);
340 } else {
341 VG_(xaprintf)(text, " obj:*\n");
342 }
343}
sewardj738856f2009-07-15 14:48:32 +0000344
345/* Generate a suppression for an error, either in text or XML mode.
346*/
347static void gen_suppression(Error* err)
348{
florian54fe2022012-10-27 23:07:42 +0000349 HChar xtra[256]; /* assumed big enough (is overrun-safe) */
sewardj588adef2009-08-15 22:41:51 +0000350 Bool anyXtra;
floriandbb35842012-10-27 18:39:11 +0000351 const HChar* name;
sewardj588adef2009-08-15 22:41:51 +0000352 ExeContext* ec;
353 XArray* /* HChar */ text;
sewardj738856f2009-07-15 14:48:32 +0000354
sewardj588adef2009-08-15 22:41:51 +0000355 const HChar* dummy_name = "insert_a_suppression_name_here";
sewardj738856f2009-07-15 14:48:32 +0000356
sewardj588adef2009-08-15 22:41:51 +0000357 vg_assert(err);
358
sewardj588adef2009-08-15 22:41:51 +0000359 ec = VG_(get_error_where)(err);
360 vg_assert(ec);
361
362 name = VG_TDICT_CALL(tool_get_error_name, err);
363 if (NULL == name) {
364 VG_(umsg)("(%s does not allow error to be suppressed)\n",
365 VG_(details).name);
366 return;
sewardj738856f2009-07-15 14:48:32 +0000367 }
368
tom7420e0a2011-07-06 14:08:24 +0000369 /* In XML mode, we also need to print the plain text version of the
370 suppresion in a CDATA section. What that really means is, we
371 need to generate the plaintext version both in XML and text
372 mode. So generate it into TEXT. */
373 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
374 VG_(free), sizeof(HChar) );
375 vg_assert(text);
376
sewardj588adef2009-08-15 22:41:51 +0000377 /* Ok. Generate the plain text version into TEXT. */
378 VG_(xaprintf)(text, "{\n");
379 VG_(xaprintf)(text, " <%s>\n", dummy_name);
380 VG_(xaprintf)(text, " %s:%s\n", VG_(details).name, name);
381
382 VG_(memset)(xtra, 0, sizeof(xtra));
383 anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info,
384 err, xtra, sizeof(xtra));
385 vg_assert(xtra[sizeof(xtra)-1] == 0);
386
387 if (anyXtra)
388 VG_(xaprintf)(text, " %s\n", xtra);
389
sewardj738856f2009-07-15 14:48:32 +0000390 // Print stack trace elements
sewardj2f340eb2011-01-28 00:44:52 +0000391 UInt n_ips = VG_(get_ExeContext_n_ips)(ec);
392 tl_assert(n_ips > 0);
393 if (n_ips > VG_MAX_SUPP_CALLERS)
394 n_ips = VG_MAX_SUPP_CALLERS;
sewardj588adef2009-08-15 22:41:51 +0000395 VG_(apply_StackTrace)(printSuppForIp_nonXML,
396 text,
sewardj738856f2009-07-15 14:48:32 +0000397 VG_(get_ExeContext_StackTrace)(ec),
sewardj2f340eb2011-01-28 00:44:52 +0000398 n_ips);
sewardj738856f2009-07-15 14:48:32 +0000399
sewardj588adef2009-08-15 22:41:51 +0000400 VG_(xaprintf)(text, "}\n");
401 // zero terminate
402 VG_(xaprintf)(text, "%c", (HChar)0 );
403 // VG_(printf) of text
404
405 /* And now display it. */
406 if (! VG_(clo_xml) ) {
407
408 // the simple case
409 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
410
sewardj738856f2009-07-15 14:48:32 +0000411 } else {
sewardj588adef2009-08-15 22:41:51 +0000412
413 /* Now we have to print the XML directly. No need to go to the
414 effort of stuffing it in an XArray, since we won't need it
415 again. */
416 VG_(printf_xml)(" <suppression>\n");
417 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name);
bartb3af9cf2011-10-06 19:08:37 +0000418 VG_(printf_xml)(
419 " <skind>%pS:%pS</skind>\n", VG_(details).name, name);
sewardj588adef2009-08-15 22:41:51 +0000420 if (anyXtra)
bartb3af9cf2011-10-06 19:08:37 +0000421 VG_(printf_xml)(" <skaux>%pS</skaux>\n", xtra);
sewardj588adef2009-08-15 22:41:51 +0000422
423 // Print stack trace elements
424 VG_(apply_StackTrace)(printSuppForIp_XML,
425 NULL,
426 VG_(get_ExeContext_StackTrace)(ec),
427 VG_(get_ExeContext_n_ips)(ec));
428
429 // And now the cdata bit
430 // XXX FIXME! properly handle the case where the raw text
431 // itself contains "]]>", as specified in Protocol 4.
432 VG_(printf_xml)(" <rawtext>\n");
433 VG_(printf_xml)("<![CDATA[\n");
sewardjde78f9a2009-08-15 23:33:04 +0000434 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
sewardj588adef2009-08-15 22:41:51 +0000435 VG_(printf_xml)("]]>\n");
436 VG_(printf_xml)(" </rawtext>\n");
437 VG_(printf_xml)(" </suppression>\n");
438
sewardj738856f2009-07-15 14:48:32 +0000439 }
sewardj588adef2009-08-15 22:41:51 +0000440
441 VG_(deleteXA)(text);
sewardj738856f2009-07-15 14:48:32 +0000442}
443
444
445/* Figure out if we want to perform a given action for this error,
446 possibly by asking the user.
447*/
florian2b8059a2012-10-14 16:45:23 +0000448Bool VG_(is_action_requested) ( const HChar* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000449{
florian19f91bb2012-11-10 22:29:54 +0000450 HChar ch, ch2;
sewardjde4a1d02002-03-22 01:27:54 +0000451 Int res;
452
sewardj738856f2009-07-15 14:48:32 +0000453 /* First off, we shouldn't be asking the user anything if
454 we're in XML mode. */
455 if (VG_(clo_xml))
456 return False; /* That's a Nein, oder Nay as they say down here in B-W */
457
njn43c799e2003-04-08 00:08:52 +0000458 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000459 return False;
460
sewardj738856f2009-07-15 14:48:32 +0000461 VG_(umsg)("\n");
sewardjde4a1d02002-03-22 01:27:54 +0000462
463 again:
464 VG_(printf)(
465 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000466 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
467 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000468 );
469
sewardj6024b212003-07-13 10:54:33 +0000470 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000471 if (res != 1) goto ioerror;
472 /* res == 1 */
473 if (ch == '\n') return False;
474 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
475 && ch != 'C' && ch != 'c') goto again;
476
sewardj6024b212003-07-13 10:54:33 +0000477 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000478 if (res != 1) goto ioerror;
479 if (ch2 != '\n') goto again;
480
njn43c799e2003-04-08 00:08:52 +0000481 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000482 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000483 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000484 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000485 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000486 vg_assert(ch == 'c' || ch == 'C');
487
488 ioerror:
njn43c799e2003-04-08 00:08:52 +0000489 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000490 return False;
491}
492
493
sewardj738856f2009-07-15 14:48:32 +0000494/* Do text-mode actions on error, that is, immediately after an error
495 is printed. These are:
496 * possibly, attach to a debugger
497 * possibly, generate a suppression.
498 Note this should not be called in XML mode!
499*/
500static
501void do_actions_on_error(Error* err, Bool allow_db_attach)
502{
503 Bool still_noisy = True;
504
505 /* Should be assured by caller */
506 vg_assert( ! VG_(clo_xml) );
507
sewardj3b290482011-05-06 21:02:55 +0000508 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
509 if (VG_(clo_vgdb) != Vg_VgdbNo
510 && allow_db_attach
philippebaf69642012-02-15 22:29:30 +0000511 && VG_(dyn_vgdb_error) <= n_errs_shown) {
sewardj3b290482011-05-06 21:02:55 +0000512 VG_(umsg)("(action on error) vgdb me ... \n");
513 VG_(gdbserver)( err->tid );
514 VG_(umsg)("Continuing ...\n");
515 }
516
sewardj738856f2009-07-15 14:48:32 +0000517 /* Perhaps we want a debugger attach at this point? */
sewardj3b290482011-05-06 21:02:55 +0000518 /* GDBTD ??? maybe we should/could remove the below assuming the
519 gdbserver interface is better ??? */
sewardj738856f2009-07-15 14:48:32 +0000520 if (allow_db_attach &&
521 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
522 {
523 if (0) VG_(printf)("starting debugger\n");
524 VG_(start_debugger)( err->tid );
525 }
526 /* Or maybe we want to generate the error's suppression? */
527 if (VG_(clo_gen_suppressions) == 2
528 || (VG_(clo_gen_suppressions) == 1
529 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
530 ) {
531 gen_suppression(err);
532 }
533 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
534 VG_(clo_gen_suppressions) = 0;
535}
536
537
538/* Prints an error. Not entirely simple because of the differences
539 between XML and text mode output.
540
541 In XML mode:
542
543 * calls the tool's pre-show method, so the tool can create any
544 preamble ahead of the message, if it wants.
545
546 * prints the opening tag, and the <unique> and <tid> fields
547
548 * prints the tool-specific parts of the message
549
550 * if suppression generation is required, a suppression
551
552 * the closing tag
553
554 In text mode:
555
556 * calls the tool's pre-show method, so the tool can create any
557 preamble ahead of the message, if it wants.
558
559 * prints the tool-specific parts of the message
560
561 * calls do_actions_on_error. This optionally does a debugger
562 attach (and detach), and optionally prints a suppression; both
563 of these may require user input.
564*/
sewardj3b290482011-05-06 21:02:55 +0000565static void pp_Error ( Error* err, Bool allow_db_attach, Bool xml )
sewardj738856f2009-07-15 14:48:32 +0000566{
567 /* If this fails, you probably specified your tool's method
568 dictionary incorrectly. */
569 vg_assert(VG_(needs).tool_errors);
570
sewardj3b290482011-05-06 21:02:55 +0000571 if (xml) {
sewardj738856f2009-07-15 14:48:32 +0000572
573 /* Note, allow_db_attach is ignored in here. */
574
575 /* Ensure that suppression generation is either completely
576 enabled or completely disabled; either way, we won't require
577 any user input. m_main.process_cmd_line_options should
578 ensure the asserted condition holds. */
579 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
580 || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
581
582 /* Pre-show it to the tool */
583 VG_TDICT_CALL( tool_before_pp_Error, err );
584
585 /* standard preamble */
586 VG_(printf_xml)("<error>\n");
587 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
588 VG_(printf_xml)(" <tid>%d</tid>\n", err->tid);
589
590 /* actually print it */
591 VG_TDICT_CALL( tool_pp_Error, err );
592
593 if (VG_(clo_gen_suppressions) > 0)
594 gen_suppression(err);
595
596 /* postamble */
597 VG_(printf_xml)("</error>\n");
njnb6267bd2009-08-12 00:14:16 +0000598 VG_(printf_xml)("\n");
sewardj738856f2009-07-15 14:48:32 +0000599
600 } else {
601
602 VG_TDICT_CALL( tool_before_pp_Error, err );
603
604 if (VG_(tdict).tool_show_ThreadIDs_for_errors
605 && err->tid > 0 && err->tid != last_tid_printed) {
606 VG_(umsg)("Thread %d:\n", err->tid );
607 last_tid_printed = err->tid;
608 }
609
610 VG_TDICT_CALL( tool_pp_Error, err );
njnb6267bd2009-08-12 00:14:16 +0000611 VG_(umsg)("\n");
sewardj738856f2009-07-15 14:48:32 +0000612
613 do_actions_on_error(err, allow_db_attach);
sewardj738856f2009-07-15 14:48:32 +0000614 }
615}
616
617
sewardjb5f6f512005-03-10 23:59:00 +0000618/* Construct an error */
sewardj738856f2009-07-15 14:48:32 +0000619static
njn72718642003-07-24 08:45:32 +0000620void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
floriane543f302012-10-21 19:43:43 +0000621 const HChar* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000622{
sewardjdbada272005-07-02 21:16:30 +0000623 /* DO NOT MAKE unique_counter NON-STATIC */
624 static UInt unique_counter = 0;
625
njnca82cc02004-11-22 17:18:48 +0000626 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000627
njn810086f2002-11-14 12:42:47 +0000628 /* Core-only parts */
sewardjdbada272005-07-02 21:16:30 +0000629 err->unique = unique_counter++;
njn25e49d8e72002-09-23 09:36:25 +0000630 err->next = NULL;
631 err->supp = NULL;
632 err->count = 1;
njn72718642003-07-24 08:45:32 +0000633 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000634 if (NULL == where)
sewardjadb102f2007-11-09 23:21:44 +0000635 err->where = VG_(record_ExeContext)( tid, 0 );
njn43c799e2003-04-08 00:08:52 +0000636 else
637 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000638
nethercote996901a2004-08-03 13:29:09 +0000639 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000640 err->ekind = ekind;
641 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000642 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000643 err->string = s;
644
njn25e49d8e72002-09-23 09:36:25 +0000645 /* sanity... */
njn72718642003-07-24 08:45:32 +0000646 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000647}
648
njn83f9e792005-06-11 05:04:09 +0000649
njn43c799e2003-04-08 00:08:52 +0000650
njn25e49d8e72002-09-23 09:36:25 +0000651/* Top-level entry point to the error management subsystem.
652 All detected errors are notified here; this routine decides if/when the
653 user should see the error. */
njn72718642003-07-24 08:45:32 +0000654void VG_(maybe_record_error) ( ThreadId tid,
floriane543f302012-10-21 19:43:43 +0000655 ErrorKind ekind, Addr a, const HChar* s, void* extra )
njn25e49d8e72002-09-23 09:36:25 +0000656{
njn810086f2002-11-14 12:42:47 +0000657 Error err;
658 Error* p;
659 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000660 UInt extra_size;
njn695c16e2005-03-27 03:40:28 +0000661 VgRes exe_res = Vg_MedRes;
662 static Bool stopping_message = False;
663 static Bool slowdown_message = False;
sewardjde4a1d02002-03-22 01:27:54 +0000664
njn14319cc2005-03-13 06:26:22 +0000665 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
666 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000667 have been found, just refuse to collect any more. This stops
668 the burden of the error-management system becoming excessive in
669 extremely buggy programs, although it does make it pretty
670 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000671 if (VG_(clo_error_limit)
njn695c16e2005-03-27 03:40:28 +0000672 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
sewardj8a051722005-06-30 00:10:16 +0000673 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
674 && !VG_(clo_xml)) {
sewardjde4a1d02002-03-22 01:27:54 +0000675 if (!stopping_message) {
sewardj738856f2009-07-15 14:48:32 +0000676 VG_(umsg)("\n");
sewardjf2537be2002-04-24 21:03:47 +0000677
njn695c16e2005-03-27 03:40:28 +0000678 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardj738856f2009-07-15 14:48:32 +0000679 VG_(umsg)(
sewardjf2537be2002-04-24 21:03:47 +0000680 "More than %d different errors detected. "
sewardj738856f2009-07-15 14:48:32 +0000681 "I'm not reporting any more.\n",
njn14319cc2005-03-13 06:26:22 +0000682 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000683 } else {
sewardj738856f2009-07-15 14:48:32 +0000684 VG_(umsg)(
sewardjf2537be2002-04-24 21:03:47 +0000685 "More than %d total errors detected. "
sewardj738856f2009-07-15 14:48:32 +0000686 "I'm not reporting any more.\n",
njn14319cc2005-03-13 06:26:22 +0000687 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000688 }
689
sewardj738856f2009-07-15 14:48:32 +0000690 VG_(umsg)("Final error counts will be inaccurate. "
691 "Go fix your program!\n");
692 VG_(umsg)("Rerun with --error-limit=no to disable "
693 "this cutoff. Note\n");
694 VG_(umsg)("that errors may occur in your program without "
695 "prior warning from\n");
696 VG_(umsg)("Valgrind, because errors are no longer "
697 "being displayed.\n");
698 VG_(umsg)("\n");
sewardjde4a1d02002-03-22 01:27:54 +0000699 stopping_message = True;
700 }
701 return;
702 }
703
sewardjdc873c02011-07-24 16:02:33 +0000704 /* Ignore it if error acquisition is disabled for this thread. */
705 { ThreadState* tst = VG_(get_ThreadState)(tid);
706 if (tst->err_disablement_level > 0)
707 return;
708 }
709
njn14319cc2005-03-13 06:26:22 +0000710 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000711 been found, be much more conservative about collecting new
712 ones. */
sewardj8a051722005-06-30 00:10:16 +0000713 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
714 && !VG_(clo_xml)) {
njn25e49d8e72002-09-23 09:36:25 +0000715 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000716 if (!slowdown_message) {
sewardj738856f2009-07-15 14:48:32 +0000717 VG_(umsg)("\n");
718 VG_(umsg)("More than %d errors detected. Subsequent errors\n",
719 M_COLLECT_ERRORS_SLOWLY_AFTER);
720 VG_(umsg)("will still be recorded, but in less "
721 "detail than before.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000722 slowdown_message = True;
723 }
724 }
725
njn25e49d8e72002-09-23 09:36:25 +0000726 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000727 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000728
729 /* First, see if we've got an error record matching this one. */
sewardj8a7d4e42006-10-17 01:41:17 +0000730 em_errlist_searches++;
731 p = errors;
732 p_prev = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000733 while (p != NULL) {
sewardj8a7d4e42006-10-17 01:41:17 +0000734 em_errlist_cmps++;
njn810086f2002-11-14 12:42:47 +0000735 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000736 /* Found it. */
737 p->count++;
738 if (p->supp != NULL) {
739 /* Deal correctly with suppressed errors. */
740 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000741 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000742 } else {
nethercotef2b11482004-08-02 12:36:01 +0000743 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000744 }
745
746 /* Move p to the front of the list so that future searches
sewardj3b290482011-05-06 21:02:55 +0000747 for it are faster. It also allows to print the last
748 error (see VG_(show_last_error). */
sewardjde4a1d02002-03-22 01:27:54 +0000749 if (p_prev != NULL) {
750 vg_assert(p_prev->next == p);
njn695c16e2005-03-27 03:40:28 +0000751 p_prev->next = p->next;
752 p->next = errors;
753 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000754 }
sewardj7ebf7c32003-07-24 21:29:40 +0000755
sewardjde4a1d02002-03-22 01:27:54 +0000756 return;
757 }
758 p_prev = p;
759 p = p->next;
760 }
761
762 /* Didn't see it. Copy and add. */
763
njn43c799e2003-04-08 00:08:52 +0000764 /* OK, we're really going to collect it. The context is on the stack and
765 will disappear shortly, so we must copy it. First do the main
njn02bc4b82005-05-15 17:28:26 +0000766 (non-'extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000767
njn02bc4b82005-05-15 17:28:26 +0000768 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
njn51d827b2005-05-09 01:02:08 +0000769 is for when there are more details to fill in which take time to work
770 out but don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000771 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000772 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000773
njn02bc4b82005-05-15 17:28:26 +0000774 Then, if there is an 'extra' part, copy it too, using the size that
njn51d827b2005-05-09 01:02:08 +0000775 VG_(tdict).tool_update_extra returned. Also allow for people using
776 the void* extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000777 */
778
779 /* copy main part */
sewardj9c606bd2008-09-18 18:12:50 +0000780 p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000781 *p = err;
njn43c799e2003-04-08 00:08:52 +0000782
njn02bc4b82005-05-15 17:28:26 +0000783 /* update 'extra' */
sewardjb5f6f512005-03-10 23:59:00 +0000784 switch (ekind) {
njna86f29e2006-12-14 02:55:58 +0000785 //(example code, see comment on CoreSuppKind above)
786 //case ThreadErr:
787 // vg_assert(VG_(needs).core_errors);
788 // extra_size = <something>
789 // break;
sewardjb5f6f512005-03-10 23:59:00 +0000790 default:
791 vg_assert(VG_(needs).tool_errors);
njn51d827b2005-05-09 01:02:08 +0000792 extra_size = VG_TDICT_CALL(tool_update_extra, p);
sewardjb5f6f512005-03-10 23:59:00 +0000793 break;
794 }
njn43c799e2003-04-08 00:08:52 +0000795
njn02bc4b82005-05-15 17:28:26 +0000796 /* copy block pointed to by 'extra', if there is one */
sewardjb5f6f512005-03-10 23:59:00 +0000797 if (NULL != p->extra && 0 != extra_size) {
sewardj9c606bd2008-09-18 18:12:50 +0000798 void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
sewardjb5f6f512005-03-10 23:59:00 +0000799 VG_(memcpy)(new_extra, p->extra, extra_size);
800 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000801 }
802
njn695c16e2005-03-27 03:40:28 +0000803 p->next = errors;
njn25e49d8e72002-09-23 09:36:25 +0000804 p->supp = is_suppressible_error(&err);
njn695c16e2005-03-27 03:40:28 +0000805 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000806 if (p->supp == NULL) {
philippebaf69642012-02-15 22:29:30 +0000807 /* update stats */
njn606a4ae2009-08-11 00:52:40 +0000808 n_err_contexts++;
nethercotef2b11482004-08-02 12:36:01 +0000809 n_errs_found++;
philippebaf69642012-02-15 22:29:30 +0000810 n_errs_shown++;
sewardj738856f2009-07-15 14:48:32 +0000811 /* Actually show the error; more complex than you might think. */
sewardj3b290482011-05-06 21:02:55 +0000812 pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml) );
sewardjde4a1d02002-03-22 01:27:54 +0000813 } else {
njn606a4ae2009-08-11 00:52:40 +0000814 n_supp_contexts++;
nethercotef2b11482004-08-02 12:36:01 +0000815 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000816 p->supp->count++;
817 }
818}
819
njn43c799e2003-04-08 00:08:52 +0000820/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000821 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000822 guaranteed to only happen once. This avoids all the recording and
823 comparing stuff. But they can be suppressed; returns True if it is
njn02bc4b82005-05-15 17:28:26 +0000824 suppressed. Bool 'print_error' dictates whether to print the error.
njn18afe5d2009-08-10 08:25:39 +0000825 Bool 'count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000826*/
floriane543f302012-10-21 19:43:43 +0000827Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, const HChar* s,
njn3e884182003-04-15 13:03:23 +0000828 void* extra, ExeContext* where, Bool print_error,
njn18afe5d2009-08-10 08:25:39 +0000829 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000830{
njnfb289bc2007-01-12 23:59:50 +0000831 Error err;
832 Supp *su;
njn43c799e2003-04-08 00:08:52 +0000833
sewardjdc873c02011-07-24 16:02:33 +0000834 /* Ignore it if error acquisition is disabled for this thread. */
835 ThreadState* tst = VG_(get_ThreadState)(tid);
836 if (tst->err_disablement_level > 0)
837 return False; /* ignored, not suppressed */
838
njn43c799e2003-04-08 00:08:52 +0000839 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000840 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000841
842 /* Unless it's suppressed, we're going to show it. Don't need to make
843 a copy, because it's only temporary anyway.
844
njn02bc4b82005-05-15 17:28:26 +0000845 Then update the 'extra' part with VG_(tdict).tool_update_extra),
njn51d827b2005-05-09 01:02:08 +0000846 because that can have an affect on whether it's suppressed. Ignore
847 the size return value of VG_(tdict).tool_update_extra, because we're
njn02bc4b82005-05-15 17:28:26 +0000848 not copying 'extra'. */
njn51d827b2005-05-09 01:02:08 +0000849 (void)VG_TDICT_CALL(tool_update_extra, &err);
njn43c799e2003-04-08 00:08:52 +0000850
njnfb289bc2007-01-12 23:59:50 +0000851 su = is_suppressible_error(&err);
852 if (NULL == su) {
njn606a4ae2009-08-11 00:52:40 +0000853 if (count_error) {
njn18afe5d2009-08-10 08:25:39 +0000854 n_errs_found++;
njn606a4ae2009-08-11 00:52:40 +0000855 n_err_contexts++;
856 }
njn43c799e2003-04-08 00:08:52 +0000857
858 if (print_error) {
sewardj738856f2009-07-15 14:48:32 +0000859 /* update stats */
njnfb289bc2007-01-12 23:59:50 +0000860 n_errs_shown++;
philippebaf69642012-02-15 22:29:30 +0000861 /* Actually show the error; more complex than you might think. */
862 pp_Error(&err, allow_db_attach, VG_(clo_xml));
njn43c799e2003-04-08 00:08:52 +0000863 }
njn43c799e2003-04-08 00:08:52 +0000864 return False;
865
866 } else {
njn663ab792009-08-13 04:24:38 +0000867 if (count_error) {
868 n_errs_suppressed++;
869 n_supp_contexts++;
870 }
njnfb289bc2007-01-12 23:59:50 +0000871 su->count++;
njn43c799e2003-04-08 00:08:52 +0000872 return True;
873 }
874}
875
sewardjde4a1d02002-03-22 01:27:54 +0000876
sewardjde4a1d02002-03-22 01:27:54 +0000877/*------------------------------------------------------------*/
878/*--- Exported fns ---*/
879/*------------------------------------------------------------*/
880
sewardj71bc3cb2005-05-19 00:25:45 +0000881/* Show the used suppressions. Returns False if no suppression
882 got used. */
883static Bool show_used_suppressions ( void )
884{
885 Supp *su;
886 Bool any_supp;
887
sewardj7c9e57c2005-05-24 14:21:45 +0000888 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000889 VG_(printf_xml)("<suppcounts>\n");
sewardj7c9e57c2005-05-24 14:21:45 +0000890
sewardj71bc3cb2005-05-19 00:25:45 +0000891 any_supp = False;
892 for (su = suppressions; su != NULL; su = su->next) {
893 if (su->count <= 0)
894 continue;
sewardj71bc3cb2005-05-19 00:25:45 +0000895 if (VG_(clo_xml)) {
bartb3af9cf2011-10-06 19:08:37 +0000896 VG_(printf_xml)( " <pair>\n"
sewardj738856f2009-07-15 14:48:32 +0000897 " <count>%d</count>\n"
bartb3af9cf2011-10-06 19:08:37 +0000898 " <name>%pS</name>\n"
sewardj738856f2009-07-15 14:48:32 +0000899 " </pair>\n",
900 su->count, su->sname );
sewardj71bc3cb2005-05-19 00:25:45 +0000901 } else {
sewardj2d9e8742009-08-07 15:46:56 +0000902 // blank line before the first shown suppression, if any
903 if (!any_supp)
904 VG_(dmsg)("\n");
905 VG_(dmsg)("used_suppression: %6d %s\n", su->count, su->sname);
sewardj71bc3cb2005-05-19 00:25:45 +0000906 }
sewardj2d9e8742009-08-07 15:46:56 +0000907 any_supp = True;
sewardj71bc3cb2005-05-19 00:25:45 +0000908 }
909
sewardj7c9e57c2005-05-24 14:21:45 +0000910 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000911 VG_(printf_xml)("</suppcounts>\n");
sewardj7c9e57c2005-05-24 14:21:45 +0000912
sewardj71bc3cb2005-05-19 00:25:45 +0000913 return any_supp;
914}
915
sewardj9f297ca2005-05-20 02:29:52 +0000916/* Show all the errors that occurred, and possibly also the
917 suppressions used. */
sewardj3b290482011-05-06 21:02:55 +0000918void VG_(show_all_errors) ( Int verbosity, Bool xml )
sewardjde4a1d02002-03-22 01:27:54 +0000919{
njn810086f2002-11-14 12:42:47 +0000920 Int i, n_min;
njn810086f2002-11-14 12:42:47 +0000921 Error *p, *p_min;
njn810086f2002-11-14 12:42:47 +0000922 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000923
sewardj3b290482011-05-06 21:02:55 +0000924 if (verbosity == 0)
sewardjde4a1d02002-03-22 01:27:54 +0000925 return;
926
njn606a4ae2009-08-11 00:52:40 +0000927 /* If we're printing XML, just show the suppressions and stop. */
sewardj3b290482011-05-06 21:02:55 +0000928 if (xml) {
sewardj71bc3cb2005-05-19 00:25:45 +0000929 (void)show_used_suppressions();
930 return;
931 }
932
933 /* We only get here if not printing XML. */
sewardj738856f2009-07-15 14:48:32 +0000934 VG_(umsg)("ERROR SUMMARY: "
935 "%d errors from %d contexts (suppressed: %d from %d)\n",
936 n_errs_found, n_err_contexts,
937 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000938
sewardj3b290482011-05-06 21:02:55 +0000939 if (verbosity <= 1)
sewardjde4a1d02002-03-22 01:27:54 +0000940 return;
941
sewardj2d9e8742009-08-07 15:46:56 +0000942 // We do the following only at -v or above, and only in non-XML
943 // mode
944
sewardj3b290482011-05-06 21:02:55 +0000945 /* Print the contexts in order of increasing error count.
946 Once an error is shown, we add a huge value to its count to filter it
947 out. After having shown all errors, we reset count to the original value. */
sewardjde4a1d02002-03-22 01:27:54 +0000948 for (i = 0; i < n_err_contexts; i++) {
949 n_min = (1 << 30) - 1;
950 p_min = NULL;
njn695c16e2005-03-27 03:40:28 +0000951 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000952 if (p->supp != NULL) continue;
953 if (p->count < n_min) {
954 n_min = p->count;
955 p_min = p;
956 }
957 }
njn663ab792009-08-13 04:24:38 +0000958 // XXX: this isn't right. See bug 203651.
959 if (p_min == NULL) continue; //VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000960
sewardj738856f2009-07-15 14:48:32 +0000961 VG_(umsg)("\n");
962 VG_(umsg)("%d errors in context %d of %d:\n",
963 p_min->count, i+1, n_err_contexts);
sewardj3b290482011-05-06 21:02:55 +0000964 pp_Error( p_min, False/*allow_db_attach*/, False /* xml */ );
sewardj738856f2009-07-15 14:48:32 +0000965
966 // We're not printing XML -- we'd have exited above if so.
sewardj3b290482011-05-06 21:02:55 +0000967 vg_assert(! xml);
sewardjde4a1d02002-03-22 01:27:54 +0000968
969 if ((i+1 == VG_(clo_dump_error))) {
sewardj7cf4e6b2008-05-01 20:24:26 +0000970 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
sewardjfa8ec112005-01-19 11:55:34 +0000971 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
njn394213a2005-06-19 18:38:24 +0000972 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
sewardj0ec07f32006-01-12 12:32:32 +0000973 /*bbs_done*/0,
974 /*allow redir?*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000975 }
976
sewardj3b290482011-05-06 21:02:55 +0000977 p_min->count = p_min->count + (1 << 30);
sewardjde4a1d02002-03-22 01:27:54 +0000978 }
979
sewardj3b290482011-05-06 21:02:55 +0000980 /* reset the counts, otherwise a 2nd call does not show anything anymore */
981 for (p = errors; p != NULL; p = p->next) {
982 if (p->count >= (1 << 30))
983 p->count = p->count - (1 << 30);
984 }
985
986
sewardj71bc3cb2005-05-19 00:25:45 +0000987 any_supp = show_used_suppressions();
sewardjde4a1d02002-03-22 01:27:54 +0000988
sewardj2d9e8742009-08-07 15:46:56 +0000989 if (any_supp)
sewardj738856f2009-07-15 14:48:32 +0000990 VG_(umsg)("\n");
sewardj2d9e8742009-08-07 15:46:56 +0000991 // reprint this, so users don't have to scroll way up to find
992 // the first printing
993 VG_(umsg)("ERROR SUMMARY: "
994 "%d errors from %d contexts (suppressed: %d from %d)\n",
995 n_errs_found, n_err_contexts, n_errs_suppressed,
996 n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000997}
998
sewardj3b290482011-05-06 21:02:55 +0000999void VG_(show_last_error) ( void )
1000{
1001 if (n_err_contexts == 0) {
1002 VG_(umsg)("No errors yet\n");
1003 return;
1004 }
1005
1006 pp_Error( errors, False/*allow_db_attach*/, False/*xml*/ );
1007}
1008
sewardj9f297ca2005-05-20 02:29:52 +00001009
1010/* Show occurrence counts of all errors, in XML form. */
1011void VG_(show_error_counts_as_XML) ( void )
1012{
1013 Error* err;
sewardj738856f2009-07-15 14:48:32 +00001014 VG_(printf_xml)("<errorcounts>\n");
sewardj9f297ca2005-05-20 02:29:52 +00001015 for (err = errors; err != NULL; err = err->next) {
1016 if (err->supp != NULL)
1017 continue;
1018 if (err->count <= 0)
1019 continue;
sewardj738856f2009-07-15 14:48:32 +00001020 VG_(printf_xml)(" <pair>\n");
1021 VG_(printf_xml)(" <count>%d</count>\n", err->count);
1022 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
1023 VG_(printf_xml)(" </pair>\n");
sewardj9f297ca2005-05-20 02:29:52 +00001024 }
sewardj738856f2009-07-15 14:48:32 +00001025 VG_(printf_xml)("</errorcounts>\n");
njnb6267bd2009-08-12 00:14:16 +00001026 VG_(printf_xml)("\n");
sewardj9f297ca2005-05-20 02:29:52 +00001027}
1028
1029
sewardjde4a1d02002-03-22 01:27:54 +00001030/*------------------------------------------------------------*/
sewardjd7a02db2008-12-12 08:07:49 +00001031/*--- Suppression parsing ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001032/*------------------------------------------------------------*/
1033
sewardj8a7d4e42006-10-17 01:41:17 +00001034/* Get the next char from fd into *out_buf. Returns 1 if success,
1035 0 if eof or < 0 if error. */
1036
florian19f91bb2012-11-10 22:29:54 +00001037static Int get_char ( Int fd, HChar* out_buf )
sewardj8a7d4e42006-10-17 01:41:17 +00001038{
1039 Int r;
florian19f91bb2012-11-10 22:29:54 +00001040 static HChar buf[256];
sewardj8a7d4e42006-10-17 01:41:17 +00001041 static Int buf_size = 0;
1042 static Int buf_used = 0;
sewardj89c5bd82008-10-23 10:15:37 +00001043 vg_assert(buf_size >= 0 && buf_size <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001044 vg_assert(buf_used >= 0 && buf_used <= buf_size);
1045 if (buf_used == buf_size) {
sewardj89c5bd82008-10-23 10:15:37 +00001046 r = VG_(read)(fd, buf, 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001047 if (r < 0) return r; /* read failed */
sewardj89c5bd82008-10-23 10:15:37 +00001048 vg_assert(r >= 0 && r <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001049 buf_size = r;
1050 buf_used = 0;
1051 }
1052 if (buf_size == 0)
1053 return 0; /* eof */
sewardj89c5bd82008-10-23 10:15:37 +00001054 vg_assert(buf_size >= 0 && buf_size <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001055 vg_assert(buf_used >= 0 && buf_used < buf_size);
1056 *out_buf = buf[buf_used];
1057 buf_used++;
1058 return 1;
1059}
1060
philippe2193a7c2012-12-08 17:54:16 +00001061// Get a non blank non comment line.
1062// Returns True if eof.
1063static Bool get_nbnc_line ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00001064{
florian19f91bb2012-11-10 22:29:54 +00001065 HChar* buf = *bufpp;
njn35db56c2009-07-24 07:38:29 +00001066 SizeT nBuf = *nBufp;
florian19f91bb2012-11-10 22:29:54 +00001067 HChar ch;
njn35db56c2009-07-24 07:38:29 +00001068 Int n, i;
sewardjde4a1d02002-03-22 01:27:54 +00001069 while (True) {
philippe2193a7c2012-12-08 17:54:16 +00001070 buf[0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001071 /* First, read until a non-blank char appears. */
1072 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +00001073 n = get_char(fd, &ch);
njn0c0f32a2005-03-26 04:14:01 +00001074 if (n == 1 && !VG_(isspace)(ch)) break;
bart050eec52009-07-27 12:03:03 +00001075 if (n == 1 && ch == '\n' && lineno)
1076 (*lineno)++;
sewardj8a7d4e42006-10-17 01:41:17 +00001077 if (n <= 0) return True;
sewardjde4a1d02002-03-22 01:27:54 +00001078 }
1079
1080 /* Now, read the line into buf. */
1081 i = 0;
1082 buf[i++] = ch; buf[i] = 0;
1083 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +00001084 n = get_char(fd, &ch);
1085 if (n <= 0) return False; /* the next call will return True */
bart050eec52009-07-27 12:03:03 +00001086 if (ch == '\n' && lineno)
1087 (*lineno)++;
sewardjde4a1d02002-03-22 01:27:54 +00001088 if (ch == '\n') break;
njn35db56c2009-07-24 07:38:29 +00001089 if (i > 0 && i == nBuf-1) {
1090 *nBufp = nBuf = nBuf * 2;
1091 #define RIDICULOUS 100000
1092 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really.
1093 "VG_(get_line): line longer than %d chars, aborting\n",
1094 RIDICULOUS);
1095 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1096 }
sewardjde4a1d02002-03-22 01:27:54 +00001097 buf[i++] = ch; buf[i] = 0;
1098 }
njn0c0f32a2005-03-26 04:14:01 +00001099 while (i > 1 && VG_(isspace)(buf[i-1])) {
sewardjde4a1d02002-03-22 01:27:54 +00001100 i--; buf[i] = 0;
1101 };
1102
njn02bc4b82005-05-15 17:28:26 +00001103 /* VG_(printf)("The line is '%s'\n", buf); */
sewardjde4a1d02002-03-22 01:27:54 +00001104 /* Ok, we have a line. If a non-comment line, return.
1105 If a comment line, start all over again. */
1106 if (buf[0] != '#') return False;
1107 }
1108}
1109
philippe2193a7c2012-12-08 17:54:16 +00001110// True if buf starts with fun: or obj: or is ...
1111static Bool is_location_line (HChar* buf)
1112{
1113 return VG_(strncmp)(buf, "fun:", 4) == 0
1114 || VG_(strncmp)(buf, "obj:", 4) == 0
1115 || VG_(strcmp)(buf, "...") == 0;
1116}
1117
1118Bool VG_(get_line) ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno )
1119{
1120 Bool eof = get_nbnc_line (fd, bufpp, nBufp, lineno);
1121
1122 if (eof)
1123 return True;
1124
1125 if (is_location_line(*bufpp))
1126 return True; // Not a extra suppr line
1127 else
1128 return False; // An suppression extra line
1129}
sewardjde4a1d02002-03-22 01:27:54 +00001130
philippe2c5c05e2012-07-26 21:37:36 +00001131/* True if s contains no wildcard (?, *) characters. */
florian19f91bb2012-11-10 22:29:54 +00001132static Bool is_simple_str (const HChar *s)
philippe2c5c05e2012-07-26 21:37:36 +00001133{
philippe2c5c05e2012-07-26 21:37:36 +00001134 while (*s) {
1135 if (*s == '?' || *s == '*')
1136 return False;
1137 s++;
1138 }
1139 return True;
1140}
1141
philippe7d69fd92012-02-26 21:26:00 +00001142/* buf contains the raw name of a caller, supposedly either
sewardjde4a1d02002-03-22 01:27:54 +00001143 fun:some_function_name or
philippe7d69fd92012-02-26 21:26:00 +00001144 obj:some_object_name or
1145 ...
1146 Set p->ty and p->name accordingly.
1147 p->name is allocated and set to the string
1148 after the descriptor (fun: or obj:) part.
sewardjde4a1d02002-03-22 01:27:54 +00001149 Returns False if failed.
1150*/
florian19f91bb2012-11-10 22:29:54 +00001151static Bool setLocationTy ( SuppLoc* p, HChar *buf )
sewardjde4a1d02002-03-22 01:27:54 +00001152{
philippe7d69fd92012-02-26 21:26:00 +00001153 if (VG_(strncmp)(buf, "fun:", 4) == 0) {
1154 p->name = VG_(arena_strdup)(VG_AR_CORE,
1155 "errormgr.sLTy.1", buf+4);
philippe2c5c05e2012-07-26 21:37:36 +00001156 p->name_is_simple_str = is_simple_str (p->name);
sewardjb5f6f512005-03-10 23:59:00 +00001157 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +00001158 return True;
1159 }
philippe7d69fd92012-02-26 21:26:00 +00001160 if (VG_(strncmp)(buf, "obj:", 4) == 0) {
1161 p->name = VG_(arena_strdup)(VG_AR_CORE,
1162 "errormgr.sLTy.2", buf+4);
philippe2c5c05e2012-07-26 21:37:36 +00001163 p->name_is_simple_str = is_simple_str (p->name);
sewardjb5f6f512005-03-10 23:59:00 +00001164 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +00001165 return True;
1166 }
philippe7d69fd92012-02-26 21:26:00 +00001167 if (VG_(strcmp)(buf, "...") == 0) {
sewardj5e519302008-11-03 23:10:25 +00001168 p->name = NULL;
philippe2c5c05e2012-07-26 21:37:36 +00001169 p->name_is_simple_str = False;
sewardj5e519302008-11-03 23:10:25 +00001170 p->ty = DotDotDot;
1171 return True;
1172 }
1173 VG_(printf)("location should be \"...\", or should start "
1174 "with \"fun:\" or \"obj:\"\n");
sewardjde4a1d02002-03-22 01:27:54 +00001175 return False;
1176}
1177
1178
nethercote7cc9c232004-01-21 15:08:04 +00001179/* Look for "tool" in a string like "tool1,tool2,tool3" */
florian19f91bb2012-11-10 22:29:54 +00001180static Bool tool_name_present(const HChar *name, HChar *names)
njn11cc9252002-10-07 14:42:59 +00001181{
1182 Bool found;
florian19f91bb2012-11-10 22:29:54 +00001183 HChar *s = NULL; /* Shut gcc up */
njn11cc9252002-10-07 14:42:59 +00001184 Int len = VG_(strlen)(name);
1185
1186 found = (NULL != (s = VG_(strstr)(names, name)) &&
1187 (s == names || *(s-1) == ',') &&
1188 (*(s+len) == ',' || *(s+len) == '\0')
1189 );
1190
1191 return found;
1192}
1193
njn695c16e2005-03-27 03:40:28 +00001194/* Read suppressions from the file specified in VG_(clo_suppressions)
sewardjde4a1d02002-03-22 01:27:54 +00001195 and place them in the suppressions list. If there's any difficulty
1196 doing this, just give up -- there's no point in trying to recover.
1197*/
florian19f91bb2012-11-10 22:29:54 +00001198static void load_one_suppressions_file ( const HChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00001199{
sewardj92645592005-07-23 09:18:34 +00001200 SysRes sres;
sewardj5e519302008-11-03 23:10:25 +00001201 Int fd, i, j, lineno = 0;
philippe2193a7c2012-12-08 17:54:16 +00001202 Bool got_a_location_line_read_by_tool;
sewardj92645592005-07-23 09:18:34 +00001203 Bool eof;
njn35db56c2009-07-24 07:38:29 +00001204 SizeT nBuf = 200;
florian19f91bb2012-11-10 22:29:54 +00001205 HChar* buf = VG_(malloc)("errormgr.losf.1", nBuf);
1206 HChar* tool_names;
1207 HChar* supp_name;
florian2b8059a2012-10-14 16:45:23 +00001208 const HChar* err_str = NULL;
sewardjb5f6f512005-03-10 23:59:00 +00001209 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +00001210
njncc37d2e2009-06-24 03:49:19 +00001211 // Check it's not a directory.
1212 if (VG_(is_dir)( filename )) {
1213 if (VG_(clo_xml))
sewardj09361bf2011-01-28 00:19:25 +00001214 VG_(printf_xml)("</valgrindoutput>\n");
sewardj738856f2009-07-15 14:48:32 +00001215 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
njncc37d2e2009-06-24 03:49:19 +00001216 VG_(exit)(1);
1217 }
1218
1219 // Open the suppression file.
sewardj92645592005-07-23 09:18:34 +00001220 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
njncda2f0f2009-05-18 02:12:08 +00001221 if (sr_isError(sres)) {
sewardjf349d552005-11-14 17:01:01 +00001222 if (VG_(clo_xml))
sewardj09361bf2011-01-28 00:19:25 +00001223 VG_(printf_xml)("</valgrindoutput>\n");
sewardj738856f2009-07-15 14:48:32 +00001224 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
sewardjde4a1d02002-03-22 01:27:54 +00001225 VG_(exit)(1);
1226 }
njncda2f0f2009-05-18 02:12:08 +00001227 fd = sr_Res(sres);
sewardjde4a1d02002-03-22 01:27:54 +00001228
sewardj92645592005-07-23 09:18:34 +00001229# define BOMB(S) { err_str = S; goto syntax_error; }
sewardjb5f6f512005-03-10 23:59:00 +00001230
sewardjde4a1d02002-03-22 01:27:54 +00001231 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +00001232 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +00001233 Supp* supp;
sewardj9c606bd2008-09-18 18:12:50 +00001234 supp = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
1235 sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +00001236 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001237
1238 // Initialise temporary reading-in buffer.
1239 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
1240 tmp_callers[i].ty = NoName;
philippe2c5c05e2012-07-26 21:37:36 +00001241 tmp_callers[i].name_is_simple_str = False;
sewardjb5f6f512005-03-10 23:59:00 +00001242 tmp_callers[i].name = NULL;
1243 }
1244
njn810086f2002-11-14 12:42:47 +00001245 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001246
philippe2193a7c2012-12-08 17:54:16 +00001247 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
philippe7d69fd92012-02-26 21:26:00 +00001248 if (eof) {
1249 VG_(arena_free)(VG_AR_CORE, supp);
1250 break;
1251 }
sewardjde4a1d02002-03-22 01:27:54 +00001252
sewardjb5f6f512005-03-10 23:59:00 +00001253 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +00001254
philippe2193a7c2012-12-08 17:54:16 +00001255 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
sewardjb5f6f512005-03-10 23:59:00 +00001256
1257 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1258
sewardj9c606bd2008-09-18 18:12:50 +00001259 supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
sewardjde4a1d02002-03-22 01:27:54 +00001260
philippe2193a7c2012-12-08 17:54:16 +00001261 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
njn25e49d8e72002-09-23 09:36:25 +00001262
philippe2193a7c2012-12-08 17:54:16 +00001263 if (eof) BOMB("unexpected end-of-file (expecting tool:suppr)");
sewardjde4a1d02002-03-22 01:27:54 +00001264
njn94065fd2004-11-22 19:26:27 +00001265 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +00001266 i = 0;
1267 while (True) {
1268 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +00001269 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +00001270 i++;
njn25e49d8e72002-09-23 09:36:25 +00001271 }
njnc40c3a82002-10-02 11:02:27 +00001272 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1273
nethercote7cc9c232004-01-21 15:08:04 +00001274 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +00001275 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +00001276
nethercote7cc9c232004-01-21 15:08:04 +00001277 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +00001278 {
sewardjb5f6f512005-03-10 23:59:00 +00001279 // A core suppression
njna86f29e2006-12-14 02:55:58 +00001280 //(example code, see comment on CoreSuppKind above)
1281 //if (VG_STREQ(supp_name, "Thread"))
1282 // supp->skind = ThreadSupp;
1283 //else
sewardjb5f6f512005-03-10 23:59:00 +00001284 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +00001285 }
njn95ec8702004-11-22 16:46:13 +00001286 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +00001287 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +00001288 {
sewardjb5f6f512005-03-10 23:59:00 +00001289 // A tool suppression
njn51d827b2005-05-09 01:02:08 +00001290 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +00001291 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +00001292 } else {
1293 BOMB("unknown tool suppression type");
1294 }
njnc40c3a82002-10-02 11:02:27 +00001295 }
njn25e49d8e72002-09-23 09:36:25 +00001296 else {
sewardjb5f6f512005-03-10 23:59:00 +00001297 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +00001298 while (True) {
philippe2193a7c2012-12-08 17:54:16 +00001299 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1300 if (eof) BOMB("unexpected end-of-file (when skipping suppression)");
njn43c799e2003-04-08 00:08:52 +00001301 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +00001302 break;
1303 }
philippe7d69fd92012-02-26 21:26:00 +00001304 VG_(arena_free)(VG_AR_CORE, supp->sname);
1305 VG_(arena_free)(VG_AR_CORE, supp);
njn25e49d8e72002-09-23 09:36:25 +00001306 continue;
sewardjde4a1d02002-03-22 01:27:54 +00001307 }
1308
philippe2193a7c2012-12-08 17:54:16 +00001309 buf[0] = 0;
1310 // tool_read_extra_suppression_info might read lines
1311 // from fd till a location line.
njn95ec8702004-11-22 16:46:13 +00001312 if (VG_(needs).tool_errors &&
sewardjd7a02db2008-12-12 08:07:49 +00001313 !VG_TDICT_CALL(tool_read_extra_suppression_info,
njn35db56c2009-07-24 07:38:29 +00001314 fd, &buf, &nBuf, supp))
sewardjb5f6f512005-03-10 23:59:00 +00001315 {
1316 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +00001317 }
1318
philippe2193a7c2012-12-08 17:54:16 +00001319 got_a_location_line_read_by_tool = buf[0] != 0 && is_location_line(buf);
1320
sewardj5e519302008-11-03 23:10:25 +00001321 /* the main frame-descriptor reading loop */
sewardjb5f6f512005-03-10 23:59:00 +00001322 i = 0;
1323 while (True) {
philippe2193a7c2012-12-08 17:54:16 +00001324 if (got_a_location_line_read_by_tool) {
1325 got_a_location_line_read_by_tool = False;
1326 eof = False;
1327 } else {
1328 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1329 }
sewardjb5f6f512005-03-10 23:59:00 +00001330 if (eof)
philippe2193a7c2012-12-08 17:54:16 +00001331 BOMB("unexpected end-of-file (when reading stack trace)");
sewardjb5f6f512005-03-10 23:59:00 +00001332 if (VG_STREQ(buf, "}")) {
1333 if (i > 0) {
1334 break;
1335 } else {
1336 BOMB("missing stack trace");
1337 }
1338 }
1339 if (i == VG_MAX_SUPP_CALLERS)
1340 BOMB("too many callers in stack trace");
1341 if (i > 0 && i >= VG_(clo_backtrace_size))
1342 break;
philippe7d69fd92012-02-26 21:26:00 +00001343 if (!setLocationTy(&(tmp_callers[i]), buf))
sewardj5e519302008-11-03 23:10:25 +00001344 BOMB("location should be \"...\", or should start "
1345 "with \"fun:\" or \"obj:\"");
sewardjb5f6f512005-03-10 23:59:00 +00001346 i++;
1347 }
1348
1349 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1350 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +00001351 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +00001352 do {
philippe2193a7c2012-12-08 17:54:16 +00001353 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
sewardjb5f6f512005-03-10 23:59:00 +00001354 } while (!eof && !VG_STREQ(buf, "}"));
1355 }
1356
sewardj5e519302008-11-03 23:10:25 +00001357 // Reject entries which are entirely composed of frame
1358 // level wildcards.
1359 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1360 for (j = 0; j < i; j++) {
1361 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
1362 break;
1363 vg_assert(tmp_callers[j].ty == DotDotDot);
1364 }
1365 vg_assert(j >= 0 && j <= i);
1366 if (j == i) {
1367 // we didn't find any non-"..." entries
1368 BOMB("suppression must contain at least one location "
1369 "line which is not \"...\"");
1370 }
1371
sewardjb5f6f512005-03-10 23:59:00 +00001372 // Copy tmp_callers[] into supp->callers[]
1373 supp->n_callers = i;
sewardj9c606bd2008-09-18 18:12:50 +00001374 supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
1375 i*sizeof(SuppLoc));
sewardjb5f6f512005-03-10 23:59:00 +00001376 for (i = 0; i < supp->n_callers; i++) {
1377 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +00001378 }
1379
njn695c16e2005-03-27 03:40:28 +00001380 supp->next = suppressions;
1381 suppressions = supp;
sewardjde4a1d02002-03-22 01:27:54 +00001382 }
njn35db56c2009-07-24 07:38:29 +00001383 VG_(free)(buf);
sewardjde4a1d02002-03-22 01:27:54 +00001384 VG_(close)(fd);
1385 return;
1386
1387 syntax_error:
sewardjf349d552005-11-14 17:01:01 +00001388 if (VG_(clo_xml))
sewardj09361bf2011-01-28 00:19:25 +00001389 VG_(printf_xml)("</valgrindoutput>\n");
sewardj738856f2009-07-15 14:48:32 +00001390 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
njn6f74a7e2009-03-12 00:06:45 +00001391 filename, lineno );
sewardj738856f2009-07-15 14:48:32 +00001392 VG_(umsg)(" %s\n", err_str );
sewardjb5f6f512005-03-10 23:59:00 +00001393
sewardjde4a1d02002-03-22 01:27:54 +00001394 VG_(close)(fd);
sewardj738856f2009-07-15 14:48:32 +00001395 VG_(umsg)("exiting now.\n");
nethercote8ed8a892004-11-08 13:24:25 +00001396 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001397
sewardjb5f6f512005-03-10 23:59:00 +00001398# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +00001399}
1400
1401
1402void VG_(load_suppressions) ( void )
1403{
1404 Int i;
njn695c16e2005-03-27 03:40:28 +00001405 suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001406 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1407 if (VG_(clo_verbosity) > 1) {
sewardj738856f2009-07-15 14:48:32 +00001408 VG_(dmsg)("Reading suppressions file: %s\n",
1409 VG_(clo_suppressions)[i] );
sewardjde4a1d02002-03-22 01:27:54 +00001410 }
1411 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1412 }
1413}
1414
sewardjd7a02db2008-12-12 08:07:49 +00001415
1416/*------------------------------------------------------------*/
1417/*--- Matching errors to suppressions ---*/
1418/*------------------------------------------------------------*/
1419
1420/* Parameterising functions for the use of VG_(generic_match) in
1421 suppression-vs-error matching. The suppression frames (SuppLoc)
1422 play the role of 'pattern'-element, and the error frames (IPs,
1423 hence simply Addrs) play the role of 'input'. In short then, we're
1424 matching a sequence of Addrs against a pattern composed of a
1425 sequence of SuppLocs.
1426*/
florian3e798632012-11-24 19:41:54 +00001427static Bool supploc_IsStar ( const void* supplocV )
sewardjd7a02db2008-12-12 08:07:49 +00001428{
florian3e798632012-11-24 19:41:54 +00001429 const SuppLoc* supploc = supplocV;
sewardjd7a02db2008-12-12 08:07:49 +00001430 return supploc->ty == DotDotDot;
1431}
1432
florian3e798632012-11-24 19:41:54 +00001433static Bool supploc_IsQuery ( const void* supplocV )
sewardjd7a02db2008-12-12 08:07:49 +00001434{
1435 return False; /* there's no '?' equivalent in the supp syntax */
1436}
1437
philippe13a59522012-08-03 23:11:39 +00001438/* IPtoFunOrObjCompleter is a lazy completer of the IPs
1439 needed to match an error with the suppression patterns.
1440 The matching between an IP and a suppression pattern is done either
1441 with the IP function name or with the IP object name.
1442 First time the fun or obj name is needed for an IP member
1443 of a stack trace, it will be computed and stored in names.
1444 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1445 allocations and the nr of debuginfo search. */
1446typedef
1447 struct {
1448 StackTrace ips; // stack trace we are lazily completing.
1449 UWord n_ips; // nr of elements in ips.
1450
1451 Int* fun_offsets;
1452 // fun_offsets[i] is the offset in names where the
1453 // function name for ips[i] is located.
1454 // An offset -1 means the function name is not yet completed.
1455 Int* obj_offsets;
1456 // Similarly, obj_offsets[i] gives the offset for the
1457 // object name for ips[i] (-1 meaning object name not yet completed).
1458
1459 // All function names and object names will be concatenated
1460 // in names. names is reallocated on demand.
florian19f91bb2012-11-10 22:29:54 +00001461 HChar *names;
philippe13a59522012-08-03 23:11:39 +00001462 Int names_szB; // size of names.
florian19f91bb2012-11-10 22:29:54 +00001463 Int names_free; // offset first free HChar in names.
philippe13a59522012-08-03 23:11:39 +00001464 }
1465 IPtoFunOrObjCompleter;
1466
1467// free the memory in ip2fo.
1468static void clearIPtoFunOrObjCompleter
1469 (IPtoFunOrObjCompleter* ip2fo)
1470{
1471 if (ip2fo->fun_offsets) VG_(free)(ip2fo->fun_offsets);
1472 if (ip2fo->obj_offsets) VG_(free)(ip2fo->obj_offsets);
1473 if (ip2fo->names) VG_(free)(ip2fo->names);
1474}
1475
1476/* foComplete returns the function name or object name for IP.
1477 If needFun, returns the function name for IP
1478 else returns the object name for IP.
1479 The function name or object name will be computed and added in
1480 names if not yet done.
1481 IP must be equal to focompl->ipc[ixIP]. */
florian19f91bb2012-11-10 22:29:54 +00001482static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo,
1483 Addr IP, Int ixIP, Bool needFun)
philippe13a59522012-08-03 23:11:39 +00001484{
1485 vg_assert (ixIP < ip2fo->n_ips);
1486 vg_assert (IP == ip2fo->ips[ixIP]);
1487
1488 // ptr to the offset array for function offsets (if needFun)
1489 // or object offsets (if !needFun).
1490 Int** offsets;
1491 if (needFun)
1492 offsets = &ip2fo->fun_offsets;
1493 else
1494 offsets = &ip2fo->obj_offsets;
1495
1496 // Allocate offsets if not yet done.
1497 if (!*offsets) {
1498 Int i;
1499 *offsets =
1500 VG_(malloc)("foComplete",
1501 ip2fo->n_ips * sizeof(Int));
1502 for (i = 0; i < ip2fo->n_ips; i++)
1503 (*offsets)[i] = -1;
1504 }
1505
1506 // Complete Fun name or Obj name for IP if not yet done.
1507 if ((*offsets)[ixIP] == -1) {
1508 /* Ensure we have ERRTXT_LEN characters available in names */
1509 if (ip2fo->names_szB
1510 < ip2fo->names_free + ERRTXT_LEN) {
1511 ip2fo->names
1512 = VG_(realloc)("foc_names",
1513 ip2fo->names,
1514 ip2fo->names_szB + ERRTXT_LEN);
1515 ip2fo->names_szB += ERRTXT_LEN;
1516 }
florian19f91bb2012-11-10 22:29:54 +00001517 HChar* caller_name = ip2fo->names + ip2fo->names_free;
philippe13a59522012-08-03 23:11:39 +00001518 (*offsets)[ixIP] = ip2fo->names_free;
1519 if (needFun) {
1520 /* Get the function name into 'caller_name', or "???"
1521 if unknown. */
1522 // Nb: C++-mangled names are used in suppressions. Do, though,
1523 // Z-demangle them, since otherwise it's possible to wind
1524 // up comparing "malloc" in the suppression against
1525 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1526 // two of them need to be made to match.
1527 if (!VG_(get_fnname_no_cxx_demangle)(IP, caller_name, ERRTXT_LEN))
1528 VG_(strcpy)(caller_name, "???");
1529 } else {
1530 /* Get the object name into 'caller_name', or "???"
1531 if unknown. */
1532 if (!VG_(get_objname)(IP, caller_name, ERRTXT_LEN))
1533 VG_(strcpy)(caller_name, "???");
1534 }
1535 ip2fo->names_free += VG_(strlen)(caller_name) + 1;
1536 }
1537
1538 return ip2fo->names + (*offsets)[ixIP];
1539}
1540
florian3e798632012-11-24 19:41:54 +00001541static Bool supp_pattEQinp ( const void* supplocV, const void* addrV,
philippe13a59522012-08-03 23:11:39 +00001542 void* inputCompleter, UWord ixAddrV )
sewardjd7a02db2008-12-12 08:07:49 +00001543{
florian3e798632012-11-24 19:41:54 +00001544 const SuppLoc* supploc = supplocV; /* PATTERN */
1545 Addr ip = *(const Addr*)addrV; /* INPUT */
1546 IPtoFunOrObjCompleter* ip2fo = inputCompleter;
florian19f91bb2012-11-10 22:29:54 +00001547 HChar* funobj_name; // Fun or Obj name.
sewardjd7a02db2008-12-12 08:07:49 +00001548
1549 /* So, does this IP address match this suppression-line? */
1550 switch (supploc->ty) {
1551 case DotDotDot:
1552 /* supp_pattEQinp is a callback from VG_(generic_match). As
1553 per the spec thereof (see include/pub_tool_seqmatch.h), we
1554 should never get called with a pattern value for which the
1555 _IsStar or _IsQuery function would return True. Hence
1556 this can't happen. */
1557 vg_assert(0);
1558 case ObjName:
philippe13a59522012-08-03 23:11:39 +00001559 funobj_name = foComplete(ip2fo, ip, ixAddrV, False /*needFun*/);
sewardjd7a02db2008-12-12 08:07:49 +00001560 break;
philippe13a59522012-08-03 23:11:39 +00001561 case FunName:
1562 funobj_name = foComplete(ip2fo, ip, ixAddrV, True /*needFun*/);
sewardjd7a02db2008-12-12 08:07:49 +00001563 break;
1564 default:
1565 vg_assert(0);
1566 }
1567
philippe13a59522012-08-03 23:11:39 +00001568 /* So now we have the function or object name in funobj_name, and
sewardjd7a02db2008-12-12 08:07:49 +00001569 the pattern (at the character level) to match against is in
1570 supploc->name. Hence (and leading to a re-entrant call of
philippe2c5c05e2012-07-26 21:37:36 +00001571 VG_(generic_match) if there is a wildcard character): */
1572 if (supploc->name_is_simple_str)
philippe13a59522012-08-03 23:11:39 +00001573 return VG_(strcmp) (supploc->name, funobj_name) == 0;
philippe2c5c05e2012-07-26 21:37:36 +00001574 else
philippe13a59522012-08-03 23:11:39 +00001575 return VG_(string_match)(supploc->name, funobj_name);
sewardjd7a02db2008-12-12 08:07:49 +00001576}
1577
1578/////////////////////////////////////////////////////
1579
philippe13a59522012-08-03 23:11:39 +00001580static Bool supp_matches_callers(IPtoFunOrObjCompleter* ip2fo, Supp* su)
sewardjd7a02db2008-12-12 08:07:49 +00001581{
1582 /* Unwrap the args and set up the correct parameterisation of
1583 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1584 supp_pattEQinp. */
philippe13a59522012-08-03 23:11:39 +00001585 /* note, StackTrace ip2fo->ips === Addr* */
sewardjd7a02db2008-12-12 08:07:49 +00001586 SuppLoc* supps = su->callers;
1587 UWord n_supps = su->n_callers;
1588 UWord szbPatt = sizeof(SuppLoc);
1589 UWord szbInput = sizeof(Addr);
1590 Bool matchAll = False; /* we just want to match a prefix */
1591 return
1592 VG_(generic_match)(
1593 matchAll,
1594 /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
philippe13a59522012-08-03 23:11:39 +00001595 /*INPUT*/ip2fo->ips, szbInput, ip2fo->n_ips, 0/*initial Ix*/,
1596 supploc_IsStar, supploc_IsQuery, supp_pattEQinp,
1597 ip2fo
sewardjd7a02db2008-12-12 08:07:49 +00001598 );
1599}
1600
1601/////////////////////////////////////////////////////
1602
sewardjb5f6f512005-03-10 23:59:00 +00001603static
njn810086f2002-11-14 12:42:47 +00001604Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +00001605{
njn810086f2002-11-14 12:42:47 +00001606 switch (su->skind) {
njna86f29e2006-12-14 02:55:58 +00001607 //(example code, see comment on CoreSuppKind above)
1608 //case ThreadSupp:
1609 // return (err->ekind == ThreadErr);
njn25e49d8e72002-09-23 09:36:25 +00001610 default:
njn95ec8702004-11-22 16:46:13 +00001611 if (VG_(needs).tool_errors) {
njn51d827b2005-05-09 01:02:08 +00001612 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
njn25e49d8e72002-09-23 09:36:25 +00001613 } else {
1614 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +00001615 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +00001616 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +00001617 err->ekind);
njn67993252004-11-22 18:02:32 +00001618 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +00001619 }
1620 }
1621}
1622
sewardjd7a02db2008-12-12 08:07:49 +00001623/////////////////////////////////////////////////////
sewardj5e519302008-11-03 23:10:25 +00001624
njn810086f2002-11-14 12:42:47 +00001625/* Does an error context match a suppression? ie is this a suppressible
1626 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001627 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001628*/
njn810086f2002-11-14 12:42:47 +00001629static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001630{
njn810086f2002-11-14 12:42:47 +00001631 Supp* su;
sewardj8a7d4e42006-10-17 01:41:17 +00001632 Supp* su_prev;
1633
philippe13a59522012-08-03 23:11:39 +00001634 IPtoFunOrObjCompleter ip2fo;
1635 /* Conceptually, ip2fo contains an array of function names and an array of
1636 object names, corresponding to the array of IP of err->where.
1637 These names are just computed 'on demand' (so once maximum),
1638 then stored (efficiently, avoiding too many allocs) in ip2fo to be re-usable
1639 for the matching of the same IP with the next suppression pattern.
1640
1641 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
1642 of its arguments. It will then pass it to the function
1643 supp_pattEQinp which will then lazily complete the IP function name or
1644 object name inside ip2fo. Next time the fun or obj name for the same
1645 IP is needed (i.e. for the matching with the next suppr pattern), then
1646 the fun or obj name will not be searched again in the debug info. */
1647
sewardj8a7d4e42006-10-17 01:41:17 +00001648 /* stats gathering */
1649 em_supplist_searches++;
sewardjde4a1d02002-03-22 01:27:54 +00001650
philippe13a59522012-08-03 23:11:39 +00001651 /* Prepare the lazy input completer. */
1652 ip2fo.ips = VG_(get_ExeContext_StackTrace)(err->where);
1653 ip2fo.n_ips = VG_(get_ExeContext_n_ips)(err->where);
1654 ip2fo.fun_offsets = NULL;
1655 ip2fo.obj_offsets = NULL;
1656 ip2fo.names = NULL;
1657 ip2fo.names_szB = 0;
1658 ip2fo.names_free = 0;
1659
sewardjde4a1d02002-03-22 01:27:54 +00001660 /* See if the error context matches any suppression. */
sewardj8a7d4e42006-10-17 01:41:17 +00001661 su_prev = NULL;
njn695c16e2005-03-27 03:40:28 +00001662 for (su = suppressions; su != NULL; su = su->next) {
sewardj8a7d4e42006-10-17 01:41:17 +00001663 em_supplist_cmps++;
philippe13a59522012-08-03 23:11:39 +00001664 if (supp_matches_error(su, err)
1665 && supp_matches_callers(&ip2fo, su)) {
sewardj8a7d4e42006-10-17 01:41:17 +00001666 /* got a match. Move this entry to the head of the list
1667 in the hope of making future searches cheaper. */
1668 if (su_prev) {
1669 vg_assert(su_prev->next == su);
1670 su_prev->next = su->next;
1671 su->next = suppressions;
1672 suppressions = su;
1673 }
philippe13a59522012-08-03 23:11:39 +00001674 clearIPtoFunOrObjCompleter(&ip2fo);
njn25e49d8e72002-09-23 09:36:25 +00001675 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001676 }
sewardj8a7d4e42006-10-17 01:41:17 +00001677 su_prev = su;
sewardjde4a1d02002-03-22 01:27:54 +00001678 }
philippe13a59522012-08-03 23:11:39 +00001679 clearIPtoFunOrObjCompleter(&ip2fo);
njn25e49d8e72002-09-23 09:36:25 +00001680 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001681}
1682
sewardj8a7d4e42006-10-17 01:41:17 +00001683/* Show accumulated error-list and suppression-list search stats.
1684*/
1685void VG_(print_errormgr_stats) ( void )
1686{
sewardj738856f2009-07-15 14:48:32 +00001687 VG_(dmsg)(
1688 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
sewardj8a7d4e42006-10-17 01:41:17 +00001689 em_supplist_searches, em_supplist_cmps
1690 );
sewardj738856f2009-07-15 14:48:32 +00001691 VG_(dmsg)(
1692 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
sewardj8a7d4e42006-10-17 01:41:17 +00001693 em_errlist_searches, em_errlist_cmps
1694 );
1695}
1696
sewardjde4a1d02002-03-22 01:27:54 +00001697/*--------------------------------------------------------------------*/
njneb8896b2005-06-04 20:03:55 +00001698/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001699/*--------------------------------------------------------------------*/