FreeBSD Helgrind: turn off check for locks held on exit for FreeBSD 14.2
[valgrind.git] / coregrind / m_errormgr.c
blob4bbcea02474cca4656a61cba92d3ddc2132adca8
2 /*--------------------------------------------------------------------*/
3 /*--- Management of error messages. m_errormgr.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2017 Julian Seward
11 jseward@acm.org
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.
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.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #include "pub_core_basics.h"
30 #include "pub_core_vki.h"
31 #include "pub_core_threadstate.h" // For VG_N_THREADS
32 #include "pub_core_debuginfo.h"
33 #include "pub_core_debuglog.h"
34 #include "pub_core_errormgr.h"
35 #include "pub_core_execontext.h"
36 #include "pub_core_gdbserver.h"
37 #include "pub_core_libcbase.h"
38 #include "pub_core_libcassert.h"
39 #include "pub_core_libcfile.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_libcproc.h" // For VG_(getpid)()
42 #include "pub_core_seqmatch.h"
43 #include "pub_core_mallocfree.h"
44 #include "pub_core_options.h"
45 #include "pub_core_stacktrace.h"
46 #include "pub_core_tooliface.h"
47 #include "pub_core_translate.h" // for VG_(translate)()
48 #include "pub_core_xarray.h" // VG_(xaprintf) et al
49 #include "pub_core_syswrap.h" // for core callbacks (Fds)
51 #define DEBUG_ERRORMGR 0 // set to 1 for heavyweight tracing
53 /*------------------------------------------------------------*/
54 /*--- Globals ---*/
55 /*------------------------------------------------------------*/
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
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
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
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;
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 static Bool load_suppressions_called = False;
80 /* Running count of unsuppressed errors detected. */
81 static UInt n_errs_found = 0;
83 /* Running count of suppressed errors detected. */
84 static UInt n_errs_suppressed = 0;
86 /* Running count of errors shown. */
87 static UInt n_errs_shown = 0;
89 /* Running count of unsuppressed error contexts. */
90 static UInt n_err_contexts = 0;
92 /* Running count of suppressed error contexts. */
93 static UInt n_supp_contexts = 0;
96 /* forwards ... */
97 static Supp* is_suppressible_error ( const Error* err );
99 static Bool core_eq_Error (VgRes, const Error*, const Error*);
100 static void core_before_pp_Error (const Error*);
101 static void core_pp_Error (const Error*);
102 static UInt core_update_extra (const Error*);
104 static const HChar *core_get_error_name(const Error*);
105 static SizeT core_get_extra_suppression_info(const Error*,HChar*,Int);
107 static ThreadId last_tid_printed = 1;
109 /* Stats: number of searches of the error list initiated. */
110 static UWord em_errlist_searches = 0;
112 /* Stats: number of comparisons done during error list
113 searching. */
114 static UWord em_errlist_cmps = 0;
116 /* Stats: number of searches of the suppression list initiated. */
117 static UWord em_supplist_searches = 0;
119 /* Stats: number of comparisons done during suppression list
120 searching. */
121 static UWord em_supplist_cmps = 0;
123 /*------------------------------------------------------------*/
124 /*--- Error type ---*/
125 /*------------------------------------------------------------*/
127 /* Errors. Extensible (via the 'extra' field). Tools can use a normal
128 enum (with element values in the normal range (0..)) for 'ekind'.
129 Functions for getting/setting the tool-relevant fields are in
130 include/pub_tool_errormgr.h.
132 When errors are found and recorded with VG_(maybe_record_error)(), all
133 the tool must do is pass in the four parameters; core will
134 allocate/initialise the error record.
136 struct _Error {
137 struct _Error* next;
138 // Unique tag. This gives the error a unique identity (handle) by
139 // which it can be referred to afterwords. Currently only used for
140 // XML printing.
141 UInt unique;
142 Int count;
143 // NULL if unsuppressed; or ptr to suppression record.
144 Supp* supp;
146 // The tool-specific part
147 ThreadId tid; // Initialised by core
148 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
149 ExeContext* where; // Initialised by core
150 Addr addr; // Used frequently
151 const HChar* string; // Used frequently
152 void* extra; // For any tool-specific extras
156 ExeContext* VG_(get_error_where) ( const Error* err )
158 return err->where;
161 ErrorKind VG_(get_error_kind) ( const Error* err )
163 return err->ekind;
166 Addr VG_(get_error_address) ( const Error* err )
168 return err->addr;
171 const HChar* VG_(get_error_string) ( const Error* err )
173 return err->string;
176 void* VG_(get_error_extra) ( const Error* err )
178 return err->extra;
181 UInt VG_(get_n_errs_found)( void )
183 return n_errs_found;
186 UInt VG_(get_n_errs_shown)( void )
188 return n_errs_shown;
191 Bool VG_(found_or_suppressed_errs)( void )
193 return errors != NULL;
196 /*------------------------------------------------------------*/
197 /*--- Suppression type ---*/
198 /*------------------------------------------------------------*/
200 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools
201 * effectively extend it by defining their own enums in the (0..) range. */
202 typedef
203 enum {
204 // Nb: thread errors are a relic of the time when Valgrind's core
205 // could detect them. This example is left commented-out as an
206 // example should new core errors ever be added.
207 ThreadSupp = -1, /* Matches ThreadErr */
208 FdBadCloseSupp = -2,
209 FdNotClosedSupp = -3
211 CoreSuppKind;
213 /* Max number of callers for context in a suppression is
214 VG_DEEPEST_BACKTRACE. */
216 /* For each caller specified for a suppression, record the nature of
217 the caller name. Not of interest to tools. */
218 typedef
219 enum {
220 NoName, /* Error case */
221 ObjName, /* Name is of an shared object file. */
222 FunName, /* Name is of a function. */
223 DotDotDot, /* Frame-level wildcard */
224 SrcName /* Name is of a src file. */
226 SuppLocTy;
228 typedef
229 struct {
230 SuppLocTy ty;
231 Bool name_is_simple_str; /* True if name is a string without
232 '?' and '*' wildcard characters. */
233 HChar* name; /* NULL for NoName and DotDotDot */
234 UInt lineno; /* Valid for SrcName. */
236 SuppLoc;
238 /* Suppressions. Tools can get/set tool-relevant parts with functions
239 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
240 Tools can use a normal enum (with element values in the normal range
241 (0..)) for 'skind'. */
242 struct _Supp {
243 struct _Supp* next;
244 HChar* sname; // The name by which the suppression is referred to.
245 Int count; // The number of times this error has been suppressed.
247 // Index in VG_(clo_suppressions) giving filename from which suppression
248 // was read, and the lineno in this file where sname was read.
249 Int clo_suppressions_i;
250 Int sname_lineno;
252 // Length of 'callers'
253 Int n_callers;
254 // Array of callers, for matching stack traces. First one (name of fn
255 // where err occurs) is mandatory; rest are optional.
256 SuppLoc* callers;
258 /* The tool-specific part */
259 SuppKind skind; // What kind of suppression. Must use the range (0..).
260 HChar* string; // String -- use is optional. NULL by default.
261 void* extra; // Anything else -- use is optional. NULL by default.
264 SuppKind VG_(get_supp_kind) ( const Supp* su )
266 return su->skind;
269 HChar* VG_(get_supp_string) ( const Supp* su )
271 return su->string;
274 void* VG_(get_supp_extra) ( const Supp* su )
276 return su->extra;
280 void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
282 su->skind = skind;
285 void VG_(set_supp_string) ( Supp* su, HChar* string )
287 su->string = string;
290 void VG_(set_supp_extra) ( Supp* su, void* extra )
292 su->extra = extra;
296 /*------------------------------------------------------------*/
297 /*--- Helper fns ---*/
298 /*------------------------------------------------------------*/
300 // Only show core warnings if the tool wants to, we're not running with -q,
301 // and were not outputting XML.
302 Bool VG_(showing_core_warnings)(void)
304 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
307 /* Compare errors, to detect duplicates.
309 static Bool eq_Error ( VgRes res, const Error* e1, const Error* e2 )
311 if (e1->ekind != e2->ekind)
312 return False;
313 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
314 return False;
316 if (e1->ekind >= 0) {
317 if (VG_(needs).tool_errors) {
318 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
319 } else {
320 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
321 "probably needs to be set.\n",
322 (UInt)e1->ekind);
323 VG_(core_panic)("unhandled error type");
325 } else {
326 return core_eq_Error(res, e1, e2);
331 /* Helper functions for suppression generation: print a single line of
332 a suppression pseudo-stack-trace, either in XML or text mode. It's
333 important that the behaviour of these two functions exactly
334 corresponds.
336 #define ERRTXT_LEN 4096
338 static void printSuppForIp_XML(UInt n, DiEpoch ep, Addr ip, void* uu_opaque)
340 const HChar *buf;
341 InlIPCursor* iipc = VG_(new_IIPC)(ep, ip);
342 do {
343 if ( VG_(get_fnname_no_cxx_demangle) (ep, ip, &buf, iipc) ) {
344 VG_(printf_xml)(" <sframe> <fun>%pS</fun> </sframe>\n", buf);
345 } else
346 if ( VG_(get_objname)(ep, ip, &buf) ) {
347 VG_(printf_xml)(" <sframe> <obj>%pS</obj> </sframe>\n", buf);
348 } else {
349 VG_(printf_xml)(" <sframe> <obj>*</obj> </sframe>\n");
351 } while (VG_(next_IIPC)(iipc));
352 VG_(delete_IIPC)(iipc);
355 static void printSuppForIp_nonXML(UInt n, DiEpoch ep, Addr ip, void* textV)
357 const HChar *buf;
358 XArray* /* of HChar */ text = (XArray*)textV;
359 InlIPCursor* iipc = VG_(new_IIPC)(ep, ip);
360 do {
361 if ( VG_(get_fnname_no_cxx_demangle) (ep, ip, &buf, iipc) ) {
362 VG_(xaprintf)(text, " fun:%s\n", buf);
363 } else
364 if ( VG_(get_objname)(ep, ip, &buf) ) {
365 VG_(xaprintf)(text, " obj:%s\n", buf);
366 } else {
367 VG_(xaprintf)(text, " obj:*\n");
369 } while (VG_(next_IIPC)(iipc));
370 VG_(delete_IIPC)(iipc);
373 /* Generate a suppression for an error, either in text or XML mode.
375 static void gen_suppression(const Error* err)
377 const HChar* name;
378 const HChar* component;
379 ExeContext* ec;
380 XArray* /* HChar */ text;
382 const HChar* dummy_name = "insert_a_suppression_name_here";
384 vg_assert(err);
386 ec = VG_(get_error_where)(err);
387 if (ec == NULL) {
388 /* This can happen with core errors for --track-fds=all
389 with "leaked" inherited file descriptors, which aren't
390 created in the current program. */
391 VG_(umsg)("(No origin, error cannot be suppressed)\n");
392 return;
395 if (err->ekind >= 0) {
396 name = VG_TDICT_CALL(tool_get_error_name, err);
397 if (NULL == name) {
398 VG_(umsg)("(%s does not allow error to be suppressed)\n",
399 VG_(details).name);
400 return;
402 } else {
403 name = core_get_error_name(err);
404 if (NULL == name) {
405 VG_(umsg)("(core error cannot be suppressed)\n");
406 return;
410 /* In XML mode, we also need to print the plain text version of the
411 suppresion in a CDATA section. What that really means is, we
412 need to generate the plaintext version both in XML and text
413 mode. So generate it into TEXT. */
414 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
415 VG_(free), sizeof(HChar) );
417 /* Ok. Generate the plain text version into TEXT. */
418 if (err->ekind >= 0)
419 component = VG_(details).name;
420 else
421 component = "CoreError";
422 VG_(xaprintf)(text, "{\n");
423 VG_(xaprintf)(text, " <%s>\n", dummy_name);
424 VG_(xaprintf)(text, " %s:%s\n", component, name);
426 HChar *xtra = NULL;
427 SizeT xtra_size = 0;
428 SizeT num_written;
430 do {
431 xtra_size += 256;
432 xtra = VG_(realloc)("errormgr.gen_suppression.2", xtra,xtra_size);
433 if (err->ekind >= 0)
434 num_written = VG_TDICT_CALL(tool_get_extra_suppression_info,
435 err, xtra, xtra_size);
436 else
437 num_written = core_get_extra_suppression_info(err, xtra, xtra_size);
438 } while (num_written == xtra_size); // resize buffer and retry
440 // Ensure buffer is properly terminated
441 vg_assert(xtra[num_written] == '\0');
443 if (num_written)
444 VG_(xaprintf)(text, " %s\n", xtra);
446 // Print stack trace elements
447 UInt n_ips = VG_(get_ExeContext_n_ips)(ec);
448 vg_assert(n_ips > 0);
449 vg_assert(n_ips <= VG_DEEPEST_BACKTRACE);
450 VG_(apply_StackTrace)(printSuppForIp_nonXML,
451 text, VG_(get_ExeContext_epoch)(ec),
452 VG_(get_ExeContext_StackTrace)(ec),
453 n_ips);
455 VG_(xaprintf)(text, "}\n");
456 // zero terminate
457 VG_(xaprintf)(text, "%c", (HChar)0 );
458 // VG_(printf) of text
460 /* And now display it. */
461 if (! VG_(clo_xml) ) {
463 // the simple case
464 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
466 } else {
468 /* Now we have to print the XML directly. No need to go to the
469 effort of stuffing it in an XArray, since we won't need it
470 again. */
471 VG_(printf_xml)(" <suppression>\n");
472 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name);
473 VG_(printf_xml)(
474 " <skind>%pS:%pS</skind>\n", component, name);
475 if (num_written)
476 VG_(printf_xml)(" <skaux>%pS</skaux>\n", xtra);
478 // Print stack trace elements
479 VG_(apply_StackTrace)(printSuppForIp_XML,
480 NULL, VG_(get_ExeContext_epoch)(ec),
481 VG_(get_ExeContext_StackTrace)(ec),
482 VG_(get_ExeContext_n_ips)(ec));
484 // And now the cdata bit
485 // XXX FIXME! properly handle the case where the raw text
486 // itself contains "]]>", as specified in Protocol 4.
487 VG_(printf_xml)(" <rawtext>\n");
488 VG_(printf_xml)("<![CDATA[\n");
489 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
490 VG_(printf_xml)("]]>\n");
491 VG_(printf_xml)(" </rawtext>\n");
492 VG_(printf_xml)(" </suppression>\n");
496 VG_(deleteXA)(text);
497 VG_(free)(xtra);
501 /* Figure out if we want to perform a given action for this error,
502 possibly by asking the user.
504 Bool VG_(is_action_requested) ( const HChar* action, Bool* clo )
506 HChar ch, ch2;
507 Int res;
509 /* First off, we shouldn't be asking the user anything if
510 we're in XML mode. */
511 if (VG_(clo_xml))
512 return False; /* That's a Nein, oder Nay as they say down here in B-W */
514 if (*clo == False)
515 return False;
517 VG_(umsg)("\n");
519 again:
520 VG_(printf)(
521 "==%d== "
522 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
523 VG_(getpid)(), action
526 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
527 if (res != 1) goto ioerror;
528 /* res == 1 */
529 if (ch == '\n') return False;
530 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
531 && ch != 'C' && ch != 'c') goto again;
533 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
534 if (res != 1) goto ioerror;
535 if (ch2 != '\n') goto again;
537 /* No, don't want to do action. */
538 if (ch == 'n' || ch == 'N') return False;
539 /* Yes, want to do action. */
540 if (ch == 'y' || ch == 'Y') return True;
541 /* No, don't want to do action, and don't ask again either. */
542 vg_assert(ch == 'c' || ch == 'C');
544 ioerror:
545 *clo = False;
546 return False;
550 /* Do actions on error, that is, immediately after an error is printed.
551 These are:
552 * possibly, call the GDB server
553 * possibly, generate a suppression.
555 static
556 void do_actions_on_error(const Error* err, Bool allow_db_attach, Bool count_error)
558 Bool still_noisy = True;
560 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
561 if (VG_(clo_vgdb) != Vg_VgdbNo
562 && allow_db_attach
563 && VG_(clo_vgdb_error) <= n_errs_shown) {
564 if (!(VG_(clo_launched_with_multi)))
565 VG_(umsg)("(action on error) vgdb me ... \n");
566 VG_(gdbserver)( err->tid );
567 if (!(VG_(clo_launched_with_multi)))
568 VG_(umsg)("Continuing ...\n");
571 /* Or maybe we want to generate the error's suppression? */
572 if (VG_(clo_gen_suppressions) == 2
573 || (VG_(clo_gen_suppressions) == 1
574 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
576 gen_suppression(err);
578 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
579 VG_(clo_gen_suppressions) = 0;
581 if (count_error && VG_(clo_exit_on_first_error)) {
582 if (VG_(clo_xml))
583 VG_(printf_xml)("</valgrindoutput>\n");
584 VG_(umsg)("\n");
585 VG_(umsg)("Exit program on first error (--exit-on-first-error=yes)\n");
586 VG_(client_exit)( VG_(clo_error_exitcode) );
591 /* Prints an error. Not entirely simple because of the differences
592 between XML and text mode output.
594 In XML mode:
596 * calls the tool's pre-show method, so the tool can create any
597 preamble ahead of the message, if it wants.
599 * prints the opening tag, and the <unique> and <tid> fields
601 * prints the tool-specific parts of the message
603 * if suppression generation is required, a suppression
605 * the closing tag
607 In text mode:
609 * calls the tool's pre-show method, so the tool can create any
610 preamble ahead of the message, if it wants.
612 * prints the tool-specific parts of the message
614 In both modes:
616 * calls do_actions_on_error. This optionally does a gdbserver call
617 and optionally prints a suppression; both of these may require user input.
619 static void pp_Error ( const Error* err, Bool allow_db_attach, Bool xml, Bool count_error )
621 /* If this fails, you probably specified your tool's method
622 dictionary incorrectly. */
623 vg_assert(VG_(needs).tool_errors || err->ekind < 0 /* core errors */);
625 if (xml) {
627 /* Ensure that suppression generation is either completely
628 enabled or completely disabled; either way, we won't require
629 any user input. m_main.process_cmd_line_options should
630 ensure the asserted condition holds. */
631 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
632 || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
634 /* Pre-show it to the tool */
635 if (err->ekind >= 0)
636 VG_TDICT_CALL( tool_before_pp_Error, err );
637 else
638 core_before_pp_Error (err);
640 /* standard preamble */
641 VG_(printf_xml)("<error>\n");
642 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
643 VG_(printf_xml)(" <tid>%u</tid>\n", err->tid);
644 ThreadState* tst = VG_(get_ThreadState)(err->tid);
645 if (tst->thread_name) {
646 VG_(printf_xml)(" <threadname>%s</threadname>\n", tst->thread_name);
649 /* actually print it */
650 if (err->ekind >= 0)
651 VG_TDICT_CALL( tool_pp_Error, err );
652 else
653 core_pp_Error (err);
655 if (VG_(clo_gen_suppressions) > 0)
656 gen_suppression(err);
658 /* postamble */
659 VG_(printf_xml)("</error>\n");
660 VG_(printf_xml)("\n");
662 } else {
664 if (VG_(clo_error_markers)[0])
665 VG_(umsg)("%s\n", VG_(clo_error_markers)[0]);
666 if (err->ekind >= 0)
667 VG_TDICT_CALL( tool_before_pp_Error, err );
668 else
669 core_before_pp_Error(err);
671 if (VG_(tdict).tool_show_ThreadIDs_for_errors
672 && err->tid > 0 && err->tid != last_tid_printed) {
673 ThreadState* tst = VG_(get_ThreadState)(err->tid);
674 if (tst->thread_name) {
675 VG_(umsg)("Thread %u %s:\n", err->tid, tst->thread_name );
676 } else {
677 VG_(umsg)("Thread %u:\n", err->tid );
679 last_tid_printed = err->tid;
682 if (err->ekind >= 0) {
683 VG_TDICT_CALL( tool_pp_Error, err );
684 VG_(umsg)("\n");
685 } else {
686 core_pp_Error(err);
688 if (VG_(clo_error_markers)[1])
689 VG_(umsg)("%s\n", VG_(clo_error_markers)[1]);
693 do_actions_on_error(err, allow_db_attach, count_error);
697 /* Construct an error */
698 static
699 void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
700 const HChar* s, void* extra, ExeContext* where )
702 /* DO NOT MAKE unique_counter NON-STATIC */
703 static UInt unique_counter = 0;
705 vg_assert(tid < VG_N_THREADS);
707 /* Core-only parts */
708 err->unique = unique_counter++;
709 err->next = NULL;
710 err->supp = NULL;
711 err->count = 1;
712 err->tid = tid;
713 if (NULL == where && VG_(is_valid_tid)(tid))
714 err->where = VG_(record_ExeContext)( tid, 0 );
715 else
716 err->where = where;
718 /* Tool-relevant parts */
719 err->ekind = ekind;
720 err->addr = a;
721 err->extra = extra;
722 err->string = s;
724 /* sanity... */
725 vg_assert( tid < VG_N_THREADS );
730 /* Top-level entry point to the error management subsystem.
731 All detected errors are notified here; this routine decides if/when the
732 user should see the error. */
733 void VG_(maybe_record_error) ( ThreadId tid,
734 ErrorKind ekind, Addr a,
735 const HChar* s, void* extra )
737 Error err;
738 Error* p;
739 Error* p_prev;
740 UInt extra_size;
741 VgRes exe_res = Vg_MedRes;
742 static Bool stopping_message = False;
743 static Bool slowdown_message = False;
745 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
746 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
747 have been found, just refuse to collect any more. This stops
748 the burden of the error-management system becoming excessive in
749 extremely buggy programs, although it does make it pretty
750 pointless to continue the Valgrind run after this point. */
751 if (VG_(clo_error_limit)
752 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
753 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
754 && !VG_(clo_xml)) {
755 if (!stopping_message) {
756 VG_(umsg)("\n");
758 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
759 VG_(umsg)(
760 "More than %d different errors detected. "
761 "I'm not reporting any more.\n",
762 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
763 } else {
764 VG_(umsg)(
765 "More than %d total errors detected. "
766 "I'm not reporting any more.\n",
767 M_COLLECT_NO_ERRORS_AFTER_FOUND );
770 VG_(umsg)("Final error counts will be inaccurate. "
771 "Go fix your program!\n");
772 VG_(umsg)("Rerun with --error-limit=no to disable "
773 "this cutoff. Note\n");
774 VG_(umsg)("that errors may occur in your program without "
775 "prior warning from\n");
776 VG_(umsg)("Valgrind, because errors are no longer "
777 "being displayed.\n");
778 VG_(umsg)("\n");
779 stopping_message = True;
781 return;
784 /* Ignore it if error acquisition is disabled for this thread. */
785 { ThreadState* tst = VG_(get_ThreadState)(tid);
786 if (tst->err_disablement_level > 0)
787 return;
790 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
791 been found, be much more conservative about collecting new
792 ones. */
793 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
794 && !VG_(clo_xml)) {
795 exe_res = Vg_LowRes;
796 if (!slowdown_message) {
797 VG_(umsg)("\n");
798 VG_(umsg)("More than %d errors detected. Subsequent errors\n",
799 M_COLLECT_ERRORS_SLOWLY_AFTER);
800 VG_(umsg)("will still be recorded, but in less "
801 "detail than before.\n");
802 slowdown_message = True;
806 /* Build ourselves the error */
807 construct_error ( &err, tid, ekind, a, s, extra, NULL );
809 /* First, see if we've got an error record matching this one. */
810 em_errlist_searches++;
811 p = errors;
812 p_prev = NULL;
813 while (p != NULL) {
814 em_errlist_cmps++;
815 if (eq_Error(exe_res, p, &err)) {
816 /* Found it. */
817 p->count++;
818 if (p->supp != NULL) {
819 /* Deal correctly with suppressed errors. */
820 p->supp->count++;
821 n_errs_suppressed++;
822 } else {
823 n_errs_found++;
826 /* Move p to the front of the list so that future searches
827 for it are faster. It also allows to print the last
828 error (see VG_(show_last_error). */
829 if (p_prev != NULL) {
830 vg_assert(p_prev->next == p);
831 p_prev->next = p->next;
832 p->next = errors;
833 errors = p;
836 return;
838 p_prev = p;
839 p = p->next;
842 /* Didn't see it. Copy and add. */
844 /* OK, we're really going to collect it. The context is on the stack and
845 will disappear shortly, so we must copy it. First do the main
846 (non-'extra') part.
848 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
849 is for when there are more details to fill in which take time to work
850 out but don't affect our earlier decision to include the error -- by
851 postponing those details until now, we avoid the extra work in the
852 case where we ignore the error. Ugly.
854 Then, if there is an 'extra' part, copy it too, using the size that
855 VG_(tdict).tool_update_extra returned. Also allow for people using
856 the void* extra field for a scalar value like an integer.
859 /* copy main part */
860 p = VG_(malloc)("errormgr.mre.1", sizeof(Error));
861 *p = err;
863 /* update 'extra' */
864 if (ekind < 0) {
865 /* core error */
866 extra_size = core_update_extra (p);
867 } else {
868 vg_assert(VG_(needs).tool_errors);
869 extra_size = VG_TDICT_CALL(tool_update_extra, p);
872 /* copy the error string, if there is one.
873 note: if we would have many errors with big strings, using a
874 DedupPoolAlloc for these strings will avoid duplicating
875 such string in each error using it. */
876 if (NULL != p->string) {
877 p->string = VG_(strdup)("errormgr.mre.2", p->string);
880 /* copy block pointed to by 'extra', if there is one */
881 if (NULL != p->extra && 0 != extra_size) {
882 void* new_extra = VG_(malloc)("errormgr.mre.3", extra_size);
883 VG_(memcpy)(new_extra, p->extra, extra_size);
884 p->extra = new_extra;
887 p->next = errors;
888 p->supp = is_suppressible_error(&err);
889 errors = p;
890 if (p->supp == NULL) {
891 /* update stats */
892 n_err_contexts++;
893 n_errs_found++;
894 n_errs_shown++;
895 /* Actually show the error; more complex than you might think. */
896 pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml), /* count_error */ True );
897 } else {
898 n_supp_contexts++;
899 n_errs_suppressed++;
900 p->supp->count++;
904 /* Second top-level entry point to the error management subsystem, for
905 errors that the tool wants to report immediately, eg. because they're
906 guaranteed to only happen once. This avoids all the recording and
907 comparing stuff. But they can be suppressed; returns True if it is
908 suppressed. Bool 'print_error' dictates whether to print the error.
909 Bool 'count_error' dictates whether to count the error in n_errs_found.
911 Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, const HChar* s,
912 void* extra, ExeContext* where, Bool print_error,
913 Bool allow_db_attach, Bool count_error )
915 Error err;
916 Supp *su;
918 /* Ignore it if error acquisition is disabled for this thread. */
919 ThreadState* tst = VG_(get_ThreadState)(tid);
920 if (tst->err_disablement_level > 0)
921 return False; /* ignored, not suppressed */
923 /* Build ourselves the error */
924 construct_error ( &err, tid, ekind, a, s, extra, where );
926 /* Unless it's suppressed, we're going to show it. Don't need to make
927 a copy, because it's only temporary anyway.
929 Then update the 'extra' part with VG_(tdict).tool_update_extra),
930 because that can have an affect on whether it's suppressed. Ignore
931 the size return value of VG_(tdict).tool_update_extra, because we're
932 not copying 'extra'. Similarly, 's' is also not copied. */
933 if (ekind >= 0)
934 (void)VG_TDICT_CALL(tool_update_extra, &err);
935 else
936 (void)core_update_extra(&err);
938 su = is_suppressible_error(&err);
939 if (NULL == su) {
940 if (count_error) {
941 n_errs_found++;
942 n_err_contexts++;
945 if (print_error) {
946 /* update stats */
947 n_errs_shown++;
948 /* Actually show the error; more complex than you might think. */
949 pp_Error(&err, allow_db_attach, VG_(clo_xml), count_error);
951 return False;
953 } else {
954 if (count_error) {
955 n_errs_suppressed++;
956 n_supp_contexts++;
958 su->count++;
959 return True;
964 /*------------------------------------------------------------*/
965 /*--- Core error fns ---*/
966 /*------------------------------------------------------------*/
968 static Bool is_fd_core_error (const Error *e)
970 return e->ekind == FdBadClose || e->ekind == FdNotClosed ||
971 e->ekind == FdBadUse;
974 static Bool core_eq_Error (VgRes res, const Error *e1, const Error *e2)
976 if (is_fd_core_error(e1))
977 return fd_eq_Error (res, e1, e2);
978 else {
979 VG_(umsg)("FATAL: unknown core error kind: %d\n", e1->ekind );
980 VG_(exit)(1);
984 static void core_before_pp_Error (const Error *err)
986 if (is_fd_core_error(err))
987 fd_before_pp_Error(err);
988 else {
989 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
990 VG_(exit)(1);
994 static void core_pp_Error (const Error *err)
996 if (is_fd_core_error(err))
997 fd_pp_Error(err);
998 else {
999 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
1000 VG_(exit)(1);
1004 static UInt core_update_extra (const Error *err)
1006 if (is_fd_core_error(err))
1007 return fd_update_extra(err);
1008 else {
1009 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
1010 VG_(exit)(1);
1014 static const HChar *core_get_error_name(const Error *err)
1016 switch (err->ekind) {
1017 case FdBadClose:
1018 return "FdBadClose";
1019 case FdNotClosed:
1020 return "FdNotClosed";
1021 case FdBadUse:
1022 return "FdBadUse";
1023 default:
1024 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
1025 VG_(exit)(1);
1029 static Bool core_error_matches_suppression(const Error* err, const Supp* su)
1031 switch (su->skind) {
1032 case FdBadCloseSupp:
1033 return err->ekind == FdBadClose;
1034 case FdNotClosedSupp:
1035 return err->ekind == FdNotClosed;
1036 case FdBadUse:
1037 return err->ekind == FdBadUse;
1038 default:
1039 VG_(umsg)("FATAL: unknown core suppression kind: %d\n", su->skind );
1040 VG_(exit)(1);
1044 static SizeT core_get_extra_suppression_info(const Error *err,
1045 HChar* buf, Int nBuf)
1047 /* No core error has any extra suppression info at the moment. */
1048 buf[0] = '\0';
1049 return 0;
1052 static SizeT core_print_extra_suppression_use(const Supp* su,
1053 HChar* buf, Int nBuf)
1055 /* No core error has any extra suppression info at the moment. */
1056 buf[0] = '\0';
1057 return 0;
1061 /*------------------------------------------------------------*/
1062 /*--- Exported fns ---*/
1063 /*------------------------------------------------------------*/
1065 /* Show the used suppressions. Returns False if no suppression
1066 got used. */
1067 static Bool show_used_suppressions ( void )
1069 Supp *su;
1070 Bool any_supp;
1072 if (VG_(clo_xml))
1073 VG_(printf_xml)("<suppcounts>\n");
1075 any_supp = False;
1076 for (su = suppressions; su != NULL; su = su->next) {
1077 if (su->count <= 0)
1078 continue;
1079 if (VG_(clo_xml)) {
1080 VG_(printf_xml)( " <pair>\n"
1081 " <count>%d</count>\n"
1082 " <name>%pS</name>\n"
1083 " </pair>\n",
1084 su->count, su->sname );
1085 } else {
1086 HChar *xtra = NULL;
1087 Int xtra_size = 0;
1088 SizeT num_written;
1089 // blank line before the first shown suppression, if any
1090 if (!any_supp)
1091 VG_(dmsg)("\n");
1093 do {
1094 xtra_size += 256;
1095 xtra = VG_(realloc)("errormgr.sus.1", xtra, xtra_size);
1096 if (su->skind >= 0)
1097 num_written = VG_TDICT_CALL(tool_print_extra_suppression_use,
1098 su, xtra, xtra_size);
1099 else
1100 num_written = core_print_extra_suppression_use(su,
1101 xtra, xtra_size);
1102 } while (num_written == xtra_size); // resize buffer and retry
1104 // Ensure buffer is properly terminated
1105 vg_assert(xtra[num_written] == '\0');
1107 HChar *filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
1108 su->clo_suppressions_i);
1109 VG_(dmsg)("used_suppression: %6d %s %s:%d%s%s\n", su->count, su->sname,
1110 filename,
1111 su->sname_lineno,
1112 num_written ? " " : "", xtra);
1113 VG_(free)(xtra);
1115 any_supp = True;
1118 if (VG_(clo_xml))
1119 VG_(printf_xml)("</suppcounts>\n");
1121 return any_supp;
1124 /* See pub_core_errormgr.h. */
1125 void VG_(show_all_errors) ( Int verbosity, Bool xml, Int show_error_list)
1127 Int i, n_min;
1128 Error *p, *p_min;
1129 Bool any_supp;
1130 Bool any_error = False;
1131 UInt n_errs;
1133 if (verbosity == 0 && show_error_list == 0)
1134 return;
1136 /* If we're printing XML, just show the suppressions and stop. */
1137 if (xml) {
1138 if (show_error_list > 0)
1139 (void)show_used_suppressions();
1140 return;
1143 /* We only get here if not printing XML. */
1144 VG_(umsg)("ERROR SUMMARY: "
1145 "%u errors from %u contexts (suppressed: %u from %u)\n",
1146 n_errs_found, n_err_contexts,
1147 n_errs_suppressed, n_supp_contexts );
1149 if (show_error_list == 0)
1150 return;
1152 // We do the following if show_error_list > 0
1153 // or at -v or above, and only in non-XML mode.
1155 /* Print the contexts in order of increasing error count.
1156 The below implements this in a quadratic algorithm based on the assumption
1157 that there are not too many errors (including the suppressed if showing
1158 the suppressed errors) !
1159 Once an error is shown, we add a huge value to its count to filter it
1160 out.
1161 After having shown all errors, we reset count to the original value. */
1162 n_errs = n_err_contexts + (show_error_list < 2 ? 0 : n_errs_suppressed);
1163 for (i = 0; i < n_errs; i++) {
1164 n_min = (1 << 30) - 1;
1165 p_min = NULL;
1166 for (p = errors; p != NULL; p = p->next) {
1167 if (show_error_list < 2 && p->supp != NULL) continue;
1168 if (p->count < n_min) {
1169 n_min = p->count;
1170 p_min = p;
1173 // XXX: this isn't right. See bug 203651.
1174 if (p_min == NULL) continue; //VG_(core_panic)("show_all_errors()");
1176 any_error = True;
1177 VG_(umsg)("\n");
1178 VG_(umsg)("%d errors%s%s%s in context %d of %u:\n",
1179 p_min->count,
1180 p_min->supp == NULL ? "" : " (suppressed by ",
1181 p_min->supp == NULL ? "" : p_min->supp->sname,
1182 p_min->supp == NULL ? "" : ")",
1183 i+1, n_errs);
1184 pp_Error( p_min, False/*allow_db_attach*/, False /* xml */, True /* count_error */ );
1186 // We're not printing XML -- we'd have exited above if so.
1187 vg_assert(! xml);
1189 if ((i+1 == VG_(clo_dump_error))) {
1190 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
1191 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1192 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
1193 /*bbs_done*/0,
1194 /*allow redir?*/True);
1197 p_min->count = p_min->count + (1 << 30);
1200 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1201 for (p = errors; p != NULL; p = p->next) {
1202 if (p->count >= (1 << 30))
1203 p->count = p->count - (1 << 30);
1207 any_supp = show_used_suppressions();
1209 if (any_supp)
1210 VG_(umsg)("\n");
1211 // reprint summary, so users don't have to scroll way up to find
1212 // the first printing
1213 if (any_supp || any_error)
1214 VG_(umsg)("ERROR SUMMARY: "
1215 "%u errors from %u contexts (suppressed: %u from %u)\n",
1216 n_errs_found, n_err_contexts, n_errs_suppressed,
1217 n_supp_contexts );
1220 void VG_(show_last_error) ( void )
1222 if (n_err_contexts == 0) {
1223 VG_(umsg)("No errors yet\n");
1224 return;
1227 pp_Error( errors, False/*allow_db_attach*/, False/*xml*/, True/*count_error*/ );
1231 /* Show occurrence counts of all errors, in XML form. */
1232 void VG_(show_error_counts_as_XML) ( void )
1234 Error* err;
1235 VG_(printf_xml)("<errorcounts>\n");
1236 for (err = errors; err != NULL; err = err->next) {
1237 if (err->supp != NULL)
1238 continue;
1239 if (err->count <= 0)
1240 continue;
1241 VG_(printf_xml)(" <pair>\n");
1242 VG_(printf_xml)(" <count>%d</count>\n", err->count);
1243 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
1244 VG_(printf_xml)(" </pair>\n");
1246 VG_(printf_xml)("</errorcounts>\n");
1247 VG_(printf_xml)("\n");
1251 /*------------------------------------------------------------*/
1252 /*--- Suppression parsing ---*/
1253 /*------------------------------------------------------------*/
1255 /* Get the next char from fd into *out_buf. Returns 1 if success,
1256 0 if eof or < 0 if error. */
1258 static Int get_char ( Int fd, HChar* out_buf )
1260 Int r;
1261 static HChar buf[256];
1262 static Int buf_size = 0;
1263 static Int buf_used = 0;
1264 vg_assert(buf_size >= 0 && buf_size <= sizeof buf);
1265 vg_assert(buf_used >= 0 && buf_used <= buf_size);
1266 if (buf_used == buf_size) {
1267 r = VG_(read)(fd, buf, sizeof buf);
1268 if (r < 0) return r; /* read failed */
1269 vg_assert(r >= 0 && r <= sizeof buf);
1270 buf_size = r;
1271 buf_used = 0;
1273 if (buf_size == 0)
1274 return 0; /* eof */
1275 vg_assert(buf_size >= 0 && buf_size <= sizeof buf);
1276 vg_assert(buf_used >= 0 && buf_used < buf_size);
1277 *out_buf = buf[buf_used];
1278 buf_used++;
1279 return 1;
1282 // Get a non blank non comment line.
1283 // Returns True if eof.
1284 static Bool get_nbnc_line ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno )
1286 HChar* buf = *bufpp;
1287 SizeT nBuf = *nBufp;
1288 HChar ch;
1289 Int n, i;
1291 vg_assert(lineno); // lineno needed to correctly track line numbers.
1293 while (True) {
1294 buf[0] = 0;
1295 /* First, read until a non-blank char appears. */
1296 while (True) {
1297 n = get_char(fd, &ch);
1298 if (n == 1 && !VG_(isspace)(ch)) break;
1299 if (n == 1 && ch == '\n')
1300 (*lineno)++;
1301 if (n <= 0) return True;
1304 /* Now, read the line into buf. */
1305 i = 0;
1306 buf[i++] = ch; buf[i] = 0;
1307 while (True) {
1308 n = get_char(fd, &ch);
1309 if (n <= 0) return False; /* the next call will return True */
1310 if (ch == '\n')
1311 (*lineno)++;
1312 if (ch == '\n') break;
1313 if (i > 0 && i == nBuf-1) {
1314 *nBufp = nBuf = nBuf * 2;
1315 #define RIDICULOUS 100000
1316 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really.
1317 "VG_(get_line): line longer than %d chars, aborting\n",
1318 RIDICULOUS);
1319 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1321 buf[i++] = ch; buf[i] = 0;
1323 while (i > 1 && VG_(isspace)(buf[i-1])) {
1324 i--; buf[i] = 0;
1327 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1328 /* Ok, we have a line. If a non-comment line, return.
1329 If a comment line, start all over again. */
1330 if (buf[0] != '#') return False;
1334 // True if buf starts with fun: or obj: or is ...
1335 static Bool is_location_line (const HChar* buf)
1337 return VG_(strncmp)(buf, "fun:", 4) == 0
1338 || VG_(strncmp)(buf, "obj:", 4) == 0
1339 || VG_(strcmp)(buf, "...") == 0;
1342 Bool VG_(get_line) ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno )
1344 Bool eof = get_nbnc_line (fd, bufpp, nBufp, lineno);
1346 if (eof)
1347 return True;
1349 if (is_location_line(*bufpp))
1350 return True; // Not a extra suppr line
1351 else
1352 return False; // A suppression extra line
1355 /* True if s contains no wildcard (?, *) characters. */
1356 static Bool is_simple_str (const HChar *s)
1358 while (*s) {
1359 if (*s == '?' || *s == '*')
1360 return False;
1361 s++;
1363 return True;
1366 /* buf contains the raw name of a caller, supposedly either
1367 fun:some_function_name or
1368 obj:some_object_name or
1369 src:some_file_name or
1370 src:some_file_name:line# or
1372 Set p->ty and p->name accordingly.
1373 p->name is allocated and set to the string
1374 after the descriptor (fun:, obj:, or src: san line#) part.
1375 p->lineno is set to non-zero if line# specified; 0 otherwise.
1376 Returns False if failed.
1378 static Bool setLocationTy ( SuppLoc* p, const HChar *buf )
1380 if (VG_(strncmp)(buf, "fun:", 4) == 0) {
1381 p->name = VG_(strdup)("errormgr.sLTy.1", buf+4);
1382 p->name_is_simple_str = is_simple_str (p->name);
1383 p->ty = FunName;
1384 return True;
1386 if (VG_(strncmp)(buf, "obj:", 4) == 0) {
1387 p->name = VG_(strdup)("errormgr.sLTy.2", buf+4);
1388 p->name_is_simple_str = is_simple_str (p->name);
1389 p->ty = ObjName;
1390 return True;
1392 if (VG_(strncmp)(buf, "src:", 4) == 0) {
1393 p->name = VG_(strdup)("errormgr.sLTy.3", buf+4);
1394 p->name_is_simple_str = is_simple_str (p->name);
1395 p->ty = SrcName;
1396 HChar *s = VG_(strchr)(p->name, ':');
1397 if (s != NULL) {
1398 *s++ = '\0'; // trim colon
1399 p->lineno = (UInt) VG_(strtoll10)(s, NULL);
1400 } else {
1401 p->lineno = 0;
1403 return True;
1405 if (VG_(strcmp)(buf, "...") == 0) {
1406 p->name = NULL;
1407 p->name_is_simple_str = False;
1408 p->ty = DotDotDot;
1409 return True;
1411 VG_(printf)("location should be \"...\", or should start "
1412 "with \"fun:\", \"obj:\", or \"src:\"\n");
1413 return False;
1417 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1418 static Bool tool_name_present(const HChar *name, const HChar *names)
1420 Bool found;
1421 HChar *s = NULL; /* Shut gcc up */
1422 Int len = VG_(strlen)(name);
1424 found = (NULL != (s = VG_(strstr)(names, name))
1425 && (s == names || *(s-1) == ',')
1426 && (*(s+len) == ',' || *(s+len) == '\0'));
1428 return found;
1431 /* Read suppressions from the file specified in
1432 VG_(clo_suppressions)[clo_suppressions_i]
1433 and place them in the suppressions list. If there's any difficulty
1434 doing this, just give up -- there's no point in trying to recover.
1436 static void load_one_suppressions_file ( Int clo_suppressions_i )
1438 const HChar* filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
1439 clo_suppressions_i);
1440 SysRes sres;
1441 Int fd, i, j, lineno = 0;
1442 Bool got_a_location_line_read_by_tool;
1443 Bool eof;
1444 SizeT nBuf = 200;
1445 HChar* buf = VG_(malloc)("errormgr.losf.1", nBuf);
1446 HChar* tool_names;
1447 HChar* supp_name;
1448 const HChar* err_str = NULL;
1449 SuppLoc tmp_callers[VG_DEEPEST_BACKTRACE];
1451 // Check it's not a directory.
1452 if (VG_(is_dir)( filename )) {
1453 if (VG_(clo_xml))
1454 VG_(printf_xml)("</valgrindoutput>\n");
1455 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
1456 VG_(exit)(1);
1459 // Open the suppression file.
1460 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
1461 if (sr_isError(sres)) {
1462 if (VG_(clo_xml))
1463 VG_(printf_xml)("</valgrindoutput>\n");
1464 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
1465 VG_(exit)(1);
1467 fd = sr_Res(sres);
1469 # define BOMB(S) { err_str = S; goto syntax_error; }
1471 while (True) {
1472 /* Assign and initialise the two suppression halves (core and tool) */
1473 Supp* supp;
1474 supp = VG_(malloc)("errormgr.losf.1", sizeof(Supp));
1475 supp->count = 0;
1477 // Initialise temporary reading-in buffer.
1478 for (i = 0; i < VG_DEEPEST_BACKTRACE; i++) {
1479 tmp_callers[i].ty = NoName;
1480 tmp_callers[i].name_is_simple_str = False;
1481 tmp_callers[i].name = NULL;
1484 supp->string = supp->extra = NULL;
1486 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1487 if (eof) {
1488 VG_(free)(supp);
1489 break;
1492 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
1494 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1496 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1498 supp->sname = VG_(strdup)("errormgr.losf.2", buf);
1499 supp->clo_suppressions_i = clo_suppressions_i;
1500 supp->sname_lineno = lineno;
1502 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1504 if (eof) BOMB("unexpected end-of-file (expecting tool:suppr)");
1506 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1507 i = 0;
1508 while (True) {
1509 if (buf[i] == ':') break;
1510 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1511 i++;
1513 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1515 tool_names = & buf[0];
1516 supp_name = & buf[i+1];
1518 if (VG_(needs).core_errors
1519 && tool_name_present("CoreError", tool_names)) {
1520 // A core suppression
1521 if (VG_STREQ(supp_name, "FdBadClose"))
1522 supp->skind = FdBadCloseSupp;
1523 else if (VG_STREQ(supp_name, "FdNotClosed"))
1524 supp->skind = FdNotClosedSupp;
1525 else
1526 BOMB("unknown core suppression type");
1528 else if (VG_(needs).tool_errors
1529 && tool_name_present(VG_(details).name, tool_names)) {
1530 // A tool suppression
1531 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
1532 /* Do nothing, function fills in supp->skind */
1533 } else {
1534 BOMB("unknown tool suppression type");
1537 else {
1538 // Ignore rest of suppression
1539 while (True) {
1540 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1541 if (eof) BOMB("unexpected end-of-file (when skipping suppression)");
1542 if (VG_STREQ(buf, "}"))
1543 break;
1545 VG_(free)(supp->sname);
1546 VG_(free)(supp);
1547 continue;
1550 buf[0] = 0;
1551 // tool_read_extra_suppression_info might read lines
1552 // from fd till a location line.
1553 if (VG_(needs).tool_errors
1554 && !VG_TDICT_CALL(tool_read_extra_suppression_info,
1555 fd, &buf, &nBuf, &lineno, supp)) {
1556 BOMB("bad or missing extra suppression info");
1559 // No core errors need to read extra suppression info
1561 got_a_location_line_read_by_tool = buf[0] != 0 && is_location_line(buf);
1563 /* the main frame-descriptor reading loop */
1564 i = 0;
1565 while (True) {
1566 if (got_a_location_line_read_by_tool) {
1567 got_a_location_line_read_by_tool = False;
1568 eof = False;
1569 } else {
1570 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1572 if (eof)
1573 BOMB("unexpected end-of-file (when reading stack trace)");
1574 if (VG_STREQ(buf, "}")) {
1575 if (i > 0) {
1576 break;
1577 } else {
1578 BOMB("missing stack trace");
1581 if (i == VG_DEEPEST_BACKTRACE)
1582 BOMB("too many callers in stack trace");
1583 if (i > 0 && i >= VG_(clo_backtrace_size))
1584 break;
1585 if (!setLocationTy(&(tmp_callers[i]), buf))
1586 BOMB("location should be \"...\", or should start "
1587 "with \"fun:\", \"obj:\", or \"src:\"");
1588 i++;
1591 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1592 // lines and grab the '}'.
1593 if (!VG_STREQ(buf, "}")) {
1594 do {
1595 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1596 } while (!eof && !VG_STREQ(buf, "}"));
1599 // Reject entries which are entirely composed of frame
1600 // level wildcards.
1601 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1602 for (j = 0; j < i; j++) {
1603 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName
1604 || tmp_callers[j].ty == SrcName) {
1605 break;
1607 vg_assert(tmp_callers[j].ty == DotDotDot);
1609 vg_assert(j >= 0 && j <= i);
1610 if (j == i) {
1611 // we didn't find any non-"..." entries
1612 BOMB("suppression must contain at least one location "
1613 "line which is not \"...\"");
1616 // Copy tmp_callers[] into supp->callers[]
1617 supp->n_callers = i;
1618 supp->callers = VG_(malloc)("errormgr.losf.4", i * sizeof(SuppLoc));
1619 for (i = 0; i < supp->n_callers; i++) {
1620 supp->callers[i] = tmp_callers[i];
1623 supp->next = suppressions;
1624 suppressions = supp;
1626 VG_(free)(buf);
1627 VG_(close)(fd);
1628 return;
1630 syntax_error:
1631 if (VG_(clo_xml))
1632 VG_(printf_xml)("</valgrindoutput>\n");
1633 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
1634 filename, lineno );
1635 VG_(umsg)(" %s\n", err_str );
1637 VG_(close)(fd);
1638 VG_(umsg)("exiting now.\n");
1639 VG_(exit)(1);
1641 # undef BOMB
1644 void VG_(add_suppression_file)(const HChar *filename)
1646 HChar *f = VG_(strdup)("errormgr.addsup", filename);
1647 VG_(addToXA)(VG_(clo_suppressions), &f);
1648 if (load_suppressions_called)
1649 load_one_suppressions_file( VG_(sizeXA)(VG_(clo_suppressions)) - 1 );
1652 void VG_(load_suppressions) ( void )
1654 Int i;
1655 suppressions = NULL;
1656 load_suppressions_called = True;
1657 for (i = 0; i < VG_(sizeXA)(VG_(clo_suppressions)); i++) {
1658 if (VG_(clo_verbosity) > 1) {
1659 VG_(dmsg)("Reading suppressions file: %s\n",
1660 *(HChar**) VG_(indexXA)(VG_(clo_suppressions), i));
1662 load_one_suppressions_file( i );
1667 /*------------------------------------------------------------*/
1668 /*--- Matching errors to suppressions ---*/
1669 /*------------------------------------------------------------*/
1671 /* Parameterising functions for the use of VG_(generic_match) in
1672 suppression-vs-error matching. The suppression frames (SuppLoc)
1673 play the role of 'pattern'-element, and the error frames (IPs,
1674 hence simply Addrs) play the role of 'input'. In short then, we're
1675 matching a sequence of Addrs against a pattern composed of a
1676 sequence of SuppLocs.
1678 static Bool supploc_IsStar ( const void* supplocV )
1680 const SuppLoc* supploc = supplocV;
1681 return supploc->ty == DotDotDot;
1684 static Bool supploc_IsQuery ( const void* supplocV )
1686 return False; /* there's no '?' equivalent in the supp syntax */
1689 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1690 needed to match an error with the suppression patterns.
1691 The matching between an IP and a suppression pattern is done either
1692 with the IP function name or with the IP object name.
1693 First time the fun or obj name is needed for an IP member
1694 of a stack trace, it will be computed and stored in names.
1695 Also, if the IP corresponds to one or more inlined function calls,
1696 the inlined function names are expanded.
1697 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1698 allocations and the nr of debuginfo search. */
1699 typedef
1700 struct {
1701 DiEpoch epoch; // used to interpret .ips
1702 StackTrace ips; // stack trace we are lazily completing.
1703 UWord n_ips; // nr of elements in ips.
1705 // VG_(generic_match) calls haveInputInpC to check
1706 // for the presence of an input element identified by ixInput
1707 // (i.e. a number that identifies the ixInput element of the
1708 // input sequence). It calls supp_pattEQinp to match this input
1709 // element with a pattern.
1710 // When inlining info is used to provide inlined function calls
1711 // in stacktraces, one IP in ips can be expanded in several
1712 // function names. So, each time input (or presence of input)
1713 // is requested by VG_(generic_match), we will expand
1714 // more IP of ips till we have expanded enough to reach the
1715 // input element requested (or we cannot expand anymore).
1717 UWord n_ips_expanded;
1718 // n_ips_expanded maintains the nr of elements in ips that we have
1719 // already expanded.
1720 UWord n_expanded;
1721 // n_expanded maintains the nr of elements resulting from the expansion
1722 // of the n_ips_expanded IPs. Without inlined function calls,
1723 // n_expanded == n_ips_expanded. With inlining info,
1724 // n_expanded >= n_ips_expanded.
1726 Int* n_offsets_per_ip;
1727 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1728 // obj_offsets resulting of the expansion of ips[i].
1729 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1730 // This array allows to retrieve the position in ips corresponding to
1731 // an ixInput.
1733 // size (in elements) of fun_offsets and obj_offsets.
1734 // (fun|obj)_offsets are reallocated if more space is needed
1735 // to expand an IP.
1736 UWord sz_offsets;
1738 Int* fun_offsets;
1739 // fun_offsets[ixInput] is the offset in names where the
1740 // function name for the ixInput element of the input sequence
1741 // can be found. As one IP of ips can be expanded in several
1742 // function calls due to inlined function calls, we can have more
1743 // elements in fun_offsets than in ips.
1744 // An offset -1 means the function name has not yet been computed.
1745 Int* obj_offsets;
1746 // Similarly, obj_offsets[ixInput] gives the offset for the
1747 // object name for ips[ixInput]
1748 // (-1 meaning object name not yet been computed).
1750 // All function names and object names will be concatenated
1751 // in names. names is reallocated on demand.
1752 HChar *names;
1753 Int names_szB; // size of names.
1754 Int names_free; // offset first free HChar in names.
1756 IPtoFunOrObjCompleter;
1758 static void pp_ip2fo (const IPtoFunOrObjCompleter* ip2fo)
1760 Int i, j;
1761 Int o;
1763 VG_(printf)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1764 ip2fo->n_ips, ip2fo->n_ips_expanded, ip2fo->n_expanded);
1765 for (i = 0; i < ip2fo->n_ips_expanded; i++) {
1766 o = 0;
1767 for (j = 0; j < i; j++)
1768 o += ip2fo->n_offsets_per_ip[j];
1769 VG_(printf)("ips %d 0x08%lx offset [%d,%d] ",
1770 i, ip2fo->ips[i],
1771 o, o+ip2fo->n_offsets_per_ip[i]-1);
1772 for (j = 0; j < ip2fo->n_offsets_per_ip[i]; j++) {
1773 VG_(printf)("%sfun:%s obj:%s\n",
1774 j == 0 ? "" : " ",
1775 ip2fo->fun_offsets[o+j] == -1 ?
1776 "<not expanded>" : &ip2fo->names[ip2fo->fun_offsets[o+j]],
1777 ip2fo->obj_offsets[o+j] == -1 ?
1778 "<not expanded>" : &ip2fo->names[ip2fo->obj_offsets[o+j]]);
1783 /* free the memory in ip2fo.
1784 At debuglog 4, su (or NULL) will be used to show the matching
1785 (or non matching) with ip2fo. */
1786 static void clearIPtoFunOrObjCompleter ( const Supp *su,
1787 IPtoFunOrObjCompleter* ip2fo)
1789 if (DEBUG_ERRORMGR || VG_(debugLog_getLevel)() >= 4) {
1790 if (su) {
1791 HChar *filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
1792 su->clo_suppressions_i);
1793 VG_(dmsg)("errormgr matching end suppression %s %s:%d matched:\n",
1794 su->sname,
1795 filename,
1796 su->sname_lineno);
1797 } else {
1798 VG_(dmsg)("errormgr matching end no suppression matched:\n");
1800 VG_(pp_StackTrace) (ip2fo->epoch, ip2fo->ips, ip2fo->n_ips);
1801 pp_ip2fo(ip2fo);
1803 if (ip2fo->n_offsets_per_ip) VG_(free)(ip2fo->n_offsets_per_ip);
1804 if (ip2fo->fun_offsets) VG_(free)(ip2fo->fun_offsets);
1805 if (ip2fo->obj_offsets) VG_(free)(ip2fo->obj_offsets);
1806 if (ip2fo->names) VG_(free)(ip2fo->names);
1809 /* Grow ip2fo->names to ensure we have NEEDED characters available
1810 in ip2fo->names and returns a pointer to the first free char. */
1811 static HChar* grow_names(IPtoFunOrObjCompleter* ip2fo, SizeT needed)
1813 if (ip2fo->names_szB
1814 < ip2fo->names_free + needed) {
1815 if (needed < ERRTXT_LEN) needed = ERRTXT_LEN;
1817 ip2fo->names
1818 = VG_(realloc)("foc_names",
1819 ip2fo->names,
1820 ip2fo->names_szB + needed);
1821 ip2fo->names_szB += needed;
1823 return ip2fo->names + ip2fo->names_free;
1826 /* foComplete returns the function name or object name for ixInput.
1827 If needFun, returns the function name for this input
1828 else returns the object name for this input.
1829 The function name or object name will be computed and added in
1830 names if not yet done. */
1831 static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo,
1832 Int ixInput, Bool needFun)
1834 vg_assert (ixInput < ip2fo->n_expanded);
1835 vg_assert (VG_(clo_read_inline_info) || ixInput < ip2fo->n_ips);
1837 // ptr to the offset array for function offsets (if needFun)
1838 // or object offsets (if !needFun).
1839 Int** offsets;
1840 if (needFun)
1841 offsets = &ip2fo->fun_offsets;
1842 else
1843 offsets = &ip2fo->obj_offsets;
1845 // Complete Fun name or Obj name for IP if not yet done.
1846 if ((*offsets)[ixInput] == -1) {
1847 const HChar* caller;
1849 (*offsets)[ixInput] = ip2fo->names_free;
1850 if (DEBUG_ERRORMGR) VG_(printf)("marking %s ixInput %d offset %d\n",
1851 needFun ? "fun" : "obj",
1852 ixInput, ip2fo->names_free);
1853 if (needFun) {
1854 // With inline info, fn names must have been completed already.
1855 vg_assert (!VG_(clo_read_inline_info));
1856 /* Get the function name into 'caller_name', or "???"
1857 if unknown. */
1858 // Nb: C++-mangled names are used in suppressions. Do, though,
1859 // Z-demangle them, since otherwise it's possible to wind
1860 // up comparing "malloc" in the suppression against
1861 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1862 // two of them need to be made to match.
1863 if (!VG_(get_fnname_no_cxx_demangle)(ip2fo->epoch,
1864 ip2fo->ips[ixInput],
1865 &caller,
1866 NULL))
1867 caller = "???";
1868 } else {
1869 /* Get the object name into 'caller_name', or "???"
1870 if unknown. */
1871 UWord i;
1872 UWord last_expand_pos_ips = 0;
1873 UWord pos_ips;
1875 /* First get the pos in ips corresponding to ixInput */
1876 for (pos_ips = 0; pos_ips < ip2fo->n_expanded; pos_ips++) {
1877 last_expand_pos_ips += ip2fo->n_offsets_per_ip[pos_ips];
1878 if (ixInput < last_expand_pos_ips)
1879 break;
1881 /* pos_ips is the position in ips corresponding to ixInput.
1882 last_expand_pos_ips is the last offset in fun/obj where
1883 ips[pos_ips] has been expanded. */
1885 if (!VG_(get_objname)(ip2fo->epoch, ip2fo->ips[pos_ips], &caller))
1886 caller = "???";
1888 // Have all inlined calls pointing at this object name
1889 for (i = last_expand_pos_ips - ip2fo->n_offsets_per_ip[pos_ips] + 1;
1890 i < last_expand_pos_ips;
1891 i++) {
1892 ip2fo->obj_offsets[i] = ip2fo->names_free;
1893 if (DEBUG_ERRORMGR)
1894 VG_(printf) (" set obj_offset %lu to %d\n",
1895 i, ip2fo->names_free);
1898 SizeT caller_len = VG_(strlen)(caller);
1899 HChar* caller_name = grow_names(ip2fo, caller_len + 1);
1900 VG_(strcpy)(caller_name, caller);
1901 ip2fo->names_free += caller_len + 1;
1902 if (DEBUG_ERRORMGR) pp_ip2fo(ip2fo);
1905 return ip2fo->names + (*offsets)[ixInput];
1908 // Grow fun and obj _offsets arrays to have at least n_req elements.
1909 // Ensure n_offsets_per_ip is allocated.
1910 static void grow_offsets(IPtoFunOrObjCompleter* ip2fo, Int n_req)
1912 Int i;
1914 // n_offsets_per_ip must always have the size of the ips array
1915 if (ip2fo->n_offsets_per_ip == NULL) {
1916 ip2fo->n_offsets_per_ip = VG_(malloc)("grow_offsets",
1917 ip2fo->n_ips * sizeof(Int));
1918 for (i = 0; i < ip2fo->n_ips; i++)
1919 ip2fo->n_offsets_per_ip[i] = 0;
1922 if (ip2fo->sz_offsets >= n_req)
1923 return;
1925 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1926 // elements and at least a few more elements than the current size.
1927 if (n_req < ip2fo->n_ips)
1928 n_req = ip2fo->n_ips;
1929 if (n_req < ip2fo->sz_offsets + 5)
1930 n_req = ip2fo->sz_offsets + 5;
1932 ip2fo->fun_offsets = VG_(realloc)("grow_offsets", ip2fo->fun_offsets,
1933 n_req * sizeof(Int));
1934 for (i = ip2fo->sz_offsets; i < n_req; i++)
1935 ip2fo->fun_offsets[i] = -1;
1937 ip2fo->obj_offsets = VG_(realloc)("grow_offsets", ip2fo->obj_offsets,
1938 n_req * sizeof(Int));
1939 for (i = ip2fo->sz_offsets; i < n_req; i++)
1940 ip2fo->obj_offsets[i] = -1;
1942 ip2fo->sz_offsets = n_req;
1945 // Expands more IPs from ip2fo->ips.
1946 static void expandInput (IPtoFunOrObjCompleter* ip2fo, UWord ixInput )
1948 while (ip2fo->n_ips_expanded < ip2fo->n_ips
1949 && ip2fo->n_expanded <= ixInput) {
1950 if (VG_(clo_read_inline_info)) {
1951 // Expand one more IP in one or more calls.
1952 const Addr IP = ip2fo->ips[ip2fo->n_ips_expanded];
1953 InlIPCursor *iipc;
1955 iipc = VG_(new_IIPC)(ip2fo->epoch, IP);
1956 // The only thing we really need is the nr of inlined fn calls
1957 // corresponding to the IP we will expand.
1958 // However, computing this is mostly the same as finding
1959 // the function name. So, let's directly complete the function name.
1960 do {
1961 const HChar *caller;
1962 grow_offsets(ip2fo, ip2fo->n_expanded+1);
1963 ip2fo->fun_offsets[ip2fo->n_expanded] = ip2fo->names_free;
1964 if (!VG_(get_fnname_no_cxx_demangle)(ip2fo->epoch, IP,
1965 &caller,
1966 iipc))
1967 caller = "???";
1968 SizeT caller_len = VG_(strlen)(caller);
1969 HChar* caller_name = grow_names(ip2fo, caller_len + 1);
1970 VG_(strcpy)(caller_name, caller);
1971 ip2fo->names_free += caller_len + 1;
1972 ip2fo->n_expanded++;
1973 ip2fo->n_offsets_per_ip[ip2fo->n_ips_expanded]++;
1974 } while (VG_(next_IIPC)(iipc));
1975 ip2fo->n_ips_expanded++;
1976 VG_(delete_IIPC) (iipc);
1977 } else {
1978 // Without inlined fn call info, expansion simply
1979 // consists in allocating enough elements in (fun|obj)_offsets.
1980 // The function or object names themselves will be completed
1981 // when requested.
1982 Int i;
1983 grow_offsets(ip2fo, ip2fo->n_ips);
1984 ip2fo->n_ips_expanded = ip2fo->n_ips;
1985 ip2fo->n_expanded = ip2fo->n_ips;
1986 for (i = 0; i < ip2fo->n_ips; i++)
1987 ip2fo->n_offsets_per_ip[i] = 1;
1992 static Bool haveInputInpC (void* inputCompleterV, UWord ixInput )
1994 IPtoFunOrObjCompleter* ip2fo = (IPtoFunOrObjCompleter*)inputCompleterV;
1995 expandInput(ip2fo, ixInput);
1996 return ixInput < ip2fo->n_expanded;
1999 static Bool supp_pattEQinp ( const void* supplocV, const void* addrV,
2000 void* inputCompleterV, UWord ixInput )
2002 const SuppLoc* supploc = (const SuppLoc*)supplocV; /* PATTERN */
2003 IPtoFunOrObjCompleter* ip2fo = (IPtoFunOrObjCompleter*)inputCompleterV;
2004 const HChar* funobjsrc_name; // Fun, Obj, or src file name.
2005 UInt src_lineno = 0;
2006 Bool ret;
2008 expandInput(ip2fo, ixInput);
2009 vg_assert(ixInput < ip2fo->n_expanded);
2011 /* So, does this IP address match this suppression-line? */
2012 switch (supploc->ty) {
2013 case DotDotDot:
2014 /* supp_pattEQinp is a callback from VG_(generic_match). As
2015 per the spec thereof (see include/pub_tool_seqmatch.h), we
2016 should never get called with a pattern value for which the
2017 _IsStar or _IsQuery function would return True. Hence
2018 this can't happen. */
2019 vg_assert(0);
2020 case ObjName:
2021 funobjsrc_name = foComplete(ip2fo, ixInput, False /*needFun*/);
2022 break;
2023 case FunName:
2024 funobjsrc_name = foComplete(ip2fo, ixInput, True /*needFun*/);
2025 break;
2026 case SrcName: {
2027 const HChar* src_dirname; // placeholder only
2028 ret = VG_(get_filename_linenum)(VG_(current_DiEpoch)(),
2029 ip2fo->ips[ixInput], &funobjsrc_name, &src_dirname, &src_lineno);
2030 if (!ret) {
2031 /* No file name found for location so no way this is a match. */
2032 return ret;
2034 break;
2036 default:
2037 vg_assert(0);
2040 /* So now we have the function or object name in funobjsrc_name, and
2041 the pattern (at the character level) to match against is in
2042 supploc->name. Hence (and leading to a re-entrant call of
2043 VG_(generic_match) if there is a wildcard character): */
2044 if (supploc->name_is_simple_str)
2045 ret = VG_(strcmp) (supploc->name, funobjsrc_name) == 0;
2046 else
2047 ret = VG_(string_match)(supploc->name, funobjsrc_name);
2048 if (ret && supploc->ty == SrcName && supploc->lineno != 0) {
2049 ret = (supploc->lineno == src_lineno);
2051 if (DEBUG_ERRORMGR)
2052 VG_(printf) ("supp_pattEQinp %s patt %s ixInput %lu value:%s (lineno:%u vs %u) match:%s\n",
2053 supploc->ty == FunName ? "fun" : (supploc->ty == SrcName ? "src" : "obj"),
2054 supploc->name, ixInput, funobjsrc_name,
2055 supploc->ty == SrcName ? supploc->lineno : 0,
2056 supploc->ty == SrcName ? src_lineno : 0,
2057 ret ? "yes" : "no");
2058 return ret;
2061 /////////////////////////////////////////////////////
2063 static Bool supp_matches_callers(IPtoFunOrObjCompleter* ip2fo,
2064 const Supp* su)
2066 /* Unwrap the args and set up the correct parameterisation of
2067 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
2068 supp_pattEQinp. */
2069 /* note, StackTrace ip2fo->ips === Addr* */
2070 SuppLoc* supps = su->callers;
2071 UWord n_supps = su->n_callers;
2072 UWord szbPatt = sizeof(SuppLoc);
2073 Bool matchAll = False; /* we just want to match a prefix */
2074 if (DEBUG_ERRORMGR) {
2075 HChar *filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
2076 su->clo_suppressions_i);
2077 VG_(dmsg)(" errormgr Checking match with %s %s:%d\n",
2078 su->sname,
2079 filename,
2080 su->sname_lineno);
2082 return
2083 VG_(generic_match)(
2084 matchAll,
2085 /*PATT*/supps, szbPatt, n_supps, 0/*initial ixPatt*/,
2086 /*INPUT*/
2087 NULL, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
2088 0/*initial ixInput*/,
2089 supploc_IsStar, supploc_IsQuery, supp_pattEQinp,
2090 ip2fo, haveInputInpC
2094 /////////////////////////////////////////////////////
2096 static
2097 Bool supp_matches_error(const Supp* su, const Error* err)
2099 if (su->skind >= 0) {
2100 if (VG_(needs).tool_errors) {
2101 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
2102 } else {
2103 VG_(printf)(
2104 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
2105 "probably needs to be set.\n",
2106 (UInt)err->ekind);
2107 VG_(core_panic)("unhandled suppression type");
2109 } else {
2110 return core_error_matches_suppression(err, su);
2114 /////////////////////////////////////////////////////
2116 /* Does an error context match a suppression? ie is this a suppressible
2117 error? If so, return a pointer to the Supp record, otherwise NULL.
2118 Tries to minimise the number of symbol searches since they are expensive.
2120 static Supp* is_suppressible_error ( const Error* err )
2122 Supp* su;
2123 Supp* su_prev;
2125 IPtoFunOrObjCompleter ip2fo;
2126 /* Conceptually, ip2fo contains an array of function names and an array of
2127 object names, corresponding to the array of IP of err->where.
2128 These names are just computed 'on demand' (so once maximum),
2129 then stored (efficiently, avoiding too many allocs) in ip2fo to be
2130 re-usable for the matching of the same IP with the next suppression
2131 pattern.
2133 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
2134 of its arguments. It will then pass it to the function
2135 supp_pattEQinp which will then lazily complete the IP function name or
2136 object name inside ip2fo. Next time the fun or obj name for the same
2137 IP is needed (i.e. for the matching with the next suppr pattern), then
2138 the fun or obj name will not be searched again in the debug info. */
2140 if (err->where == NULL)
2141 return NULL;
2143 /* stats gathering */
2144 em_supplist_searches++;
2146 /* Prepare the lazy input completer. */
2147 ip2fo.epoch = VG_(get_ExeContext_epoch)(err->where);
2148 ip2fo.ips = VG_(get_ExeContext_StackTrace)(err->where);
2149 ip2fo.n_ips = VG_(get_ExeContext_n_ips)(err->where);
2150 ip2fo.n_ips_expanded = 0;
2151 ip2fo.n_expanded = 0;
2152 ip2fo.sz_offsets = 0;
2153 ip2fo.n_offsets_per_ip = NULL;
2154 ip2fo.fun_offsets = NULL;
2155 ip2fo.obj_offsets = NULL;
2156 ip2fo.names = NULL;
2157 ip2fo.names_szB = 0;
2158 ip2fo.names_free = 0;
2160 /* See if the error context matches any suppression. */
2161 if (DEBUG_ERRORMGR || VG_(debugLog_getLevel)() >= 4)
2162 VG_(dmsg)("errormgr matching begin\n");
2163 su_prev = NULL;
2164 for (su = suppressions; su != NULL; su = su->next) {
2165 em_supplist_cmps++;
2166 if (supp_matches_error(su, err)
2167 && supp_matches_callers(&ip2fo, su)) {
2168 /* got a match. */
2169 /* Inform the tool that err is suppressed by su. */
2170 if (su->skind >= 0)
2171 (void)VG_TDICT_CALL(tool_update_extra_suppression_use, err, su);
2172 /* No core errors need to update extra suppression info */
2173 /* Move this entry to the head of the list
2174 in the hope of making future searches cheaper. */
2175 if (su_prev) {
2176 vg_assert(su_prev->next == su);
2177 su_prev->next = su->next;
2178 su->next = suppressions;
2179 suppressions = su;
2181 clearIPtoFunOrObjCompleter(su, &ip2fo);
2182 return su;
2184 su_prev = su;
2186 clearIPtoFunOrObjCompleter(NULL, &ip2fo);
2187 return NULL; /* no matches */
2190 /* Show accumulated error-list and suppression-list search stats.
2192 void VG_(print_errormgr_stats) ( void )
2194 VG_(dmsg)(
2195 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
2196 em_supplist_searches, em_supplist_cmps
2198 VG_(dmsg)(
2199 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
2200 em_errlist_searches, em_errlist_cmps
2204 /*--------------------------------------------------------------------*/
2205 /*--- end ---*/
2206 /*--------------------------------------------------------------------*/