1
2 /*--------------------------------------------------------------------*/
3 /*--- Management of error messages. m_errormgr.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2012 Julian Seward
11 jseward@acm.org
12
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
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_libcsetjmp.h"
34 #include "pub_core_threadstate.h" // For VG_N_THREADS
35 #include "pub_core_debugger.h"
36 #include "pub_core_debuginfo.h"
37 #include "pub_core_errormgr.h"
38 #include "pub_core_execontext.h"
39 #include "pub_core_gdbserver.h"
40 #include "pub_core_libcbase.h"
41 #include "pub_core_libcassert.h"
42 #include "pub_core_libcfile.h"
43 #include "pub_core_libcprint.h"
44 #include "pub_core_libcproc.h" // For VG_(getpid)()
45 #include "pub_core_seqmatch.h"
46 #include "pub_core_mallocfree.h"
47 #include "pub_core_options.h"
48 #include "pub_core_stacktrace.h"
49 #include "pub_core_tooliface.h"
50 #include "pub_core_translate.h" // for VG_(translate)()
51 #include "pub_core_xarray.h" // VG_(xaprintf) et al
52
53 /*------------------------------------------------------------*/
54 /*--- Globals ---*/
55 /*------------------------------------------------------------*/
56
57 /* After this many different unsuppressed errors have been observed,
58 be more conservative about collecting new ones. */
59 #define M_COLLECT_ERRORS_SLOWLY_AFTER 100
60
61 /* After this many different unsuppressed errors have been observed,
62 stop collecting errors at all, and tell the user their program is
63 evidently a steaming pile of camel dung. */
64 #define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
65
66 /* After this many total errors have been observed, stop collecting
67 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
68 #define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
69
70 /* The list of error contexts found, both suppressed and unsuppressed.
71 Initially empty, and grows as errors are detected. */
72 static Error* errors = NULL;
73
74 /* The list of suppression directives, as read from the specified
75 suppressions file. Note that the list gets rearranged as a result
76 of the searches done by is_suppressible_error(). */
77 static Supp* suppressions = NULL;
78
79 /* Running count of unsuppressed errors detected. */
80 static UInt n_errs_found = 0;
81
82 /* Running count of suppressed errors detected. */
83 static UInt n_errs_suppressed = 0;
84
85 /* Running count of errors shown. */
86 static UInt n_errs_shown = 0;
87
88 /* Running count of unsuppressed error contexts. */
89 static UInt n_err_contexts = 0;
90
91 /* Running count of suppressed error contexts. */
92 static UInt n_supp_contexts = 0;
93
94
95 /* forwards ... */
96 static Supp* is_suppressible_error ( Error* err );
97
98 static ThreadId last_tid_printed = 1;
99
100 /* Stats: number of searches of the error list initiated. */
101 static UWord em_errlist_searches = 0;
102
103 /* Stats: number of comparisons done during error list
104 searching. */
105 static UWord em_errlist_cmps = 0;
106
107 /* Stats: number of searches of the suppression list initiated. */
108 static UWord em_supplist_searches = 0;
109
110 /* Stats: number of comparisons done during suppression list
111 searching. */
112 static UWord em_supplist_cmps = 0;
113
114 /*------------------------------------------------------------*/
115 /*--- Error type ---*/
116 /*------------------------------------------------------------*/
117
118 /* Errors. Extensible (via the 'extra' field). Tools can use a normal
119 enum (with element values in the normal range (0..)) for 'ekind'.
120 Functions for getting/setting the tool-relevant fields are in
121 include/pub_tool_errormgr.h.
122
123 When errors are found and recorded with VG_(maybe_record_error)(), all
124 the tool must do is pass in the four parameters; core will
125 allocate/initialise the error record.
126 */
127 struct _Error {
128 struct _Error* next;
129 // Unique tag. This gives the error a unique identity (handle) by
130 // which it can be referred to afterwords. Currently only used for
131 // XML printing.
132 UInt unique;
133 // NULL if unsuppressed; or ptr to suppression record.
134 Supp* supp;
135 Int count;
136
137 // The tool-specific part
138 ThreadId tid; // Initialised by core
139 ExeContext* where; // Initialised by core
140 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
141 Addr addr; // Used frequently
142 Char* string; // Used frequently
143 void* extra; // For any tool-specific extras
144 };
145
146
VG_(get_error_where)147 ExeContext* VG_(get_error_where) ( Error* err )
148 {
149 return err->where;
150 }
151
VG_(get_error_kind)152 ErrorKind VG_(get_error_kind) ( Error* err )
153 {
154 return err->ekind;
155 }
156
VG_(get_error_address)157 Addr VG_(get_error_address) ( Error* err )
158 {
159 return err->addr;
160 }
161
VG_(get_error_string)162 Char* VG_(get_error_string) ( Error* err )
163 {
164 return err->string;
165 }
166
VG_(get_error_extra)167 void* VG_(get_error_extra) ( Error* err )
168 {
169 return err->extra;
170 }
171
VG_(get_n_errs_found)172 UInt VG_(get_n_errs_found)( void )
173 {
174 return n_errs_found;
175 }
176
VG_(get_n_errs_shown)177 UInt VG_(get_n_errs_shown)( void )
178 {
179 return n_errs_shown;
180 }
181
182 /*------------------------------------------------------------*/
183 /*--- Suppression type ---*/
184 /*------------------------------------------------------------*/
185
186 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools
187 * effectively extend it by defining their own enums in the (0..) range. */
188 typedef
189 enum {
190 // Nb: thread errors are a relic of the time when Valgrind's core
191 // could detect them. This example is left commented-out as an
192 // example should new core errors ever be added.
193 ThreadSupp = -1, /* Matches ThreadErr */
194 }
195 CoreSuppKind;
196
197 /* Max number of callers for context in a suppression. */
198 #define VG_MAX_SUPP_CALLERS 24
199
200 /* For each caller specified for a suppression, record the nature of
201 the caller name. Not of interest to tools. */
202 typedef
203 enum {
204 NoName, /* Error case */
205 ObjName, /* Name is of an shared object file. */
206 FunName, /* Name is of a function. */
207 DotDotDot /* Frame-level wildcard */
208 }
209 SuppLocTy;
210
211 typedef
212 struct {
213 SuppLocTy ty;
214 Bool name_is_simple_str; /* True if name is a string without
215 '?' and '*' wildcard characters. */
216 Char* name; /* NULL for NoName and DotDotDot */
217 }
218 SuppLoc;
219
220 /* Suppressions. Tools can get/set tool-relevant parts with functions
221 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
222 Tools can use a normal enum (with element values in the normal range
223 (0..)) for 'skind'. */
224 struct _Supp {
225 struct _Supp* next;
226 Int count; // The number of times this error has been suppressed.
227 Char* sname; // The name by which the suppression is referred to.
228
229 // Length of 'callers'
230 Int n_callers;
231 // Array of callers, for matching stack traces. First one (name of fn
232 // where err occurs) is mandatory; rest are optional.
233 SuppLoc* callers;
234
235 /* The tool-specific part */
236 SuppKind skind; // What kind of suppression. Must use the range (0..).
237 Char* string; // String -- use is optional. NULL by default.
238 void* extra; // Anything else -- use is optional. NULL by default.
239 };
240
VG_(get_supp_kind)241 SuppKind VG_(get_supp_kind) ( Supp* su )
242 {
243 return su->skind;
244 }
245
VG_(get_supp_string)246 Char* VG_(get_supp_string) ( Supp* su )
247 {
248 return su->string;
249 }
250
VG_(get_supp_extra)251 void* VG_(get_supp_extra) ( Supp* su )
252 {
253 return su->extra;
254 }
255
256
VG_(set_supp_kind)257 void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
258 {
259 su->skind = skind;
260 }
261
VG_(set_supp_string)262 void VG_(set_supp_string) ( Supp* su, Char* string )
263 {
264 su->string = string;
265 }
266
VG_(set_supp_extra)267 void VG_(set_supp_extra) ( Supp* su, void* extra )
268 {
269 su->extra = extra;
270 }
271
272
273 /*------------------------------------------------------------*/
274 /*--- Helper fns ---*/
275 /*------------------------------------------------------------*/
276
277 // Only show core errors if the tool wants to, we're not running with -q,
278 // and were not outputting XML.
VG_(showing_core_errors)279 Bool VG_(showing_core_errors)(void)
280 {
281 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
282 }
283
284 /* Compare errors, to detect duplicates.
285 */
eq_Error(VgRes res,Error * e1,Error * e2)286 static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
287 {
288 if (e1->ekind != e2->ekind)
289 return False;
290 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
291 return False;
292
293 switch (e1->ekind) {
294 //(example code, see comment on CoreSuppKind above)
295 //case ThreadErr:
296 // vg_assert(VG_(needs).core_errors);
297 // return <something>
298 default:
299 if (VG_(needs).tool_errors) {
300 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
301 } else {
302 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
303 "probably needs to be set.\n",
304 e1->ekind);
305 VG_(tool_panic)("unhandled error type");
306 }
307 }
308 }
309
310
311 /* Helper functions for suppression generation: print a single line of
312 a suppression pseudo-stack-trace, either in XML or text mode. It's
313 important that the behaviour of these two functions exactly
314 corresponds.
315 */
316 #define ERRTXT_LEN 4096
317
printSuppForIp_XML(UInt n,Addr ip,void * uu_opaque)318 static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque)
319 {
320 static UChar buf[ERRTXT_LEN];
321 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
322 VG_(printf_xml)(" <sframe> <fun>%pS</fun> </sframe>\n", buf);
323 } else
324 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
325 VG_(printf_xml)(" <sframe> <obj>%pS</obj> </sframe>\n", buf);
326 } else {
327 VG_(printf_xml)(" <sframe> <obj>*</obj> </sframe>\n");
328 }
329 }
330
printSuppForIp_nonXML(UInt n,Addr ip,void * textV)331 static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV)
332 {
333 static UChar buf[ERRTXT_LEN];
334 XArray* /* of HChar */ text = (XArray*)textV;
335 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
336 VG_(xaprintf)(text, " fun:%s\n", buf);
337 } else
338 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
339 VG_(xaprintf)(text, " obj:%s\n", buf);
340 } else {
341 VG_(xaprintf)(text, " obj:*\n");
342 }
343 }
344
345 /* Generate a suppression for an error, either in text or XML mode.
346 */
gen_suppression(Error * err)347 static void gen_suppression(Error* err)
348 {
349 Char xtra[256]; /* assumed big enough (is overrun-safe) */
350 Bool anyXtra;
351 Char* name;
352 ExeContext* ec;
353 XArray* /* HChar */ text;
354
355 const HChar* dummy_name = "insert_a_suppression_name_here";
356
357 vg_assert(err);
358
359 ec = VG_(get_error_where)(err);
360 vg_assert(ec);
361
362 name = VG_TDICT_CALL(tool_get_error_name, err);
363 if (NULL == name) {
364 VG_(umsg)("(%s does not allow error to be suppressed)\n",
365 VG_(details).name);
366 return;
367 }
368
369 /* In XML mode, we also need to print the plain text version of the
370 suppresion in a CDATA section. What that really means is, we
371 need to generate the plaintext version both in XML and text
372 mode. So generate it into TEXT. */
373 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
374 VG_(free), sizeof(HChar) );
375 vg_assert(text);
376
377 /* Ok. Generate the plain text version into TEXT. */
378 VG_(xaprintf)(text, "{\n");
379 VG_(xaprintf)(text, " <%s>\n", dummy_name);
380 VG_(xaprintf)(text, " %s:%s\n", VG_(details).name, name);
381
382 VG_(memset)(xtra, 0, sizeof(xtra));
383 anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info,
384 err, xtra, sizeof(xtra));
385 vg_assert(xtra[sizeof(xtra)-1] == 0);
386
387 if (anyXtra)
388 VG_(xaprintf)(text, " %s\n", xtra);
389
390 // Print stack trace elements
391 UInt n_ips = VG_(get_ExeContext_n_ips)(ec);
392 tl_assert(n_ips > 0);
393 if (n_ips > VG_MAX_SUPP_CALLERS)
394 n_ips = VG_MAX_SUPP_CALLERS;
395 VG_(apply_StackTrace)(printSuppForIp_nonXML,
396 text,
397 VG_(get_ExeContext_StackTrace)(ec),
398 n_ips);
399
400 VG_(xaprintf)(text, "}\n");
401 // zero terminate
402 VG_(xaprintf)(text, "%c", (HChar)0 );
403 // VG_(printf) of text
404
405 /* And now display it. */
406 if (! VG_(clo_xml) ) {
407
408 // the simple case
409 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
410
411 } else {
412
413 /* Now we have to print the XML directly. No need to go to the
414 effort of stuffing it in an XArray, since we won't need it
415 again. */
416 VG_(printf_xml)(" <suppression>\n");
417 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name);
418 VG_(printf_xml)(
419 " <skind>%pS:%pS</skind>\n", VG_(details).name, name);
420 if (anyXtra)
421 VG_(printf_xml)(" <skaux>%pS</skaux>\n", xtra);
422
423 // Print stack trace elements
424 VG_(apply_StackTrace)(printSuppForIp_XML,
425 NULL,
426 VG_(get_ExeContext_StackTrace)(ec),
427 VG_(get_ExeContext_n_ips)(ec));
428
429 // And now the cdata bit
430 // XXX FIXME! properly handle the case where the raw text
431 // itself contains "]]>", as specified in Protocol 4.
432 VG_(printf_xml)(" <rawtext>\n");
433 VG_(printf_xml)("<![CDATA[\n");
434 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
435 VG_(printf_xml)("]]>\n");
436 VG_(printf_xml)(" </rawtext>\n");
437 VG_(printf_xml)(" </suppression>\n");
438
439 }
440
441 VG_(deleteXA)(text);
442 }
443
444
445 /* Figure out if we want to perform a given action for this error,
446 possibly by asking the user.
447 */
VG_(is_action_requested)448 Bool VG_(is_action_requested) ( Char* action, Bool* clo )
449 {
450 Char ch, ch2;
451 Int res;
452
453 /* First off, we shouldn't be asking the user anything if
454 we're in XML mode. */
455 if (VG_(clo_xml))
456 return False; /* That's a Nein, oder Nay as they say down here in B-W */
457
458 if (*clo == False)
459 return False;
460
461 VG_(umsg)("\n");
462
463 again:
464 VG_(printf)(
465 "==%d== "
466 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
467 VG_(getpid)(), action
468 );
469
470 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
471 if (res != 1) goto ioerror;
472 /* res == 1 */
473 if (ch == '\n') return False;
474 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
475 && ch != 'C' && ch != 'c') goto again;
476
477 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
478 if (res != 1) goto ioerror;
479 if (ch2 != '\n') goto again;
480
481 /* No, don't want to do action. */
482 if (ch == 'n' || ch == 'N') return False;
483 /* Yes, want to do action. */
484 if (ch == 'y' || ch == 'Y') return True;
485 /* No, don't want to do action, and don't ask again either. */
486 vg_assert(ch == 'c' || ch == 'C');
487
488 ioerror:
489 *clo = False;
490 return False;
491 }
492
493
494 /* Do text-mode actions on error, that is, immediately after an error
495 is printed. These are:
496 * possibly, attach to a debugger
497 * possibly, generate a suppression.
498 Note this should not be called in XML mode!
499 */
500 static
do_actions_on_error(Error * err,Bool allow_db_attach)501 void do_actions_on_error(Error* err, Bool allow_db_attach)
502 {
503 Bool still_noisy = True;
504
505 /* Should be assured by caller */
506 vg_assert( ! VG_(clo_xml) );
507
508 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
509 if (VG_(clo_vgdb) != Vg_VgdbNo
510 && allow_db_attach
511 && VG_(dyn_vgdb_error) <= n_errs_shown) {
512 VG_(umsg)("(action on error) vgdb me ... \n");
513 VG_(gdbserver)( err->tid );
514 VG_(umsg)("Continuing ...\n");
515 }
516
517 /* Perhaps we want a debugger attach at this point? */
518 /* GDBTD ??? maybe we should/could remove the below assuming the
519 gdbserver interface is better ??? */
520 if (allow_db_attach &&
521 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
522 {
523 if (0) VG_(printf)("starting debugger\n");
524 VG_(start_debugger)( err->tid );
525 }
526 /* Or maybe we want to generate the error's suppression? */
527 if (VG_(clo_gen_suppressions) == 2
528 || (VG_(clo_gen_suppressions) == 1
529 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
530 ) {
531 gen_suppression(err);
532 }
533 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
534 VG_(clo_gen_suppressions) = 0;
535 }
536
537
538 /* Prints an error. Not entirely simple because of the differences
539 between XML and text mode output.
540
541 In XML mode:
542
543 * calls the tool's pre-show method, so the tool can create any
544 preamble ahead of the message, if it wants.
545
546 * prints the opening tag, and the <unique> and <tid> fields
547
548 * prints the tool-specific parts of the message
549
550 * if suppression generation is required, a suppression
551
552 * the closing tag
553
554 In text mode:
555
556 * calls the tool's pre-show method, so the tool can create any
557 preamble ahead of the message, if it wants.
558
559 * prints the tool-specific parts of the message
560
561 * calls do_actions_on_error. This optionally does a debugger
562 attach (and detach), and optionally prints a suppression; both
563 of these may require user input.
564 */
pp_Error(Error * err,Bool allow_db_attach,Bool xml)565 static void pp_Error ( Error* err, Bool allow_db_attach, Bool xml )
566 {
567 /* If this fails, you probably specified your tool's method
568 dictionary incorrectly. */
569 vg_assert(VG_(needs).tool_errors);
570
571 if (xml) {
572
573 /* Note, allow_db_attach is ignored in here. */
574
575 /* Ensure that suppression generation is either completely
576 enabled or completely disabled; either way, we won't require
577 any user input. m_main.process_cmd_line_options should
578 ensure the asserted condition holds. */
579 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
580 || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
581
582 /* Pre-show it to the tool */
583 VG_TDICT_CALL( tool_before_pp_Error, err );
584
585 /* standard preamble */
586 VG_(printf_xml)("<error>\n");
587 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
588 VG_(printf_xml)(" <tid>%d</tid>\n", err->tid);
589
590 /* actually print it */
591 VG_TDICT_CALL( tool_pp_Error, err );
592
593 if (VG_(clo_gen_suppressions) > 0)
594 gen_suppression(err);
595
596 /* postamble */
597 VG_(printf_xml)("</error>\n");
598 VG_(printf_xml)("\n");
599
600 } else {
601
602 VG_TDICT_CALL( tool_before_pp_Error, err );
603
604 if (VG_(tdict).tool_show_ThreadIDs_for_errors
605 && err->tid > 0 && err->tid != last_tid_printed) {
606 VG_(umsg)("Thread %d:\n", err->tid );
607 last_tid_printed = err->tid;
608 }
609
610 VG_TDICT_CALL( tool_pp_Error, err );
611 VG_(umsg)("\n");
612
613 do_actions_on_error(err, allow_db_attach);
614 }
615 }
616
617
618 /* Construct an error */
619 static
construct_error(Error * err,ThreadId tid,ErrorKind ekind,Addr a,Char * s,void * extra,ExeContext * where)620 void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
621 Char* s, void* extra, ExeContext* where )
622 {
623 /* DO NOT MAKE unique_counter NON-STATIC */
624 static UInt unique_counter = 0;
625
626 tl_assert(tid < VG_N_THREADS);
627
628 /* Core-only parts */
629 err->unique = unique_counter++;
630 err->next = NULL;
631 err->supp = NULL;
632 err->count = 1;
633 err->tid = tid;
634 if (NULL == where)
635 err->where = VG_(record_ExeContext)( tid, 0 );
636 else
637 err->where = where;
638
639 /* Tool-relevant parts */
640 err->ekind = ekind;
641 err->addr = a;
642 err->extra = extra;
643 err->string = s;
644
645 /* sanity... */
646 vg_assert( tid < VG_N_THREADS );
647 }
648
649
650
651 /* Top-level entry point to the error management subsystem.
652 All detected errors are notified here; this routine decides if/when the
653 user should see the error. */
VG_(maybe_record_error)654 void VG_(maybe_record_error) ( ThreadId tid,
655 ErrorKind ekind, Addr a, Char* s, void* extra )
656 {
657 Error err;
658 Error* p;
659 Error* p_prev;
660 UInt extra_size;
661 VgRes exe_res = Vg_MedRes;
662 static Bool stopping_message = False;
663 static Bool slowdown_message = False;
664
665 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
666 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
667 have been found, just refuse to collect any more. This stops
668 the burden of the error-management system becoming excessive in
669 extremely buggy programs, although it does make it pretty
670 pointless to continue the Valgrind run after this point. */
671 if (VG_(clo_error_limit)
672 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
673 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
674 && !VG_(clo_xml)) {
675 if (!stopping_message) {
676 VG_(umsg)("\n");
677
678 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
679 VG_(umsg)(
680 "More than %d different errors detected. "
681 "I'm not reporting any more.\n",
682 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
683 } else {
684 VG_(umsg)(
685 "More than %d total errors detected. "
686 "I'm not reporting any more.\n",
687 M_COLLECT_NO_ERRORS_AFTER_FOUND );
688 }
689
690 VG_(umsg)("Final error counts will be inaccurate. "
691 "Go fix your program!\n");
692 VG_(umsg)("Rerun with --error-limit=no to disable "
693 "this cutoff. Note\n");
694 VG_(umsg)("that errors may occur in your program without "
695 "prior warning from\n");
696 VG_(umsg)("Valgrind, because errors are no longer "
697 "being displayed.\n");
698 VG_(umsg)("\n");
699 stopping_message = True;
700 }
701 return;
702 }
703
704 /* Ignore it if error acquisition is disabled for this thread. */
705 { ThreadState* tst = VG_(get_ThreadState)(tid);
706 if (tst->err_disablement_level > 0)
707 return;
708 }
709
710 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
711 been found, be much more conservative about collecting new
712 ones. */
713 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
714 && !VG_(clo_xml)) {
715 exe_res = Vg_LowRes;
716 if (!slowdown_message) {
717 VG_(umsg)("\n");
718 VG_(umsg)("More than %d errors detected. Subsequent errors\n",
719 M_COLLECT_ERRORS_SLOWLY_AFTER);
720 VG_(umsg)("will still be recorded, but in less "
721 "detail than before.\n");
722 slowdown_message = True;
723 }
724 }
725
726 /* Build ourselves the error */
727 construct_error ( &err, tid, ekind, a, s, extra, NULL );
728
729 /* First, see if we've got an error record matching this one. */
730 em_errlist_searches++;
731 p = errors;
732 p_prev = NULL;
733 while (p != NULL) {
734 em_errlist_cmps++;
735 if (eq_Error(exe_res, p, &err)) {
736 /* Found it. */
737 p->count++;
738 if (p->supp != NULL) {
739 /* Deal correctly with suppressed errors. */
740 p->supp->count++;
741 n_errs_suppressed++;
742 } else {
743 n_errs_found++;
744 }
745
746 /* Move p to the front of the list so that future searches
747 for it are faster. It also allows to print the last
748 error (see VG_(show_last_error). */
749 if (p_prev != NULL) {
750 vg_assert(p_prev->next == p);
751 p_prev->next = p->next;
752 p->next = errors;
753 errors = p;
754 }
755
756 return;
757 }
758 p_prev = p;
759 p = p->next;
760 }
761
762 /* Didn't see it. Copy and add. */
763
764 /* OK, we're really going to collect it. The context is on the stack and
765 will disappear shortly, so we must copy it. First do the main
766 (non-'extra') part.
767
768 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
769 is for when there are more details to fill in which take time to work
770 out but don't affect our earlier decision to include the error -- by
771 postponing those details until now, we avoid the extra work in the
772 case where we ignore the error. Ugly.
773
774 Then, if there is an 'extra' part, copy it too, using the size that
775 VG_(tdict).tool_update_extra returned. Also allow for people using
776 the void* extra field for a scalar value like an integer.
777 */
778
779 /* copy main part */
780 p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
781 *p = err;
782
783 /* update 'extra' */
784 switch (ekind) {
785 //(example code, see comment on CoreSuppKind above)
786 //case ThreadErr:
787 // vg_assert(VG_(needs).core_errors);
788 // extra_size = <something>
789 // break;
790 default:
791 vg_assert(VG_(needs).tool_errors);
792 extra_size = VG_TDICT_CALL(tool_update_extra, p);
793 break;
794 }
795
796 /* copy block pointed to by 'extra', if there is one */
797 if (NULL != p->extra && 0 != extra_size) {
798 void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
799 VG_(memcpy)(new_extra, p->extra, extra_size);
800 p->extra = new_extra;
801 }
802
803 p->next = errors;
804 p->supp = is_suppressible_error(&err);
805 errors = p;
806 if (p->supp == NULL) {
807 /* update stats */
808 n_err_contexts++;
809 n_errs_found++;
810 n_errs_shown++;
811 /* Actually show the error; more complex than you might think. */
812 pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml) );
813 } else {
814 n_supp_contexts++;
815 n_errs_suppressed++;
816 p->supp->count++;
817 }
818 }
819
820 /* Second top-level entry point to the error management subsystem, for
821 errors that the tool wants to report immediately, eg. because they're
822 guaranteed to only happen once. This avoids all the recording and
823 comparing stuff. But they can be suppressed; returns True if it is
824 suppressed. Bool 'print_error' dictates whether to print the error.
825 Bool 'count_error' dictates whether to count the error in n_errs_found.
826 */
VG_(unique_error)827 Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
828 void* extra, ExeContext* where, Bool print_error,
829 Bool allow_db_attach, Bool count_error )
830 {
831 Error err;
832 Supp *su;
833
834 /* Ignore it if error acquisition is disabled for this thread. */
835 ThreadState* tst = VG_(get_ThreadState)(tid);
836 if (tst->err_disablement_level > 0)
837 return False; /* ignored, not suppressed */
838
839 /* Build ourselves the error */
840 construct_error ( &err, tid, ekind, a, s, extra, where );
841
842 /* Unless it's suppressed, we're going to show it. Don't need to make
843 a copy, because it's only temporary anyway.
844
845 Then update the 'extra' part with VG_(tdict).tool_update_extra),
846 because that can have an affect on whether it's suppressed. Ignore
847 the size return value of VG_(tdict).tool_update_extra, because we're
848 not copying 'extra'. */
849 (void)VG_TDICT_CALL(tool_update_extra, &err);
850
851 su = is_suppressible_error(&err);
852 if (NULL == su) {
853 if (count_error) {
854 n_errs_found++;
855 n_err_contexts++;
856 }
857
858 if (print_error) {
859 /* update stats */
860 n_errs_shown++;
861 /* Actually show the error; more complex than you might think. */
862 pp_Error(&err, allow_db_attach, VG_(clo_xml));
863 }
864 return False;
865
866 } else {
867 if (count_error) {
868 n_errs_suppressed++;
869 n_supp_contexts++;
870 }
871 su->count++;
872 return True;
873 }
874 }
875
876
877 /*------------------------------------------------------------*/
878 /*--- Exported fns ---*/
879 /*------------------------------------------------------------*/
880
881 /* Show the used suppressions. Returns False if no suppression
882 got used. */
show_used_suppressions(void)883 static Bool show_used_suppressions ( void )
884 {
885 Supp *su;
886 Bool any_supp;
887
888 if (VG_(clo_xml))
889 VG_(printf_xml)("<suppcounts>\n");
890
891 any_supp = False;
892 for (su = suppressions; su != NULL; su = su->next) {
893 if (su->count <= 0)
894 continue;
895 if (VG_(clo_xml)) {
896 VG_(printf_xml)( " <pair>\n"
897 " <count>%d</count>\n"
898 " <name>%pS</name>\n"
899 " </pair>\n",
900 su->count, su->sname );
901 } else {
902 // blank line before the first shown suppression, if any
903 if (!any_supp)
904 VG_(dmsg)("\n");
905 VG_(dmsg)("used_suppression: %6d %s\n", su->count, su->sname);
906 }
907 any_supp = True;
908 }
909
910 if (VG_(clo_xml))
911 VG_(printf_xml)("</suppcounts>\n");
912
913 return any_supp;
914 }
915
916 /* Show all the errors that occurred, and possibly also the
917 suppressions used. */
VG_(show_all_errors)918 void VG_(show_all_errors) ( Int verbosity, Bool xml )
919 {
920 Int i, n_min;
921 Error *p, *p_min;
922 Bool any_supp;
923
924 if (verbosity == 0)
925 return;
926
927 /* If we're printing XML, just show the suppressions and stop. */
928 if (xml) {
929 (void)show_used_suppressions();
930 return;
931 }
932
933 /* We only get here if not printing XML. */
934 VG_(umsg)("ERROR SUMMARY: "
935 "%d errors from %d contexts (suppressed: %d from %d)\n",
936 n_errs_found, n_err_contexts,
937 n_errs_suppressed, n_supp_contexts );
938
939 if (verbosity <= 1)
940 return;
941
942 // We do the following only at -v or above, and only in non-XML
943 // mode
944
945 /* Print the contexts in order of increasing error count.
946 Once an error is shown, we add a huge value to its count to filter it
947 out. After having shown all errors, we reset count to the original value. */
948 for (i = 0; i < n_err_contexts; i++) {
949 n_min = (1 << 30) - 1;
950 p_min = NULL;
951 for (p = errors; p != NULL; p = p->next) {
952 if (p->supp != NULL) continue;
953 if (p->count < n_min) {
954 n_min = p->count;
955 p_min = p;
956 }
957 }
958 // XXX: this isn't right. See bug 203651.
959 if (p_min == NULL) continue; //VG_(tool_panic)("show_all_errors()");
960
961 VG_(umsg)("\n");
962 VG_(umsg)("%d errors in context %d of %d:\n",
963 p_min->count, i+1, n_err_contexts);
964 pp_Error( p_min, False/*allow_db_attach*/, False /* xml */ );
965
966 // We're not printing XML -- we'd have exited above if so.
967 vg_assert(! xml);
968
969 if ((i+1 == VG_(clo_dump_error))) {
970 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
971 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
972 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
973 /*bbs_done*/0,
974 /*allow redir?*/True);
975 }
976
977 p_min->count = p_min->count + (1 << 30);
978 }
979
980 /* reset the counts, otherwise a 2nd call does not show anything anymore */
981 for (p = errors; p != NULL; p = p->next) {
982 if (p->count >= (1 << 30))
983 p->count = p->count - (1 << 30);
984 }
985
986
987 any_supp = show_used_suppressions();
988
989 if (any_supp)
990 VG_(umsg)("\n");
991 // reprint this, so users don't have to scroll way up to find
992 // the first printing
993 VG_(umsg)("ERROR SUMMARY: "
994 "%d errors from %d contexts (suppressed: %d from %d)\n",
995 n_errs_found, n_err_contexts, n_errs_suppressed,
996 n_supp_contexts );
997 }
998
VG_(show_last_error)999 void VG_(show_last_error) ( void )
1000 {
1001 if (n_err_contexts == 0) {
1002 VG_(umsg)("No errors yet\n");
1003 return;
1004 }
1005
1006 pp_Error( errors, False/*allow_db_attach*/, False/*xml*/ );
1007 }
1008
1009
1010 /* Show occurrence counts of all errors, in XML form. */
VG_(show_error_counts_as_XML)1011 void VG_(show_error_counts_as_XML) ( void )
1012 {
1013 Error* err;
1014 VG_(printf_xml)("<errorcounts>\n");
1015 for (err = errors; err != NULL; err = err->next) {
1016 if (err->supp != NULL)
1017 continue;
1018 if (err->count <= 0)
1019 continue;
1020 VG_(printf_xml)(" <pair>\n");
1021 VG_(printf_xml)(" <count>%d</count>\n", err->count);
1022 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
1023 VG_(printf_xml)(" </pair>\n");
1024 }
1025 VG_(printf_xml)("</errorcounts>\n");
1026 VG_(printf_xml)("\n");
1027 }
1028
1029
1030 /*------------------------------------------------------------*/
1031 /*--- Suppression parsing ---*/
1032 /*------------------------------------------------------------*/
1033
1034 /* Get the next char from fd into *out_buf. Returns 1 if success,
1035 0 if eof or < 0 if error. */
1036
get_char(Int fd,Char * out_buf)1037 static Int get_char ( Int fd, Char* out_buf )
1038 {
1039 Int r;
1040 static Char buf[256];
1041 static Int buf_size = 0;
1042 static Int buf_used = 0;
1043 vg_assert(buf_size >= 0 && buf_size <= 256);
1044 vg_assert(buf_used >= 0 && buf_used <= buf_size);
1045 if (buf_used == buf_size) {
1046 r = VG_(read)(fd, buf, 256);
1047 if (r < 0) return r; /* read failed */
1048 vg_assert(r >= 0 && r <= 256);
1049 buf_size = r;
1050 buf_used = 0;
1051 }
1052 if (buf_size == 0)
1053 return 0; /* eof */
1054 vg_assert(buf_size >= 0 && buf_size <= 256);
1055 vg_assert(buf_used >= 0 && buf_used < buf_size);
1056 *out_buf = buf[buf_used];
1057 buf_used++;
1058 return 1;
1059 }
1060
VG_(get_line)1061 Bool VG_(get_line) ( Int fd, Char** bufpp, SizeT* nBufp, Int* lineno )
1062 {
1063 Char* buf = *bufpp;
1064 SizeT nBuf = *nBufp;
1065 Char ch;
1066 Int n, i;
1067 while (True) {
1068 /* First, read until a non-blank char appears. */
1069 while (True) {
1070 n = get_char(fd, &ch);
1071 if (n == 1 && !VG_(isspace)(ch)) break;
1072 if (n == 1 && ch == '\n' && lineno)
1073 (*lineno)++;
1074 if (n <= 0) return True;
1075 }
1076
1077 /* Now, read the line into buf. */
1078 i = 0;
1079 buf[i++] = ch; buf[i] = 0;
1080 while (True) {
1081 n = get_char(fd, &ch);
1082 if (n <= 0) return False; /* the next call will return True */
1083 if (ch == '\n' && lineno)
1084 (*lineno)++;
1085 if (ch == '\n') break;
1086 if (i > 0 && i == nBuf-1) {
1087 *nBufp = nBuf = nBuf * 2;
1088 #define RIDICULOUS 100000
1089 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really.
1090 "VG_(get_line): line longer than %d chars, aborting\n",
1091 RIDICULOUS);
1092 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1093 }
1094 buf[i++] = ch; buf[i] = 0;
1095 }
1096 while (i > 1 && VG_(isspace)(buf[i-1])) {
1097 i--; buf[i] = 0;
1098 };
1099
1100 /* VG_(printf)("The line is '%s'\n", buf); */
1101 /* Ok, we have a line. If a non-comment line, return.
1102 If a comment line, start all over again. */
1103 if (buf[0] != '#') return False;
1104 }
1105 }
1106
1107
1108 /* True if s contains no wildcard (?, *) characters. */
is_simple_str(Char * s)1109 static Bool is_simple_str (Char *s)
1110 {
1111 while (*s) {
1112 if (*s == '?' || *s == '*')
1113 return False;
1114 s++;
1115 }
1116 return True;
1117 }
1118
1119 /* buf contains the raw name of a caller, supposedly either
1120 fun:some_function_name or
1121 obj:some_object_name or
1122 ...
1123 Set p->ty and p->name accordingly.
1124 p->name is allocated and set to the string
1125 after the descriptor (fun: or obj:) part.
1126 Returns False if failed.
1127 */
setLocationTy(SuppLoc * p,Char * buf)1128 static Bool setLocationTy ( SuppLoc* p, Char *buf )
1129 {
1130 if (VG_(strncmp)(buf, "fun:", 4) == 0) {
1131 p->name = VG_(arena_strdup)(VG_AR_CORE,
1132 "errormgr.sLTy.1", buf+4);
1133 p->name_is_simple_str = is_simple_str (p->name);
1134 p->ty = FunName;
1135 return True;
1136 }
1137 if (VG_(strncmp)(buf, "obj:", 4) == 0) {
1138 p->name = VG_(arena_strdup)(VG_AR_CORE,
1139 "errormgr.sLTy.2", buf+4);
1140 p->name_is_simple_str = is_simple_str (p->name);
1141 p->ty = ObjName;
1142 return True;
1143 }
1144 if (VG_(strcmp)(buf, "...") == 0) {
1145 p->name = NULL;
1146 p->name_is_simple_str = False;
1147 p->ty = DotDotDot;
1148 return True;
1149 }
1150 VG_(printf)("location should be \"...\", or should start "
1151 "with \"fun:\" or \"obj:\"\n");
1152 return False;
1153 }
1154
1155
1156 /* Look for "tool" in a string like "tool1,tool2,tool3" */
tool_name_present(Char * name,Char * names)1157 static Bool tool_name_present(Char *name, Char *names)
1158 {
1159 Bool found;
1160 Char *s = NULL; /* Shut gcc up */
1161 Int len = VG_(strlen)(name);
1162
1163 found = (NULL != (s = VG_(strstr)(names, name)) &&
1164 (s == names || *(s-1) == ',') &&
1165 (*(s+len) == ',' || *(s+len) == '\0')
1166 );
1167
1168 return found;
1169 }
1170
1171 /* Read suppressions from the file specified in VG_(clo_suppressions)
1172 and place them in the suppressions list. If there's any difficulty
1173 doing this, just give up -- there's no point in trying to recover.
1174 */
load_one_suppressions_file(Char * filename)1175 static void load_one_suppressions_file ( Char* filename )
1176 {
1177 SysRes sres;
1178 Int fd, i, j, lineno = 0;
1179 Bool eof;
1180 SizeT nBuf = 200;
1181 Char* buf = VG_(malloc)("errormgr.losf.1", nBuf);
1182 Char* tool_names;
1183 Char* supp_name;
1184 Char* err_str = NULL;
1185 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
1186
1187 // Check it's not a directory.
1188 if (VG_(is_dir)( filename )) {
1189 if (VG_(clo_xml))
1190 VG_(printf_xml)("</valgrindoutput>\n");
1191 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
1192 VG_(exit)(1);
1193 }
1194
1195 // Open the suppression file.
1196 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
1197 if (sr_isError(sres)) {
1198 if (VG_(clo_xml))
1199 VG_(printf_xml)("</valgrindoutput>\n");
1200 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
1201 VG_(exit)(1);
1202 }
1203 fd = sr_Res(sres);
1204
1205 # define BOMB(S) { err_str = S; goto syntax_error; }
1206
1207 while (True) {
1208 /* Assign and initialise the two suppression halves (core and tool) */
1209 Supp* supp;
1210 supp = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
1211 sizeof(Supp));
1212 supp->count = 0;
1213
1214 // Initialise temporary reading-in buffer.
1215 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
1216 tmp_callers[i].ty = NoName;
1217 tmp_callers[i].name_is_simple_str = False;
1218 tmp_callers[i].name = NULL;
1219 }
1220
1221 supp->string = supp->extra = NULL;
1222
1223 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1224 if (eof) {
1225 VG_(arena_free)(VG_AR_CORE, supp);
1226 break;
1227 }
1228
1229 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
1230
1231 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1232
1233 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1234
1235 supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
1236
1237 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1238
1239 if (eof) BOMB("unexpected end-of-file");
1240
1241 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1242 i = 0;
1243 while (True) {
1244 if (buf[i] == ':') break;
1245 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1246 i++;
1247 }
1248 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1249
1250 tool_names = & buf[0];
1251 supp_name = & buf[i+1];
1252
1253 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
1254 {
1255 // A core suppression
1256 //(example code, see comment on CoreSuppKind above)
1257 //if (VG_STREQ(supp_name, "Thread"))
1258 // supp->skind = ThreadSupp;
1259 //else
1260 BOMB("unknown core suppression type");
1261 }
1262 else if (VG_(needs).tool_errors &&
1263 tool_name_present(VG_(details).name, tool_names))
1264 {
1265 // A tool suppression
1266 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
1267 /* Do nothing, function fills in supp->skind */
1268 } else {
1269 BOMB("unknown tool suppression type");
1270 }
1271 }
1272 else {
1273 // Ignore rest of suppression
1274 while (True) {
1275 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1276 if (eof) BOMB("unexpected end-of-file");
1277 if (VG_STREQ(buf, "}"))
1278 break;
1279 }
1280 VG_(arena_free)(VG_AR_CORE, supp->sname);
1281 VG_(arena_free)(VG_AR_CORE, supp);
1282 continue;
1283 }
1284
1285 if (VG_(needs).tool_errors &&
1286 !VG_TDICT_CALL(tool_read_extra_suppression_info,
1287 fd, &buf, &nBuf, supp))
1288 {
1289 BOMB("bad or missing extra suppression info");
1290 }
1291
1292 /* the main frame-descriptor reading loop */
1293 i = 0;
1294 while (True) {
1295 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1296 if (eof)
1297 BOMB("unexpected end-of-file");
1298 if (VG_STREQ(buf, "}")) {
1299 if (i > 0) {
1300 break;
1301 } else {
1302 BOMB("missing stack trace");
1303 }
1304 }
1305 if (i == VG_MAX_SUPP_CALLERS)
1306 BOMB("too many callers in stack trace");
1307 if (i > 0 && i >= VG_(clo_backtrace_size))
1308 break;
1309 if (!setLocationTy(&(tmp_callers[i]), buf))
1310 BOMB("location should be \"...\", or should start "
1311 "with \"fun:\" or \"obj:\"");
1312 i++;
1313 }
1314
1315 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1316 // lines and grab the '}'.
1317 if (!VG_STREQ(buf, "}")) {
1318 do {
1319 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1320 } while (!eof && !VG_STREQ(buf, "}"));
1321 }
1322
1323 // Reject entries which are entirely composed of frame
1324 // level wildcards.
1325 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1326 for (j = 0; j < i; j++) {
1327 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
1328 break;
1329 vg_assert(tmp_callers[j].ty == DotDotDot);
1330 }
1331 vg_assert(j >= 0 && j <= i);
1332 if (j == i) {
1333 // we didn't find any non-"..." entries
1334 BOMB("suppression must contain at least one location "
1335 "line which is not \"...\"");
1336 }
1337
1338 // Copy tmp_callers[] into supp->callers[]
1339 supp->n_callers = i;
1340 supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
1341 i*sizeof(SuppLoc));
1342 for (i = 0; i < supp->n_callers; i++) {
1343 supp->callers[i] = tmp_callers[i];
1344 }
1345
1346 supp->next = suppressions;
1347 suppressions = supp;
1348 }
1349 VG_(free)(buf);
1350 VG_(close)(fd);
1351 return;
1352
1353 syntax_error:
1354 if (VG_(clo_xml))
1355 VG_(printf_xml)("</valgrindoutput>\n");
1356 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
1357 filename, lineno );
1358 VG_(umsg)(" %s\n", err_str );
1359
1360 VG_(close)(fd);
1361 VG_(umsg)("exiting now.\n");
1362 VG_(exit)(1);
1363
1364 # undef BOMB
1365 }
1366
1367
VG_(load_suppressions)1368 void VG_(load_suppressions) ( void )
1369 {
1370 Int i;
1371 suppressions = NULL;
1372 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1373 if (VG_(clo_verbosity) > 1) {
1374 VG_(dmsg)("Reading suppressions file: %s\n",
1375 VG_(clo_suppressions)[i] );
1376 }
1377 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1378 }
1379 }
1380
1381
1382 /*------------------------------------------------------------*/
1383 /*--- Matching errors to suppressions ---*/
1384 /*------------------------------------------------------------*/
1385
1386 /* Parameterising functions for the use of VG_(generic_match) in
1387 suppression-vs-error matching. The suppression frames (SuppLoc)
1388 play the role of 'pattern'-element, and the error frames (IPs,
1389 hence simply Addrs) play the role of 'input'. In short then, we're
1390 matching a sequence of Addrs against a pattern composed of a
1391 sequence of SuppLocs.
1392 */
supploc_IsStar(void * supplocV)1393 static Bool supploc_IsStar ( void* supplocV )
1394 {
1395 SuppLoc* supploc = (SuppLoc*)supplocV;
1396 return supploc->ty == DotDotDot;
1397 }
1398
supploc_IsQuery(void * supplocV)1399 static Bool supploc_IsQuery ( void* supplocV )
1400 {
1401 return False; /* there's no '?' equivalent in the supp syntax */
1402 }
1403
1404 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1405 needed to match an error with the suppression patterns.
1406 The matching between an IP and a suppression pattern is done either
1407 with the IP function name or with the IP object name.
1408 First time the fun or obj name is needed for an IP member
1409 of a stack trace, it will be computed and stored in names.
1410 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1411 allocations and the nr of debuginfo search. */
1412 typedef
1413 struct {
1414 StackTrace ips; // stack trace we are lazily completing.
1415 UWord n_ips; // nr of elements in ips.
1416
1417 Int* fun_offsets;
1418 // fun_offsets[i] is the offset in names where the
1419 // function name for ips[i] is located.
1420 // An offset -1 means the function name is not yet completed.
1421 Int* obj_offsets;
1422 // Similarly, obj_offsets[i] gives the offset for the
1423 // object name for ips[i] (-1 meaning object name not yet completed).
1424
1425 // All function names and object names will be concatenated
1426 // in names. names is reallocated on demand.
1427 Char *names;
1428 Int names_szB; // size of names.
1429 Int names_free; // offset first free Char in names.
1430 }
1431 IPtoFunOrObjCompleter;
1432
1433 // free the memory in ip2fo.
clearIPtoFunOrObjCompleter(IPtoFunOrObjCompleter * ip2fo)1434 static void clearIPtoFunOrObjCompleter
1435 (IPtoFunOrObjCompleter* ip2fo)
1436 {
1437 if (ip2fo->fun_offsets) VG_(free)(ip2fo->fun_offsets);
1438 if (ip2fo->obj_offsets) VG_(free)(ip2fo->obj_offsets);
1439 if (ip2fo->names) VG_(free)(ip2fo->names);
1440 }
1441
1442 /* foComplete returns the function name or object name for IP.
1443 If needFun, returns the function name for IP
1444 else returns the object name for IP.
1445 The function name or object name will be computed and added in
1446 names if not yet done.
1447 IP must be equal to focompl->ipc[ixIP]. */
foComplete(IPtoFunOrObjCompleter * ip2fo,Addr IP,Int ixIP,Bool needFun)1448 static Char* foComplete(IPtoFunOrObjCompleter* ip2fo,
1449 Addr IP, Int ixIP, Bool needFun)
1450 {
1451 vg_assert (ixIP < ip2fo->n_ips);
1452 vg_assert (IP == ip2fo->ips[ixIP]);
1453
1454 // ptr to the offset array for function offsets (if needFun)
1455 // or object offsets (if !needFun).
1456 Int** offsets;
1457 if (needFun)
1458 offsets = &ip2fo->fun_offsets;
1459 else
1460 offsets = &ip2fo->obj_offsets;
1461
1462 // Allocate offsets if not yet done.
1463 if (!*offsets) {
1464 Int i;
1465 *offsets =
1466 VG_(malloc)("foComplete",
1467 ip2fo->n_ips * sizeof(Int));
1468 for (i = 0; i < ip2fo->n_ips; i++)
1469 (*offsets)[i] = -1;
1470 }
1471
1472 // Complete Fun name or Obj name for IP if not yet done.
1473 if ((*offsets)[ixIP] == -1) {
1474 /* Ensure we have ERRTXT_LEN characters available in names */
1475 if (ip2fo->names_szB
1476 < ip2fo->names_free + ERRTXT_LEN) {
1477 ip2fo->names
1478 = VG_(realloc)("foc_names",
1479 ip2fo->names,
1480 ip2fo->names_szB + ERRTXT_LEN);
1481 ip2fo->names_szB += ERRTXT_LEN;
1482 }
1483 Char* caller_name = ip2fo->names + ip2fo->names_free;
1484 (*offsets)[ixIP] = ip2fo->names_free;
1485 if (needFun) {
1486 /* Get the function name into 'caller_name', or "???"
1487 if unknown. */
1488 // Nb: C++-mangled names are used in suppressions. Do, though,
1489 // Z-demangle them, since otherwise it's possible to wind
1490 // up comparing "malloc" in the suppression against
1491 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1492 // two of them need to be made to match.
1493 if (!VG_(get_fnname_no_cxx_demangle)(IP, caller_name, ERRTXT_LEN))
1494 VG_(strcpy)(caller_name, "???");
1495 } else {
1496 /* Get the object name into 'caller_name', or "???"
1497 if unknown. */
1498 if (!VG_(get_objname)(IP, caller_name, ERRTXT_LEN))
1499 VG_(strcpy)(caller_name, "???");
1500 }
1501 ip2fo->names_free += VG_(strlen)(caller_name) + 1;
1502 }
1503
1504 return ip2fo->names + (*offsets)[ixIP];
1505 }
1506
supp_pattEQinp(void * supplocV,void * addrV,void * inputCompleter,UWord ixAddrV)1507 static Bool supp_pattEQinp ( void* supplocV, void* addrV,
1508 void* inputCompleter, UWord ixAddrV )
1509 {
1510 SuppLoc* supploc = (SuppLoc*)supplocV; /* PATTERN */
1511 Addr ip = *(Addr*)addrV; /* INPUT */
1512 IPtoFunOrObjCompleter* ip2fo
1513 = (IPtoFunOrObjCompleter*)inputCompleter;
1514 Char* funobj_name; // Fun or Obj name.
1515
1516 /* So, does this IP address match this suppression-line? */
1517 switch (supploc->ty) {
1518 case DotDotDot:
1519 /* supp_pattEQinp is a callback from VG_(generic_match). As
1520 per the spec thereof (see include/pub_tool_seqmatch.h), we
1521 should never get called with a pattern value for which the
1522 _IsStar or _IsQuery function would return True. Hence
1523 this can't happen. */
1524 vg_assert(0);
1525 case ObjName:
1526 funobj_name = foComplete(ip2fo, ip, ixAddrV, False /*needFun*/);
1527 break;
1528 case FunName:
1529 funobj_name = foComplete(ip2fo, ip, ixAddrV, True /*needFun*/);
1530 break;
1531 default:
1532 vg_assert(0);
1533 }
1534
1535 /* So now we have the function or object name in funobj_name, and
1536 the pattern (at the character level) to match against is in
1537 supploc->name. Hence (and leading to a re-entrant call of
1538 VG_(generic_match) if there is a wildcard character): */
1539 if (supploc->name_is_simple_str)
1540 return VG_(strcmp) (supploc->name, funobj_name) == 0;
1541 else
1542 return VG_(string_match)(supploc->name, funobj_name);
1543 }
1544
1545 /////////////////////////////////////////////////////
1546
supp_matches_callers(IPtoFunOrObjCompleter * ip2fo,Supp * su)1547 static Bool supp_matches_callers(IPtoFunOrObjCompleter* ip2fo, Supp* su)
1548 {
1549 /* Unwrap the args and set up the correct parameterisation of
1550 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1551 supp_pattEQinp. */
1552 /* note, StackTrace ip2fo->ips === Addr* */
1553 SuppLoc* supps = su->callers;
1554 UWord n_supps = su->n_callers;
1555 UWord szbPatt = sizeof(SuppLoc);
1556 UWord szbInput = sizeof(Addr);
1557 Bool matchAll = False; /* we just want to match a prefix */
1558 return
1559 VG_(generic_match)(
1560 matchAll,
1561 /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
1562 /*INPUT*/ip2fo->ips, szbInput, ip2fo->n_ips, 0/*initial Ix*/,
1563 supploc_IsStar, supploc_IsQuery, supp_pattEQinp,
1564 ip2fo
1565 );
1566 }
1567
1568 /////////////////////////////////////////////////////
1569
1570 static
supp_matches_error(Supp * su,Error * err)1571 Bool supp_matches_error(Supp* su, Error* err)
1572 {
1573 switch (su->skind) {
1574 //(example code, see comment on CoreSuppKind above)
1575 //case ThreadSupp:
1576 // return (err->ekind == ThreadErr);
1577 default:
1578 if (VG_(needs).tool_errors) {
1579 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
1580 } else {
1581 VG_(printf)(
1582 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
1583 "probably needs to be set.\n",
1584 err->ekind);
1585 VG_(tool_panic)("unhandled suppression type");
1586 }
1587 }
1588 }
1589
1590 /////////////////////////////////////////////////////
1591
1592 /* Does an error context match a suppression? ie is this a suppressible
1593 error? If so, return a pointer to the Supp record, otherwise NULL.
1594 Tries to minimise the number of symbol searches since they are expensive.
1595 */
is_suppressible_error(Error * err)1596 static Supp* is_suppressible_error ( Error* err )
1597 {
1598 Supp* su;
1599 Supp* su_prev;
1600
1601 IPtoFunOrObjCompleter ip2fo;
1602 /* Conceptually, ip2fo contains an array of function names and an array of
1603 object names, corresponding to the array of IP of err->where.
1604 These names are just computed 'on demand' (so once maximum),
1605 then stored (efficiently, avoiding too many allocs) in ip2fo to be re-usable
1606 for the matching of the same IP with the next suppression pattern.
1607
1608 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
1609 of its arguments. It will then pass it to the function
1610 supp_pattEQinp which will then lazily complete the IP function name or
1611 object name inside ip2fo. Next time the fun or obj name for the same
1612 IP is needed (i.e. for the matching with the next suppr pattern), then
1613 the fun or obj name will not be searched again in the debug info. */
1614
1615 /* stats gathering */
1616 em_supplist_searches++;
1617
1618 /* Prepare the lazy input completer. */
1619 ip2fo.ips = VG_(get_ExeContext_StackTrace)(err->where);
1620 ip2fo.n_ips = VG_(get_ExeContext_n_ips)(err->where);
1621 ip2fo.fun_offsets = NULL;
1622 ip2fo.obj_offsets = NULL;
1623 ip2fo.names = NULL;
1624 ip2fo.names_szB = 0;
1625 ip2fo.names_free = 0;
1626
1627 /* See if the error context matches any suppression. */
1628 su_prev = NULL;
1629 for (su = suppressions; su != NULL; su = su->next) {
1630 em_supplist_cmps++;
1631 if (supp_matches_error(su, err)
1632 && supp_matches_callers(&ip2fo, su)) {
1633 /* got a match. Move this entry to the head of the list
1634 in the hope of making future searches cheaper. */
1635 if (su_prev) {
1636 vg_assert(su_prev->next == su);
1637 su_prev->next = su->next;
1638 su->next = suppressions;
1639 suppressions = su;
1640 }
1641 clearIPtoFunOrObjCompleter(&ip2fo);
1642 return su;
1643 }
1644 su_prev = su;
1645 }
1646 clearIPtoFunOrObjCompleter(&ip2fo);
1647 return NULL; /* no matches */
1648 }
1649
1650 /* Show accumulated error-list and suppression-list search stats.
1651 */
VG_(print_errormgr_stats)1652 void VG_(print_errormgr_stats) ( void )
1653 {
1654 VG_(dmsg)(
1655 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
1656 em_supplist_searches, em_supplist_cmps
1657 );
1658 VG_(dmsg)(
1659 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
1660 em_errlist_searches, em_errlist_cmps
1661 );
1662 }
1663
1664 /*--------------------------------------------------------------------*/
1665 /*--- end ---*/
1666 /*--------------------------------------------------------------------*/
1667