blob: fa61362d0e0cbb824e7d0e339b08c1331ed6630b [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njnd2b17112005-04-19 04:10:25 +00003/*--- Management of error messages. 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"
njnd2b17112005-04-19 04:10:25 +000034#include "pub_core_stacktrace.h"
sewardjde4a1d02002-03-22 01:27:54 +000035
36/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000037/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000038/*------------------------------------------------------------*/
39
njn14319cc2005-03-13 06:26:22 +000040/* After this many different unsuppressed errors have been observed,
41 be more conservative about collecting new ones. */
42#define M_COLLECT_ERRORS_SLOWLY_AFTER 50
43
44/* After this many different unsuppressed errors have been observed,
45 stop collecting errors at all, and tell the user their program is
46 evidently a steaming pile of camel dung. */
47#define M_COLLECT_NO_ERRORS_AFTER_SHOWN 300
48
49/* After this many total errors have been observed, stop collecting
50 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
51#define M_COLLECT_NO_ERRORS_AFTER_FOUND 30000
52
sewardjde4a1d02002-03-22 01:27:54 +000053/* The list of error contexts found, both suppressed and unsuppressed.
54 Initially empty, and grows as errors are detected. */
njn695c16e2005-03-27 03:40:28 +000055static Error* errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000056
57/* The list of suppression directives, as read from the specified
58 suppressions file. */
njn695c16e2005-03-27 03:40:28 +000059static Supp* suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000060
61/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000062static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000063
64/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000065static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000066
67/* forwards ... */
njn810086f2002-11-14 12:42:47 +000068static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000069
sewardjb5f6f512005-03-10 23:59:00 +000070static ThreadId last_tid_printed = 1;
sewardjde4a1d02002-03-22 01:27:54 +000071
72/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +000073/*--- Error type ---*/
74/*------------------------------------------------------------*/
75
nethercote996901a2004-08-03 13:29:09 +000076/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
nethercote4a184902004-08-02 12:21:09 +000077 * effectively extend it by defining their own enums in the (0..) range. */
nethercote4a184902004-08-02 12:21:09 +000078
79/* Errors. Extensible (via the 'extra' field). Tools can use a normal
80 enum (with element values in the normal range (0..)) for `ekind'.
81 Functions for getting/setting the tool-relevant fields are in
nethercote46063202004-09-02 08:51:43 +000082 include/tool.h.
nethercote4a184902004-08-02 12:21:09 +000083
84 When errors are found and recorded with VG_(maybe_record_error)(), all
85 the tool must do is pass in the four parameters; core will
86 allocate/initialise the error record.
87*/
88struct _Error {
89 struct _Error* next;
90 // NULL if unsuppressed; or ptr to suppression record.
91 Supp* supp;
92 Int count;
93 ThreadId tid;
94
95 // The tool-specific part
96 ExeContext* where; // Initialised by core
njnd2b17112005-04-19 04:10:25 +000097 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
nethercote4a184902004-08-02 12:21:09 +000098 Addr addr; // Used frequently
99 Char* string; // Used frequently
100 void* extra; // For any tool-specific extras
101};
102
103ExeContext* VG_(get_error_where) ( Error* err )
104{
105 return err->where;
106}
107
108ErrorKind VG_(get_error_kind) ( Error* err )
109{
110 return err->ekind;
111}
112
113Addr VG_(get_error_address) ( Error* err )
114{
115 return err->addr;
116}
117
118Char* VG_(get_error_string) ( Error* err )
119{
120 return err->string;
121}
122
123void* VG_(get_error_extra) ( Error* err )
124{
125 return err->extra;
126}
127
nethercotef2b11482004-08-02 12:36:01 +0000128UInt VG_(get_n_errs_found)( void )
129{
130 return n_errs_found;
131}
132
nethercote4a184902004-08-02 12:21:09 +0000133/*------------------------------------------------------------*/
134/*--- Suppression type ---*/
135/*------------------------------------------------------------*/
136
137/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
138 * effectively extend it by defining their own enums in the (0..) range. */
139typedef
140 enum {
141 PThreadSupp = -1, /* Matches PThreadErr */
142 }
143 CoreSuppKind;
144
sewardjb5f6f512005-03-10 23:59:00 +0000145/* Max number of callers for context in a suppression. */
146#define VG_MAX_SUPP_CALLERS 24
147
nethercote4a184902004-08-02 12:21:09 +0000148/* For each caller specified for a suppression, record the nature of
149 the caller name. Not of interest to tools. */
150typedef
151 enum {
sewardjb5f6f512005-03-10 23:59:00 +0000152 NoName, /* Error case */
nethercote4a184902004-08-02 12:21:09 +0000153 ObjName, /* Name is of an shared object file. */
154 FunName /* Name is of a function. */
155 }
156 SuppLocTy;
157
sewardjb5f6f512005-03-10 23:59:00 +0000158typedef
159 struct {
160 SuppLocTy ty;
161 Char* name;
162 }
163 SuppLoc;
164
nethercote4a184902004-08-02 12:21:09 +0000165/* Suppressions. Tools can get/set tool-relevant parts with functions
nethercote46063202004-09-02 08:51:43 +0000166 declared in include/tool.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000167 Tools can use a normal enum (with element values in the normal range
168 (0..)) for `skind'. */
169struct _Supp {
170 struct _Supp* next;
171 Int count; // The number of times this error has been suppressed.
172 Char* sname; // The name by which the suppression is referred to.
sewardjb5f6f512005-03-10 23:59:00 +0000173
174 // Length of 'callers'
175 Int n_callers;
176 // Array of callers, for matching stack traces. First one (name of fn
177 // where err occurs) is mandatory; rest are optional.
178 SuppLoc* callers;
nethercote4a184902004-08-02 12:21:09 +0000179
180 /* The tool-specific part */
181 SuppKind skind; // What kind of suppression. Must use the range (0..).
182 Char* string; // String -- use is optional. NULL by default.
183 void* extra; // Anything else -- use is optional. NULL by default.
184};
185
186SuppKind VG_(get_supp_kind) ( Supp* su )
187{
188 return su->skind;
189}
190
191Char* VG_(get_supp_string) ( Supp* su )
192{
193 return su->string;
194}
195
196void* VG_(get_supp_extra) ( Supp* su )
197{
198 return su->extra;
199}
200
201
202void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
203{
204 su->skind = skind;
205}
206
207void VG_(set_supp_string) ( Supp* su, Char* string )
208{
209 su->string = string;
210}
211
212void VG_(set_supp_extra) ( Supp* su, void* extra )
213{
214 su->extra = extra;
215}
216
217
218/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000219/*--- Helper fns ---*/
220/*------------------------------------------------------------*/
221
sewardjde4a1d02002-03-22 01:27:54 +0000222/* Compare error contexts, to detect duplicates. Note that if they
223 are otherwise the same, the faulting addrs and associated rwoffsets
224 are allowed to be different. */
njn810086f2002-11-14 12:42:47 +0000225static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000226{
njn810086f2002-11-14 12:42:47 +0000227 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000228 return False;
njn25e49d8e72002-09-23 09:36:25 +0000229 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000230 return False;
231
njn810086f2002-11-14 12:42:47 +0000232 switch (e1->ekind) {
sewardjb5f6f512005-03-10 23:59:00 +0000233 // case ThreadErr:
234 // case MutexErr:
235 // vg_assert(VG_(needs).core_errors);
236 // return VG_(tm_error_equal)(res, e1, e2);
sewardjde4a1d02002-03-22 01:27:54 +0000237 default:
njn95ec8702004-11-22 16:46:13 +0000238 if (VG_(needs).tool_errors)
njn26f02512004-11-22 18:33:15 +0000239 return TL_(eq_Error)(res, e1, e2);
njn25e49d8e72002-09-23 09:36:25 +0000240 else {
njn95ec8702004-11-22 16:46:13 +0000241 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000242 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000243 e1->ekind);
njn67993252004-11-22 18:02:32 +0000244 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000245 }
sewardjde4a1d02002-03-22 01:27:54 +0000246 }
247}
248
njn810086f2002-11-14 12:42:47 +0000249static void pp_Error ( Error* err, Bool printCount )
sewardjde4a1d02002-03-22 01:27:54 +0000250{
sewardjde4a1d02002-03-22 01:27:54 +0000251 if (printCount)
njn25e49d8e72002-09-23 09:36:25 +0000252 VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
sewardjb5f6f512005-03-10 23:59:00 +0000253 if (err->tid > 0 && err->tid != last_tid_printed) {
njn25e49d8e72002-09-23 09:36:25 +0000254 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
sewardjb5f6f512005-03-10 23:59:00 +0000255 last_tid_printed = err->tid;
256 }
njn25e49d8e72002-09-23 09:36:25 +0000257
njn810086f2002-11-14 12:42:47 +0000258 switch (err->ekind) {
sewardjb5f6f512005-03-10 23:59:00 +0000259 // case ThreadErr:
260 // case MutexErr:
261 // vg_assert(VG_(needs).core_errors);
262 // VG_(tm_error_print)(err);
263 // break;
sewardjde4a1d02002-03-22 01:27:54 +0000264 default:
njn95ec8702004-11-22 16:46:13 +0000265 if (VG_(needs).tool_errors)
njn26f02512004-11-22 18:33:15 +0000266 TL_(pp_Error)( err );
njn25e49d8e72002-09-23 09:36:25 +0000267 else {
njn95ec8702004-11-22 16:46:13 +0000268 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000269 "probably needs to be set?\n",
njn810086f2002-11-14 12:42:47 +0000270 err->ekind);
njn67993252004-11-22 18:02:32 +0000271 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000272 }
sewardjde4a1d02002-03-22 01:27:54 +0000273 }
274}
275
nethercote04d0fbc2004-01-26 16:48:06 +0000276/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000277 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000278Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000279{
280 Char ch, ch2;
281 Int res;
282
njn43c799e2003-04-08 00:08:52 +0000283 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000284 return False;
285
286 VG_(message)(Vg_UserMsg, "");
287
288 again:
289 VG_(printf)(
290 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000291 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
292 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000293 );
294
sewardj6024b212003-07-13 10:54:33 +0000295 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000296 if (res != 1) goto ioerror;
297 /* res == 1 */
298 if (ch == '\n') return False;
299 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
300 && ch != 'C' && ch != 'c') goto again;
301
sewardj6024b212003-07-13 10:54:33 +0000302 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000303 if (res != 1) goto ioerror;
304 if (ch2 != '\n') goto again;
305
njn43c799e2003-04-08 00:08:52 +0000306 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000307 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000308 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000309 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000310 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000311 vg_assert(ch == 'c' || ch == 'C');
312
313 ioerror:
njn43c799e2003-04-08 00:08:52 +0000314 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000315 return False;
316}
317
318
sewardjb5f6f512005-03-10 23:59:00 +0000319/* Construct an error */
njn25e49d8e72002-09-23 09:36:25 +0000320static __inline__
njn72718642003-07-24 08:45:32 +0000321void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
322 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000323{
njnca82cc02004-11-22 17:18:48 +0000324 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000325
njn810086f2002-11-14 12:42:47 +0000326 /* Core-only parts */
njn25e49d8e72002-09-23 09:36:25 +0000327 err->next = NULL;
328 err->supp = NULL;
329 err->count = 1;
njn72718642003-07-24 08:45:32 +0000330 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000331 if (NULL == where)
njnd01fef72005-03-25 23:35:48 +0000332 err->where = VG_(record_ExeContext)( tid );
njn43c799e2003-04-08 00:08:52 +0000333 else
334 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000335
nethercote996901a2004-08-03 13:29:09 +0000336 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000337 err->ekind = ekind;
338 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000339 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000340 err->string = s;
341
njn25e49d8e72002-09-23 09:36:25 +0000342 /* sanity... */
njn72718642003-07-24 08:45:32 +0000343 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000344}
345
njnf4261312005-03-20 23:45:36 +0000346static void printSuppForIp(UInt n, Addr ip)
347{
njn47b209a2005-03-25 23:47:16 +0000348 static UChar buf[VG_ERRTXT_LEN];
njnf4261312005-03-20 23:45:36 +0000349
njn47b209a2005-03-25 23:47:16 +0000350 if ( VG_(get_fnname_nodemangle) (ip, buf, VG_ERRTXT_LEN) ) {
njnf4261312005-03-20 23:45:36 +0000351 VG_(printf)(" fun:%s\n", buf);
njn47b209a2005-03-25 23:47:16 +0000352 } else if ( VG_(get_objname)(ip, buf+7, VG_ERRTXT_LEN-7) ) {
njnf4261312005-03-20 23:45:36 +0000353 VG_(printf)(" obj:%s\n", buf);
354 } else {
355 VG_(printf)(" ???:??? "
356 "# unknown, suppression will not work, sorry\n");
357 }
358}
359
nethercote10d481a2004-01-25 20:33:53 +0000360static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000361{
njn43c799e2003-04-08 00:08:52 +0000362 ExeContext* ec = VG_(get_error_where)(err);
363 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000364
sewardjb5f6f512005-03-10 23:59:00 +0000365 /* At most VG_MAX_SUPP_CALLERS names */
366 if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
njn43c799e2003-04-08 00:08:52 +0000367 vg_assert(stop_at > 0);
368
369 VG_(printf)("{\n");
370 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000371
sewardjb5f6f512005-03-10 23:59:00 +0000372 if (ThreadErr == err->ekind || MutexErr == err->ekind) {
njn6a230532003-07-21 10:38:23 +0000373 VG_(printf)(" core:PThread\n");
374
375 } else {
njn26f02512004-11-22 18:33:15 +0000376 Char* name = TL_(get_error_name)(err);
njn6a230532003-07-21 10:38:23 +0000377 if (NULL == name) {
378 VG_(message)(Vg_UserMsg,
nethercote137bc552003-11-14 17:47:54 +0000379 "(tool does not allow error to be suppressed)");
njn6a230532003-07-21 10:38:23 +0000380 return;
381 }
382 VG_(printf)(" %s:%s\n", VG_(details).name, name);
njn26f02512004-11-22 18:33:15 +0000383 TL_(print_extra_suppression_info)(err);
njn6a230532003-07-21 10:38:23 +0000384 }
njn43c799e2003-04-08 00:08:52 +0000385
njnf4261312005-03-20 23:45:36 +0000386 // Print stack trace elements
njnd01fef72005-03-25 23:35:48 +0000387 VG_(apply_StackTrace)(printSuppForIp, VG_(extract_StackTrace)(ec), stop_at);
njn43c799e2003-04-08 00:08:52 +0000388
389 VG_(printf)("}\n");
390}
391
njnb4aee052003-04-15 14:09:58 +0000392static
nethercote04d0fbc2004-01-26 16:48:06 +0000393void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000394{
sewardjd153fae2005-01-10 17:24:47 +0000395 Bool still_noisy = True;
396
nethercote04d0fbc2004-01-26 16:48:06 +0000397 /* Perhaps we want a debugger attach at this point? */
398 if (allow_db_attach &&
njnd2b17112005-04-19 04:10:25 +0000399 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
400 {
nethercote04d0fbc2004-01-26 16:48:06 +0000401 VG_(printf)("starting debugger\n");
402 VG_(start_debugger)( err->tid );
njnd2b17112005-04-19 04:10:25 +0000403 }
njn43c799e2003-04-08 00:08:52 +0000404 /* Or maybe we want to generate the error's suppression? */
sewardjd153fae2005-01-10 17:24:47 +0000405 if (VG_(clo_gen_suppressions) == 2
406 || (VG_(clo_gen_suppressions) == 1
njnd2b17112005-04-19 04:10:25 +0000407 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
sewardjd153fae2005-01-10 17:24:47 +0000408 ) {
nethercote42602b12004-01-25 19:30:29 +0000409 gen_suppression(err);
sewardjd153fae2005-01-10 17:24:47 +0000410 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
411 VG_(clo_gen_suppressions) = 0;
njn43c799e2003-04-08 00:08:52 +0000412 }
413}
414
415/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
416 just for pretty printing purposes. */
417static Bool is_first_shown_context = True;
418
njn25e49d8e72002-09-23 09:36:25 +0000419/* Top-level entry point to the error management subsystem.
420 All detected errors are notified here; this routine decides if/when the
421 user should see the error. */
njn72718642003-07-24 08:45:32 +0000422void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000423 ErrorKind ekind, Addr a, Char* s, void* extra )
424{
njn810086f2002-11-14 12:42:47 +0000425 Error err;
426 Error* p;
427 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000428 UInt extra_size;
njn695c16e2005-03-27 03:40:28 +0000429 VgRes exe_res = Vg_MedRes;
430 static Bool stopping_message = False;
431 static Bool slowdown_message = False;
432 static Int n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000433
njn14319cc2005-03-13 06:26:22 +0000434 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
435 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
sewardjf2537be2002-04-24 21:03:47 +0000436 have been found, just refuse to collect any more. This stops
437 the burden of the error-management system becoming excessive in
438 extremely buggy programs, although it does make it pretty
439 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000440 if (VG_(clo_error_limit)
njn695c16e2005-03-27 03:40:28 +0000441 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
njn14319cc2005-03-13 06:26:22 +0000442 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000443 if (!stopping_message) {
444 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000445
njn695c16e2005-03-27 03:40:28 +0000446 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
sewardjf2537be2002-04-24 21:03:47 +0000447 VG_(message)(Vg_UserMsg,
448 "More than %d different errors detected. "
449 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000450 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
sewardjf2537be2002-04-24 21:03:47 +0000451 } else {
452 VG_(message)(Vg_UserMsg,
453 "More than %d total errors detected. "
454 "I'm not reporting any more.",
njn14319cc2005-03-13 06:26:22 +0000455 M_COLLECT_NO_ERRORS_AFTER_FOUND );
sewardjf2537be2002-04-24 21:03:47 +0000456 }
457
sewardjde4a1d02002-03-22 01:27:54 +0000458 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000459 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000460 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000461 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000462 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000463 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000464 VG_(message)(Vg_UserMsg,
465 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000466 VG_(message)(Vg_UserMsg, "");
467 stopping_message = True;
468 }
469 return;
470 }
471
njn14319cc2005-03-13 06:26:22 +0000472 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
sewardjde4a1d02002-03-22 01:27:54 +0000473 been found, be much more conservative about collecting new
474 ones. */
njn695c16e2005-03-27 03:40:28 +0000475 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000476 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000477 if (!slowdown_message) {
478 VG_(message)(Vg_UserMsg, "");
479 VG_(message)(Vg_UserMsg,
480 "More than %d errors detected. Subsequent errors",
njn14319cc2005-03-13 06:26:22 +0000481 M_COLLECT_ERRORS_SLOWLY_AFTER);
sewardjde4a1d02002-03-22 01:27:54 +0000482 VG_(message)(Vg_UserMsg,
483 "will still be recorded, but in less detail than before.");
484 slowdown_message = True;
485 }
486 }
487
njn25e49d8e72002-09-23 09:36:25 +0000488 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000489 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000490
491 /* First, see if we've got an error record matching this one. */
njn695c16e2005-03-27 03:40:28 +0000492 p = errors;
sewardjde4a1d02002-03-22 01:27:54 +0000493 p_prev = NULL;
494 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000495 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000496 /* Found it. */
497 p->count++;
498 if (p->supp != NULL) {
499 /* Deal correctly with suppressed errors. */
500 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000501 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000502 } else {
nethercotef2b11482004-08-02 12:36:01 +0000503 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000504 }
505
506 /* Move p to the front of the list so that future searches
507 for it are faster. */
508 if (p_prev != NULL) {
509 vg_assert(p_prev->next == p);
njn695c16e2005-03-27 03:40:28 +0000510 p_prev->next = p->next;
511 p->next = errors;
512 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000513 }
sewardj7ebf7c32003-07-24 21:29:40 +0000514
sewardjde4a1d02002-03-22 01:27:54 +0000515 return;
516 }
517 p_prev = p;
518 p = p->next;
519 }
520
521 /* Didn't see it. Copy and add. */
522
njn43c799e2003-04-08 00:08:52 +0000523 /* OK, we're really going to collect it. The context is on the stack and
524 will disappear shortly, so we must copy it. First do the main
525 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000526
njn26f02512004-11-22 18:33:15 +0000527 Then TL_(update_extra) can update the `extra' part. This is for when
njn43c799e2003-04-08 00:08:52 +0000528 there are more details to fill in which take time to work out but
529 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000530 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000531 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000532
533 Then, if there is an `extra' part, copy it too, using the size that
njn26f02512004-11-22 18:33:15 +0000534 TL_(update_extra) returned. Also allow for people using the void*
njna70114c2003-08-19 16:14:42 +0000535 extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000536 */
537
538 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000539 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000540 *p = err;
njn43c799e2003-04-08 00:08:52 +0000541
sewardjb5f6f512005-03-10 23:59:00 +0000542 /* update `extra' */
543 switch (ekind) {
544 // case ThreadErr:
545 // case MutexErr:
546 // vg_assert(VG_(needs).core_errors);
547 // extra_size = VG_(tm_error_update_extra)(p);
548 // break;
549 default:
550 vg_assert(VG_(needs).tool_errors);
551 extra_size = TL_(update_extra)(p);
552 break;
553 }
njn43c799e2003-04-08 00:08:52 +0000554
sewardjb5f6f512005-03-10 23:59:00 +0000555 /* copy block pointed to by `extra', if there is one */
556 if (NULL != p->extra && 0 != extra_size) {
557 void* new_extra = VG_(malloc)(extra_size);
558 VG_(memcpy)(new_extra, p->extra, extra_size);
559 p->extra = new_extra;
njn43c799e2003-04-08 00:08:52 +0000560 }
561
njn695c16e2005-03-27 03:40:28 +0000562 p->next = errors;
njn25e49d8e72002-09-23 09:36:25 +0000563 p->supp = is_suppressible_error(&err);
njn695c16e2005-03-27 03:40:28 +0000564 errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000565 if (p->supp == NULL) {
nethercotef2b11482004-08-02 12:36:01 +0000566 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000567 if (!is_first_shown_context)
568 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000569 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000570 is_first_shown_context = False;
njn695c16e2005-03-27 03:40:28 +0000571 n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000572 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000573 } else {
nethercotef2b11482004-08-02 12:36:01 +0000574 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000575 p->supp->count++;
576 }
577}
578
njn43c799e2003-04-08 00:08:52 +0000579/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000580 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000581 guaranteed to only happen once. This avoids all the recording and
582 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000583 suppressed. Bool `print_error' dictates whether to print the error.
nethercotef2b11482004-08-02 12:36:01 +0000584 Bool `count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000585*/
njn72718642003-07-24 08:45:32 +0000586Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000587 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000588 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000589{
590 Error err;
591
592 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000593 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000594
595 /* Unless it's suppressed, we're going to show it. Don't need to make
596 a copy, because it's only temporary anyway.
597
njn26f02512004-11-22 18:33:15 +0000598 Then update the `extra' part with TL_(update_extra), because that can
njn43c799e2003-04-08 00:08:52 +0000599 have an affect on whether it's suppressed. Ignore the size return
njn26f02512004-11-22 18:33:15 +0000600 value of TL_(update_extra), because we're not copying `extra'. */
601 (void)TL_(update_extra)(&err);
njn43c799e2003-04-08 00:08:52 +0000602
603 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000604 if (count_error)
nethercotef2b11482004-08-02 12:36:01 +0000605 n_errs_found++;
njn43c799e2003-04-08 00:08:52 +0000606
607 if (print_error) {
608 if (!is_first_shown_context)
609 VG_(message)(Vg_UserMsg, "");
610 pp_Error(&err, False);
611 is_first_shown_context = False;
612 }
nethercote04d0fbc2004-01-26 16:48:06 +0000613 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000614
615 return False;
616
617 } else {
nethercotef2b11482004-08-02 12:36:01 +0000618 n_errs_suppressed++;
njn43c799e2003-04-08 00:08:52 +0000619 return True;
620 }
621}
622
sewardjde4a1d02002-03-22 01:27:54 +0000623
sewardjde4a1d02002-03-22 01:27:54 +0000624/*------------------------------------------------------------*/
625/*--- Exported fns ---*/
626/*------------------------------------------------------------*/
627
njnb9ecfe32005-03-13 05:27:57 +0000628/* This is called not from generated code but from the scheduler */
sewardjde4a1d02002-03-22 01:27:54 +0000629void VG_(show_all_errors) ( void )
630{
njn810086f2002-11-14 12:42:47 +0000631 Int i, n_min;
632 Int n_err_contexts, n_supp_contexts;
633 Error *p, *p_min;
634 Supp *su;
635 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000636
637 if (VG_(clo_verbosity) == 0)
638 return;
639
640 n_err_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000641 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000642 if (p->supp == NULL)
643 n_err_contexts++;
644 }
645
646 n_supp_contexts = 0;
njn695c16e2005-03-27 03:40:28 +0000647 for (su = suppressions; su != NULL; su = su->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000648 if (su->count > 0)
649 n_supp_contexts++;
650 }
sewardjde4a1d02002-03-22 01:27:54 +0000651 VG_(message)(Vg_UserMsg,
652 "ERROR SUMMARY: "
653 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000654 n_errs_found, n_err_contexts,
655 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000656
657 if (VG_(clo_verbosity) <= 1)
658 return;
659
660 /* Print the contexts in order of increasing error count. */
661 for (i = 0; i < n_err_contexts; i++) {
662 n_min = (1 << 30) - 1;
663 p_min = NULL;
njn695c16e2005-03-27 03:40:28 +0000664 for (p = errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000665 if (p->supp != NULL) continue;
666 if (p->count < n_min) {
667 n_min = p->count;
668 p_min = p;
669 }
670 }
njn67993252004-11-22 18:02:32 +0000671 if (p_min == NULL) VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000672
673 VG_(message)(Vg_UserMsg, "");
674 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
675 p_min->count,
676 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000677 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000678
679 if ((i+1 == VG_(clo_dump_error))) {
njnd01fef72005-03-25 23:35:48 +0000680 StackTrace ips = VG_(extract_StackTrace)(p_min->where);
sewardjfa8ec112005-01-19 11:55:34 +0000681 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
njnd01fef72005-03-25 23:35:48 +0000682 ips[0], /*debugging*/True, 0xFE/*verbosity*/);
sewardjde4a1d02002-03-22 01:27:54 +0000683 }
684
685 p_min->count = 1 << 30;
686 }
687
688 if (n_supp_contexts > 0)
689 VG_(message)(Vg_DebugMsg, "");
690 any_supp = False;
njn695c16e2005-03-27 03:40:28 +0000691 for (su = suppressions; su != NULL; su = su->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000692 if (su->count > 0) {
693 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000694 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000695 }
696 }
697
698 if (n_err_contexts > 0) {
699 if (any_supp)
700 VG_(message)(Vg_UserMsg, "");
701 VG_(message)(Vg_UserMsg,
702 "IN SUMMARY: "
703 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000704 n_errs_found, n_err_contexts, n_errs_suppressed,
sewardjde4a1d02002-03-22 01:27:54 +0000705 n_supp_contexts );
706 VG_(message)(Vg_UserMsg, "");
707 }
708}
709
710/*------------------------------------------------------------*/
711/*--- Standard suppressions ---*/
712/*------------------------------------------------------------*/
713
714/* Get a non-blank, non-comment line of at most nBuf chars from fd.
715 Skips leading spaces on the line. Return True if EOF was hit instead.
716*/
njn4ba5a792002-09-30 10:23:54 +0000717Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000718{
719 Char ch;
720 Int n, i;
721 while (True) {
722 /* First, read until a non-blank char appears. */
723 while (True) {
724 n = VG_(read)(fd, &ch, 1);
njn0c0f32a2005-03-26 04:14:01 +0000725 if (n == 1 && !VG_(isspace)(ch)) break;
sewardjde4a1d02002-03-22 01:27:54 +0000726 if (n == 0) return True;
727 }
728
729 /* Now, read the line into buf. */
730 i = 0;
731 buf[i++] = ch; buf[i] = 0;
732 while (True) {
733 n = VG_(read)(fd, &ch, 1);
734 if (n == 0) return False; /* the next call will return True */
735 if (ch == '\n') break;
736 if (i > 0 && i == nBuf-1) i--;
737 buf[i++] = ch; buf[i] = 0;
738 }
njn0c0f32a2005-03-26 04:14:01 +0000739 while (i > 1 && VG_(isspace)(buf[i-1])) {
sewardjde4a1d02002-03-22 01:27:54 +0000740 i--; buf[i] = 0;
741 };
742
743 /* VG_(printf)("The line is `%s'\n", buf); */
744 /* Ok, we have a line. If a non-comment line, return.
745 If a comment line, start all over again. */
746 if (buf[0] != '#') return False;
747 }
748}
749
750
751/* *p_caller contains the raw name of a caller, supposedly either
752 fun:some_function_name or
753 obj:some_object_name.
754 Set *p_ty accordingly and advance *p_caller over the descriptor
755 (fun: or obj:) part.
756 Returns False if failed.
757*/
sewardjb5f6f512005-03-10 23:59:00 +0000758static Bool setLocationTy ( SuppLoc* p )
sewardjde4a1d02002-03-22 01:27:54 +0000759{
sewardjb5f6f512005-03-10 23:59:00 +0000760 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
761 p->name += 4;
762 p->ty = FunName;
sewardjde4a1d02002-03-22 01:27:54 +0000763 return True;
764 }
sewardjb5f6f512005-03-10 23:59:00 +0000765 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
766 p->name += 4;
767 p->ty = ObjName;
sewardjde4a1d02002-03-22 01:27:54 +0000768 return True;
769 }
770 VG_(printf)("location should start with fun: or obj:\n");
771 return False;
772}
773
774
nethercote7cc9c232004-01-21 15:08:04 +0000775/* Look for "tool" in a string like "tool1,tool2,tool3" */
njn11cc9252002-10-07 14:42:59 +0000776static __inline__
nethercote7cc9c232004-01-21 15:08:04 +0000777Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000778{
779 Bool found;
780 Char *s = NULL; /* Shut gcc up */
781 Int len = VG_(strlen)(name);
782
783 found = (NULL != (s = VG_(strstr)(names, name)) &&
784 (s == names || *(s-1) == ',') &&
785 (*(s+len) == ',' || *(s+len) == '\0')
786 );
787
788 return found;
789}
790
njn695c16e2005-03-27 03:40:28 +0000791/* Read suppressions from the file specified in VG_(clo_suppressions)
sewardjde4a1d02002-03-22 01:27:54 +0000792 and place them in the suppressions list. If there's any difficulty
793 doing this, just give up -- there's no point in trying to recover.
794*/
sewardjde4a1d02002-03-22 01:27:54 +0000795static void load_one_suppressions_file ( Char* filename )
796{
797# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000798 Int fd, i;
sewardjb5f6f512005-03-10 23:59:00 +0000799 Bool eof;
njnc40c3a82002-10-02 11:02:27 +0000800 Char buf[N_BUF+1];
nethercote7cc9c232004-01-21 15:08:04 +0000801 Char* tool_names;
njnc40c3a82002-10-02 11:02:27 +0000802 Char* supp_name;
sewardjb5f6f512005-03-10 23:59:00 +0000803 Char* err_str = NULL;
804 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
njnc40c3a82002-10-02 11:02:27 +0000805
njn25e49d8e72002-09-23 09:36:25 +0000806 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000807 if (fd < 0) {
njn25e49d8e72002-09-23 09:36:25 +0000808 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000809 filename );
810 VG_(exit)(1);
811 }
812
sewardjb5f6f512005-03-10 23:59:00 +0000813#define BOMB(S) { err_str = S; goto syntax_error; }
814
sewardjde4a1d02002-03-22 01:27:54 +0000815 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000816 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000817 Supp* supp;
818 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000819 supp->count = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000820
821 // Initialise temporary reading-in buffer.
822 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
823 tmp_callers[i].ty = NoName;
824 tmp_callers[i].name = NULL;
825 }
826
njn810086f2002-11-14 12:42:47 +0000827 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000828
njn4ba5a792002-09-30 10:23:54 +0000829 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000830 if (eof) break;
831
sewardjb5f6f512005-03-10 23:59:00 +0000832 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000833
njn4ba5a792002-09-30 10:23:54 +0000834 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000835
836 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
837
njn25e49d8e72002-09-23 09:36:25 +0000838 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000839
njn4ba5a792002-09-30 10:23:54 +0000840 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000841
sewardjb5f6f512005-03-10 23:59:00 +0000842 if (eof) BOMB("unexpected end-of-file");
sewardjde4a1d02002-03-22 01:27:54 +0000843
njn94065fd2004-11-22 19:26:27 +0000844 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000845 i = 0;
846 while (True) {
847 if (buf[i] == ':') break;
sewardjb5f6f512005-03-10 23:59:00 +0000848 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
njnc40c3a82002-10-02 11:02:27 +0000849 i++;
njn25e49d8e72002-09-23 09:36:25 +0000850 }
njnc40c3a82002-10-02 11:02:27 +0000851 buf[i] = '\0'; /* Replace ':', splitting into two strings */
852
nethercote7cc9c232004-01-21 15:08:04 +0000853 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +0000854 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000855
nethercote7cc9c232004-01-21 15:08:04 +0000856 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +0000857 {
sewardjb5f6f512005-03-10 23:59:00 +0000858 // A core suppression
njn43c799e2003-04-08 00:08:52 +0000859 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000860 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000861 else
sewardjb5f6f512005-03-10 23:59:00 +0000862 BOMB("unknown core suppression type");
njnc40c3a82002-10-02 11:02:27 +0000863 }
njn95ec8702004-11-22 16:46:13 +0000864 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +0000865 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +0000866 {
sewardjb5f6f512005-03-10 23:59:00 +0000867 // A tool suppression
868 if (TL_(recognised_suppression)(supp_name, supp)) {
njn810086f2002-11-14 12:42:47 +0000869 /* Do nothing, function fills in supp->skind */
sewardjb5f6f512005-03-10 23:59:00 +0000870 } else {
871 BOMB("unknown tool suppression type");
872 }
njnc40c3a82002-10-02 11:02:27 +0000873 }
njn25e49d8e72002-09-23 09:36:25 +0000874 else {
sewardjb5f6f512005-03-10 23:59:00 +0000875 // Ignore rest of suppression
njn25e49d8e72002-09-23 09:36:25 +0000876 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000877 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjb5f6f512005-03-10 23:59:00 +0000878 if (eof) BOMB("unexpected end-of-file");
njn43c799e2003-04-08 00:08:52 +0000879 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000880 break;
881 }
882 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000883 }
884
njn95ec8702004-11-22 16:46:13 +0000885 if (VG_(needs).tool_errors &&
sewardjb5f6f512005-03-10 23:59:00 +0000886 !TL_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
887 {
888 BOMB("bad or missing extra suppression info");
sewardjde4a1d02002-03-22 01:27:54 +0000889 }
890
sewardjb5f6f512005-03-10 23:59:00 +0000891 i = 0;
892 while (True) {
893 eof = VG_(get_line) ( fd, buf, N_BUF );
894 if (eof)
895 BOMB("unexpected end-of-file");
896 if (VG_STREQ(buf, "}")) {
897 if (i > 0) {
898 break;
899 } else {
900 BOMB("missing stack trace");
901 }
902 }
903 if (i == VG_MAX_SUPP_CALLERS)
904 BOMB("too many callers in stack trace");
905 if (i > 0 && i >= VG_(clo_backtrace_size))
906 break;
907 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE, buf);
908 if (!setLocationTy(&(tmp_callers[i])))
909 BOMB("location should start with 'fun:' or 'obj:'");
910 i++;
911 }
912
913 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
914 // lines and grab the '}'.
sewardj57a8f5f2003-07-06 01:40:11 +0000915 if (!VG_STREQ(buf, "}")) {
sewardjb5f6f512005-03-10 23:59:00 +0000916 do {
917 eof = VG_(get_line) ( fd, buf, N_BUF );
918 } while (!eof && !VG_STREQ(buf, "}"));
919 }
920
921 // Copy tmp_callers[] into supp->callers[]
922 supp->n_callers = i;
923 supp->callers = VG_(arena_malloc)(VG_AR_CORE, i*sizeof(SuppLoc));
924 for (i = 0; i < supp->n_callers; i++) {
925 supp->callers[i] = tmp_callers[i];
sewardj57a8f5f2003-07-06 01:40:11 +0000926 }
927
njn695c16e2005-03-27 03:40:28 +0000928 supp->next = suppressions;
929 suppressions = supp;
sewardjde4a1d02002-03-22 01:27:54 +0000930 }
sewardjde4a1d02002-03-22 01:27:54 +0000931 VG_(close)(fd);
932 return;
933
934 syntax_error:
sewardjb5f6f512005-03-10 23:59:00 +0000935 VG_(message)(Vg_UserMsg,
936 "FATAL: in suppressions file `%s': %s", filename, err_str );
937
sewardjde4a1d02002-03-22 01:27:54 +0000938 VG_(close)(fd);
939 VG_(message)(Vg_UserMsg, "exiting now.");
nethercote8ed8a892004-11-08 13:24:25 +0000940 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +0000941
sewardjb5f6f512005-03-10 23:59:00 +0000942# undef BOMB
sewardjde4a1d02002-03-22 01:27:54 +0000943# undef N_BUF
944}
945
946
947void VG_(load_suppressions) ( void )
948{
949 Int i;
njn695c16e2005-03-27 03:40:28 +0000950 suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000951 for (i = 0; i < VG_(clo_n_suppressions); i++) {
952 if (VG_(clo_verbosity) > 1) {
njn3f04d242005-03-20 18:21:14 +0000953 VG_(message)(Vg_DebugMsg, "Reading suppressions file: %s",
954 VG_(clo_suppressions)[i] );
sewardjde4a1d02002-03-22 01:27:54 +0000955 }
956 load_one_suppressions_file( VG_(clo_suppressions)[i] );
957 }
958}
959
sewardjb5f6f512005-03-10 23:59:00 +0000960static
njn810086f2002-11-14 12:42:47 +0000961Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000962{
njn810086f2002-11-14 12:42:47 +0000963 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000964 case PThreadSupp:
sewardjb5f6f512005-03-10 23:59:00 +0000965 return (err->ekind == ThreadErr || err->ekind == MutexErr);
njn25e49d8e72002-09-23 09:36:25 +0000966 default:
njn95ec8702004-11-22 16:46:13 +0000967 if (VG_(needs).tool_errors) {
njn26f02512004-11-22 18:33:15 +0000968 return TL_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000969 } else {
970 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +0000971 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000972 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000973 err->ekind);
njn67993252004-11-22 18:02:32 +0000974 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000975 }
976 }
977}
978
sewardjb5f6f512005-03-10 23:59:00 +0000979static
980Bool supp_matches_callers(Error* err, Supp* su)
njn25e49d8e72002-09-23 09:36:25 +0000981{
982 Int i;
njn47b209a2005-03-25 23:47:16 +0000983 Char caller_name[VG_ERRTXT_LEN];
njnd01fef72005-03-25 23:35:48 +0000984 StackTrace ips = VG_(extract_StackTrace)(err->where);
njn25e49d8e72002-09-23 09:36:25 +0000985
sewardjb5f6f512005-03-10 23:59:00 +0000986 for (i = 0; i < su->n_callers; i++) {
njnd01fef72005-03-25 23:35:48 +0000987 Addr a = ips[i];
sewardjb5f6f512005-03-10 23:59:00 +0000988 vg_assert(su->callers[i].name != NULL);
989 switch (su->callers[i].ty) {
990 case ObjName:
njn47b209a2005-03-25 23:47:16 +0000991 if (!VG_(get_objname)(a, caller_name, VG_ERRTXT_LEN))
njn58c9f812005-03-11 04:46:09 +0000992 return False;
sewardjb5f6f512005-03-10 23:59:00 +0000993 break;
994
995 case FunName:
996 // Nb: mangled names used in suppressions
njn47b209a2005-03-25 23:47:16 +0000997 if (!VG_(get_fnname_nodemangle)(a, caller_name, VG_ERRTXT_LEN))
njn58c9f812005-03-11 04:46:09 +0000998 return False;
sewardjb5f6f512005-03-10 23:59:00 +0000999 break;
njn67993252004-11-22 18:02:32 +00001000 default: VG_(tool_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +00001001 }
sewardjb5f6f512005-03-10 23:59:00 +00001002 if (!VG_(string_match)(su->callers[i].name, caller_name))
1003 return False;
njn25e49d8e72002-09-23 09:36:25 +00001004 }
1005
1006 /* If we reach here, it's a match */
1007 return True;
1008}
sewardjde4a1d02002-03-22 01:27:54 +00001009
njn810086f2002-11-14 12:42:47 +00001010/* Does an error context match a suppression? ie is this a suppressible
1011 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +00001012 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +00001013*/
njn810086f2002-11-14 12:42:47 +00001014static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +00001015{
njn810086f2002-11-14 12:42:47 +00001016 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +00001017
sewardjde4a1d02002-03-22 01:27:54 +00001018 /* See if the error context matches any suppression. */
njn695c16e2005-03-27 03:40:28 +00001019 for (su = suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +00001020 if (supp_matches_error(su, err) &&
sewardjb5f6f512005-03-10 23:59:00 +00001021 supp_matches_callers(err, su))
1022 {
njn25e49d8e72002-09-23 09:36:25 +00001023 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001024 }
sewardjde4a1d02002-03-22 01:27:54 +00001025 }
njn25e49d8e72002-09-23 09:36:25 +00001026 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001027}
1028
sewardjde4a1d02002-03-22 01:27:54 +00001029/*--------------------------------------------------------------------*/
sewardjb5f6f512005-03-10 23:59:00 +00001030/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00001031/*--------------------------------------------------------------------*/