blob: 79b2d15a371e01e8545ea48b41445c47b94f9bcb [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
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"
njnd2b17112005-04-19 04:10:25 +000032#include "pub_core_errormgr.h"
njnd01fef72005-03-25 23:35:48 +000033#include "pub_core_execontext.h"
njn20242342005-05-16 23:31:24 +000034#include "pub_core_options.h"
njnd2b17112005-04-19 04:10:25 +000035#include "pub_core_stacktrace.h"
njn43b9a8a2005-05-10 04:37:01 +000036#include "pub_core_tooliface.h"
njn3cbfbc12005-05-13 23:11:40 +000037#include "pub_core_translate.h"
sewardjde4a1d02002-03-22 01:27:54 +000038
39/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000040/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000041/*------------------------------------------------------------*/
42
njn14319cc2005-03-13 06:26:22 +000043/* After this many different unsuppressed errors have been observed,
44 be more conservative about collecting new ones. */
45#define M_COLLECT_ERRORS_SLOWLY_AFTER 50
46
47/* After this many different unsuppressed errors have been observed,
48 stop collecting errors at all, and tell the user their program is
49 evidently a steaming pile of camel dung. */
50#define M_COLLECT_NO_ERRORS_AFTER_SHOWN 300
51
52/* After this many total errors have been observed, stop collecting
53 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
54#define M_COLLECT_NO_ERRORS_AFTER_FOUND 30000
55
sewardjde4a1d02002-03-22 01:27:54 +000056/* The list of error contexts found, both suppressed and unsuppressed.
57 Initially empty, and grows as errors are detected. */
njn695c16e2005-03-27 03:40:28 +000058static Error* errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000059
60/* The list of suppression directives, as read from the specified
61 suppressions file. */
njn695c16e2005-03-27 03:40:28 +000062static Supp* suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000063
64/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000065static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000066
67/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000068static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000069
70/* forwards ... */
njn810086f2002-11-14 12:42:47 +000071static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000072
sewardjb5f6f512005-03-10 23:59:00 +000073static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000074
75/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +000076/*--- Error type ---*/
77/*------------------------------------------------------------*/
78
nethercote996901a2004-08-03 13:29:09 +000079/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
nethercote4a184902004-08-02 12:21:09 +000080 * effectively extend it by defining their own enums in the (0..) range. */
nethercote4a184902004-08-02 12:21:09 +000081
82/* Errors. Extensible (via the 'extra' field). Tools can use a normal
njn02bc4b82005-05-15 17:28:26 +000083 enum (with element values in the normal range (0..)) for 'ekind'.
nethercote4a184902004-08-02 12:21:09 +000084 Functions for getting/setting the tool-relevant fields are in
nethercote46063202004-09-02 08:51:43 +000085 include/tool.h.
nethercote4a184902004-08-02 12:21:09 +000086
87 When errors are found and recorded with VG_(maybe_record_error)(), all
88 the tool must do is pass in the four parameters; core will
89 allocate/initialise the error record.
90*/
91struct _Error {
92 struct _Error* next;
93 // NULL if unsuppressed; or ptr to suppression record.
94 Supp* supp;
95 Int count;
96 ThreadId tid;
97
98 // The tool-specific part
99 ExeContext* where; // Initialised by core
njnd2b17112005-04-19 04:10:25 +0000100 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
nethercote4a184902004-08-02 12:21:09 +0000101 Addr addr; // Used frequently
102 Char* string; // Used frequently
103 void* extra; // For any tool-specific extras
104};
105
106ExeContext* VG_(get_error_where) ( Error* err )
107{
108 return err->where;
109}
110
111ErrorKind VG_(get_error_kind) ( Error* err )
112{
113 return err->ekind;
114}
115
116Addr VG_(get_error_address) ( Error* err )
117{
118 return err->addr;
119}
120
121Char* VG_(get_error_string) ( Error* err )
122{
123 return err->string;
124}
125
126void* VG_(get_error_extra) ( Error* err )
127{
128 return err->extra;
129}
130
nethercotef2b11482004-08-02 12:36:01 +0000131UInt VG_(get_n_errs_found)( void )
132{
133 return n_errs_found;
134}
135
nethercote4a184902004-08-02 12:21:09 +0000136/*------------------------------------------------------------*/
137/*--- Suppression type ---*/
138/*------------------------------------------------------------*/
139
140/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
141 * effectively extend it by defining their own enums in the (0..) range. */
142typedef
143 enum {
144 PThreadSupp = -1, /* Matches PThreadErr */
145 }
146 CoreSuppKind;
147
sewardjb5f6f512005-03-10 23:59:00 +0000148/* Max number of callers for context in a suppression. */
149#define VG_MAX_SUPP_CALLERS 24
150
nethercote4a184902004-08-02 12:21:09 +0000151/* For each caller specified for a suppression, record the nature of
152 the caller name. Not of interest to tools. */
153typedef
154 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000155 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000156 ObjName, /* Name is of an shared object file. */
157 FunName /* Name is of a function. */
158 }
159 SuppLocTy;
160
sewardjb5f6f512005-03-10 23:59:00 +0000161typedef
162 struct {
163 SuppLocTy ty;
164 Char* name;
165 }
166 SuppLoc;
167
nethercote4a184902004-08-02 12:21:09 +0000168/* Suppressions. Tools can get/set tool-relevant parts with functions
nethercote46063202004-09-02 08:51:43 +0000169 declared in include/tool.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000170 Tools can use a normal enum (with element values in the normal range
njn02bc4b82005-05-15 17:28:26 +0000171 (0..)) for 'skind'. */
nethercote4a184902004-08-02 12:21:09 +0000172struct _Supp {
173 struct _Supp* next;
174 Int count; // The number of times this error has been suppressed.
175 Char* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000176
177 // Length of 'callers'
178 Int n_callers;
179 // Array of callers, for matching stack traces. First one (name of fn
180 // where err occurs) is mandatory; rest are optional.
181 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000182
183 /* The tool-specific part */
184 SuppKind skind; // What kind of suppression. Must use the range (0..).
185 Char* string; // String -- use is optional. NULL by default.
186 void* extra; // Anything else -- use is optional. NULL by default.
187};
188
189SuppKind VG_(get_supp_kind) ( Supp* su )
190{
191 return su->skind;
192}
193
194Char* VG_(get_supp_string) ( Supp* su )
195{
196 return su->string;
197}
198
199void* VG_(get_supp_extra) ( Supp* su )
200{
201 return su->extra;
202}
203
204
205void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
206{
207 su->skind = skind;
208}
209
210void VG_(set_supp_string) ( Supp* su, Char* string )
211{
212 su->string = string;
213}
214
215void VG_(set_supp_extra) ( Supp* su, void* extra )
216{
217 su->extra = extra;
218}
219
220
221/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000222/*--- Helper fns ---*/
223/*------------------------------------------------------------*/
224
sewardjde4a1d02002-03-22 01:27:54 +0000225/* Compare error contexts, to detect duplicates. Note that if they
226 are otherwise the same, the faulting addrs and associated rwoffsets
227 are allowed to be different. */
njn810086f2002-11-14 12:42:47 +0000228static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000229{
njn810086f2002-11-14 12:42:47 +0000230 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000231 return False;
njn25e49d8e72002-09-23 09:36:25 +0000232 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000233 return False;
234
njn810086f2002-11-14 12:42:47 +0000235 switch (e1->ekind) {
sewardjb5f6f512005-03-10 23:59:00 +0000236 // case ThreadErr:
237 // case MutexErr:
238 // vg_assert(VG_(needs).core_errors);
239 // return VG_(tm_error_equal)(res, e1, e2);
sewardjde4a1d02002-03-22 01:27:54 +0000240 default:
njn51d827b2005-05-09 01:02:08 +0000241 if (VG_(needs).tool_errors) {
242 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
243 } else {
njn95ec8702004-11-22 16:46:13 +0000244 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000245 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000246 e1->ekind);
njn67993252004-11-22 18:02:32 +0000247 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000248 }
sewardjde4a1d02002-03-22 01:27:54 +0000249 }
250}
251
njn810086f2002-11-14 12:42:47 +0000252static void pp_Error ( Error* err, Bool printCount )
sewardjde4a1d02002-03-22 01:27:54 +0000253{
sewardj71bc3cb2005-05-19 00:25:45 +0000254 if (VG_(clo_xml)) {
255 VG_(message)(Vg_UserMsg, "<error>");
256 VG_(message)(Vg_UserMsg, " <tid>%d</tid>", err->tid);
257 }
258
259 if (!VG_(clo_xml)) {
260 if (printCount)
261 VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
262 if (err->tid > 0 && err->tid != last_tid_printed) {
263 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
264 last_tid_printed = err->tid;
265 }
sewardjb5f6f512005-03-10 23:59:00 +0000266 }
njn25e49d8e72002-09-23 09:36:25 +0000267
njn810086f2002-11-14 12:42:47 +0000268 switch (err->ekind) {
sewardjb5f6f512005-03-10 23:59:00 +0000269 // case ThreadErr:
270 // case MutexErr:
271 // vg_assert(VG_(needs).core_errors);
272 // VG_(tm_error_print)(err);
273 // break;
sewardjde4a1d02002-03-22 01:27:54 +0000274 default:
njn95ec8702004-11-22 16:46:13 +0000275 if (VG_(needs).tool_errors)
njn51d827b2005-05-09 01:02:08 +0000276 VG_TDICT_CALL( tool_pp_Error, err );
njn25e49d8e72002-09-23 09:36:25 +0000277 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 err->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 }
sewardj71bc3cb2005-05-19 00:25:45 +0000284
285 if (VG_(clo_xml))
286 VG_(message)(Vg_UserMsg, "</error>");
sewardjde4a1d02002-03-22 01:27:54 +0000287}
288
nethercote04d0fbc2004-01-26 16:48:06 +0000289/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000290 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000291Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000292{
293 Char ch, ch2;
294 Int res;
295
njn43c799e2003-04-08 00:08:52 +0000296 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000297 return False;
298
299 VG_(message)(Vg_UserMsg, "");
300
301 again:
302 VG_(printf)(
303 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000304 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
305 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000306 );
307
sewardj6024b212003-07-13 10:54:33 +0000308 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000309 if (res != 1) goto ioerror;
310 /* res == 1 */
311 if (ch == '\n') return False;
312 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
313 && ch != 'C' && ch != 'c') goto again;
314
sewardj6024b212003-07-13 10:54:33 +0000315 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000316 if (res != 1) goto ioerror;
317 if (ch2 != '\n') goto again;
318
njn43c799e2003-04-08 00:08:52 +0000319 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000320 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000321 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000322 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000323 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000324 vg_assert(ch == 'c' || ch == 'C');
325
326 ioerror:
njn43c799e2003-04-08 00:08:52 +0000327 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000328 return False;
329}
330
331
sewardjb5f6f512005-03-10 23:59:00 +0000332/* Construct an error */
njn25e49d8e72002-09-23 09:36:25 +0000333static __inline__
njn72718642003-07-24 08:45:32 +0000334void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
335 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000336{
njnca82cc02004-11-22 17:18:48 +0000337 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000338
njn810086f2002-11-14 12:42:47 +0000339 /* Core-only parts */
njn25e49d8e72002-09-23 09:36:25 +0000340 err->next = NULL;
341 err->supp = NULL;
342 err->count = 1;
njn72718642003-07-24 08:45:32 +0000343 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000344 if (NULL == where)
njnd01fef72005-03-25 23:35:48 +0000345 err->where = VG_(record_ExeContext)( tid );
njn43c799e2003-04-08 00:08:52 +0000346 else
347 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000348
nethercote996901a2004-08-03 13:29:09 +0000349 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000350 err->ekind = ekind;
351 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000352 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000353 err->string = s;
354
njn25e49d8e72002-09-23 09:36:25 +0000355 /* sanity... */
njn72718642003-07-24 08:45:32 +0000356 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000357}
358
njnf4261312005-03-20 23:45:36 +0000359static void printSuppForIp(UInt n, Addr ip)
360{
njn47b209a2005-03-25 23:47:16 +0000361 static UChar buf[VG_ERRTXT_LEN];
njnf4261312005-03-20 23:45:36 +0000362
njn47b209a2005-03-25 23:47:16 +0000363 if ( VG_(get_fnname_nodemangle) (ip, buf, VG_ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000364 VG_(printf)(" fun:%s\n", buf);
njnbc93cc02005-05-15 21:09:40 +0000365 } else if ( VG_(get_objname)(ip, buf, VG_ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000366 VG_(printf)(" obj:%s\n", buf);
367 } else {
368 VG_(printf)(" ???:??? "
369 "# unknown, suppression will not work, sorry\n");
370 }
371}
372
nethercote10d481a2004-01-25 20:33:53 +0000373static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000374{
njn43c799e2003-04-08 00:08:52 +0000375 ExeContext* ec = VG_(get_error_where)(err);
376 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000377
sewardjb5f6f512005-03-10 23:59:00 +0000378 /* At most VG_MAX_SUPP_CALLERS names */
379 if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
njn43c799e2003-04-08 00:08:52 +0000380 vg_assert(stop_at > 0);
381
382 VG_(printf)("{\n");
383 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000384
sewardjb5f6f512005-03-10 23:59:00 +0000385 if (ThreadErr == err->ekind || MutexErr == err->ekind) {
njn6a230532003-07-21 10:38:23 +0000386 VG_(printf)(" core:PThread\n");
387
388 } else {
njn51d827b2005-05-09 01:02:08 +0000389 Char* name = VG_TDICT_CALL(tool_get_error_name, err);
njn6a230532003-07-21 10:38:23 +0000390 if (NULL == name) {
391 VG_(message)(Vg_UserMsg,
nethercote137bc552003-11-14 17:47:54 +0000392 "(tool does not allow error to be suppressed)");
njn6a230532003-07-21 10:38:23 +0000393 return;
394 }
395 VG_(printf)(" %s:%s\n", VG_(details).name, name);
njn51d827b2005-05-09 01:02:08 +0000396 VG_TDICT_CALL(tool_print_extra_suppression_info, err);
njn6a230532003-07-21 10:38:23 +0000397 }
njn43c799e2003-04-08 00:08:52 +0000398
njnf4261312005-03-20 23:45:36 +0000399 // Print stack trace elements
njnd01fef72005-03-25 23:35:48 +0000400 VG_(apply_StackTrace)(printSuppForIp, VG_(extract_StackTrace)(ec), stop_at);
njn43c799e2003-04-08 00:08:52 +0000401
402 VG_(printf)("}\n");
403}
404
njnb4aee052003-04-15 14:09:58 +0000405static
nethercote04d0fbc2004-01-26 16:48:06 +0000406void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000407{
sewardjd153fae2005-01-10 17:24:47 +0000408 Bool still_noisy = True;
409
nethercote04d0fbc2004-01-26 16:48:06 +0000410 /* Perhaps we want a debugger attach at this point? */
411 if (allow_db_attach &&
njnd2b17112005-04-19 04:10:25 +0000412 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
413 {
nethercote04d0fbc2004-01-26 16:48:06 +0000414 VG_(printf)("starting debugger\n");
415 VG_(start_debugger)( err->tid );
njnd2b17112005-04-19 04:10:25 +0000416 }
njn43c799e2003-04-08 00:08:52 +0000417 /* Or maybe we want to generate the error's suppression? */
sewardjd153fae2005-01-10 17:24:47 +0000418 if (VG_(clo_gen_suppressions) == 2
419 || (VG_(clo_gen_suppressions) == 1
njnd2b17112005-04-19 04:10:25 +0000420 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
sewardjd153fae2005-01-10 17:24:47 +0000421 ) {
nethercote42602b12004-01-25 19:30:29 +0000422 gen_suppression(err);
sewardjd153fae2005-01-10 17:24:47 +0000423 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
424 VG_(clo_gen_suppressions) = 0;
njn43c799e2003-04-08 00:08:52 +0000425 }
426}
427
428/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
429 just for pretty printing purposes. */
430static Bool is_first_shown_context = True;
431
njn25e49d8e72002-09-23 09:36:25 +0000432/* Top-level entry point to the error management subsystem.
433 All detected errors are notified here; this routine decides if/when the
434 user should see the error. */
njn72718642003-07-24 08:45:32 +0000435void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000436 ErrorKind ekind, Addr a, Char* s, void* extra )
437{
njn810086f2002-11-14 12:42:47 +0000438 Error err;
439 Error* p;
440 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000441 UInt extra_size;
njn695c16e2005-03-27 03:40:28 +0000442 VgRes exe_res = Vg_MedRes;
443 static Bool stopping_message = False;
444 static Bool slowdown_message = False;
445 static Int n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000446
njn14319cc2005-03-13 06:26:22 +0000447 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
448 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000449 have been found, just refuse to collect any more. This stops
450 the burden of the error-management system becoming excessive in
451 extremely buggy programs, although it does make it pretty
452 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000453 if (VG_(clo_error_limit)
njn695c16e2005-03-27 03:40:28 +0000454 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
njn14319cc2005-03-13 06:26:22 +0000455 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000456 if (!stopping_message) {
457 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000458
njn695c16e2005-03-27 03:40:28 +0000459 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardjf2537be2002-04-24 21:03:47 +0000460 VG_(message)(Vg_UserMsg,
461 "More than %d different errors detected. "
462 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000463 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000464 } else {
465 VG_(message)(Vg_UserMsg,
466 "More than %d total errors detected. "
467 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000468 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000469 }
470
sewardjde4a1d02002-03-22 01:27:54 +0000471 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000472 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000473 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000474 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000475 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000476 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000477 VG_(message)(Vg_UserMsg,
478 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000479 VG_(message)(Vg_UserMsg, "");
480 stopping_message = True;
481 }
482 return;
483 }
484
njn14319cc2005-03-13 06:26:22 +0000485 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000486 been found, be much more conservative about collecting new
487 ones. */
njn695c16e2005-03-27 03:40:28 +0000488 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000489 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000490 if (!slowdown_message) {
491 VG_(message)(Vg_UserMsg, "");
492 VG_(message)(Vg_UserMsg,
493 "More than %d errors detected. Subsequent errors",
njn14319cc2005-03-13 06:26:22 +0000494 M_COLLECT_ERRORS_SLOWLY_AFTER);
sewardjde4a1d02002-03-22 01:27:54 +0000495 VG_(message)(Vg_UserMsg,
496 "will still be recorded, but in less detail than before.");
497 slowdown_message = True;
498 }
499 }
500
njn25e49d8e72002-09-23 09:36:25 +0000501 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000502 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000503
504 /* First, see if we've got an error record matching this one. */
njn695c16e2005-03-27 03:40:28 +0000505 p = errors;
sewardjde4a1d02002-03-22 01:27:54 +0000506 p_prev = NULL;
507 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000508 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000509 /* Found it. */
510 p->count++;
511 if (p->supp != NULL) {
512 /* Deal correctly with suppressed errors. */
513 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000514 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000515 } else {
nethercotef2b11482004-08-02 12:36:01 +0000516 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000517 }
518
519 /* Move p to the front of the list so that future searches
520 for it are faster. */
521 if (p_prev != NULL) {
522 vg_assert(p_prev->next == p);
njn695c16e2005-03-27 03:40:28 +0000523 p_prev->next = p->next;
524 p->next = errors;
525 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000526 }
sewardj7ebf7c32003-07-24 21:29:40 +0000527
sewardjde4a1d02002-03-22 01:27:54 +0000528 return;
529 }
530 p_prev = p;
531 p = p->next;
532 }
533
534 /* Didn't see it. Copy and add. */
535
njn43c799e2003-04-08 00:08:52 +0000536 /* OK, we're really going to collect it. The context is on the stack and
537 will disappear shortly, so we must copy it. First do the main
njn02bc4b82005-05-15 17:28:26 +0000538 (non-'extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000539
njn02bc4b82005-05-15 17:28:26 +0000540 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
njn51d827b2005-05-09 01:02:08 +0000541 is for when there are more details to fill in which take time to work
542 out but don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000543 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000544 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000545
njn02bc4b82005-05-15 17:28:26 +0000546 Then, if there is an 'extra' part, copy it too, using the size that
njn51d827b2005-05-09 01:02:08 +0000547 VG_(tdict).tool_update_extra returned. Also allow for people using
548 the void* extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000549 */
550
551 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000552 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000553 *p = err;
njn43c799e2003-04-08 00:08:52 +0000554
njn02bc4b82005-05-15 17:28:26 +0000555 /* update 'extra' */
sewardjb5f6f512005-03-10 23:59:00 +0000556 switch (ekind) {
557 // case ThreadErr:
558 // case MutexErr:
559 // vg_assert(VG_(needs).core_errors);
560 // extra_size = VG_(tm_error_update_extra)(p);
561 // break;
562 default:
563 vg_assert(VG_(needs).tool_errors);
njn51d827b2005-05-09 01:02:08 +0000564 extra_size = VG_TDICT_CALL(tool_update_extra, p);
sewardjb5f6f512005-03-10 23:59:00 +0000565 break;
566 }
njn43c799e2003-04-08 00:08:52 +0000567
njn02bc4b82005-05-15 17:28:26 +0000568 /* copy block pointed to by 'extra', if there is one */
sewardjb5f6f512005-03-10 23:59:00 +0000569 if (NULL != p->extra && 0 != extra_size) {
570 void* new_extra = VG_(malloc)(extra_size);
571 VG_(memcpy)(new_extra, p->extra, extra_size);
572 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000573 }
574
njn695c16e2005-03-27 03:40:28 +0000575 p->next = errors;
njn25e49d8e72002-09-23 09:36:25 +0000576 p->supp = is_suppressible_error(&err);
njn695c16e2005-03-27 03:40:28 +0000577 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000578 if (p->supp == NULL) {
nethercotef2b11482004-08-02 12:36:01 +0000579 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000580 if (!is_first_shown_context)
581 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000582 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000583 is_first_shown_context = False;
njn695c16e2005-03-27 03:40:28 +0000584 n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000585 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000586 } else {
nethercotef2b11482004-08-02 12:36:01 +0000587 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000588 p->supp->count++;
589 }
590}
591
njn43c799e2003-04-08 00:08:52 +0000592/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000593 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000594 guaranteed to only happen once. This avoids all the recording and
595 comparing stuff. But they can be suppressed; returns True if it is
njn02bc4b82005-05-15 17:28:26 +0000596 suppressed. Bool 'print_error' dictates whether to print the error.
597 Bool 'count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000598*/
njn72718642003-07-24 08:45:32 +0000599Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000600 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000601 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000602{
603 Error err;
604
605 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000606 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000607
608 /* Unless it's suppressed, we're going to show it. Don't need to make
609 a copy, because it's only temporary anyway.
610
njn02bc4b82005-05-15 17:28:26 +0000611 Then update the 'extra' part with VG_(tdict).tool_update_extra),
njn51d827b2005-05-09 01:02:08 +0000612 because that can have an affect on whether it's suppressed. Ignore
613 the size return value of VG_(tdict).tool_update_extra, because we're
njn02bc4b82005-05-15 17:28:26 +0000614 not copying 'extra'. */
njn51d827b2005-05-09 01:02:08 +0000615 (void)VG_TDICT_CALL(tool_update_extra, &err);
njn43c799e2003-04-08 00:08:52 +0000616
617 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000618 if (count_error)
nethercotef2b11482004-08-02 12:36:01 +0000619 n_errs_found++;
njn43c799e2003-04-08 00:08:52 +0000620
621 if (print_error) {
622 if (!is_first_shown_context)
623 VG_(message)(Vg_UserMsg, "");
624 pp_Error(&err, False);
625 is_first_shown_context = False;
626 }
nethercote04d0fbc2004-01-26 16:48:06 +0000627 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000628
629 return False;
630
631 } else {
nethercotef2b11482004-08-02 12:36:01 +0000632 n_errs_suppressed++;
njn43c799e2003-04-08 00:08:52 +0000633 return True;
634 }
635}
636
sewardjde4a1d02002-03-22 01:27:54 +0000637
sewardjde4a1d02002-03-22 01:27:54 +0000638/*------------------------------------------------------------*/
639/*--- Exported fns ---*/
640/*------------------------------------------------------------*/
641
sewardj71bc3cb2005-05-19 00:25:45 +0000642/* Show the used suppressions. Returns False if no suppression
643 got used. */
644static Bool show_used_suppressions ( void )
645{
646 Supp *su;
647 Bool any_supp;
648
649 any_supp = False;
650 for (su = suppressions; su != NULL; su = su->next) {
651 if (su->count <= 0)
652 continue;
653 any_supp = True;
654 if (VG_(clo_xml)) {
655 VG_(message)(Vg_DebugMsg,
656 "<supp><count>%d</count><name>%s</name></supp>",
657 su->count, su->sname);
658 } else {
659 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
660 }
661 }
662
663 return any_supp;
664}
665
666
njnb9ecfe32005-03-13 05:27:57 +0000667/* This is called not from generated code but from the scheduler */
sewardjde4a1d02002-03-22 01:27:54 +0000668void VG_(show_all_errors) ( void )
669{
njn810086f2002-11-14 12:42:47 +0000670 Int i, n_min;
671 Int n_err_contexts, n_supp_contexts;
672 Error *p, *p_min;
673 Supp *su;
674 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000675
676 if (VG_(clo_verbosity) == 0)
677 return;
678
679 n_err_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000680 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000681 if (p->supp == NULL)
682 n_err_contexts++;
683 }
684
685 n_supp_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000686 for (su = suppressions; su != NULL; su = su->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000687 if (su->count > 0)
688 n_supp_contexts++;
689 }
sewardj71bc3cb2005-05-19 00:25:45 +0000690
691 /* If we're printing XML, just show the suppressions and stop.
692 */
693 if (VG_(clo_xml)) {
694 (void)show_used_suppressions();
695 return;
696 }
697
698 /* We only get here if not printing XML. */
sewardjde4a1d02002-03-22 01:27:54 +0000699 VG_(message)(Vg_UserMsg,
700 "ERROR SUMMARY: "
701 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000702 n_errs_found, n_err_contexts,
703 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000704
705 if (VG_(clo_verbosity) <= 1)
706 return;
707
708 /* Print the contexts in order of increasing error count. */
709 for (i = 0; i < n_err_contexts; i++) {
710 n_min = (1 << 30) - 1;
711 p_min = NULL;
njn695c16e2005-03-27 03:40:28 +0000712 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000713 if (p->supp != NULL) continue;
714 if (p->count < n_min) {
715 n_min = p->count;
716 p_min = p;
717 }
718 }
njn67993252004-11-22 18:02:32 +0000719 if (p_min == NULL) VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000720
721 VG_(message)(Vg_UserMsg, "");
722 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
723 p_min->count,
724 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000725 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000726
727 if ((i+1 == VG_(clo_dump_error))) {
njnd01fef72005-03-25 23:35:48 +0000728 StackTrace ips = VG_(extract_StackTrace)(p_min->where);
sewardjfa8ec112005-01-19 11:55:34 +0000729 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
njnd01fef72005-03-25 23:35:48 +0000730 ips[0], /*debugging*/True, 0xFE/*verbosity*/);
sewardjde4a1d02002-03-22 01:27:54 +0000731 }
732
733 p_min->count = 1 << 30;
734 }
735
736 if (n_supp_contexts > 0)
737 VG_(message)(Vg_DebugMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +0000738 any_supp = show_used_suppressions();
sewardjde4a1d02002-03-22 01:27:54 +0000739
740 if (n_err_contexts > 0) {
741 if (any_supp)
742 VG_(message)(Vg_UserMsg, "");
743 VG_(message)(Vg_UserMsg,
744 "IN SUMMARY: "
745 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000746 n_errs_found, n_err_contexts, n_errs_suppressed,
sewardjde4a1d02002-03-22 01:27:54 +0000747 n_supp_contexts );
748 VG_(message)(Vg_UserMsg, "");
749 }
750}
751
752/*------------------------------------------------------------*/
753/*--- Standard suppressions ---*/
754/*------------------------------------------------------------*/
755
756/* Get a non-blank, non-comment line of at most nBuf chars from fd.
757 Skips leading spaces on the line. Return True if EOF was hit instead.
758*/
njn4ba5a792002-09-30 10:23:54 +0000759Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000760{
761 Char ch;
762 Int n, i;
763 while (True) {
764 /* First, read until a non-blank char appears. */
765 while (True) {
766 n = VG_(read)(fd, &ch, 1);
njn0c0f32a2005-03-26 04:14:01 +0000767 if (n == 1 && !VG_(isspace)(ch)) break;
sewardjde4a1d02002-03-22 01:27:54 +0000768 if (n == 0) return True;
769 }
770
771 /* Now, read the line into buf. */
772 i = 0;
773 buf[i++] = ch; buf[i] = 0;
774 while (True) {
775 n = VG_(read)(fd, &ch, 1);
776 if (n == 0) return False; /* the next call will return True */
777 if (ch == '\n') break;
778 if (i > 0 && i == nBuf-1) i--;
779 buf[i++] = ch; buf[i] = 0;
780 }
njn0c0f32a2005-03-26 04:14:01 +0000781 while (i > 1 && VG_(isspace)(buf[i-1])) {
sewardjde4a1d02002-03-22 01:27:54 +0000782 i--; buf[i] = 0;
783 };
784
njn02bc4b82005-05-15 17:28:26 +0000785 /* VG_(printf)("The line is '%s'\n", buf); */
sewardjde4a1d02002-03-22 01:27:54 +0000786 /* Ok, we have a line. If a non-comment line, return.
787 If a comment line, start all over again. */
788 if (buf[0] != '#') return False;
789 }
790}
791
792
793/* *p_caller contains the raw name of a caller, supposedly either
794 fun:some_function_name or
795 obj:some_object_name.
796 Set *p_ty accordingly and advance *p_caller over the descriptor
797 (fun: or obj:) part.
798 Returns False if failed.
799*/
sewardjb5f6f512005-03-10 23:59:00 +0000800static Bool setLocationTy ( SuppLoc* p )
sewardjde4a1d02002-03-22 01:27:54 +0000801{
sewardjb5f6f512005-03-10 23:59:00 +0000802 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
803 p->name += 4;
804 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +0000805 return True;
806 }
sewardjb5f6f512005-03-10 23:59:00 +0000807 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
808 p->name += 4;
809 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +0000810 return True;
811 }
812 VG_(printf)("location should start with fun: or obj:\n");
813 return False;
814}
815
816
nethercote7cc9c232004-01-21 15:08:04 +0000817/* Look for "tool" in a string like "tool1,tool2,tool3" */
njn11cc9252002-10-07 14:42:59 +0000818static __inline__
nethercote7cc9c232004-01-21 15:08:04 +0000819Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000820{
821 Bool found;
822 Char *s = NULL; /* Shut gcc up */
823 Int len = VG_(strlen)(name);
824
825 found = (NULL != (s = VG_(strstr)(names, name)) &&
826 (s == names || *(s-1) == ',') &&
827 (*(s+len) == ',' || *(s+len) == '\0')
828 );
829
830 return found;
831}
832
njn695c16e2005-03-27 03:40:28 +0000833/* Read suppressions from the file specified in VG_(clo_suppressions)
sewardjde4a1d02002-03-22 01:27:54 +0000834 and place them in the suppressions list. If there's any difficulty
835 doing this, just give up -- there's no point in trying to recover.
836*/
sewardjde4a1d02002-03-22 01:27:54 +0000837static void load_one_suppressions_file ( Char* filename )
838{
839# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000840 Int fd, i;
sewardjb5f6f512005-03-10 23:59:00 +0000841 Bool eof;
njnc40c3a82002-10-02 11:02:27 +0000842 Char buf[N_BUF+1];
nethercote7cc9c232004-01-21 15:08:04 +0000843 Char* tool_names;
njnc40c3a82002-10-02 11:02:27 +0000844 Char* supp_name;
sewardjb5f6f512005-03-10 23:59:00 +0000845 Char* err_str = NULL;
846 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +0000847
njn25e49d8e72002-09-23 09:36:25 +0000848 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000849 if (fd < 0) {
njn02bc4b82005-05-15 17:28:26 +0000850 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file '%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000851 filename );
852 VG_(exit)(1);
853 }
854
sewardjb5f6f512005-03-10 23:59:00 +0000855#define BOMB(S) { err_str = S; goto syntax_error; }
856
sewardjde4a1d02002-03-22 01:27:54 +0000857 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000858 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000859 Supp* supp;
860 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000861 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000862
863 // Initialise temporary reading-in buffer.
864 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
865 tmp_callers[i].ty = NoName;
866 tmp_callers[i].name = NULL;
867 }
868
njn810086f2002-11-14 12:42:47 +0000869 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000870
njn4ba5a792002-09-30 10:23:54 +0000871 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000872 if (eof) break;
873
sewardjb5f6f512005-03-10 23:59:00 +0000874 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000875
njn4ba5a792002-09-30 10:23:54 +0000876 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000877
878 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
879
njn25e49d8e72002-09-23 09:36:25 +0000880 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000881
njn4ba5a792002-09-30 10:23:54 +0000882 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000883
sewardjb5f6f512005-03-10 23:59:00 +0000884 if (eof) BOMB("unexpected end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000885
njn94065fd2004-11-22 19:26:27 +0000886 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000887 i = 0;
888 while (True) {
889 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +0000890 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +0000891 i++;
njn25e49d8e72002-09-23 09:36:25 +0000892 }
njnc40c3a82002-10-02 11:02:27 +0000893 buf[i] = '\0'; /* Replace ':', splitting into two strings */
894
nethercote7cc9c232004-01-21 15:08:04 +0000895 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +0000896 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000897
nethercote7cc9c232004-01-21 15:08:04 +0000898 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +0000899 {
sewardjb5f6f512005-03-10 23:59:00 +0000900 // A core suppression
njn43c799e2003-04-08 00:08:52 +0000901 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000902 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000903 else
sewardjb5f6f512005-03-10 23:59:00 +0000904 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +0000905 }
njn95ec8702004-11-22 16:46:13 +0000906 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +0000907 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +0000908 {
sewardjb5f6f512005-03-10 23:59:00 +0000909 // A tool suppression
njn51d827b2005-05-09 01:02:08 +0000910 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +0000911 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +0000912 } else {
913 BOMB("unknown tool suppression type");
914 }
njnc40c3a82002-10-02 11:02:27 +0000915 }
njn25e49d8e72002-09-23 09:36:25 +0000916 else {
sewardjb5f6f512005-03-10 23:59:00 +0000917 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +0000918 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000919 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000920 if (eof) BOMB("unexpected end-of-file");
njn43c799e2003-04-08 00:08:52 +0000921 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000922 break;
923 }
924 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000925 }
926
njn95ec8702004-11-22 16:46:13 +0000927 if (VG_(needs).tool_errors &&
njn51d827b2005-05-09 01:02:08 +0000928 !VG_TDICT_CALL(tool_read_extra_suppression_info, fd, buf, N_BUF, supp))
sewardjb5f6f512005-03-10 23:59:00 +0000929 {
930 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +0000931 }
932
sewardjb5f6f512005-03-10 23:59:00 +0000933 i = 0;
934 while (True) {
935 eof = VG_(get_line) ( fd, buf, N_BUF );
936 if (eof)
937 BOMB("unexpected end-of-file");
938 if (VG_STREQ(buf, "}")) {
939 if (i > 0) {
940 break;
941 } else {
942 BOMB("missing stack trace");
943 }
944 }
945 if (i == VG_MAX_SUPP_CALLERS)
946 BOMB("too many callers in stack trace");
947 if (i > 0 && i >= VG_(clo_backtrace_size))
948 break;
949 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE, buf);
950 if (!setLocationTy(&(tmp_callers[i])))
951 BOMB("location should start with 'fun:' or 'obj:'");
952 i++;
953 }
954
955 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
956 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +0000957 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +0000958 do {
959 eof = VG_(get_line) ( fd, buf, N_BUF );
960 } while (!eof && !VG_STREQ(buf, "}"));
961 }
962
963 // Copy tmp_callers[] into supp->callers[]
964 supp->n_callers = i;
965 supp->callers = VG_(arena_malloc)(VG_AR_CORE, i*sizeof(SuppLoc));
966 for (i = 0; i < supp->n_callers; i++) {
967 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +0000968 }
969
njn695c16e2005-03-27 03:40:28 +0000970 supp->next = suppressions;
971 suppressions = supp;
sewardjde4a1d02002-03-22 01:27:54 +0000972 }
sewardjde4a1d02002-03-22 01:27:54 +0000973 VG_(close)(fd);
974 return;
975
976 syntax_error:
sewardjb5f6f512005-03-10 23:59:00 +0000977 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000978 "FATAL: in suppressions file '%s': %s", filename, err_str );
sewardjb5f6f512005-03-10 23:59:00 +0000979
sewardjde4a1d02002-03-22 01:27:54 +0000980 VG_(close)(fd);
981 VG_(message)(Vg_UserMsg, "exiting now.");
nethercote8ed8a892004-11-08 13:24:25 +0000982 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +0000983
sewardjb5f6f512005-03-10 23:59:00 +0000984# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +0000985# undef N_BUF
986}
987
988
989void VG_(load_suppressions) ( void )
990{
991 Int i;
njn695c16e2005-03-27 03:40:28 +0000992 suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000993 for (i = 0; i < VG_(clo_n_suppressions); i++) {
994 if (VG_(clo_verbosity) > 1) {
njn3f04d242005-03-20 18:21:14 +0000995 VG_(message)(Vg_DebugMsg, "Reading suppressions file: %s",
996 VG_(clo_suppressions)[i] );
sewardjde4a1d02002-03-22 01:27:54 +0000997 }
998 load_one_suppressions_file( VG_(clo_suppressions)[i] );
999 }
1000}
1001
sewardjb5f6f512005-03-10 23:59:00 +00001002static
njn810086f2002-11-14 12:42:47 +00001003Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +00001004{
njn810086f2002-11-14 12:42:47 +00001005 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +00001006 case PThreadSupp:
sewardjb5f6f512005-03-10 23:59:00 +00001007 return (err->ekind == ThreadErr || err->ekind == MutexErr);
njn25e49d8e72002-09-23 09:36:25 +00001008 default:
njn95ec8702004-11-22 16:46:13 +00001009 if (VG_(needs).tool_errors) {
njn51d827b2005-05-09 01:02:08 +00001010 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
njn25e49d8e72002-09-23 09:36:25 +00001011 } else {
1012 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +00001013 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +00001014 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +00001015 err->ekind);
njn67993252004-11-22 18:02:32 +00001016 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +00001017 }
1018 }
1019}
1020
sewardjb5f6f512005-03-10 23:59:00 +00001021static
1022Bool supp_matches_callers(Error* err, Supp* su)
njn25e49d8e72002-09-23 09:36:25 +00001023{
1024 Int i;
njn47b209a2005-03-25 23:47:16 +00001025 Char caller_name[VG_ERRTXT_LEN];
njnd01fef72005-03-25 23:35:48 +00001026 StackTrace ips = VG_(extract_StackTrace)(err->where);
njn25e49d8e72002-09-23 09:36:25 +00001027
sewardjb5f6f512005-03-10 23:59:00 +00001028 for (i = 0; i < su->n_callers; i++) {
njnd01fef72005-03-25 23:35:48 +00001029 Addr a = ips[i];
sewardjb5f6f512005-03-10 23:59:00 +00001030 vg_assert(su->callers[i].name != NULL);
1031 switch (su->callers[i].ty) {
1032 case ObjName:
njn47b209a2005-03-25 23:47:16 +00001033 if (!VG_(get_objname)(a, caller_name, VG_ERRTXT_LEN))
njn58c9f812005-03-11 04:46:09 +00001034 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001035 break;
1036
1037 case FunName:
1038 // Nb: mangled names used in suppressions
njn47b209a2005-03-25 23:47:16 +00001039 if (!VG_(get_fnname_nodemangle)(a, caller_name, VG_ERRTXT_LEN))
njn58c9f812005-03-11 04:46:09 +00001040 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001041 break;
njn67993252004-11-22 18:02:32 +00001042 default: VG_(tool_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +00001043 }
sewardjb5f6f512005-03-10 23:59:00 +00001044 if (!VG_(string_match)(su->callers[i].name, caller_name))
1045 return False;
njn25e49d8e72002-09-23 09:36:25 +00001046 }
1047
1048 /* If we reach here, it's a match */
1049 return True;
1050}
sewardjde4a1d02002-03-22 01:27:54 +00001051
njn810086f2002-11-14 12:42:47 +00001052/* Does an error context match a suppression? ie is this a suppressible
1053 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001054 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001055*/
njn810086f2002-11-14 12:42:47 +00001056static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001057{
njn810086f2002-11-14 12:42:47 +00001058 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +00001059
sewardjde4a1d02002-03-22 01:27:54 +00001060 /* See if the error context matches any suppression. */
njn695c16e2005-03-27 03:40:28 +00001061 for (su = suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +00001062 if (supp_matches_error(su, err) &&
sewardjb5f6f512005-03-10 23:59:00 +00001063 supp_matches_callers(err, su))
1064 {
njn25e49d8e72002-09-23 09:36:25 +00001065 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001066 }
sewardjde4a1d02002-03-22 01:27:54 +00001067 }
njn25e49d8e72002-09-23 09:36:25 +00001068 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001069}
1070
sewardjde4a1d02002-03-22 01:27:54 +00001071/*--------------------------------------------------------------------*/
sewardj267100d2005-04-24 12:33:12 +00001072/*--- end m_errormgr.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001073/*--------------------------------------------------------------------*/