2 /*--------------------------------------------------------------------*/
3 /*--- Management of error messages. m_errormgr.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 Julian Seward
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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_threadstate.h" // For VG_N_THREADS
34 #include "pub_core_debugger.h"
35 #include "pub_core_debuginfo.h"
36 #include "pub_core_errormgr.h"
37 #include "pub_core_execontext.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcfile.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_libcproc.h" // For VG_(getpid)()
43 #include "pub_core_seqmatch.h"
44 #include "pub_core_mallocfree.h"
45 #include "pub_core_options.h"
46 #include "pub_core_stacktrace.h"
47 #include "pub_core_tooliface.h"
48 #include "pub_core_translate.h" // for VG_(translate)()
49 #include "pub_core_xarray.h" // VG_(xaprintf) et al
51 /*------------------------------------------------------------*/
53 /*------------------------------------------------------------*/
55 /* After this many different unsuppressed errors have been observed,
56 be more conservative about collecting new ones. */
57 #define M_COLLECT_ERRORS_SLOWLY_AFTER 100
59 /* After this many different unsuppressed errors have been observed,
60 stop collecting errors at all, and tell the user their program is
61 evidently a steaming pile of camel dung. */
62 #define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
64 /* After this many total errors have been observed, stop collecting
65 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
66 #define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
68 /* The list of error contexts found, both suppressed and unsuppressed.
69 Initially empty, and grows as errors are detected. */
70 static Error* errors = NULL;
72 /* The list of suppression directives, as read from the specified
73 suppressions file. Note that the list gets rearranged as a result
74 of the searches done by is_suppressible_error(). */
75 static Supp* suppressions = NULL;
77 /* Running count of unsuppressed errors detected. */
78 static UInt n_errs_found = 0;
80 /* Running count of suppressed errors detected. */
81 static UInt n_errs_suppressed = 0;
83 /* Running count of unsuppressed error contexts. */
84 static UInt n_err_contexts = 0;
86 /* Running count of suppressed error contexts. */
87 static UInt n_supp_contexts = 0;
91 static Supp* is_suppressible_error ( Error* err );
93 static ThreadId last_tid_printed = 1;
95 /* Stats: number of searches of the error list initiated. */
96 static UWord em_errlist_searches = 0;
98 /* Stats: number of comparisons done during error list
100 static UWord em_errlist_cmps = 0;
102 /* Stats: number of searches of the suppression list initiated. */
103 static UWord em_supplist_searches = 0;
105 /* Stats: number of comparisons done during suppression list
107 static UWord em_supplist_cmps = 0;
109 /*------------------------------------------------------------*/
110 /*--- Error type ---*/
111 /*------------------------------------------------------------*/
113 /* Errors. Extensible (via the 'extra' field). Tools can use a normal
114 enum (with element values in the normal range (0..)) for 'ekind'.
115 Functions for getting/setting the tool-relevant fields are in
116 include/pub_tool_errormgr.h.
118 When errors are found and recorded with VG_(maybe_record_error)(), all
119 the tool must do is pass in the four parameters; core will
120 allocate/initialise the error record.
124 // Unique tag. This gives the error a unique identity (handle) by
125 // which it can be referred to afterwords. Currently only used for
128 // NULL if unsuppressed; or ptr to suppression record.
132 // The tool-specific part
133 ThreadId tid; // Initialised by core
134 ExeContext* where; // Initialised by core
135 ErrorKind ekind; // Used by ALL. Must be in the range (0..)
136 Addr addr; // Used frequently
137 Char* string; // Used frequently
138 void* extra; // For any tool-specific extras
142 ExeContext* VG_(get_error_where) ( Error* err )
147 ErrorKind VG_(get_error_kind) ( Error* err )
152 Addr VG_(get_error_address) ( Error* err )
157 Char* VG_(get_error_string) ( Error* err )
162 void* VG_(get_error_extra) ( Error* err )
167 UInt VG_(get_n_errs_found)( void )
172 /*------------------------------------------------------------*/
173 /*--- Suppression type ---*/
174 /*------------------------------------------------------------*/
176 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools
177 * effectively extend it by defining their own enums in the (0..) range. */
180 // Nb: thread errors are a relic of the time when Valgrind's core
181 // could detect them. This example is left commented-out as an
182 // example should new core errors ever be added.
183 ThreadSupp = -1, /* Matches ThreadErr */
187 /* Max number of callers for context in a suppression. */
188 #define VG_MAX_SUPP_CALLERS 24
190 /* For each caller specified for a suppression, record the nature of
191 the caller name. Not of interest to tools. */
194 NoName, /* Error case */
195 ObjName, /* Name is of an shared object file. */
196 FunName, /* Name is of a function. */
197 DotDotDot /* Frame-level wildcard */
204 Char* name; /* NULL for NoName and DotDotDot */
208 /* Suppressions. Tools can get/set tool-relevant parts with functions
209 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
210 Tools can use a normal enum (with element values in the normal range
211 (0..)) for 'skind'. */
214 Int count; // The number of times this error has been suppressed.
215 Char* sname; // The name by which the suppression is referred to.
217 // Length of 'callers'
219 // Array of callers, for matching stack traces. First one (name of fn
220 // where err occurs) is mandatory; rest are optional.
223 /* The tool-specific part */
224 SuppKind skind; // What kind of suppression. Must use the range (0..).
225 Char* string; // String -- use is optional. NULL by default.
226 void* extra; // Anything else -- use is optional. NULL by default.
229 SuppKind VG_(get_supp_kind) ( Supp* su )
234 Char* VG_(get_supp_string) ( Supp* su )
239 void* VG_(get_supp_extra) ( Supp* su )
245 void VG_(set_supp_kind) ( Supp* su, SuppKind skind )
250 void VG_(set_supp_string) ( Supp* su, Char* string )
255 void VG_(set_supp_extra) ( Supp* su, void* extra )
261 /*------------------------------------------------------------*/
262 /*--- Helper fns ---*/
263 /*------------------------------------------------------------*/
265 // Only show core errors if the tool wants to, we're not running with -q,
266 // and were not outputting XML.
267 Bool VG_(showing_core_errors)(void)
269 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
272 /* Compare errors, to detect duplicates.
274 static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
276 if (e1->ekind != e2->ekind)
278 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
282 //(example code, see comment on CoreSuppKind above)
284 // vg_assert(VG_(needs).core_errors);
285 // return <something>
287 if (VG_(needs).tool_errors) {
288 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
290 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
291 "probably needs to be set.\n",
293 VG_(tool_panic)("unhandled error type");
299 /* Helper functions for suppression generation: print a single line of
300 a suppression pseudo-stack-trace, either in XML or text mode. It's
301 important that the behaviour of these two functions exactly
304 #define ERRTXT_LEN 4096
306 static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque)
308 static UChar buf[ERRTXT_LEN];
309 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
310 VG_(printf_xml_no_f_c)(" <sframe> <fun>%t</fun> </sframe>\n", buf);
312 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
313 VG_(printf_xml_no_f_c)(" <sframe> <obj>%t</obj> </sframe>\n", buf);
315 VG_(printf_xml_no_f_c)(" <sframe> <obj>*</obj> </sframe>\n");
319 static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV)
321 static UChar buf[ERRTXT_LEN];
322 XArray* /* of HChar */ text = (XArray*)textV;
323 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) {
324 VG_(xaprintf)(text, " fun:%s\n", buf);
326 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
327 VG_(xaprintf)(text, " obj:%s\n", buf);
329 VG_(xaprintf)(text, " obj:*\n");
333 /* Generate a suppression for an error, either in text or XML mode.
335 static void gen_suppression(Error* err)
337 Char xtra[256]; /* assumed big enough (is overrun-safe) */
341 XArray* /* HChar */ text;
343 const HChar* dummy_name = "insert_a_suppression_name_here";
347 /* In XML mode, we also need to print the plain text version of the
348 suppresion in a CDATA section. What that really means is, we
349 need to generate the plaintext version both in XML and text
350 mode. So generate it into TEXT. */
351 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
352 VG_(free), sizeof(HChar) );
355 ec = VG_(get_error_where)(err);
358 name = VG_TDICT_CALL(tool_get_error_name, err);
360 VG_(umsg)("(%s does not allow error to be suppressed)\n",
365 /* Ok. Generate the plain text version into TEXT. */
366 VG_(xaprintf)(text, "{\n");
367 VG_(xaprintf)(text, " <%s>\n", dummy_name);
368 VG_(xaprintf)(text, " %s:%s\n", VG_(details).name, name);
370 VG_(memset)(xtra, 0, sizeof(xtra));
371 anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info,
372 err, xtra, sizeof(xtra));
373 vg_assert(xtra[sizeof(xtra)-1] == 0);
376 VG_(xaprintf)(text, " %s\n", xtra);
378 // Print stack trace elements
379 VG_(apply_StackTrace)(printSuppForIp_nonXML,
381 VG_(get_ExeContext_StackTrace)(ec),
382 VG_(get_ExeContext_n_ips)(ec));
384 VG_(xaprintf)(text, "}\n");
386 VG_(xaprintf)(text, "%c", (HChar)0 );
387 // VG_(printf) of text
389 /* And now display it. */
390 if (! VG_(clo_xml) ) {
393 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
397 /* Now we have to print the XML directly. No need to go to the
398 effort of stuffing it in an XArray, since we won't need it
400 VG_(printf_xml)(" <suppression>\n");
401 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name);
402 VG_(printf_xml_no_f_c)(
403 " <skind>%t:%t</skind>\n", VG_(details).name, name);
405 VG_(printf_xml_no_f_c)(" <skaux>%t</skaux>\n", xtra);
407 // Print stack trace elements
408 VG_(apply_StackTrace)(printSuppForIp_XML,
410 VG_(get_ExeContext_StackTrace)(ec),
411 VG_(get_ExeContext_n_ips)(ec));
413 // And now the cdata bit
414 // XXX FIXME! properly handle the case where the raw text
415 // itself contains "]]>", as specified in Protocol 4.
416 VG_(printf_xml)(" <rawtext>\n");
417 VG_(printf_xml)("<![CDATA[\n");
418 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
419 VG_(printf_xml)("]]>\n");
420 VG_(printf_xml)(" </rawtext>\n");
421 VG_(printf_xml)(" </suppression>\n");
429 /* Figure out if we want to perform a given action for this error,
430 possibly by asking the user.
432 Bool VG_(is_action_requested) ( Char* action, Bool* clo )
437 /* First off, we shouldn't be asking the user anything if
438 we're in XML mode. */
440 return False; /* That's a Nein, oder Nay as they say down here in B-W */
450 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
451 VG_(getpid)(), action
454 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
455 if (res != 1) goto ioerror;
457 if (ch == '\n') return False;
458 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
459 && ch != 'C' && ch != 'c') goto again;
461 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
462 if (res != 1) goto ioerror;
463 if (ch2 != '\n') goto again;
465 /* No, don't want to do action. */
466 if (ch == 'n' || ch == 'N') return False;
467 /* Yes, want to do action. */
468 if (ch == 'y' || ch == 'Y') return True;
469 /* No, don't want to do action, and don't ask again either. */
470 vg_assert(ch == 'c' || ch == 'C');
478 /* Do text-mode actions on error, that is, immediately after an error
479 is printed. These are:
480 * possibly, attach to a debugger
481 * possibly, generate a suppression.
482 Note this should not be called in XML mode!
485 void do_actions_on_error(Error* err, Bool allow_db_attach)
487 Bool still_noisy = True;
489 /* Should be assured by caller */
490 vg_assert( ! VG_(clo_xml) );
492 /* Perhaps we want a debugger attach at this point? */
493 if (allow_db_attach &&
494 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
496 if (0) VG_(printf)("starting debugger\n");
497 VG_(start_debugger)( err->tid );
499 /* Or maybe we want to generate the error's suppression? */
500 if (VG_(clo_gen_suppressions) == 2
501 || (VG_(clo_gen_suppressions) == 1
502 && VG_(is_action_requested)( "Print suppression", &still_noisy ))
504 gen_suppression(err);
506 if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
507 VG_(clo_gen_suppressions) = 0;
511 /* Prints an error. Not entirely simple because of the differences
512 between XML and text mode output.
516 * calls the tool's pre-show method, so the tool can create any
517 preamble ahead of the message, if it wants.
519 * prints the opening tag, and the <unique> and <tid> fields
521 * prints the tool-specific parts of the message
523 * if suppression generation is required, a suppression
529 * calls the tool's pre-show method, so the tool can create any
530 preamble ahead of the message, if it wants.
532 * prints the tool-specific parts of the message
534 * calls do_actions_on_error. This optionally does a debugger
535 attach (and detach), and optionally prints a suppression; both
536 of these may require user input.
538 static void pp_Error ( Error* err, Bool allow_db_attach )
540 /* If this fails, you probably specified your tool's method
541 dictionary incorrectly. */
542 vg_assert(VG_(needs).tool_errors);
546 /* Note, allow_db_attach is ignored in here. */
548 /* Ensure that suppression generation is either completely
549 enabled or completely disabled; either way, we won't require
550 any user input. m_main.process_cmd_line_options should
551 ensure the asserted condition holds. */
552 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
553 || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
555 /* Pre-show it to the tool */
556 VG_TDICT_CALL( tool_before_pp_Error, err );
558 /* standard preamble */
559 VG_(printf_xml)("<error>\n");
560 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
561 VG_(printf_xml)(" <tid>%d</tid>\n", err->tid);
563 /* actually print it */
564 VG_TDICT_CALL( tool_pp_Error, err );
566 if (VG_(clo_gen_suppressions) > 0)
567 gen_suppression(err);
570 VG_(printf_xml)("</error>\n");
571 VG_(printf_xml)("\n");
575 VG_TDICT_CALL( tool_before_pp_Error, err );
577 if (VG_(tdict).tool_show_ThreadIDs_for_errors
578 && err->tid > 0 && err->tid != last_tid_printed) {
579 VG_(umsg)("Thread %d:\n", err->tid );
580 last_tid_printed = err->tid;
583 VG_TDICT_CALL( tool_pp_Error, err );
586 do_actions_on_error(err, allow_db_attach);
591 /* Construct an error */
593 void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
594 Char* s, void* extra, ExeContext* where )
596 /* DO NOT MAKE unique_counter NON-STATIC */
597 static UInt unique_counter = 0;
599 tl_assert(tid < VG_N_THREADS);
601 /* Core-only parts */
602 err->unique = unique_counter++;
608 err->where = VG_(record_ExeContext)( tid, 0 );
612 /* Tool-relevant parts */
619 vg_assert( tid < VG_N_THREADS );
624 static Int n_errs_shown = 0;
626 /* Top-level entry point to the error management subsystem.
627 All detected errors are notified here; this routine decides if/when the
628 user should see the error. */
629 void VG_(maybe_record_error) ( ThreadId tid,
630 ErrorKind ekind, Addr a, Char* s, void* extra )
636 VgRes exe_res = Vg_MedRes;
637 static Bool stopping_message = False;
638 static Bool slowdown_message = False;
640 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
641 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
642 have been found, just refuse to collect any more. This stops
643 the burden of the error-management system becoming excessive in
644 extremely buggy programs, although it does make it pretty
645 pointless to continue the Valgrind run after this point. */
646 if (VG_(clo_error_limit)
647 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
648 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
650 if (!stopping_message) {
653 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
655 "More than %d different errors detected. "
656 "I'm not reporting any more.\n",
657 M_COLLECT_NO_ERRORS_AFTER_SHOWN );
660 "More than %d total errors detected. "
661 "I'm not reporting any more.\n",
662 M_COLLECT_NO_ERRORS_AFTER_FOUND );
665 VG_(umsg)("Final error counts will be inaccurate. "
666 "Go fix your program!\n");
667 VG_(umsg)("Rerun with --error-limit=no to disable "
668 "this cutoff. Note\n");
669 VG_(umsg)("that errors may occur in your program without "
670 "prior warning from\n");
671 VG_(umsg)("Valgrind, because errors are no longer "
672 "being displayed.\n");
674 stopping_message = True;
679 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
680 been found, be much more conservative about collecting new
682 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
685 if (!slowdown_message) {
687 VG_(umsg)("More than %d errors detected. Subsequent errors\n",
688 M_COLLECT_ERRORS_SLOWLY_AFTER);
689 VG_(umsg)("will still be recorded, but in less "
690 "detail than before.\n");
691 slowdown_message = True;
695 /* Build ourselves the error */
696 construct_error ( &err, tid, ekind, a, s, extra, NULL );
698 /* First, see if we've got an error record matching this one. */
699 em_errlist_searches++;
704 if (eq_Error(exe_res, p, &err)) {
707 if (p->supp != NULL) {
708 /* Deal correctly with suppressed errors. */
715 /* Move p to the front of the list so that future searches
716 for it are faster. */
717 if (p_prev != NULL) {
718 vg_assert(p_prev->next == p);
719 p_prev->next = p->next;
730 /* Didn't see it. Copy and add. */
732 /* OK, we're really going to collect it. The context is on the stack and
733 will disappear shortly, so we must copy it. First do the main
736 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
737 is for when there are more details to fill in which take time to work
738 out but don't affect our earlier decision to include the error -- by
739 postponing those details until now, we avoid the extra work in the
740 case where we ignore the error. Ugly.
742 Then, if there is an 'extra' part, copy it too, using the size that
743 VG_(tdict).tool_update_extra returned. Also allow for people using
744 the void* extra field for a scalar value like an integer.
748 p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
753 //(example code, see comment on CoreSuppKind above)
755 // vg_assert(VG_(needs).core_errors);
756 // extra_size = <something>
759 vg_assert(VG_(needs).tool_errors);
760 extra_size = VG_TDICT_CALL(tool_update_extra, p);
764 /* copy block pointed to by 'extra', if there is one */
765 if (NULL != p->extra && 0 != extra_size) {
766 void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
767 VG_(memcpy)(new_extra, p->extra, extra_size);
768 p->extra = new_extra;
772 p->supp = is_suppressible_error(&err);
774 if (p->supp == NULL) {
777 /* Actually show the error; more complex than you might think. */
778 pp_Error( p, /*allow_db_attach*/True );
788 /* Second top-level entry point to the error management subsystem, for
789 errors that the tool wants to report immediately, eg. because they're
790 guaranteed to only happen once. This avoids all the recording and
791 comparing stuff. But they can be suppressed; returns True if it is
792 suppressed. Bool 'print_error' dictates whether to print the error.
793 Bool 'count_error' dictates whether to count the error in n_errs_found.
795 Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
796 void* extra, ExeContext* where, Bool print_error,
797 Bool allow_db_attach, Bool count_error )
802 /* Build ourselves the error */
803 construct_error ( &err, tid, ekind, a, s, extra, where );
805 /* Unless it's suppressed, we're going to show it. Don't need to make
806 a copy, because it's only temporary anyway.
808 Then update the 'extra' part with VG_(tdict).tool_update_extra),
809 because that can have an affect on whether it's suppressed. Ignore
810 the size return value of VG_(tdict).tool_update_extra, because we're
811 not copying 'extra'. */
812 (void)VG_TDICT_CALL(tool_update_extra, &err);
814 su = is_suppressible_error(&err);
822 /* Actually show the error; more complex than you might think. */
823 pp_Error(&err, allow_db_attach);
840 /*------------------------------------------------------------*/
841 /*--- Exported fns ---*/
842 /*------------------------------------------------------------*/
844 /* Show the used suppressions. Returns False if no suppression
846 static Bool show_used_suppressions ( void )
852 VG_(printf_xml)("<suppcounts>\n");
855 for (su = suppressions; su != NULL; su = su->next) {
859 VG_(printf_xml_no_f_c)( " <pair>\n"
860 " <count>%d</count>\n"
863 su->count, su->sname );
865 // blank line before the first shown suppression, if any
868 VG_(dmsg)("used_suppression: %6d %s\n", su->count, su->sname);
874 VG_(printf_xml)("</suppcounts>\n");
880 /* Show all the errors that occurred, and possibly also the
881 suppressions used. */
882 void VG_(show_all_errors) ( void )
888 if (VG_(clo_verbosity) == 0)
891 /* If we're printing XML, just show the suppressions and stop. */
893 (void)show_used_suppressions();
897 /* We only get here if not printing XML. */
898 VG_(umsg)("ERROR SUMMARY: "
899 "%d errors from %d contexts (suppressed: %d from %d)\n",
900 n_errs_found, n_err_contexts,
901 n_errs_suppressed, n_supp_contexts );
903 if (VG_(clo_verbosity) <= 1)
906 // We do the following only at -v or above, and only in non-XML
909 /* Print the contexts in order of increasing error count. */
910 for (i = 0; i < n_err_contexts; i++) {
911 n_min = (1 << 30) - 1;
913 for (p = errors; p != NULL; p = p->next) {
914 if (p->supp != NULL) continue;
915 if (p->count < n_min) {
920 // XXX: this isn't right. See bug 203651.
921 if (p_min == NULL) continue; //VG_(tool_panic)("show_all_errors()");
924 VG_(umsg)("%d errors in context %d of %d:\n",
925 p_min->count, i+1, n_err_contexts);
926 pp_Error( p_min, False/*allow_db_attach*/ );
928 // We're not printing XML -- we'd have exited above if so.
929 vg_assert(! VG_(clo_xml));
931 if ((i+1 == VG_(clo_dump_error))) {
932 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
933 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
934 ips[0], /*debugging*/True, 0xFE/*verbosity*/,
936 /*allow redir?*/True);
939 p_min->count = 1 << 30;
942 any_supp = show_used_suppressions();
946 // reprint this, so users don't have to scroll way up to find
947 // the first printing
948 VG_(umsg)("ERROR SUMMARY: "
949 "%d errors from %d contexts (suppressed: %d from %d)\n",
950 n_errs_found, n_err_contexts, n_errs_suppressed,
955 /* Show occurrence counts of all errors, in XML form. */
956 void VG_(show_error_counts_as_XML) ( void )
959 VG_(printf_xml)("<errorcounts>\n");
960 for (err = errors; err != NULL; err = err->next) {
961 if (err->supp != NULL)
965 VG_(printf_xml)(" <pair>\n");
966 VG_(printf_xml)(" <count>%d</count>\n", err->count);
967 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique);
968 VG_(printf_xml)(" </pair>\n");
970 VG_(printf_xml)("</errorcounts>\n");
971 VG_(printf_xml)("\n");
975 /*------------------------------------------------------------*/
976 /*--- Suppression parsing ---*/
977 /*------------------------------------------------------------*/
979 /* Get the next char from fd into *out_buf. Returns 1 if success,
980 0 if eof or < 0 if error. */
982 static Int get_char ( Int fd, Char* out_buf )
985 static Char buf[256];
986 static Int buf_size = 0;
987 static Int buf_used = 0;
988 vg_assert(buf_size >= 0 && buf_size <= 256);
989 vg_assert(buf_used >= 0 && buf_used <= buf_size);
990 if (buf_used == buf_size) {
991 r = VG_(read)(fd, buf, 256);
992 if (r < 0) return r; /* read failed */
993 vg_assert(r >= 0 && r <= 256);
999 vg_assert(buf_size >= 0 && buf_size <= 256);
1000 vg_assert(buf_used >= 0 && buf_used < buf_size);
1001 *out_buf = buf[buf_used];
1006 Bool VG_(get_line) ( Int fd, Char** bufpp, SizeT* nBufp, Int* lineno )
1009 SizeT nBuf = *nBufp;
1013 /* First, read until a non-blank char appears. */
1015 n = get_char(fd, &ch);
1016 if (n == 1 && !VG_(isspace)(ch)) break;
1017 if (n == 1 && ch == '\n' && lineno)
1019 if (n <= 0) return True;
1022 /* Now, read the line into buf. */
1024 buf[i++] = ch; buf[i] = 0;
1026 n = get_char(fd, &ch);
1027 if (n <= 0) return False; /* the next call will return True */
1028 if (ch == '\n' && lineno)
1030 if (ch == '\n') break;
1031 if (i > 0 && i == nBuf-1) {
1032 *nBufp = nBuf = nBuf * 2;
1033 #define RIDICULOUS 100000
1034 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really.
1035 "VG_(get_line): line longer than %d chars, aborting\n",
1037 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1039 buf[i++] = ch; buf[i] = 0;
1041 while (i > 1 && VG_(isspace)(buf[i-1])) {
1045 /* VG_(printf)("The line is '%s'\n", buf); */
1046 /* Ok, we have a line. If a non-comment line, return.
1047 If a comment line, start all over again. */
1048 if (buf[0] != '#') return False;
1053 /* *p_caller contains the raw name of a caller, supposedly either
1054 fun:some_function_name or
1055 obj:some_object_name.
1056 Set *p_ty accordingly and advance *p_caller over the descriptor
1057 (fun: or obj:) part.
1058 Returns False if failed.
1060 static Bool setLocationTy ( SuppLoc* p )
1062 if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
1067 if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
1072 if (VG_(strcmp)(p->name, "...") == 0) {
1077 VG_(printf)("location should be \"...\", or should start "
1078 "with \"fun:\" or \"obj:\"\n");
1083 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1084 static Bool tool_name_present(Char *name, Char *names)
1087 Char *s = NULL; /* Shut gcc up */
1088 Int len = VG_(strlen)(name);
1090 found = (NULL != (s = VG_(strstr)(names, name)) &&
1091 (s == names || *(s-1) == ',') &&
1092 (*(s+len) == ',' || *(s+len) == '\0')
1098 /* Read suppressions from the file specified in VG_(clo_suppressions)
1099 and place them in the suppressions list. If there's any difficulty
1100 doing this, just give up -- there's no point in trying to recover.
1102 static void load_one_suppressions_file ( Char* filename )
1105 Int fd, i, j, lineno = 0;
1108 Char* buf = VG_(malloc)("errormgr.losf.1", nBuf);
1111 Char* err_str = NULL;
1112 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
1114 // Check it's not a directory.
1115 if (VG_(is_dir)( filename )) {
1117 VG_(umsg)("</valgrindoutput>\n");
1118 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
1122 // Open the suppression file.
1123 sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
1124 if (sr_isError(sres)) {
1126 VG_(umsg)("</valgrindoutput>\n");
1127 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
1132 # define BOMB(S) { err_str = S; goto syntax_error; }
1135 /* Assign and initialise the two suppression halves (core and tool) */
1137 supp = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
1141 // Initialise temporary reading-in buffer.
1142 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
1143 tmp_callers[i].ty = NoName;
1144 tmp_callers[i].name = NULL;
1147 supp->string = supp->extra = NULL;
1149 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1152 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
1154 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1156 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1158 supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
1160 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1162 if (eof) BOMB("unexpected end-of-file");
1164 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1167 if (buf[i] == ':') break;
1168 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1171 buf[i] = '\0'; /* Replace ':', splitting into two strings */
1173 tool_names = & buf[0];
1174 supp_name = & buf[i+1];
1176 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
1178 // A core suppression
1179 //(example code, see comment on CoreSuppKind above)
1180 //if (VG_STREQ(supp_name, "Thread"))
1181 // supp->skind = ThreadSupp;
1183 BOMB("unknown core suppression type");
1185 else if (VG_(needs).tool_errors &&
1186 tool_name_present(VG_(details).name, tool_names))
1188 // A tool suppression
1189 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
1190 /* Do nothing, function fills in supp->skind */
1192 BOMB("unknown tool suppression type");
1196 // Ignore rest of suppression
1198 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1199 if (eof) BOMB("unexpected end-of-file");
1200 if (VG_STREQ(buf, "}"))
1206 if (VG_(needs).tool_errors &&
1207 !VG_TDICT_CALL(tool_read_extra_suppression_info,
1208 fd, &buf, &nBuf, supp))
1210 BOMB("bad or missing extra suppression info");
1213 /* the main frame-descriptor reading loop */
1216 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1218 BOMB("unexpected end-of-file");
1219 if (VG_STREQ(buf, "}")) {
1223 BOMB("missing stack trace");
1226 if (i == VG_MAX_SUPP_CALLERS)
1227 BOMB("too many callers in stack trace");
1228 if (i > 0 && i >= VG_(clo_backtrace_size))
1230 tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE,
1231 "errormgr.losf.3", buf);
1232 if (!setLocationTy(&(tmp_callers[i])))
1233 BOMB("location should be \"...\", or should start "
1234 "with \"fun:\" or \"obj:\"");
1238 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1239 // lines and grab the '}'.
1240 if (!VG_STREQ(buf, "}")) {
1242 eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1243 } while (!eof && !VG_STREQ(buf, "}"));
1246 // Reject entries which are entirely composed of frame
1248 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1249 for (j = 0; j < i; j++) {
1250 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
1252 vg_assert(tmp_callers[j].ty == DotDotDot);
1254 vg_assert(j >= 0 && j <= i);
1256 // we didn't find any non-"..." entries
1257 BOMB("suppression must contain at least one location "
1258 "line which is not \"...\"");
1261 // Copy tmp_callers[] into supp->callers[]
1262 supp->n_callers = i;
1263 supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
1265 for (i = 0; i < supp->n_callers; i++) {
1266 supp->callers[i] = tmp_callers[i];
1269 supp->next = suppressions;
1270 suppressions = supp;
1278 VG_(umsg)("</valgrindoutput>\n");
1279 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
1281 VG_(umsg)(" %s\n", err_str );
1284 VG_(umsg)("exiting now.\n");
1291 void VG_(load_suppressions) ( void )
1294 suppressions = NULL;
1295 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1296 if (VG_(clo_verbosity) > 1) {
1297 VG_(dmsg)("Reading suppressions file: %s\n",
1298 VG_(clo_suppressions)[i] );
1300 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1305 /*------------------------------------------------------------*/
1306 /*--- Matching errors to suppressions ---*/
1307 /*------------------------------------------------------------*/
1309 /* Parameterising functions for the use of VG_(generic_match) in
1310 suppression-vs-error matching. The suppression frames (SuppLoc)
1311 play the role of 'pattern'-element, and the error frames (IPs,
1312 hence simply Addrs) play the role of 'input'. In short then, we're
1313 matching a sequence of Addrs against a pattern composed of a
1314 sequence of SuppLocs.
1316 static Bool supploc_IsStar ( void* supplocV )
1318 SuppLoc* supploc = (SuppLoc*)supplocV;
1319 return supploc->ty == DotDotDot;
1322 static Bool supploc_IsQuery ( void* supplocV )
1324 return False; /* there's no '?' equivalent in the supp syntax */
1327 static Bool supp_pattEQinp ( void* supplocV, void* addrV )
1329 SuppLoc* supploc = (SuppLoc*)supplocV; /* PATTERN */
1330 Addr ip = *(Addr*)addrV; /* INPUT */
1332 Char caller_name[ERRTXT_LEN];
1335 /* So, does this IP address match this suppression-line? */
1336 switch (supploc->ty) {
1338 /* supp_pattEQinp is a callback from VG_(generic_match). As
1339 per the spec thereof (see include/pub_tool_seqmatch.h), we
1340 should never get called with a pattern value for which the
1341 _IsStar or _IsQuery function would return True. Hence
1342 this can't happen. */
1345 /* Get the object name into 'caller_name', or "???"
1347 if (!VG_(get_objname)(ip, caller_name, ERRTXT_LEN))
1348 VG_(strcpy)(caller_name, "???");
1351 /* Get the function name into 'caller_name', or "???"
1353 // Nb: C++-mangled names are used in suppressions. Do, though,
1354 // Z-demangle them, since otherwise it's possible to wind
1355 // up comparing "malloc" in the suppression against
1356 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1357 // two of them need to be made to match.
1358 if (!VG_(get_fnname_no_cxx_demangle)(ip, caller_name, ERRTXT_LEN))
1359 VG_(strcpy)(caller_name, "???");
1365 /* So now we have the function or object name in caller_name, and
1366 the pattern (at the character level) to match against is in
1367 supploc->name. Hence (and leading to a re-entrant call of
1368 VG_(generic_match)): */
1369 return VG_(string_match)(supploc->name, caller_name);
1372 /////////////////////////////////////////////////////
1374 static Bool supp_matches_callers(Error* err, Supp* su)
1376 /* Unwrap the args and set up the correct parameterisation of
1377 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1379 /* note, StackTrace === Addr* */
1380 StackTrace ips = VG_(get_ExeContext_StackTrace)(err->where);
1381 UWord n_ips = VG_(get_ExeContext_n_ips)(err->where);
1382 SuppLoc* supps = su->callers;
1383 UWord n_supps = su->n_callers;
1384 UWord szbPatt = sizeof(SuppLoc);
1385 UWord szbInput = sizeof(Addr);
1386 Bool matchAll = False; /* we just want to match a prefix */
1390 /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
1391 /*INPUT*/ips, szbInput, n_ips, 0/*initial Ix*/,
1392 supploc_IsStar, supploc_IsQuery, supp_pattEQinp
1396 /////////////////////////////////////////////////////
1399 Bool supp_matches_error(Supp* su, Error* err)
1401 switch (su->skind) {
1402 //(example code, see comment on CoreSuppKind above)
1404 // return (err->ekind == ThreadErr);
1406 if (VG_(needs).tool_errors) {
1407 return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
1410 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
1411 "probably needs to be set.\n",
1413 VG_(tool_panic)("unhandled suppression type");
1418 /////////////////////////////////////////////////////
1420 /* Does an error context match a suppression? ie is this a suppressible
1421 error? If so, return a pointer to the Supp record, otherwise NULL.
1422 Tries to minimise the number of symbol searches since they are expensive.
1424 static Supp* is_suppressible_error ( Error* err )
1429 /* stats gathering */
1430 em_supplist_searches++;
1432 /* See if the error context matches any suppression. */
1434 for (su = suppressions; su != NULL; su = su->next) {
1436 if (supp_matches_error(su, err) && supp_matches_callers(err, su)) {
1437 /* got a match. Move this entry to the head of the list
1438 in the hope of making future searches cheaper. */
1440 vg_assert(su_prev->next == su);
1441 su_prev->next = su->next;
1442 su->next = suppressions;
1449 return NULL; /* no matches */
1452 /* Show accumulated error-list and suppression-list search stats.
1454 void VG_(print_errormgr_stats) ( void )
1457 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
1458 em_supplist_searches, em_supplist_cmps
1461 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
1462 em_errlist_searches, em_errlist_cmps
1466 /*--------------------------------------------------------------------*/
1468 /*--------------------------------------------------------------------*/