blob: 98e9d53a6f128dfb46ea5d09077a7bfc6afa4ff1 [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
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 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
njn606a4ae2009-08-11 00:52:40 +000085/* Running count of unsuppressed error contexts. */
86static UInt n_err_contexts = 0;
87
88/* Running count of suppressed error contexts. */
89static UInt n_supp_contexts = 0;
90
91
sewardjde4a1d02002-03-22 01:27:54 +000092/* forwards ... */
njn810086f2002-11-14 12:42:47 +000093static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000094
sewardjb5f6f512005-03-10 23:59:00 +000095static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000096
sewardj8a7d4e42006-10-17 01:41:17 +000097/* Stats: number of searches of the error list initiated. */
98static UWord em_errlist_searches = 0;
99
100/* Stats: number of comparisons done during error list
101 searching. */
102static UWord em_errlist_cmps = 0;
103
104/* Stats: number of searches of the suppression list initiated. */
105static UWord em_supplist_searches = 0;
106
107/* Stats: number of comparisons done during suppression list
108 searching. */
109static UWord em_supplist_cmps = 0;
110
sewardjde4a1d02002-03-22 01:27:54 +0000111/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +0000112/*--- Error type ---*/
113/*------------------------------------------------------------*/
114
nethercote4a184902004-08-02 12:21:09 +0000115/* Errors. Extensible (via the 'extra' field). Tools can use a normal
njn02bc4b82005-05-15 17:28:26 +0000116 enum (with element values in the normal range (0..)) for 'ekind'.
nethercote4a184902004-08-02 12:21:09 +0000117 Functions for getting/setting the tool-relevant fields are in
njnc7561b92005-06-19 01:24:32 +0000118 include/pub_tool_errormgr.h.
nethercote4a184902004-08-02 12:21:09 +0000119
120 When errors are found and recorded with VG_(maybe_record_error)(), all
121 the tool must do is pass in the four parameters; core will
122 allocate/initialise the error record.
123*/
124struct _Error {
125 struct _Error* next;
sewardjdbada272005-07-02 21:16:30 +0000126 // Unique tag. This gives the error a unique identity (handle) by
127 // which it can be referred to afterwords. Currently only used for
128 // XML printing.
129 UInt unique;
nethercote4a184902004-08-02 12:21:09 +0000130 // NULL if unsuppressed; or ptr to suppression record.
131 Supp* supp;
132 Int count;
nethercote4a184902004-08-02 12:21:09 +0000133
134 // The tool-specific part
sewardjb8b79ad2008-03-03 01:35:41 +0000135 ThreadId tid; // Initialised by core
nethercote4a184902004-08-02 12:21:09 +0000136 ExeContext* where; // Initialised by core
njnd2b17112005-04-19 04:10:25 +0000137 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
nethercote4a184902004-08-02 12:21:09 +0000138 Addr addr; // Used frequently
139 Char* string; // Used frequently
140 void* extra; // For any tool-specific extras
141};
142
sewardjb8b79ad2008-03-03 01:35:41 +0000143
nethercote4a184902004-08-02 12:21:09 +0000144ExeContext* VG_(get_error_where) ( Error* err )
145{
146 return err->where;
147}
148
149ErrorKind VG_(get_error_kind) ( Error* err )
150{
151 return err->ekind;
152}
153
154Addr VG_(get_error_address) ( Error* err )
155{
156 return err->addr;
157}
158
159Char* VG_(get_error_string) ( Error* err )
160{
161 return err->string;
162}
163
164void* VG_(get_error_extra) ( Error* err )
165{
166 return err->extra;
167}
168
nethercotef2b11482004-08-02 12:36:01 +0000169UInt VG_(get_n_errs_found)( void )
170{
171 return n_errs_found;
172}
173
nethercote4a184902004-08-02 12:21:09 +0000174/*------------------------------------------------------------*/
175/*--- Suppression type ---*/
176/*------------------------------------------------------------*/
177
178/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
179 * effectively extend it by defining their own enums in the (0..) range. */
180typedef
181 enum {
njna86f29e2006-12-14 02:55:58 +0000182 // Nb: thread errors are a relic of the time when Valgrind's core
183 // could detect them. This example is left commented-out as an
184 // example should new core errors ever be added.
185 ThreadSupp = -1, /* Matches ThreadErr */
nethercote4a184902004-08-02 12:21:09 +0000186 }
187 CoreSuppKind;
188
sewardjb5f6f512005-03-10 23:59:00 +0000189/* Max number of callers for context in a suppression. */
190#define VG_MAX_SUPP_CALLERS 24
191
nethercote4a184902004-08-02 12:21:09 +0000192/* For each caller specified for a suppression, record the nature of
193 the caller name. Not of interest to tools. */
194typedef
195 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000196 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000197 ObjName, /* Name is of an shared object file. */
sewardj5e519302008-11-03 23:10:25 +0000198 FunName, /* Name is of a function. */
199 DotDotDot /* Frame-level wildcard */
nethercote4a184902004-08-02 12:21:09 +0000200 }
201 SuppLocTy;
202
sewardjb5f6f512005-03-10 23:59:00 +0000203typedef
204 struct {
205 SuppLocTy ty;
sewardj5e519302008-11-03 23:10:25 +0000206 Char* name; /* NULL for NoName and DotDotDot */
sewardjb5f6f512005-03-10 23:59:00 +0000207 }
208 SuppLoc;
209
nethercote4a184902004-08-02 12:21:09 +0000210/* Suppressions. Tools can get/set tool-relevant parts with functions
njnc7561b92005-06-19 01:24:32 +0000211 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000212 Tools can use a normal enum (with element values in the normal range
njn02bc4b82005-05-15 17:28:26 +0000213 (0..)) for 'skind'. */
nethercote4a184902004-08-02 12:21:09 +0000214struct _Supp {
215 struct _Supp* next;
216 Int count; // The number of times this error has been suppressed.
217 Char* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000218
219 // Length of 'callers'
220 Int n_callers;
221 // Array of callers, for matching stack traces. First one (name of fn
222 // where err occurs) is mandatory; rest are optional.
223 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000224
225 /* The tool-specific part */
226 SuppKind skind; // What kind of suppression. Must use the range (0..).
227 Char* string; // String -- use is optional. NULL by default.
228 void* extra; // Anything else -- use is optional. NULL by default.
229};
230
231SuppKind VG_(get_supp_kind) ( Supp* su )
232{
233 return su->skind;
234}
235
236Char* VG_(get_supp_string) ( Supp* su )
237{
238 return su->string;
239}
240
241void* VG_(get_supp_extra) ( Supp* su )
242{
243 return su->extra;
244}
245
246
247void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
248{
249 su->skind = skind;
250}
251
252void VG_(set_supp_string) ( Supp* su, Char* string )
253{
254 su->string = string;
255}
256
257void VG_(set_supp_extra) ( Supp* su, void* extra )
258{
259 su->extra = extra;
260}
261
262
263/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000264/*--- Helper fns ---*/
265/*------------------------------------------------------------*/
266
njn0087c502005-07-01 04:15:36 +0000267// Only show core errors if the tool wants to, we're not running with -q,
268// and were not outputting XML.
269Bool VG_(showing_core_errors)(void)
270{
271 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
272}
273
sewardj738856f2009-07-15 14:48:32 +0000274/* Compare errors, to detect duplicates.
275*/
njn810086f2002-11-14 12:42:47 +0000276static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000277{
njn810086f2002-11-14 12:42:47 +0000278 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000279 return False;
njn25e49d8e72002-09-23 09:36:25 +0000280 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000281 return False;
282
njn810086f2002-11-14 12:42:47 +0000283 switch (e1->ekind) {
njna86f29e2006-12-14 02:55:58 +0000284 //(example code, see comment on CoreSuppKind above)
285 //case ThreadErr:
286 // vg_assert(VG_(needs).core_errors);
287 // return <something>
sewardjde4a1d02002-03-22 01:27:54 +0000288 default:
njn51d827b2005-05-09 01:02:08 +0000289 if (VG_(needs).tool_errors) {
290 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
291 } else {
njn95ec8702004-11-22 16:46:13 +0000292 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000293 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000294 e1->ekind);
njn67993252004-11-22 18:02:32 +0000295 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000296 }
sewardjde4a1d02002-03-22 01:27:54 +0000297 }
298}
299
sewardj738856f2009-07-15 14:48:32 +0000300
sewardj588adef2009-08-15 22:41:51 +0000301/* Helper functions for suppression generation: print a single line of
302 a suppression pseudo-stack-trace, either in XML or text mode. It's
303 important that the behaviour of these two functions exactly
304 corresponds.
sewardj738856f2009-07-15 14:48:32 +0000305*/
306#define ERRTXT_LEN 4096
307
sewardj588adef2009-08-15 22:41:51 +0000308static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque)
sewardjde4a1d02002-03-22 01:27:54 +0000309{
sewardj738856f2009-07-15 14:48:32 +0000310 static UChar buf[ERRTXT_LEN];
sewardj738856f2009-07-15 14:48:32 +0000311 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
sewardj588adef2009-08-15 22:41:51 +0000312 VG_(printf_xml_no_f_c)(" <sframe> <fun>%t</fun> </sframe>\n", buf);
313 } else
314 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
315 VG_(printf_xml_no_f_c)(" <sframe> <obj>%t</obj> </sframe>\n", buf);
sewardj738856f2009-07-15 14:48:32 +0000316 } else {
sewardj588adef2009-08-15 22:41:51 +0000317 VG_(printf_xml_no_f_c)(" <sframe> <obj>*</obj> </sframe>\n");
sewardjde4a1d02002-03-22 01:27:54 +0000318 }
319}
320
sewardj588adef2009-08-15 22:41:51 +0000321static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV)
322{
323 static UChar buf[ERRTXT_LEN];
324 XArray* /* of HChar */ text = (XArray*)textV;
325 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
326 VG_(xaprintf)(text, " fun:%s\n", buf);
327 } else
328 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
329 VG_(xaprintf)(text, " obj:%s\n", buf);
330 } else {
331 VG_(xaprintf)(text, " obj:*\n");
332 }
333}
sewardj738856f2009-07-15 14:48:32 +0000334
335/* Generate a suppression for an error, either in text or XML mode.
336*/
337static void gen_suppression(Error* err)
338{
sewardj588adef2009-08-15 22:41:51 +0000339 Char xtra[256]; /* assumed big enough (is overrun-safe) */
340 Bool anyXtra;
341 Char* name;
342 ExeContext* ec;
343 XArray* /* HChar */ text;
sewardj738856f2009-07-15 14:48:32 +0000344
sewardj588adef2009-08-15 22:41:51 +0000345 const HChar* dummy_name = "insert_a_suppression_name_here";
sewardj738856f2009-07-15 14:48:32 +0000346
sewardj588adef2009-08-15 22:41:51 +0000347 vg_assert(err);
348
349 /* In XML mode, we also need to print the plain text version of the
350 suppresion in a CDATA section. What that really means is, we
351 need to generate the plaintext version both in XML and text
352 mode. So generate it into TEXT. */
353 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
354 VG_(free), sizeof(HChar) );
355 vg_assert(text);
356
357 ec = VG_(get_error_where)(err);
358 vg_assert(ec);
359
360 name = VG_TDICT_CALL(tool_get_error_name, err);
361 if (NULL == name) {
362 VG_(umsg)("(%s does not allow error to be suppressed)\n",
363 VG_(details).name);
364 return;
sewardj738856f2009-07-15 14:48:32 +0000365 }
366
sewardj588adef2009-08-15 22:41:51 +0000367 /* Ok. Generate the plain text version into TEXT. */
368 VG_(xaprintf)(text, "{\n");
369 VG_(xaprintf)(text, " <%s>\n", dummy_name);
370 VG_(xaprintf)(text, " %s:%s\n", VG_(details).name, name);
371
372 VG_(memset)(xtra, 0, sizeof(xtra));
373 anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info,
374 err, xtra, sizeof(xtra));
375 vg_assert(xtra[sizeof(xtra)-1] == 0);
376
377 if (anyXtra)
378 VG_(xaprintf)(text, " %s\n", xtra);
379
sewardj738856f2009-07-15 14:48:32 +0000380 // Print stack trace elements
sewardj2f340eb2011-01-28 00:44:52 +0000381 UInt n_ips = VG_(get_ExeContext_n_ips)(ec);
382 tl_assert(n_ips > 0);
383 if (n_ips > VG_MAX_SUPP_CALLERS)
384 n_ips = VG_MAX_SUPP_CALLERS;
sewardj588adef2009-08-15 22:41:51 +0000385 VG_(apply_StackTrace)(printSuppForIp_nonXML,
386 text,
sewardj738856f2009-07-15 14:48:32 +0000387 VG_(get_ExeContext_StackTrace)(ec),
sewardj2f340eb2011-01-28 00:44:52 +0000388 n_ips);
sewardj738856f2009-07-15 14:48:32 +0000389
sewardj588adef2009-08-15 22:41:51 +0000390 VG_(xaprintf)(text, "}\n");
391 // zero terminate
392 VG_(xaprintf)(text, "%c", (HChar)0 );
393 // VG_(printf) of text
394
395 /* And now display it. */
396 if (! VG_(clo_xml) ) {
397
398 // the simple case
399 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
400
sewardj738856f2009-07-15 14:48:32 +0000401 } else {
sewardj588adef2009-08-15 22:41:51 +0000402
403 /* Now we have to print the XML directly. No need to go to the
404 effort of stuffing it in an XArray, since we won't need it
405 again. */
406 VG_(printf_xml)(" <suppression>\n");
407 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name);
408 VG_(printf_xml_no_f_c)(
409 " <skind>%t:%t</skind>\n", VG_(details).name, name);
410 if (anyXtra)
411 VG_(printf_xml_no_f_c)(" <skaux>%t</skaux>\n", xtra);
412
413 // Print stack trace elements
414 VG_(apply_StackTrace)(printSuppForIp_XML,
415 NULL,
416 VG_(get_ExeContext_StackTrace)(ec),
417 VG_(get_ExeContext_n_ips)(ec));
418
419 // And now the cdata bit
420 // XXX FIXME! properly handle the case where the raw text
421 // itself contains "]]>", as specified in Protocol 4.
422 VG_(printf_xml)(" <rawtext>\n");
423 VG_(printf_xml)("<![CDATA[\n");
sewardjde78f9a2009-08-15 23:33:04 +0000424 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
sewardj588adef2009-08-15 22:41:51 +0000425 VG_(printf_xml)("]]>\n");
426 VG_(printf_xml)(" </rawtext>\n");
427 VG_(printf_xml)(" </suppression>\n");
428
sewardj738856f2009-07-15 14:48:32 +0000429 }
sewardj588adef2009-08-15 22:41:51 +0000430
431 VG_(deleteXA)(text);
sewardj738856f2009-07-15 14:48:32 +0000432}
433
434
435/* Figure out if we want to perform a given action for this error,
436 possibly by asking the user.
437*/
njn43c799e2003-04-08 00:08:52 +0000438Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000439{
440 Char ch, ch2;
441 Int res;
442
sewardj738856f2009-07-15 14:48:32 +0000443 /* First off, we shouldn't be asking the user anything if
444 we're in XML mode. */
445 if (VG_(clo_xml))
446 return False; /* That's a Nein, oder Nay as they say down here in B-W */
447
njn43c799e2003-04-08 00:08:52 +0000448 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000449 return False;
450
sewardj738856f2009-07-15 14:48:32 +0000451 VG_(umsg)("\n");
sewardjde4a1d02002-03-22 01:27:54 +0000452
453 again:
454 VG_(printf)(
455 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000456 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
457 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000458 );
459
sewardj6024b212003-07-13 10:54:33 +0000460 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000461 if (res != 1) goto ioerror;
462 /* res == 1 */
463 if (ch == '\n') return False;
464 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
465 && ch != 'C' && ch != 'c') goto again;
466
sewardj6024b212003-07-13 10:54:33 +0000467 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000468 if (res != 1) goto ioerror;
469 if (ch2 != '\n') goto again;
470
njn43c799e2003-04-08 00:08:52 +0000471 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000472 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000473 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000474 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000475 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000476 vg_assert(ch == 'c' || ch == 'C');
477
478 ioerror:
njn43c799e2003-04-08 00:08:52 +0000479 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000480 return False;
481}
482
483
sewardj738856f2009-07-15 14:48:32 +0000484/* Do text-mode actions on error, that is, immediately after an error
485 is printed. These are:
486 * possibly, attach to a debugger
487 * possibly, generate a suppression.
488 Note this should not be called in XML mode!
489*/
490static
491void do_actions_on_error(Error* err, Bool allow_db_attach)
492{
493 Bool still_noisy = True;
494
495 /* Should be assured by caller */
496 vg_assert( ! VG_(clo_xml) );
497
sewardj3b290482011-05-06 21:02:55 +0000498 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
499 if (VG_(clo_vgdb) != Vg_VgdbNo
500 && allow_db_attach
501 && VG_(dyn_vgdb_error) <= n_errs_found) {
502 VG_(umsg)("(action on error) vgdb me ... \n");
503 VG_(gdbserver)( err->tid );
504 VG_(umsg)("Continuing ...\n");
505 }
506
sewardj738856f2009-07-15 14:48:32 +0000507 /* Perhaps we want a debugger attach at this point? */
sewardj3b290482011-05-06 21:02:55 +0000508 /* GDBTD ??? maybe we should/could remove the below assuming the
509 gdbserver interface is better ??? */
sewardj738856f2009-07-15 14:48:32 +0000510 if (allow_db_attach &&
511 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
512 {
513 if (0) VG_(printf)("starting debugger\n");
514 VG_(start_debugger)( err->tid );
515 }
516 /* Or maybe we want to generate the error's suppression? */
517 if (VG_(clo_gen_suppressions) == 2
518 || (VG_(clo_gen_suppressions) == 1
519 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
520 ) {
521 gen_suppression(err);
522 }
523 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
524 VG_(clo_gen_suppressions) = 0;
525}
526
527
528/* Prints an error. Not entirely simple because of the differences
529 between XML and text mode output.
530
531 In XML mode:
532
533 * calls the tool's pre-show method, so the tool can create any
534 preamble ahead of the message, if it wants.
535
536 * prints the opening tag, and the <unique> and <tid> fields
537
538 * prints the tool-specific parts of the message
539
540 * if suppression generation is required, a suppression
541
542 * the closing tag
543
544 In text mode:
545
546 * calls the tool's pre-show method, so the tool can create any
547 preamble ahead of the message, if it wants.
548
549 * prints the tool-specific parts of the message
550
551 * calls do_actions_on_error. This optionally does a debugger
552 attach (and detach), and optionally prints a suppression; both
553 of these may require user input.
554*/
sewardj3b290482011-05-06 21:02:55 +0000555static void pp_Error ( Error* err, Bool allow_db_attach, Bool xml )
sewardj738856f2009-07-15 14:48:32 +0000556{
557 /* If this fails, you probably specified your tool's method
558 dictionary incorrectly. */
559 vg_assert(VG_(needs).tool_errors);
560
sewardj3b290482011-05-06 21:02:55 +0000561 if (xml) {
sewardj738856f2009-07-15 14:48:32 +0000562
563 /* Note, allow_db_attach is ignored in here. */
564
565 /* Ensure that suppression generation is either completely
566 enabled or completely disabled; either way, we won't require
567 any user input. m_main.process_cmd_line_options should
568 ensure the asserted condition holds. */
569 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
570 || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
571
572 /* Pre-show it to the tool */
573 VG_TDICT_CALL( tool_before_pp_Error, err );
574
575 /* standard preamble */
576 VG_(printf_xml)("<error>\n");
577 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
578 VG_(printf_xml)(" <tid>%d</tid>\n", err->tid);
579
580 /* actually print it */
581 VG_TDICT_CALL( tool_pp_Error, err );
582
583 if (VG_(clo_gen_suppressions) > 0)
584 gen_suppression(err);
585
586 /* postamble */
587 VG_(printf_xml)("</error>\n");
njnb6267bd2009-08-12 00:14:16 +0000588 VG_(printf_xml)("\n");
sewardj738856f2009-07-15 14:48:32 +0000589
590 } else {
591
592 VG_TDICT_CALL( tool_before_pp_Error, err );
593
594 if (VG_(tdict).tool_show_ThreadIDs_for_errors
595 && err->tid > 0 && err->tid != last_tid_printed) {
596 VG_(umsg)("Thread %d:\n", err->tid );
597 last_tid_printed = err->tid;
598 }
599
600 VG_TDICT_CALL( tool_pp_Error, err );
njnb6267bd2009-08-12 00:14:16 +0000601 VG_(umsg)("\n");
sewardj738856f2009-07-15 14:48:32 +0000602
603 do_actions_on_error(err, allow_db_attach);
sewardj738856f2009-07-15 14:48:32 +0000604 }
605}
606
607
sewardjb5f6f512005-03-10 23:59:00 +0000608/* Construct an error */
sewardj738856f2009-07-15 14:48:32 +0000609static
njn72718642003-07-24 08:45:32 +0000610void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
611 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000612{
sewardjdbada272005-07-02 21:16:30 +0000613 /* DO NOT MAKE unique_counter NON-STATIC */
614 static UInt unique_counter = 0;
615
njnca82cc02004-11-22 17:18:48 +0000616 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000617
njn810086f2002-11-14 12:42:47 +0000618 /* Core-only parts */
sewardjdbada272005-07-02 21:16:30 +0000619 err->unique = unique_counter++;
njn25e49d8e72002-09-23 09:36:25 +0000620 err->next = NULL;
621 err->supp = NULL;
622 err->count = 1;
njn72718642003-07-24 08:45:32 +0000623 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000624 if (NULL == where)
sewardjadb102f2007-11-09 23:21:44 +0000625 err->where = VG_(record_ExeContext)( tid, 0 );
njn43c799e2003-04-08 00:08:52 +0000626 else
627 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000628
nethercote996901a2004-08-03 13:29:09 +0000629 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000630 err->ekind = ekind;
631 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000632 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000633 err->string = s;
634
njn25e49d8e72002-09-23 09:36:25 +0000635 /* sanity... */
njn72718642003-07-24 08:45:32 +0000636 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000637}
638
njn83f9e792005-06-11 05:04:09 +0000639
njn43c799e2003-04-08 00:08:52 +0000640
njnfb289bc2007-01-12 23:59:50 +0000641static Int n_errs_shown = 0;
642
njn25e49d8e72002-09-23 09:36:25 +0000643/* Top-level entry point to the error management subsystem.
644 All detected errors are notified here; this routine decides if/when the
645 user should see the error. */
njn72718642003-07-24 08:45:32 +0000646void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000647 ErrorKind ekind, Addr a, Char* s, void* extra )
648{
njn810086f2002-11-14 12:42:47 +0000649 Error err;
650 Error* p;
651 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000652 UInt extra_size;
njn695c16e2005-03-27 03:40:28 +0000653 VgRes exe_res = Vg_MedRes;
654 static Bool stopping_message = False;
655 static Bool slowdown_message = False;
sewardjde4a1d02002-03-22 01:27:54 +0000656
njn14319cc2005-03-13 06:26:22 +0000657 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
658 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000659 have been found, just refuse to collect any more. This stops
660 the burden of the error-management system becoming excessive in
661 extremely buggy programs, although it does make it pretty
662 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000663 if (VG_(clo_error_limit)
njn695c16e2005-03-27 03:40:28 +0000664 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
sewardj8a051722005-06-30 00:10:16 +0000665 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
666 && !VG_(clo_xml)) {
sewardjde4a1d02002-03-22 01:27:54 +0000667 if (!stopping_message) {
sewardj738856f2009-07-15 14:48:32 +0000668 VG_(umsg)("\n");
sewardjf2537be2002-04-24 21:03:47 +0000669
njn695c16e2005-03-27 03:40:28 +0000670 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardj738856f2009-07-15 14:48:32 +0000671 VG_(umsg)(
sewardjf2537be2002-04-24 21:03:47 +0000672 "More than %d different errors detected. "
sewardj738856f2009-07-15 14:48:32 +0000673 "I'm not reporting any more.\n",
njn14319cc2005-03-13 06:26:22 +0000674 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000675 } else {
sewardj738856f2009-07-15 14:48:32 +0000676 VG_(umsg)(
sewardjf2537be2002-04-24 21:03:47 +0000677 "More than %d total errors detected. "
sewardj738856f2009-07-15 14:48:32 +0000678 "I'm not reporting any more.\n",
njn14319cc2005-03-13 06:26:22 +0000679 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000680 }
681
sewardj738856f2009-07-15 14:48:32 +0000682 VG_(umsg)("Final error counts will be inaccurate. "
683 "Go fix your program!\n");
684 VG_(umsg)("Rerun with --error-limit=no to disable "
685 "this cutoff. Note\n");
686 VG_(umsg)("that errors may occur in your program without "
687 "prior warning from\n");
688 VG_(umsg)("Valgrind, because errors are no longer "
689 "being displayed.\n");
690 VG_(umsg)("\n");
sewardjde4a1d02002-03-22 01:27:54 +0000691 stopping_message = True;
692 }
693 return;
694 }
695
njn14319cc2005-03-13 06:26:22 +0000696 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000697 been found, be much more conservative about collecting new
698 ones. */
sewardj8a051722005-06-30 00:10:16 +0000699 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
700 && !VG_(clo_xml)) {
njn25e49d8e72002-09-23 09:36:25 +0000701 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000702 if (!slowdown_message) {
sewardj738856f2009-07-15 14:48:32 +0000703 VG_(umsg)("\n");
704 VG_(umsg)("More than %d errors detected. Subsequent errors\n",
705 M_COLLECT_ERRORS_SLOWLY_AFTER);
706 VG_(umsg)("will still be recorded, but in less "
707 "detail than before.\n");
sewardjde4a1d02002-03-22 01:27:54 +0000708 slowdown_message = True;
709 }
710 }
711
njn25e49d8e72002-09-23 09:36:25 +0000712 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000713 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000714
715 /* First, see if we've got an error record matching this one. */
sewardj8a7d4e42006-10-17 01:41:17 +0000716 em_errlist_searches++;
717 p = errors;
718 p_prev = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000719 while (p != NULL) {
sewardj8a7d4e42006-10-17 01:41:17 +0000720 em_errlist_cmps++;
njn810086f2002-11-14 12:42:47 +0000721 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000722 /* Found it. */
723 p->count++;
724 if (p->supp != NULL) {
725 /* Deal correctly with suppressed errors. */
726 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000727 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000728 } else {
nethercotef2b11482004-08-02 12:36:01 +0000729 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000730 }
731
732 /* Move p to the front of the list so that future searches
sewardj3b290482011-05-06 21:02:55 +0000733 for it are faster. It also allows to print the last
734 error (see VG_(show_last_error). */
sewardjde4a1d02002-03-22 01:27:54 +0000735 if (p_prev != NULL) {
736 vg_assert(p_prev->next == p);
njn695c16e2005-03-27 03:40:28 +0000737 p_prev->next = p->next;
738 p->next = errors;
739 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000740 }
sewardj7ebf7c32003-07-24 21:29:40 +0000741
sewardjde4a1d02002-03-22 01:27:54 +0000742 return;
743 }
744 p_prev = p;
745 p = p->next;
746 }
747
748 /* Didn't see it. Copy and add. */
749
njn43c799e2003-04-08 00:08:52 +0000750 /* OK, we're really going to collect it. The context is on the stack and
751 will disappear shortly, so we must copy it. First do the main
njn02bc4b82005-05-15 17:28:26 +0000752 (non-'extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000753
njn02bc4b82005-05-15 17:28:26 +0000754 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
njn51d827b2005-05-09 01:02:08 +0000755 is for when there are more details to fill in which take time to work
756 out but don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000757 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000758 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000759
njn02bc4b82005-05-15 17:28:26 +0000760 Then, if there is an 'extra' part, copy it too, using the size that
njn51d827b2005-05-09 01:02:08 +0000761 VG_(tdict).tool_update_extra returned. Also allow for people using
762 the void* extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000763 */
764
765 /* copy main part */
sewardj9c606bd2008-09-18 18:12:50 +0000766 p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000767 *p = err;
njn43c799e2003-04-08 00:08:52 +0000768
njn02bc4b82005-05-15 17:28:26 +0000769 /* update 'extra' */
sewardjb5f6f512005-03-10 23:59:00 +0000770 switch (ekind) {
njna86f29e2006-12-14 02:55:58 +0000771 //(example code, see comment on CoreSuppKind above)
772 //case ThreadErr:
773 // vg_assert(VG_(needs).core_errors);
774 // extra_size = <something>
775 // break;
sewardjb5f6f512005-03-10 23:59:00 +0000776 default:
777 vg_assert(VG_(needs).tool_errors);
njn51d827b2005-05-09 01:02:08 +0000778 extra_size = VG_TDICT_CALL(tool_update_extra, p);
sewardjb5f6f512005-03-10 23:59:00 +0000779 break;
780 }
njn43c799e2003-04-08 00:08:52 +0000781
njn02bc4b82005-05-15 17:28:26 +0000782 /* copy block pointed to by 'extra', if there is one */
sewardjb5f6f512005-03-10 23:59:00 +0000783 if (NULL != p->extra && 0 != extra_size) {
sewardj9c606bd2008-09-18 18:12:50 +0000784 void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
sewardjb5f6f512005-03-10 23:59:00 +0000785 VG_(memcpy)(new_extra, p->extra, extra_size);
786 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000787 }
788
njn695c16e2005-03-27 03:40:28 +0000789 p->next = errors;
njn25e49d8e72002-09-23 09:36:25 +0000790 p->supp = is_suppressible_error(&err);
njn695c16e2005-03-27 03:40:28 +0000791 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000792 if (p->supp == NULL) {
njn606a4ae2009-08-11 00:52:40 +0000793 n_err_contexts++;
nethercotef2b11482004-08-02 12:36:01 +0000794 n_errs_found++;
sewardj738856f2009-07-15 14:48:32 +0000795 /* Actually show the error; more complex than you might think. */
sewardj3b290482011-05-06 21:02:55 +0000796 pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml) );
sewardj738856f2009-07-15 14:48:32 +0000797 /* update stats */
njn695c16e2005-03-27 03:40:28 +0000798 n_errs_shown++;
sewardjde4a1d02002-03-22 01:27:54 +0000799 } else {
njn606a4ae2009-08-11 00:52:40 +0000800 n_supp_contexts++;
nethercotef2b11482004-08-02 12:36:01 +0000801 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000802 p->supp->count++;
803 }
804}
805
njn43c799e2003-04-08 00:08:52 +0000806/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000807 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000808 guaranteed to only happen once. This avoids all the recording and
809 comparing stuff. But they can be suppressed; returns True if it is
njn02bc4b82005-05-15 17:28:26 +0000810 suppressed. Bool 'print_error' dictates whether to print the error.
njn18afe5d2009-08-10 08:25:39 +0000811 Bool 'count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000812*/
njn72718642003-07-24 08:45:32 +0000813Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000814 void* extra, ExeContext* where, Bool print_error,
njn18afe5d2009-08-10 08:25:39 +0000815 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000816{
njnfb289bc2007-01-12 23:59:50 +0000817 Error err;
818 Supp *su;
njn43c799e2003-04-08 00:08:52 +0000819
820 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000821 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000822
823 /* Unless it's suppressed, we're going to show it. Don't need to make
824 a copy, because it's only temporary anyway.
825
njn02bc4b82005-05-15 17:28:26 +0000826 Then update the 'extra' part with VG_(tdict).tool_update_extra),
njn51d827b2005-05-09 01:02:08 +0000827 because that can have an affect on whether it's suppressed. Ignore
828 the size return value of VG_(tdict).tool_update_extra, because we're
njn02bc4b82005-05-15 17:28:26 +0000829 not copying 'extra'. */
njn51d827b2005-05-09 01:02:08 +0000830 (void)VG_TDICT_CALL(tool_update_extra, &err);
njn43c799e2003-04-08 00:08:52 +0000831
njnfb289bc2007-01-12 23:59:50 +0000832 su = is_suppressible_error(&err);
833 if (NULL == su) {
njn606a4ae2009-08-11 00:52:40 +0000834 if (count_error) {
njn18afe5d2009-08-10 08:25:39 +0000835 n_errs_found++;
njn606a4ae2009-08-11 00:52:40 +0000836 n_err_contexts++;
837 }
njn43c799e2003-04-08 00:08:52 +0000838
839 if (print_error) {
sewardj738856f2009-07-15 14:48:32 +0000840 /* Actually show the error; more complex than you might think. */
sewardj3b290482011-05-06 21:02:55 +0000841 pp_Error(&err, allow_db_attach, VG_(clo_xml));
sewardj738856f2009-07-15 14:48:32 +0000842 /* update stats */
njnfb289bc2007-01-12 23:59:50 +0000843 n_errs_shown++;
njn43c799e2003-04-08 00:08:52 +0000844 }
njn43c799e2003-04-08 00:08:52 +0000845 return False;
846
847 } else {
njn663ab792009-08-13 04:24:38 +0000848 if (count_error) {
849 n_errs_suppressed++;
850 n_supp_contexts++;
851 }
njnfb289bc2007-01-12 23:59:50 +0000852 su->count++;
njn43c799e2003-04-08 00:08:52 +0000853 return True;
854 }
855}
856
sewardjde4a1d02002-03-22 01:27:54 +0000857
sewardjde4a1d02002-03-22 01:27:54 +0000858/*------------------------------------------------------------*/
859/*--- Exported fns ---*/
860/*------------------------------------------------------------*/
861
sewardj71bc3cb2005-05-19 00:25:45 +0000862/* Show the used suppressions. Returns False if no suppression
863 got used. */
864static Bool show_used_suppressions ( void )
865{
866 Supp *su;
867 Bool any_supp;
868
sewardj7c9e57c2005-05-24 14:21:45 +0000869 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000870 VG_(printf_xml)("<suppcounts>\n");
sewardj7c9e57c2005-05-24 14:21:45 +0000871
sewardj71bc3cb2005-05-19 00:25:45 +0000872 any_supp = False;
873 for (su = suppressions; su != NULL; su = su->next) {
874 if (su->count <= 0)
875 continue;
sewardj71bc3cb2005-05-19 00:25:45 +0000876 if (VG_(clo_xml)) {
sewardj738856f2009-07-15 14:48:32 +0000877 VG_(printf_xml_no_f_c)( " <pair>\n"
878 " <count>%d</count>\n"
879 " <name>%t</name>\n"
880 " </pair>\n",
881 su->count, su->sname );
sewardj71bc3cb2005-05-19 00:25:45 +0000882 } else {
sewardj2d9e8742009-08-07 15:46:56 +0000883 // blank line before the first shown suppression, if any
884 if (!any_supp)
885 VG_(dmsg)("\n");
886 VG_(dmsg)("used_suppression: %6d %s\n", su->count, su->sname);
sewardj71bc3cb2005-05-19 00:25:45 +0000887 }
sewardj2d9e8742009-08-07 15:46:56 +0000888 any_supp = True;
sewardj71bc3cb2005-05-19 00:25:45 +0000889 }
890
sewardj7c9e57c2005-05-24 14:21:45 +0000891 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000892 VG_(printf_xml)("</suppcounts>\n");
sewardj7c9e57c2005-05-24 14:21:45 +0000893
sewardj71bc3cb2005-05-19 00:25:45 +0000894 return any_supp;
895}
896
sewardj9f297ca2005-05-20 02:29:52 +0000897/* Show all the errors that occurred, and possibly also the
898 suppressions used. */
sewardj3b290482011-05-06 21:02:55 +0000899void VG_(show_all_errors) ( Int verbosity, Bool xml )
sewardjde4a1d02002-03-22 01:27:54 +0000900{
njn810086f2002-11-14 12:42:47 +0000901 Int i, n_min;
njn810086f2002-11-14 12:42:47 +0000902 Error *p, *p_min;
njn810086f2002-11-14 12:42:47 +0000903 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000904
sewardj3b290482011-05-06 21:02:55 +0000905 if (verbosity == 0)
sewardjde4a1d02002-03-22 01:27:54 +0000906 return;
907
njn606a4ae2009-08-11 00:52:40 +0000908 /* If we're printing XML, just show the suppressions and stop. */
sewardj3b290482011-05-06 21:02:55 +0000909 if (xml) {
sewardj71bc3cb2005-05-19 00:25:45 +0000910 (void)show_used_suppressions();
911 return;
912 }
913
914 /* We only get here if not printing XML. */
sewardj738856f2009-07-15 14:48:32 +0000915 VG_(umsg)("ERROR SUMMARY: "
916 "%d errors from %d contexts (suppressed: %d from %d)\n",
917 n_errs_found, n_err_contexts,
918 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000919
sewardj3b290482011-05-06 21:02:55 +0000920 if (verbosity <= 1)
sewardjde4a1d02002-03-22 01:27:54 +0000921 return;
922
sewardj2d9e8742009-08-07 15:46:56 +0000923 // We do the following only at -v or above, and only in non-XML
924 // mode
925
sewardj3b290482011-05-06 21:02:55 +0000926 /* Print the contexts in order of increasing error count.
927 Once an error is shown, we add a huge value to its count to filter it
928 out. After having shown all errors, we reset count to the original value. */
sewardjde4a1d02002-03-22 01:27:54 +0000929 for (i = 0; i < n_err_contexts; i++) {
930 n_min = (1 << 30) - 1;
931 p_min = NULL;
njn695c16e2005-03-27 03:40:28 +0000932 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000933 if (p->supp != NULL) continue;
934 if (p->count < n_min) {
935 n_min = p->count;
936 p_min = p;
937 }
938 }
njn663ab792009-08-13 04:24:38 +0000939 // XXX: this isn't right. See bug 203651.
940 if (p_min == NULL) continue; //VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000941
sewardj738856f2009-07-15 14:48:32 +0000942 VG_(umsg)("\n");
943 VG_(umsg)("%d errors in context %d of %d:\n",
944 p_min->count, i+1, n_err_contexts);
sewardj3b290482011-05-06 21:02:55 +0000945 pp_Error( p_min, False/*allow_db_attach*/, False /* xml */ );
sewardj738856f2009-07-15 14:48:32 +0000946
947 // We're not printing XML -- we'd have exited above if so.
sewardj3b290482011-05-06 21:02:55 +0000948 vg_assert(! xml);
sewardjde4a1d02002-03-22 01:27:54 +0000949
950 if ((i+1 == VG_(clo_dump_error))) {
sewardj7cf4e6b2008-05-01 20:24:26 +0000951 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
sewardjfa8ec112005-01-19 11:55:34 +0000952 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
njn394213a2005-06-19 18:38:24 +0000953 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
sewardj0ec07f32006-01-12 12:32:32 +0000954 /*bbs_done*/0,
955 /*allow redir?*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000956 }
957
sewardj3b290482011-05-06 21:02:55 +0000958 p_min->count = p_min->count + (1 << 30);
sewardjde4a1d02002-03-22 01:27:54 +0000959 }
960
sewardj3b290482011-05-06 21:02:55 +0000961 /* reset the counts, otherwise a 2nd call does not show anything anymore */
962 for (p = errors; p != NULL; p = p->next) {
963 if (p->count >= (1 << 30))
964 p->count = p->count - (1 << 30);
965 }
966
967
sewardj71bc3cb2005-05-19 00:25:45 +0000968 any_supp = show_used_suppressions();
sewardjde4a1d02002-03-22 01:27:54 +0000969
sewardj2d9e8742009-08-07 15:46:56 +0000970 if (any_supp)
sewardj738856f2009-07-15 14:48:32 +0000971 VG_(umsg)("\n");
sewardj2d9e8742009-08-07 15:46:56 +0000972 // reprint this, so users don't have to scroll way up to find
973 // the first printing
974 VG_(umsg)("ERROR SUMMARY: "
975 "%d errors from %d contexts (suppressed: %d from %d)\n",
976 n_errs_found, n_err_contexts, n_errs_suppressed,
977 n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000978}
979
sewardj3b290482011-05-06 21:02:55 +0000980void VG_(show_last_error) ( void )
981{
982 if (n_err_contexts == 0) {
983 VG_(umsg)("No errors yet\n");
984 return;
985 }
986
987 pp_Error( errors, False/*allow_db_attach*/, False/*xml*/ );
988}
989
sewardj9f297ca2005-05-20 02:29:52 +0000990
991/* Show occurrence counts of all errors, in XML form. */
992void VG_(show_error_counts_as_XML) ( void )
993{
994 Error* err;
sewardj738856f2009-07-15 14:48:32 +0000995 VG_(printf_xml)("<errorcounts>\n");
sewardj9f297ca2005-05-20 02:29:52 +0000996 for (err = errors; err != NULL; err = err->next) {
997 if (err->supp != NULL)
998 continue;
999 if (err->count <= 0)
1000 continue;
sewardj738856f2009-07-15 14:48:32 +00001001 VG_(printf_xml)(" <pair>\n");
1002 VG_(printf_xml)(" <count>%d</count>\n", err->count);
1003 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
1004 VG_(printf_xml)(" </pair>\n");
sewardj9f297ca2005-05-20 02:29:52 +00001005 }
sewardj738856f2009-07-15 14:48:32 +00001006 VG_(printf_xml)("</errorcounts>\n");
njnb6267bd2009-08-12 00:14:16 +00001007 VG_(printf_xml)("\n");
sewardj9f297ca2005-05-20 02:29:52 +00001008}
1009
1010
sewardjde4a1d02002-03-22 01:27:54 +00001011/*------------------------------------------------------------*/
sewardjd7a02db2008-12-12 08:07:49 +00001012/*--- Suppression parsing ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001013/*------------------------------------------------------------*/
1014
sewardj8a7d4e42006-10-17 01:41:17 +00001015/* Get the next char from fd into *out_buf. Returns 1 if success,
1016 0 if eof or < 0 if error. */
1017
1018static Int get_char ( Int fd, Char* out_buf )
1019{
1020 Int r;
sewardj89c5bd82008-10-23 10:15:37 +00001021 static Char buf[256];
sewardj8a7d4e42006-10-17 01:41:17 +00001022 static Int buf_size = 0;
1023 static Int buf_used = 0;
sewardj89c5bd82008-10-23 10:15:37 +00001024 vg_assert(buf_size >= 0 && buf_size <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001025 vg_assert(buf_used >= 0 && buf_used <= buf_size);
1026 if (buf_used == buf_size) {
sewardj89c5bd82008-10-23 10:15:37 +00001027 r = VG_(read)(fd, buf, 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001028 if (r < 0) return r; /* read failed */
sewardj89c5bd82008-10-23 10:15:37 +00001029 vg_assert(r >= 0 && r <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001030 buf_size = r;
1031 buf_used = 0;
1032 }
1033 if (buf_size == 0)
1034 return 0; /* eof */
sewardj89c5bd82008-10-23 10:15:37 +00001035 vg_assert(buf_size >= 0 && buf_size <= 256);
sewardj8a7d4e42006-10-17 01:41:17 +00001036 vg_assert(buf_used >= 0 && buf_used < buf_size);
1037 *out_buf = buf[buf_used];
1038 buf_used++;
1039 return 1;
1040}
1041
bart050eec52009-07-27 12:03:03 +00001042Bool VG_(get_line) ( Int fd, Char** bufpp, SizeT* nBufp, Int* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00001043{
njn35db56c2009-07-24 07:38:29 +00001044 Char* buf = *bufpp;
1045 SizeT nBuf = *nBufp;
1046 Char ch;
1047 Int n, i;
sewardjde4a1d02002-03-22 01:27:54 +00001048 while (True) {
1049 /* First, read until a non-blank char appears. */
1050 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +00001051 n = get_char(fd, &ch);
njn0c0f32a2005-03-26 04:14:01 +00001052 if (n == 1 && !VG_(isspace)(ch)) break;
bart050eec52009-07-27 12:03:03 +00001053 if (n == 1 && ch == '\n' && lineno)
1054 (*lineno)++;
sewardj8a7d4e42006-10-17 01:41:17 +00001055 if (n <= 0) return True;
sewardjde4a1d02002-03-22 01:27:54 +00001056 }
1057
1058 /* Now, read the line into buf. */
1059 i = 0;
1060 buf[i++] = ch; buf[i] = 0;
1061 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +00001062 n = get_char(fd, &ch);
1063 if (n <= 0) return False; /* the next call will return True */
bart050eec52009-07-27 12:03:03 +00001064 if (ch == '\n' && lineno)
1065 (*lineno)++;
sewardjde4a1d02002-03-22 01:27:54 +00001066 if (ch == '\n') break;
njn35db56c2009-07-24 07:38:29 +00001067 if (i > 0 && i == nBuf-1) {
1068 *nBufp = nBuf = nBuf * 2;
1069 #define RIDICULOUS 100000
1070 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really.
1071 "VG_(get_line): line longer than %d chars, aborting\n",
1072 RIDICULOUS);
1073 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1074 }
sewardjde4a1d02002-03-22 01:27:54 +00001075 buf[i++] = ch; buf[i] = 0;
1076 }
njn0c0f32a2005-03-26 04:14:01 +00001077 while (i > 1 && VG_(isspace)(buf[i-1])) {
sewardjde4a1d02002-03-22 01:27:54 +00001078 i--; buf[i] = 0;
1079 };
1080
njn02bc4b82005-05-15 17:28:26 +00001081 /* VG_(printf)("The line is '%s'\n", buf); */
sewardjde4a1d02002-03-22 01:27:54 +00001082 /* Ok, we have a line. If a non-comment line, return.
1083 If a comment line, start all over again. */
1084 if (buf[0] != '#') return False;
1085 }
1086}
1087
1088
1089/* *p_caller contains the raw name of a caller, supposedly either
1090 fun:some_function_name or
1091 obj:some_object_name.
1092 Set *p_ty accordingly and advance *p_caller over the descriptor
1093 (fun: or obj:) part.
1094 Returns False if failed.
1095*/
sewardjb5f6f512005-03-10 23:59:00 +00001096static Bool setLocationTy ( SuppLoc* p )
sewardjde4a1d02002-03-22 01:27:54 +00001097{
sewardjb5f6f512005-03-10 23:59:00 +00001098 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
1099 p->name += 4;
1100 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +00001101 return True;
1102 }
sewardjb5f6f512005-03-10 23:59:00 +00001103 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
1104 p->name += 4;
1105 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +00001106 return True;
1107 }
sewardj5e519302008-11-03 23:10:25 +00001108 if (VG_(strcmp)(p->name, "...") == 0) {
1109 p->name = NULL;
1110 p->ty = DotDotDot;
1111 return True;
1112 }
1113 VG_(printf)("location should be \"...\", or should start "
1114 "with \"fun:\" or \"obj:\"\n");
sewardjde4a1d02002-03-22 01:27:54 +00001115 return False;
1116}
1117
1118
nethercote7cc9c232004-01-21 15:08:04 +00001119/* Look for "tool" in a string like "tool1,tool2,tool3" */
sewardjd7a02db2008-12-12 08:07:49 +00001120static Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +00001121{
1122 Bool found;
1123 Char *s = NULL; /* Shut gcc up */
1124 Int len = VG_(strlen)(name);
1125
1126 found = (NULL != (s = VG_(strstr)(names, name)) &&
1127 (s == names || *(s-1) == ',') &&
1128 (*(s+len) == ',' || *(s+len) == '\0')
1129 );
1130
1131 return found;
1132}
1133
njn695c16e2005-03-27 03:40:28 +00001134/* Read suppressions from the file specified in VG_(clo_suppressions)
sewardjde4a1d02002-03-22 01:27:54 +00001135 and place them in the suppressions list. If there's any difficulty
1136 doing this, just give up -- there's no point in trying to recover.
1137*/
sewardjde4a1d02002-03-22 01:27:54 +00001138static void load_one_suppressions_file ( Char* filename )
1139{
sewardj92645592005-07-23 09:18:34 +00001140 SysRes sres;
sewardj5e519302008-11-03 23:10:25 +00001141 Int fd, i, j, lineno = 0;
sewardj92645592005-07-23 09:18:34 +00001142 Bool eof;
njn35db56c2009-07-24 07:38:29 +00001143 SizeT nBuf = 200;
1144 Char* buf = VG_(malloc)("errormgr.losf.1", nBuf);
sewardj92645592005-07-23 09:18:34 +00001145 Char* tool_names;
1146 Char* supp_name;
1147 Char* err_str = NULL;
sewardjb5f6f512005-03-10 23:59:00 +00001148 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +00001149
njncc37d2e2009-06-24 03:49:19 +00001150 // Check it's not a directory.
1151 if (VG_(is_dir)( filename )) {
1152 if (VG_(clo_xml))
sewardj09361bf2011-01-28 00:19:25 +00001153 VG_(printf_xml)("</valgrindoutput>\n");
sewardj738856f2009-07-15 14:48:32 +00001154 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
njncc37d2e2009-06-24 03:49:19 +00001155 VG_(exit)(1);
1156 }
1157
1158 // Open the suppression file.
sewardj92645592005-07-23 09:18:34 +00001159 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
njncda2f0f2009-05-18 02:12:08 +00001160 if (sr_isError(sres)) {
sewardjf349d552005-11-14 17:01:01 +00001161 if (VG_(clo_xml))
sewardj09361bf2011-01-28 00:19:25 +00001162 VG_(printf_xml)("</valgrindoutput>\n");
sewardj738856f2009-07-15 14:48:32 +00001163 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
sewardjde4a1d02002-03-22 01:27:54 +00001164 VG_(exit)(1);
1165 }
njncda2f0f2009-05-18 02:12:08 +00001166 fd = sr_Res(sres);
sewardjde4a1d02002-03-22 01:27:54 +00001167
sewardj92645592005-07-23 09:18:34 +00001168# define BOMB(S) { err_str = S; goto syntax_error; }
sewardjb5f6f512005-03-10 23:59:00 +00001169
sewardjde4a1d02002-03-22 01:27:54 +00001170 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +00001171 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +00001172 Supp* supp;
sewardj9c606bd2008-09-18 18:12:50 +00001173 supp = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
1174 sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +00001175 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001176
1177 // Initialise temporary reading-in buffer.
1178 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
1179 tmp_callers[i].ty = NoName;
1180 tmp_callers[i].name = NULL;
1181 }
1182
njn810086f2002-11-14 12:42:47 +00001183 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001184
bart050eec52009-07-27 12:03:03 +00001185 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
sewardjde4a1d02002-03-22 01:27:54 +00001186 if (eof) break;
1187
sewardjb5f6f512005-03-10 23:59:00 +00001188 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +00001189
bart050eec52009-07-27 12:03:03 +00001190 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
sewardjb5f6f512005-03-10 23:59:00 +00001191
1192 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1193
sewardj9c606bd2008-09-18 18:12:50 +00001194 supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
sewardjde4a1d02002-03-22 01:27:54 +00001195
bart050eec52009-07-27 12:03:03 +00001196 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
njn25e49d8e72002-09-23 09:36:25 +00001197
sewardjb5f6f512005-03-10 23:59:00 +00001198 if (eof) BOMB("unexpected end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +00001199
njn94065fd2004-11-22 19:26:27 +00001200 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +00001201 i = 0;
1202 while (True) {
1203 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +00001204 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +00001205 i++;
njn25e49d8e72002-09-23 09:36:25 +00001206 }
njnc40c3a82002-10-02 11:02:27 +00001207 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1208
nethercote7cc9c232004-01-21 15:08:04 +00001209 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +00001210 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +00001211
nethercote7cc9c232004-01-21 15:08:04 +00001212 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +00001213 {
sewardjb5f6f512005-03-10 23:59:00 +00001214 // A core suppression
njna86f29e2006-12-14 02:55:58 +00001215 //(example code, see comment on CoreSuppKind above)
1216 //if (VG_STREQ(supp_name, "Thread"))
1217 // supp->skind = ThreadSupp;
1218 //else
sewardjb5f6f512005-03-10 23:59:00 +00001219 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +00001220 }
njn95ec8702004-11-22 16:46:13 +00001221 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +00001222 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +00001223 {
sewardjb5f6f512005-03-10 23:59:00 +00001224 // A tool suppression
njn51d827b2005-05-09 01:02:08 +00001225 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +00001226 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +00001227 } else {
1228 BOMB("unknown tool suppression type");
1229 }
njnc40c3a82002-10-02 11:02:27 +00001230 }
njn25e49d8e72002-09-23 09:36:25 +00001231 else {
sewardjb5f6f512005-03-10 23:59:00 +00001232 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +00001233 while (True) {
bart050eec52009-07-27 12:03:03 +00001234 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
sewardjb5f6f512005-03-10 23:59:00 +00001235 if (eof) BOMB("unexpected end-of-file");
njn43c799e2003-04-08 00:08:52 +00001236 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +00001237 break;
1238 }
1239 continue;
sewardjde4a1d02002-03-22 01:27:54 +00001240 }
1241
njn95ec8702004-11-22 16:46:13 +00001242 if (VG_(needs).tool_errors &&
sewardjd7a02db2008-12-12 08:07:49 +00001243 !VG_TDICT_CALL(tool_read_extra_suppression_info,
njn35db56c2009-07-24 07:38:29 +00001244 fd, &buf, &nBuf, supp))
sewardjb5f6f512005-03-10 23:59:00 +00001245 {
1246 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +00001247 }
1248
sewardj5e519302008-11-03 23:10:25 +00001249 /* the main frame-descriptor reading loop */
sewardjb5f6f512005-03-10 23:59:00 +00001250 i = 0;
1251 while (True) {
bart050eec52009-07-27 12:03:03 +00001252 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
sewardjb5f6f512005-03-10 23:59:00 +00001253 if (eof)
1254 BOMB("unexpected end-of-file");
1255 if (VG_STREQ(buf, "}")) {
1256 if (i > 0) {
1257 break;
1258 } else {
1259 BOMB("missing stack trace");
1260 }
1261 }
1262 if (i == VG_MAX_SUPP_CALLERS)
1263 BOMB("too many callers in stack trace");
1264 if (i > 0 && i >= VG_(clo_backtrace_size))
1265 break;
sewardj9c606bd2008-09-18 18:12:50 +00001266 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE,
1267 "errormgr.losf.3", buf);
sewardjb5f6f512005-03-10 23:59:00 +00001268 if (!setLocationTy(&(tmp_callers[i])))
sewardj5e519302008-11-03 23:10:25 +00001269 BOMB("location should be \"...\", or should start "
1270 "with \"fun:\" or \"obj:\"");
sewardjb5f6f512005-03-10 23:59:00 +00001271 i++;
1272 }
1273
1274 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1275 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +00001276 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +00001277 do {
bart050eec52009-07-27 12:03:03 +00001278 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
sewardjb5f6f512005-03-10 23:59:00 +00001279 } while (!eof && !VG_STREQ(buf, "}"));
1280 }
1281
sewardj5e519302008-11-03 23:10:25 +00001282 // Reject entries which are entirely composed of frame
1283 // level wildcards.
1284 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1285 for (j = 0; j < i; j++) {
1286 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
1287 break;
1288 vg_assert(tmp_callers[j].ty == DotDotDot);
1289 }
1290 vg_assert(j >= 0 && j <= i);
1291 if (j == i) {
1292 // we didn't find any non-"..." entries
1293 BOMB("suppression must contain at least one location "
1294 "line which is not \"...\"");
1295 }
1296
sewardjb5f6f512005-03-10 23:59:00 +00001297 // Copy tmp_callers[] into supp->callers[]
1298 supp->n_callers = i;
sewardj9c606bd2008-09-18 18:12:50 +00001299 supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
1300 i*sizeof(SuppLoc));
sewardjb5f6f512005-03-10 23:59:00 +00001301 for (i = 0; i < supp->n_callers; i++) {
1302 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +00001303 }
1304
njn695c16e2005-03-27 03:40:28 +00001305 supp->next = suppressions;
1306 suppressions = supp;
sewardjde4a1d02002-03-22 01:27:54 +00001307 }
njn35db56c2009-07-24 07:38:29 +00001308 VG_(free)(buf);
sewardjde4a1d02002-03-22 01:27:54 +00001309 VG_(close)(fd);
1310 return;
1311
1312 syntax_error:
sewardjf349d552005-11-14 17:01:01 +00001313 if (VG_(clo_xml))
sewardj09361bf2011-01-28 00:19:25 +00001314 VG_(printf_xml)("</valgrindoutput>\n");
sewardj738856f2009-07-15 14:48:32 +00001315 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
njn6f74a7e2009-03-12 00:06:45 +00001316 filename, lineno );
sewardj738856f2009-07-15 14:48:32 +00001317 VG_(umsg)(" %s\n", err_str );
sewardjb5f6f512005-03-10 23:59:00 +00001318
sewardjde4a1d02002-03-22 01:27:54 +00001319 VG_(close)(fd);
sewardj738856f2009-07-15 14:48:32 +00001320 VG_(umsg)("exiting now.\n");
nethercote8ed8a892004-11-08 13:24:25 +00001321 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001322
sewardjb5f6f512005-03-10 23:59:00 +00001323# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +00001324}
1325
1326
1327void VG_(load_suppressions) ( void )
1328{
1329 Int i;
njn695c16e2005-03-27 03:40:28 +00001330 suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001331 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1332 if (VG_(clo_verbosity) > 1) {
sewardj738856f2009-07-15 14:48:32 +00001333 VG_(dmsg)("Reading suppressions file: %s\n",
1334 VG_(clo_suppressions)[i] );
sewardjde4a1d02002-03-22 01:27:54 +00001335 }
1336 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1337 }
1338}
1339
sewardjd7a02db2008-12-12 08:07:49 +00001340
1341/*------------------------------------------------------------*/
1342/*--- Matching errors to suppressions ---*/
1343/*------------------------------------------------------------*/
1344
1345/* Parameterising functions for the use of VG_(generic_match) in
1346 suppression-vs-error matching. The suppression frames (SuppLoc)
1347 play the role of 'pattern'-element, and the error frames (IPs,
1348 hence simply Addrs) play the role of 'input'. In short then, we're
1349 matching a sequence of Addrs against a pattern composed of a
1350 sequence of SuppLocs.
1351*/
1352static Bool supploc_IsStar ( void* supplocV )
1353{
1354 SuppLoc* supploc = (SuppLoc*)supplocV;
1355 return supploc->ty == DotDotDot;
1356}
1357
1358static Bool supploc_IsQuery ( void* supplocV )
1359{
1360 return False; /* there's no '?' equivalent in the supp syntax */
1361}
1362
1363static Bool supp_pattEQinp ( void* supplocV, void* addrV )
1364{
1365 SuppLoc* supploc = (SuppLoc*)supplocV; /* PATTERN */
1366 Addr ip = *(Addr*)addrV; /* INPUT */
1367
1368 Char caller_name[ERRTXT_LEN];
1369 caller_name[0] = 0;
1370
1371 /* So, does this IP address match this suppression-line? */
1372 switch (supploc->ty) {
1373 case DotDotDot:
1374 /* supp_pattEQinp is a callback from VG_(generic_match). As
1375 per the spec thereof (see include/pub_tool_seqmatch.h), we
1376 should never get called with a pattern value for which the
1377 _IsStar or _IsQuery function would return True. Hence
1378 this can't happen. */
1379 vg_assert(0);
1380 case ObjName:
1381 /* Get the object name into 'caller_name', or "???"
1382 if unknown. */
1383 if (!VG_(get_objname)(ip, caller_name, ERRTXT_LEN))
1384 VG_(strcpy)(caller_name, "???");
1385 break;
1386 case FunName:
1387 /* Get the function name into 'caller_name', or "???"
1388 if unknown. */
njn6b7611b2009-02-11 06:06:10 +00001389 // Nb: C++-mangled names are used in suppressions. Do, though,
sewardjd7a02db2008-12-12 08:07:49 +00001390 // Z-demangle them, since otherwise it's possible to wind
1391 // up comparing "malloc" in the suppression against
1392 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1393 // two of them need to be made to match.
njn6b7611b2009-02-11 06:06:10 +00001394 if (!VG_(get_fnname_no_cxx_demangle)(ip, caller_name, ERRTXT_LEN))
sewardjd7a02db2008-12-12 08:07:49 +00001395 VG_(strcpy)(caller_name, "???");
1396 break;
1397 default:
1398 vg_assert(0);
1399 }
1400
1401 /* So now we have the function or object name in caller_name, and
1402 the pattern (at the character level) to match against is in
1403 supploc->name. Hence (and leading to a re-entrant call of
1404 VG_(generic_match)): */
1405 return VG_(string_match)(supploc->name, caller_name);
1406}
1407
1408/////////////////////////////////////////////////////
1409
1410static Bool supp_matches_callers(Error* err, Supp* su)
1411{
1412 /* Unwrap the args and set up the correct parameterisation of
1413 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1414 supp_pattEQinp. */
1415 /* note, StackTrace === Addr* */
1416 StackTrace ips = VG_(get_ExeContext_StackTrace)(err->where);
1417 UWord n_ips = VG_(get_ExeContext_n_ips)(err->where);
1418 SuppLoc* supps = su->callers;
1419 UWord n_supps = su->n_callers;
1420 UWord szbPatt = sizeof(SuppLoc);
1421 UWord szbInput = sizeof(Addr);
1422 Bool matchAll = False; /* we just want to match a prefix */
1423 return
1424 VG_(generic_match)(
1425 matchAll,
1426 /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
1427 /*INPUT*/ips, szbInput, n_ips, 0/*initial Ix*/,
1428 supploc_IsStar, supploc_IsQuery, supp_pattEQinp
1429 );
1430}
1431
1432/////////////////////////////////////////////////////
1433
sewardjb5f6f512005-03-10 23:59:00 +00001434static
njn810086f2002-11-14 12:42:47 +00001435Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +00001436{
njn810086f2002-11-14 12:42:47 +00001437 switch (su->skind) {
njna86f29e2006-12-14 02:55:58 +00001438 //(example code, see comment on CoreSuppKind above)
1439 //case ThreadSupp:
1440 // return (err->ekind == ThreadErr);
njn25e49d8e72002-09-23 09:36:25 +00001441 default:
njn95ec8702004-11-22 16:46:13 +00001442 if (VG_(needs).tool_errors) {
njn51d827b2005-05-09 01:02:08 +00001443 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
njn25e49d8e72002-09-23 09:36:25 +00001444 } else {
1445 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +00001446 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +00001447 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +00001448 err->ekind);
njn67993252004-11-22 18:02:32 +00001449 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +00001450 }
1451 }
1452}
1453
sewardjd7a02db2008-12-12 08:07:49 +00001454/////////////////////////////////////////////////////
sewardj5e519302008-11-03 23:10:25 +00001455
njn810086f2002-11-14 12:42:47 +00001456/* Does an error context match a suppression? ie is this a suppressible
1457 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001458 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001459*/
njn810086f2002-11-14 12:42:47 +00001460static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001461{
njn810086f2002-11-14 12:42:47 +00001462 Supp* su;
sewardj8a7d4e42006-10-17 01:41:17 +00001463 Supp* su_prev;
1464
1465 /* stats gathering */
1466 em_supplist_searches++;
sewardjde4a1d02002-03-22 01:27:54 +00001467
sewardjde4a1d02002-03-22 01:27:54 +00001468 /* See if the error context matches any suppression. */
sewardj8a7d4e42006-10-17 01:41:17 +00001469 su_prev = NULL;
njn695c16e2005-03-27 03:40:28 +00001470 for (su = suppressions; su != NULL; su = su->next) {
sewardj8a7d4e42006-10-17 01:41:17 +00001471 em_supplist_cmps++;
1472 if (supp_matches_error(su, err) && supp_matches_callers(err, su)) {
1473 /* got a match. Move this entry to the head of the list
1474 in the hope of making future searches cheaper. */
1475 if (su_prev) {
1476 vg_assert(su_prev->next == su);
1477 su_prev->next = su->next;
1478 su->next = suppressions;
1479 suppressions = su;
1480 }
njn25e49d8e72002-09-23 09:36:25 +00001481 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001482 }
sewardj8a7d4e42006-10-17 01:41:17 +00001483 su_prev = su;
sewardjde4a1d02002-03-22 01:27:54 +00001484 }
njn25e49d8e72002-09-23 09:36:25 +00001485 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001486}
1487
sewardj8a7d4e42006-10-17 01:41:17 +00001488/* Show accumulated error-list and suppression-list search stats.
1489*/
1490void VG_(print_errormgr_stats) ( void )
1491{
sewardj738856f2009-07-15 14:48:32 +00001492 VG_(dmsg)(
1493 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
sewardj8a7d4e42006-10-17 01:41:17 +00001494 em_supplist_searches, em_supplist_cmps
1495 );
sewardj738856f2009-07-15 14:48:32 +00001496 VG_(dmsg)(
1497 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
sewardj8a7d4e42006-10-17 01:41:17 +00001498 em_errlist_searches, em_errlist_cmps
1499 );
1500}
1501
sewardjde4a1d02002-03-22 01:27:54 +00001502/*--------------------------------------------------------------------*/
njneb8896b2005-06-04 20:03:55 +00001503/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001504/*--------------------------------------------------------------------*/