blob: 612f666ec6345f440324c9a3e11bac26b8925032 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Management of error messages. vg_errcontext.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercotef1e5e152004-09-01 23:58:16 +000031#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000032
33/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000034/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000035/*------------------------------------------------------------*/
36
sewardjde4a1d02002-03-22 01:27:54 +000037/* The list of error contexts found, both suppressed and unsuppressed.
38 Initially empty, and grows as errors are detected. */
njn810086f2002-11-14 12:42:47 +000039static Error* vg_errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000040
41/* The list of suppression directives, as read from the specified
42 suppressions file. */
njn810086f2002-11-14 12:42:47 +000043static Supp* vg_suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000044
45/* Running count of unsuppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000046static UInt n_errs_found = 0;
sewardjde4a1d02002-03-22 01:27:54 +000047
48/* Running count of suppressed errors detected. */
nethercotef2b11482004-08-02 12:36:01 +000049static UInt n_errs_suppressed = 0;
sewardjde4a1d02002-03-22 01:27:54 +000050
51/* forwards ... */
njn810086f2002-11-14 12:42:47 +000052static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000053
54
55/*------------------------------------------------------------*/
nethercote4a184902004-08-02 12:21:09 +000056/*--- Error type ---*/
57/*------------------------------------------------------------*/
58
nethercote996901a2004-08-03 13:29:09 +000059/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
nethercote4a184902004-08-02 12:21:09 +000060 * effectively extend it by defining their own enums in the (0..) range. */
61typedef
62 enum {
63 PThreadErr = -1, // Pthreading error
64 }
65 CoreErrorKind;
66
67/* Errors. Extensible (via the 'extra' field). Tools can use a normal
68 enum (with element values in the normal range (0..)) for `ekind'.
69 Functions for getting/setting the tool-relevant fields are in
nethercote46063202004-09-02 08:51:43 +000070 include/tool.h.
nethercote4a184902004-08-02 12:21:09 +000071
72 When errors are found and recorded with VG_(maybe_record_error)(), all
73 the tool must do is pass in the four parameters; core will
74 allocate/initialise the error record.
75*/
76struct _Error {
77 struct _Error* next;
78 // NULL if unsuppressed; or ptr to suppression record.
79 Supp* supp;
80 Int count;
81 ThreadId tid;
82
83 // The tool-specific part
84 ExeContext* where; // Initialised by core
85 Int ekind; // Used by ALL. Must be in the range (0..)
86 Addr addr; // Used frequently
87 Char* string; // Used frequently
88 void* extra; // For any tool-specific extras
89};
90
91ExeContext* VG_(get_error_where) ( Error* err )
92{
93 return err->where;
94}
95
96ErrorKind VG_(get_error_kind) ( Error* err )
97{
98 return err->ekind;
99}
100
101Addr VG_(get_error_address) ( Error* err )
102{
103 return err->addr;
104}
105
106Char* VG_(get_error_string) ( Error* err )
107{
108 return err->string;
109}
110
111void* VG_(get_error_extra) ( Error* err )
112{
113 return err->extra;
114}
115
nethercotef2b11482004-08-02 12:36:01 +0000116UInt VG_(get_n_errs_found)( void )
117{
118 return n_errs_found;
119}
120
nethercote4a184902004-08-02 12:21:09 +0000121/*------------------------------------------------------------*/
122/*--- Suppression type ---*/
123/*------------------------------------------------------------*/
124
125/* Note: it is imperative this doesn't overlap with (0..) at all, as tools
126 * effectively extend it by defining their own enums in the (0..) range. */
127typedef
128 enum {
129 PThreadSupp = -1, /* Matches PThreadErr */
130 }
131 CoreSuppKind;
132
133/* For each caller specified for a suppression, record the nature of
134 the caller name. Not of interest to tools. */
135typedef
136 enum {
137 ObjName, /* Name is of an shared object file. */
138 FunName /* Name is of a function. */
139 }
140 SuppLocTy;
141
142/* Suppressions. Tools can get/set tool-relevant parts with functions
nethercote46063202004-09-02 08:51:43 +0000143 declared in include/tool.h. Extensible via the 'extra' field.
nethercote4a184902004-08-02 12:21:09 +0000144 Tools can use a normal enum (with element values in the normal range
145 (0..)) for `skind'. */
146struct _Supp {
147 struct _Supp* next;
148 Int count; // The number of times this error has been suppressed.
149 Char* sname; // The name by which the suppression is referred to.
150 /* First two (name of fn where err occurs, and immediate caller)
151 * are mandatory; extra two are optional. */
152 SuppLocTy caller_ty[VG_N_SUPP_CALLERS];
153 Char* caller [VG_N_SUPP_CALLERS];
154
155 /* The tool-specific part */
156 SuppKind skind; // What kind of suppression. Must use the range (0..).
157 Char* string; // String -- use is optional. NULL by default.
158 void* extra; // Anything else -- use is optional. NULL by default.
159};
160
161SuppKind VG_(get_supp_kind) ( Supp* su )
162{
163 return su->skind;
164}
165
166Char* VG_(get_supp_string) ( Supp* su )
167{
168 return su->string;
169}
170
171void* VG_(get_supp_extra) ( Supp* su )
172{
173 return su->extra;
174}
175
176
177void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
178{
179 su->skind = skind;
180}
181
182void VG_(set_supp_string) ( Supp* su, Char* string )
183{
184 su->string = string;
185}
186
187void VG_(set_supp_extra) ( Supp* su, void* extra )
188{
189 su->extra = extra;
190}
191
192
193/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000194/*--- Helper fns ---*/
195/*------------------------------------------------------------*/
196
sewardjde4a1d02002-03-22 01:27:54 +0000197/* Compare error contexts, to detect duplicates. Note that if they
198 are otherwise the same, the faulting addrs and associated rwoffsets
199 are allowed to be different. */
njn810086f2002-11-14 12:42:47 +0000200static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +0000201{
njn810086f2002-11-14 12:42:47 +0000202 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +0000203 return False;
njn25e49d8e72002-09-23 09:36:25 +0000204 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +0000205 return False;
206
njn810086f2002-11-14 12:42:47 +0000207 switch (e1->ekind) {
sewardj4dced352002-06-04 22:54:20 +0000208 case PThreadErr:
njn25e49d8e72002-09-23 09:36:25 +0000209 vg_assert(VG_(needs).core_errors);
njn810086f2002-11-14 12:42:47 +0000210 if (e1->string == e2->string)
sewardj4dced352002-06-04 22:54:20 +0000211 return True;
njn810086f2002-11-14 12:42:47 +0000212 if (0 == VG_(strcmp)(e1->string, e2->string))
sewardj4dced352002-06-04 22:54:20 +0000213 return True;
214 return False;
sewardjde4a1d02002-03-22 01:27:54 +0000215 default:
njn95ec8702004-11-22 16:46:13 +0000216 if (VG_(needs).tool_errors)
njn26f02512004-11-22 18:33:15 +0000217 return TL_(eq_Error)(res, e1, e2);
njn25e49d8e72002-09-23 09:36:25 +0000218 else {
njn95ec8702004-11-22 16:46:13 +0000219 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000220 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000221 e1->ekind);
njn67993252004-11-22 18:02:32 +0000222 VG_(tool_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000223 }
sewardjde4a1d02002-03-22 01:27:54 +0000224 }
225}
226
njn810086f2002-11-14 12:42:47 +0000227static void pp_Error ( Error* err, Bool printCount )
sewardjde4a1d02002-03-22 01:27:54 +0000228{
sewardjde4a1d02002-03-22 01:27:54 +0000229 if (printCount)
njn25e49d8e72002-09-23 09:36:25 +0000230 VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
231 if (err->tid > 1)
232 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
233
njn810086f2002-11-14 12:42:47 +0000234 switch (err->ekind) {
sewardj4dced352002-06-04 22:54:20 +0000235 case PThreadErr:
njn25e49d8e72002-09-23 09:36:25 +0000236 vg_assert(VG_(needs).core_errors);
njn810086f2002-11-14 12:42:47 +0000237 VG_(message)(Vg_UserMsg, "%s", err->string );
njn25e49d8e72002-09-23 09:36:25 +0000238 VG_(pp_ExeContext)(err->where);
sewardj4dced352002-06-04 22:54:20 +0000239 break;
sewardjde4a1d02002-03-22 01:27:54 +0000240 default:
njn95ec8702004-11-22 16:46:13 +0000241 if (VG_(needs).tool_errors)
njn26f02512004-11-22 18:33:15 +0000242 TL_(pp_Error)( err );
njn25e49d8e72002-09-23 09:36:25 +0000243 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 err->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
nethercote04d0fbc2004-01-26 16:48:06 +0000252/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000253 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000254Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000255{
256 Char ch, ch2;
257 Int res;
258
njn43c799e2003-04-08 00:08:52 +0000259 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000260 return False;
261
262 VG_(message)(Vg_UserMsg, "");
263
264 again:
265 VG_(printf)(
266 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000267 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
268 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000269 );
270
sewardj6024b212003-07-13 10:54:33 +0000271 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000272 if (res != 1) goto ioerror;
273 /* res == 1 */
274 if (ch == '\n') return False;
275 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
276 && ch != 'C' && ch != 'c') goto again;
277
sewardj6024b212003-07-13 10:54:33 +0000278 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000279 if (res != 1) goto ioerror;
280 if (ch2 != '\n') goto again;
281
njn43c799e2003-04-08 00:08:52 +0000282 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000283 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000284 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000285 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000286 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000287 vg_assert(ch == 'c' || ch == 'C');
288
289 ioerror:
njn43c799e2003-04-08 00:08:52 +0000290 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000291 return False;
292}
293
294
njnbd2e75c2004-11-24 16:43:43 +0000295// Initialisation picks out values from the appropriate ThreadState as
296// necessary.
njn25e49d8e72002-09-23 09:36:25 +0000297static __inline__
njn72718642003-07-24 08:45:32 +0000298void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
299 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000300{
njnca82cc02004-11-22 17:18:48 +0000301 tl_assert(tid < VG_N_THREADS);
njn72718642003-07-24 08:45:32 +0000302
njn810086f2002-11-14 12:42:47 +0000303 /* Core-only parts */
njn25e49d8e72002-09-23 09:36:25 +0000304 err->next = NULL;
305 err->supp = NULL;
306 err->count = 1;
njn72718642003-07-24 08:45:32 +0000307 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000308 if (NULL == where)
njn72718642003-07-24 08:45:32 +0000309 err->where = VG_(get_ExeContext)( tid );
njn43c799e2003-04-08 00:08:52 +0000310 else
311 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000312
nethercote996901a2004-08-03 13:29:09 +0000313 /* Tool-relevant parts */
njn810086f2002-11-14 12:42:47 +0000314 err->ekind = ekind;
315 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000316 err->extra = extra;
sewardja6022612003-07-24 23:50:17 +0000317 err->string = s;
318
njn25e49d8e72002-09-23 09:36:25 +0000319 /* sanity... */
njn72718642003-07-24 08:45:32 +0000320 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000321}
322
nethercote10d481a2004-01-25 20:33:53 +0000323static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000324{
sewardj05bcdcb2003-05-18 10:05:38 +0000325 Int i;
nethercote3b38c1d2004-10-18 15:47:18 +0000326 static UChar buf[M_VG_ERRTXT];
nethercote77eba602003-11-13 17:35:04 +0000327 Bool main_done = False;
njn43c799e2003-04-08 00:08:52 +0000328 ExeContext* ec = VG_(get_error_where)(err);
329 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000330
nethercote0ec1e192004-11-18 12:45:40 +0000331 /* At most VG_N_SUPP_CALLERS names */
332 if (stop_at > VG_N_SUPP_CALLERS) stop_at = VG_N_SUPP_CALLERS;
njn43c799e2003-04-08 00:08:52 +0000333 vg_assert(stop_at > 0);
334
335 VG_(printf)("{\n");
336 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000337
338 if (PThreadErr == err->ekind) {
339 VG_(printf)(" core:PThread\n");
340
341 } else {
njn26f02512004-11-22 18:33:15 +0000342 Char* name = TL_(get_error_name)(err);
njn6a230532003-07-21 10:38:23 +0000343 if (NULL == name) {
344 VG_(message)(Vg_UserMsg,
nethercote137bc552003-11-14 17:47:54 +0000345 "(tool does not allow error to be suppressed)");
njn6a230532003-07-21 10:38:23 +0000346 return;
347 }
348 VG_(printf)(" %s:%s\n", VG_(details).name, name);
njn26f02512004-11-22 18:33:15 +0000349 TL_(print_extra_suppression_info)(err);
njn6a230532003-07-21 10:38:23 +0000350 }
njn43c799e2003-04-08 00:08:52 +0000351
352 /* This loop condensed from VG_(mini_stack_dump)() */
353 i = 0;
354 do {
nethercote86c5dcb2004-09-05 21:32:37 +0000355 Addr eip = ec->ips[i];
nethercotefbfc1082004-09-04 15:28:37 +0000356 if (i > 0)
357 eip -= MIN_INSTR_SIZE; // point to calling line
njn43c799e2003-04-08 00:08:52 +0000358 if ( VG_(get_fnname_nodemangle) (eip, buf, M_VG_ERRTXT) ) {
nethercote77eba602003-11-13 17:35:04 +0000359 // Stop after "main"; if main() is recursive, stop after last main().
360
361 if ( ! VG_(clo_show_below_main)) {
362 if (VG_STREQ(buf, "main"))
363 main_done = True;
364 else if (main_done)
365 break;
366 }
njn43c799e2003-04-08 00:08:52 +0000367 VG_(printf)(" fun:%s\n", buf);
368 } else if ( VG_(get_objname)(eip, buf, M_VG_ERRTXT) ) {
369 VG_(printf)(" obj:%s\n", buf);
370 } else {
371 VG_(printf)(" ???:??? "
nethercote125c91e2004-06-27 12:38:17 +0000372 "# unknown, suppression will not work, sorry\n");
njn43c799e2003-04-08 00:08:52 +0000373 }
374 i++;
nethercote86c5dcb2004-09-05 21:32:37 +0000375 } while (i < stop_at && ec->ips[i] != 0);
njn43c799e2003-04-08 00:08:52 +0000376
377 VG_(printf)("}\n");
378}
379
njnb4aee052003-04-15 14:09:58 +0000380static
nethercote04d0fbc2004-01-26 16:48:06 +0000381void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000382{
sewardjd153fae2005-01-10 17:24:47 +0000383 Bool still_noisy = True;
384
nethercote04d0fbc2004-01-26 16:48:06 +0000385 /* Perhaps we want a debugger attach at this point? */
386 if (allow_db_attach &&
387 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
njn3e884182003-04-15 13:03:23 +0000388 {
nethercote04d0fbc2004-01-26 16:48:06 +0000389 VG_(printf)("starting debugger\n");
390 VG_(start_debugger)( err->tid );
njn43c799e2003-04-08 00:08:52 +0000391 }
392 /* Or maybe we want to generate the error's suppression? */
sewardjd153fae2005-01-10 17:24:47 +0000393 if (VG_(clo_gen_suppressions) == 2
394 || (VG_(clo_gen_suppressions) == 1
395 && VG_(is_action_requested)( "Print suppression",
396 &still_noisy ))
397 ) {
nethercote42602b12004-01-25 19:30:29 +0000398 gen_suppression(err);
sewardjd153fae2005-01-10 17:24:47 +0000399 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
400 VG_(clo_gen_suppressions) = 0;
njn43c799e2003-04-08 00:08:52 +0000401 }
402}
403
404/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
405 just for pretty printing purposes. */
406static Bool is_first_shown_context = True;
407
njn25e49d8e72002-09-23 09:36:25 +0000408/* Top-level entry point to the error management subsystem.
409 All detected errors are notified here; this routine decides if/when the
410 user should see the error. */
njn72718642003-07-24 08:45:32 +0000411void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000412 ErrorKind ekind, Addr a, Char* s, void* extra )
413{
njn810086f2002-11-14 12:42:47 +0000414 Error err;
415 Error* p;
416 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000417 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000418 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000419 static Bool stopping_message = False;
420 static Bool slowdown_message = False;
421 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000422
sewardjf2537be2002-04-24 21:03:47 +0000423 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
424 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
425 have been found, just refuse to collect any more. This stops
426 the burden of the error-management system becoming excessive in
427 extremely buggy programs, although it does make it pretty
428 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000429 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000430 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
nethercotef2b11482004-08-02 12:36:01 +0000431 || n_errs_found >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000432 if (!stopping_message) {
433 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000434
435 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
436 VG_(message)(Vg_UserMsg,
437 "More than %d different errors detected. "
438 "I'm not reporting any more.",
439 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
440 } else {
441 VG_(message)(Vg_UserMsg,
442 "More than %d total errors detected. "
443 "I'm not reporting any more.",
444 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
445 }
446
sewardjde4a1d02002-03-22 01:27:54 +0000447 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000448 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000449 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000450 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000451 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000452 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000453 VG_(message)(Vg_UserMsg,
454 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000455 VG_(message)(Vg_UserMsg, "");
456 stopping_message = True;
457 }
458 return;
459 }
460
461 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
462 been found, be much more conservative about collecting new
463 ones. */
464 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000465 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000466 if (!slowdown_message) {
467 VG_(message)(Vg_UserMsg, "");
468 VG_(message)(Vg_UserMsg,
469 "More than %d errors detected. Subsequent errors",
470 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
471 VG_(message)(Vg_UserMsg,
472 "will still be recorded, but in less detail than before.");
473 slowdown_message = True;
474 }
475 }
476
njn25e49d8e72002-09-23 09:36:25 +0000477 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000478 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000479
480 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000481 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000482 p_prev = NULL;
483 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000484 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000485 /* Found it. */
486 p->count++;
487 if (p->supp != NULL) {
488 /* Deal correctly with suppressed errors. */
489 p->supp->count++;
nethercotef2b11482004-08-02 12:36:01 +0000490 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000491 } else {
nethercotef2b11482004-08-02 12:36:01 +0000492 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000493 }
494
495 /* Move p to the front of the list so that future searches
496 for it are faster. */
497 if (p_prev != NULL) {
498 vg_assert(p_prev->next == p);
499 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000500 p->next = vg_errors;
501 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000502 }
sewardj7ebf7c32003-07-24 21:29:40 +0000503
sewardjde4a1d02002-03-22 01:27:54 +0000504 return;
505 }
506 p_prev = p;
507 p = p->next;
508 }
509
510 /* Didn't see it. Copy and add. */
511
njn43c799e2003-04-08 00:08:52 +0000512 /* OK, we're really going to collect it. The context is on the stack and
513 will disappear shortly, so we must copy it. First do the main
514 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000515
njn26f02512004-11-22 18:33:15 +0000516 Then TL_(update_extra) can update the `extra' part. This is for when
njn43c799e2003-04-08 00:08:52 +0000517 there are more details to fill in which take time to work out but
518 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000519 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000520 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000521
522 Then, if there is an `extra' part, copy it too, using the size that
njn26f02512004-11-22 18:33:15 +0000523 TL_(update_extra) returned. Also allow for people using the void*
njna70114c2003-08-19 16:14:42 +0000524 extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000525 */
526
527 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000528 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000529 *p = err;
njn43c799e2003-04-08 00:08:52 +0000530
njn6a230532003-07-21 10:38:23 +0000531 /* update `extra', for non-core errors (core ones don't use 'extra') */
njn95ec8702004-11-22 16:46:13 +0000532 if (VG_(needs).tool_errors && PThreadErr != ekind) {
njn26f02512004-11-22 18:33:15 +0000533 extra_size = TL_(update_extra)(p);
njn43c799e2003-04-08 00:08:52 +0000534
njna70114c2003-08-19 16:14:42 +0000535 /* copy block pointed to by `extra', if there is one */
536 if (NULL != p->extra && 0 != extra_size) {
njn6a230532003-07-21 10:38:23 +0000537 void* new_extra = VG_(malloc)(extra_size);
538 VG_(memcpy)(new_extra, p->extra, extra_size);
539 p->extra = new_extra;
540 }
njn43c799e2003-04-08 00:08:52 +0000541 }
542
njn25e49d8e72002-09-23 09:36:25 +0000543 p->next = vg_errors;
544 p->supp = is_suppressible_error(&err);
545 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000546 if (p->supp == NULL) {
nethercotef2b11482004-08-02 12:36:01 +0000547 n_errs_found++;
sewardjde4a1d02002-03-22 01:27:54 +0000548 if (!is_first_shown_context)
549 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000550 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000551 is_first_shown_context = False;
552 vg_n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000553 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000554 } else {
nethercotef2b11482004-08-02 12:36:01 +0000555 n_errs_suppressed++;
sewardjde4a1d02002-03-22 01:27:54 +0000556 p->supp->count++;
557 }
558}
559
njn43c799e2003-04-08 00:08:52 +0000560/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000561 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000562 guaranteed to only happen once. This avoids all the recording and
563 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000564 suppressed. Bool `print_error' dictates whether to print the error.
nethercotef2b11482004-08-02 12:36:01 +0000565 Bool `count_error' dictates whether to count the error in n_errs_found.
njn47363ab2003-04-21 13:24:40 +0000566*/
njn72718642003-07-24 08:45:32 +0000567Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000568 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000569 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000570{
571 Error err;
572
573 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000574 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000575
576 /* Unless it's suppressed, we're going to show it. Don't need to make
577 a copy, because it's only temporary anyway.
578
njn26f02512004-11-22 18:33:15 +0000579 Then update the `extra' part with TL_(update_extra), because that can
njn43c799e2003-04-08 00:08:52 +0000580 have an affect on whether it's suppressed. Ignore the size return
njn26f02512004-11-22 18:33:15 +0000581 value of TL_(update_extra), because we're not copying `extra'. */
582 (void)TL_(update_extra)(&err);
njn43c799e2003-04-08 00:08:52 +0000583
584 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000585 if (count_error)
nethercotef2b11482004-08-02 12:36:01 +0000586 n_errs_found++;
njn43c799e2003-04-08 00:08:52 +0000587
588 if (print_error) {
589 if (!is_first_shown_context)
590 VG_(message)(Vg_UserMsg, "");
591 pp_Error(&err, False);
592 is_first_shown_context = False;
593 }
nethercote04d0fbc2004-01-26 16:48:06 +0000594 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000595
596 return False;
597
598 } else {
nethercotef2b11482004-08-02 12:36:01 +0000599 n_errs_suppressed++;
njn43c799e2003-04-08 00:08:52 +0000600 return True;
601 }
602}
603
sewardjde4a1d02002-03-22 01:27:54 +0000604
sewardjde4a1d02002-03-22 01:27:54 +0000605/*------------------------------------------------------------*/
606/*--- Exported fns ---*/
607/*------------------------------------------------------------*/
608
njn25e49d8e72002-09-23 09:36:25 +0000609/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000610
njn25e49d8e72002-09-23 09:36:25 +0000611void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000612{
njn25e49d8e72002-09-23 09:36:25 +0000613 if (! VG_(needs).core_errors) return;
njn72718642003-07-24 08:45:32 +0000614 VG_(maybe_record_error)( tid, PThreadErr, /*addr*/0, msg, /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000615}
616
sewardjde4a1d02002-03-22 01:27:54 +0000617void VG_(show_all_errors) ( void )
618{
njn810086f2002-11-14 12:42:47 +0000619 Int i, n_min;
620 Int n_err_contexts, n_supp_contexts;
621 Error *p, *p_min;
622 Supp *su;
623 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000624
625 if (VG_(clo_verbosity) == 0)
626 return;
627
628 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000629 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000630 if (p->supp == NULL)
631 n_err_contexts++;
632 }
633
634 n_supp_contexts = 0;
635 for (su = vg_suppressions; su != NULL; su = su->next) {
636 if (su->count > 0)
637 n_supp_contexts++;
638 }
sewardjde4a1d02002-03-22 01:27:54 +0000639 VG_(message)(Vg_UserMsg,
640 "ERROR SUMMARY: "
641 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000642 n_errs_found, n_err_contexts,
643 n_errs_suppressed, n_supp_contexts );
sewardjde4a1d02002-03-22 01:27:54 +0000644
645 if (VG_(clo_verbosity) <= 1)
646 return;
647
648 /* Print the contexts in order of increasing error count. */
649 for (i = 0; i < n_err_contexts; i++) {
650 n_min = (1 << 30) - 1;
651 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000652 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000653 if (p->supp != NULL) continue;
654 if (p->count < n_min) {
655 n_min = p->count;
656 p_min = p;
657 }
658 }
njn67993252004-11-22 18:02:32 +0000659 if (p_min == NULL) VG_(tool_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000660
661 VG_(message)(Vg_UserMsg, "");
662 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
663 p_min->count,
664 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000665 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000666
667 if ((i+1 == VG_(clo_dump_error))) {
sewardjfa8ec112005-01-19 11:55:34 +0000668 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
669 p_min->where->ips[0], /*debugging*/True,
670 0xFE/*verbosity*/);
sewardjde4a1d02002-03-22 01:27:54 +0000671 }
672
673 p_min->count = 1 << 30;
674 }
675
676 if (n_supp_contexts > 0)
677 VG_(message)(Vg_DebugMsg, "");
678 any_supp = False;
679 for (su = vg_suppressions; su != NULL; su = su->next) {
680 if (su->count > 0) {
681 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000682 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000683 }
684 }
685
686 if (n_err_contexts > 0) {
687 if (any_supp)
688 VG_(message)(Vg_UserMsg, "");
689 VG_(message)(Vg_UserMsg,
690 "IN SUMMARY: "
691 "%d errors from %d contexts (suppressed: %d from %d)",
nethercotef2b11482004-08-02 12:36:01 +0000692 n_errs_found, n_err_contexts, n_errs_suppressed,
sewardjde4a1d02002-03-22 01:27:54 +0000693 n_supp_contexts );
694 VG_(message)(Vg_UserMsg, "");
695 }
696}
697
698/*------------------------------------------------------------*/
699/*--- Standard suppressions ---*/
700/*------------------------------------------------------------*/
701
702/* Get a non-blank, non-comment line of at most nBuf chars from fd.
703 Skips leading spaces on the line. Return True if EOF was hit instead.
704*/
705
706#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
707
njn4ba5a792002-09-30 10:23:54 +0000708Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000709{
710 Char ch;
711 Int n, i;
712 while (True) {
713 /* First, read until a non-blank char appears. */
714 while (True) {
715 n = VG_(read)(fd, &ch, 1);
716 if (n == 1 && !VG_ISSPACE(ch)) break;
717 if (n == 0) return True;
718 }
719
720 /* Now, read the line into buf. */
721 i = 0;
722 buf[i++] = ch; buf[i] = 0;
723 while (True) {
724 n = VG_(read)(fd, &ch, 1);
725 if (n == 0) return False; /* the next call will return True */
726 if (ch == '\n') break;
727 if (i > 0 && i == nBuf-1) i--;
728 buf[i++] = ch; buf[i] = 0;
729 }
730 while (i > 1 && VG_ISSPACE(buf[i-1])) {
731 i--; buf[i] = 0;
732 };
733
734 /* VG_(printf)("The line is `%s'\n", buf); */
735 /* Ok, we have a line. If a non-comment line, return.
736 If a comment line, start all over again. */
737 if (buf[0] != '#') return False;
738 }
739}
740
741
742/* *p_caller contains the raw name of a caller, supposedly either
743 fun:some_function_name or
744 obj:some_object_name.
745 Set *p_ty accordingly and advance *p_caller over the descriptor
746 (fun: or obj:) part.
747 Returns False if failed.
748*/
njn25e49d8e72002-09-23 09:36:25 +0000749static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000750{
751 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
752 (*p_caller) += 4;
753 *p_ty = FunName;
754 return True;
755 }
756 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
757 (*p_caller) += 4;
758 *p_ty = ObjName;
759 return True;
760 }
761 VG_(printf)("location should start with fun: or obj:\n");
762 return False;
763}
764
765
nethercote7cc9c232004-01-21 15:08:04 +0000766/* Look for "tool" in a string like "tool1,tool2,tool3" */
njn11cc9252002-10-07 14:42:59 +0000767static __inline__
nethercote7cc9c232004-01-21 15:08:04 +0000768Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000769{
770 Bool found;
771 Char *s = NULL; /* Shut gcc up */
772 Int len = VG_(strlen)(name);
773
774 found = (NULL != (s = VG_(strstr)(names, name)) &&
775 (s == names || *(s-1) == ',') &&
776 (*(s+len) == ',' || *(s+len) == '\0')
777 );
778
779 return found;
780}
781
sewardjde4a1d02002-03-22 01:27:54 +0000782/* Read suppressions from the file specified in vg_clo_suppressions
783 and place them in the suppressions list. If there's any difficulty
784 doing this, just give up -- there's no point in trying to recover.
785*/
sewardjde4a1d02002-03-22 01:27:54 +0000786static void load_one_suppressions_file ( Char* filename )
787{
788# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000789 Int fd, i;
nethercote8ed8a892004-11-08 13:24:25 +0000790 Bool eof, too_many_contexts = False;
njnc40c3a82002-10-02 11:02:27 +0000791 Char buf[N_BUF+1];
nethercote7cc9c232004-01-21 15:08:04 +0000792 Char* tool_names;
njnc40c3a82002-10-02 11:02:27 +0000793 Char* supp_name;
794
njn25e49d8e72002-09-23 09:36:25 +0000795 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000796 if (fd < 0) {
njn25e49d8e72002-09-23 09:36:25 +0000797 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000798 filename );
799 VG_(exit)(1);
800 }
801
802 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000803 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000804 Supp* supp;
805 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000806 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000807 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000808 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000809
njn4ba5a792002-09-30 10:23:54 +0000810 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000811 if (eof) break;
812
njn43c799e2003-04-08 00:08:52 +0000813 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000814
njn4ba5a792002-09-30 10:23:54 +0000815 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000816 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000817 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000818
njn4ba5a792002-09-30 10:23:54 +0000819 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000820
sewardjde4a1d02002-03-22 01:27:54 +0000821 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000822
njn94065fd2004-11-22 19:26:27 +0000823 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000824 i = 0;
825 while (True) {
826 if (buf[i] == ':') break;
827 if (buf[i] == '\0') goto syntax_error;
828 i++;
njn25e49d8e72002-09-23 09:36:25 +0000829 }
njnc40c3a82002-10-02 11:02:27 +0000830 buf[i] = '\0'; /* Replace ':', splitting into two strings */
831
nethercote7cc9c232004-01-21 15:08:04 +0000832 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +0000833 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000834
njn11cc9252002-10-07 14:42:59 +0000835 /* Is it a core suppression? */
nethercote7cc9c232004-01-21 15:08:04 +0000836 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +0000837 {
njn43c799e2003-04-08 00:08:52 +0000838 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000839 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000840 else
841 goto syntax_error;
842 }
843
nethercote7cc9c232004-01-21 15:08:04 +0000844 /* Is it a tool suppression? */
njn95ec8702004-11-22 16:46:13 +0000845 else if (VG_(needs).tool_errors &&
nethercote7cc9c232004-01-21 15:08:04 +0000846 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +0000847 {
njn26f02512004-11-22 18:33:15 +0000848 if (TL_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000849 {
njn810086f2002-11-14 12:42:47 +0000850 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000851 } else
852 goto syntax_error;
853 }
854
njn25e49d8e72002-09-23 09:36:25 +0000855 else {
njnc40c3a82002-10-02 11:02:27 +0000856 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000857 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000858 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000859 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000860 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000861 break;
862 }
863 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000864 }
865
njn95ec8702004-11-22 16:46:13 +0000866 if (VG_(needs).tool_errors &&
njn26f02512004-11-22 18:33:15 +0000867 !TL_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000868 goto syntax_error;
869
njn25e49d8e72002-09-23 09:36:25 +0000870 /* "i > 0" ensures at least one caller read. */
njn633de322003-05-12 20:40:13 +0000871 for (i = 0; i <= VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000872 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000873 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000874 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000875 break;
njn633de322003-05-12 20:40:13 +0000876 if (i == VG_N_SUPP_CALLERS)
877 break;
njn25e49d8e72002-09-23 09:36:25 +0000878 supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf);
879 if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i])))
880 goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000881 }
882
sewardj57a8f5f2003-07-06 01:40:11 +0000883 /* make sure to grab the '}' if the num callers is >=
884 VG_N_SUPP_CALLERS */
885 if (!VG_STREQ(buf, "}")) {
nethercote8ed8a892004-11-08 13:24:25 +0000886 // Don't just ignore extra lines -- abort. (Someone complained
887 // about silent ignoring of lines in bug #77922.)
888 //do {
889 // eof = VG_(get_line) ( fd, buf, N_BUF );
890 //} while (!eof && !VG_STREQ(buf, "}"));
891 too_many_contexts = True;
892 goto syntax_error;
sewardj57a8f5f2003-07-06 01:40:11 +0000893 }
894
sewardjde4a1d02002-03-22 01:27:54 +0000895 supp->next = vg_suppressions;
896 vg_suppressions = supp;
897 }
sewardjde4a1d02002-03-22 01:27:54 +0000898 VG_(close)(fd);
899 return;
900
901 syntax_error:
902 if (eof) {
903 VG_(message)(Vg_UserMsg,
904 "FATAL: in suppressions file `%s': unexpected EOF",
905 filename );
nethercote8ed8a892004-11-08 13:24:25 +0000906 } else if (too_many_contexts) {
907 VG_(message)(Vg_UserMsg,
908 "FATAL: in suppressions file: `%s': at %s:",
909 filename, buf );
910 VG_(message)(Vg_UserMsg,
911 "too many lines (limit of %d contexts in suppressions)",
912 VG_N_SUPP_CALLERS);
sewardjde4a1d02002-03-22 01:27:54 +0000913 } else {
914 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000915 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000916 filename, buf );
917 }
918 VG_(close)(fd);
919 VG_(message)(Vg_UserMsg, "exiting now.");
nethercote8ed8a892004-11-08 13:24:25 +0000920 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +0000921
922# undef N_BUF
923}
924
925
926void VG_(load_suppressions) ( void )
927{
928 Int i;
929 vg_suppressions = NULL;
930 for (i = 0; i < VG_(clo_n_suppressions); i++) {
931 if (VG_(clo_verbosity) > 1) {
932 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
933 VG_(clo_suppressions)[i] );
934 }
935 load_one_suppressions_file( VG_(clo_suppressions)[i] );
936 }
937}
938
njn25e49d8e72002-09-23 09:36:25 +0000939/* Return the name of an erring fn in a way which is useful
940 for comparing against the contents of a suppressions file.
941 Doesn't demangle the fn name, because we want to refer to
942 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000943*/
njn43c799e2003-04-08 00:08:52 +0000944static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
945 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000946{
947 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
948 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
949}
950
951static __inline__
njn810086f2002-11-14 12:42:47 +0000952Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000953{
njn810086f2002-11-14 12:42:47 +0000954 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000955 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000956 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000957 default:
njn95ec8702004-11-22 16:46:13 +0000958 if (VG_(needs).tool_errors) {
njn26f02512004-11-22 18:33:15 +0000959 return TL_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000960 } else {
961 VG_(printf)(
njn95ec8702004-11-22 16:46:13 +0000962 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
njn25e49d8e72002-09-23 09:36:25 +0000963 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000964 err->ekind);
njn67993252004-11-22 18:02:32 +0000965 VG_(tool_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000966 }
967 }
968}
969
970static __inline__
njn810086f2002-11-14 12:42:47 +0000971Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
972 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000973{
974 Int i;
975
njn633de322003-05-12 20:40:13 +0000976 for (i = 0; i < VG_N_SUPP_CALLERS && su->caller[i] != NULL; i++) {
njn25e49d8e72002-09-23 09:36:25 +0000977 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000978 case ObjName: if (VG_(string_match)(su->caller[i],
979 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000980 return False;
njn4ba5a792002-09-30 10:23:54 +0000981 case FunName: if (VG_(string_match)(su->caller[i],
982 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000983 return False;
njn67993252004-11-22 18:02:32 +0000984 default: VG_(tool_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000985 }
986 }
987
988 /* If we reach here, it's a match */
989 return True;
990}
sewardjde4a1d02002-03-22 01:27:54 +0000991
njn810086f2002-11-14 12:42:47 +0000992/* Does an error context match a suppression? ie is this a suppressible
993 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000994 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000995*/
njn810086f2002-11-14 12:42:47 +0000996static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000997{
njn25e49d8e72002-09-23 09:36:25 +0000998 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000999
nethercote3b38c1d2004-10-18 15:47:18 +00001000 static Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
1001 static Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +00001002
njn810086f2002-11-14 12:42:47 +00001003 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +00001004
njn25e49d8e72002-09-23 09:36:25 +00001005 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +00001006 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +00001007 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +00001008 */
1009
1010 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +00001011 if get_objname_fnname doesn't write anything to them. */
1012 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
1013 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001014
njn25e49d8e72002-09-23 09:36:25 +00001015 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
nethercote86c5dcb2004-09-05 21:32:37 +00001016 get_objname_fnname ( err->where->ips[i], caller_obj[i], M_VG_ERRTXT,
1017 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +00001018 }
1019
1020 /* See if the error context matches any suppression. */
1021 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +00001022 if (supp_matches_error(su, err) &&
1023 supp_matches_callers(su, caller_obj, caller_fun)) {
1024 return su;
sewardjde4a1d02002-03-22 01:27:54 +00001025 }
sewardjde4a1d02002-03-22 01:27:54 +00001026 }
njn25e49d8e72002-09-23 09:36:25 +00001027 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +00001028}
1029
sewardjde4a1d02002-03-22 01:27:54 +00001030/*--------------------------------------------------------------------*/
1031/*--- end vg_errcontext.c ---*/
1032/*--------------------------------------------------------------------*/