blob: 7f8927836d1262e726c63ce10672aa4f92da07f7 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Management of error messages. vg_errcontext.c ---*/
4/*--------------------------------------------------------------------*/
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
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 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
nethercotef1e5e152004-09-01 23:58:16 +000031#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000032
33/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000034/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000035/*------------------------------------------------------------*/
36
njn14319cc2005-03-13 06:26:22 +000037/* After this many different unsuppressed errors have been observed,
38 be more conservative about collecting new ones. */
39#define M_COLLECT_ERRORS_SLOWLY_AFTER 50
40
41/* After this many different unsuppressed errors have been observed,
42 stop collecting errors at all, and tell the user their program is
43 evidently a steaming pile of camel dung. */
44#define M_COLLECT_NO_ERRORS_AFTER_SHOWN 300
45
46/* After this many total errors have been observed, stop collecting
47 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
48#define M_COLLECT_NO_ERRORS_AFTER_FOUND 30000
49
sewardjde4a1d02002-03-22 01:27:54 +000050/* The list of error contexts found, both suppressed and unsuppressed.
51 Initially empty, and grows as errors are detected. */
njn810086f2002-11-14 12:42:47 +000052static Error* vg_errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000053
54/* The list of suppression directives, as read from the specified
55 suppressions file. */
njn810086f2002-11-14 12:42:47 +000056static Supp* vg_suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000057
58/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000059static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000060
61/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000062static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000063
64/* forwards ... */
njn810086f2002-11-14 12:42:47 +000065static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000066
sewardjb5f6f512005-03-10 23:59:00 +000067static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000068
69/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +000070/*--- Error type ---*/
71/*------------------------------------------------------------*/
72
nethercote996901a2004-08-03 13:29:09 +000073/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
nethercote4a184902004-08-02 12:21:09 +000074 * effectively extend it by defining their own enums in the (0..) range. */
nethercote4a184902004-08-02 12:21:09 +000075
76/* Errors. Extensible (via the 'extra' field). Tools can use a normal
77 enum (with element values in the normal range (0..)) for `ekind'.
78 Functions for getting/setting the tool-relevant fields are in
nethercote46063202004-09-02 08:51:43 +000079 include/tool.h.
nethercote4a184902004-08-02 12:21:09 +000080
81 When errors are found and recorded with VG_(maybe_record_error)(), all
82 the tool must do is pass in the four parameters; core will
83 allocate/initialise the error record.
84*/
85struct _Error {
86 struct _Error* next;
87 // NULL if unsuppressed; or ptr to suppression record.
88 Supp* supp;
89 Int count;
90 ThreadId tid;
91
92 // The tool-specific part
93 ExeContext* where; // Initialised by core
94 Int ekind; // Used by ALL. Must be in the range (0..)
95 Addr addr; // Used frequently
96 Char* string; // Used frequently
97 void* extra; // For any tool-specific extras
98};
99
100ExeContext* VG_(get_error_where) ( Error* err )
101{
102 return err->where;
103}
104
105ErrorKind VG_(get_error_kind) ( Error* err )
106{
107 return err->ekind;
108}
109
110Addr VG_(get_error_address) ( Error* err )
111{
112 return err->addr;
113}
114
115Char* VG_(get_error_string) ( Error* err )
116{
117 return err->string;
118}
119
120void* VG_(get_error_extra) ( Error* err )
121{
122 return err->extra;
123}
124
nethercotef2b11482004-08-02 12:36:01 +0000125UInt VG_(get_n_errs_found)( void )
126{
127 return n_errs_found;
128}
129
nethercote4a184902004-08-02 12:21:09 +0000130/*------------------------------------------------------------*/
131/*--- Suppression type ---*/
132/*------------------------------------------------------------*/
133
134/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
135 * effectively extend it by defining their own enums in the (0..) range. */
136typedef
137 enum {
138 PThreadSupp = -1, /* Matches PThreadErr */
139 }
140 CoreSuppKind;
141
sewardjb5f6f512005-03-10 23:59:00 +0000142/* Max number of callers for context in a suppression. */
143#define VG_MAX_SUPP_CALLERS 24
144
nethercote4a184902004-08-02 12:21:09 +0000145/* For each caller specified for a suppression, record the nature of
146 the caller name. Not of interest to tools. */
147typedef
148 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000149 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000150 ObjName, /* Name is of an shared object file. */
151 FunName /* Name is of a function. */
152 }
153 SuppLocTy;
154
sewardjb5f6f512005-03-10 23:59:00 +0000155typedef
156 struct {
157 SuppLocTy ty;
158 Char* name;
159 }
160 SuppLoc;
161
nethercote4a184902004-08-02 12:21:09 +0000162/* Suppressions. Tools can get/set tool-relevant parts with functions
nethercote46063202004-09-02 08:51:43 +0000163 declared in include/tool.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000164 Tools can use a normal enum (with element values in the normal range
165 (0..)) for `skind'. */
166struct _Supp {
167 struct _Supp* next;
168 Int count; // The number of times this error has been suppressed.
169 Char* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000170
171 // Length of 'callers'
172 Int n_callers;
173 // Array of callers, for matching stack traces. First one (name of fn
174 // where err occurs) is mandatory; rest are optional.
175 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000176
177 /* The tool-specific part */
178 SuppKind skind; // What kind of suppression. Must use the range (0..).
179 Char* string; // String -- use is optional. NULL by default.
180 void* extra; // Anything else -- use is optional. NULL by default.
181};
182
183SuppKind VG_(get_supp_kind) ( Supp* su )
184{
185 return su->skind;
186}
187
188Char* VG_(get_supp_string) ( Supp* su )
189{
190 return su->string;
191}
192
193void* VG_(get_supp_extra) ( Supp* su )
194{
195 return su->extra;
196}
197
198
199void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
200{
201 su->skind = skind;
202}
203
204void VG_(set_supp_string) ( Supp* su, Char* string )
205{
206 su->string = string;
207}
208
209void VG_(set_supp_extra) ( Supp* su, void* extra )
210{
211 su->extra = extra;
212}
213
214
215/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000216/*--- Helper fns ---*/
217/*------------------------------------------------------------*/
218
sewardjde4a1d02002-03-22 01:27:54 +0000219/* Compare error contexts, to detect duplicates. Note that if they
220 are otherwise the same, the faulting addrs and associated rwoffsets
221 are allowed to be different. */
njn810086f2002-11-14 12:42:47 +0000222static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000223{
njn810086f2002-11-14 12:42:47 +0000224 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000225 return False;
njn25e49d8e72002-09-23 09:36:25 +0000226 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000227 return False;
228
njn810086f2002-11-14 12:42:47 +0000229 switch (e1->ekind) {
sewardjb5f6f512005-03-10 23:59:00 +0000230 // case ThreadErr:
231 // case MutexErr:
232 // vg_assert(VG_(needs).core_errors);
233 // return VG_(tm_error_equal)(res, e1, e2);
sewardjde4a1d02002-03-22 01:27:54 +0000234 default:
njn95ec8702004-11-22 16:46:13 +0000235 if (VG_(needs).tool_errors)
njn26f02512004-11-22 18:33:15 +0000236 return TL_(eq_Error)(res, e1, e2);
njn25e49d8e72002-09-23 09:36:25 +0000237 else {
njn95ec8702004-11-22 16:46:13 +0000238 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000239 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000240 e1->ekind);
njn67993252004-11-22 18:02:32 +0000241 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000242 }
sewardjde4a1d02002-03-22 01:27:54 +0000243 }
244}
245
njn810086f2002-11-14 12:42:47 +0000246static void pp_Error ( Error* err, Bool printCount )
sewardjde4a1d02002-03-22 01:27:54 +0000247{
sewardjde4a1d02002-03-22 01:27:54 +0000248 if (printCount)
njn25e49d8e72002-09-23 09:36:25 +0000249 VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
sewardjb5f6f512005-03-10 23:59:00 +0000250 if (err->tid > 0 && err->tid != last_tid_printed) {
njn25e49d8e72002-09-23 09:36:25 +0000251 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
sewardjb5f6f512005-03-10 23:59:00 +0000252 last_tid_printed = err->tid;
253 }
njn25e49d8e72002-09-23 09:36:25 +0000254
njn810086f2002-11-14 12:42:47 +0000255 switch (err->ekind) {
sewardjb5f6f512005-03-10 23:59:00 +0000256 // case ThreadErr:
257 // case MutexErr:
258 // vg_assert(VG_(needs).core_errors);
259 // VG_(tm_error_print)(err);
260 // break;
sewardjde4a1d02002-03-22 01:27:54 +0000261 default:
njn95ec8702004-11-22 16:46:13 +0000262 if (VG_(needs).tool_errors)
njn26f02512004-11-22 18:33:15 +0000263 TL_(pp_Error)( err );
njn25e49d8e72002-09-23 09:36:25 +0000264 else {
njn95ec8702004-11-22 16:46:13 +0000265 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000266 "probably needs to be set?\n",
njn810086f2002-11-14 12:42:47 +0000267 err->ekind);
njn67993252004-11-22 18:02:32 +0000268 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000269 }
sewardjde4a1d02002-03-22 01:27:54 +0000270 }
271}
272
nethercote04d0fbc2004-01-26 16:48:06 +0000273/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000274 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000275Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000276{
277 Char ch, ch2;
278 Int res;
279
njn43c799e2003-04-08 00:08:52 +0000280 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000281 return False;
282
283 VG_(message)(Vg_UserMsg, "");
284
285 again:
286 VG_(printf)(
287 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000288 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
289 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000290 );
291
sewardj6024b212003-07-13 10:54:33 +0000292 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000293 if (res != 1) goto ioerror;
294 /* res == 1 */
295 if (ch == '\n') return False;
296 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
297 && ch != 'C' && ch != 'c') goto again;
298
sewardj6024b212003-07-13 10:54:33 +0000299 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000300 if (res != 1) goto ioerror;
301 if (ch2 != '\n') goto again;
302
njn43c799e2003-04-08 00:08:52 +0000303 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000304 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000305 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000306 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000307 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000308 vg_assert(ch == 'c' || ch == 'C');
309
310 ioerror:
njn43c799e2003-04-08 00:08:52 +0000311 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000312 return False;
313}
314
315
sewardjb5f6f512005-03-10 23:59:00 +0000316/* Construct an error */
njn25e49d8e72002-09-23 09:36:25 +0000317static __inline__
njn72718642003-07-24 08:45:32 +0000318void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
319 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000320{
njnca82cc02004-11-22 17:18:48 +0000321 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000322
njn810086f2002-11-14 12:42:47 +0000323 /* Core-only parts */
njn25e49d8e72002-09-23 09:36:25 +0000324 err->next = NULL;
325 err->supp = NULL;
326 err->count = 1;
njn72718642003-07-24 08:45:32 +0000327 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000328 if (NULL == where)
njn72718642003-07-24 08:45:32 +0000329 err->where = VG_(get_ExeContext)( tid );
njn43c799e2003-04-08 00:08:52 +0000330 else
331 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000332
nethercote996901a2004-08-03 13:29:09 +0000333 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000334 err->ekind = ekind;
335 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000336 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000337 err->string = s;
338
njn25e49d8e72002-09-23 09:36:25 +0000339 /* sanity... */
njn72718642003-07-24 08:45:32 +0000340 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000341}
342
nethercote10d481a2004-01-25 20:33:53 +0000343static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000344{
sewardj05bcdcb2003-05-18 10:05:38 +0000345 Int i;
nethercote3b38c1d2004-10-18 15:47:18 +0000346 static UChar buf[M_VG_ERRTXT];
nethercote77eba602003-11-13 17:35:04 +0000347 Bool main_done = False;
njn43c799e2003-04-08 00:08:52 +0000348 ExeContext* ec = VG_(get_error_where)(err);
349 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000350
sewardjb5f6f512005-03-10 23:59:00 +0000351 /* At most VG_MAX_SUPP_CALLERS names */
352 if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
njn43c799e2003-04-08 00:08:52 +0000353 vg_assert(stop_at > 0);
354
355 VG_(printf)("{\n");
356 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000357
sewardjb5f6f512005-03-10 23:59:00 +0000358 if (ThreadErr == err->ekind || MutexErr == err->ekind) {
njn6a230532003-07-21 10:38:23 +0000359 VG_(printf)(" core:PThread\n");
360
361 } else {
njn26f02512004-11-22 18:33:15 +0000362 Char* name = TL_(get_error_name)(err);
njn6a230532003-07-21 10:38:23 +0000363 if (NULL == name) {
364 VG_(message)(Vg_UserMsg,
nethercote137bc552003-11-14 17:47:54 +0000365 "(tool does not allow error to be suppressed)");
njn6a230532003-07-21 10:38:23 +0000366 return;
367 }
368 VG_(printf)(" %s:%s\n", VG_(details).name, name);
njn26f02512004-11-22 18:33:15 +0000369 TL_(print_extra_suppression_info)(err);
njn6a230532003-07-21 10:38:23 +0000370 }
njn43c799e2003-04-08 00:08:52 +0000371
372 /* This loop condensed from VG_(mini_stack_dump)() */
373 i = 0;
374 do {
nethercote86c5dcb2004-09-05 21:32:37 +0000375 Addr eip = ec->ips[i];
nethercotefbfc1082004-09-04 15:28:37 +0000376 if (i > 0)
377 eip -= MIN_INSTR_SIZE; // point to calling line
njn43c799e2003-04-08 00:08:52 +0000378 if ( VG_(get_fnname_nodemangle) (eip, buf, M_VG_ERRTXT) ) {
nethercote77eba602003-11-13 17:35:04 +0000379 // Stop after "main"; if main() is recursive, stop after last main().
380
381 if ( ! VG_(clo_show_below_main)) {
382 if (VG_STREQ(buf, "main"))
383 main_done = True;
384 else if (main_done)
385 break;
386 }
njn43c799e2003-04-08 00:08:52 +0000387 VG_(printf)(" fun:%s\n", buf);
388 } else if ( VG_(get_objname)(eip, buf, M_VG_ERRTXT) ) {
389 VG_(printf)(" obj:%s\n", buf);
390 } else {
391 VG_(printf)(" ???:??? "
nethercote125c91e2004-06-27 12:38:17 +0000392 "# unknown, suppression will not work, sorry\n");
njn43c799e2003-04-08 00:08:52 +0000393 }
394 i++;
nethercote86c5dcb2004-09-05 21:32:37 +0000395 } while (i < stop_at && ec->ips[i] != 0);
njn43c799e2003-04-08 00:08:52 +0000396
397 VG_(printf)("}\n");
398}
399
njnb4aee052003-04-15 14:09:58 +0000400static
nethercote04d0fbc2004-01-26 16:48:06 +0000401void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000402{
sewardjd153fae2005-01-10 17:24:47 +0000403 Bool still_noisy = True;
404
nethercote04d0fbc2004-01-26 16:48:06 +0000405 /* Perhaps we want a debugger attach at this point? */
406 if (allow_db_attach &&
407 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
njn3e884182003-04-15 13:03:23 +0000408 {
nethercote04d0fbc2004-01-26 16:48:06 +0000409 VG_(printf)("starting debugger\n");
410 VG_(start_debugger)( err->tid );
njn43c799e2003-04-08 00:08:52 +0000411 }
412 /* Or maybe we want to generate the error's suppression? */
sewardjd153fae2005-01-10 17:24:47 +0000413 if (VG_(clo_gen_suppressions) == 2
414 || (VG_(clo_gen_suppressions) == 1
415 && VG_(is_action_requested)( "Print suppression",
416 &still_noisy ))
417 ) {
nethercote42602b12004-01-25 19:30:29 +0000418 gen_suppression(err);
sewardjd153fae2005-01-10 17:24:47 +0000419 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
420 VG_(clo_gen_suppressions) = 0;
njn43c799e2003-04-08 00:08:52 +0000421 }
422}
423
424/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
425 just for pretty printing purposes. */
426static Bool is_first_shown_context = True;
427
njn25e49d8e72002-09-23 09:36:25 +0000428/* Top-level entry point to the error management subsystem.
429 All detected errors are notified here; this routine decides if/when the
430 user should see the error. */
njn72718642003-07-24 08:45:32 +0000431void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000432 ErrorKind ekind, Addr a, Char* s, void* extra )
433{
njn810086f2002-11-14 12:42:47 +0000434 Error err;
435 Error* p;
436 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000437 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000438 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000439 static Bool stopping_message = False;
440 static Bool slowdown_message = False;
441 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000442
njn14319cc2005-03-13 06:26:22 +0000443 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
444 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000445 have been found, just refuse to collect any more. This stops
446 the burden of the error-management system becoming excessive in
447 extremely buggy programs, although it does make it pretty
448 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000449 if (VG_(clo_error_limit)
njn14319cc2005-03-13 06:26:22 +0000450 && (vg_n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
451 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000452 if (!stopping_message) {
453 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000454
njn14319cc2005-03-13 06:26:22 +0000455 if (vg_n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardjf2537be2002-04-24 21:03:47 +0000456 VG_(message)(Vg_UserMsg,
457 "More than %d different errors detected. "
458 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000459 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000460 } else {
461 VG_(message)(Vg_UserMsg,
462 "More than %d total errors detected. "
463 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000464 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000465 }
466
sewardjde4a1d02002-03-22 01:27:54 +0000467 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000468 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000469 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000470 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000471 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000472 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000473 VG_(message)(Vg_UserMsg,
474 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000475 VG_(message)(Vg_UserMsg, "");
476 stopping_message = True;
477 }
478 return;
479 }
480
njn14319cc2005-03-13 06:26:22 +0000481 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000482 been found, be much more conservative about collecting new
483 ones. */
njn14319cc2005-03-13 06:26:22 +0000484 if (vg_n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000485 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000486 if (!slowdown_message) {
487 VG_(message)(Vg_UserMsg, "");
488 VG_(message)(Vg_UserMsg,
489 "More than %d errors detected. Subsequent errors",
njn14319cc2005-03-13 06:26:22 +0000490 M_COLLECT_ERRORS_SLOWLY_AFTER);
sewardjde4a1d02002-03-22 01:27:54 +0000491 VG_(message)(Vg_UserMsg,
492 "will still be recorded, but in less detail than before.");
493 slowdown_message = True;
494 }
495 }
496
njn25e49d8e72002-09-23 09:36:25 +0000497 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000498 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000499
500 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000501 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000502 p_prev = NULL;
503 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000504 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000505 /* Found it. */
506 p->count++;
507 if (p->supp != NULL) {
508 /* Deal correctly with suppressed errors. */
509 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000510 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000511 } else {
nethercotef2b11482004-08-02 12:36:01 +0000512 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000513 }
514
515 /* Move p to the front of the list so that future searches
516 for it are faster. */
517 if (p_prev != NULL) {
518 vg_assert(p_prev->next == p);
519 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000520 p->next = vg_errors;
521 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000522 }
sewardj7ebf7c32003-07-24 21:29:40 +0000523
sewardjde4a1d02002-03-22 01:27:54 +0000524 return;
525 }
526 p_prev = p;
527 p = p->next;
528 }
529
530 /* Didn't see it. Copy and add. */
531
njn43c799e2003-04-08 00:08:52 +0000532 /* OK, we're really going to collect it. The context is on the stack and
533 will disappear shortly, so we must copy it. First do the main
534 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000535
njn26f02512004-11-22 18:33:15 +0000536 Then TL_(update_extra) can update the `extra' part. This is for when
njn43c799e2003-04-08 00:08:52 +0000537 there are more details to fill in which take time to work out but
538 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000539 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000540 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000541
542 Then, if there is an `extra' part, copy it too, using the size that
njn26f02512004-11-22 18:33:15 +0000543 TL_(update_extra) returned. Also allow for people using the void*
njna70114c2003-08-19 16:14:42 +0000544 extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000545 */
546
547 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000548 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000549 *p = err;
njn43c799e2003-04-08 00:08:52 +0000550
sewardjb5f6f512005-03-10 23:59:00 +0000551 /* update `extra' */
552 switch (ekind) {
553 // case ThreadErr:
554 // case MutexErr:
555 // vg_assert(VG_(needs).core_errors);
556 // extra_size = VG_(tm_error_update_extra)(p);
557 // break;
558 default:
559 vg_assert(VG_(needs).tool_errors);
560 extra_size = TL_(update_extra)(p);
561 break;
562 }
njn43c799e2003-04-08 00:08:52 +0000563
sewardjb5f6f512005-03-10 23:59:00 +0000564 /* copy block pointed to by `extra', if there is one */
565 if (NULL != p->extra && 0 != extra_size) {
566 void* new_extra = VG_(malloc)(extra_size);
567 VG_(memcpy)(new_extra, p->extra, extra_size);
568 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000569 }
570
njn25e49d8e72002-09-23 09:36:25 +0000571 p->next = vg_errors;
572 p->supp = is_suppressible_error(&err);
573 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000574 if (p->supp == NULL) {
nethercotef2b11482004-08-02 12:36:01 +0000575 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000576 if (!is_first_shown_context)
577 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000578 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000579 is_first_shown_context = False;
580 vg_n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000581 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000582 } else {
nethercotef2b11482004-08-02 12:36:01 +0000583 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000584 p->supp->count++;
585 }
586}
587
njn43c799e2003-04-08 00:08:52 +0000588/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000589 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000590 guaranteed to only happen once. This avoids all the recording and
591 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000592 suppressed. Bool `print_error' dictates whether to print the error.
nethercotef2b11482004-08-02 12:36:01 +0000593 Bool `count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000594*/
njn72718642003-07-24 08:45:32 +0000595Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000596 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000597 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000598{
599 Error err;
600
601 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000602 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000603
604 /* Unless it's suppressed, we're going to show it. Don't need to make
605 a copy, because it's only temporary anyway.
606
njn26f02512004-11-22 18:33:15 +0000607 Then update the `extra' part with TL_(update_extra), because that can
njn43c799e2003-04-08 00:08:52 +0000608 have an affect on whether it's suppressed. Ignore the size return
njn26f02512004-11-22 18:33:15 +0000609 value of TL_(update_extra), because we're not copying `extra'. */
610 (void)TL_(update_extra)(&err);
njn43c799e2003-04-08 00:08:52 +0000611
612 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000613 if (count_error)
nethercotef2b11482004-08-02 12:36:01 +0000614 n_errs_found++;
njn43c799e2003-04-08 00:08:52 +0000615
616 if (print_error) {
617 if (!is_first_shown_context)
618 VG_(message)(Vg_UserMsg, "");
619 pp_Error(&err, False);
620 is_first_shown_context = False;
621 }
nethercote04d0fbc2004-01-26 16:48:06 +0000622 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000623
624 return False;
625
626 } else {
nethercotef2b11482004-08-02 12:36:01 +0000627 n_errs_suppressed++;
njn43c799e2003-04-08 00:08:52 +0000628 return True;
629 }
630}
631
sewardjde4a1d02002-03-22 01:27:54 +0000632
sewardjde4a1d02002-03-22 01:27:54 +0000633/*------------------------------------------------------------*/
634/*--- Exported fns ---*/
635/*------------------------------------------------------------*/
636
njnb9ecfe32005-03-13 05:27:57 +0000637/* This is called not from generated code but from the scheduler */
sewardjde4a1d02002-03-22 01:27:54 +0000638void VG_(show_all_errors) ( void )
639{
njn810086f2002-11-14 12:42:47 +0000640 Int i, n_min;
641 Int n_err_contexts, n_supp_contexts;
642 Error *p, *p_min;
643 Supp *su;
644 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000645
646 if (VG_(clo_verbosity) == 0)
647 return;
648
649 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000650 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000651 if (p->supp == NULL)
652 n_err_contexts++;
653 }
654
655 n_supp_contexts = 0;
656 for (su = vg_suppressions; su != NULL; su = su->next) {
657 if (su->count > 0)
658 n_supp_contexts++;
659 }
sewardjde4a1d02002-03-22 01:27:54 +0000660 VG_(message)(Vg_UserMsg,
661 "ERROR SUMMARY: "
662 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000663 n_errs_found, n_err_contexts,
664 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000665
666 if (VG_(clo_verbosity) <= 1)
667 return;
668
669 /* Print the contexts in order of increasing error count. */
670 for (i = 0; i < n_err_contexts; i++) {
671 n_min = (1 << 30) - 1;
672 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000673 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000674 if (p->supp != NULL) continue;
675 if (p->count < n_min) {
676 n_min = p->count;
677 p_min = p;
678 }
679 }
njn67993252004-11-22 18:02:32 +0000680 if (p_min == NULL) VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000681
682 VG_(message)(Vg_UserMsg, "");
683 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
684 p_min->count,
685 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000686 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000687
688 if ((i+1 == VG_(clo_dump_error))) {
sewardjfa8ec112005-01-19 11:55:34 +0000689 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
690 p_min->where->ips[0], /*debugging*/True,
691 0xFE/*verbosity*/);
sewardjde4a1d02002-03-22 01:27:54 +0000692 }
693
694 p_min->count = 1 << 30;
695 }
696
697 if (n_supp_contexts > 0)
698 VG_(message)(Vg_DebugMsg, "");
699 any_supp = False;
700 for (su = vg_suppressions; su != NULL; su = su->next) {
701 if (su->count > 0) {
702 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000703 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000704 }
705 }
706
707 if (n_err_contexts > 0) {
708 if (any_supp)
709 VG_(message)(Vg_UserMsg, "");
710 VG_(message)(Vg_UserMsg,
711 "IN SUMMARY: "
712 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000713 n_errs_found, n_err_contexts, n_errs_suppressed,
sewardjde4a1d02002-03-22 01:27:54 +0000714 n_supp_contexts );
715 VG_(message)(Vg_UserMsg, "");
716 }
717}
718
719/*------------------------------------------------------------*/
720/*--- Standard suppressions ---*/
721/*------------------------------------------------------------*/
722
723/* Get a non-blank, non-comment line of at most nBuf chars from fd.
724 Skips leading spaces on the line. Return True if EOF was hit instead.
725*/
726
727#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
728
njn4ba5a792002-09-30 10:23:54 +0000729Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000730{
731 Char ch;
732 Int n, i;
733 while (True) {
734 /* First, read until a non-blank char appears. */
735 while (True) {
736 n = VG_(read)(fd, &ch, 1);
737 if (n == 1 && !VG_ISSPACE(ch)) break;
738 if (n == 0) return True;
739 }
740
741 /* Now, read the line into buf. */
742 i = 0;
743 buf[i++] = ch; buf[i] = 0;
744 while (True) {
745 n = VG_(read)(fd, &ch, 1);
746 if (n == 0) return False; /* the next call will return True */
747 if (ch == '\n') break;
748 if (i > 0 && i == nBuf-1) i--;
749 buf[i++] = ch; buf[i] = 0;
750 }
751 while (i > 1 && VG_ISSPACE(buf[i-1])) {
752 i--; buf[i] = 0;
753 };
754
755 /* VG_(printf)("The line is `%s'\n", buf); */
756 /* Ok, we have a line. If a non-comment line, return.
757 If a comment line, start all over again. */
758 if (buf[0] != '#') return False;
759 }
760}
761
762
763/* *p_caller contains the raw name of a caller, supposedly either
764 fun:some_function_name or
765 obj:some_object_name.
766 Set *p_ty accordingly and advance *p_caller over the descriptor
767 (fun: or obj:) part.
768 Returns False if failed.
769*/
sewardjb5f6f512005-03-10 23:59:00 +0000770static Bool setLocationTy ( SuppLoc* p )
sewardjde4a1d02002-03-22 01:27:54 +0000771{
sewardjb5f6f512005-03-10 23:59:00 +0000772 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
773 p->name += 4;
774 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +0000775 return True;
776 }
sewardjb5f6f512005-03-10 23:59:00 +0000777 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
778 p->name += 4;
779 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +0000780 return True;
781 }
782 VG_(printf)("location should start with fun: or obj:\n");
783 return False;
784}
785
786
nethercote7cc9c232004-01-21 15:08:04 +0000787/* Look for "tool" in a string like "tool1,tool2,tool3" */
njn11cc9252002-10-07 14:42:59 +0000788static __inline__
nethercote7cc9c232004-01-21 15:08:04 +0000789Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000790{
791 Bool found;
792 Char *s = NULL; /* Shut gcc up */
793 Int len = VG_(strlen)(name);
794
795 found = (NULL != (s = VG_(strstr)(names, name)) &&
796 (s == names || *(s-1) == ',') &&
797 (*(s+len) == ',' || *(s+len) == '\0')
798 );
799
800 return found;
801}
802
sewardjde4a1d02002-03-22 01:27:54 +0000803/* Read suppressions from the file specified in vg_clo_suppressions
804 and place them in the suppressions list. If there's any difficulty
805 doing this, just give up -- there's no point in trying to recover.
806*/
sewardjde4a1d02002-03-22 01:27:54 +0000807static void load_one_suppressions_file ( Char* filename )
808{
809# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000810 Int fd, i;
sewardjb5f6f512005-03-10 23:59:00 +0000811 Bool eof;
njnc40c3a82002-10-02 11:02:27 +0000812 Char buf[N_BUF+1];
nethercote7cc9c232004-01-21 15:08:04 +0000813 Char* tool_names;
njnc40c3a82002-10-02 11:02:27 +0000814 Char* supp_name;
sewardjb5f6f512005-03-10 23:59:00 +0000815 Char* err_str = NULL;
816 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +0000817
njn25e49d8e72002-09-23 09:36:25 +0000818 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000819 if (fd < 0) {
njn25e49d8e72002-09-23 09:36:25 +0000820 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000821 filename );
822 VG_(exit)(1);
823 }
824
sewardjb5f6f512005-03-10 23:59:00 +0000825#define BOMB(S) { err_str = S; goto syntax_error; }
826
sewardjde4a1d02002-03-22 01:27:54 +0000827 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000828 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000829 Supp* supp;
830 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000831 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000832
833 // Initialise temporary reading-in buffer.
834 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
835 tmp_callers[i].ty = NoName;
836 tmp_callers[i].name = NULL;
837 }
838
njn810086f2002-11-14 12:42:47 +0000839 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000840
njn4ba5a792002-09-30 10:23:54 +0000841 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000842 if (eof) break;
843
sewardjb5f6f512005-03-10 23:59:00 +0000844 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000845
njn4ba5a792002-09-30 10:23:54 +0000846 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000847
848 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
849
njn25e49d8e72002-09-23 09:36:25 +0000850 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000851
njn4ba5a792002-09-30 10:23:54 +0000852 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000853
sewardjb5f6f512005-03-10 23:59:00 +0000854 if (eof) BOMB("unexpected end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000855
njn94065fd2004-11-22 19:26:27 +0000856 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000857 i = 0;
858 while (True) {
859 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +0000860 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +0000861 i++;
njn25e49d8e72002-09-23 09:36:25 +0000862 }
njnc40c3a82002-10-02 11:02:27 +0000863 buf[i] = '\0'; /* Replace ':', splitting into two strings */
864
nethercote7cc9c232004-01-21 15:08:04 +0000865 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +0000866 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000867
nethercote7cc9c232004-01-21 15:08:04 +0000868 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +0000869 {
sewardjb5f6f512005-03-10 23:59:00 +0000870 // A core suppression
njn43c799e2003-04-08 00:08:52 +0000871 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000872 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000873 else
sewardjb5f6f512005-03-10 23:59:00 +0000874 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +0000875 }
njn95ec8702004-11-22 16:46:13 +0000876 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +0000877 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +0000878 {
sewardjb5f6f512005-03-10 23:59:00 +0000879 // A tool suppression
880 if (TL_(recognised_suppression)(supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +0000881 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +0000882 } else {
883 BOMB("unknown tool suppression type");
884 }
njnc40c3a82002-10-02 11:02:27 +0000885 }
njn25e49d8e72002-09-23 09:36:25 +0000886 else {
sewardjb5f6f512005-03-10 23:59:00 +0000887 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +0000888 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000889 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000890 if (eof) BOMB("unexpected end-of-file");
njn43c799e2003-04-08 00:08:52 +0000891 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000892 break;
893 }
894 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000895 }
896
njn95ec8702004-11-22 16:46:13 +0000897 if (VG_(needs).tool_errors &&
sewardjb5f6f512005-03-10 23:59:00 +0000898 !TL_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
899 {
900 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +0000901 }
902
sewardjb5f6f512005-03-10 23:59:00 +0000903 i = 0;
904 while (True) {
905 eof = VG_(get_line) ( fd, buf, N_BUF );
906 if (eof)
907 BOMB("unexpected end-of-file");
908 if (VG_STREQ(buf, "}")) {
909 if (i > 0) {
910 break;
911 } else {
912 BOMB("missing stack trace");
913 }
914 }
915 if (i == VG_MAX_SUPP_CALLERS)
916 BOMB("too many callers in stack trace");
917 if (i > 0 && i >= VG_(clo_backtrace_size))
918 break;
919 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE, buf);
920 if (!setLocationTy(&(tmp_callers[i])))
921 BOMB("location should start with 'fun:' or 'obj:'");
922 i++;
923 }
924
925 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
926 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +0000927 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +0000928 do {
929 eof = VG_(get_line) ( fd, buf, N_BUF );
930 } while (!eof && !VG_STREQ(buf, "}"));
931 }
932
933 // Copy tmp_callers[] into supp->callers[]
934 supp->n_callers = i;
935 supp->callers = VG_(arena_malloc)(VG_AR_CORE, i*sizeof(SuppLoc));
936 for (i = 0; i < supp->n_callers; i++) {
937 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +0000938 }
939
sewardjde4a1d02002-03-22 01:27:54 +0000940 supp->next = vg_suppressions;
941 vg_suppressions = supp;
942 }
sewardjde4a1d02002-03-22 01:27:54 +0000943 VG_(close)(fd);
944 return;
945
946 syntax_error:
sewardjb5f6f512005-03-10 23:59:00 +0000947 VG_(message)(Vg_UserMsg,
948 "FATAL: in suppressions file `%s': %s", filename, err_str );
949
sewardjde4a1d02002-03-22 01:27:54 +0000950 VG_(close)(fd);
951 VG_(message)(Vg_UserMsg, "exiting now.");
nethercote8ed8a892004-11-08 13:24:25 +0000952 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +0000953
sewardjb5f6f512005-03-10 23:59:00 +0000954# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +0000955# undef N_BUF
956}
957
958
959void VG_(load_suppressions) ( void )
960{
961 Int i;
962 vg_suppressions = NULL;
963 for (i = 0; i < VG_(clo_n_suppressions); i++) {
964 if (VG_(clo_verbosity) > 1) {
965 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
966 VG_(clo_suppressions)[i] );
967 }
968 load_one_suppressions_file( VG_(clo_suppressions)[i] );
969 }
970}
971
sewardjb5f6f512005-03-10 23:59:00 +0000972static
njn810086f2002-11-14 12:42:47 +0000973Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000974{
njn810086f2002-11-14 12:42:47 +0000975 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000976 case PThreadSupp:
sewardjb5f6f512005-03-10 23:59:00 +0000977 return (err->ekind == ThreadErr || err->ekind == MutexErr);
njn25e49d8e72002-09-23 09:36:25 +0000978 default:
njn95ec8702004-11-22 16:46:13 +0000979 if (VG_(needs).tool_errors) {
njn26f02512004-11-22 18:33:15 +0000980 return TL_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000981 } else {
982 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +0000983 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000984 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000985 err->ekind);
njn67993252004-11-22 18:02:32 +0000986 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000987 }
988 }
989}
990
sewardjb5f6f512005-03-10 23:59:00 +0000991static
992Bool supp_matches_callers(Error* err, Supp* su)
njn25e49d8e72002-09-23 09:36:25 +0000993{
994 Int i;
sewardjb5f6f512005-03-10 23:59:00 +0000995 Char caller_name[M_VG_ERRTXT];
njn25e49d8e72002-09-23 09:36:25 +0000996
sewardjb5f6f512005-03-10 23:59:00 +0000997 for (i = 0; i < su->n_callers; i++) {
998 Addr a = err->where->ips[i];
999 vg_assert(su->callers[i].name != NULL);
1000 switch (su->callers[i].ty) {
1001 case ObjName:
njn58c9f812005-03-11 04:46:09 +00001002 if (!VG_(get_objname)(a, caller_name, M_VG_ERRTXT))
1003 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001004 break;
1005
1006 case FunName:
1007 // Nb: mangled names used in suppressions
njn58c9f812005-03-11 04:46:09 +00001008 if (!VG_(get_fnname_nodemangle)(a, caller_name, M_VG_ERRTXT))
1009 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001010 break;
njn67993252004-11-22 18:02:32 +00001011 default: VG_(tool_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +00001012 }
sewardjb5f6f512005-03-10 23:59:00 +00001013 if (!VG_(string_match)(su->callers[i].name, caller_name))
1014 return False;
njn25e49d8e72002-09-23 09:36:25 +00001015 }
1016
1017 /* If we reach here, it's a match */
1018 return True;
1019}
sewardjde4a1d02002-03-22 01:27:54 +00001020
njn810086f2002-11-14 12:42:47 +00001021/* Does an error context match a suppression? ie is this a suppressible
1022 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001023 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001024*/
njn810086f2002-11-14 12:42:47 +00001025static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001026{
njn810086f2002-11-14 12:42:47 +00001027 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +00001028
sewardjde4a1d02002-03-22 01:27:54 +00001029 /* See if the error context matches any suppression. */
1030 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +00001031 if (supp_matches_error(su, err) &&
sewardjb5f6f512005-03-10 23:59:00 +00001032 supp_matches_callers(err, su))
1033 {
njn25e49d8e72002-09-23 09:36:25 +00001034 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001035 }
sewardjde4a1d02002-03-22 01:27:54 +00001036 }
njn25e49d8e72002-09-23 09:36:25 +00001037 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001038}
1039
sewardjde4a1d02002-03-22 01:27:54 +00001040/*--------------------------------------------------------------------*/
sewardjb5f6f512005-03-10 23:59:00 +00001041/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001042/*--------------------------------------------------------------------*/