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-2017 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, 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 /*------------------------------------------------------------*/
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;
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
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
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.
138 // Unique tag. This gives the error a unique identity (handle) by
139 // which it can be referred to afterwords. Currently only used for
143 // NULL if unsuppressed; or ptr to suppression record.
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
)
161 ErrorKind
VG_(get_error_kind
) ( const Error
* err
)
166 Addr
VG_(get_error_address
) ( const Error
* err
)
171 const HChar
* VG_(get_error_string
) ( const Error
* err
)
176 void* VG_(get_error_extra
) ( const Error
* err
)
181 UInt
VG_(get_n_errs_found
)( void )
186 UInt
VG_(get_n_errs_shown
)( void )
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. */
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 */
213 /* Max number of callers for context in a suppression is
214 VG_DEEPEST_BACKTRACE. */
216 /* For each caller specified for a suppression, record the nature of
217 the caller name. Not of interest to tools. */
220 NoName
, /* Error case */
221 ObjName
, /* Name is of an shared object file. */
222 FunName
, /* Name is of a function. */
223 DotDotDot
, /* Frame-level wildcard */
224 SrcName
/* Name is of a src file. */
231 Bool name_is_simple_str
; /* True if name is a string without
232 '?' and '*' wildcard characters. */
233 HChar
* name
; /* NULL for NoName and DotDotDot */
234 UInt lineno
; /* Valid for SrcName. */
238 /* Suppressions. Tools can get/set tool-relevant parts with functions
239 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
240 Tools can use a normal enum (with element values in the normal range
241 (0..)) for 'skind'. */
244 HChar
* sname
; // The name by which the suppression is referred to.
245 Int count
; // The number of times this error has been suppressed.
247 // Index in VG_(clo_suppressions) giving filename from which suppression
248 // was read, and the lineno in this file where sname was read.
249 Int clo_suppressions_i
;
252 // Length of 'callers'
254 // Array of callers, for matching stack traces. First one (name of fn
255 // where err occurs) is mandatory; rest are optional.
258 /* The tool-specific part */
259 SuppKind skind
; // What kind of suppression. Must use the range (0..).
260 HChar
* string
; // String -- use is optional. NULL by default.
261 void* extra
; // Anything else -- use is optional. NULL by default.
264 SuppKind
VG_(get_supp_kind
) ( const Supp
* su
)
269 HChar
* VG_(get_supp_string
) ( const Supp
* su
)
274 void* VG_(get_supp_extra
) ( const Supp
* su
)
280 void VG_(set_supp_kind
) ( Supp
* su
, SuppKind skind
)
285 void VG_(set_supp_string
) ( Supp
* su
, HChar
* string
)
290 void VG_(set_supp_extra
) ( Supp
* su
, void* extra
)
296 /*------------------------------------------------------------*/
297 /*--- Helper fns ---*/
298 /*------------------------------------------------------------*/
300 // Only show core errors if the tool wants to, we're not running with -q,
301 // and were not outputting XML.
302 Bool
VG_(showing_core_errors
)(void)
304 return VG_(needs
).core_errors
&& VG_(clo_verbosity
) >= 1 && !VG_(clo_xml
);
307 /* Compare errors, to detect duplicates.
309 static Bool
eq_Error ( VgRes res
, const Error
* e1
, const Error
* e2
)
311 if (e1
->ekind
!= e2
->ekind
)
313 if (!VG_(eq_ExeContext
)(res
, e1
->where
, e2
->where
))
316 if (e1
->ekind
>= 0) {
317 if (VG_(needs
).tool_errors
) {
318 return VG_TDICT_CALL(tool_eq_Error
, res
, e1
, e2
);
320 VG_(printf
)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
321 "probably needs to be set.\n",
323 VG_(core_panic
)("unhandled error type");
326 return core_eq_Error(res
, e1
, e2
);
331 /* Helper functions for suppression generation: print a single line of
332 a suppression pseudo-stack-trace, either in XML or text mode. It's
333 important that the behaviour of these two functions exactly
336 #define ERRTXT_LEN 4096
338 static void printSuppForIp_XML(UInt n
, DiEpoch ep
, Addr ip
, void* uu_opaque
)
341 InlIPCursor
* iipc
= VG_(new_IIPC
)(ep
, ip
);
343 if ( VG_(get_fnname_no_cxx_demangle
) (ep
, ip
, &buf
, iipc
) ) {
344 VG_(printf_xml
)(" <sframe> <fun>%pS</fun> </sframe>\n", buf
);
346 if ( VG_(get_objname
)(ep
, ip
, &buf
) ) {
347 VG_(printf_xml
)(" <sframe> <obj>%pS</obj> </sframe>\n", buf
);
349 VG_(printf_xml
)(" <sframe> <obj>*</obj> </sframe>\n");
351 } while (VG_(next_IIPC
)(iipc
));
352 VG_(delete_IIPC
)(iipc
);
355 static void printSuppForIp_nonXML(UInt n
, DiEpoch ep
, Addr ip
, void* textV
)
358 XArray
* /* of HChar */ text
= (XArray
*)textV
;
359 InlIPCursor
* iipc
= VG_(new_IIPC
)(ep
, ip
);
361 if ( VG_(get_fnname_no_cxx_demangle
) (ep
, ip
, &buf
, iipc
) ) {
362 VG_(xaprintf
)(text
, " fun:%s\n", buf
);
364 if ( VG_(get_objname
)(ep
, ip
, &buf
) ) {
365 VG_(xaprintf
)(text
, " obj:%s\n", buf
);
367 VG_(xaprintf
)(text
, " obj:*\n");
369 } while (VG_(next_IIPC
)(iipc
));
370 VG_(delete_IIPC
)(iipc
);
373 /* Generate a suppression for an error, either in text or XML mode.
375 static void gen_suppression(const Error
* err
)
378 const HChar
* component
;
380 XArray
* /* HChar */ text
;
382 const HChar
* dummy_name
= "insert_a_suppression_name_here";
386 ec
= VG_(get_error_where
)(err
);
388 /* This can happen with core errors for --track-fds=all
389 with "leaked" inherited file descriptors, which aren't
390 created in the current program. */
391 VG_(umsg
)("(No origin, error cannot be suppressed)\n");
395 if (err
->ekind
>= 0) {
396 name
= VG_TDICT_CALL(tool_get_error_name
, err
);
398 VG_(umsg
)("(%s does not allow error to be suppressed)\n",
403 name
= core_get_error_name(err
);
405 VG_(umsg
)("(core error cannot be suppressed)\n");
410 /* In XML mode, we also need to print the plain text version of the
411 suppresion in a CDATA section. What that really means is, we
412 need to generate the plaintext version both in XML and text
413 mode. So generate it into TEXT. */
414 text
= VG_(newXA
)( VG_(malloc
), "errormgr.gen_suppression.1",
415 VG_(free
), sizeof(HChar
) );
417 /* Ok. Generate the plain text version into TEXT. */
419 component
= VG_(details
).name
;
421 component
= "CoreError";
422 VG_(xaprintf
)(text
, "{\n");
423 VG_(xaprintf
)(text
, " <%s>\n", dummy_name
);
424 VG_(xaprintf
)(text
, " %s:%s\n", component
, name
);
432 xtra
= VG_(realloc
)("errormgr.gen_suppression.2", xtra
,xtra_size
);
434 num_written
= VG_TDICT_CALL(tool_get_extra_suppression_info
,
435 err
, xtra
, xtra_size
);
437 num_written
= core_get_extra_suppression_info(err
, xtra
, xtra_size
);
438 } while (num_written
== xtra_size
); // resize buffer and retry
440 // Ensure buffer is properly terminated
441 vg_assert(xtra
[num_written
] == '\0');
444 VG_(xaprintf
)(text
, " %s\n", xtra
);
446 // Print stack trace elements
447 UInt n_ips
= VG_(get_ExeContext_n_ips
)(ec
);
448 vg_assert(n_ips
> 0);
449 vg_assert(n_ips
<= VG_DEEPEST_BACKTRACE
);
450 VG_(apply_StackTrace
)(printSuppForIp_nonXML
,
451 text
, VG_(get_ExeContext_epoch
)(ec
),
452 VG_(get_ExeContext_StackTrace
)(ec
),
455 VG_(xaprintf
)(text
, "}\n");
457 VG_(xaprintf
)(text
, "%c", (HChar
)0 );
458 // VG_(printf) of text
460 /* And now display it. */
461 if (! VG_(clo_xml
) ) {
464 VG_(printf
)("%s", (HChar
*) VG_(indexXA
)(text
, 0) );
468 /* Now we have to print the XML directly. No need to go to the
469 effort of stuffing it in an XArray, since we won't need it
471 VG_(printf_xml
)(" <suppression>\n");
472 VG_(printf_xml
)(" <sname>%s</sname>\n", dummy_name
);
474 " <skind>%pS:%pS</skind>\n", component
, name
);
476 VG_(printf_xml
)(" <skaux>%pS</skaux>\n", xtra
);
478 // Print stack trace elements
479 VG_(apply_StackTrace
)(printSuppForIp_XML
,
480 NULL
, VG_(get_ExeContext_epoch
)(ec
),
481 VG_(get_ExeContext_StackTrace
)(ec
),
482 VG_(get_ExeContext_n_ips
)(ec
));
484 // And now the cdata bit
485 // XXX FIXME! properly handle the case where the raw text
486 // itself contains "]]>", as specified in Protocol 4.
487 VG_(printf_xml
)(" <rawtext>\n");
488 VG_(printf_xml
)("<![CDATA[\n");
489 VG_(printf_xml
)("%s", (HChar
*) VG_(indexXA
)(text
, 0) );
490 VG_(printf_xml
)("]]>\n");
491 VG_(printf_xml
)(" </rawtext>\n");
492 VG_(printf_xml
)(" </suppression>\n");
501 /* Figure out if we want to perform a given action for this error,
502 possibly by asking the user.
504 Bool
VG_(is_action_requested
) ( const HChar
* action
, Bool
* clo
)
509 /* First off, we shouldn't be asking the user anything if
510 we're in XML mode. */
512 return False
; /* That's a Nein, oder Nay as they say down here in B-W */
522 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
523 VG_(getpid
)(), action
526 res
= VG_(read
)(VG_(clo_input_fd
), &ch
, 1);
527 if (res
!= 1) goto ioerror
;
529 if (ch
== '\n') return False
;
530 if (ch
!= 'N' && ch
!= 'n' && ch
!= 'Y' && ch
!= 'y'
531 && ch
!= 'C' && ch
!= 'c') goto again
;
533 res
= VG_(read
)(VG_(clo_input_fd
), &ch2
, 1);
534 if (res
!= 1) goto ioerror
;
535 if (ch2
!= '\n') goto again
;
537 /* No, don't want to do action. */
538 if (ch
== 'n' || ch
== 'N') return False
;
539 /* Yes, want to do action. */
540 if (ch
== 'y' || ch
== 'Y') return True
;
541 /* No, don't want to do action, and don't ask again either. */
542 vg_assert(ch
== 'c' || ch
== 'C');
550 /* Do actions on error, that is, immediately after an error is printed.
552 * possibly, call the GDB server
553 * possibly, generate a suppression.
556 void do_actions_on_error(const Error
* err
, Bool allow_db_attach
, Bool count_error
)
558 Bool still_noisy
= True
;
560 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
561 if (VG_(clo_vgdb
) != Vg_VgdbNo
563 && VG_(clo_vgdb_error
) <= n_errs_shown
) {
564 if (!(VG_(clo_launched_with_multi
)))
565 VG_(umsg
)("(action on error) vgdb me ... \n");
566 VG_(gdbserver
)( err
->tid
);
567 if (!(VG_(clo_launched_with_multi
)))
568 VG_(umsg
)("Continuing ...\n");
571 /* Or maybe we want to generate the error's suppression? */
572 if (VG_(clo_gen_suppressions
) == 2
573 || (VG_(clo_gen_suppressions
) == 1
574 && VG_(is_action_requested
)( "Print suppression", &still_noisy
))
576 gen_suppression(err
);
578 if (VG_(clo_gen_suppressions
) == 1 && !still_noisy
)
579 VG_(clo_gen_suppressions
) = 0;
581 if (count_error
&& VG_(clo_exit_on_first_error
)) {
583 VG_(printf_xml
)("</valgrindoutput>\n");
585 VG_(umsg
)("Exit program on first error (--exit-on-first-error=yes)\n");
586 VG_(client_exit
)( VG_(clo_error_exitcode
) );
591 /* Prints an error. Not entirely simple because of the differences
592 between XML and text mode output.
596 * calls the tool's pre-show method, so the tool can create any
597 preamble ahead of the message, if it wants.
599 * prints the opening tag, and the <unique> and <tid> fields
601 * prints the tool-specific parts of the message
603 * if suppression generation is required, a suppression
609 * calls the tool's pre-show method, so the tool can create any
610 preamble ahead of the message, if it wants.
612 * prints the tool-specific parts of the message
616 * calls do_actions_on_error. This optionally does a gdbserver call
617 and optionally prints a suppression; both of these may require user input.
619 static void pp_Error ( const Error
* err
, Bool allow_db_attach
, Bool xml
, Bool count_error
)
621 /* If this fails, you probably specified your tool's method
622 dictionary incorrectly. */
623 vg_assert(VG_(needs
).tool_errors
|| err
->ekind
< 0 /* core errors */);
627 /* Ensure that suppression generation is either completely
628 enabled or completely disabled; either way, we won't require
629 any user input. m_main.process_cmd_line_options should
630 ensure the asserted condition holds. */
631 vg_assert( VG_(clo_gen_suppressions
) == 0 /* disabled */
632 || VG_(clo_gen_suppressions
) == 2 /* for all errors */ );
634 /* Pre-show it to the tool */
636 VG_TDICT_CALL( tool_before_pp_Error
, err
);
638 core_before_pp_Error (err
);
640 /* standard preamble */
641 VG_(printf_xml
)("<error>\n");
642 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
643 VG_(printf_xml
)(" <tid>%u</tid>\n", err
->tid
);
644 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
645 if (tst
->thread_name
) {
646 VG_(printf_xml
)(" <threadname>%s</threadname>\n", tst
->thread_name
);
649 /* actually print it */
651 VG_TDICT_CALL( tool_pp_Error
, err
);
655 if (VG_(clo_gen_suppressions
) > 0)
656 gen_suppression(err
);
659 VG_(printf_xml
)("</error>\n");
660 VG_(printf_xml
)("\n");
664 if (VG_(clo_error_markers
)[0])
665 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[0]);
667 VG_TDICT_CALL( tool_before_pp_Error
, err
);
669 core_before_pp_Error(err
);
671 if (VG_(tdict
).tool_show_ThreadIDs_for_errors
672 && err
->tid
> 0 && err
->tid
!= last_tid_printed
) {
673 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
674 if (tst
->thread_name
) {
675 VG_(umsg
)("Thread %u %s:\n", err
->tid
, tst
->thread_name
);
677 VG_(umsg
)("Thread %u:\n", err
->tid
);
679 last_tid_printed
= err
->tid
;
682 if (err
->ekind
>= 0) {
683 VG_TDICT_CALL( tool_pp_Error
, err
);
688 if (VG_(clo_error_markers
)[1])
689 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[1]);
693 do_actions_on_error(err
, allow_db_attach
, count_error
);
697 /* Construct an error */
699 void construct_error ( Error
* err
, ThreadId tid
, ErrorKind ekind
, Addr a
,
700 const HChar
* s
, void* extra
, ExeContext
* where
)
702 /* DO NOT MAKE unique_counter NON-STATIC */
703 static UInt unique_counter
= 0;
705 vg_assert(tid
< VG_N_THREADS
);
707 /* Core-only parts */
708 err
->unique
= unique_counter
++;
713 if (NULL
== where
&& VG_(is_valid_tid
)(tid
))
714 err
->where
= VG_(record_ExeContext
)( tid
, 0 );
718 /* Tool-relevant parts */
725 vg_assert( tid
< VG_N_THREADS
);
730 /* Top-level entry point to the error management subsystem.
731 All detected errors are notified here; this routine decides if/when the
732 user should see the error. */
733 void VG_(maybe_record_error
) ( ThreadId tid
,
734 ErrorKind ekind
, Addr a
,
735 const HChar
* s
, void* extra
)
741 VgRes exe_res
= Vg_MedRes
;
742 static Bool stopping_message
= False
;
743 static Bool slowdown_message
= False
;
745 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
746 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
747 have been found, just refuse to collect any more. This stops
748 the burden of the error-management system becoming excessive in
749 extremely buggy programs, although it does make it pretty
750 pointless to continue the Valgrind run after this point. */
751 if (VG_(clo_error_limit
)
752 && (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
753 || n_errs_found
>= M_COLLECT_NO_ERRORS_AFTER_FOUND
)
755 if (!stopping_message
) {
758 if (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
) {
760 "More than %d different errors detected. "
761 "I'm not reporting any more.\n",
762 M_COLLECT_NO_ERRORS_AFTER_SHOWN
);
765 "More than %d total errors detected. "
766 "I'm not reporting any more.\n",
767 M_COLLECT_NO_ERRORS_AFTER_FOUND
);
770 VG_(umsg
)("Final error counts will be inaccurate. "
771 "Go fix your program!\n");
772 VG_(umsg
)("Rerun with --error-limit=no to disable "
773 "this cutoff. Note\n");
774 VG_(umsg
)("that errors may occur in your program without "
775 "prior warning from\n");
776 VG_(umsg
)("Valgrind, because errors are no longer "
777 "being displayed.\n");
779 stopping_message
= True
;
784 /* Ignore it if error acquisition is disabled for this thread. */
785 { ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
786 if (tst
->err_disablement_level
> 0)
790 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
791 been found, be much more conservative about collecting new
793 if (n_errs_shown
>= M_COLLECT_ERRORS_SLOWLY_AFTER
796 if (!slowdown_message
) {
798 VG_(umsg
)("More than %d errors detected. Subsequent errors\n",
799 M_COLLECT_ERRORS_SLOWLY_AFTER
);
800 VG_(umsg
)("will still be recorded, but in less "
801 "detail than before.\n");
802 slowdown_message
= True
;
806 /* Build ourselves the error */
807 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, NULL
);
809 /* First, see if we've got an error record matching this one. */
810 em_errlist_searches
++;
815 if (eq_Error(exe_res
, p
, &err
)) {
818 if (p
->supp
!= NULL
) {
819 /* Deal correctly with suppressed errors. */
826 /* Move p to the front of the list so that future searches
827 for it are faster. It also allows to print the last
828 error (see VG_(show_last_error). */
829 if (p_prev
!= NULL
) {
830 vg_assert(p_prev
->next
== p
);
831 p_prev
->next
= p
->next
;
842 /* Didn't see it. Copy and add. */
844 /* OK, we're really going to collect it. The context is on the stack and
845 will disappear shortly, so we must copy it. First do the main
848 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
849 is for when there are more details to fill in which take time to work
850 out but don't affect our earlier decision to include the error -- by
851 postponing those details until now, we avoid the extra work in the
852 case where we ignore the error. Ugly.
854 Then, if there is an 'extra' part, copy it too, using the size that
855 VG_(tdict).tool_update_extra returned. Also allow for people using
856 the void* extra field for a scalar value like an integer.
860 p
= VG_(malloc
)("errormgr.mre.1", sizeof(Error
));
866 extra_size
= core_update_extra (p
);
868 vg_assert(VG_(needs
).tool_errors
);
869 extra_size
= VG_TDICT_CALL(tool_update_extra
, p
);
872 /* copy the error string, if there is one.
873 note: if we would have many errors with big strings, using a
874 DedupPoolAlloc for these strings will avoid duplicating
875 such string in each error using it. */
876 if (NULL
!= p
->string
) {
877 p
->string
= VG_(strdup
)("errormgr.mre.2", p
->string
);
880 /* copy block pointed to by 'extra', if there is one */
881 if (NULL
!= p
->extra
&& 0 != extra_size
) {
882 void* new_extra
= VG_(malloc
)("errormgr.mre.3", extra_size
);
883 VG_(memcpy
)(new_extra
, p
->extra
, extra_size
);
884 p
->extra
= new_extra
;
888 p
->supp
= is_suppressible_error(&err
);
890 if (p
->supp
== NULL
) {
895 /* Actually show the error; more complex than you might think. */
896 pp_Error( p
, /*allow_db_attach*/True
, VG_(clo_xml
), /* count_error */ True
);
904 /* Second top-level entry point to the error management subsystem, for
905 errors that the tool wants to report immediately, eg. because they're
906 guaranteed to only happen once. This avoids all the recording and
907 comparing stuff. But they can be suppressed; returns True if it is
908 suppressed. Bool 'print_error' dictates whether to print the error.
909 Bool 'count_error' dictates whether to count the error in n_errs_found.
911 Bool
VG_(unique_error
) ( ThreadId tid
, ErrorKind ekind
, Addr a
, const HChar
* s
,
912 void* extra
, ExeContext
* where
, Bool print_error
,
913 Bool allow_db_attach
, Bool count_error
)
918 /* Ignore it if error acquisition is disabled for this thread. */
919 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
920 if (tst
->err_disablement_level
> 0)
921 return False
; /* ignored, not suppressed */
923 /* Build ourselves the error */
924 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, where
);
926 /* Unless it's suppressed, we're going to show it. Don't need to make
927 a copy, because it's only temporary anyway.
929 Then update the 'extra' part with VG_(tdict).tool_update_extra),
930 because that can have an affect on whether it's suppressed. Ignore
931 the size return value of VG_(tdict).tool_update_extra, because we're
932 not copying 'extra'. Similarly, 's' is also not copied. */
934 (void)VG_TDICT_CALL(tool_update_extra
, &err
);
936 (void)core_update_extra(&err
);
938 su
= is_suppressible_error(&err
);
948 /* Actually show the error; more complex than you might think. */
949 pp_Error(&err
, allow_db_attach
, VG_(clo_xml
), count_error
);
964 /*------------------------------------------------------------*/
965 /*--- Core error fns ---*/
966 /*------------------------------------------------------------*/
968 static Bool
is_fd_core_error (const Error
*e
)
970 return e
->ekind
== FdBadClose
|| e
->ekind
== FdNotClosed
;
973 static Bool
core_eq_Error (VgRes res
, const Error
*e1
, const Error
*e2
)
975 if (is_fd_core_error(e1
))
976 return fd_eq_Error (res
, e1
, e2
);
978 VG_(umsg
)("FATAL: unknown core error kind: %d\n", e1
->ekind
);
983 static void core_before_pp_Error (const Error
*err
)
985 if (is_fd_core_error(err
))
986 fd_before_pp_Error(err
);
988 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
993 static void core_pp_Error (const Error
*err
)
995 if (is_fd_core_error(err
))
998 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
1003 static UInt
core_update_extra (const Error
*err
)
1005 if (is_fd_core_error(err
))
1006 return fd_update_extra(err
);
1008 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
1013 static const HChar
*core_get_error_name(const Error
*err
)
1015 switch (err
->ekind
) {
1017 return "FdBadClose";
1019 return "FdNotClosed";
1021 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
1026 static Bool
core_error_matches_suppression(const Error
* err
, const Supp
* su
)
1028 switch (su
->skind
) {
1029 case FdBadCloseSupp
:
1030 return err
->ekind
== FdBadClose
;
1031 case FdNotClosedSupp
:
1032 return err
->ekind
== FdNotClosed
;
1034 VG_(umsg
)("FATAL: unknown core suppression kind: %d\n", su
->skind
);
1039 static SizeT
core_get_extra_suppression_info(const Error
*err
,
1040 HChar
* buf
, Int nBuf
)
1042 /* No core error has any extra suppression info at the moment. */
1047 static SizeT
core_print_extra_suppression_use(const Supp
* su
,
1048 HChar
* buf
, Int nBuf
)
1050 /* No core error has any extra suppression info at the moment. */
1056 /*------------------------------------------------------------*/
1057 /*--- Exported fns ---*/
1058 /*------------------------------------------------------------*/
1060 /* Show the used suppressions. Returns False if no suppression
1062 static Bool
show_used_suppressions ( void )
1068 VG_(printf_xml
)("<suppcounts>\n");
1071 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
1075 VG_(printf_xml
)( " <pair>\n"
1076 " <count>%d</count>\n"
1077 " <name>%pS</name>\n"
1079 su
->count
, su
->sname
);
1084 // blank line before the first shown suppression, if any
1090 xtra
= VG_(realloc
)("errormgr.sus.1", xtra
, xtra_size
);
1092 num_written
= VG_TDICT_CALL(tool_print_extra_suppression_use
,
1093 su
, xtra
, xtra_size
);
1095 num_written
= core_print_extra_suppression_use(su
,
1097 } while (num_written
== xtra_size
); // resize buffer and retry
1099 // Ensure buffer is properly terminated
1100 vg_assert(xtra
[num_written
] == '\0');
1102 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1103 su
->clo_suppressions_i
);
1104 VG_(dmsg
)("used_suppression: %6d %s %s:%d%s%s\n", su
->count
, su
->sname
,
1107 num_written
? " " : "", xtra
);
1114 VG_(printf_xml
)("</suppcounts>\n");
1119 /* See pub_core_errormgr.h. */
1120 void VG_(show_all_errors
) ( Int verbosity
, Bool xml
, Int show_error_list
)
1125 Bool any_error
= False
;
1128 if (verbosity
== 0 && show_error_list
== 0)
1131 /* If we're printing XML, just show the suppressions and stop. */
1133 if (show_error_list
> 0)
1134 (void)show_used_suppressions();
1138 /* We only get here if not printing XML. */
1139 VG_(umsg
)("ERROR SUMMARY: "
1140 "%u errors from %u contexts (suppressed: %u from %u)\n",
1141 n_errs_found
, n_err_contexts
,
1142 n_errs_suppressed
, n_supp_contexts
);
1144 if (show_error_list
== 0)
1147 // We do the following if show_error_list > 0
1148 // or at -v or above, and only in non-XML mode.
1150 /* Print the contexts in order of increasing error count.
1151 The below implements this in a quadratic algorithm based on the assumption
1152 that there are not too many errors (including the suppressed if showing
1153 the suppressed errors) !
1154 Once an error is shown, we add a huge value to its count to filter it
1156 After having shown all errors, we reset count to the original value. */
1157 n_errs
= n_err_contexts
+ (show_error_list
< 2 ? 0 : n_errs_suppressed
);
1158 for (i
= 0; i
< n_errs
; i
++) {
1159 n_min
= (1 << 30) - 1;
1161 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1162 if (show_error_list
< 2 && p
->supp
!= NULL
) continue;
1163 if (p
->count
< n_min
) {
1168 // XXX: this isn't right. See bug 203651.
1169 if (p_min
== NULL
) continue; //VG_(core_panic)("show_all_errors()");
1173 VG_(umsg
)("%d errors%s%s%s in context %d of %u:\n",
1175 p_min
->supp
== NULL
? "" : " (suppressed by ",
1176 p_min
->supp
== NULL
? "" : p_min
->supp
->sname
,
1177 p_min
->supp
== NULL
? "" : ")",
1179 pp_Error( p_min
, False
/*allow_db_attach*/, False
/* xml */, True
/* count_error */ );
1181 // We're not printing XML -- we'd have exited above if so.
1184 if ((i
+1 == VG_(clo_dump_error
))) {
1185 StackTrace ips
= VG_(get_ExeContext_StackTrace
)(p_min
->where
);
1186 VG_(translate
) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1187 ips
[0], /*debugging*/True
, 0xFE/*verbosity*/,
1189 /*allow redir?*/True
);
1192 p_min
->count
= p_min
->count
+ (1 << 30);
1195 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1196 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1197 if (p
->count
>= (1 << 30))
1198 p
->count
= p
->count
- (1 << 30);
1202 any_supp
= show_used_suppressions();
1206 // reprint summary, so users don't have to scroll way up to find
1207 // the first printing
1208 if (any_supp
|| any_error
)
1209 VG_(umsg
)("ERROR SUMMARY: "
1210 "%u errors from %u contexts (suppressed: %u from %u)\n",
1211 n_errs_found
, n_err_contexts
, n_errs_suppressed
,
1215 void VG_(show_last_error
) ( void )
1217 if (n_err_contexts
== 0) {
1218 VG_(umsg
)("No errors yet\n");
1222 pp_Error( errors
, False
/*allow_db_attach*/, False
/*xml*/, True
/*count_error*/ );
1226 /* Show occurrence counts of all errors, in XML form. */
1227 void VG_(show_error_counts_as_XML
) ( void )
1230 VG_(printf_xml
)("<errorcounts>\n");
1231 for (err
= errors
; err
!= NULL
; err
= err
->next
) {
1232 if (err
->supp
!= NULL
)
1234 if (err
->count
<= 0)
1236 VG_(printf_xml
)(" <pair>\n");
1237 VG_(printf_xml
)(" <count>%d</count>\n", err
->count
);
1238 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
1239 VG_(printf_xml
)(" </pair>\n");
1241 VG_(printf_xml
)("</errorcounts>\n");
1242 VG_(printf_xml
)("\n");
1246 /*------------------------------------------------------------*/
1247 /*--- Suppression parsing ---*/
1248 /*------------------------------------------------------------*/
1250 /* Get the next char from fd into *out_buf. Returns 1 if success,
1251 0 if eof or < 0 if error. */
1253 static Int
get_char ( Int fd
, HChar
* out_buf
)
1256 static HChar buf
[256];
1257 static Int buf_size
= 0;
1258 static Int buf_used
= 0;
1259 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1260 vg_assert(buf_used
>= 0 && buf_used
<= buf_size
);
1261 if (buf_used
== buf_size
) {
1262 r
= VG_(read
)(fd
, buf
, sizeof buf
);
1263 if (r
< 0) return r
; /* read failed */
1264 vg_assert(r
>= 0 && r
<= sizeof buf
);
1270 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1271 vg_assert(buf_used
>= 0 && buf_used
< buf_size
);
1272 *out_buf
= buf
[buf_used
];
1277 // Get a non blank non comment line.
1278 // Returns True if eof.
1279 static Bool
get_nbnc_line ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1281 HChar
* buf
= *bufpp
;
1282 SizeT nBuf
= *nBufp
;
1286 vg_assert(lineno
); // lineno needed to correctly track line numbers.
1290 /* First, read until a non-blank char appears. */
1292 n
= get_char(fd
, &ch
);
1293 if (n
== 1 && !VG_(isspace
)(ch
)) break;
1294 if (n
== 1 && ch
== '\n')
1296 if (n
<= 0) return True
;
1299 /* Now, read the line into buf. */
1301 buf
[i
++] = ch
; buf
[i
] = 0;
1303 n
= get_char(fd
, &ch
);
1304 if (n
<= 0) return False
; /* the next call will return True */
1307 if (ch
== '\n') break;
1308 if (i
> 0 && i
== nBuf
-1) {
1309 *nBufp
= nBuf
= nBuf
* 2;
1310 #define RIDICULOUS 100000
1311 vg_assert2(nBuf
< RIDICULOUS
, // Just a sanity check, really.
1312 "VG_(get_line): line longer than %d chars, aborting\n",
1314 *bufpp
= buf
= VG_(realloc
)("errormgr.get_line.1", buf
, nBuf
);
1316 buf
[i
++] = ch
; buf
[i
] = 0;
1318 while (i
> 1 && VG_(isspace
)(buf
[i
-1])) {
1322 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1323 /* Ok, we have a line. If a non-comment line, return.
1324 If a comment line, start all over again. */
1325 if (buf
[0] != '#') return False
;
1329 // True if buf starts with fun: or obj: or is ...
1330 static Bool
is_location_line (const HChar
* buf
)
1332 return VG_(strncmp
)(buf
, "fun:", 4) == 0
1333 || VG_(strncmp
)(buf
, "obj:", 4) == 0
1334 || VG_(strcmp
)(buf
, "...") == 0;
1337 Bool
VG_(get_line
) ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1339 Bool eof
= get_nbnc_line (fd
, bufpp
, nBufp
, lineno
);
1344 if (is_location_line(*bufpp
))
1345 return True
; // Not a extra suppr line
1347 return False
; // A suppression extra line
1350 /* True if s contains no wildcard (?, *) characters. */
1351 static Bool
is_simple_str (const HChar
*s
)
1354 if (*s
== '?' || *s
== '*')
1361 /* buf contains the raw name of a caller, supposedly either
1362 fun:some_function_name or
1363 obj:some_object_name or
1364 src:some_file_name or
1365 src:some_file_name:line# or
1367 Set p->ty and p->name accordingly.
1368 p->name is allocated and set to the string
1369 after the descriptor (fun:, obj:, or src: san line#) part.
1370 p->lineno is set to non-zero if line# specified; 0 otherwise.
1371 Returns False if failed.
1373 static Bool
setLocationTy ( SuppLoc
* p
, const HChar
*buf
)
1375 if (VG_(strncmp
)(buf
, "fun:", 4) == 0) {
1376 p
->name
= VG_(strdup
)("errormgr.sLTy.1", buf
+4);
1377 p
->name_is_simple_str
= is_simple_str (p
->name
);
1381 if (VG_(strncmp
)(buf
, "obj:", 4) == 0) {
1382 p
->name
= VG_(strdup
)("errormgr.sLTy.2", buf
+4);
1383 p
->name_is_simple_str
= is_simple_str (p
->name
);
1387 if (VG_(strncmp
)(buf
, "src:", 4) == 0) {
1388 p
->name
= VG_(strdup
)("errormgr.sLTy.3", buf
+4);
1389 p
->name_is_simple_str
= is_simple_str (p
->name
);
1391 HChar
*s
= VG_(strchr
)(p
->name
, ':');
1393 *s
++ = '\0'; // trim colon
1394 p
->lineno
= (UInt
) VG_(strtoll10
)(s
, NULL
);
1400 if (VG_(strcmp
)(buf
, "...") == 0) {
1402 p
->name_is_simple_str
= False
;
1406 VG_(printf
)("location should be \"...\", or should start "
1407 "with \"fun:\", \"obj:\", or \"src:\"\n");
1412 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1413 static Bool
tool_name_present(const HChar
*name
, const HChar
*names
)
1416 HChar
*s
= NULL
; /* Shut gcc up */
1417 Int len
= VG_(strlen
)(name
);
1419 found
= (NULL
!= (s
= VG_(strstr
)(names
, name
))
1420 && (s
== names
|| *(s
-1) == ',')
1421 && (*(s
+len
) == ',' || *(s
+len
) == '\0'));
1426 /* Read suppressions from the file specified in
1427 VG_(clo_suppressions)[clo_suppressions_i]
1428 and place them in the suppressions list. If there's any difficulty
1429 doing this, just give up -- there's no point in trying to recover.
1431 static void load_one_suppressions_file ( Int clo_suppressions_i
)
1433 const HChar
* filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1434 clo_suppressions_i
);
1436 Int fd
, i
, j
, lineno
= 0;
1437 Bool got_a_location_line_read_by_tool
;
1440 HChar
* buf
= VG_(malloc
)("errormgr.losf.1", nBuf
);
1443 const HChar
* err_str
= NULL
;
1444 SuppLoc tmp_callers
[VG_DEEPEST_BACKTRACE
];
1446 // Check it's not a directory.
1447 if (VG_(is_dir
)( filename
)) {
1449 VG_(printf_xml
)("</valgrindoutput>\n");
1450 VG_(umsg
)("FATAL: suppressions file \"%s\" is a directory\n", filename
);
1454 // Open the suppression file.
1455 sres
= VG_(open
)( filename
, VKI_O_RDONLY
, 0 );
1456 if (sr_isError(sres
)) {
1458 VG_(printf_xml
)("</valgrindoutput>\n");
1459 VG_(umsg
)("FATAL: can't open suppressions file \"%s\"\n", filename
);
1464 # define BOMB(S) { err_str = S; goto syntax_error; }
1467 /* Assign and initialise the two suppression halves (core and tool) */
1469 supp
= VG_(malloc
)("errormgr.losf.1", sizeof(Supp
));
1472 // Initialise temporary reading-in buffer.
1473 for (i
= 0; i
< VG_DEEPEST_BACKTRACE
; i
++) {
1474 tmp_callers
[i
].ty
= NoName
;
1475 tmp_callers
[i
].name_is_simple_str
= False
;
1476 tmp_callers
[i
].name
= NULL
;
1479 supp
->string
= supp
->extra
= NULL
;
1481 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1487 if (!VG_STREQ(buf
, "{")) BOMB("expected '{' or end-of-file");
1489 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1491 if (eof
|| VG_STREQ(buf
, "}")) BOMB("unexpected '}'");
1493 supp
->sname
= VG_(strdup
)("errormgr.losf.2", buf
);
1494 supp
->clo_suppressions_i
= clo_suppressions_i
;
1495 supp
->sname_lineno
= lineno
;
1497 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1499 if (eof
) BOMB("unexpected end-of-file (expecting tool:suppr)");
1501 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1504 if (buf
[i
] == ':') break;
1505 if (buf
[i
] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1508 buf
[i
] = '\0'; /* Replace ':', splitting into two strings */
1510 tool_names
= & buf
[0];
1511 supp_name
= & buf
[i
+1];
1513 if (VG_(needs
).core_errors
1514 && tool_name_present("CoreError", tool_names
)) {
1515 // A core suppression
1516 if (VG_STREQ(supp_name
, "FdBadClose"))
1517 supp
->skind
= FdBadCloseSupp
;
1518 else if (VG_STREQ(supp_name
, "FdNotClosed"))
1519 supp
->skind
= FdNotClosedSupp
;
1521 BOMB("unknown core suppression type");
1523 else if (VG_(needs
).tool_errors
1524 && tool_name_present(VG_(details
).name
, tool_names
)) {
1525 // A tool suppression
1526 if (VG_TDICT_CALL(tool_recognised_suppression
, supp_name
, supp
)) {
1527 /* Do nothing, function fills in supp->skind */
1529 BOMB("unknown tool suppression type");
1533 // Ignore rest of suppression
1535 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1536 if (eof
) BOMB("unexpected end-of-file (when skipping suppression)");
1537 if (VG_STREQ(buf
, "}"))
1540 VG_(free
)(supp
->sname
);
1546 // tool_read_extra_suppression_info might read lines
1547 // from fd till a location line.
1548 if (VG_(needs
).tool_errors
1549 && !VG_TDICT_CALL(tool_read_extra_suppression_info
,
1550 fd
, &buf
, &nBuf
, &lineno
, supp
)) {
1551 BOMB("bad or missing extra suppression info");
1554 // No core errors need to read extra suppression info
1556 got_a_location_line_read_by_tool
= buf
[0] != 0 && is_location_line(buf
);
1558 /* the main frame-descriptor reading loop */
1561 if (got_a_location_line_read_by_tool
) {
1562 got_a_location_line_read_by_tool
= False
;
1565 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1568 BOMB("unexpected end-of-file (when reading stack trace)");
1569 if (VG_STREQ(buf
, "}")) {
1573 BOMB("missing stack trace");
1576 if (i
== VG_DEEPEST_BACKTRACE
)
1577 BOMB("too many callers in stack trace");
1578 if (i
> 0 && i
>= VG_(clo_backtrace_size
))
1580 if (!setLocationTy(&(tmp_callers
[i
]), buf
))
1581 BOMB("location should be \"...\", or should start "
1582 "with \"fun:\", \"obj:\", or \"src:\"");
1586 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1587 // lines and grab the '}'.
1588 if (!VG_STREQ(buf
, "}")) {
1590 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1591 } while (!eof
&& !VG_STREQ(buf
, "}"));
1594 // Reject entries which are entirely composed of frame
1596 vg_assert(i
> 0); // guaranteed by frame-descriptor reading loop
1597 for (j
= 0; j
< i
; j
++) {
1598 if (tmp_callers
[j
].ty
== FunName
|| tmp_callers
[j
].ty
== ObjName
1599 || tmp_callers
[j
].ty
== SrcName
) {
1602 vg_assert(tmp_callers
[j
].ty
== DotDotDot
);
1604 vg_assert(j
>= 0 && j
<= i
);
1606 // we didn't find any non-"..." entries
1607 BOMB("suppression must contain at least one location "
1608 "line which is not \"...\"");
1611 // Copy tmp_callers[] into supp->callers[]
1612 supp
->n_callers
= i
;
1613 supp
->callers
= VG_(malloc
)("errormgr.losf.4", i
* sizeof(SuppLoc
));
1614 for (i
= 0; i
< supp
->n_callers
; i
++) {
1615 supp
->callers
[i
] = tmp_callers
[i
];
1618 supp
->next
= suppressions
;
1619 suppressions
= supp
;
1627 VG_(printf_xml
)("</valgrindoutput>\n");
1628 VG_(umsg
)("FATAL: in suppressions file \"%s\" near line %d:\n",
1630 VG_(umsg
)(" %s\n", err_str
);
1633 VG_(umsg
)("exiting now.\n");
1639 void VG_(add_suppression_file
)(const HChar
*filename
)
1641 HChar
*f
= VG_(strdup
)("errormgr.addsup", filename
);
1642 VG_(addToXA
)(VG_(clo_suppressions
), &f
);
1643 if (load_suppressions_called
)
1644 load_one_suppressions_file( VG_(sizeXA
)(VG_(clo_suppressions
)) - 1 );
1647 void VG_(load_suppressions
) ( void )
1650 suppressions
= NULL
;
1651 load_suppressions_called
= True
;
1652 for (i
= 0; i
< VG_(sizeXA
)(VG_(clo_suppressions
)); i
++) {
1653 if (VG_(clo_verbosity
) > 1) {
1654 VG_(dmsg
)("Reading suppressions file: %s\n",
1655 *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
), i
));
1657 load_one_suppressions_file( i
);
1662 /*------------------------------------------------------------*/
1663 /*--- Matching errors to suppressions ---*/
1664 /*------------------------------------------------------------*/
1666 /* Parameterising functions for the use of VG_(generic_match) in
1667 suppression-vs-error matching. The suppression frames (SuppLoc)
1668 play the role of 'pattern'-element, and the error frames (IPs,
1669 hence simply Addrs) play the role of 'input'. In short then, we're
1670 matching a sequence of Addrs against a pattern composed of a
1671 sequence of SuppLocs.
1673 static Bool
supploc_IsStar ( const void* supplocV
)
1675 const SuppLoc
* supploc
= supplocV
;
1676 return supploc
->ty
== DotDotDot
;
1679 static Bool
supploc_IsQuery ( const void* supplocV
)
1681 return False
; /* there's no '?' equivalent in the supp syntax */
1684 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1685 needed to match an error with the suppression patterns.
1686 The matching between an IP and a suppression pattern is done either
1687 with the IP function name or with the IP object name.
1688 First time the fun or obj name is needed for an IP member
1689 of a stack trace, it will be computed and stored in names.
1690 Also, if the IP corresponds to one or more inlined function calls,
1691 the inlined function names are expanded.
1692 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1693 allocations and the nr of debuginfo search. */
1696 DiEpoch epoch
; // used to interpret .ips
1697 StackTrace ips
; // stack trace we are lazily completing.
1698 UWord n_ips
; // nr of elements in ips.
1700 // VG_(generic_match) calls haveInputInpC to check
1701 // for the presence of an input element identified by ixInput
1702 // (i.e. a number that identifies the ixInput element of the
1703 // input sequence). It calls supp_pattEQinp to match this input
1704 // element with a pattern.
1705 // When inlining info is used to provide inlined function calls
1706 // in stacktraces, one IP in ips can be expanded in several
1707 // function names. So, each time input (or presence of input)
1708 // is requested by VG_(generic_match), we will expand
1709 // more IP of ips till we have expanded enough to reach the
1710 // input element requested (or we cannot expand anymore).
1712 UWord n_ips_expanded
;
1713 // n_ips_expanded maintains the nr of elements in ips that we have
1714 // already expanded.
1716 // n_expanded maintains the nr of elements resulting from the expansion
1717 // of the n_ips_expanded IPs. Without inlined function calls,
1718 // n_expanded == n_ips_expanded. With inlining info,
1719 // n_expanded >= n_ips_expanded.
1721 Int
* n_offsets_per_ip
;
1722 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1723 // obj_offsets resulting of the expansion of ips[i].
1724 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1725 // This array allows to retrieve the position in ips corresponding to
1728 // size (in elements) of fun_offsets and obj_offsets.
1729 // (fun|obj)_offsets are reallocated if more space is needed
1734 // fun_offsets[ixInput] is the offset in names where the
1735 // function name for the ixInput element of the input sequence
1736 // can be found. As one IP of ips can be expanded in several
1737 // function calls due to inlined function calls, we can have more
1738 // elements in fun_offsets than in ips.
1739 // An offset -1 means the function name has not yet been computed.
1741 // Similarly, obj_offsets[ixInput] gives the offset for the
1742 // object name for ips[ixInput]
1743 // (-1 meaning object name not yet been computed).
1745 // All function names and object names will be concatenated
1746 // in names. names is reallocated on demand.
1748 Int names_szB
; // size of names.
1749 Int names_free
; // offset first free HChar in names.
1751 IPtoFunOrObjCompleter
;
1753 static void pp_ip2fo (const IPtoFunOrObjCompleter
* ip2fo
)
1758 VG_(printf
)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1759 ip2fo
->n_ips
, ip2fo
->n_ips_expanded
, ip2fo
->n_expanded
);
1760 for (i
= 0; i
< ip2fo
->n_ips_expanded
; i
++) {
1762 for (j
= 0; j
< i
; j
++)
1763 o
+= ip2fo
->n_offsets_per_ip
[j
];
1764 VG_(printf
)("ips %d 0x08%lx offset [%d,%d] ",
1766 o
, o
+ip2fo
->n_offsets_per_ip
[i
]-1);
1767 for (j
= 0; j
< ip2fo
->n_offsets_per_ip
[i
]; j
++) {
1768 VG_(printf
)("%sfun:%s obj:%s\n",
1770 ip2fo
->fun_offsets
[o
+j
] == -1 ?
1771 "<not expanded>" : &ip2fo
->names
[ip2fo
->fun_offsets
[o
+j
]],
1772 ip2fo
->obj_offsets
[o
+j
] == -1 ?
1773 "<not expanded>" : &ip2fo
->names
[ip2fo
->obj_offsets
[o
+j
]]);
1778 /* free the memory in ip2fo.
1779 At debuglog 4, su (or NULL) will be used to show the matching
1780 (or non matching) with ip2fo. */
1781 static void clearIPtoFunOrObjCompleter ( const Supp
*su
,
1782 IPtoFunOrObjCompleter
* ip2fo
)
1784 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4) {
1786 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1787 su
->clo_suppressions_i
);
1788 VG_(dmsg
)("errormgr matching end suppression %s %s:%d matched:\n",
1793 VG_(dmsg
)("errormgr matching end no suppression matched:\n");
1795 VG_(pp_StackTrace
) (ip2fo
->epoch
, ip2fo
->ips
, ip2fo
->n_ips
);
1798 if (ip2fo
->n_offsets_per_ip
) VG_(free
)(ip2fo
->n_offsets_per_ip
);
1799 if (ip2fo
->fun_offsets
) VG_(free
)(ip2fo
->fun_offsets
);
1800 if (ip2fo
->obj_offsets
) VG_(free
)(ip2fo
->obj_offsets
);
1801 if (ip2fo
->names
) VG_(free
)(ip2fo
->names
);
1804 /* Grow ip2fo->names to ensure we have NEEDED characters available
1805 in ip2fo->names and returns a pointer to the first free char. */
1806 static HChar
* grow_names(IPtoFunOrObjCompleter
* ip2fo
, SizeT needed
)
1808 if (ip2fo
->names_szB
1809 < ip2fo
->names_free
+ needed
) {
1810 if (needed
< ERRTXT_LEN
) needed
= ERRTXT_LEN
;
1813 = VG_(realloc
)("foc_names",
1815 ip2fo
->names_szB
+ needed
);
1816 ip2fo
->names_szB
+= needed
;
1818 return ip2fo
->names
+ ip2fo
->names_free
;
1821 /* foComplete returns the function name or object name for ixInput.
1822 If needFun, returns the function name for this input
1823 else returns the object name for this input.
1824 The function name or object name will be computed and added in
1825 names if not yet done. */
1826 static HChar
* foComplete(IPtoFunOrObjCompleter
* ip2fo
,
1827 Int ixInput
, Bool needFun
)
1829 vg_assert (ixInput
< ip2fo
->n_expanded
);
1830 vg_assert (VG_(clo_read_inline_info
) || ixInput
< ip2fo
->n_ips
);
1832 // ptr to the offset array for function offsets (if needFun)
1833 // or object offsets (if !needFun).
1836 offsets
= &ip2fo
->fun_offsets
;
1838 offsets
= &ip2fo
->obj_offsets
;
1840 // Complete Fun name or Obj name for IP if not yet done.
1841 if ((*offsets
)[ixInput
] == -1) {
1842 const HChar
* caller
;
1844 (*offsets
)[ixInput
] = ip2fo
->names_free
;
1845 if (DEBUG_ERRORMGR
) VG_(printf
)("marking %s ixInput %d offset %d\n",
1846 needFun
? "fun" : "obj",
1847 ixInput
, ip2fo
->names_free
);
1849 // With inline info, fn names must have been completed already.
1850 vg_assert (!VG_(clo_read_inline_info
));
1851 /* Get the function name into 'caller_name', or "???"
1853 // Nb: C++-mangled names are used in suppressions. Do, though,
1854 // Z-demangle them, since otherwise it's possible to wind
1855 // up comparing "malloc" in the suppression against
1856 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1857 // two of them need to be made to match.
1858 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->epoch
,
1859 ip2fo
->ips
[ixInput
],
1864 /* Get the object name into 'caller_name', or "???"
1867 UWord last_expand_pos_ips
= 0;
1870 /* First get the pos in ips corresponding to ixInput */
1871 for (pos_ips
= 0; pos_ips
< ip2fo
->n_expanded
; pos_ips
++) {
1872 last_expand_pos_ips
+= ip2fo
->n_offsets_per_ip
[pos_ips
];
1873 if (ixInput
< last_expand_pos_ips
)
1876 /* pos_ips is the position in ips corresponding to ixInput.
1877 last_expand_pos_ips is the last offset in fun/obj where
1878 ips[pos_ips] has been expanded. */
1880 if (!VG_(get_objname
)(ip2fo
->epoch
, ip2fo
->ips
[pos_ips
], &caller
))
1883 // Have all inlined calls pointing at this object name
1884 for (i
= last_expand_pos_ips
- ip2fo
->n_offsets_per_ip
[pos_ips
] + 1;
1885 i
< last_expand_pos_ips
;
1887 ip2fo
->obj_offsets
[i
] = ip2fo
->names_free
;
1889 VG_(printf
) (" set obj_offset %lu to %d\n",
1890 i
, ip2fo
->names_free
);
1893 SizeT caller_len
= VG_(strlen
)(caller
);
1894 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1895 VG_(strcpy
)(caller_name
, caller
);
1896 ip2fo
->names_free
+= caller_len
+ 1;
1897 if (DEBUG_ERRORMGR
) pp_ip2fo(ip2fo
);
1900 return ip2fo
->names
+ (*offsets
)[ixInput
];
1903 // Grow fun and obj _offsets arrays to have at least n_req elements.
1904 // Ensure n_offsets_per_ip is allocated.
1905 static void grow_offsets(IPtoFunOrObjCompleter
* ip2fo
, Int n_req
)
1909 // n_offsets_per_ip must always have the size of the ips array
1910 if (ip2fo
->n_offsets_per_ip
== NULL
) {
1911 ip2fo
->n_offsets_per_ip
= VG_(malloc
)("grow_offsets",
1912 ip2fo
->n_ips
* sizeof(Int
));
1913 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1914 ip2fo
->n_offsets_per_ip
[i
] = 0;
1917 if (ip2fo
->sz_offsets
>= n_req
)
1920 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1921 // elements and at least a few more elements than the current size.
1922 if (n_req
< ip2fo
->n_ips
)
1923 n_req
= ip2fo
->n_ips
;
1924 if (n_req
< ip2fo
->sz_offsets
+ 5)
1925 n_req
= ip2fo
->sz_offsets
+ 5;
1927 ip2fo
->fun_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->fun_offsets
,
1928 n_req
* sizeof(Int
));
1929 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1930 ip2fo
->fun_offsets
[i
] = -1;
1932 ip2fo
->obj_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->obj_offsets
,
1933 n_req
* sizeof(Int
));
1934 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1935 ip2fo
->obj_offsets
[i
] = -1;
1937 ip2fo
->sz_offsets
= n_req
;
1940 // Expands more IPs from ip2fo->ips.
1941 static void expandInput (IPtoFunOrObjCompleter
* ip2fo
, UWord ixInput
)
1943 while (ip2fo
->n_ips_expanded
< ip2fo
->n_ips
1944 && ip2fo
->n_expanded
<= ixInput
) {
1945 if (VG_(clo_read_inline_info
)) {
1946 // Expand one more IP in one or more calls.
1947 const Addr IP
= ip2fo
->ips
[ip2fo
->n_ips_expanded
];
1950 iipc
= VG_(new_IIPC
)(ip2fo
->epoch
, IP
);
1951 // The only thing we really need is the nr of inlined fn calls
1952 // corresponding to the IP we will expand.
1953 // However, computing this is mostly the same as finding
1954 // the function name. So, let's directly complete the function name.
1956 const HChar
*caller
;
1957 grow_offsets(ip2fo
, ip2fo
->n_expanded
+1);
1958 ip2fo
->fun_offsets
[ip2fo
->n_expanded
] = ip2fo
->names_free
;
1959 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->epoch
, IP
,
1963 SizeT caller_len
= VG_(strlen
)(caller
);
1964 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1965 VG_(strcpy
)(caller_name
, caller
);
1966 ip2fo
->names_free
+= caller_len
+ 1;
1967 ip2fo
->n_expanded
++;
1968 ip2fo
->n_offsets_per_ip
[ip2fo
->n_ips_expanded
]++;
1969 } while (VG_(next_IIPC
)(iipc
));
1970 ip2fo
->n_ips_expanded
++;
1971 VG_(delete_IIPC
) (iipc
);
1973 // Without inlined fn call info, expansion simply
1974 // consists in allocating enough elements in (fun|obj)_offsets.
1975 // The function or object names themselves will be completed
1978 grow_offsets(ip2fo
, ip2fo
->n_ips
);
1979 ip2fo
->n_ips_expanded
= ip2fo
->n_ips
;
1980 ip2fo
->n_expanded
= ip2fo
->n_ips
;
1981 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1982 ip2fo
->n_offsets_per_ip
[i
] = 1;
1987 static Bool
haveInputInpC (void* inputCompleterV
, UWord ixInput
)
1989 IPtoFunOrObjCompleter
* ip2fo
= (IPtoFunOrObjCompleter
*)inputCompleterV
;
1990 expandInput(ip2fo
, ixInput
);
1991 return ixInput
< ip2fo
->n_expanded
;
1994 static Bool
supp_pattEQinp ( const void* supplocV
, const void* addrV
,
1995 void* inputCompleterV
, UWord ixInput
)
1997 const SuppLoc
* supploc
= (const SuppLoc
*)supplocV
; /* PATTERN */
1998 IPtoFunOrObjCompleter
* ip2fo
= (IPtoFunOrObjCompleter
*)inputCompleterV
;
1999 const HChar
* funobjsrc_name
; // Fun, Obj, or src file name.
2000 UInt src_lineno
= 0;
2003 expandInput(ip2fo
, ixInput
);
2004 vg_assert(ixInput
< ip2fo
->n_expanded
);
2006 /* So, does this IP address match this suppression-line? */
2007 switch (supploc
->ty
) {
2009 /* supp_pattEQinp is a callback from VG_(generic_match). As
2010 per the spec thereof (see include/pub_tool_seqmatch.h), we
2011 should never get called with a pattern value for which the
2012 _IsStar or _IsQuery function would return True. Hence
2013 this can't happen. */
2016 funobjsrc_name
= foComplete(ip2fo
, ixInput
, False
/*needFun*/);
2019 funobjsrc_name
= foComplete(ip2fo
, ixInput
, True
/*needFun*/);
2022 const HChar
* src_dirname
; // placeholder only
2023 ret
= VG_(get_filename_linenum
)(VG_(current_DiEpoch
)(),
2024 ip2fo
->ips
[ixInput
], &funobjsrc_name
, &src_dirname
, &src_lineno
);
2026 /* No file name found for location so no way this is a match. */
2035 /* So now we have the function or object name in funobjsrc_name, and
2036 the pattern (at the character level) to match against is in
2037 supploc->name. Hence (and leading to a re-entrant call of
2038 VG_(generic_match) if there is a wildcard character): */
2039 if (supploc
->name_is_simple_str
)
2040 ret
= VG_(strcmp
) (supploc
->name
, funobjsrc_name
) == 0;
2042 ret
= VG_(string_match
)(supploc
->name
, funobjsrc_name
);
2043 if (ret
&& supploc
->ty
== SrcName
&& supploc
->lineno
!= 0) {
2044 ret
= (supploc
->lineno
== src_lineno
);
2047 VG_(printf
) ("supp_pattEQinp %s patt %s ixInput %lu value:%s (lineno:%u vs %u) match:%s\n",
2048 supploc
->ty
== FunName
? "fun" : (supploc
->ty
== SrcName
? "src" : "obj"),
2049 supploc
->name
, ixInput
, funobjsrc_name
,
2050 supploc
->ty
== SrcName
? supploc
->lineno
: 0,
2051 supploc
->ty
== SrcName
? src_lineno
: 0,
2052 ret
? "yes" : "no");
2056 /////////////////////////////////////////////////////
2058 static Bool
supp_matches_callers(IPtoFunOrObjCompleter
* ip2fo
,
2061 /* Unwrap the args and set up the correct parameterisation of
2062 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
2064 /* note, StackTrace ip2fo->ips === Addr* */
2065 SuppLoc
* supps
= su
->callers
;
2066 UWord n_supps
= su
->n_callers
;
2067 UWord szbPatt
= sizeof(SuppLoc
);
2068 Bool matchAll
= False
; /* we just want to match a prefix */
2069 if (DEBUG_ERRORMGR
) {
2070 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
2071 su
->clo_suppressions_i
);
2072 VG_(dmsg
)(" errormgr Checking match with %s %s:%d\n",
2080 /*PATT*/supps
, szbPatt
, n_supps
, 0/*initial ixPatt*/,
2082 NULL
, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
2083 0/*initial ixInput*/,
2084 supploc_IsStar
, supploc_IsQuery
, supp_pattEQinp
,
2085 ip2fo
, haveInputInpC
2089 /////////////////////////////////////////////////////
2092 Bool
supp_matches_error(const Supp
* su
, const Error
* err
)
2094 if (su
->skind
>= 0) {
2095 if (VG_(needs
).tool_errors
) {
2096 return VG_TDICT_CALL(tool_error_matches_suppression
, err
, su
);
2099 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
2100 "probably needs to be set.\n",
2102 VG_(core_panic
)("unhandled suppression type");
2105 return core_error_matches_suppression(err
, su
);
2109 /////////////////////////////////////////////////////
2111 /* Does an error context match a suppression? ie is this a suppressible
2112 error? If so, return a pointer to the Supp record, otherwise NULL.
2113 Tries to minimise the number of symbol searches since they are expensive.
2115 static Supp
* is_suppressible_error ( const Error
* err
)
2120 IPtoFunOrObjCompleter ip2fo
;
2121 /* Conceptually, ip2fo contains an array of function names and an array of
2122 object names, corresponding to the array of IP of err->where.
2123 These names are just computed 'on demand' (so once maximum),
2124 then stored (efficiently, avoiding too many allocs) in ip2fo to be
2125 re-usable for the matching of the same IP with the next suppression
2128 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
2129 of its arguments. It will then pass it to the function
2130 supp_pattEQinp which will then lazily complete the IP function name or
2131 object name inside ip2fo. Next time the fun or obj name for the same
2132 IP is needed (i.e. for the matching with the next suppr pattern), then
2133 the fun or obj name will not be searched again in the debug info. */
2135 if (err
->where
== NULL
)
2138 /* stats gathering */
2139 em_supplist_searches
++;
2141 /* Prepare the lazy input completer. */
2142 ip2fo
.epoch
= VG_(get_ExeContext_epoch
)(err
->where
);
2143 ip2fo
.ips
= VG_(get_ExeContext_StackTrace
)(err
->where
);
2144 ip2fo
.n_ips
= VG_(get_ExeContext_n_ips
)(err
->where
);
2145 ip2fo
.n_ips_expanded
= 0;
2146 ip2fo
.n_expanded
= 0;
2147 ip2fo
.sz_offsets
= 0;
2148 ip2fo
.n_offsets_per_ip
= NULL
;
2149 ip2fo
.fun_offsets
= NULL
;
2150 ip2fo
.obj_offsets
= NULL
;
2152 ip2fo
.names_szB
= 0;
2153 ip2fo
.names_free
= 0;
2155 /* See if the error context matches any suppression. */
2156 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4)
2157 VG_(dmsg
)("errormgr matching begin\n");
2159 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
2161 if (supp_matches_error(su
, err
)
2162 && supp_matches_callers(&ip2fo
, su
)) {
2164 /* Inform the tool that err is suppressed by su. */
2166 (void)VG_TDICT_CALL(tool_update_extra_suppression_use
, err
, su
);
2167 /* No core errors need to update extra suppression info */
2168 /* Move this entry to the head of the list
2169 in the hope of making future searches cheaper. */
2171 vg_assert(su_prev
->next
== su
);
2172 su_prev
->next
= su
->next
;
2173 su
->next
= suppressions
;
2176 clearIPtoFunOrObjCompleter(su
, &ip2fo
);
2181 clearIPtoFunOrObjCompleter(NULL
, &ip2fo
);
2182 return NULL
; /* no matches */
2185 /* Show accumulated error-list and suppression-list search stats.
2187 void VG_(print_errormgr_stats
) ( void )
2190 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
2191 em_supplist_searches
, em_supplist_cmps
2194 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
2195 em_errlist_searches
, em_errlist_cmps
2199 /*--------------------------------------------------------------------*/
2201 /*--------------------------------------------------------------------*/