Revert "FreeBSD regtest: Implement setaffinity in gdb sleepers for nlvgdbsigqueue"
[valgrind.git] / coregrind / m_errormgr.c
blob2ce919482f771b89bfce9e6c9cae8455374349ba
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,
210 FdBadUseSupp = -4
212 CoreSuppKind;
214 /* Max number of callers for context in a suppression is
215 VG_DEEPEST_BACKTRACE. */
217 /* For each caller specified for a suppression, record the nature of
218 the caller name. Not of interest to tools. */
219 typedef
220 enum {
221 NoName, /* Error case */
222 ObjName, /* Name is of an shared object file. */
223 FunName, /* Name is of a function. */
224 DotDotDot, /* Frame-level wildcard */
225 SrcName /* Name is of a src file. */
227 SuppLocTy;
229 typedef
230 struct {
231 SuppLocTy ty;
232 Bool name_is_simple_str; /* True if name is a string without
233 '?' and '*' wildcard characters. */
234 HChar* name; /* NULL for NoName and DotDotDot */
235 UInt lineno; /* Valid for SrcName. */
237 SuppLoc;
239 /* Suppressions. Tools can get/set tool-relevant parts with functions
240 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
241 Tools can use a normal enum (with element values in the normal range
242 (0..)) for 'skind'. */
243 struct _Supp {
244 struct _Supp* next;
245 HChar* sname; // The name by which the suppression is referred to.
246 Int count; // The number of times this error has been suppressed.
248 // Index in VG_(clo_suppressions) giving filename from which suppression
249 // was read, and the lineno in this file where sname was read.
250 Int clo_suppressions_i;
251 Int sname_lineno;
253 // Length of 'callers'
254 Int n_callers;
255 // Array of callers, for matching stack traces. First one (name of fn
256 // where err occurs) is mandatory; rest are optional.
257 SuppLoc* callers;
259 /* The tool-specific part */
260 SuppKind skind; // What kind of suppression. Must use the range (0..).
261 HChar* string; // String -- use is optional. NULL by default.
262 void* extra; // Anything else -- use is optional. NULL by default.
265 SuppKind VG_(get_supp_kind) ( const Supp* su )
267 return su->skind;
270 HChar* VG_(get_supp_string) ( const Supp* su )
272 return su->string;
275 void* VG_(get_supp_extra) ( const Supp* su )
277 return su->extra;
281 void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
283 su->skind = skind;
286 void VG_(set_supp_string) ( Supp* su, HChar* string )
288 su->string = string;
291 void VG_(set_supp_extra) ( Supp* su, void* extra )
293 su->extra = extra;
297 /*------------------------------------------------------------*/
298 /*--- Helper fns ---*/
299 /*------------------------------------------------------------*/
301 // Only show core warnings if the tool wants to, we're not running with -q,
302 // and were not outputting XML.
303 Bool VG_(showing_core_warnings)(void)
305 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
308 /* Compare errors, to detect duplicates.
310 static Bool eq_Error ( VgRes res, const Error* e1, const Error* e2 )
312 if (e1->ekind != e2->ekind)
313 return False;
314 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
315 return False;
317 if (e1->ekind >= 0) {
318 if (VG_(needs).tool_errors) {
319 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
320 } else {
321 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
322 "probably needs to be set.\n",
323 (UInt)e1->ekind);
324 VG_(core_panic)("unhandled error type");
326 } else {
327 return core_eq_Error(res, e1, e2);
332 /* Helper functions for suppression generation: print a single line of
333 a suppression pseudo-stack-trace, either in XML or text mode. It's
334 important that the behaviour of these two functions exactly
335 corresponds.
337 #define ERRTXT_LEN 4096
339 static void printSuppForIp_XML(UInt n, DiEpoch ep, Addr ip, void* uu_opaque)
341 const HChar *buf;
342 InlIPCursor* iipc = VG_(new_IIPC)(ep, ip);
343 do {
344 if ( VG_(get_fnname_no_cxx_demangle) (ep, ip, &buf, iipc) ) {
345 VG_(printf_xml)(" <sframe> <fun>%pS</fun> </sframe>\n", buf);
346 } else
347 if ( VG_(get_objname)(ep, ip, &buf) ) {
348 VG_(printf_xml)(" <sframe> <obj>%pS</obj> </sframe>\n", buf);
349 } else {
350 VG_(printf_xml)(" <sframe> <obj>*</obj> </sframe>\n");
352 } while (VG_(next_IIPC)(iipc));
353 VG_(delete_IIPC)(iipc);
356 static void printSuppForIp_nonXML(UInt n, DiEpoch ep, Addr ip, void* textV)
358 const HChar *buf;
359 XArray* /* of HChar */ text = (XArray*)textV;
360 InlIPCursor* iipc = VG_(new_IIPC)(ep, ip);
361 do {
362 if ( VG_(get_fnname_no_cxx_demangle) (ep, ip, &buf, iipc) ) {
363 VG_(xaprintf)(text, " fun:%s\n", buf);
364 } else
365 if ( VG_(get_objname)(ep, ip, &buf) ) {
366 VG_(xaprintf)(text, " obj:%s\n", buf);
367 } else {
368 VG_(xaprintf)(text, " obj:*\n");
370 } while (VG_(next_IIPC)(iipc));
371 VG_(delete_IIPC)(iipc);
374 /* Generate a suppression for an error, either in text or XML mode.
376 static void gen_suppression(const Error* err)
378 const HChar* name;
379 const HChar* component;
380 ExeContext* ec;
381 XArray* /* HChar */ text;
383 const HChar* dummy_name = "insert_a_suppression_name_here";
385 vg_assert(err);
387 ec = VG_(get_error_where)(err);
388 if (ec == NULL) {
389 /* This can happen with core errors for --track-fds=all
390 with "leaked" inherited file descriptors, which aren't
391 created in the current program. */
392 VG_(umsg)("(No origin, error cannot be suppressed)\n");
393 return;
396 if (err->ekind >= 0) {
397 name = VG_TDICT_CALL(tool_get_error_name, err);
398 if (NULL == name) {
399 VG_(umsg)("(%s does not allow error to be suppressed)\n",
400 VG_(details).name);
401 return;
403 } else {
404 name = core_get_error_name(err);
405 if (NULL == name) {
406 VG_(umsg)("(core error cannot be suppressed)\n");
407 return;
411 /* In XML mode, we also need to print the plain text version of the
412 suppresion in a CDATA section. What that really means is, we
413 need to generate the plaintext version both in XML and text
414 mode. So generate it into TEXT. */
415 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
416 VG_(free), sizeof(HChar) );
418 /* Ok. Generate the plain text version into TEXT. */
419 if (err->ekind >= 0)
420 component = VG_(details).name;
421 else
422 component = "CoreError";
423 VG_(xaprintf)(text, "{\n");
424 VG_(xaprintf)(text, " <%s>\n", dummy_name);
425 VG_(xaprintf)(text, " %s:%s\n", component, name);
427 HChar *xtra = NULL;
428 SizeT xtra_size = 0;
429 SizeT num_written;
431 do {
432 xtra_size += 256;
433 xtra = VG_(realloc)("errormgr.gen_suppression.2", xtra,xtra_size);
434 if (err->ekind >= 0)
435 num_written = VG_TDICT_CALL(tool_get_extra_suppression_info,
436 err, xtra, xtra_size);
437 else
438 num_written = core_get_extra_suppression_info(err, xtra, xtra_size);
439 } while (num_written == xtra_size); // resize buffer and retry
441 // Ensure buffer is properly terminated
442 vg_assert(xtra[num_written] == '\0');
444 if (num_written)
445 VG_(xaprintf)(text, " %s\n", xtra);
447 // Print stack trace elements
448 UInt n_ips = VG_(get_ExeContext_n_ips)(ec);
449 vg_assert(n_ips > 0);
450 vg_assert(n_ips <= VG_DEEPEST_BACKTRACE);
451 VG_(apply_StackTrace)(printSuppForIp_nonXML,
452 text, VG_(get_ExeContext_epoch)(ec),
453 VG_(get_ExeContext_StackTrace)(ec),
454 n_ips);
456 VG_(xaprintf)(text, "}\n");
457 // zero terminate
458 VG_(xaprintf)(text, "%c", (HChar)0 );
459 // VG_(printf) of text
461 /* And now display it. */
462 if (! VG_(clo_xml) ) {
464 // the simple case
465 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
467 } else {
469 /* Now we have to print the XML directly. No need to go to the
470 effort of stuffing it in an XArray, since we won't need it
471 again. */
472 VG_(printf_xml)(" <suppression>\n");
473 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name);
474 VG_(printf_xml)(
475 " <skind>%pS:%pS</skind>\n", component, name);
476 if (num_written)
477 VG_(printf_xml)(" <skaux>%pS</skaux>\n", xtra);
479 // Print stack trace elements
480 VG_(apply_StackTrace)(printSuppForIp_XML,
481 NULL, VG_(get_ExeContext_epoch)(ec),
482 VG_(get_ExeContext_StackTrace)(ec),
483 VG_(get_ExeContext_n_ips)(ec));
485 // And now the cdata bit
486 // XXX FIXME! properly handle the case where the raw text
487 // itself contains "]]>", as specified in Protocol 4.
488 VG_(printf_xml)(" <rawtext>\n");
489 VG_(printf_xml)("<![CDATA[\n");
490 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
491 VG_(printf_xml)("]]>\n");
492 VG_(printf_xml)(" </rawtext>\n");
493 VG_(printf_xml)(" </suppression>\n");
497 VG_(deleteXA)(text);
498 VG_(free)(xtra);
502 /* Figure out if we want to perform a given action for this error,
503 possibly by asking the user.
505 Bool VG_(is_action_requested) ( const HChar* action, Bool* clo )
507 HChar ch, ch2;
508 Int res;
510 /* First off, we shouldn't be asking the user anything if
511 we're in XML mode. */
512 if (VG_(clo_xml))
513 return False; /* That's a Nein, oder Nay as they say down here in B-W */
515 if (*clo == False)
516 return False;
518 VG_(umsg)("\n");
520 again:
521 VG_(printf)(
522 "==%d== "
523 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
524 VG_(getpid)(), action
527 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
528 if (res != 1) goto ioerror;
529 /* res == 1 */
530 if (ch == '\n') return False;
531 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
532 && ch != 'C' && ch != 'c') goto again;
534 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
535 if (res != 1) goto ioerror;
536 if (ch2 != '\n') goto again;
538 /* No, don't want to do action. */
539 if (ch == 'n' || ch == 'N') return False;
540 /* Yes, want to do action. */
541 if (ch == 'y' || ch == 'Y') return True;
542 /* No, don't want to do action, and don't ask again either. */
543 vg_assert(ch == 'c' || ch == 'C');
545 ioerror:
546 *clo = False;
547 return False;
551 /* Do actions on error, that is, immediately after an error is printed.
552 These are:
553 * possibly, call the GDB server
554 * possibly, generate a suppression.
556 static
557 void do_actions_on_error(const Error* err, Bool allow_db_attach, Bool count_error)
559 Bool still_noisy = True;
561 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
562 if (VG_(clo_vgdb) != Vg_VgdbNo
563 && allow_db_attach
564 && VG_(clo_vgdb_error) <= n_errs_shown) {
565 if (!(VG_(clo_launched_with_multi)))
566 VG_(umsg)("(action on error) vgdb me ... \n");
567 VG_(gdbserver)( err->tid );
568 if (!(VG_(clo_launched_with_multi)))
569 VG_(umsg)("Continuing ...\n");
572 /* Or maybe we want to generate the error's suppression? */
573 if (VG_(clo_gen_suppressions) == 2
574 || (VG_(clo_gen_suppressions) == 1
575 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
577 gen_suppression(err);
579 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
580 VG_(clo_gen_suppressions) = 0;
582 if (count_error && VG_(clo_exit_on_first_error)) {
583 if (VG_(clo_xml))
584 VG_(printf_xml)("</valgrindoutput>\n");
585 VG_(umsg)("\n");
586 VG_(umsg)("Exit program on first error (--exit-on-first-error=yes)\n");
587 VG_(client_exit)( VG_(clo_error_exitcode) );
592 /* Prints an error. Not entirely simple because of the differences
593 between XML and text mode output.
595 In XML mode:
597 * calls the tool's pre-show method, so the tool can create any
598 preamble ahead of the message, if it wants.
600 * prints the opening tag, and the <unique> and <tid> fields
602 * prints the tool-specific parts of the message
604 * if suppression generation is required, a suppression
606 * the closing tag
608 In text mode:
610 * calls the tool's pre-show method, so the tool can create any
611 preamble ahead of the message, if it wants.
613 * prints the tool-specific parts of the message
615 In both modes:
617 * calls do_actions_on_error. This optionally does a gdbserver call
618 and optionally prints a suppression; both of these may require user input.
620 static void pp_Error ( const Error* err, Bool allow_db_attach, Bool xml, Bool count_error )
622 /* If this fails, you probably specified your tool's method
623 dictionary incorrectly. */
624 vg_assert(VG_(needs).tool_errors || err->ekind < 0 /* core errors */);
626 if (xml) {
628 /* Ensure that suppression generation is either completely
629 enabled or completely disabled; either way, we won't require
630 any user input. m_main.process_cmd_line_options should
631 ensure the asserted condition holds. */
632 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
633 || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
635 /* Pre-show it to the tool */
636 if (err->ekind >= 0)
637 VG_TDICT_CALL( tool_before_pp_Error, err );
638 else
639 core_before_pp_Error (err);
641 /* standard preamble */
642 VG_(printf_xml)("<error>\n");
643 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
644 VG_(printf_xml)(" <tid>%u</tid>\n", err->tid);
645 ThreadState* tst = VG_(get_ThreadState)(err->tid);
646 if (tst->thread_name) {
647 VG_(printf_xml)(" <threadname>%s</threadname>\n", tst->thread_name);
650 /* actually print it */
651 if (err->ekind >= 0)
652 VG_TDICT_CALL( tool_pp_Error, err );
653 else
654 core_pp_Error (err);
656 if (VG_(clo_gen_suppressions) > 0)
657 gen_suppression(err);
659 /* postamble */
660 VG_(printf_xml)("</error>\n");
661 VG_(printf_xml)("\n");
663 } else {
665 if (VG_(clo_error_markers)[0])
666 VG_(umsg)("%s\n", VG_(clo_error_markers)[0]);
667 if (err->ekind >= 0)
668 VG_TDICT_CALL( tool_before_pp_Error, err );
669 else
670 core_before_pp_Error(err);
672 if (VG_(tdict).tool_show_ThreadIDs_for_errors
673 && err->tid > 0 && err->tid != last_tid_printed) {
674 ThreadState* tst = VG_(get_ThreadState)(err->tid);
675 if (tst->thread_name) {
676 VG_(umsg)("Thread %u %s:\n", err->tid, tst->thread_name );
677 } else {
678 VG_(umsg)("Thread %u:\n", err->tid );
680 last_tid_printed = err->tid;
683 if (err->ekind >= 0) {
684 VG_TDICT_CALL( tool_pp_Error, err );
685 VG_(umsg)("\n");
686 } else {
687 core_pp_Error(err);
689 if (VG_(clo_error_markers)[1])
690 VG_(umsg)("%s\n", VG_(clo_error_markers)[1]);
694 do_actions_on_error(err, allow_db_attach, count_error);
698 /* Construct an error */
699 static
700 void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
701 const HChar* s, void* extra, ExeContext* where )
703 /* DO NOT MAKE unique_counter NON-STATIC */
704 static UInt unique_counter = 0;
706 vg_assert(tid < VG_N_THREADS);
708 /* Core-only parts */
709 err->unique = unique_counter++;
710 err->next = NULL;
711 err->supp = NULL;
712 err->count = 1;
713 err->tid = tid;
714 if (NULL == where && VG_(is_valid_tid)(tid))
715 err->where = VG_(record_ExeContext)( tid, 0 );
716 else
717 err->where = where;
719 /* Tool-relevant parts */
720 err->ekind = ekind;
721 err->addr = a;
722 err->extra = extra;
723 err->string = s;
725 /* sanity... */
726 vg_assert( tid < VG_N_THREADS );
731 /* Top-level entry point to the error management subsystem.
732 All detected errors are notified here; this routine decides if/when the
733 user should see the error. */
734 void VG_(maybe_record_error) ( ThreadId tid,
735 ErrorKind ekind, Addr a,
736 const HChar* s, void* extra )
738 Error err;
739 Error* p;
740 Error* p_prev;
741 UInt extra_size;
742 VgRes exe_res = Vg_MedRes;
743 static Bool stopping_message = False;
744 static Bool slowdown_message = False;
746 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
747 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
748 have been found, just refuse to collect any more. This stops
749 the burden of the error-management system becoming excessive in
750 extremely buggy programs, although it does make it pretty
751 pointless to continue the Valgrind run after this point. */
752 if (VG_(clo_error_limit)
753 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
754 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
755 && !VG_(clo_xml)) {
756 if (!stopping_message) {
757 VG_(umsg)("\n");
759 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
760 VG_(umsg)(
761 "More than %d different errors detected. "
762 "I'm not reporting any more.\n",
763 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
764 } else {
765 VG_(umsg)(
766 "More than %d total errors detected. "
767 "I'm not reporting any more.\n",
768 M_COLLECT_NO_ERRORS_AFTER_FOUND );
771 VG_(umsg)("Final error counts will be inaccurate. "
772 "Go fix your program!\n");
773 VG_(umsg)("Rerun with --error-limit=no to disable "
774 "this cutoff. Note\n");
775 VG_(umsg)("that errors may occur in your program without "
776 "prior warning from\n");
777 VG_(umsg)("Valgrind, because errors are no longer "
778 "being displayed.\n");
779 VG_(umsg)("\n");
780 stopping_message = True;
782 return;
785 /* Ignore it if error acquisition is disabled for this thread. */
786 { ThreadState* tst = VG_(get_ThreadState)(tid);
787 if (tst->err_disablement_level > 0)
788 return;
791 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
792 been found, be much more conservative about collecting new
793 ones. */
794 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
795 && !VG_(clo_xml)) {
796 exe_res = Vg_LowRes;
797 if (!slowdown_message) {
798 VG_(umsg)("\n");
799 VG_(umsg)("More than %d errors detected. Subsequent errors\n",
800 M_COLLECT_ERRORS_SLOWLY_AFTER);
801 VG_(umsg)("will still be recorded, but in less "
802 "detail than before.\n");
803 slowdown_message = True;
807 /* Build ourselves the error */
808 construct_error ( &err, tid, ekind, a, s, extra, NULL );
810 /* First, see if we've got an error record matching this one. */
811 em_errlist_searches++;
812 p = errors;
813 p_prev = NULL;
814 while (p != NULL) {
815 em_errlist_cmps++;
816 if (eq_Error(exe_res, p, &err)) {
817 /* Found it. */
818 p->count++;
819 if (p->supp != NULL) {
820 /* Deal correctly with suppressed errors. */
821 p->supp->count++;
822 n_errs_suppressed++;
823 } else {
824 n_errs_found++;
827 /* Move p to the front of the list so that future searches
828 for it are faster. It also allows to print the last
829 error (see VG_(show_last_error). */
830 if (p_prev != NULL) {
831 vg_assert(p_prev->next == p);
832 p_prev->next = p->next;
833 p->next = errors;
834 errors = p;
837 return;
839 p_prev = p;
840 p = p->next;
843 /* Didn't see it. Copy and add. */
845 /* OK, we're really going to collect it. The context is on the stack and
846 will disappear shortly, so we must copy it. First do the main
847 (non-'extra') part.
849 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
850 is for when there are more details to fill in which take time to work
851 out but don't affect our earlier decision to include the error -- by
852 postponing those details until now, we avoid the extra work in the
853 case where we ignore the error. Ugly.
855 Then, if there is an 'extra' part, copy it too, using the size that
856 VG_(tdict).tool_update_extra returned. Also allow for people using
857 the void* extra field for a scalar value like an integer.
860 /* copy main part */
861 p = VG_(malloc)("errormgr.mre.1", sizeof(Error));
862 *p = err;
864 /* update 'extra' */
865 if (ekind < 0) {
866 /* core error */
867 extra_size = core_update_extra (p);
868 } else {
869 vg_assert(VG_(needs).tool_errors);
870 extra_size = VG_TDICT_CALL(tool_update_extra, p);
873 /* copy the error string, if there is one.
874 note: if we would have many errors with big strings, using a
875 DedupPoolAlloc for these strings will avoid duplicating
876 such string in each error using it. */
877 if (NULL != p->string) {
878 p->string = VG_(strdup)("errormgr.mre.2", p->string);
881 /* copy block pointed to by 'extra', if there is one */
882 if (NULL != p->extra && 0 != extra_size) {
883 void* new_extra = VG_(malloc)("errormgr.mre.3", extra_size);
884 VG_(memcpy)(new_extra, p->extra, extra_size);
885 p->extra = new_extra;
888 p->next = errors;
889 p->supp = is_suppressible_error(&err);
890 errors = p;
891 if (p->supp == NULL) {
892 /* update stats */
893 n_err_contexts++;
894 n_errs_found++;
895 n_errs_shown++;
896 /* Actually show the error; more complex than you might think. */
897 pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml), /* count_error */ True );
898 } else {
899 n_supp_contexts++;
900 n_errs_suppressed++;
901 p->supp->count++;
905 /* Second top-level entry point to the error management subsystem, for
906 errors that the tool wants to report immediately, eg. because they're
907 guaranteed to only happen once. This avoids all the recording and
908 comparing stuff. But they can be suppressed; returns True if it is
909 suppressed. Bool 'print_error' dictates whether to print the error.
910 Bool 'count_error' dictates whether to count the error in n_errs_found.
912 Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, const HChar* s,
913 void* extra, ExeContext* where, Bool print_error,
914 Bool allow_db_attach, Bool count_error )
916 Error err;
917 Supp *su;
919 /* Ignore it if error acquisition is disabled for this thread. */
920 ThreadState* tst = VG_(get_ThreadState)(tid);
921 if (tst->err_disablement_level > 0)
922 return False; /* ignored, not suppressed */
924 /* Build ourselves the error */
925 construct_error ( &err, tid, ekind, a, s, extra, where );
927 /* Unless it's suppressed, we're going to show it. Don't need to make
928 a copy, because it's only temporary anyway.
930 Then update the 'extra' part with VG_(tdict).tool_update_extra),
931 because that can have an affect on whether it's suppressed. Ignore
932 the size return value of VG_(tdict).tool_update_extra, because we're
933 not copying 'extra'. Similarly, 's' is also not copied. */
934 if (ekind >= 0)
935 (void)VG_TDICT_CALL(tool_update_extra, &err);
936 else
937 (void)core_update_extra(&err);
939 su = is_suppressible_error(&err);
940 if (NULL == su) {
941 if (count_error) {
942 n_errs_found++;
943 n_err_contexts++;
946 if (print_error) {
947 /* update stats */
948 n_errs_shown++;
949 /* Actually show the error; more complex than you might think. */
950 pp_Error(&err, allow_db_attach, VG_(clo_xml), count_error);
952 return False;
954 } else {
955 if (count_error) {
956 n_errs_suppressed++;
957 n_supp_contexts++;
959 su->count++;
960 return True;
965 /*------------------------------------------------------------*/
966 /*--- Core error fns ---*/
967 /*------------------------------------------------------------*/
969 static Bool is_fd_core_error (const Error *e)
971 return e->ekind == FdBadClose || e->ekind == FdNotClosed ||
972 e->ekind == FdBadUse;
975 static Bool core_eq_Error (VgRes res, const Error *e1, const Error *e2)
977 if (is_fd_core_error(e1))
978 return fd_eq_Error (res, e1, e2);
979 else {
980 VG_(umsg)("FATAL: unknown core error kind: %d\n", e1->ekind );
981 VG_(exit)(1);
985 static void core_before_pp_Error (const Error *err)
987 if (is_fd_core_error(err))
988 fd_before_pp_Error(err);
989 else {
990 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
991 VG_(exit)(1);
995 static void core_pp_Error (const Error *err)
997 if (is_fd_core_error(err))
998 fd_pp_Error(err);
999 else {
1000 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
1001 VG_(exit)(1);
1005 static UInt core_update_extra (const Error *err)
1007 if (is_fd_core_error(err))
1008 return fd_update_extra(err);
1009 else {
1010 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
1011 VG_(exit)(1);
1015 static const HChar *core_get_error_name(const Error *err)
1017 switch (err->ekind) {
1018 case FdBadClose:
1019 return "FdBadClose";
1020 case FdNotClosed:
1021 return "FdNotClosed";
1022 case FdBadUse:
1023 return "FdBadUse";
1024 default:
1025 VG_(umsg)("FATAL: unknown core error kind: %d\n", err->ekind );
1026 VG_(exit)(1);
1030 static Bool core_error_matches_suppression(const Error* err, const Supp* su)
1032 switch (su->skind) {
1033 case FdBadCloseSupp:
1034 return err->ekind == FdBadClose;
1035 case FdNotClosedSupp:
1036 return err->ekind == FdNotClosed;
1037 case FdBadUseSupp:
1038 return err->ekind == FdBadUse;
1039 default:
1040 VG_(umsg)("FATAL: unknown core suppression kind: %d\n", su->skind );
1041 VG_(exit)(1);
1045 static SizeT core_get_extra_suppression_info(const Error *err,
1046 HChar* buf, Int nBuf)
1048 /* No core error has any extra suppression info at the moment. */
1049 buf[0] = '\0';
1050 return 0;
1053 static SizeT core_print_extra_suppression_use(const Supp* su,
1054 HChar* buf, Int nBuf)
1056 /* No core error has any extra suppression info at the moment. */
1057 buf[0] = '\0';
1058 return 0;
1062 /*------------------------------------------------------------*/
1063 /*--- Exported fns ---*/
1064 /*------------------------------------------------------------*/
1066 /* Show the used suppressions. Returns False if no suppression
1067 got used. */
1068 static Bool show_used_suppressions ( void )
1070 Supp *su;
1071 Bool any_supp;
1073 if (VG_(clo_xml))
1074 VG_(printf_xml)("<suppcounts>\n");
1076 any_supp = False;
1077 for (su = suppressions; su != NULL; su = su->next) {
1078 if (su->count <= 0)
1079 continue;
1080 if (VG_(clo_xml)) {
1081 VG_(printf_xml)( " <pair>\n"
1082 " <count>%d</count>\n"
1083 " <name>%pS</name>\n"
1084 " </pair>\n",
1085 su->count, su->sname );
1086 } else {
1087 HChar *xtra = NULL;
1088 Int xtra_size = 0;
1089 SizeT num_written;
1090 // blank line before the first shown suppression, if any
1091 if (!any_supp)
1092 VG_(dmsg)("\n");
1094 do {
1095 xtra_size += 256;
1096 xtra = VG_(realloc)("errormgr.sus.1", xtra, xtra_size);
1097 if (su->skind >= 0)
1098 num_written = VG_TDICT_CALL(tool_print_extra_suppression_use,
1099 su, xtra, xtra_size);
1100 else
1101 num_written = core_print_extra_suppression_use(su,
1102 xtra, xtra_size);
1103 } while (num_written == xtra_size); // resize buffer and retry
1105 // Ensure buffer is properly terminated
1106 vg_assert(xtra[num_written] == '\0');
1108 HChar *filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
1109 su->clo_suppressions_i);
1110 VG_(dmsg)("used_suppression: %6d %s %s:%d%s%s\n", su->count, su->sname,
1111 filename,
1112 su->sname_lineno,
1113 num_written ? " " : "", xtra);
1114 VG_(free)(xtra);
1116 any_supp = True;
1119 if (VG_(clo_xml))
1120 VG_(printf_xml)("</suppcounts>\n");
1122 return any_supp;
1125 /* See pub_core_errormgr.h. */
1126 void VG_(show_all_errors) ( Int verbosity, Bool xml, Int show_error_list)
1128 Int i, n_min;
1129 Error *p, *p_min;
1130 Bool any_supp;
1131 Bool any_error = False;
1132 UInt n_errs;
1134 if (verbosity == 0 && show_error_list == 0)
1135 return;
1137 /* If we're printing XML, just show the suppressions and stop. */
1138 if (xml) {
1139 if (show_error_list > 0)
1140 (void)show_used_suppressions();
1141 return;
1144 /* We only get here if not printing XML. */
1145 VG_(umsg)("ERROR SUMMARY: "
1146 "%u errors from %u contexts (suppressed: %u from %u)\n",
1147 n_errs_found, n_err_contexts,
1148 n_errs_suppressed, n_supp_contexts );
1150 if (show_error_list == 0)
1151 return;
1153 // We do the following if show_error_list > 0
1154 // or at -v or above, and only in non-XML mode.
1156 /* Print the contexts in order of increasing error count.
1157 The below implements this in a quadratic algorithm based on the assumption
1158 that there are not too many errors (including the suppressed if showing
1159 the suppressed errors) !
1160 Once an error is shown, we add a huge value to its count to filter it
1161 out.
1162 After having shown all errors, we reset count to the original value. */
1163 n_errs = n_err_contexts + (show_error_list < 2 ? 0 : n_errs_suppressed);
1164 for (i = 0; i < n_errs; i++) {
1165 n_min = (1 << 30) - 1;
1166 p_min = NULL;
1167 for (p = errors; p != NULL; p = p->next) {
1168 if (show_error_list < 2 && p->supp != NULL) continue;
1169 if (p->count < n_min) {
1170 n_min = p->count;
1171 p_min = p;
1174 // XXX: this isn't right. See bug 203651.
1175 if (p_min == NULL) continue; //VG_(core_panic)("show_all_errors()");
1177 any_error = True;
1178 VG_(umsg)("\n");
1179 VG_(umsg)("%d errors%s%s%s in context %d of %u:\n",
1180 p_min->count,
1181 p_min->supp == NULL ? "" : " (suppressed by ",
1182 p_min->supp == NULL ? "" : p_min->supp->sname,
1183 p_min->supp == NULL ? "" : ")",
1184 i+1, n_errs);
1185 pp_Error( p_min, False/*allow_db_attach*/, False /* xml */, True /* count_error */ );
1187 // We're not printing XML -- we'd have exited above if so.
1188 vg_assert(! xml);
1190 if ((i+1 == VG_(clo_dump_error))) {
1191 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
1192 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1193 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
1194 /*bbs_done*/0,
1195 /*allow redir?*/True);
1198 p_min->count = p_min->count + (1 << 30);
1201 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1202 for (p = errors; p != NULL; p = p->next) {
1203 if (p->count >= (1 << 30))
1204 p->count = p->count - (1 << 30);
1208 any_supp = show_used_suppressions();
1210 if (any_supp)
1211 VG_(umsg)("\n");
1212 // reprint summary, so users don't have to scroll way up to find
1213 // the first printing
1214 if (any_supp || any_error)
1215 VG_(umsg)("ERROR SUMMARY: "
1216 "%u errors from %u contexts (suppressed: %u from %u)\n",
1217 n_errs_found, n_err_contexts, n_errs_suppressed,
1218 n_supp_contexts );
1221 void VG_(show_last_error) ( void )
1223 if (n_err_contexts == 0) {
1224 VG_(umsg)("No errors yet\n");
1225 return;
1228 pp_Error( errors, False/*allow_db_attach*/, False/*xml*/, True/*count_error*/ );
1232 /* Show occurrence counts of all errors, in XML form. */
1233 void VG_(show_error_counts_as_XML) ( void )
1235 Error* err;
1236 VG_(printf_xml)("<errorcounts>\n");
1237 for (err = errors; err != NULL; err = err->next) {
1238 if (err->supp != NULL)
1239 continue;
1240 if (err->count <= 0)
1241 continue;
1242 VG_(printf_xml)(" <pair>\n");
1243 VG_(printf_xml)(" <count>%d</count>\n", err->count);
1244 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
1245 VG_(printf_xml)(" </pair>\n");
1247 VG_(printf_xml)("</errorcounts>\n");
1248 VG_(printf_xml)("\n");
1252 /*------------------------------------------------------------*/
1253 /*--- Suppression parsing ---*/
1254 /*------------------------------------------------------------*/
1256 /* Get the next char from fd into *out_buf. Returns 1 if success,
1257 0 if eof or < 0 if error. */
1259 static Int get_char ( Int fd, HChar* out_buf )
1261 Int r;
1262 static HChar buf[256];
1263 static Int buf_size = 0;
1264 static Int buf_used = 0;
1265 vg_assert(buf_size >= 0 && buf_size <= sizeof buf);
1266 vg_assert(buf_used >= 0 && buf_used <= buf_size);
1267 if (buf_used == buf_size) {
1268 r = VG_(read)(fd, buf, sizeof buf);
1269 if (r < 0) return r; /* read failed */
1270 vg_assert(r >= 0 && r <= sizeof buf);
1271 buf_size = r;
1272 buf_used = 0;
1274 if (buf_size == 0)
1275 return 0; /* eof */
1276 vg_assert(buf_size >= 0 && buf_size <= sizeof buf);
1277 vg_assert(buf_used >= 0 && buf_used < buf_size);
1278 *out_buf = buf[buf_used];
1279 buf_used++;
1280 return 1;
1283 // Get a non blank non comment line.
1284 // Returns True if eof.
1285 static Bool get_nbnc_line ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno )
1287 HChar* buf = *bufpp;
1288 SizeT nBuf = *nBufp;
1289 HChar ch;
1290 Int n, i;
1292 vg_assert(lineno); // lineno needed to correctly track line numbers.
1294 while (True) {
1295 buf[0] = 0;
1296 /* First, read until a non-blank char appears. */
1297 while (True) {
1298 n = get_char(fd, &ch);
1299 if (n == 1 && !VG_(isspace)(ch)) break;
1300 if (n == 1 && ch == '\n')
1301 (*lineno)++;
1302 if (n <= 0) return True;
1305 /* Now, read the line into buf. */
1306 i = 0;
1307 buf[i++] = ch; buf[i] = 0;
1308 while (True) {
1309 n = get_char(fd, &ch);
1310 if (n <= 0) return False; /* the next call will return True */
1311 if (ch == '\n')
1312 (*lineno)++;
1313 if (ch == '\n') break;
1314 if (i > 0 && i == nBuf-1) {
1315 *nBufp = nBuf = nBuf * 2;
1316 #define RIDICULOUS 100000
1317 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really.
1318 "VG_(get_line): line longer than %d chars, aborting\n",
1319 RIDICULOUS);
1320 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1322 buf[i++] = ch; buf[i] = 0;
1324 while (i > 1 && VG_(isspace)(buf[i-1])) {
1325 i--; buf[i] = 0;
1328 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1329 /* Ok, we have a line. If a non-comment line, return.
1330 If a comment line, start all over again. */
1331 if (buf[0] != '#') return False;
1335 // True if buf starts with fun: or obj: or is ...
1336 static Bool is_location_line (const HChar* buf)
1338 return VG_(strncmp)(buf, "fun:", 4) == 0
1339 || VG_(strncmp)(buf, "obj:", 4) == 0
1340 || VG_(strcmp)(buf, "...") == 0;
1343 Bool VG_(get_line) ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno )
1345 Bool eof = get_nbnc_line (fd, bufpp, nBufp, lineno);
1347 if (eof)
1348 return True;
1350 if (is_location_line(*bufpp))
1351 return True; // Not a extra suppr line
1352 else
1353 return False; // A suppression extra line
1356 /* True if s contains no wildcard (?, *) characters. */
1357 static Bool is_simple_str (const HChar *s)
1359 while (*s) {
1360 if (*s == '?' || *s == '*')
1361 return False;
1362 s++;
1364 return True;
1367 /* buf contains the raw name of a caller, supposedly either
1368 fun:some_function_name or
1369 obj:some_object_name or
1370 src:some_file_name or
1371 src:some_file_name:line# or
1373 Set p->ty and p->name accordingly.
1374 p->name is allocated and set to the string
1375 after the descriptor (fun:, obj:, or src: san line#) part.
1376 p->lineno is set to non-zero if line# specified; 0 otherwise.
1377 Returns False if failed.
1379 static Bool setLocationTy ( SuppLoc* p, const HChar *buf )
1381 if (VG_(strncmp)(buf, "fun:", 4) == 0) {
1382 p->name = VG_(strdup)("errormgr.sLTy.1", buf+4);
1383 p->name_is_simple_str = is_simple_str (p->name);
1384 p->ty = FunName;
1385 return True;
1387 if (VG_(strncmp)(buf, "obj:", 4) == 0) {
1388 p->name = VG_(strdup)("errormgr.sLTy.2", buf+4);
1389 p->name_is_simple_str = is_simple_str (p->name);
1390 p->ty = ObjName;
1391 return True;
1393 if (VG_(strncmp)(buf, "src:", 4) == 0) {
1394 p->name = VG_(strdup)("errormgr.sLTy.3", buf+4);
1395 p->name_is_simple_str = is_simple_str (p->name);
1396 p->ty = SrcName;
1397 HChar *s = VG_(strchr)(p->name, ':');
1398 if (s != NULL) {
1399 *s++ = '\0'; // trim colon
1400 p->lineno = (UInt) VG_(strtoll10)(s, NULL);
1401 } else {
1402 p->lineno = 0;
1404 return True;
1406 if (VG_(strcmp)(buf, "...") == 0) {
1407 p->name = NULL;
1408 p->name_is_simple_str = False;
1409 p->ty = DotDotDot;
1410 return True;
1412 VG_(printf)("location should be \"...\", or should start "
1413 "with \"fun:\", \"obj:\", or \"src:\"\n");
1414 return False;
1418 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1419 static Bool tool_name_present(const HChar *name, const HChar *names)
1421 Bool found;
1422 HChar *s = NULL; /* Shut gcc up */
1423 Int len = VG_(strlen)(name);
1425 found = (NULL != (s = VG_(strstr)(names, name))
1426 && (s == names || *(s-1) == ',')
1427 && (*(s+len) == ',' || *(s+len) == '\0'));
1429 return found;
1432 /* Read suppressions from the file specified in
1433 VG_(clo_suppressions)[clo_suppressions_i]
1434 and place them in the suppressions list. If there's any difficulty
1435 doing this, just give up -- there's no point in trying to recover.
1437 static void load_one_suppressions_file ( Int clo_suppressions_i )
1439 const HChar* filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
1440 clo_suppressions_i);
1441 SysRes sres;
1442 Int fd, i, j, lineno = 0;
1443 Bool got_a_location_line_read_by_tool;
1444 Bool eof;
1445 SizeT nBuf = 200;
1446 HChar* buf = VG_(malloc)("errormgr.losf.1", nBuf);
1447 HChar* tool_names;
1448 HChar* supp_name;
1449 const HChar* err_str = NULL;
1450 SuppLoc tmp_callers[VG_DEEPEST_BACKTRACE];
1452 // Check it's not a directory.
1453 if (VG_(is_dir)( filename )) {
1454 if (VG_(clo_xml))
1455 VG_(printf_xml)("</valgrindoutput>\n");
1456 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
1457 VG_(exit)(1);
1460 // Open the suppression file.
1461 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
1462 if (sr_isError(sres)) {
1463 if (VG_(clo_xml))
1464 VG_(printf_xml)("</valgrindoutput>\n");
1465 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
1466 VG_(exit)(1);
1468 fd = sr_Res(sres);
1470 # define BOMB(S) { err_str = S; goto syntax_error; }
1472 while (True) {
1473 /* Assign and initialise the two suppression halves (core and tool) */
1474 Supp* supp;
1475 supp = VG_(malloc)("errormgr.losf.1", sizeof(Supp));
1476 supp->count = 0;
1478 // Initialise temporary reading-in buffer.
1479 for (i = 0; i < VG_DEEPEST_BACKTRACE; i++) {
1480 tmp_callers[i].ty = NoName;
1481 tmp_callers[i].name_is_simple_str = False;
1482 tmp_callers[i].name = NULL;
1485 supp->string = supp->extra = NULL;
1487 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1488 if (eof) {
1489 VG_(free)(supp);
1490 break;
1493 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
1495 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1497 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1499 supp->sname = VG_(strdup)("errormgr.losf.2", buf);
1500 supp->clo_suppressions_i = clo_suppressions_i;
1501 supp->sname_lineno = lineno;
1503 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1505 if (eof) BOMB("unexpected end-of-file (expecting tool:suppr)");
1507 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1508 i = 0;
1509 while (True) {
1510 if (buf[i] == ':') break;
1511 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1512 i++;
1514 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1516 tool_names = & buf[0];
1517 supp_name = & buf[i+1];
1519 if (VG_(needs).core_errors
1520 && tool_name_present("CoreError", tool_names)) {
1521 // A core suppression
1522 if (VG_STREQ(supp_name, "FdBadClose"))
1523 supp->skind = FdBadCloseSupp;
1524 else if (VG_STREQ(supp_name, "FdNotClosed"))
1525 supp->skind = FdNotClosedSupp;
1526 else if (VG_STREQ(supp_name, "FdBadUse"))
1527 supp->skind = FdBadUseSupp;
1528 else
1529 BOMB("unknown core suppression type");
1531 else if (VG_(needs).tool_errors
1532 && tool_name_present(VG_(details).name, tool_names)) {
1533 // A tool suppression
1534 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
1535 /* Do nothing, function fills in supp->skind */
1536 } else {
1537 BOMB("unknown tool suppression type");
1540 else {
1541 // Ignore rest of suppression
1542 while (True) {
1543 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1544 if (eof) BOMB("unexpected end-of-file (when skipping suppression)");
1545 if (VG_STREQ(buf, "}"))
1546 break;
1548 VG_(free)(supp->sname);
1549 VG_(free)(supp);
1550 continue;
1553 buf[0] = 0;
1554 // tool_read_extra_suppression_info might read lines
1555 // from fd till a location line.
1556 if (VG_(needs).tool_errors
1557 && !VG_TDICT_CALL(tool_read_extra_suppression_info,
1558 fd, &buf, &nBuf, &lineno, supp)) {
1559 BOMB("bad or missing extra suppression info");
1562 // No core errors need to read extra suppression info
1564 got_a_location_line_read_by_tool = buf[0] != 0 && is_location_line(buf);
1566 /* the main frame-descriptor reading loop */
1567 i = 0;
1568 while (True) {
1569 if (got_a_location_line_read_by_tool) {
1570 got_a_location_line_read_by_tool = False;
1571 eof = False;
1572 } else {
1573 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1575 if (eof)
1576 BOMB("unexpected end-of-file (when reading stack trace)");
1577 if (VG_STREQ(buf, "}")) {
1578 if (i > 0) {
1579 break;
1580 } else {
1581 BOMB("missing stack trace");
1584 if (i == VG_DEEPEST_BACKTRACE)
1585 BOMB("too many callers in stack trace");
1586 if (i > 0 && i >= VG_(clo_backtrace_size))
1587 break;
1588 if (!setLocationTy(&(tmp_callers[i]), buf))
1589 BOMB("location should be \"...\", or should start "
1590 "with \"fun:\", \"obj:\", or \"src:\"");
1591 i++;
1594 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1595 // lines and grab the '}'.
1596 if (!VG_STREQ(buf, "}")) {
1597 do {
1598 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno );
1599 } while (!eof && !VG_STREQ(buf, "}"));
1602 // Reject entries which are entirely composed of frame
1603 // level wildcards.
1604 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1605 for (j = 0; j < i; j++) {
1606 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName
1607 || tmp_callers[j].ty == SrcName) {
1608 break;
1610 vg_assert(tmp_callers[j].ty == DotDotDot);
1612 vg_assert(j >= 0 && j <= i);
1613 if (j == i) {
1614 // we didn't find any non-"..." entries
1615 BOMB("suppression must contain at least one location "
1616 "line which is not \"...\"");
1619 // Copy tmp_callers[] into supp->callers[]
1620 supp->n_callers = i;
1621 supp->callers = VG_(malloc)("errormgr.losf.4", i * sizeof(SuppLoc));
1622 for (i = 0; i < supp->n_callers; i++) {
1623 supp->callers[i] = tmp_callers[i];
1626 supp->next = suppressions;
1627 suppressions = supp;
1629 VG_(free)(buf);
1630 VG_(close)(fd);
1631 return;
1633 syntax_error:
1634 if (VG_(clo_xml))
1635 VG_(printf_xml)("</valgrindoutput>\n");
1636 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
1637 filename, lineno );
1638 VG_(umsg)(" %s\n", err_str );
1640 VG_(close)(fd);
1641 VG_(umsg)("exiting now.\n");
1642 VG_(exit)(1);
1644 # undef BOMB
1647 void VG_(add_suppression_file)(const HChar *filename)
1649 HChar *f = VG_(strdup)("errormgr.addsup", filename);
1650 VG_(addToXA)(VG_(clo_suppressions), &f);
1651 if (load_suppressions_called)
1652 load_one_suppressions_file( VG_(sizeXA)(VG_(clo_suppressions)) - 1 );
1655 void VG_(load_suppressions) ( void )
1657 Int i;
1658 suppressions = NULL;
1659 load_suppressions_called = True;
1660 for (i = 0; i < VG_(sizeXA)(VG_(clo_suppressions)); i++) {
1661 if (VG_(clo_verbosity) > 1) {
1662 VG_(dmsg)("Reading suppressions file: %s\n",
1663 *(HChar**) VG_(indexXA)(VG_(clo_suppressions), i));
1665 load_one_suppressions_file( i );
1670 /*------------------------------------------------------------*/
1671 /*--- Matching errors to suppressions ---*/
1672 /*------------------------------------------------------------*/
1674 /* Parameterising functions for the use of VG_(generic_match) in
1675 suppression-vs-error matching. The suppression frames (SuppLoc)
1676 play the role of 'pattern'-element, and the error frames (IPs,
1677 hence simply Addrs) play the role of 'input'. In short then, we're
1678 matching a sequence of Addrs against a pattern composed of a
1679 sequence of SuppLocs.
1681 static Bool supploc_IsStar ( const void* supplocV )
1683 const SuppLoc* supploc = supplocV;
1684 return supploc->ty == DotDotDot;
1687 static Bool supploc_IsQuery ( const void* supplocV )
1689 return False; /* there's no '?' equivalent in the supp syntax */
1692 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1693 needed to match an error with the suppression patterns.
1694 The matching between an IP and a suppression pattern is done either
1695 with the IP function name or with the IP object name.
1696 First time the fun or obj name is needed for an IP member
1697 of a stack trace, it will be computed and stored in names.
1698 Also, if the IP corresponds to one or more inlined function calls,
1699 the inlined function names are expanded.
1700 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1701 allocations and the nr of debuginfo search. */
1702 typedef
1703 struct {
1704 DiEpoch epoch; // used to interpret .ips
1705 StackTrace ips; // stack trace we are lazily completing.
1706 UWord n_ips; // nr of elements in ips.
1708 // VG_(generic_match) calls haveInputInpC to check
1709 // for the presence of an input element identified by ixInput
1710 // (i.e. a number that identifies the ixInput element of the
1711 // input sequence). It calls supp_pattEQinp to match this input
1712 // element with a pattern.
1713 // When inlining info is used to provide inlined function calls
1714 // in stacktraces, one IP in ips can be expanded in several
1715 // function names. So, each time input (or presence of input)
1716 // is requested by VG_(generic_match), we will expand
1717 // more IP of ips till we have expanded enough to reach the
1718 // input element requested (or we cannot expand anymore).
1720 UWord n_ips_expanded;
1721 // n_ips_expanded maintains the nr of elements in ips that we have
1722 // already expanded.
1723 UWord n_expanded;
1724 // n_expanded maintains the nr of elements resulting from the expansion
1725 // of the n_ips_expanded IPs. Without inlined function calls,
1726 // n_expanded == n_ips_expanded. With inlining info,
1727 // n_expanded >= n_ips_expanded.
1729 Int* n_offsets_per_ip;
1730 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1731 // obj_offsets resulting of the expansion of ips[i].
1732 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1733 // This array allows to retrieve the position in ips corresponding to
1734 // an ixInput.
1736 // size (in elements) of fun_offsets and obj_offsets.
1737 // (fun|obj)_offsets are reallocated if more space is needed
1738 // to expand an IP.
1739 UWord sz_offsets;
1741 Int* fun_offsets;
1742 // fun_offsets[ixInput] is the offset in names where the
1743 // function name for the ixInput element of the input sequence
1744 // can be found. As one IP of ips can be expanded in several
1745 // function calls due to inlined function calls, we can have more
1746 // elements in fun_offsets than in ips.
1747 // An offset -1 means the function name has not yet been computed.
1748 Int* obj_offsets;
1749 // Similarly, obj_offsets[ixInput] gives the offset for the
1750 // object name for ips[ixInput]
1751 // (-1 meaning object name not yet been computed).
1753 // All function names and object names will be concatenated
1754 // in names. names is reallocated on demand.
1755 HChar *names;
1756 Int names_szB; // size of names.
1757 Int names_free; // offset first free HChar in names.
1759 IPtoFunOrObjCompleter;
1761 static void pp_ip2fo (const IPtoFunOrObjCompleter* ip2fo)
1763 Int i, j;
1764 Int o;
1766 VG_(printf)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1767 ip2fo->n_ips, ip2fo->n_ips_expanded, ip2fo->n_expanded);
1768 for (i = 0; i < ip2fo->n_ips_expanded; i++) {
1769 o = 0;
1770 for (j = 0; j < i; j++)
1771 o += ip2fo->n_offsets_per_ip[j];
1772 VG_(printf)("ips %d 0x08%lx offset [%d,%d] ",
1773 i, ip2fo->ips[i],
1774 o, o+ip2fo->n_offsets_per_ip[i]-1);
1775 for (j = 0; j < ip2fo->n_offsets_per_ip[i]; j++) {
1776 VG_(printf)("%sfun:%s obj:%s\n",
1777 j == 0 ? "" : " ",
1778 ip2fo->fun_offsets[o+j] == -1 ?
1779 "<not expanded>" : &ip2fo->names[ip2fo->fun_offsets[o+j]],
1780 ip2fo->obj_offsets[o+j] == -1 ?
1781 "<not expanded>" : &ip2fo->names[ip2fo->obj_offsets[o+j]]);
1786 /* free the memory in ip2fo.
1787 At debuglog 4, su (or NULL) will be used to show the matching
1788 (or non matching) with ip2fo. */
1789 static void clearIPtoFunOrObjCompleter ( const Supp *su,
1790 IPtoFunOrObjCompleter* ip2fo)
1792 if (DEBUG_ERRORMGR || VG_(debugLog_getLevel)() >= 4) {
1793 if (su) {
1794 HChar *filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
1795 su->clo_suppressions_i);
1796 VG_(dmsg)("errormgr matching end suppression %s %s:%d matched:\n",
1797 su->sname,
1798 filename,
1799 su->sname_lineno);
1800 } else {
1801 VG_(dmsg)("errormgr matching end no suppression matched:\n");
1803 VG_(pp_StackTrace) (ip2fo->epoch, ip2fo->ips, ip2fo->n_ips);
1804 pp_ip2fo(ip2fo);
1806 if (ip2fo->n_offsets_per_ip) VG_(free)(ip2fo->n_offsets_per_ip);
1807 if (ip2fo->fun_offsets) VG_(free)(ip2fo->fun_offsets);
1808 if (ip2fo->obj_offsets) VG_(free)(ip2fo->obj_offsets);
1809 if (ip2fo->names) VG_(free)(ip2fo->names);
1812 /* Grow ip2fo->names to ensure we have NEEDED characters available
1813 in ip2fo->names and returns a pointer to the first free char. */
1814 static HChar* grow_names(IPtoFunOrObjCompleter* ip2fo, SizeT needed)
1816 if (ip2fo->names_szB
1817 < ip2fo->names_free + needed) {
1818 if (needed < ERRTXT_LEN) needed = ERRTXT_LEN;
1820 ip2fo->names
1821 = VG_(realloc)("foc_names",
1822 ip2fo->names,
1823 ip2fo->names_szB + needed);
1824 ip2fo->names_szB += needed;
1826 return ip2fo->names + ip2fo->names_free;
1829 /* foComplete returns the function name or object name for ixInput.
1830 If needFun, returns the function name for this input
1831 else returns the object name for this input.
1832 The function name or object name will be computed and added in
1833 names if not yet done. */
1834 static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo,
1835 Int ixInput, Bool needFun)
1837 vg_assert (ixInput < ip2fo->n_expanded);
1838 vg_assert (VG_(clo_read_inline_info) || ixInput < ip2fo->n_ips);
1840 // ptr to the offset array for function offsets (if needFun)
1841 // or object offsets (if !needFun).
1842 Int** offsets;
1843 if (needFun)
1844 offsets = &ip2fo->fun_offsets;
1845 else
1846 offsets = &ip2fo->obj_offsets;
1848 // Complete Fun name or Obj name for IP if not yet done.
1849 if ((*offsets)[ixInput] == -1) {
1850 const HChar* caller;
1852 (*offsets)[ixInput] = ip2fo->names_free;
1853 if (DEBUG_ERRORMGR) VG_(printf)("marking %s ixInput %d offset %d\n",
1854 needFun ? "fun" : "obj",
1855 ixInput, ip2fo->names_free);
1856 if (needFun) {
1857 // With inline info, fn names must have been completed already.
1858 vg_assert (!VG_(clo_read_inline_info));
1859 /* Get the function name into 'caller_name', or "???"
1860 if unknown. */
1861 // Nb: C++-mangled names are used in suppressions. Do, though,
1862 // Z-demangle them, since otherwise it's possible to wind
1863 // up comparing "malloc" in the suppression against
1864 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1865 // two of them need to be made to match.
1866 if (!VG_(get_fnname_no_cxx_demangle)(ip2fo->epoch,
1867 ip2fo->ips[ixInput],
1868 &caller,
1869 NULL))
1870 caller = "???";
1871 } else {
1872 /* Get the object name into 'caller_name', or "???"
1873 if unknown. */
1874 UWord i;
1875 UWord last_expand_pos_ips = 0;
1876 UWord pos_ips;
1878 /* First get the pos in ips corresponding to ixInput */
1879 for (pos_ips = 0; pos_ips < ip2fo->n_expanded; pos_ips++) {
1880 last_expand_pos_ips += ip2fo->n_offsets_per_ip[pos_ips];
1881 if (ixInput < last_expand_pos_ips)
1882 break;
1884 /* pos_ips is the position in ips corresponding to ixInput.
1885 last_expand_pos_ips is the last offset in fun/obj where
1886 ips[pos_ips] has been expanded. */
1888 if (!VG_(get_objname)(ip2fo->epoch, ip2fo->ips[pos_ips], &caller))
1889 caller = "???";
1891 // Have all inlined calls pointing at this object name
1892 for (i = last_expand_pos_ips - ip2fo->n_offsets_per_ip[pos_ips] + 1;
1893 i < last_expand_pos_ips;
1894 i++) {
1895 ip2fo->obj_offsets[i] = ip2fo->names_free;
1896 if (DEBUG_ERRORMGR)
1897 VG_(printf) (" set obj_offset %lu to %d\n",
1898 i, ip2fo->names_free);
1901 SizeT caller_len = VG_(strlen)(caller);
1902 HChar* caller_name = grow_names(ip2fo, caller_len + 1);
1903 VG_(strcpy)(caller_name, caller);
1904 ip2fo->names_free += caller_len + 1;
1905 if (DEBUG_ERRORMGR) pp_ip2fo(ip2fo);
1908 return ip2fo->names + (*offsets)[ixInput];
1911 // Grow fun and obj _offsets arrays to have at least n_req elements.
1912 // Ensure n_offsets_per_ip is allocated.
1913 static void grow_offsets(IPtoFunOrObjCompleter* ip2fo, Int n_req)
1915 Int i;
1917 // n_offsets_per_ip must always have the size of the ips array
1918 if (ip2fo->n_offsets_per_ip == NULL) {
1919 ip2fo->n_offsets_per_ip = VG_(malloc)("grow_offsets",
1920 ip2fo->n_ips * sizeof(Int));
1921 for (i = 0; i < ip2fo->n_ips; i++)
1922 ip2fo->n_offsets_per_ip[i] = 0;
1925 if (ip2fo->sz_offsets >= n_req)
1926 return;
1928 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1929 // elements and at least a few more elements than the current size.
1930 if (n_req < ip2fo->n_ips)
1931 n_req = ip2fo->n_ips;
1932 if (n_req < ip2fo->sz_offsets + 5)
1933 n_req = ip2fo->sz_offsets + 5;
1935 ip2fo->fun_offsets = VG_(realloc)("grow_offsets", ip2fo->fun_offsets,
1936 n_req * sizeof(Int));
1937 for (i = ip2fo->sz_offsets; i < n_req; i++)
1938 ip2fo->fun_offsets[i] = -1;
1940 ip2fo->obj_offsets = VG_(realloc)("grow_offsets", ip2fo->obj_offsets,
1941 n_req * sizeof(Int));
1942 for (i = ip2fo->sz_offsets; i < n_req; i++)
1943 ip2fo->obj_offsets[i] = -1;
1945 ip2fo->sz_offsets = n_req;
1948 // Expands more IPs from ip2fo->ips.
1949 static void expandInput (IPtoFunOrObjCompleter* ip2fo, UWord ixInput )
1951 while (ip2fo->n_ips_expanded < ip2fo->n_ips
1952 && ip2fo->n_expanded <= ixInput) {
1953 if (VG_(clo_read_inline_info)) {
1954 // Expand one more IP in one or more calls.
1955 const Addr IP = ip2fo->ips[ip2fo->n_ips_expanded];
1956 InlIPCursor *iipc;
1958 iipc = VG_(new_IIPC)(ip2fo->epoch, IP);
1959 // The only thing we really need is the nr of inlined fn calls
1960 // corresponding to the IP we will expand.
1961 // However, computing this is mostly the same as finding
1962 // the function name. So, let's directly complete the function name.
1963 do {
1964 const HChar *caller;
1965 grow_offsets(ip2fo, ip2fo->n_expanded+1);
1966 ip2fo->fun_offsets[ip2fo->n_expanded] = ip2fo->names_free;
1967 if (!VG_(get_fnname_no_cxx_demangle)(ip2fo->epoch, IP,
1968 &caller,
1969 iipc))
1970 caller = "???";
1971 SizeT caller_len = VG_(strlen)(caller);
1972 HChar* caller_name = grow_names(ip2fo, caller_len + 1);
1973 VG_(strcpy)(caller_name, caller);
1974 ip2fo->names_free += caller_len + 1;
1975 ip2fo->n_expanded++;
1976 ip2fo->n_offsets_per_ip[ip2fo->n_ips_expanded]++;
1977 } while (VG_(next_IIPC)(iipc));
1978 ip2fo->n_ips_expanded++;
1979 VG_(delete_IIPC) (iipc);
1980 } else {
1981 // Without inlined fn call info, expansion simply
1982 // consists in allocating enough elements in (fun|obj)_offsets.
1983 // The function or object names themselves will be completed
1984 // when requested.
1985 Int i;
1986 grow_offsets(ip2fo, ip2fo->n_ips);
1987 ip2fo->n_ips_expanded = ip2fo->n_ips;
1988 ip2fo->n_expanded = ip2fo->n_ips;
1989 for (i = 0; i < ip2fo->n_ips; i++)
1990 ip2fo->n_offsets_per_ip[i] = 1;
1995 static Bool haveInputInpC (void* inputCompleterV, UWord ixInput )
1997 IPtoFunOrObjCompleter* ip2fo = (IPtoFunOrObjCompleter*)inputCompleterV;
1998 expandInput(ip2fo, ixInput);
1999 return ixInput < ip2fo->n_expanded;
2002 static Bool supp_pattEQinp ( const void* supplocV, const void* addrV,
2003 void* inputCompleterV, UWord ixInput )
2005 const SuppLoc* supploc = (const SuppLoc*)supplocV; /* PATTERN */
2006 IPtoFunOrObjCompleter* ip2fo = (IPtoFunOrObjCompleter*)inputCompleterV;
2007 const HChar* funobjsrc_name; // Fun, Obj, or src file name.
2008 UInt src_lineno = 0;
2009 Bool ret;
2011 expandInput(ip2fo, ixInput);
2012 vg_assert(ixInput < ip2fo->n_expanded);
2014 /* So, does this IP address match this suppression-line? */
2015 switch (supploc->ty) {
2016 case DotDotDot:
2017 /* supp_pattEQinp is a callback from VG_(generic_match). As
2018 per the spec thereof (see include/pub_tool_seqmatch.h), we
2019 should never get called with a pattern value for which the
2020 _IsStar or _IsQuery function would return True. Hence
2021 this can't happen. */
2022 vg_assert(0);
2023 case ObjName:
2024 funobjsrc_name = foComplete(ip2fo, ixInput, False /*needFun*/);
2025 break;
2026 case FunName:
2027 funobjsrc_name = foComplete(ip2fo, ixInput, True /*needFun*/);
2028 break;
2029 case SrcName: {
2030 const HChar* src_dirname; // placeholder only
2031 ret = VG_(get_filename_linenum)(VG_(current_DiEpoch)(),
2032 ip2fo->ips[ixInput], &funobjsrc_name, &src_dirname, &src_lineno);
2033 if (!ret) {
2034 /* No file name found for location so no way this is a match. */
2035 return ret;
2037 break;
2039 default:
2040 vg_assert(0);
2043 /* So now we have the function or object name in funobjsrc_name, and
2044 the pattern (at the character level) to match against is in
2045 supploc->name. Hence (and leading to a re-entrant call of
2046 VG_(generic_match) if there is a wildcard character): */
2047 if (supploc->name_is_simple_str)
2048 ret = VG_(strcmp) (supploc->name, funobjsrc_name) == 0;
2049 else
2050 ret = VG_(string_match)(supploc->name, funobjsrc_name);
2051 if (ret && supploc->ty == SrcName && supploc->lineno != 0) {
2052 ret = (supploc->lineno == src_lineno);
2054 if (DEBUG_ERRORMGR)
2055 VG_(printf) ("supp_pattEQinp %s patt %s ixInput %lu value:%s (lineno:%u vs %u) match:%s\n",
2056 supploc->ty == FunName ? "fun" : (supploc->ty == SrcName ? "src" : "obj"),
2057 supploc->name, ixInput, funobjsrc_name,
2058 supploc->ty == SrcName ? supploc->lineno : 0,
2059 supploc->ty == SrcName ? src_lineno : 0,
2060 ret ? "yes" : "no");
2061 return ret;
2064 /////////////////////////////////////////////////////
2066 static Bool supp_matches_callers(IPtoFunOrObjCompleter* ip2fo,
2067 const Supp* su)
2069 /* Unwrap the args and set up the correct parameterisation of
2070 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
2071 supp_pattEQinp. */
2072 /* note, StackTrace ip2fo->ips === Addr* */
2073 SuppLoc* supps = su->callers;
2074 UWord n_supps = su->n_callers;
2075 UWord szbPatt = sizeof(SuppLoc);
2076 Bool matchAll = False; /* we just want to match a prefix */
2077 if (DEBUG_ERRORMGR) {
2078 HChar *filename = *(HChar**) VG_(indexXA)(VG_(clo_suppressions),
2079 su->clo_suppressions_i);
2080 VG_(dmsg)(" errormgr Checking match with %s %s:%d\n",
2081 su->sname,
2082 filename,
2083 su->sname_lineno);
2085 return
2086 VG_(generic_match)(
2087 matchAll,
2088 /*PATT*/supps, szbPatt, n_supps, 0/*initial ixPatt*/,
2089 /*INPUT*/
2090 NULL, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
2091 0/*initial ixInput*/,
2092 supploc_IsStar, supploc_IsQuery, supp_pattEQinp,
2093 ip2fo, haveInputInpC
2097 /////////////////////////////////////////////////////
2099 static
2100 Bool supp_matches_error(const Supp* su, const Error* err)
2102 if (su->skind >= 0) {
2103 if (VG_(needs).tool_errors) {
2104 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
2105 } else {
2106 VG_(printf)(
2107 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
2108 "probably needs to be set.\n",
2109 (UInt)err->ekind);
2110 VG_(core_panic)("unhandled suppression type");
2112 } else {
2113 return core_error_matches_suppression(err, su);
2117 /////////////////////////////////////////////////////
2119 /* Does an error context match a suppression? ie is this a suppressible
2120 error? If so, return a pointer to the Supp record, otherwise NULL.
2121 Tries to minimise the number of symbol searches since they are expensive.
2123 static Supp* is_suppressible_error ( const Error* err )
2125 Supp* su;
2126 Supp* su_prev;
2128 IPtoFunOrObjCompleter ip2fo;
2129 /* Conceptually, ip2fo contains an array of function names and an array of
2130 object names, corresponding to the array of IP of err->where.
2131 These names are just computed 'on demand' (so once maximum),
2132 then stored (efficiently, avoiding too many allocs) in ip2fo to be
2133 re-usable for the matching of the same IP with the next suppression
2134 pattern.
2136 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
2137 of its arguments. It will then pass it to the function
2138 supp_pattEQinp which will then lazily complete the IP function name or
2139 object name inside ip2fo. Next time the fun or obj name for the same
2140 IP is needed (i.e. for the matching with the next suppr pattern), then
2141 the fun or obj name will not be searched again in the debug info. */
2143 if (err->where == NULL)
2144 return NULL;
2146 /* stats gathering */
2147 em_supplist_searches++;
2149 /* Prepare the lazy input completer. */
2150 ip2fo.epoch = VG_(get_ExeContext_epoch)(err->where);
2151 ip2fo.ips = VG_(get_ExeContext_StackTrace)(err->where);
2152 ip2fo.n_ips = VG_(get_ExeContext_n_ips)(err->where);
2153 ip2fo.n_ips_expanded = 0;
2154 ip2fo.n_expanded = 0;
2155 ip2fo.sz_offsets = 0;
2156 ip2fo.n_offsets_per_ip = NULL;
2157 ip2fo.fun_offsets = NULL;
2158 ip2fo.obj_offsets = NULL;
2159 ip2fo.names = NULL;
2160 ip2fo.names_szB = 0;
2161 ip2fo.names_free = 0;
2163 /* See if the error context matches any suppression. */
2164 if (DEBUG_ERRORMGR || VG_(debugLog_getLevel)() >= 4)
2165 VG_(dmsg)("errormgr matching begin\n");
2166 su_prev = NULL;
2167 for (su = suppressions; su != NULL; su = su->next) {
2168 em_supplist_cmps++;
2169 if (supp_matches_error(su, err)
2170 && supp_matches_callers(&ip2fo, su)) {
2171 /* got a match. */
2172 /* Inform the tool that err is suppressed by su. */
2173 if (su->skind >= 0)
2174 (void)VG_TDICT_CALL(tool_update_extra_suppression_use, err, su);
2175 /* No core errors need to update extra suppression info */
2176 /* Move this entry to the head of the list
2177 in the hope of making future searches cheaper. */
2178 if (su_prev) {
2179 vg_assert(su_prev->next == su);
2180 su_prev->next = su->next;
2181 su->next = suppressions;
2182 suppressions = su;
2184 clearIPtoFunOrObjCompleter(su, &ip2fo);
2185 return su;
2187 su_prev = su;
2189 clearIPtoFunOrObjCompleter(NULL, &ip2fo);
2190 return NULL; /* no matches */
2193 /* Show accumulated error-list and suppression-list search stats.
2195 void VG_(print_errormgr_stats) ( void )
2197 VG_(dmsg)(
2198 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
2199 em_supplist_searches, em_supplist_cmps
2201 VG_(dmsg)(
2202 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
2203 em_errlist_searches, em_errlist_cmps
2207 /*--------------------------------------------------------------------*/
2208 /*--- end ---*/
2209 /*--------------------------------------------------------------------*/