blob: b719dcba91d0cdbe4d8d14dfea44d86da892ee13 [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
sewardj9ebd6e02007-01-08 06:01:59 +000010 Copyright (C) 2000-2007 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
njn24a6efb2005-06-20 03:36:51 +000033#include "pub_core_threadstate.h" // For VG_N_THREADS
njn75b65aa2005-06-19 19:25:44 +000034#include "pub_core_debugger.h"
njnea27e462005-05-31 02:38:09 +000035#include "pub_core_debuginfo.h"
njnd2b17112005-04-19 04:10:25 +000036#include "pub_core_errormgr.h"
njnd01fef72005-03-25 23:35:48 +000037#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000038#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000039#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000040#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000041#include "pub_core_libcprint.h"
njn24a6efb2005-06-20 03:36:51 +000042#include "pub_core_libcproc.h" // For VG_(getpid)()
njnaf1d7df2005-06-11 01:31:52 +000043#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000044#include "pub_core_options.h"
njnd0d7c1f2005-06-21 00:33:19 +000045#include "pub_core_stacktrace.h"
njn43b9a8a2005-05-10 04:37:01 +000046#include "pub_core_tooliface.h"
njn24a6efb2005-06-20 03:36:51 +000047#include "pub_core_translate.h" // for VG_(translate)()
sewardjde4a1d02002-03-22 01:27:54 +000048
49/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000050/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000051/*------------------------------------------------------------*/
52
njn14319cc2005-03-13 06:26:22 +000053/* After this many different unsuppressed errors have been observed,
54 be more conservative about collecting new ones. */
sewardj1d1a2262005-10-20 01:57:29 +000055#define M_COLLECT_ERRORS_SLOWLY_AFTER 100
njn14319cc2005-03-13 06:26:22 +000056
57/* After this many different unsuppressed errors have been observed,
58 stop collecting errors at all, and tell the user their program is
59 evidently a steaming pile of camel dung. */
sewardj1d1a2262005-10-20 01:57:29 +000060#define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
njn14319cc2005-03-13 06:26:22 +000061
62/* After this many total errors have been observed, stop collecting
63 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
sewardj513646f2006-05-12 23:12:30 +000064#define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
njn14319cc2005-03-13 06:26:22 +000065
sewardjde4a1d02002-03-22 01:27:54 +000066/* The list of error contexts found, both suppressed and unsuppressed.
67 Initially empty, and grows as errors are detected. */
njn695c16e2005-03-27 03:40:28 +000068static Error* errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000069
70/* The list of suppression directives, as read from the specified
sewardj8a7d4e42006-10-17 01:41:17 +000071 suppressions file. Note that the list gets rearranged as a result
72 of the searches done by is_suppressible_error(). */
njn695c16e2005-03-27 03:40:28 +000073static Supp* suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000074
75/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000076static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000077
78/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000079static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000080
81/* forwards ... */
njn810086f2002-11-14 12:42:47 +000082static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000083
sewardjb5f6f512005-03-10 23:59:00 +000084static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000085
sewardj8a7d4e42006-10-17 01:41:17 +000086/* Stats: number of searches of the error list initiated. */
87static UWord em_errlist_searches = 0;
88
89/* Stats: number of comparisons done during error list
90 searching. */
91static UWord em_errlist_cmps = 0;
92
93/* Stats: number of searches of the suppression list initiated. */
94static UWord em_supplist_searches = 0;
95
96/* Stats: number of comparisons done during suppression list
97 searching. */
98static UWord em_supplist_cmps = 0;
99
sewardjde4a1d02002-03-22 01:27:54 +0000100/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +0000101/*--- Error type ---*/
102/*------------------------------------------------------------*/
103
nethercote4a184902004-08-02 12:21:09 +0000104/* Errors. Extensible (via the 'extra' field). Tools can use a normal
njn02bc4b82005-05-15 17:28:26 +0000105 enum (with element values in the normal range (0..)) for 'ekind'.
nethercote4a184902004-08-02 12:21:09 +0000106 Functions for getting/setting the tool-relevant fields are in
njnc7561b92005-06-19 01:24:32 +0000107 include/pub_tool_errormgr.h.
nethercote4a184902004-08-02 12:21:09 +0000108
109 When errors are found and recorded with VG_(maybe_record_error)(), all
110 the tool must do is pass in the four parameters; core will
111 allocate/initialise the error record.
112*/
113struct _Error {
114 struct _Error* next;
sewardjdbada272005-07-02 21:16:30 +0000115 // Unique tag. This gives the error a unique identity (handle) by
116 // which it can be referred to afterwords. Currently only used for
117 // XML printing.
118 UInt unique;
nethercote4a184902004-08-02 12:21:09 +0000119 // NULL if unsuppressed; or ptr to suppression record.
120 Supp* supp;
121 Int count;
122 ThreadId tid;
123
124 // The tool-specific part
125 ExeContext* where; // Initialised by core
njnd2b17112005-04-19 04:10:25 +0000126 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
nethercote4a184902004-08-02 12:21:09 +0000127 Addr addr; // Used frequently
128 Char* string; // Used frequently
129 void* extra; // For any tool-specific extras
130};
131
132ExeContext* VG_(get_error_where) ( Error* err )
133{
134 return err->where;
135}
136
137ErrorKind VG_(get_error_kind) ( Error* err )
138{
139 return err->ekind;
140}
141
142Addr VG_(get_error_address) ( Error* err )
143{
144 return err->addr;
145}
146
147Char* VG_(get_error_string) ( Error* err )
148{
149 return err->string;
150}
151
152void* VG_(get_error_extra) ( Error* err )
153{
154 return err->extra;
155}
156
nethercotef2b11482004-08-02 12:36:01 +0000157UInt VG_(get_n_errs_found)( void )
158{
159 return n_errs_found;
160}
161
nethercote4a184902004-08-02 12:21:09 +0000162/*------------------------------------------------------------*/
163/*--- Suppression type ---*/
164/*------------------------------------------------------------*/
165
166/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
167 * effectively extend it by defining their own enums in the (0..) range. */
168typedef
169 enum {
njna86f29e2006-12-14 02:55:58 +0000170 // Nb: thread errors are a relic of the time when Valgrind's core
171 // could detect them. This example is left commented-out as an
172 // example should new core errors ever be added.
173 ThreadSupp = -1, /* Matches ThreadErr */
nethercote4a184902004-08-02 12:21:09 +0000174 }
175 CoreSuppKind;
176
sewardjb5f6f512005-03-10 23:59:00 +0000177/* Max number of callers for context in a suppression. */
178#define VG_MAX_SUPP_CALLERS 24
179
nethercote4a184902004-08-02 12:21:09 +0000180/* For each caller specified for a suppression, record the nature of
181 the caller name. Not of interest to tools. */
182typedef
183 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000184 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000185 ObjName, /* Name is of an shared object file. */
186 FunName /* Name is of a function. */
187 }
188 SuppLocTy;
189
sewardjb5f6f512005-03-10 23:59:00 +0000190typedef
191 struct {
192 SuppLocTy ty;
193 Char* name;
194 }
195 SuppLoc;
196
nethercote4a184902004-08-02 12:21:09 +0000197/* Suppressions. Tools can get/set tool-relevant parts with functions
njnc7561b92005-06-19 01:24:32 +0000198 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000199 Tools can use a normal enum (with element values in the normal range
njn02bc4b82005-05-15 17:28:26 +0000200 (0..)) for 'skind'. */
nethercote4a184902004-08-02 12:21:09 +0000201struct _Supp {
202 struct _Supp* next;
203 Int count; // The number of times this error has been suppressed.
204 Char* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000205
206 // Length of 'callers'
207 Int n_callers;
208 // Array of callers, for matching stack traces. First one (name of fn
209 // where err occurs) is mandatory; rest are optional.
210 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000211
212 /* The tool-specific part */
213 SuppKind skind; // What kind of suppression. Must use the range (0..).
214 Char* string; // String -- use is optional. NULL by default.
215 void* extra; // Anything else -- use is optional. NULL by default.
216};
217
218SuppKind VG_(get_supp_kind) ( Supp* su )
219{
220 return su->skind;
221}
222
223Char* VG_(get_supp_string) ( Supp* su )
224{
225 return su->string;
226}
227
228void* VG_(get_supp_extra) ( Supp* su )
229{
230 return su->extra;
231}
232
233
234void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
235{
236 su->skind = skind;
237}
238
239void VG_(set_supp_string) ( Supp* su, Char* string )
240{
241 su->string = string;
242}
243
244void VG_(set_supp_extra) ( Supp* su, void* extra )
245{
246 su->extra = extra;
247}
248
249
250/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000251/*--- Helper fns ---*/
252/*------------------------------------------------------------*/
253
njn0087c502005-07-01 04:15:36 +0000254// Only show core errors if the tool wants to, we're not running with -q,
255// and were not outputting XML.
256Bool VG_(showing_core_errors)(void)
257{
258 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
259}
260
sewardjc6f43dd2007-04-07 14:46:13 +0000261/* Compare errors, to detect duplicates. */
njn810086f2002-11-14 12:42:47 +0000262static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000263{
njn810086f2002-11-14 12:42:47 +0000264 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000265 return False;
njn25e49d8e72002-09-23 09:36:25 +0000266 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000267 return False;
268
njn810086f2002-11-14 12:42:47 +0000269 switch (e1->ekind) {
njna86f29e2006-12-14 02:55:58 +0000270 //(example code, see comment on CoreSuppKind above)
271 //case ThreadErr:
272 // vg_assert(VG_(needs).core_errors);
273 // return <something>
sewardjde4a1d02002-03-22 01:27:54 +0000274 default:
njn51d827b2005-05-09 01:02:08 +0000275 if (VG_(needs).tool_errors) {
276 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
277 } else {
njn95ec8702004-11-22 16:46:13 +0000278 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000279 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000280 e1->ekind);
njn67993252004-11-22 18:02:32 +0000281 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000282 }
sewardjde4a1d02002-03-22 01:27:54 +0000283 }
284}
285
njnb0eb66e2005-07-10 16:57:24 +0000286static void pp_Error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000287{
sewardj71bc3cb2005-05-19 00:25:45 +0000288 if (VG_(clo_xml)) {
289 VG_(message)(Vg_UserMsg, "<error>");
sewardjdbada272005-07-02 21:16:30 +0000290 VG_(message)(Vg_UserMsg, " <unique>0x%x</unique>",
291 err->unique);
sewardj71bc3cb2005-05-19 00:25:45 +0000292 VG_(message)(Vg_UserMsg, " <tid>%d</tid>", err->tid);
293 }
294
295 if (!VG_(clo_xml)) {
sewardjadb102f2007-11-09 23:21:44 +0000296 if (VG_(tdict).tool_show_ThreadIDs_for_errors
297 && err->tid > 0 && err->tid != last_tid_printed) {
sewardj71bc3cb2005-05-19 00:25:45 +0000298 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
299 last_tid_printed = err->tid;
300 }
sewardjb5f6f512005-03-10 23:59:00 +0000301 }
njn25e49d8e72002-09-23 09:36:25 +0000302
njn810086f2002-11-14 12:42:47 +0000303 switch (err->ekind) {
njna86f29e2006-12-14 02:55:58 +0000304 //(example code, see comment on CoreSuppKind above)
305 //case ThreadErr:
306 // vg_assert(VG_(needs).core_errors);
307 // VG_(tm_error_print)(err);
308 // break;
sewardjde4a1d02002-03-22 01:27:54 +0000309 default:
njn95ec8702004-11-22 16:46:13 +0000310 if (VG_(needs).tool_errors)
njn51d827b2005-05-09 01:02:08 +0000311 VG_TDICT_CALL( tool_pp_Error, err );
njn25e49d8e72002-09-23 09:36:25 +0000312 else {
njn95ec8702004-11-22 16:46:13 +0000313 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000314 "probably needs to be set?\n",
njn810086f2002-11-14 12:42:47 +0000315 err->ekind);
njn67993252004-11-22 18:02:32 +0000316 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000317 }
sewardjde4a1d02002-03-22 01:27:54 +0000318 }
sewardj71bc3cb2005-05-19 00:25:45 +0000319
320 if (VG_(clo_xml))
321 VG_(message)(Vg_UserMsg, "</error>");
sewardjde4a1d02002-03-22 01:27:54 +0000322}
323
nethercote04d0fbc2004-01-26 16:48:06 +0000324/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000325 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000326Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000327{
328 Char ch, ch2;
329 Int res;
330
njn43c799e2003-04-08 00:08:52 +0000331 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000332 return False;
333
334 VG_(message)(Vg_UserMsg, "");
335
336 again:
337 VG_(printf)(
338 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000339 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
340 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000341 );
342
sewardj6024b212003-07-13 10:54:33 +0000343 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000344 if (res != 1) goto ioerror;
345 /* res == 1 */
346 if (ch == '\n') return False;
347 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
348 && ch != 'C' && ch != 'c') goto again;
349
sewardj6024b212003-07-13 10:54:33 +0000350 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000351 if (res != 1) goto ioerror;
352 if (ch2 != '\n') goto again;
353
njn43c799e2003-04-08 00:08:52 +0000354 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000355 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000356 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000357 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000358 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000359 vg_assert(ch == 'c' || ch == 'C');
360
361 ioerror:
njn43c799e2003-04-08 00:08:52 +0000362 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000363 return False;
364}
365
366
sewardjb5f6f512005-03-10 23:59:00 +0000367/* Construct an error */
njn25e49d8e72002-09-23 09:36:25 +0000368static __inline__
njn72718642003-07-24 08:45:32 +0000369void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
370 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000371{
sewardjdbada272005-07-02 21:16:30 +0000372 /* DO NOT MAKE unique_counter NON-STATIC */
373 static UInt unique_counter = 0;
374
njnca82cc02004-11-22 17:18:48 +0000375 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000376
njn810086f2002-11-14 12:42:47 +0000377 /* Core-only parts */
sewardjdbada272005-07-02 21:16:30 +0000378 err->unique = unique_counter++;
njn25e49d8e72002-09-23 09:36:25 +0000379 err->next = NULL;
380 err->supp = NULL;
381 err->count = 1;
njn72718642003-07-24 08:45:32 +0000382 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000383 if (NULL == where)
sewardjadb102f2007-11-09 23:21:44 +0000384 err->where = VG_(record_ExeContext)( tid, 0 );
njn43c799e2003-04-08 00:08:52 +0000385 else
386 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000387
nethercote996901a2004-08-03 13:29:09 +0000388 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000389 err->ekind = ekind;
390 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000391 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000392 err->string = s;
393
njn25e49d8e72002-09-23 09:36:25 +0000394 /* sanity... */
njn72718642003-07-24 08:45:32 +0000395 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000396}
397
njn83f9e792005-06-11 05:04:09 +0000398#define ERRTXT_LEN 4096
399
njnf4261312005-03-20 23:45:36 +0000400static void printSuppForIp(UInt n, Addr ip)
401{
njn83f9e792005-06-11 05:04:09 +0000402 static UChar buf[ERRTXT_LEN];
njnf4261312005-03-20 23:45:36 +0000403
sewardj39745be2006-12-06 03:35:38 +0000404 if ( VG_(get_fnname_Z_demangle_only) (ip, buf, ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000405 VG_(printf)(" fun:%s\n", buf);
njn83f9e792005-06-11 05:04:09 +0000406 } else if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000407 VG_(printf)(" obj:%s\n", buf);
408 } else {
njn966d6632005-08-18 15:49:21 +0000409 VG_(printf)(" obj:*\n");
njnf4261312005-03-20 23:45:36 +0000410 }
411}
412
nethercote10d481a2004-01-25 20:33:53 +0000413static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000414{
njn43c799e2003-04-08 00:08:52 +0000415 ExeContext* ec = VG_(get_error_where)(err);
416 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000417
sewardjb5f6f512005-03-10 23:59:00 +0000418 /* At most VG_MAX_SUPP_CALLERS names */
419 if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
njn43c799e2003-04-08 00:08:52 +0000420 vg_assert(stop_at > 0);
421
njna86f29e2006-12-14 02:55:58 +0000422 //(example code, see comment on CoreSuppKind above)
423 if (0) {
424 //if (0) ThreadErr == err->ekind) {
425 // VG_(printf)("{\n");
426 // VG_(printf)(" <insert a suppression name here>\n");
427 // VG_(printf)(" core:Thread\n");
njn6a230532003-07-21 10:38:23 +0000428
429 } else {
njn51d827b2005-05-09 01:02:08 +0000430 Char* name = VG_TDICT_CALL(tool_get_error_name, err);
njn6a230532003-07-21 10:38:23 +0000431 if (NULL == name) {
432 VG_(message)(Vg_UserMsg,
njnf7ba7032005-12-19 19:40:12 +0000433 "(%s does not allow error to be suppressed)",
434 VG_(details).name);
njn6a230532003-07-21 10:38:23 +0000435 return;
436 }
njnf7ba7032005-12-19 19:40:12 +0000437 VG_(printf)("{\n");
438 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000439 VG_(printf)(" %s:%s\n", VG_(details).name, name);
njn51d827b2005-05-09 01:02:08 +0000440 VG_TDICT_CALL(tool_print_extra_suppression_info, err);
njn6a230532003-07-21 10:38:23 +0000441 }
njn43c799e2003-04-08 00:08:52 +0000442
njnf4261312005-03-20 23:45:36 +0000443 // Print stack trace elements
njnd01fef72005-03-25 23:35:48 +0000444 VG_(apply_StackTrace)(printSuppForIp, VG_(extract_StackTrace)(ec), stop_at);
njn43c799e2003-04-08 00:08:52 +0000445
446 VG_(printf)("}\n");
447}
448
njnb4aee052003-04-15 14:09:58 +0000449static
nethercote04d0fbc2004-01-26 16:48:06 +0000450void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000451{
sewardjd153fae2005-01-10 17:24:47 +0000452 Bool still_noisy = True;
453
nethercote04d0fbc2004-01-26 16:48:06 +0000454 /* Perhaps we want a debugger attach at this point? */
455 if (allow_db_attach &&
njnd2b17112005-04-19 04:10:25 +0000456 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
457 {
nethercote04d0fbc2004-01-26 16:48:06 +0000458 VG_(printf)("starting debugger\n");
459 VG_(start_debugger)( err->tid );
njnd2b17112005-04-19 04:10:25 +0000460 }
njn43c799e2003-04-08 00:08:52 +0000461 /* Or maybe we want to generate the error's suppression? */
sewardjd153fae2005-01-10 17:24:47 +0000462 if (VG_(clo_gen_suppressions) == 2
463 || (VG_(clo_gen_suppressions) == 1
njnd2b17112005-04-19 04:10:25 +0000464 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
sewardjd153fae2005-01-10 17:24:47 +0000465 ) {
nethercote42602b12004-01-25 19:30:29 +0000466 gen_suppression(err);
njn43c799e2003-04-08 00:08:52 +0000467 }
sewardjc0c67032006-06-25 12:18:20 +0000468 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
469 VG_(clo_gen_suppressions) = 0;
njn43c799e2003-04-08 00:08:52 +0000470}
471
472/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
473 just for pretty printing purposes. */
474static Bool is_first_shown_context = True;
475
njnfb289bc2007-01-12 23:59:50 +0000476static Int n_errs_shown = 0;
477
njn25e49d8e72002-09-23 09:36:25 +0000478/* Top-level entry point to the error management subsystem.
479 All detected errors are notified here; this routine decides if/when the
480 user should see the error. */
njn72718642003-07-24 08:45:32 +0000481void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000482 ErrorKind ekind, Addr a, Char* s, void* extra )
483{
njn810086f2002-11-14 12:42:47 +0000484 Error err;
485 Error* p;
486 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000487 UInt extra_size;
njn695c16e2005-03-27 03:40:28 +0000488 VgRes exe_res = Vg_MedRes;
489 static Bool stopping_message = False;
490 static Bool slowdown_message = False;
sewardjde4a1d02002-03-22 01:27:54 +0000491
njn14319cc2005-03-13 06:26:22 +0000492 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
493 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000494 have been found, just refuse to collect any more. This stops
495 the burden of the error-management system becoming excessive in
496 extremely buggy programs, although it does make it pretty
497 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000498 if (VG_(clo_error_limit)
njn695c16e2005-03-27 03:40:28 +0000499 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
sewardj8a051722005-06-30 00:10:16 +0000500 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
501 && !VG_(clo_xml)) {
sewardjde4a1d02002-03-22 01:27:54 +0000502 if (!stopping_message) {
503 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000504
njn695c16e2005-03-27 03:40:28 +0000505 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardjf2537be2002-04-24 21:03:47 +0000506 VG_(message)(Vg_UserMsg,
507 "More than %d different errors detected. "
508 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000509 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000510 } else {
511 VG_(message)(Vg_UserMsg,
512 "More than %d total errors detected. "
513 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000514 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000515 }
516
sewardjde4a1d02002-03-22 01:27:54 +0000517 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000518 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000519 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000520 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000521 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000522 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000523 VG_(message)(Vg_UserMsg,
524 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000525 VG_(message)(Vg_UserMsg, "");
526 stopping_message = True;
527 }
528 return;
529 }
530
njn14319cc2005-03-13 06:26:22 +0000531 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000532 been found, be much more conservative about collecting new
533 ones. */
sewardj8a051722005-06-30 00:10:16 +0000534 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
535 && !VG_(clo_xml)) {
njn25e49d8e72002-09-23 09:36:25 +0000536 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000537 if (!slowdown_message) {
538 VG_(message)(Vg_UserMsg, "");
539 VG_(message)(Vg_UserMsg,
540 "More than %d errors detected. Subsequent errors",
njn14319cc2005-03-13 06:26:22 +0000541 M_COLLECT_ERRORS_SLOWLY_AFTER);
sewardjde4a1d02002-03-22 01:27:54 +0000542 VG_(message)(Vg_UserMsg,
543 "will still be recorded, but in less detail than before.");
544 slowdown_message = True;
545 }
546 }
547
njn25e49d8e72002-09-23 09:36:25 +0000548 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000549 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000550
551 /* First, see if we've got an error record matching this one. */
sewardj8a7d4e42006-10-17 01:41:17 +0000552 em_errlist_searches++;
553 p = errors;
554 p_prev = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000555 while (p != NULL) {
sewardj8a7d4e42006-10-17 01:41:17 +0000556 em_errlist_cmps++;
njn810086f2002-11-14 12:42:47 +0000557 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000558 /* Found it. */
559 p->count++;
560 if (p->supp != NULL) {
561 /* Deal correctly with suppressed errors. */
562 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000563 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000564 } else {
nethercotef2b11482004-08-02 12:36:01 +0000565 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000566 }
567
568 /* Move p to the front of the list so that future searches
569 for it are faster. */
570 if (p_prev != NULL) {
571 vg_assert(p_prev->next == p);
njn695c16e2005-03-27 03:40:28 +0000572 p_prev->next = p->next;
573 p->next = errors;
574 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000575 }
sewardj7ebf7c32003-07-24 21:29:40 +0000576
sewardjde4a1d02002-03-22 01:27:54 +0000577 return;
578 }
579 p_prev = p;
580 p = p->next;
581 }
582
583 /* Didn't see it. Copy and add. */
584
njn43c799e2003-04-08 00:08:52 +0000585 /* OK, we're really going to collect it. The context is on the stack and
586 will disappear shortly, so we must copy it. First do the main
njn02bc4b82005-05-15 17:28:26 +0000587 (non-'extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000588
njn02bc4b82005-05-15 17:28:26 +0000589 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
njn51d827b2005-05-09 01:02:08 +0000590 is for when there are more details to fill in which take time to work
591 out but don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000592 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000593 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000594
njn02bc4b82005-05-15 17:28:26 +0000595 Then, if there is an 'extra' part, copy it too, using the size that
njn51d827b2005-05-09 01:02:08 +0000596 VG_(tdict).tool_update_extra returned. Also allow for people using
597 the void* extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000598 */
599
600 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000601 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000602 *p = err;
njn43c799e2003-04-08 00:08:52 +0000603
njn02bc4b82005-05-15 17:28:26 +0000604 /* update 'extra' */
sewardjb5f6f512005-03-10 23:59:00 +0000605 switch (ekind) {
njna86f29e2006-12-14 02:55:58 +0000606 //(example code, see comment on CoreSuppKind above)
607 //case ThreadErr:
608 // vg_assert(VG_(needs).core_errors);
609 // extra_size = <something>
610 // break;
sewardjb5f6f512005-03-10 23:59:00 +0000611 default:
612 vg_assert(VG_(needs).tool_errors);
njn51d827b2005-05-09 01:02:08 +0000613 extra_size = VG_TDICT_CALL(tool_update_extra, p);
sewardjb5f6f512005-03-10 23:59:00 +0000614 break;
615 }
njn43c799e2003-04-08 00:08:52 +0000616
njn02bc4b82005-05-15 17:28:26 +0000617 /* copy block pointed to by 'extra', if there is one */
sewardjb5f6f512005-03-10 23:59:00 +0000618 if (NULL != p->extra && 0 != extra_size) {
619 void* new_extra = VG_(malloc)(extra_size);
620 VG_(memcpy)(new_extra, p->extra, extra_size);
621 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000622 }
623
njn695c16e2005-03-27 03:40:28 +0000624 p->next = errors;
njn25e49d8e72002-09-23 09:36:25 +0000625 p->supp = is_suppressible_error(&err);
njn695c16e2005-03-27 03:40:28 +0000626 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000627 if (p->supp == NULL) {
nethercotef2b11482004-08-02 12:36:01 +0000628 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000629 if (!is_first_shown_context)
630 VG_(message)(Vg_UserMsg, "");
njnb0eb66e2005-07-10 16:57:24 +0000631 pp_Error(p);
sewardjde4a1d02002-03-22 01:27:54 +0000632 is_first_shown_context = False;
njn695c16e2005-03-27 03:40:28 +0000633 n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000634 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000635 } else {
nethercotef2b11482004-08-02 12:36:01 +0000636 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000637 p->supp->count++;
638 }
639}
640
njn43c799e2003-04-08 00:08:52 +0000641/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000642 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000643 guaranteed to only happen once. This avoids all the recording and
644 comparing stuff. But they can be suppressed; returns True if it is
njn02bc4b82005-05-15 17:28:26 +0000645 suppressed. Bool 'print_error' dictates whether to print the error.
646 Bool 'count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000647*/
njn72718642003-07-24 08:45:32 +0000648Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000649 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000650 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000651{
njnfb289bc2007-01-12 23:59:50 +0000652 Error err;
653 Supp *su;
njn43c799e2003-04-08 00:08:52 +0000654
655 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000656 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000657
658 /* Unless it's suppressed, we're going to show it. Don't need to make
659 a copy, because it's only temporary anyway.
660
njn02bc4b82005-05-15 17:28:26 +0000661 Then update the 'extra' part with VG_(tdict).tool_update_extra),
njn51d827b2005-05-09 01:02:08 +0000662 because that can have an affect on whether it's suppressed. Ignore
663 the size return value of VG_(tdict).tool_update_extra, because we're
njn02bc4b82005-05-15 17:28:26 +0000664 not copying 'extra'. */
njn51d827b2005-05-09 01:02:08 +0000665 (void)VG_TDICT_CALL(tool_update_extra, &err);
njn43c799e2003-04-08 00:08:52 +0000666
njnfb289bc2007-01-12 23:59:50 +0000667 su = is_suppressible_error(&err);
668 if (NULL == su) {
njn47363ab2003-04-21 13:24:40 +0000669 if (count_error)
nethercotef2b11482004-08-02 12:36:01 +0000670 n_errs_found++;
njn43c799e2003-04-08 00:08:52 +0000671
672 if (print_error) {
673 if (!is_first_shown_context)
674 VG_(message)(Vg_UserMsg, "");
njnb0eb66e2005-07-10 16:57:24 +0000675 pp_Error(&err);
njn43c799e2003-04-08 00:08:52 +0000676 is_first_shown_context = False;
njnfb289bc2007-01-12 23:59:50 +0000677 n_errs_shown++;
678 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000679 }
njn43c799e2003-04-08 00:08:52 +0000680 return False;
681
682 } else {
nethercotef2b11482004-08-02 12:36:01 +0000683 n_errs_suppressed++;
njnfb289bc2007-01-12 23:59:50 +0000684 su->count++;
njn43c799e2003-04-08 00:08:52 +0000685 return True;
686 }
687}
688
sewardjde4a1d02002-03-22 01:27:54 +0000689
sewardjde4a1d02002-03-22 01:27:54 +0000690/*------------------------------------------------------------*/
691/*--- Exported fns ---*/
692/*------------------------------------------------------------*/
693
sewardj71bc3cb2005-05-19 00:25:45 +0000694/* Show the used suppressions. Returns False if no suppression
695 got used. */
696static Bool show_used_suppressions ( void )
697{
698 Supp *su;
699 Bool any_supp;
700
sewardj7c9e57c2005-05-24 14:21:45 +0000701 if (VG_(clo_xml))
702 VG_(message)(Vg_DebugMsg, "<suppcounts>");
703
sewardj71bc3cb2005-05-19 00:25:45 +0000704 any_supp = False;
705 for (su = suppressions; su != NULL; su = su->next) {
706 if (su->count <= 0)
707 continue;
708 any_supp = True;
709 if (VG_(clo_xml)) {
710 VG_(message)(Vg_DebugMsg,
sewardj753673f2005-08-09 22:03:08 +0000711 " <pair>\n"
712 " <count>%d</count>\n"
713 " <name>%t</name>\n"
714 " </pair>",
sewardj71bc3cb2005-05-19 00:25:45 +0000715 su->count, su->sname);
716 } else {
sewardj8a7d4e42006-10-17 01:41:17 +0000717 VG_(message)(Vg_DebugMsg, "supp: %6d %s", su->count, su->sname);
sewardj71bc3cb2005-05-19 00:25:45 +0000718 }
719 }
720
sewardj7c9e57c2005-05-24 14:21:45 +0000721 if (VG_(clo_xml))
sewardj8665d8e2005-06-01 17:35:23 +0000722 VG_(message)(Vg_DebugMsg, "</suppcounts>");
sewardj7c9e57c2005-05-24 14:21:45 +0000723
sewardj71bc3cb2005-05-19 00:25:45 +0000724 return any_supp;
725}
726
727
sewardj9f297ca2005-05-20 02:29:52 +0000728/* Show all the errors that occurred, and possibly also the
729 suppressions used. */
sewardjde4a1d02002-03-22 01:27:54 +0000730void VG_(show_all_errors) ( void )
731{
njn810086f2002-11-14 12:42:47 +0000732 Int i, n_min;
733 Int n_err_contexts, n_supp_contexts;
734 Error *p, *p_min;
735 Supp *su;
736 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000737
738 if (VG_(clo_verbosity) == 0)
739 return;
740
741 n_err_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000742 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000743 if (p->supp == NULL)
744 n_err_contexts++;
745 }
746
747 n_supp_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000748 for (su = suppressions; su != NULL; su = su->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000749 if (su->count > 0)
750 n_supp_contexts++;
751 }
sewardj71bc3cb2005-05-19 00:25:45 +0000752
753 /* If we're printing XML, just show the suppressions and stop.
754 */
755 if (VG_(clo_xml)) {
756 (void)show_used_suppressions();
757 return;
758 }
759
760 /* We only get here if not printing XML. */
sewardjde4a1d02002-03-22 01:27:54 +0000761 VG_(message)(Vg_UserMsg,
762 "ERROR SUMMARY: "
763 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000764 n_errs_found, n_err_contexts,
765 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000766
767 if (VG_(clo_verbosity) <= 1)
768 return;
769
770 /* Print the contexts in order of increasing error count. */
771 for (i = 0; i < n_err_contexts; i++) {
772 n_min = (1 << 30) - 1;
773 p_min = NULL;
njn695c16e2005-03-27 03:40:28 +0000774 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000775 if (p->supp != NULL) continue;
776 if (p->count < n_min) {
777 n_min = p->count;
778 p_min = p;
779 }
780 }
njn67993252004-11-22 18:02:32 +0000781 if (p_min == NULL) VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000782
783 VG_(message)(Vg_UserMsg, "");
784 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
785 p_min->count,
786 i+1, n_err_contexts);
njnb0eb66e2005-07-10 16:57:24 +0000787 pp_Error( p_min );
sewardjde4a1d02002-03-22 01:27:54 +0000788
789 if ((i+1 == VG_(clo_dump_error))) {
njnd01fef72005-03-25 23:35:48 +0000790 StackTrace ips = VG_(extract_StackTrace)(p_min->where);
sewardjfa8ec112005-01-19 11:55:34 +0000791 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
njn394213a2005-06-19 18:38:24 +0000792 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
sewardj0ec07f32006-01-12 12:32:32 +0000793 /*bbs_done*/0,
794 /*allow redir?*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000795 }
796
797 p_min->count = 1 << 30;
798 }
799
800 if (n_supp_contexts > 0)
801 VG_(message)(Vg_DebugMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +0000802 any_supp = show_used_suppressions();
sewardjde4a1d02002-03-22 01:27:54 +0000803
804 if (n_err_contexts > 0) {
805 if (any_supp)
806 VG_(message)(Vg_UserMsg, "");
807 VG_(message)(Vg_UserMsg,
808 "IN SUMMARY: "
809 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000810 n_errs_found, n_err_contexts, n_errs_suppressed,
sewardjde4a1d02002-03-22 01:27:54 +0000811 n_supp_contexts );
812 VG_(message)(Vg_UserMsg, "");
813 }
814}
815
sewardj9f297ca2005-05-20 02:29:52 +0000816
817/* Show occurrence counts of all errors, in XML form. */
818void VG_(show_error_counts_as_XML) ( void )
819{
820 Error* err;
821 VG_(message)(Vg_UserMsg, "<errorcounts>");
822 for (err = errors; err != NULL; err = err->next) {
823 if (err->supp != NULL)
824 continue;
825 if (err->count <= 0)
826 continue;
827 VG_(message)(
sewardj753673f2005-08-09 22:03:08 +0000828 Vg_UserMsg, " <pair>\n"
829 " <count>%d</count>\n"
cerion3a24e722005-08-09 22:34:18 +0000830 " <unique>0x%x</unique>\n"
sewardj753673f2005-08-09 22:03:08 +0000831 " </pair>",
sewardj39618202005-08-09 21:50:18 +0000832 err->count, err->unique
sewardj9f297ca2005-05-20 02:29:52 +0000833 );
834 }
835 VG_(message)(Vg_UserMsg, "</errorcounts>");
836}
837
838
sewardjde4a1d02002-03-22 01:27:54 +0000839/*------------------------------------------------------------*/
840/*--- Standard suppressions ---*/
841/*------------------------------------------------------------*/
842
sewardj8a7d4e42006-10-17 01:41:17 +0000843/* Get the next char from fd into *out_buf. Returns 1 if success,
844 0 if eof or < 0 if error. */
845
846static Int get_char ( Int fd, Char* out_buf )
847{
848 Int r;
849 static Char buf[64];
850 static Int buf_size = 0;
851 static Int buf_used = 0;
852 vg_assert(buf_size >= 0 && buf_size <= 64);
853 vg_assert(buf_used >= 0 && buf_used <= buf_size);
854 if (buf_used == buf_size) {
855 r = VG_(read)(fd, buf, 64);
856 if (r < 0) return r; /* read failed */
857 vg_assert(r >= 0 && r <= 64);
858 buf_size = r;
859 buf_used = 0;
860 }
861 if (buf_size == 0)
862 return 0; /* eof */
863 vg_assert(buf_size >= 0 && buf_size <= 64);
864 vg_assert(buf_used >= 0 && buf_used < buf_size);
865 *out_buf = buf[buf_used];
866 buf_used++;
867 return 1;
868}
869
870
sewardjde4a1d02002-03-22 01:27:54 +0000871/* Get a non-blank, non-comment line of at most nBuf chars from fd.
872 Skips leading spaces on the line. Return True if EOF was hit instead.
873*/
njn4ba5a792002-09-30 10:23:54 +0000874Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000875{
876 Char ch;
877 Int n, i;
878 while (True) {
879 /* First, read until a non-blank char appears. */
880 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +0000881 n = get_char(fd, &ch);
njn0c0f32a2005-03-26 04:14:01 +0000882 if (n == 1 && !VG_(isspace)(ch)) break;
sewardj8a7d4e42006-10-17 01:41:17 +0000883 if (n <= 0) return True;
sewardjde4a1d02002-03-22 01:27:54 +0000884 }
885
886 /* Now, read the line into buf. */
887 i = 0;
888 buf[i++] = ch; buf[i] = 0;
889 while (True) {
sewardj8a7d4e42006-10-17 01:41:17 +0000890 n = get_char(fd, &ch);
891 if (n <= 0) return False; /* the next call will return True */
sewardjde4a1d02002-03-22 01:27:54 +0000892 if (ch == '\n') break;
893 if (i > 0 && i == nBuf-1) i--;
894 buf[i++] = ch; buf[i] = 0;
895 }
njn0c0f32a2005-03-26 04:14:01 +0000896 while (i > 1 && VG_(isspace)(buf[i-1])) {
sewardjde4a1d02002-03-22 01:27:54 +0000897 i--; buf[i] = 0;
898 };
899
njn02bc4b82005-05-15 17:28:26 +0000900 /* VG_(printf)("The line is '%s'\n", buf); */
sewardjde4a1d02002-03-22 01:27:54 +0000901 /* Ok, we have a line. If a non-comment line, return.
902 If a comment line, start all over again. */
903 if (buf[0] != '#') return False;
904 }
905}
906
907
908/* *p_caller contains the raw name of a caller, supposedly either
909 fun:some_function_name or
910 obj:some_object_name.
911 Set *p_ty accordingly and advance *p_caller over the descriptor
912 (fun: or obj:) part.
913 Returns False if failed.
914*/
sewardjb5f6f512005-03-10 23:59:00 +0000915static Bool setLocationTy ( SuppLoc* p )
sewardjde4a1d02002-03-22 01:27:54 +0000916{
sewardjb5f6f512005-03-10 23:59:00 +0000917 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
918 p->name += 4;
919 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +0000920 return True;
921 }
sewardjb5f6f512005-03-10 23:59:00 +0000922 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
923 p->name += 4;
924 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +0000925 return True;
926 }
927 VG_(printf)("location should start with fun: or obj:\n");
928 return False;
929}
930
931
nethercote7cc9c232004-01-21 15:08:04 +0000932/* Look for "tool" in a string like "tool1,tool2,tool3" */
njn11cc9252002-10-07 14:42:59 +0000933static __inline__
nethercote7cc9c232004-01-21 15:08:04 +0000934Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000935{
936 Bool found;
937 Char *s = NULL; /* Shut gcc up */
938 Int len = VG_(strlen)(name);
939
940 found = (NULL != (s = VG_(strstr)(names, name)) &&
941 (s == names || *(s-1) == ',') &&
942 (*(s+len) == ',' || *(s+len) == '\0')
943 );
944
945 return found;
946}
947
njn695c16e2005-03-27 03:40:28 +0000948/* Read suppressions from the file specified in VG_(clo_suppressions)
sewardjde4a1d02002-03-22 01:27:54 +0000949 and place them in the suppressions list. If there's any difficulty
950 doing this, just give up -- there's no point in trying to recover.
951*/
sewardjde4a1d02002-03-22 01:27:54 +0000952static void load_one_suppressions_file ( Char* filename )
953{
954# define N_BUF 200
sewardj92645592005-07-23 09:18:34 +0000955 SysRes sres;
956 Int fd, i;
957 Bool eof;
958 Char buf[N_BUF+1];
959 Char* tool_names;
960 Char* supp_name;
961 Char* err_str = NULL;
sewardjb5f6f512005-03-10 23:59:00 +0000962 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +0000963
sewardj92645592005-07-23 09:18:34 +0000964 fd = -1;
965 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
966 if (sres.isError) {
sewardjf349d552005-11-14 17:01:01 +0000967 if (VG_(clo_xml))
968 VG_(message)(Vg_UserMsg, "</valgrindoutput>\n");
njn02bc4b82005-05-15 17:28:26 +0000969 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file '%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000970 filename );
971 VG_(exit)(1);
972 }
sewardj8a7d4e42006-10-17 01:41:17 +0000973 fd = sres.res;
sewardjde4a1d02002-03-22 01:27:54 +0000974
sewardj92645592005-07-23 09:18:34 +0000975# define BOMB(S) { err_str = S; goto syntax_error; }
sewardjb5f6f512005-03-10 23:59:00 +0000976
sewardjde4a1d02002-03-22 01:27:54 +0000977 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000978 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000979 Supp* supp;
980 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000981 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000982
983 // Initialise temporary reading-in buffer.
984 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
985 tmp_callers[i].ty = NoName;
986 tmp_callers[i].name = NULL;
987 }
988
njn810086f2002-11-14 12:42:47 +0000989 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000990
njn4ba5a792002-09-30 10:23:54 +0000991 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000992 if (eof) break;
993
sewardjb5f6f512005-03-10 23:59:00 +0000994 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000995
njn4ba5a792002-09-30 10:23:54 +0000996 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000997
998 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
999
njn25e49d8e72002-09-23 09:36:25 +00001000 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +00001001
njn4ba5a792002-09-30 10:23:54 +00001002 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +00001003
sewardjb5f6f512005-03-10 23:59:00 +00001004 if (eof) BOMB("unexpected end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +00001005
njn94065fd2004-11-22 19:26:27 +00001006 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +00001007 i = 0;
1008 while (True) {
1009 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +00001010 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +00001011 i++;
njn25e49d8e72002-09-23 09:36:25 +00001012 }
njnc40c3a82002-10-02 11:02:27 +00001013 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1014
nethercote7cc9c232004-01-21 15:08:04 +00001015 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +00001016 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +00001017
nethercote7cc9c232004-01-21 15:08:04 +00001018 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +00001019 {
sewardjb5f6f512005-03-10 23:59:00 +00001020 // A core suppression
njna86f29e2006-12-14 02:55:58 +00001021 //(example code, see comment on CoreSuppKind above)
1022 //if (VG_STREQ(supp_name, "Thread"))
1023 // supp->skind = ThreadSupp;
1024 //else
sewardjb5f6f512005-03-10 23:59:00 +00001025 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +00001026 }
njn95ec8702004-11-22 16:46:13 +00001027 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +00001028 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +00001029 {
sewardjb5f6f512005-03-10 23:59:00 +00001030 // A tool suppression
njn51d827b2005-05-09 01:02:08 +00001031 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +00001032 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +00001033 } else {
1034 BOMB("unknown tool suppression type");
1035 }
njnc40c3a82002-10-02 11:02:27 +00001036 }
njn25e49d8e72002-09-23 09:36:25 +00001037 else {
sewardjb5f6f512005-03-10 23:59:00 +00001038 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +00001039 while (True) {
njn4ba5a792002-09-30 10:23:54 +00001040 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +00001041 if (eof) BOMB("unexpected end-of-file");
njn43c799e2003-04-08 00:08:52 +00001042 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +00001043 break;
1044 }
1045 continue;
sewardjde4a1d02002-03-22 01:27:54 +00001046 }
1047
njn95ec8702004-11-22 16:46:13 +00001048 if (VG_(needs).tool_errors &&
njn51d827b2005-05-09 01:02:08 +00001049 !VG_TDICT_CALL(tool_read_extra_suppression_info, fd, buf, N_BUF, supp))
sewardjb5f6f512005-03-10 23:59:00 +00001050 {
1051 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +00001052 }
1053
sewardjb5f6f512005-03-10 23:59:00 +00001054 i = 0;
1055 while (True) {
1056 eof = VG_(get_line) ( fd, buf, N_BUF );
1057 if (eof)
1058 BOMB("unexpected end-of-file");
1059 if (VG_STREQ(buf, "}")) {
1060 if (i > 0) {
1061 break;
1062 } else {
1063 BOMB("missing stack trace");
1064 }
1065 }
1066 if (i == VG_MAX_SUPP_CALLERS)
1067 BOMB("too many callers in stack trace");
1068 if (i > 0 && i >= VG_(clo_backtrace_size))
1069 break;
1070 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE, buf);
1071 if (!setLocationTy(&(tmp_callers[i])))
1072 BOMB("location should start with 'fun:' or 'obj:'");
1073 i++;
1074 }
1075
1076 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1077 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +00001078 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +00001079 do {
1080 eof = VG_(get_line) ( fd, buf, N_BUF );
1081 } while (!eof && !VG_STREQ(buf, "}"));
1082 }
1083
1084 // Copy tmp_callers[] into supp->callers[]
1085 supp->n_callers = i;
1086 supp->callers = VG_(arena_malloc)(VG_AR_CORE, i*sizeof(SuppLoc));
1087 for (i = 0; i < supp->n_callers; i++) {
1088 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +00001089 }
1090
njn695c16e2005-03-27 03:40:28 +00001091 supp->next = suppressions;
1092 suppressions = supp;
sewardjde4a1d02002-03-22 01:27:54 +00001093 }
sewardjde4a1d02002-03-22 01:27:54 +00001094 VG_(close)(fd);
1095 return;
1096
1097 syntax_error:
sewardjf349d552005-11-14 17:01:01 +00001098 if (VG_(clo_xml))
1099 VG_(message)(Vg_UserMsg, "</valgrindoutput>\n");
sewardjb5f6f512005-03-10 23:59:00 +00001100 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001101 "FATAL: in suppressions file '%s': %s", filename, err_str );
sewardjb5f6f512005-03-10 23:59:00 +00001102
sewardjde4a1d02002-03-22 01:27:54 +00001103 VG_(close)(fd);
1104 VG_(message)(Vg_UserMsg, "exiting now.");
nethercote8ed8a892004-11-08 13:24:25 +00001105 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001106
sewardjb5f6f512005-03-10 23:59:00 +00001107# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +00001108# undef N_BUF
1109}
1110
1111
1112void VG_(load_suppressions) ( void )
1113{
1114 Int i;
njn695c16e2005-03-27 03:40:28 +00001115 suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001116 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1117 if (VG_(clo_verbosity) > 1) {
njn3f04d242005-03-20 18:21:14 +00001118 VG_(message)(Vg_DebugMsg, "Reading suppressions file: %s",
1119 VG_(clo_suppressions)[i] );
sewardjde4a1d02002-03-22 01:27:54 +00001120 }
1121 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1122 }
1123}
1124
sewardjb5f6f512005-03-10 23:59:00 +00001125static
njn810086f2002-11-14 12:42:47 +00001126Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +00001127{
njn810086f2002-11-14 12:42:47 +00001128 switch (su->skind) {
njna86f29e2006-12-14 02:55:58 +00001129 //(example code, see comment on CoreSuppKind above)
1130 //case ThreadSupp:
1131 // return (err->ekind == ThreadErr);
njn25e49d8e72002-09-23 09:36:25 +00001132 default:
njn95ec8702004-11-22 16:46:13 +00001133 if (VG_(needs).tool_errors) {
njn51d827b2005-05-09 01:02:08 +00001134 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
njn25e49d8e72002-09-23 09:36:25 +00001135 } else {
1136 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +00001137 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +00001138 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +00001139 err->ekind);
njn67993252004-11-22 18:02:32 +00001140 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +00001141 }
1142 }
1143}
1144
sewardjb5f6f512005-03-10 23:59:00 +00001145static
1146Bool supp_matches_callers(Error* err, Supp* su)
njn25e49d8e72002-09-23 09:36:25 +00001147{
1148 Int i;
njn83f9e792005-06-11 05:04:09 +00001149 Char caller_name[ERRTXT_LEN];
njnd01fef72005-03-25 23:35:48 +00001150 StackTrace ips = VG_(extract_StackTrace)(err->where);
njn25e49d8e72002-09-23 09:36:25 +00001151
sewardjb5f6f512005-03-10 23:59:00 +00001152 for (i = 0; i < su->n_callers; i++) {
njnd01fef72005-03-25 23:35:48 +00001153 Addr a = ips[i];
sewardjb5f6f512005-03-10 23:59:00 +00001154 vg_assert(su->callers[i].name != NULL);
njn966d6632005-08-18 15:49:21 +00001155 // The string to be used in the unknown case ("???") can be anything
1156 // that couldn't be a valid function or objname. --gen-suppressions
1157 // prints 'obj:*' for such an entry, which will match any string we
1158 // use.
sewardjb5f6f512005-03-10 23:59:00 +00001159 switch (su->callers[i].ty) {
1160 case ObjName:
njn83f9e792005-06-11 05:04:09 +00001161 if (!VG_(get_objname)(a, caller_name, ERRTXT_LEN))
njn966d6632005-08-18 15:49:21 +00001162 VG_(strcpy)(caller_name, "???");
sewardjb5f6f512005-03-10 23:59:00 +00001163 break;
1164
1165 case FunName:
sewardj0c95e942006-01-18 04:23:10 +00001166 // Nb: mangled names used in suppressions. Do, though,
1167 // Z-demangle them, since otherwise it's possible to wind
1168 // up comparing "malloc" in the suppression against
1169 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1170 // two of them need to be made to match.
1171 if (!VG_(get_fnname_Z_demangle_only)(a, caller_name, ERRTXT_LEN))
njn966d6632005-08-18 15:49:21 +00001172 VG_(strcpy)(caller_name, "???");
sewardjb5f6f512005-03-10 23:59:00 +00001173 break;
njn67993252004-11-22 18:02:32 +00001174 default: VG_(tool_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +00001175 }
sewardjda646ca2006-01-19 03:36:52 +00001176 if (0) VG_(printf)("cmp %s %s\n", su->callers[i].name, caller_name);
sewardjb5f6f512005-03-10 23:59:00 +00001177 if (!VG_(string_match)(su->callers[i].name, caller_name))
1178 return False;
njn25e49d8e72002-09-23 09:36:25 +00001179 }
1180
1181 /* If we reach here, it's a match */
1182 return True;
1183}
sewardjde4a1d02002-03-22 01:27:54 +00001184
njn810086f2002-11-14 12:42:47 +00001185/* Does an error context match a suppression? ie is this a suppressible
1186 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001187 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001188*/
njn810086f2002-11-14 12:42:47 +00001189static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001190{
njn810086f2002-11-14 12:42:47 +00001191 Supp* su;
sewardj8a7d4e42006-10-17 01:41:17 +00001192 Supp* su_prev;
1193
1194 /* stats gathering */
1195 em_supplist_searches++;
sewardjde4a1d02002-03-22 01:27:54 +00001196
sewardjde4a1d02002-03-22 01:27:54 +00001197 /* See if the error context matches any suppression. */
sewardj8a7d4e42006-10-17 01:41:17 +00001198 su_prev = NULL;
njn695c16e2005-03-27 03:40:28 +00001199 for (su = suppressions; su != NULL; su = su->next) {
sewardj8a7d4e42006-10-17 01:41:17 +00001200 em_supplist_cmps++;
1201 if (supp_matches_error(su, err) && supp_matches_callers(err, su)) {
1202 /* got a match. Move this entry to the head of the list
1203 in the hope of making future searches cheaper. */
1204 if (su_prev) {
1205 vg_assert(su_prev->next == su);
1206 su_prev->next = su->next;
1207 su->next = suppressions;
1208 suppressions = su;
1209 }
njn25e49d8e72002-09-23 09:36:25 +00001210 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001211 }
sewardj8a7d4e42006-10-17 01:41:17 +00001212 su_prev = su;
sewardjde4a1d02002-03-22 01:27:54 +00001213 }
njn25e49d8e72002-09-23 09:36:25 +00001214 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001215}
1216
sewardj8a7d4e42006-10-17 01:41:17 +00001217/* Show accumulated error-list and suppression-list search stats.
1218*/
1219void VG_(print_errormgr_stats) ( void )
1220{
1221 VG_(message)(Vg_DebugMsg,
1222 " errormgr: %,lu supplist searches, %,lu comparisons during search",
1223 em_supplist_searches, em_supplist_cmps
1224 );
1225 VG_(message)(Vg_DebugMsg,
1226 " errormgr: %,lu errlist searches, %,lu comparisons during search",
1227 em_errlist_searches, em_errlist_cmps
1228 );
1229}
1230
sewardjde4a1d02002-03-22 01:27:54 +00001231/*--------------------------------------------------------------------*/
njneb8896b2005-06-04 20:03:55 +00001232/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001233/*--------------------------------------------------------------------*/