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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_threadstate.h" // For VG_N_THREADS
34 #include "pub_core_debuginfo.h"
35 #include "pub_core_debuglog.h"
36 #include "pub_core_errormgr.h"
37 #include "pub_core_execontext.h"
38 #include "pub_core_gdbserver.h"
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcassert.h"
41 #include "pub_core_libcfile.h"
42 #include "pub_core_libcprint.h"
43 #include "pub_core_libcproc.h" // For VG_(getpid)()
44 #include "pub_core_seqmatch.h"
45 #include "pub_core_mallocfree.h"
46 #include "pub_core_options.h"
47 #include "pub_core_stacktrace.h"
48 #include "pub_core_tooliface.h"
49 #include "pub_core_translate.h" // for VG_(translate)()
50 #include "pub_core_xarray.h" // VG_(xaprintf) et al
52 #define DEBUG_ERRORMGR 0 // set to 1 for heavyweight tracing
54 /*------------------------------------------------------------*/
56 /*------------------------------------------------------------*/
58 /* After this many different unsuppressed errors have been observed,
59 be more conservative about collecting new ones. */
60 #define M_COLLECT_ERRORS_SLOWLY_AFTER 100
62 /* After this many different unsuppressed errors have been observed,
63 stop collecting errors at all, and tell the user their program is
64 evidently a steaming pile of camel dung. */
65 #define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
67 /* After this many total errors have been observed, stop collecting
68 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
69 #define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
71 /* The list of error contexts found, both suppressed and unsuppressed.
72 Initially empty, and grows as errors are detected. */
73 static Error
* errors
= NULL
;
75 /* The list of suppression directives, as read from the specified
76 suppressions file. Note that the list gets rearranged as a result
77 of the searches done by is_suppressible_error(). */
78 static Supp
* suppressions
= NULL
;
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 ThreadId last_tid_printed
= 1;
101 /* Stats: number of searches of the error list initiated. */
102 static UWord em_errlist_searches
= 0;
104 /* Stats: number of comparisons done during error list
106 static UWord em_errlist_cmps
= 0;
108 /* Stats: number of searches of the suppression list initiated. */
109 static UWord em_supplist_searches
= 0;
111 /* Stats: number of comparisons done during suppression list
113 static UWord em_supplist_cmps
= 0;
115 /*------------------------------------------------------------*/
116 /*--- Error type ---*/
117 /*------------------------------------------------------------*/
119 /* Errors. Extensible (via the 'extra' field). Tools can use a normal
120 enum (with element values in the normal range (0..)) for 'ekind'.
121 Functions for getting/setting the tool-relevant fields are in
122 include/pub_tool_errormgr.h.
124 When errors are found and recorded with VG_(maybe_record_error)(), all
125 the tool must do is pass in the four parameters; core will
126 allocate/initialise the error record.
130 // Unique tag. This gives the error a unique identity (handle) by
131 // which it can be referred to afterwords. Currently only used for
134 // NULL if unsuppressed; or ptr to suppression record.
138 // The tool-specific part
139 ThreadId tid
; // Initialised by core
140 ExeContext
* where
; // Initialised by core
141 ErrorKind ekind
; // Used by ALL. Must be in the range (0..)
142 Addr addr
; // Used frequently
143 const HChar
* string
; // Used frequently
144 void* extra
; // For any tool-specific extras
148 ExeContext
* VG_(get_error_where
) ( const Error
* err
)
153 ErrorKind
VG_(get_error_kind
) ( const Error
* err
)
158 Addr
VG_(get_error_address
) ( const Error
* err
)
163 const HChar
* VG_(get_error_string
) ( const Error
* err
)
168 void* VG_(get_error_extra
) ( const Error
* err
)
173 UInt
VG_(get_n_errs_found
)( void )
178 UInt
VG_(get_n_errs_shown
)( void )
183 /*------------------------------------------------------------*/
184 /*--- Suppression type ---*/
185 /*------------------------------------------------------------*/
187 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools
188 * effectively extend it by defining their own enums in the (0..) range. */
191 // Nb: thread errors are a relic of the time when Valgrind's core
192 // could detect them. This example is left commented-out as an
193 // example should new core errors ever be added.
194 ThreadSupp
= -1, /* Matches ThreadErr */
198 /* Max number of callers for context in a suppression is
199 VG_DEEPEST_BACKTRACE. */
201 /* For each caller specified for a suppression, record the nature of
202 the caller name. Not of interest to tools. */
205 NoName
, /* Error case */
206 ObjName
, /* Name is of an shared object file. */
207 FunName
, /* Name is of a function. */
208 DotDotDot
/* Frame-level wildcard */
215 Bool name_is_simple_str
; /* True if name is a string without
216 '?' and '*' wildcard characters. */
217 HChar
* name
; /* NULL for NoName and DotDotDot */
221 /* Suppressions. Tools can get/set tool-relevant parts with functions
222 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
223 Tools can use a normal enum (with element values in the normal range
224 (0..)) for 'skind'. */
227 Int count
; // The number of times this error has been suppressed.
228 HChar
* sname
; // The name by which the suppression is referred to.
230 // Index in VG_(clo_suppressions) giving filename from which suppression
231 // was read, and the lineno in this file where sname was read.
232 Int clo_suppressions_i
;
235 // Length of 'callers'
237 // Array of callers, for matching stack traces. First one (name of fn
238 // where err occurs) is mandatory; rest are optional.
241 /* The tool-specific part */
242 SuppKind skind
; // What kind of suppression. Must use the range (0..).
243 HChar
* string
; // String -- use is optional. NULL by default.
244 void* extra
; // Anything else -- use is optional. NULL by default.
247 SuppKind
VG_(get_supp_kind
) ( const Supp
* su
)
252 HChar
* VG_(get_supp_string
) ( const Supp
* su
)
257 void* VG_(get_supp_extra
) ( const Supp
* su
)
263 void VG_(set_supp_kind
) ( Supp
* su
, SuppKind skind
)
268 void VG_(set_supp_string
) ( Supp
* su
, HChar
* string
)
273 void VG_(set_supp_extra
) ( Supp
* su
, void* extra
)
279 /*------------------------------------------------------------*/
280 /*--- Helper fns ---*/
281 /*------------------------------------------------------------*/
283 // Only show core errors if the tool wants to, we're not running with -q,
284 // and were not outputting XML.
285 Bool
VG_(showing_core_errors
)(void)
287 return VG_(needs
).core_errors
&& VG_(clo_verbosity
) >= 1 && !VG_(clo_xml
);
290 /* Compare errors, to detect duplicates.
292 static Bool
eq_Error ( VgRes res
, const Error
* e1
, const Error
* e2
)
294 if (e1
->ekind
!= e2
->ekind
)
296 if (!VG_(eq_ExeContext
)(res
, e1
->where
, e2
->where
))
300 //(example code, see comment on CoreSuppKind above)
302 // vg_assert(VG_(needs).core_errors);
303 // return <something>
305 if (VG_(needs
).tool_errors
) {
306 return VG_TDICT_CALL(tool_eq_Error
, res
, e1
, e2
);
308 VG_(printf
)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
309 "probably needs to be set.\n",
311 VG_(core_panic
)("unhandled error type");
317 /* Helper functions for suppression generation: print a single line of
318 a suppression pseudo-stack-trace, either in XML or text mode. It's
319 important that the behaviour of these two functions exactly
322 #define ERRTXT_LEN 4096
324 static void printSuppForIp_XML(UInt n
, DiEpoch ep
, Addr ip
, void* uu_opaque
)
327 InlIPCursor
* iipc
= VG_(new_IIPC
)(ep
, ip
);
329 if ( VG_(get_fnname_no_cxx_demangle
) (ep
, ip
, &buf
, iipc
) ) {
330 VG_(printf_xml
)(" <sframe> <fun>%pS</fun> </sframe>\n", buf
);
332 if ( VG_(get_objname
)(ep
, ip
, &buf
) ) {
333 VG_(printf_xml
)(" <sframe> <obj>%pS</obj> </sframe>\n", buf
);
335 VG_(printf_xml
)(" <sframe> <obj>*</obj> </sframe>\n");
337 } while (VG_(next_IIPC
)(iipc
));
338 VG_(delete_IIPC
)(iipc
);
341 static void printSuppForIp_nonXML(UInt n
, DiEpoch ep
, Addr ip
, void* textV
)
344 XArray
* /* of HChar */ text
= (XArray
*)textV
;
345 InlIPCursor
* iipc
= VG_(new_IIPC
)(ep
, ip
);
347 if ( VG_(get_fnname_no_cxx_demangle
) (ep
, ip
, &buf
, iipc
) ) {
348 VG_(xaprintf
)(text
, " fun:%s\n", buf
);
350 if ( VG_(get_objname
)(ep
, ip
, &buf
) ) {
351 VG_(xaprintf
)(text
, " obj:%s\n", buf
);
353 VG_(xaprintf
)(text
, " obj:*\n");
355 } while (VG_(next_IIPC
)(iipc
));
356 VG_(delete_IIPC
)(iipc
);
359 /* Generate a suppression for an error, either in text or XML mode.
361 static void gen_suppression(const Error
* err
)
365 XArray
* /* HChar */ text
;
367 const HChar
* dummy_name
= "insert_a_suppression_name_here";
371 ec
= VG_(get_error_where
)(err
);
374 name
= VG_TDICT_CALL(tool_get_error_name
, err
);
376 VG_(umsg
)("(%s does not allow error to be suppressed)\n",
381 /* In XML mode, we also need to print the plain text version of the
382 suppresion in a CDATA section. What that really means is, we
383 need to generate the plaintext version both in XML and text
384 mode. So generate it into TEXT. */
385 text
= VG_(newXA
)( VG_(malloc
), "errormgr.gen_suppression.1",
386 VG_(free
), sizeof(HChar
) );
388 /* Ok. Generate the plain text version into TEXT. */
389 VG_(xaprintf
)(text
, "{\n");
390 VG_(xaprintf
)(text
, " <%s>\n", dummy_name
);
391 VG_(xaprintf
)(text
, " %s:%s\n", VG_(details
).name
, name
);
399 xtra
= VG_(realloc
)("errormgr.gen_suppression.2", xtra
,xtra_size
);
400 num_written
= VG_TDICT_CALL(tool_get_extra_suppression_info
,
401 err
, xtra
, xtra_size
);
402 } while (num_written
== xtra_size
); // resize buffer and retry
404 // Ensure buffer is properly terminated
405 vg_assert(xtra
[num_written
] == '\0');
408 VG_(xaprintf
)(text
, " %s\n", xtra
);
410 // Print stack trace elements
411 UInt n_ips
= VG_(get_ExeContext_n_ips
)(ec
);
412 vg_assert(n_ips
> 0);
413 vg_assert(n_ips
<= VG_DEEPEST_BACKTRACE
);
414 VG_(apply_StackTrace
)(printSuppForIp_nonXML
,
415 text
, VG_(get_ExeContext_epoch
)(ec
),
416 VG_(get_ExeContext_StackTrace
)(ec
),
419 VG_(xaprintf
)(text
, "}\n");
421 VG_(xaprintf
)(text
, "%c", (HChar
)0 );
422 // VG_(printf) of text
424 /* And now display it. */
425 if (! VG_(clo_xml
) ) {
428 VG_(printf
)("%s", (HChar
*) VG_(indexXA
)(text
, 0) );
432 /* Now we have to print the XML directly. No need to go to the
433 effort of stuffing it in an XArray, since we won't need it
435 VG_(printf_xml
)(" <suppression>\n");
436 VG_(printf_xml
)(" <sname>%s</sname>\n", dummy_name
);
438 " <skind>%pS:%pS</skind>\n", VG_(details
).name
, name
);
440 VG_(printf_xml
)(" <skaux>%pS</skaux>\n", xtra
);
442 // Print stack trace elements
443 VG_(apply_StackTrace
)(printSuppForIp_XML
,
444 NULL
, VG_(get_ExeContext_epoch
)(ec
),
445 VG_(get_ExeContext_StackTrace
)(ec
),
446 VG_(get_ExeContext_n_ips
)(ec
));
448 // And now the cdata bit
449 // XXX FIXME! properly handle the case where the raw text
450 // itself contains "]]>", as specified in Protocol 4.
451 VG_(printf_xml
)(" <rawtext>\n");
452 VG_(printf_xml
)("<![CDATA[\n");
453 VG_(printf_xml
)("%s", (HChar
*) VG_(indexXA
)(text
, 0) );
454 VG_(printf_xml
)("]]>\n");
455 VG_(printf_xml
)(" </rawtext>\n");
456 VG_(printf_xml
)(" </suppression>\n");
465 /* Figure out if we want to perform a given action for this error,
466 possibly by asking the user.
468 Bool
VG_(is_action_requested
) ( const HChar
* action
, Bool
* clo
)
473 /* First off, we shouldn't be asking the user anything if
474 we're in XML mode. */
476 return False
; /* That's a Nein, oder Nay as they say down here in B-W */
486 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
487 VG_(getpid
)(), action
490 res
= VG_(read
)(VG_(clo_input_fd
), &ch
, 1);
491 if (res
!= 1) goto ioerror
;
493 if (ch
== '\n') return False
;
494 if (ch
!= 'N' && ch
!= 'n' && ch
!= 'Y' && ch
!= 'y'
495 && ch
!= 'C' && ch
!= 'c') goto again
;
497 res
= VG_(read
)(VG_(clo_input_fd
), &ch2
, 1);
498 if (res
!= 1) goto ioerror
;
499 if (ch2
!= '\n') goto again
;
501 /* No, don't want to do action. */
502 if (ch
== 'n' || ch
== 'N') return False
;
503 /* Yes, want to do action. */
504 if (ch
== 'y' || ch
== 'Y') return True
;
505 /* No, don't want to do action, and don't ask again either. */
506 vg_assert(ch
== 'c' || ch
== 'C');
514 /* Do actions on error, that is, immediately after an error is printed.
516 * possibly, call the GDB server
517 * possibly, generate a suppression.
520 void do_actions_on_error(const Error
* err
, Bool allow_db_attach
)
522 Bool still_noisy
= True
;
524 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
525 if (VG_(clo_vgdb
) != Vg_VgdbNo
527 && VG_(dyn_vgdb_error
) <= n_errs_shown
) {
528 VG_(umsg
)("(action on error) vgdb me ... \n");
529 VG_(gdbserver
)( err
->tid
);
530 VG_(umsg
)("Continuing ...\n");
533 /* Or maybe we want to generate the error's suppression? */
534 if (VG_(clo_gen_suppressions
) == 2
535 || (VG_(clo_gen_suppressions
) == 1
536 && VG_(is_action_requested
)( "Print suppression", &still_noisy
))
538 gen_suppression(err
);
540 if (VG_(clo_gen_suppressions
) == 1 && !still_noisy
)
541 VG_(clo_gen_suppressions
) = 0;
543 if (VG_(clo_exit_on_first_error
)) {
545 VG_(printf_xml
)("</valgrindoutput>\n");
547 VG_(umsg
)("Exit program on first error (--exit-on-first-error=yes)\n");
548 VG_(client_exit
)( VG_(clo_error_exitcode
) );
553 /* Prints an error. Not entirely simple because of the differences
554 between XML and text mode output.
558 * calls the tool's pre-show method, so the tool can create any
559 preamble ahead of the message, if it wants.
561 * prints the opening tag, and the <unique> and <tid> fields
563 * prints the tool-specific parts of the message
565 * if suppression generation is required, a suppression
571 * calls the tool's pre-show method, so the tool can create any
572 preamble ahead of the message, if it wants.
574 * prints the tool-specific parts of the message
578 * calls do_actions_on_error. This optionally does a gdbserver call
579 and optionally prints a suppression; both of these may require user input.
581 static void pp_Error ( const Error
* err
, Bool allow_db_attach
, Bool xml
)
583 /* If this fails, you probably specified your tool's method
584 dictionary incorrectly. */
585 vg_assert(VG_(needs
).tool_errors
);
589 /* Ensure that suppression generation is either completely
590 enabled or completely disabled; either way, we won't require
591 any user input. m_main.process_cmd_line_options should
592 ensure the asserted condition holds. */
593 vg_assert( VG_(clo_gen_suppressions
) == 0 /* disabled */
594 || VG_(clo_gen_suppressions
) == 2 /* for all errors */ );
596 /* Pre-show it to the tool */
597 VG_TDICT_CALL( tool_before_pp_Error
, err
);
599 /* standard preamble */
600 VG_(printf_xml
)("<error>\n");
601 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
602 VG_(printf_xml
)(" <tid>%u</tid>\n", err
->tid
);
603 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
604 if (tst
->thread_name
) {
605 VG_(printf_xml
)(" <threadname>%s</threadname>\n", tst
->thread_name
);
608 /* actually print it */
609 VG_TDICT_CALL( tool_pp_Error
, err
);
611 if (VG_(clo_gen_suppressions
) > 0)
612 gen_suppression(err
);
615 VG_(printf_xml
)("</error>\n");
616 VG_(printf_xml
)("\n");
620 if (VG_(clo_error_markers
)[0])
621 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[0]);
622 VG_TDICT_CALL( tool_before_pp_Error
, err
);
624 if (VG_(tdict
).tool_show_ThreadIDs_for_errors
625 && err
->tid
> 0 && err
->tid
!= last_tid_printed
) {
626 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
627 if (tst
->thread_name
) {
628 VG_(umsg
)("Thread %u %s:\n", err
->tid
, tst
->thread_name
);
630 VG_(umsg
)("Thread %u:\n", err
->tid
);
632 last_tid_printed
= err
->tid
;
635 VG_TDICT_CALL( tool_pp_Error
, err
);
637 if (VG_(clo_error_markers
)[1])
638 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[1]);
642 do_actions_on_error(err
, allow_db_attach
);
646 /* Construct an error */
648 void construct_error ( Error
* err
, ThreadId tid
, ErrorKind ekind
, Addr a
,
649 const HChar
* s
, void* extra
, ExeContext
* where
)
651 /* DO NOT MAKE unique_counter NON-STATIC */
652 static UInt unique_counter
= 0;
654 vg_assert(tid
< VG_N_THREADS
);
656 /* Core-only parts */
657 err
->unique
= unique_counter
++;
663 err
->where
= VG_(record_ExeContext
)( tid
, 0 );
667 /* Tool-relevant parts */
674 vg_assert( tid
< VG_N_THREADS
);
679 /* Top-level entry point to the error management subsystem.
680 All detected errors are notified here; this routine decides if/when the
681 user should see the error. */
682 void VG_(maybe_record_error
) ( ThreadId tid
,
683 ErrorKind ekind
, Addr a
,
684 const HChar
* s
, void* extra
)
690 VgRes exe_res
= Vg_MedRes
;
691 static Bool stopping_message
= False
;
692 static Bool slowdown_message
= False
;
694 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
695 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
696 have been found, just refuse to collect any more. This stops
697 the burden of the error-management system becoming excessive in
698 extremely buggy programs, although it does make it pretty
699 pointless to continue the Valgrind run after this point. */
700 if (VG_(clo_error_limit
)
701 && (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
702 || n_errs_found
>= M_COLLECT_NO_ERRORS_AFTER_FOUND
)
704 if (!stopping_message
) {
707 if (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
) {
709 "More than %d different errors detected. "
710 "I'm not reporting any more.\n",
711 M_COLLECT_NO_ERRORS_AFTER_SHOWN
);
714 "More than %d total errors detected. "
715 "I'm not reporting any more.\n",
716 M_COLLECT_NO_ERRORS_AFTER_FOUND
);
719 VG_(umsg
)("Final error counts will be inaccurate. "
720 "Go fix your program!\n");
721 VG_(umsg
)("Rerun with --error-limit=no to disable "
722 "this cutoff. Note\n");
723 VG_(umsg
)("that errors may occur in your program without "
724 "prior warning from\n");
725 VG_(umsg
)("Valgrind, because errors are no longer "
726 "being displayed.\n");
728 stopping_message
= True
;
733 /* Ignore it if error acquisition is disabled for this thread. */
734 { ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
735 if (tst
->err_disablement_level
> 0)
739 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
740 been found, be much more conservative about collecting new
742 if (n_errs_shown
>= M_COLLECT_ERRORS_SLOWLY_AFTER
745 if (!slowdown_message
) {
747 VG_(umsg
)("More than %d errors detected. Subsequent errors\n",
748 M_COLLECT_ERRORS_SLOWLY_AFTER
);
749 VG_(umsg
)("will still be recorded, but in less "
750 "detail than before.\n");
751 slowdown_message
= True
;
755 /* Build ourselves the error */
756 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, NULL
);
758 /* First, see if we've got an error record matching this one. */
759 em_errlist_searches
++;
764 if (eq_Error(exe_res
, p
, &err
)) {
767 if (p
->supp
!= NULL
) {
768 /* Deal correctly with suppressed errors. */
775 /* Move p to the front of the list so that future searches
776 for it are faster. It also allows to print the last
777 error (see VG_(show_last_error). */
778 if (p_prev
!= NULL
) {
779 vg_assert(p_prev
->next
== p
);
780 p_prev
->next
= p
->next
;
791 /* Didn't see it. Copy and add. */
793 /* OK, we're really going to collect it. The context is on the stack and
794 will disappear shortly, so we must copy it. First do the main
797 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
798 is for when there are more details to fill in which take time to work
799 out but don't affect our earlier decision to include the error -- by
800 postponing those details until now, we avoid the extra work in the
801 case where we ignore the error. Ugly.
803 Then, if there is an 'extra' part, copy it too, using the size that
804 VG_(tdict).tool_update_extra returned. Also allow for people using
805 the void* extra field for a scalar value like an integer.
809 p
= VG_(malloc
)("errormgr.mre.1", sizeof(Error
));
814 //(example code, see comment on CoreSuppKind above)
816 // vg_assert(VG_(needs).core_errors);
817 // extra_size = <something>
820 vg_assert(VG_(needs
).tool_errors
);
821 extra_size
= VG_TDICT_CALL(tool_update_extra
, p
);
825 /* copy the error string, if there is one.
826 note: if we would have many errors with big strings, using a
827 DedupPoolAlloc for these strings will avoid duplicating
828 such string in each error using it. */
829 if (NULL
!= p
->string
) {
830 p
->string
= VG_(strdup
)("errormgr.mre.2", p
->string
);
833 /* copy block pointed to by 'extra', if there is one */
834 if (NULL
!= p
->extra
&& 0 != extra_size
) {
835 void* new_extra
= VG_(malloc
)("errormgr.mre.3", extra_size
);
836 VG_(memcpy
)(new_extra
, p
->extra
, extra_size
);
837 p
->extra
= new_extra
;
841 p
->supp
= is_suppressible_error(&err
);
843 if (p
->supp
== NULL
) {
848 /* Actually show the error; more complex than you might think. */
849 pp_Error( p
, /*allow_db_attach*/True
, VG_(clo_xml
) );
857 /* Second top-level entry point to the error management subsystem, for
858 errors that the tool wants to report immediately, eg. because they're
859 guaranteed to only happen once. This avoids all the recording and
860 comparing stuff. But they can be suppressed; returns True if it is
861 suppressed. Bool 'print_error' dictates whether to print the error.
862 Bool 'count_error' dictates whether to count the error in n_errs_found.
864 Bool
VG_(unique_error
) ( ThreadId tid
, ErrorKind ekind
, Addr a
, const HChar
* s
,
865 void* extra
, ExeContext
* where
, Bool print_error
,
866 Bool allow_db_attach
, Bool count_error
)
871 /* Ignore it if error acquisition is disabled for this thread. */
872 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
873 if (tst
->err_disablement_level
> 0)
874 return False
; /* ignored, not suppressed */
876 /* Build ourselves the error */
877 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, where
);
879 /* Unless it's suppressed, we're going to show it. Don't need to make
880 a copy, because it's only temporary anyway.
882 Then update the 'extra' part with VG_(tdict).tool_update_extra),
883 because that can have an affect on whether it's suppressed. Ignore
884 the size return value of VG_(tdict).tool_update_extra, because we're
885 not copying 'extra'. Similarly, 's' is also not copied. */
886 (void)VG_TDICT_CALL(tool_update_extra
, &err
);
888 su
= is_suppressible_error(&err
);
898 /* Actually show the error; more complex than you might think. */
899 pp_Error(&err
, allow_db_attach
, VG_(clo_xml
));
914 /*------------------------------------------------------------*/
915 /*--- Exported fns ---*/
916 /*------------------------------------------------------------*/
918 /* Show the used suppressions. Returns False if no suppression
920 static Bool
show_used_suppressions ( void )
926 VG_(printf_xml
)("<suppcounts>\n");
929 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
933 VG_(printf_xml
)( " <pair>\n"
934 " <count>%d</count>\n"
935 " <name>%pS</name>\n"
937 su
->count
, su
->sname
);
942 // blank line before the first shown suppression, if any
948 xtra
= VG_(realloc
)("errormgr.sus.1", xtra
, xtra_size
);
949 num_written
= VG_TDICT_CALL(tool_print_extra_suppression_use
,
950 su
, xtra
, xtra_size
);
951 } while (num_written
== xtra_size
); // resize buffer and retry
953 // Ensure buffer is properly terminated
954 vg_assert(xtra
[num_written
] == '\0');
956 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
957 su
->clo_suppressions_i
);
958 VG_(dmsg
)("used_suppression: %6d %s %s:%d%s%s\n", su
->count
, su
->sname
,
961 num_written
? " " : "", xtra
);
968 VG_(printf_xml
)("</suppcounts>\n");
973 /* Show all the errors that occurred, and possibly also the
974 suppressions used. */
975 void VG_(show_all_errors
) ( Int verbosity
, Bool xml
)
984 /* If we're printing XML, just show the suppressions and stop. */
986 (void)show_used_suppressions();
990 /* We only get here if not printing XML. */
991 VG_(umsg
)("ERROR SUMMARY: "
992 "%u errors from %u contexts (suppressed: %u from %u)\n",
993 n_errs_found
, n_err_contexts
,
994 n_errs_suppressed
, n_supp_contexts
);
999 // We do the following only at -v or above, and only in non-XML
1002 /* Print the contexts in order of increasing error count.
1003 Once an error is shown, we add a huge value to its count to filter it
1005 After having shown all errors, we reset count to the original value. */
1006 for (i
= 0; i
< n_err_contexts
; i
++) {
1007 n_min
= (1 << 30) - 1;
1009 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1010 if (p
->supp
!= NULL
) continue;
1011 if (p
->count
< n_min
) {
1016 // XXX: this isn't right. See bug 203651.
1017 if (p_min
== NULL
) continue; //VG_(core_panic)("show_all_errors()");
1020 VG_(umsg
)("%d errors in context %d of %u:\n",
1021 p_min
->count
, i
+1, n_err_contexts
);
1022 pp_Error( p_min
, False
/*allow_db_attach*/, False
/* xml */ );
1024 // We're not printing XML -- we'd have exited above if so.
1027 if ((i
+1 == VG_(clo_dump_error
))) {
1028 StackTrace ips
= VG_(get_ExeContext_StackTrace
)(p_min
->where
);
1029 VG_(translate
) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1030 ips
[0], /*debugging*/True
, 0xFE/*verbosity*/,
1032 /*allow redir?*/True
);
1035 p_min
->count
= p_min
->count
+ (1 << 30);
1038 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1039 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1040 if (p
->count
>= (1 << 30))
1041 p
->count
= p
->count
- (1 << 30);
1045 any_supp
= show_used_suppressions();
1049 // reprint this, so users don't have to scroll way up to find
1050 // the first printing
1051 VG_(umsg
)("ERROR SUMMARY: "
1052 "%u errors from %u contexts (suppressed: %u from %u)\n",
1053 n_errs_found
, n_err_contexts
, n_errs_suppressed
,
1057 void VG_(show_last_error
) ( void )
1059 if (n_err_contexts
== 0) {
1060 VG_(umsg
)("No errors yet\n");
1064 pp_Error( errors
, False
/*allow_db_attach*/, False
/*xml*/ );
1068 /* Show occurrence counts of all errors, in XML form. */
1069 void VG_(show_error_counts_as_XML
) ( void )
1072 VG_(printf_xml
)("<errorcounts>\n");
1073 for (err
= errors
; err
!= NULL
; err
= err
->next
) {
1074 if (err
->supp
!= NULL
)
1076 if (err
->count
<= 0)
1078 VG_(printf_xml
)(" <pair>\n");
1079 VG_(printf_xml
)(" <count>%d</count>\n", err
->count
);
1080 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
1081 VG_(printf_xml
)(" </pair>\n");
1083 VG_(printf_xml
)("</errorcounts>\n");
1084 VG_(printf_xml
)("\n");
1088 /*------------------------------------------------------------*/
1089 /*--- Suppression parsing ---*/
1090 /*------------------------------------------------------------*/
1092 /* Get the next char from fd into *out_buf. Returns 1 if success,
1093 0 if eof or < 0 if error. */
1095 static Int
get_char ( Int fd
, HChar
* out_buf
)
1098 static HChar buf
[256];
1099 static Int buf_size
= 0;
1100 static Int buf_used
= 0;
1101 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1102 vg_assert(buf_used
>= 0 && buf_used
<= buf_size
);
1103 if (buf_used
== buf_size
) {
1104 r
= VG_(read
)(fd
, buf
, sizeof buf
);
1105 if (r
< 0) return r
; /* read failed */
1106 vg_assert(r
>= 0 && r
<= sizeof buf
);
1112 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1113 vg_assert(buf_used
>= 0 && buf_used
< buf_size
);
1114 *out_buf
= buf
[buf_used
];
1119 // Get a non blank non comment line.
1120 // Returns True if eof.
1121 static Bool
get_nbnc_line ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1123 HChar
* buf
= *bufpp
;
1124 SizeT nBuf
= *nBufp
;
1128 vg_assert(lineno
); // lineno needed to correctly track line numbers.
1132 /* First, read until a non-blank char appears. */
1134 n
= get_char(fd
, &ch
);
1135 if (n
== 1 && !VG_(isspace
)(ch
)) break;
1136 if (n
== 1 && ch
== '\n')
1138 if (n
<= 0) return True
;
1141 /* Now, read the line into buf. */
1143 buf
[i
++] = ch
; buf
[i
] = 0;
1145 n
= get_char(fd
, &ch
);
1146 if (n
<= 0) return False
; /* the next call will return True */
1149 if (ch
== '\n') break;
1150 if (i
> 0 && i
== nBuf
-1) {
1151 *nBufp
= nBuf
= nBuf
* 2;
1152 #define RIDICULOUS 100000
1153 vg_assert2(nBuf
< RIDICULOUS
, // Just a sanity check, really.
1154 "VG_(get_line): line longer than %d chars, aborting\n",
1156 *bufpp
= buf
= VG_(realloc
)("errormgr.get_line.1", buf
, nBuf
);
1158 buf
[i
++] = ch
; buf
[i
] = 0;
1160 while (i
> 1 && VG_(isspace
)(buf
[i
-1])) {
1164 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1165 /* Ok, we have a line. If a non-comment line, return.
1166 If a comment line, start all over again. */
1167 if (buf
[0] != '#') return False
;
1171 // True if buf starts with fun: or obj: or is ...
1172 static Bool
is_location_line (const HChar
* buf
)
1174 return VG_(strncmp
)(buf
, "fun:", 4) == 0
1175 || VG_(strncmp
)(buf
, "obj:", 4) == 0
1176 || VG_(strcmp
)(buf
, "...") == 0;
1179 Bool
VG_(get_line
) ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1181 Bool eof
= get_nbnc_line (fd
, bufpp
, nBufp
, lineno
);
1186 if (is_location_line(*bufpp
))
1187 return True
; // Not a extra suppr line
1189 return False
; // A suppression extra line
1192 /* True if s contains no wildcard (?, *) characters. */
1193 static Bool
is_simple_str (const HChar
*s
)
1196 if (*s
== '?' || *s
== '*')
1203 /* buf contains the raw name of a caller, supposedly either
1204 fun:some_function_name or
1205 obj:some_object_name or
1207 Set p->ty and p->name accordingly.
1208 p->name is allocated and set to the string
1209 after the descriptor (fun: or obj:) part.
1210 Returns False if failed.
1212 static Bool
setLocationTy ( SuppLoc
* p
, const HChar
*buf
)
1214 if (VG_(strncmp
)(buf
, "fun:", 4) == 0) {
1215 p
->name
= VG_(strdup
)("errormgr.sLTy.1", buf
+4);
1216 p
->name_is_simple_str
= is_simple_str (p
->name
);
1220 if (VG_(strncmp
)(buf
, "obj:", 4) == 0) {
1221 p
->name
= VG_(strdup
)("errormgr.sLTy.2", buf
+4);
1222 p
->name_is_simple_str
= is_simple_str (p
->name
);
1226 if (VG_(strcmp
)(buf
, "...") == 0) {
1228 p
->name_is_simple_str
= False
;
1232 VG_(printf
)("location should be \"...\", or should start "
1233 "with \"fun:\" or \"obj:\"\n");
1238 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1239 static Bool
tool_name_present(const HChar
*name
, const HChar
*names
)
1242 HChar
*s
= NULL
; /* Shut gcc up */
1243 Int len
= VG_(strlen
)(name
);
1245 found
= (NULL
!= (s
= VG_(strstr
)(names
, name
)) &&
1246 (s
== names
|| *(s
-1) == ',') &&
1247 (*(s
+len
) == ',' || *(s
+len
) == '\0')
1253 /* Read suppressions from the file specified in
1254 VG_(clo_suppressions)[clo_suppressions_i]
1255 and place them in the suppressions list. If there's any difficulty
1256 doing this, just give up -- there's no point in trying to recover.
1258 static void load_one_suppressions_file ( Int clo_suppressions_i
)
1260 const HChar
* filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1261 clo_suppressions_i
);
1263 Int fd
, i
, j
, lineno
= 0;
1264 Bool got_a_location_line_read_by_tool
;
1267 HChar
* buf
= VG_(malloc
)("errormgr.losf.1", nBuf
);
1270 const HChar
* err_str
= NULL
;
1271 SuppLoc tmp_callers
[VG_DEEPEST_BACKTRACE
];
1273 // Check it's not a directory.
1274 if (VG_(is_dir
)( filename
)) {
1276 VG_(printf_xml
)("</valgrindoutput>\n");
1277 VG_(umsg
)("FATAL: suppressions file \"%s\" is a directory\n", filename
);
1281 // Open the suppression file.
1282 sres
= VG_(open
)( filename
, VKI_O_RDONLY
, 0 );
1283 if (sr_isError(sres
)) {
1285 VG_(printf_xml
)("</valgrindoutput>\n");
1286 VG_(umsg
)("FATAL: can't open suppressions file \"%s\"\n", filename
);
1291 # define BOMB(S) { err_str = S; goto syntax_error; }
1294 /* Assign and initialise the two suppression halves (core and tool) */
1296 supp
= VG_(malloc
)("errormgr.losf.1", sizeof(Supp
));
1299 // Initialise temporary reading-in buffer.
1300 for (i
= 0; i
< VG_DEEPEST_BACKTRACE
; i
++) {
1301 tmp_callers
[i
].ty
= NoName
;
1302 tmp_callers
[i
].name_is_simple_str
= False
;
1303 tmp_callers
[i
].name
= NULL
;
1306 supp
->string
= supp
->extra
= NULL
;
1308 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1314 if (!VG_STREQ(buf
, "{")) BOMB("expected '{' or end-of-file");
1316 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1318 if (eof
|| VG_STREQ(buf
, "}")) BOMB("unexpected '}'");
1320 supp
->sname
= VG_(strdup
)("errormgr.losf.2", buf
);
1321 supp
->clo_suppressions_i
= clo_suppressions_i
;
1322 supp
->sname_lineno
= lineno
;
1324 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1326 if (eof
) BOMB("unexpected end-of-file (expecting tool:suppr)");
1328 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1331 if (buf
[i
] == ':') break;
1332 if (buf
[i
] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1335 buf
[i
] = '\0'; /* Replace ':', splitting into two strings */
1337 tool_names
= & buf
[0];
1338 supp_name
= & buf
[i
+1];
1340 if (VG_(needs
).core_errors
&& tool_name_present("core", tool_names
))
1342 // A core suppression
1343 //(example code, see comment on CoreSuppKind above)
1344 //if (VG_STREQ(supp_name, "Thread"))
1345 // supp->skind = ThreadSupp;
1347 BOMB("unknown core suppression type");
1349 else if (VG_(needs
).tool_errors
&&
1350 tool_name_present(VG_(details
).name
, tool_names
))
1352 // A tool suppression
1353 if (VG_TDICT_CALL(tool_recognised_suppression
, supp_name
, supp
)) {
1354 /* Do nothing, function fills in supp->skind */
1356 BOMB("unknown tool suppression type");
1360 // Ignore rest of suppression
1362 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1363 if (eof
) BOMB("unexpected end-of-file (when skipping suppression)");
1364 if (VG_STREQ(buf
, "}"))
1367 VG_(free
)(supp
->sname
);
1373 // tool_read_extra_suppression_info might read lines
1374 // from fd till a location line.
1375 if (VG_(needs
).tool_errors
&&
1376 !VG_TDICT_CALL(tool_read_extra_suppression_info
,
1377 fd
, &buf
, &nBuf
, &lineno
, supp
))
1379 BOMB("bad or missing extra suppression info");
1382 got_a_location_line_read_by_tool
= buf
[0] != 0 && is_location_line(buf
);
1384 /* the main frame-descriptor reading loop */
1387 if (got_a_location_line_read_by_tool
) {
1388 got_a_location_line_read_by_tool
= False
;
1391 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1394 BOMB("unexpected end-of-file (when reading stack trace)");
1395 if (VG_STREQ(buf
, "}")) {
1399 BOMB("missing stack trace");
1402 if (i
== VG_DEEPEST_BACKTRACE
)
1403 BOMB("too many callers in stack trace");
1404 if (i
> 0 && i
>= VG_(clo_backtrace_size
))
1406 if (!setLocationTy(&(tmp_callers
[i
]), buf
))
1407 BOMB("location should be \"...\", or should start "
1408 "with \"fun:\" or \"obj:\"");
1412 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1413 // lines and grab the '}'.
1414 if (!VG_STREQ(buf
, "}")) {
1416 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1417 } while (!eof
&& !VG_STREQ(buf
, "}"));
1420 // Reject entries which are entirely composed of frame
1422 vg_assert(i
> 0); // guaranteed by frame-descriptor reading loop
1423 for (j
= 0; j
< i
; j
++) {
1424 if (tmp_callers
[j
].ty
== FunName
|| tmp_callers
[j
].ty
== ObjName
)
1426 vg_assert(tmp_callers
[j
].ty
== DotDotDot
);
1428 vg_assert(j
>= 0 && j
<= i
);
1430 // we didn't find any non-"..." entries
1431 BOMB("suppression must contain at least one location "
1432 "line which is not \"...\"");
1435 // Copy tmp_callers[] into supp->callers[]
1436 supp
->n_callers
= i
;
1437 supp
->callers
= VG_(malloc
)("errormgr.losf.4", i
* sizeof(SuppLoc
));
1438 for (i
= 0; i
< supp
->n_callers
; i
++) {
1439 supp
->callers
[i
] = tmp_callers
[i
];
1442 supp
->next
= suppressions
;
1443 suppressions
= supp
;
1451 VG_(printf_xml
)("</valgrindoutput>\n");
1452 VG_(umsg
)("FATAL: in suppressions file \"%s\" near line %d:\n",
1454 VG_(umsg
)(" %s\n", err_str
);
1457 VG_(umsg
)("exiting now.\n");
1464 void VG_(load_suppressions
) ( void )
1467 suppressions
= NULL
;
1468 for (i
= 0; i
< VG_(sizeXA
)(VG_(clo_suppressions
)); i
++) {
1469 if (VG_(clo_verbosity
) > 1) {
1470 VG_(dmsg
)("Reading suppressions file: %s\n",
1471 *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
), i
));
1473 load_one_suppressions_file( i
);
1478 /*------------------------------------------------------------*/
1479 /*--- Matching errors to suppressions ---*/
1480 /*------------------------------------------------------------*/
1482 /* Parameterising functions for the use of VG_(generic_match) in
1483 suppression-vs-error matching. The suppression frames (SuppLoc)
1484 play the role of 'pattern'-element, and the error frames (IPs,
1485 hence simply Addrs) play the role of 'input'. In short then, we're
1486 matching a sequence of Addrs against a pattern composed of a
1487 sequence of SuppLocs.
1489 static Bool
supploc_IsStar ( const void* supplocV
)
1491 const SuppLoc
* supploc
= supplocV
;
1492 return supploc
->ty
== DotDotDot
;
1495 static Bool
supploc_IsQuery ( const void* supplocV
)
1497 return False
; /* there's no '?' equivalent in the supp syntax */
1500 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1501 needed to match an error with the suppression patterns.
1502 The matching between an IP and a suppression pattern is done either
1503 with the IP function name or with the IP object name.
1504 First time the fun or obj name is needed for an IP member
1505 of a stack trace, it will be computed and stored in names.
1506 Also, if the IP corresponds to one or more inlined function calls,
1507 the inlined function names are expanded.
1508 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1509 allocations and the nr of debuginfo search. */
1512 DiEpoch epoch
; // used to interpret .ips
1513 StackTrace ips
; // stack trace we are lazily completing.
1514 UWord n_ips
; // nr of elements in ips.
1516 // VG_(generic_match) calls haveInputInpC to check
1517 // for the presence of an input element identified by ixInput
1518 // (i.e. a number that identifies the ixInput element of the
1519 // input sequence). It calls supp_pattEQinp to match this input
1520 // element with a pattern.
1521 // When inlining info is used to provide inlined function calls
1522 // in stacktraces, one IP in ips can be expanded in several
1523 // function names. So, each time input (or presence of input)
1524 // is requested by VG_(generic_match), we will expand
1525 // more IP of ips till we have expanded enough to reach the
1526 // input element requested (or we cannot expand anymore).
1528 UWord n_ips_expanded
;
1529 // n_ips_expanded maintains the nr of elements in ips that we have
1530 // already expanded.
1532 // n_expanded maintains the nr of elements resulting from the expansion
1533 // of the n_ips_expanded IPs. Without inlined function calls,
1534 // n_expanded == n_ips_expanded. With inlining info,
1535 // n_expanded >= n_ips_expanded.
1537 Int
* n_offsets_per_ip
;
1538 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1539 // obj_offsets resulting of the expansion of ips[i].
1540 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1541 // This array allows to retrieve the position in ips corresponding to
1544 // size (in elements) of fun_offsets and obj_offsets.
1545 // (fun|obj)_offsets are reallocated if more space is needed
1550 // fun_offsets[ixInput] is the offset in names where the
1551 // function name for the ixInput element of the input sequence
1552 // can be found. As one IP of ips can be expanded in several
1553 // function calls due to inlined function calls, we can have more
1554 // elements in fun_offsets than in ips.
1555 // An offset -1 means the function name has not yet been computed.
1557 // Similarly, obj_offsets[ixInput] gives the offset for the
1558 // object name for ips[ixInput]
1559 // (-1 meaning object name not yet been computed).
1561 // All function names and object names will be concatenated
1562 // in names. names is reallocated on demand.
1564 Int names_szB
; // size of names.
1565 Int names_free
; // offset first free HChar in names.
1567 IPtoFunOrObjCompleter
;
1569 static void pp_ip2fo (const IPtoFunOrObjCompleter
* ip2fo
)
1574 VG_(printf
)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1575 ip2fo
->n_ips
, ip2fo
->n_ips_expanded
, ip2fo
->n_expanded
);
1576 for (i
= 0; i
< ip2fo
->n_ips_expanded
; i
++) {
1578 for (j
= 0; j
< i
; j
++)
1579 o
+= ip2fo
->n_offsets_per_ip
[j
];
1580 VG_(printf
)("ips %d 0x08%lx offset [%d,%d] ",
1582 o
, o
+ip2fo
->n_offsets_per_ip
[i
]-1);
1583 for (j
= 0; j
< ip2fo
->n_offsets_per_ip
[i
]; j
++) {
1584 VG_(printf
)("%sfun:%s obj:%s\n",
1586 ip2fo
->fun_offsets
[o
+j
] == -1 ?
1587 "<not expanded>" : &ip2fo
->names
[ip2fo
->fun_offsets
[o
+j
]],
1588 ip2fo
->obj_offsets
[o
+j
] == -1 ?
1589 "<not expanded>" : &ip2fo
->names
[ip2fo
->obj_offsets
[o
+j
]]);
1594 /* free the memory in ip2fo.
1595 At debuglog 4, su (or NULL) will be used to show the matching
1596 (or non matching) with ip2fo. */
1597 static void clearIPtoFunOrObjCompleter ( const Supp
*su
,
1598 IPtoFunOrObjCompleter
* ip2fo
)
1600 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4) {
1602 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1603 su
->clo_suppressions_i
);
1604 VG_(dmsg
)("errormgr matching end suppression %s %s:%d matched:\n",
1609 VG_(dmsg
)("errormgr matching end no suppression matched:\n");
1611 VG_(pp_StackTrace
) (ip2fo
->epoch
, ip2fo
->ips
, ip2fo
->n_ips
);
1614 if (ip2fo
->n_offsets_per_ip
) VG_(free
)(ip2fo
->n_offsets_per_ip
);
1615 if (ip2fo
->fun_offsets
) VG_(free
)(ip2fo
->fun_offsets
);
1616 if (ip2fo
->obj_offsets
) VG_(free
)(ip2fo
->obj_offsets
);
1617 if (ip2fo
->names
) VG_(free
)(ip2fo
->names
);
1620 /* Grow ip2fo->names to ensure we have NEEDED characters available
1621 in ip2fo->names and returns a pointer to the first free char. */
1622 static HChar
* grow_names(IPtoFunOrObjCompleter
* ip2fo
, SizeT needed
)
1624 if (ip2fo
->names_szB
1625 < ip2fo
->names_free
+ needed
) {
1626 if (needed
< ERRTXT_LEN
) needed
= ERRTXT_LEN
;
1629 = VG_(realloc
)("foc_names",
1631 ip2fo
->names_szB
+ needed
);
1632 ip2fo
->names_szB
+= needed
;
1634 return ip2fo
->names
+ ip2fo
->names_free
;
1637 /* foComplete returns the function name or object name for ixInput.
1638 If needFun, returns the function name for this input
1639 else returns the object name for this input.
1640 The function name or object name will be computed and added in
1641 names if not yet done. */
1642 static HChar
* foComplete(IPtoFunOrObjCompleter
* ip2fo
,
1643 Int ixInput
, Bool needFun
)
1645 vg_assert (ixInput
< ip2fo
->n_expanded
);
1646 vg_assert (VG_(clo_read_inline_info
) || ixInput
< ip2fo
->n_ips
);
1648 // ptr to the offset array for function offsets (if needFun)
1649 // or object offsets (if !needFun).
1652 offsets
= &ip2fo
->fun_offsets
;
1654 offsets
= &ip2fo
->obj_offsets
;
1656 // Complete Fun name or Obj name for IP if not yet done.
1657 if ((*offsets
)[ixInput
] == -1) {
1658 const HChar
* caller
;
1660 (*offsets
)[ixInput
] = ip2fo
->names_free
;
1661 if (DEBUG_ERRORMGR
) VG_(printf
)("marking %s ixInput %d offset %d\n",
1662 needFun
? "fun" : "obj",
1663 ixInput
, ip2fo
->names_free
);
1665 // With inline info, fn names must have been completed already.
1666 vg_assert (!VG_(clo_read_inline_info
));
1667 /* Get the function name into 'caller_name', or "???"
1669 // Nb: C++-mangled names are used in suppressions. Do, though,
1670 // Z-demangle them, since otherwise it's possible to wind
1671 // up comparing "malloc" in the suppression against
1672 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1673 // two of them need to be made to match.
1674 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->epoch
,
1675 ip2fo
->ips
[ixInput
],
1680 /* Get the object name into 'caller_name', or "???"
1683 UWord last_expand_pos_ips
= 0;
1686 /* First get the pos in ips corresponding to ixInput */
1687 for (pos_ips
= 0; pos_ips
< ip2fo
->n_expanded
; pos_ips
++) {
1688 last_expand_pos_ips
+= ip2fo
->n_offsets_per_ip
[pos_ips
];
1689 if (ixInput
< last_expand_pos_ips
)
1692 /* pos_ips is the position in ips corresponding to ixInput.
1693 last_expand_pos_ips is the last offset in fun/obj where
1694 ips[pos_ips] has been expanded. */
1696 if (!VG_(get_objname
)(ip2fo
->epoch
, ip2fo
->ips
[pos_ips
], &caller
))
1699 // Have all inlined calls pointing at this object name
1700 for (i
= last_expand_pos_ips
- ip2fo
->n_offsets_per_ip
[pos_ips
] + 1;
1701 i
< last_expand_pos_ips
;
1703 ip2fo
->obj_offsets
[i
] = ip2fo
->names_free
;
1705 VG_(printf
) (" set obj_offset %lu to %d\n",
1706 i
, ip2fo
->names_free
);
1709 SizeT caller_len
= VG_(strlen
)(caller
);
1710 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1711 VG_(strcpy
)(caller_name
, caller
);
1712 ip2fo
->names_free
+= caller_len
+ 1;
1713 if (DEBUG_ERRORMGR
) pp_ip2fo(ip2fo
);
1716 return ip2fo
->names
+ (*offsets
)[ixInput
];
1719 // Grow fun and obj _offsets arrays to have at least n_req elements.
1720 // Ensure n_offsets_per_ip is allocated.
1721 static void grow_offsets(IPtoFunOrObjCompleter
* ip2fo
, Int n_req
)
1725 // n_offsets_per_ip must always have the size of the ips array
1726 if (ip2fo
->n_offsets_per_ip
== NULL
) {
1727 ip2fo
->n_offsets_per_ip
= VG_(malloc
)("grow_offsets",
1728 ip2fo
->n_ips
* sizeof(Int
));
1729 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1730 ip2fo
->n_offsets_per_ip
[i
] = 0;
1733 if (ip2fo
->sz_offsets
>= n_req
)
1736 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1737 // elements and at least a few more elements than the current size.
1738 if (n_req
< ip2fo
->n_ips
)
1739 n_req
= ip2fo
->n_ips
;
1740 if (n_req
< ip2fo
->sz_offsets
+ 5)
1741 n_req
= ip2fo
->sz_offsets
+ 5;
1743 ip2fo
->fun_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->fun_offsets
,
1744 n_req
* sizeof(Int
));
1745 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1746 ip2fo
->fun_offsets
[i
] = -1;
1748 ip2fo
->obj_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->obj_offsets
,
1749 n_req
* sizeof(Int
));
1750 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1751 ip2fo
->obj_offsets
[i
] = -1;
1753 ip2fo
->sz_offsets
= n_req
;
1756 // Expands more IPs from ip2fo->ips.
1757 static void expandInput (IPtoFunOrObjCompleter
* ip2fo
, UWord ixInput
)
1759 while (ip2fo
->n_ips_expanded
< ip2fo
->n_ips
1760 && ip2fo
->n_expanded
<= ixInput
) {
1761 if (VG_(clo_read_inline_info
)) {
1762 // Expand one more IP in one or more calls.
1763 const Addr IP
= ip2fo
->ips
[ip2fo
->n_ips_expanded
];
1766 iipc
= VG_(new_IIPC
)(ip2fo
->epoch
, IP
);
1767 // The only thing we really need is the nr of inlined fn calls
1768 // corresponding to the IP we will expand.
1769 // However, computing this is mostly the same as finding
1770 // the function name. So, let's directly complete the function name.
1772 const HChar
*caller
;
1773 grow_offsets(ip2fo
, ip2fo
->n_expanded
+1);
1774 ip2fo
->fun_offsets
[ip2fo
->n_expanded
] = ip2fo
->names_free
;
1775 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->epoch
, IP
,
1779 SizeT caller_len
= VG_(strlen
)(caller
);
1780 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1781 VG_(strcpy
)(caller_name
, caller
);
1782 ip2fo
->names_free
+= caller_len
+ 1;
1783 ip2fo
->n_expanded
++;
1784 ip2fo
->n_offsets_per_ip
[ip2fo
->n_ips_expanded
]++;
1785 } while (VG_(next_IIPC
)(iipc
));
1786 ip2fo
->n_ips_expanded
++;
1787 VG_(delete_IIPC
) (iipc
);
1789 // Without inlined fn call info, expansion simply
1790 // consists in allocating enough elements in (fun|obj)_offsets.
1791 // The function or object names themselves will be completed
1794 grow_offsets(ip2fo
, ip2fo
->n_ips
);
1795 ip2fo
->n_ips_expanded
= ip2fo
->n_ips
;
1796 ip2fo
->n_expanded
= ip2fo
->n_ips
;
1797 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1798 ip2fo
->n_offsets_per_ip
[i
] = 1;
1803 static Bool
haveInputInpC (void* inputCompleterV
, UWord ixInput
)
1805 IPtoFunOrObjCompleter
* ip2fo
= (IPtoFunOrObjCompleter
*)inputCompleterV
;
1806 expandInput(ip2fo
, ixInput
);
1807 return ixInput
< ip2fo
->n_expanded
;
1810 static Bool
supp_pattEQinp ( const void* supplocV
, const void* addrV
,
1811 void* inputCompleterV
, UWord ixInput
)
1813 const SuppLoc
* supploc
= (const SuppLoc
*)supplocV
; /* PATTERN */
1814 IPtoFunOrObjCompleter
* ip2fo
= (IPtoFunOrObjCompleter
*)inputCompleterV
;
1815 HChar
* funobj_name
; // Fun or Obj name.
1818 expandInput(ip2fo
, ixInput
);
1819 vg_assert(ixInput
< ip2fo
->n_expanded
);
1821 /* So, does this IP address match this suppression-line? */
1822 switch (supploc
->ty
) {
1824 /* supp_pattEQinp is a callback from VG_(generic_match). As
1825 per the spec thereof (see include/pub_tool_seqmatch.h), we
1826 should never get called with a pattern value for which the
1827 _IsStar or _IsQuery function would return True. Hence
1828 this can't happen. */
1831 funobj_name
= foComplete(ip2fo
, ixInput
, False
/*needFun*/);
1834 funobj_name
= foComplete(ip2fo
, ixInput
, True
/*needFun*/);
1840 /* So now we have the function or object name in funobj_name, and
1841 the pattern (at the character level) to match against is in
1842 supploc->name. Hence (and leading to a re-entrant call of
1843 VG_(generic_match) if there is a wildcard character): */
1844 if (supploc
->name_is_simple_str
)
1845 ret
= VG_(strcmp
) (supploc
->name
, funobj_name
) == 0;
1847 ret
= VG_(string_match
)(supploc
->name
, funobj_name
);
1849 VG_(printf
) ("supp_pattEQinp %s patt %s ixUnput %lu value:%s match:%s\n",
1850 supploc
->ty
== FunName
? "fun" : "obj",
1851 supploc
->name
, ixInput
, funobj_name
,
1852 ret
? "yes" : "no");
1856 /////////////////////////////////////////////////////
1858 static Bool
supp_matches_callers(IPtoFunOrObjCompleter
* ip2fo
,
1861 /* Unwrap the args and set up the correct parameterisation of
1862 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1864 /* note, StackTrace ip2fo->ips === Addr* */
1865 SuppLoc
* supps
= su
->callers
;
1866 UWord n_supps
= su
->n_callers
;
1867 UWord szbPatt
= sizeof(SuppLoc
);
1868 Bool matchAll
= False
; /* we just want to match a prefix */
1869 if (DEBUG_ERRORMGR
) {
1870 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1871 su
->clo_suppressions_i
);
1872 VG_(dmsg
)(" errormgr Checking match with %s %s:%d\n",
1880 /*PATT*/supps
, szbPatt
, n_supps
, 0/*initial ixPatt*/,
1882 NULL
, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
1883 0/*initial ixInput*/,
1884 supploc_IsStar
, supploc_IsQuery
, supp_pattEQinp
,
1885 ip2fo
, haveInputInpC
1889 /////////////////////////////////////////////////////
1892 Bool
supp_matches_error(const Supp
* su
, const Error
* err
)
1894 switch (su
->skind
) {
1895 //(example code, see comment on CoreSuppKind above)
1897 // return (err->ekind == ThreadErr);
1899 if (VG_(needs
).tool_errors
) {
1900 return VG_TDICT_CALL(tool_error_matches_suppression
, err
, su
);
1903 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
1904 "probably needs to be set.\n",
1906 VG_(core_panic
)("unhandled suppression type");
1911 /////////////////////////////////////////////////////
1913 /* Does an error context match a suppression? ie is this a suppressible
1914 error? If so, return a pointer to the Supp record, otherwise NULL.
1915 Tries to minimise the number of symbol searches since they are expensive.
1917 static Supp
* is_suppressible_error ( const Error
* err
)
1922 IPtoFunOrObjCompleter ip2fo
;
1923 /* Conceptually, ip2fo contains an array of function names and an array of
1924 object names, corresponding to the array of IP of err->where.
1925 These names are just computed 'on demand' (so once maximum),
1926 then stored (efficiently, avoiding too many allocs) in ip2fo to be
1927 re-usable for the matching of the same IP with the next suppression
1930 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
1931 of its arguments. It will then pass it to the function
1932 supp_pattEQinp which will then lazily complete the IP function name or
1933 object name inside ip2fo. Next time the fun or obj name for the same
1934 IP is needed (i.e. for the matching with the next suppr pattern), then
1935 the fun or obj name will not be searched again in the debug info. */
1937 /* stats gathering */
1938 em_supplist_searches
++;
1940 /* Prepare the lazy input completer. */
1941 ip2fo
.epoch
= VG_(get_ExeContext_epoch
)(err
->where
);
1942 ip2fo
.ips
= VG_(get_ExeContext_StackTrace
)(err
->where
);
1943 ip2fo
.n_ips
= VG_(get_ExeContext_n_ips
)(err
->where
);
1944 ip2fo
.n_ips_expanded
= 0;
1945 ip2fo
.n_expanded
= 0;
1946 ip2fo
.sz_offsets
= 0;
1947 ip2fo
.n_offsets_per_ip
= NULL
;
1948 ip2fo
.fun_offsets
= NULL
;
1949 ip2fo
.obj_offsets
= NULL
;
1951 ip2fo
.names_szB
= 0;
1952 ip2fo
.names_free
= 0;
1954 /* See if the error context matches any suppression. */
1955 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4)
1956 VG_(dmsg
)("errormgr matching begin\n");
1958 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
1960 if (supp_matches_error(su
, err
)
1961 && supp_matches_callers(&ip2fo
, su
)) {
1963 /* Inform the tool that err is suppressed by su. */
1964 (void)VG_TDICT_CALL(tool_update_extra_suppression_use
, err
, su
);
1965 /* Move this entry to the head of the list
1966 in the hope of making future searches cheaper. */
1968 vg_assert(su_prev
->next
== su
);
1969 su_prev
->next
= su
->next
;
1970 su
->next
= suppressions
;
1973 clearIPtoFunOrObjCompleter(su
, &ip2fo
);
1978 clearIPtoFunOrObjCompleter(NULL
, &ip2fo
);
1979 return NULL
; /* no matches */
1982 /* Show accumulated error-list and suppression-list search stats.
1984 void VG_(print_errormgr_stats
) ( void )
1987 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
1988 em_supplist_searches
, em_supplist_cmps
1991 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
1992 em_errlist_searches
, em_errlist_cmps
1996 /*--------------------------------------------------------------------*/
1998 /*--------------------------------------------------------------------*/