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 warnings if the tool wants to, we're not running with -q,
301 // and were not outputting XML.
302 Bool
VG_(showing_core_warnings
)(void)
304 return VG_(needs
).core_errors
&& VG_(clo_verbosity
) >= 1 && !VG_(clo_xml
);
307 /* Compare errors, to detect duplicates.
309 static Bool
eq_Error ( VgRes res
, const Error
* e1
, const Error
* e2
)
311 if (e1
->ekind
!= e2
->ekind
)
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
||
971 e
->ekind
== FdBadUse
;
974 static Bool
core_eq_Error (VgRes res
, const Error
*e1
, const Error
*e2
)
976 if (is_fd_core_error(e1
))
977 return fd_eq_Error (res
, e1
, e2
);
979 VG_(umsg
)("FATAL: unknown core error kind: %d\n", e1
->ekind
);
984 static void core_before_pp_Error (const Error
*err
)
986 if (is_fd_core_error(err
))
987 fd_before_pp_Error(err
);
989 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
994 static void core_pp_Error (const Error
*err
)
996 if (is_fd_core_error(err
))
999 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
1004 static UInt
core_update_extra (const Error
*err
)
1006 if (is_fd_core_error(err
))
1007 return fd_update_extra(err
);
1009 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
1014 static const HChar
*core_get_error_name(const Error
*err
)
1016 switch (err
->ekind
) {
1018 return "FdBadClose";
1020 return "FdNotClosed";
1024 VG_(umsg
)("FATAL: unknown core error kind: %d\n", err
->ekind
);
1029 static Bool
core_error_matches_suppression(const Error
* err
, const Supp
* su
)
1031 switch (su
->skind
) {
1032 case FdBadCloseSupp
:
1033 return err
->ekind
== FdBadClose
;
1034 case FdNotClosedSupp
:
1035 return err
->ekind
== FdNotClosed
;
1037 return err
->ekind
== FdBadUse
;
1039 VG_(umsg
)("FATAL: unknown core suppression kind: %d\n", su
->skind
);
1044 static SizeT
core_get_extra_suppression_info(const Error
*err
,
1045 HChar
* buf
, Int nBuf
)
1047 /* No core error has any extra suppression info at the moment. */
1052 static SizeT
core_print_extra_suppression_use(const Supp
* su
,
1053 HChar
* buf
, Int nBuf
)
1055 /* No core error has any extra suppression info at the moment. */
1061 /*------------------------------------------------------------*/
1062 /*--- Exported fns ---*/
1063 /*------------------------------------------------------------*/
1065 /* Show the used suppressions. Returns False if no suppression
1067 static Bool
show_used_suppressions ( void )
1073 VG_(printf_xml
)("<suppcounts>\n");
1076 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
1080 VG_(printf_xml
)( " <pair>\n"
1081 " <count>%d</count>\n"
1082 " <name>%pS</name>\n"
1084 su
->count
, su
->sname
);
1089 // blank line before the first shown suppression, if any
1095 xtra
= VG_(realloc
)("errormgr.sus.1", xtra
, xtra_size
);
1097 num_written
= VG_TDICT_CALL(tool_print_extra_suppression_use
,
1098 su
, xtra
, xtra_size
);
1100 num_written
= core_print_extra_suppression_use(su
,
1102 } while (num_written
== xtra_size
); // resize buffer and retry
1104 // Ensure buffer is properly terminated
1105 vg_assert(xtra
[num_written
] == '\0');
1107 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1108 su
->clo_suppressions_i
);
1109 VG_(dmsg
)("used_suppression: %6d %s %s:%d%s%s\n", su
->count
, su
->sname
,
1112 num_written
? " " : "", xtra
);
1119 VG_(printf_xml
)("</suppcounts>\n");
1124 /* See pub_core_errormgr.h. */
1125 void VG_(show_all_errors
) ( Int verbosity
, Bool xml
, Int show_error_list
)
1130 Bool any_error
= False
;
1133 if (verbosity
== 0 && show_error_list
== 0)
1136 /* If we're printing XML, just show the suppressions and stop. */
1138 if (show_error_list
> 0)
1139 (void)show_used_suppressions();
1143 /* We only get here if not printing XML. */
1144 VG_(umsg
)("ERROR SUMMARY: "
1145 "%u errors from %u contexts (suppressed: %u from %u)\n",
1146 n_errs_found
, n_err_contexts
,
1147 n_errs_suppressed
, n_supp_contexts
);
1149 if (show_error_list
== 0)
1152 // We do the following if show_error_list > 0
1153 // or at -v or above, and only in non-XML mode.
1155 /* Print the contexts in order of increasing error count.
1156 The below implements this in a quadratic algorithm based on the assumption
1157 that there are not too many errors (including the suppressed if showing
1158 the suppressed errors) !
1159 Once an error is shown, we add a huge value to its count to filter it
1161 After having shown all errors, we reset count to the original value. */
1162 n_errs
= n_err_contexts
+ (show_error_list
< 2 ? 0 : n_errs_suppressed
);
1163 for (i
= 0; i
< n_errs
; i
++) {
1164 n_min
= (1 << 30) - 1;
1166 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1167 if (show_error_list
< 2 && p
->supp
!= NULL
) continue;
1168 if (p
->count
< n_min
) {
1173 // XXX: this isn't right. See bug 203651.
1174 if (p_min
== NULL
) continue; //VG_(core_panic)("show_all_errors()");
1178 VG_(umsg
)("%d errors%s%s%s in context %d of %u:\n",
1180 p_min
->supp
== NULL
? "" : " (suppressed by ",
1181 p_min
->supp
== NULL
? "" : p_min
->supp
->sname
,
1182 p_min
->supp
== NULL
? "" : ")",
1184 pp_Error( p_min
, False
/*allow_db_attach*/, False
/* xml */, True
/* count_error */ );
1186 // We're not printing XML -- we'd have exited above if so.
1189 if ((i
+1 == VG_(clo_dump_error
))) {
1190 StackTrace ips
= VG_(get_ExeContext_StackTrace
)(p_min
->where
);
1191 VG_(translate
) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1192 ips
[0], /*debugging*/True
, 0xFE/*verbosity*/,
1194 /*allow redir?*/True
);
1197 p_min
->count
= p_min
->count
+ (1 << 30);
1200 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1201 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1202 if (p
->count
>= (1 << 30))
1203 p
->count
= p
->count
- (1 << 30);
1207 any_supp
= show_used_suppressions();
1211 // reprint summary, so users don't have to scroll way up to find
1212 // the first printing
1213 if (any_supp
|| any_error
)
1214 VG_(umsg
)("ERROR SUMMARY: "
1215 "%u errors from %u contexts (suppressed: %u from %u)\n",
1216 n_errs_found
, n_err_contexts
, n_errs_suppressed
,
1220 void VG_(show_last_error
) ( void )
1222 if (n_err_contexts
== 0) {
1223 VG_(umsg
)("No errors yet\n");
1227 pp_Error( errors
, False
/*allow_db_attach*/, False
/*xml*/, True
/*count_error*/ );
1231 /* Show occurrence counts of all errors, in XML form. */
1232 void VG_(show_error_counts_as_XML
) ( void )
1235 VG_(printf_xml
)("<errorcounts>\n");
1236 for (err
= errors
; err
!= NULL
; err
= err
->next
) {
1237 if (err
->supp
!= NULL
)
1239 if (err
->count
<= 0)
1241 VG_(printf_xml
)(" <pair>\n");
1242 VG_(printf_xml
)(" <count>%d</count>\n", err
->count
);
1243 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
1244 VG_(printf_xml
)(" </pair>\n");
1246 VG_(printf_xml
)("</errorcounts>\n");
1247 VG_(printf_xml
)("\n");
1251 /*------------------------------------------------------------*/
1252 /*--- Suppression parsing ---*/
1253 /*------------------------------------------------------------*/
1255 /* Get the next char from fd into *out_buf. Returns 1 if success,
1256 0 if eof or < 0 if error. */
1258 static Int
get_char ( Int fd
, HChar
* out_buf
)
1261 static HChar buf
[256];
1262 static Int buf_size
= 0;
1263 static Int buf_used
= 0;
1264 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1265 vg_assert(buf_used
>= 0 && buf_used
<= buf_size
);
1266 if (buf_used
== buf_size
) {
1267 r
= VG_(read
)(fd
, buf
, sizeof buf
);
1268 if (r
< 0) return r
; /* read failed */
1269 vg_assert(r
>= 0 && r
<= sizeof buf
);
1275 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1276 vg_assert(buf_used
>= 0 && buf_used
< buf_size
);
1277 *out_buf
= buf
[buf_used
];
1282 // Get a non blank non comment line.
1283 // Returns True if eof.
1284 static Bool
get_nbnc_line ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1286 HChar
* buf
= *bufpp
;
1287 SizeT nBuf
= *nBufp
;
1291 vg_assert(lineno
); // lineno needed to correctly track line numbers.
1295 /* First, read until a non-blank char appears. */
1297 n
= get_char(fd
, &ch
);
1298 if (n
== 1 && !VG_(isspace
)(ch
)) break;
1299 if (n
== 1 && ch
== '\n')
1301 if (n
<= 0) return True
;
1304 /* Now, read the line into buf. */
1306 buf
[i
++] = ch
; buf
[i
] = 0;
1308 n
= get_char(fd
, &ch
);
1309 if (n
<= 0) return False
; /* the next call will return True */
1312 if (ch
== '\n') break;
1313 if (i
> 0 && i
== nBuf
-1) {
1314 *nBufp
= nBuf
= nBuf
* 2;
1315 #define RIDICULOUS 100000
1316 vg_assert2(nBuf
< RIDICULOUS
, // Just a sanity check, really.
1317 "VG_(get_line): line longer than %d chars, aborting\n",
1319 *bufpp
= buf
= VG_(realloc
)("errormgr.get_line.1", buf
, nBuf
);
1321 buf
[i
++] = ch
; buf
[i
] = 0;
1323 while (i
> 1 && VG_(isspace
)(buf
[i
-1])) {
1327 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1328 /* Ok, we have a line. If a non-comment line, return.
1329 If a comment line, start all over again. */
1330 if (buf
[0] != '#') return False
;
1334 // True if buf starts with fun: or obj: or is ...
1335 static Bool
is_location_line (const HChar
* buf
)
1337 return VG_(strncmp
)(buf
, "fun:", 4) == 0
1338 || VG_(strncmp
)(buf
, "obj:", 4) == 0
1339 || VG_(strcmp
)(buf
, "...") == 0;
1342 Bool
VG_(get_line
) ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1344 Bool eof
= get_nbnc_line (fd
, bufpp
, nBufp
, lineno
);
1349 if (is_location_line(*bufpp
))
1350 return True
; // Not a extra suppr line
1352 return False
; // A suppression extra line
1355 /* True if s contains no wildcard (?, *) characters. */
1356 static Bool
is_simple_str (const HChar
*s
)
1359 if (*s
== '?' || *s
== '*')
1366 /* buf contains the raw name of a caller, supposedly either
1367 fun:some_function_name or
1368 obj:some_object_name or
1369 src:some_file_name or
1370 src:some_file_name:line# or
1372 Set p->ty and p->name accordingly.
1373 p->name is allocated and set to the string
1374 after the descriptor (fun:, obj:, or src: san line#) part.
1375 p->lineno is set to non-zero if line# specified; 0 otherwise.
1376 Returns False if failed.
1378 static Bool
setLocationTy ( SuppLoc
* p
, const HChar
*buf
)
1380 if (VG_(strncmp
)(buf
, "fun:", 4) == 0) {
1381 p
->name
= VG_(strdup
)("errormgr.sLTy.1", buf
+4);
1382 p
->name_is_simple_str
= is_simple_str (p
->name
);
1386 if (VG_(strncmp
)(buf
, "obj:", 4) == 0) {
1387 p
->name
= VG_(strdup
)("errormgr.sLTy.2", buf
+4);
1388 p
->name_is_simple_str
= is_simple_str (p
->name
);
1392 if (VG_(strncmp
)(buf
, "src:", 4) == 0) {
1393 p
->name
= VG_(strdup
)("errormgr.sLTy.3", buf
+4);
1394 p
->name_is_simple_str
= is_simple_str (p
->name
);
1396 HChar
*s
= VG_(strchr
)(p
->name
, ':');
1398 *s
++ = '\0'; // trim colon
1399 p
->lineno
= (UInt
) VG_(strtoll10
)(s
, NULL
);
1405 if (VG_(strcmp
)(buf
, "...") == 0) {
1407 p
->name_is_simple_str
= False
;
1411 VG_(printf
)("location should be \"...\", or should start "
1412 "with \"fun:\", \"obj:\", or \"src:\"\n");
1417 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1418 static Bool
tool_name_present(const HChar
*name
, const HChar
*names
)
1421 HChar
*s
= NULL
; /* Shut gcc up */
1422 Int len
= VG_(strlen
)(name
);
1424 found
= (NULL
!= (s
= VG_(strstr
)(names
, name
))
1425 && (s
== names
|| *(s
-1) == ',')
1426 && (*(s
+len
) == ',' || *(s
+len
) == '\0'));
1431 /* Read suppressions from the file specified in
1432 VG_(clo_suppressions)[clo_suppressions_i]
1433 and place them in the suppressions list. If there's any difficulty
1434 doing this, just give up -- there's no point in trying to recover.
1436 static void load_one_suppressions_file ( Int clo_suppressions_i
)
1438 const HChar
* filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1439 clo_suppressions_i
);
1441 Int fd
, i
, j
, lineno
= 0;
1442 Bool got_a_location_line_read_by_tool
;
1445 HChar
* buf
= VG_(malloc
)("errormgr.losf.1", nBuf
);
1448 const HChar
* err_str
= NULL
;
1449 SuppLoc tmp_callers
[VG_DEEPEST_BACKTRACE
];
1451 // Check it's not a directory.
1452 if (VG_(is_dir
)( filename
)) {
1454 VG_(printf_xml
)("</valgrindoutput>\n");
1455 VG_(umsg
)("FATAL: suppressions file \"%s\" is a directory\n", filename
);
1459 // Open the suppression file.
1460 sres
= VG_(open
)( filename
, VKI_O_RDONLY
, 0 );
1461 if (sr_isError(sres
)) {
1463 VG_(printf_xml
)("</valgrindoutput>\n");
1464 VG_(umsg
)("FATAL: can't open suppressions file \"%s\"\n", filename
);
1469 # define BOMB(S) { err_str = S; goto syntax_error; }
1472 /* Assign and initialise the two suppression halves (core and tool) */
1474 supp
= VG_(malloc
)("errormgr.losf.1", sizeof(Supp
));
1477 // Initialise temporary reading-in buffer.
1478 for (i
= 0; i
< VG_DEEPEST_BACKTRACE
; i
++) {
1479 tmp_callers
[i
].ty
= NoName
;
1480 tmp_callers
[i
].name_is_simple_str
= False
;
1481 tmp_callers
[i
].name
= NULL
;
1484 supp
->string
= supp
->extra
= NULL
;
1486 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1492 if (!VG_STREQ(buf
, "{")) BOMB("expected '{' or end-of-file");
1494 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1496 if (eof
|| VG_STREQ(buf
, "}")) BOMB("unexpected '}'");
1498 supp
->sname
= VG_(strdup
)("errormgr.losf.2", buf
);
1499 supp
->clo_suppressions_i
= clo_suppressions_i
;
1500 supp
->sname_lineno
= lineno
;
1502 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1504 if (eof
) BOMB("unexpected end-of-file (expecting tool:suppr)");
1506 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1509 if (buf
[i
] == ':') break;
1510 if (buf
[i
] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1513 buf
[i
] = '\0'; /* Replace ':', splitting into two strings */
1515 tool_names
= & buf
[0];
1516 supp_name
= & buf
[i
+1];
1518 if (VG_(needs
).core_errors
1519 && tool_name_present("CoreError", tool_names
)) {
1520 // A core suppression
1521 if (VG_STREQ(supp_name
, "FdBadClose"))
1522 supp
->skind
= FdBadCloseSupp
;
1523 else if (VG_STREQ(supp_name
, "FdNotClosed"))
1524 supp
->skind
= FdNotClosedSupp
;
1526 BOMB("unknown core suppression type");
1528 else if (VG_(needs
).tool_errors
1529 && tool_name_present(VG_(details
).name
, tool_names
)) {
1530 // A tool suppression
1531 if (VG_TDICT_CALL(tool_recognised_suppression
, supp_name
, supp
)) {
1532 /* Do nothing, function fills in supp->skind */
1534 BOMB("unknown tool suppression type");
1538 // Ignore rest of suppression
1540 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1541 if (eof
) BOMB("unexpected end-of-file (when skipping suppression)");
1542 if (VG_STREQ(buf
, "}"))
1545 VG_(free
)(supp
->sname
);
1551 // tool_read_extra_suppression_info might read lines
1552 // from fd till a location line.
1553 if (VG_(needs
).tool_errors
1554 && !VG_TDICT_CALL(tool_read_extra_suppression_info
,
1555 fd
, &buf
, &nBuf
, &lineno
, supp
)) {
1556 BOMB("bad or missing extra suppression info");
1559 // No core errors need to read extra suppression info
1561 got_a_location_line_read_by_tool
= buf
[0] != 0 && is_location_line(buf
);
1563 /* the main frame-descriptor reading loop */
1566 if (got_a_location_line_read_by_tool
) {
1567 got_a_location_line_read_by_tool
= False
;
1570 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1573 BOMB("unexpected end-of-file (when reading stack trace)");
1574 if (VG_STREQ(buf
, "}")) {
1578 BOMB("missing stack trace");
1581 if (i
== VG_DEEPEST_BACKTRACE
)
1582 BOMB("too many callers in stack trace");
1583 if (i
> 0 && i
>= VG_(clo_backtrace_size
))
1585 if (!setLocationTy(&(tmp_callers
[i
]), buf
))
1586 BOMB("location should be \"...\", or should start "
1587 "with \"fun:\", \"obj:\", or \"src:\"");
1591 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1592 // lines and grab the '}'.
1593 if (!VG_STREQ(buf
, "}")) {
1595 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1596 } while (!eof
&& !VG_STREQ(buf
, "}"));
1599 // Reject entries which are entirely composed of frame
1601 vg_assert(i
> 0); // guaranteed by frame-descriptor reading loop
1602 for (j
= 0; j
< i
; j
++) {
1603 if (tmp_callers
[j
].ty
== FunName
|| tmp_callers
[j
].ty
== ObjName
1604 || tmp_callers
[j
].ty
== SrcName
) {
1607 vg_assert(tmp_callers
[j
].ty
== DotDotDot
);
1609 vg_assert(j
>= 0 && j
<= i
);
1611 // we didn't find any non-"..." entries
1612 BOMB("suppression must contain at least one location "
1613 "line which is not \"...\"");
1616 // Copy tmp_callers[] into supp->callers[]
1617 supp
->n_callers
= i
;
1618 supp
->callers
= VG_(malloc
)("errormgr.losf.4", i
* sizeof(SuppLoc
));
1619 for (i
= 0; i
< supp
->n_callers
; i
++) {
1620 supp
->callers
[i
] = tmp_callers
[i
];
1623 supp
->next
= suppressions
;
1624 suppressions
= supp
;
1632 VG_(printf_xml
)("</valgrindoutput>\n");
1633 VG_(umsg
)("FATAL: in suppressions file \"%s\" near line %d:\n",
1635 VG_(umsg
)(" %s\n", err_str
);
1638 VG_(umsg
)("exiting now.\n");
1644 void VG_(add_suppression_file
)(const HChar
*filename
)
1646 HChar
*f
= VG_(strdup
)("errormgr.addsup", filename
);
1647 VG_(addToXA
)(VG_(clo_suppressions
), &f
);
1648 if (load_suppressions_called
)
1649 load_one_suppressions_file( VG_(sizeXA
)(VG_(clo_suppressions
)) - 1 );
1652 void VG_(load_suppressions
) ( void )
1655 suppressions
= NULL
;
1656 load_suppressions_called
= True
;
1657 for (i
= 0; i
< VG_(sizeXA
)(VG_(clo_suppressions
)); i
++) {
1658 if (VG_(clo_verbosity
) > 1) {
1659 VG_(dmsg
)("Reading suppressions file: %s\n",
1660 *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
), i
));
1662 load_one_suppressions_file( i
);
1667 /*------------------------------------------------------------*/
1668 /*--- Matching errors to suppressions ---*/
1669 /*------------------------------------------------------------*/
1671 /* Parameterising functions for the use of VG_(generic_match) in
1672 suppression-vs-error matching. The suppression frames (SuppLoc)
1673 play the role of 'pattern'-element, and the error frames (IPs,
1674 hence simply Addrs) play the role of 'input'. In short then, we're
1675 matching a sequence of Addrs against a pattern composed of a
1676 sequence of SuppLocs.
1678 static Bool
supploc_IsStar ( const void* supplocV
)
1680 const SuppLoc
* supploc
= supplocV
;
1681 return supploc
->ty
== DotDotDot
;
1684 static Bool
supploc_IsQuery ( const void* supplocV
)
1686 return False
; /* there's no '?' equivalent in the supp syntax */
1689 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1690 needed to match an error with the suppression patterns.
1691 The matching between an IP and a suppression pattern is done either
1692 with the IP function name or with the IP object name.
1693 First time the fun or obj name is needed for an IP member
1694 of a stack trace, it will be computed and stored in names.
1695 Also, if the IP corresponds to one or more inlined function calls,
1696 the inlined function names are expanded.
1697 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1698 allocations and the nr of debuginfo search. */
1701 DiEpoch epoch
; // used to interpret .ips
1702 StackTrace ips
; // stack trace we are lazily completing.
1703 UWord n_ips
; // nr of elements in ips.
1705 // VG_(generic_match) calls haveInputInpC to check
1706 // for the presence of an input element identified by ixInput
1707 // (i.e. a number that identifies the ixInput element of the
1708 // input sequence). It calls supp_pattEQinp to match this input
1709 // element with a pattern.
1710 // When inlining info is used to provide inlined function calls
1711 // in stacktraces, one IP in ips can be expanded in several
1712 // function names. So, each time input (or presence of input)
1713 // is requested by VG_(generic_match), we will expand
1714 // more IP of ips till we have expanded enough to reach the
1715 // input element requested (or we cannot expand anymore).
1717 UWord n_ips_expanded
;
1718 // n_ips_expanded maintains the nr of elements in ips that we have
1719 // already expanded.
1721 // n_expanded maintains the nr of elements resulting from the expansion
1722 // of the n_ips_expanded IPs. Without inlined function calls,
1723 // n_expanded == n_ips_expanded. With inlining info,
1724 // n_expanded >= n_ips_expanded.
1726 Int
* n_offsets_per_ip
;
1727 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1728 // obj_offsets resulting of the expansion of ips[i].
1729 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1730 // This array allows to retrieve the position in ips corresponding to
1733 // size (in elements) of fun_offsets and obj_offsets.
1734 // (fun|obj)_offsets are reallocated if more space is needed
1739 // fun_offsets[ixInput] is the offset in names where the
1740 // function name for the ixInput element of the input sequence
1741 // can be found. As one IP of ips can be expanded in several
1742 // function calls due to inlined function calls, we can have more
1743 // elements in fun_offsets than in ips.
1744 // An offset -1 means the function name has not yet been computed.
1746 // Similarly, obj_offsets[ixInput] gives the offset for the
1747 // object name for ips[ixInput]
1748 // (-1 meaning object name not yet been computed).
1750 // All function names and object names will be concatenated
1751 // in names. names is reallocated on demand.
1753 Int names_szB
; // size of names.
1754 Int names_free
; // offset first free HChar in names.
1756 IPtoFunOrObjCompleter
;
1758 static void pp_ip2fo (const IPtoFunOrObjCompleter
* ip2fo
)
1763 VG_(printf
)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1764 ip2fo
->n_ips
, ip2fo
->n_ips_expanded
, ip2fo
->n_expanded
);
1765 for (i
= 0; i
< ip2fo
->n_ips_expanded
; i
++) {
1767 for (j
= 0; j
< i
; j
++)
1768 o
+= ip2fo
->n_offsets_per_ip
[j
];
1769 VG_(printf
)("ips %d 0x08%lx offset [%d,%d] ",
1771 o
, o
+ip2fo
->n_offsets_per_ip
[i
]-1);
1772 for (j
= 0; j
< ip2fo
->n_offsets_per_ip
[i
]; j
++) {
1773 VG_(printf
)("%sfun:%s obj:%s\n",
1775 ip2fo
->fun_offsets
[o
+j
] == -1 ?
1776 "<not expanded>" : &ip2fo
->names
[ip2fo
->fun_offsets
[o
+j
]],
1777 ip2fo
->obj_offsets
[o
+j
] == -1 ?
1778 "<not expanded>" : &ip2fo
->names
[ip2fo
->obj_offsets
[o
+j
]]);
1783 /* free the memory in ip2fo.
1784 At debuglog 4, su (or NULL) will be used to show the matching
1785 (or non matching) with ip2fo. */
1786 static void clearIPtoFunOrObjCompleter ( const Supp
*su
,
1787 IPtoFunOrObjCompleter
* ip2fo
)
1789 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4) {
1791 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1792 su
->clo_suppressions_i
);
1793 VG_(dmsg
)("errormgr matching end suppression %s %s:%d matched:\n",
1798 VG_(dmsg
)("errormgr matching end no suppression matched:\n");
1800 VG_(pp_StackTrace
) (ip2fo
->epoch
, ip2fo
->ips
, ip2fo
->n_ips
);
1803 if (ip2fo
->n_offsets_per_ip
) VG_(free
)(ip2fo
->n_offsets_per_ip
);
1804 if (ip2fo
->fun_offsets
) VG_(free
)(ip2fo
->fun_offsets
);
1805 if (ip2fo
->obj_offsets
) VG_(free
)(ip2fo
->obj_offsets
);
1806 if (ip2fo
->names
) VG_(free
)(ip2fo
->names
);
1809 /* Grow ip2fo->names to ensure we have NEEDED characters available
1810 in ip2fo->names and returns a pointer to the first free char. */
1811 static HChar
* grow_names(IPtoFunOrObjCompleter
* ip2fo
, SizeT needed
)
1813 if (ip2fo
->names_szB
1814 < ip2fo
->names_free
+ needed
) {
1815 if (needed
< ERRTXT_LEN
) needed
= ERRTXT_LEN
;
1818 = VG_(realloc
)("foc_names",
1820 ip2fo
->names_szB
+ needed
);
1821 ip2fo
->names_szB
+= needed
;
1823 return ip2fo
->names
+ ip2fo
->names_free
;
1826 /* foComplete returns the function name or object name for ixInput.
1827 If needFun, returns the function name for this input
1828 else returns the object name for this input.
1829 The function name or object name will be computed and added in
1830 names if not yet done. */
1831 static HChar
* foComplete(IPtoFunOrObjCompleter
* ip2fo
,
1832 Int ixInput
, Bool needFun
)
1834 vg_assert (ixInput
< ip2fo
->n_expanded
);
1835 vg_assert (VG_(clo_read_inline_info
) || ixInput
< ip2fo
->n_ips
);
1837 // ptr to the offset array for function offsets (if needFun)
1838 // or object offsets (if !needFun).
1841 offsets
= &ip2fo
->fun_offsets
;
1843 offsets
= &ip2fo
->obj_offsets
;
1845 // Complete Fun name or Obj name for IP if not yet done.
1846 if ((*offsets
)[ixInput
] == -1) {
1847 const HChar
* caller
;
1849 (*offsets
)[ixInput
] = ip2fo
->names_free
;
1850 if (DEBUG_ERRORMGR
) VG_(printf
)("marking %s ixInput %d offset %d\n",
1851 needFun
? "fun" : "obj",
1852 ixInput
, ip2fo
->names_free
);
1854 // With inline info, fn names must have been completed already.
1855 vg_assert (!VG_(clo_read_inline_info
));
1856 /* Get the function name into 'caller_name', or "???"
1858 // Nb: C++-mangled names are used in suppressions. Do, though,
1859 // Z-demangle them, since otherwise it's possible to wind
1860 // up comparing "malloc" in the suppression against
1861 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1862 // two of them need to be made to match.
1863 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->epoch
,
1864 ip2fo
->ips
[ixInput
],
1869 /* Get the object name into 'caller_name', or "???"
1872 UWord last_expand_pos_ips
= 0;
1875 /* First get the pos in ips corresponding to ixInput */
1876 for (pos_ips
= 0; pos_ips
< ip2fo
->n_expanded
; pos_ips
++) {
1877 last_expand_pos_ips
+= ip2fo
->n_offsets_per_ip
[pos_ips
];
1878 if (ixInput
< last_expand_pos_ips
)
1881 /* pos_ips is the position in ips corresponding to ixInput.
1882 last_expand_pos_ips is the last offset in fun/obj where
1883 ips[pos_ips] has been expanded. */
1885 if (!VG_(get_objname
)(ip2fo
->epoch
, ip2fo
->ips
[pos_ips
], &caller
))
1888 // Have all inlined calls pointing at this object name
1889 for (i
= last_expand_pos_ips
- ip2fo
->n_offsets_per_ip
[pos_ips
] + 1;
1890 i
< last_expand_pos_ips
;
1892 ip2fo
->obj_offsets
[i
] = ip2fo
->names_free
;
1894 VG_(printf
) (" set obj_offset %lu to %d\n",
1895 i
, ip2fo
->names_free
);
1898 SizeT caller_len
= VG_(strlen
)(caller
);
1899 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1900 VG_(strcpy
)(caller_name
, caller
);
1901 ip2fo
->names_free
+= caller_len
+ 1;
1902 if (DEBUG_ERRORMGR
) pp_ip2fo(ip2fo
);
1905 return ip2fo
->names
+ (*offsets
)[ixInput
];
1908 // Grow fun and obj _offsets arrays to have at least n_req elements.
1909 // Ensure n_offsets_per_ip is allocated.
1910 static void grow_offsets(IPtoFunOrObjCompleter
* ip2fo
, Int n_req
)
1914 // n_offsets_per_ip must always have the size of the ips array
1915 if (ip2fo
->n_offsets_per_ip
== NULL
) {
1916 ip2fo
->n_offsets_per_ip
= VG_(malloc
)("grow_offsets",
1917 ip2fo
->n_ips
* sizeof(Int
));
1918 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1919 ip2fo
->n_offsets_per_ip
[i
] = 0;
1922 if (ip2fo
->sz_offsets
>= n_req
)
1925 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1926 // elements and at least a few more elements than the current size.
1927 if (n_req
< ip2fo
->n_ips
)
1928 n_req
= ip2fo
->n_ips
;
1929 if (n_req
< ip2fo
->sz_offsets
+ 5)
1930 n_req
= ip2fo
->sz_offsets
+ 5;
1932 ip2fo
->fun_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->fun_offsets
,
1933 n_req
* sizeof(Int
));
1934 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1935 ip2fo
->fun_offsets
[i
] = -1;
1937 ip2fo
->obj_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->obj_offsets
,
1938 n_req
* sizeof(Int
));
1939 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1940 ip2fo
->obj_offsets
[i
] = -1;
1942 ip2fo
->sz_offsets
= n_req
;
1945 // Expands more IPs from ip2fo->ips.
1946 static void expandInput (IPtoFunOrObjCompleter
* ip2fo
, UWord ixInput
)
1948 while (ip2fo
->n_ips_expanded
< ip2fo
->n_ips
1949 && ip2fo
->n_expanded
<= ixInput
) {
1950 if (VG_(clo_read_inline_info
)) {
1951 // Expand one more IP in one or more calls.
1952 const Addr IP
= ip2fo
->ips
[ip2fo
->n_ips_expanded
];
1955 iipc
= VG_(new_IIPC
)(ip2fo
->epoch
, IP
);
1956 // The only thing we really need is the nr of inlined fn calls
1957 // corresponding to the IP we will expand.
1958 // However, computing this is mostly the same as finding
1959 // the function name. So, let's directly complete the function name.
1961 const HChar
*caller
;
1962 grow_offsets(ip2fo
, ip2fo
->n_expanded
+1);
1963 ip2fo
->fun_offsets
[ip2fo
->n_expanded
] = ip2fo
->names_free
;
1964 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->epoch
, IP
,
1968 SizeT caller_len
= VG_(strlen
)(caller
);
1969 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1970 VG_(strcpy
)(caller_name
, caller
);
1971 ip2fo
->names_free
+= caller_len
+ 1;
1972 ip2fo
->n_expanded
++;
1973 ip2fo
->n_offsets_per_ip
[ip2fo
->n_ips_expanded
]++;
1974 } while (VG_(next_IIPC
)(iipc
));
1975 ip2fo
->n_ips_expanded
++;
1976 VG_(delete_IIPC
) (iipc
);
1978 // Without inlined fn call info, expansion simply
1979 // consists in allocating enough elements in (fun|obj)_offsets.
1980 // The function or object names themselves will be completed
1983 grow_offsets(ip2fo
, ip2fo
->n_ips
);
1984 ip2fo
->n_ips_expanded
= ip2fo
->n_ips
;
1985 ip2fo
->n_expanded
= ip2fo
->n_ips
;
1986 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1987 ip2fo
->n_offsets_per_ip
[i
] = 1;
1992 static Bool
haveInputInpC (void* inputCompleterV
, UWord ixInput
)
1994 IPtoFunOrObjCompleter
* ip2fo
= (IPtoFunOrObjCompleter
*)inputCompleterV
;
1995 expandInput(ip2fo
, ixInput
);
1996 return ixInput
< ip2fo
->n_expanded
;
1999 static Bool
supp_pattEQinp ( const void* supplocV
, const void* addrV
,
2000 void* inputCompleterV
, UWord ixInput
)
2002 const SuppLoc
* supploc
= (const SuppLoc
*)supplocV
; /* PATTERN */
2003 IPtoFunOrObjCompleter
* ip2fo
= (IPtoFunOrObjCompleter
*)inputCompleterV
;
2004 const HChar
* funobjsrc_name
; // Fun, Obj, or src file name.
2005 UInt src_lineno
= 0;
2008 expandInput(ip2fo
, ixInput
);
2009 vg_assert(ixInput
< ip2fo
->n_expanded
);
2011 /* So, does this IP address match this suppression-line? */
2012 switch (supploc
->ty
) {
2014 /* supp_pattEQinp is a callback from VG_(generic_match). As
2015 per the spec thereof (see include/pub_tool_seqmatch.h), we
2016 should never get called with a pattern value for which the
2017 _IsStar or _IsQuery function would return True. Hence
2018 this can't happen. */
2021 funobjsrc_name
= foComplete(ip2fo
, ixInput
, False
/*needFun*/);
2024 funobjsrc_name
= foComplete(ip2fo
, ixInput
, True
/*needFun*/);
2027 const HChar
* src_dirname
; // placeholder only
2028 ret
= VG_(get_filename_linenum
)(VG_(current_DiEpoch
)(),
2029 ip2fo
->ips
[ixInput
], &funobjsrc_name
, &src_dirname
, &src_lineno
);
2031 /* No file name found for location so no way this is a match. */
2040 /* So now we have the function or object name in funobjsrc_name, and
2041 the pattern (at the character level) to match against is in
2042 supploc->name. Hence (and leading to a re-entrant call of
2043 VG_(generic_match) if there is a wildcard character): */
2044 if (supploc
->name_is_simple_str
)
2045 ret
= VG_(strcmp
) (supploc
->name
, funobjsrc_name
) == 0;
2047 ret
= VG_(string_match
)(supploc
->name
, funobjsrc_name
);
2048 if (ret
&& supploc
->ty
== SrcName
&& supploc
->lineno
!= 0) {
2049 ret
= (supploc
->lineno
== src_lineno
);
2052 VG_(printf
) ("supp_pattEQinp %s patt %s ixInput %lu value:%s (lineno:%u vs %u) match:%s\n",
2053 supploc
->ty
== FunName
? "fun" : (supploc
->ty
== SrcName
? "src" : "obj"),
2054 supploc
->name
, ixInput
, funobjsrc_name
,
2055 supploc
->ty
== SrcName
? supploc
->lineno
: 0,
2056 supploc
->ty
== SrcName
? src_lineno
: 0,
2057 ret
? "yes" : "no");
2061 /////////////////////////////////////////////////////
2063 static Bool
supp_matches_callers(IPtoFunOrObjCompleter
* ip2fo
,
2066 /* Unwrap the args and set up the correct parameterisation of
2067 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
2069 /* note, StackTrace ip2fo->ips === Addr* */
2070 SuppLoc
* supps
= su
->callers
;
2071 UWord n_supps
= su
->n_callers
;
2072 UWord szbPatt
= sizeof(SuppLoc
);
2073 Bool matchAll
= False
; /* we just want to match a prefix */
2074 if (DEBUG_ERRORMGR
) {
2075 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
2076 su
->clo_suppressions_i
);
2077 VG_(dmsg
)(" errormgr Checking match with %s %s:%d\n",
2085 /*PATT*/supps
, szbPatt
, n_supps
, 0/*initial ixPatt*/,
2087 NULL
, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
2088 0/*initial ixInput*/,
2089 supploc_IsStar
, supploc_IsQuery
, supp_pattEQinp
,
2090 ip2fo
, haveInputInpC
2094 /////////////////////////////////////////////////////
2097 Bool
supp_matches_error(const Supp
* su
, const Error
* err
)
2099 if (su
->skind
>= 0) {
2100 if (VG_(needs
).tool_errors
) {
2101 return VG_TDICT_CALL(tool_error_matches_suppression
, err
, su
);
2104 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
2105 "probably needs to be set.\n",
2107 VG_(core_panic
)("unhandled suppression type");
2110 return core_error_matches_suppression(err
, su
);
2114 /////////////////////////////////////////////////////
2116 /* Does an error context match a suppression? ie is this a suppressible
2117 error? If so, return a pointer to the Supp record, otherwise NULL.
2118 Tries to minimise the number of symbol searches since they are expensive.
2120 static Supp
* is_suppressible_error ( const Error
* err
)
2125 IPtoFunOrObjCompleter ip2fo
;
2126 /* Conceptually, ip2fo contains an array of function names and an array of
2127 object names, corresponding to the array of IP of err->where.
2128 These names are just computed 'on demand' (so once maximum),
2129 then stored (efficiently, avoiding too many allocs) in ip2fo to be
2130 re-usable for the matching of the same IP with the next suppression
2133 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
2134 of its arguments. It will then pass it to the function
2135 supp_pattEQinp which will then lazily complete the IP function name or
2136 object name inside ip2fo. Next time the fun or obj name for the same
2137 IP is needed (i.e. for the matching with the next suppr pattern), then
2138 the fun or obj name will not be searched again in the debug info. */
2140 if (err
->where
== NULL
)
2143 /* stats gathering */
2144 em_supplist_searches
++;
2146 /* Prepare the lazy input completer. */
2147 ip2fo
.epoch
= VG_(get_ExeContext_epoch
)(err
->where
);
2148 ip2fo
.ips
= VG_(get_ExeContext_StackTrace
)(err
->where
);
2149 ip2fo
.n_ips
= VG_(get_ExeContext_n_ips
)(err
->where
);
2150 ip2fo
.n_ips_expanded
= 0;
2151 ip2fo
.n_expanded
= 0;
2152 ip2fo
.sz_offsets
= 0;
2153 ip2fo
.n_offsets_per_ip
= NULL
;
2154 ip2fo
.fun_offsets
= NULL
;
2155 ip2fo
.obj_offsets
= NULL
;
2157 ip2fo
.names_szB
= 0;
2158 ip2fo
.names_free
= 0;
2160 /* See if the error context matches any suppression. */
2161 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4)
2162 VG_(dmsg
)("errormgr matching begin\n");
2164 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
2166 if (supp_matches_error(su
, err
)
2167 && supp_matches_callers(&ip2fo
, su
)) {
2169 /* Inform the tool that err is suppressed by su. */
2171 (void)VG_TDICT_CALL(tool_update_extra_suppression_use
, err
, su
);
2172 /* No core errors need to update extra suppression info */
2173 /* Move this entry to the head of the list
2174 in the hope of making future searches cheaper. */
2176 vg_assert(su_prev
->next
== su
);
2177 su_prev
->next
= su
->next
;
2178 su
->next
= suppressions
;
2181 clearIPtoFunOrObjCompleter(su
, &ip2fo
);
2186 clearIPtoFunOrObjCompleter(NULL
, &ip2fo
);
2187 return NULL
; /* no matches */
2190 /* Show accumulated error-list and suppression-list search stats.
2192 void VG_(print_errormgr_stats
) ( void )
2195 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
2196 em_supplist_searches
, em_supplist_cmps
2199 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
2200 em_errlist_searches
, em_errlist_cmps
2204 /*--------------------------------------------------------------------*/
2206 /*--------------------------------------------------------------------*/