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-2013 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_libcsetjmp.h"
34 #include "pub_core_threadstate.h" // For VG_N_THREADS
35 #include "pub_core_debugger.h"
36 #include "pub_core_debuginfo.h"
37 #include "pub_core_debuglog.h"
38 #include "pub_core_errormgr.h"
39 #include "pub_core_execontext.h"
40 #include "pub_core_gdbserver.h"
41 #include "pub_core_libcbase.h"
42 #include "pub_core_libcassert.h"
43 #include "pub_core_libcfile.h"
44 #include "pub_core_libcprint.h"
45 #include "pub_core_libcproc.h" // For VG_(getpid)()
46 #include "pub_core_seqmatch.h"
47 #include "pub_core_mallocfree.h"
48 #include "pub_core_options.h"
49 #include "pub_core_stacktrace.h"
50 #include "pub_core_tooliface.h"
51 #include "pub_core_translate.h" // for VG_(translate)()
52 #include "pub_core_xarray.h" // VG_(xaprintf) et al
54 #define DEBUG_ERRORMGR 0 // set to 1 for heavyweight tracing
56 /*------------------------------------------------------------*/
58 /*------------------------------------------------------------*/
60 /* After this many different unsuppressed errors have been observed,
61 be more conservative about collecting new ones. */
62 #define M_COLLECT_ERRORS_SLOWLY_AFTER 100
64 /* After this many different unsuppressed errors have been observed,
65 stop collecting errors at all, and tell the user their program is
66 evidently a steaming pile of camel dung. */
67 #define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
69 /* After this many total errors have been observed, stop collecting
70 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
71 #define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
73 /* The list of error contexts found, both suppressed and unsuppressed.
74 Initially empty, and grows as errors are detected. */
75 static Error
* errors
= NULL
;
77 /* The list of suppression directives, as read from the specified
78 suppressions file. Note that the list gets rearranged as a result
79 of the searches done by is_suppressible_error(). */
80 static Supp
* suppressions
= NULL
;
82 /* Running count of unsuppressed errors detected. */
83 static UInt n_errs_found
= 0;
85 /* Running count of suppressed errors detected. */
86 static UInt n_errs_suppressed
= 0;
88 /* Running count of errors shown. */
89 static UInt n_errs_shown
= 0;
91 /* Running count of unsuppressed error contexts. */
92 static UInt n_err_contexts
= 0;
94 /* Running count of suppressed error contexts. */
95 static UInt n_supp_contexts
= 0;
99 static Supp
* is_suppressible_error ( const Error
* err
);
101 static ThreadId last_tid_printed
= 1;
103 /* Stats: number of searches of the error list initiated. */
104 static UWord em_errlist_searches
= 0;
106 /* Stats: number of comparisons done during error list
108 static UWord em_errlist_cmps
= 0;
110 /* Stats: number of searches of the suppression list initiated. */
111 static UWord em_supplist_searches
= 0;
113 /* Stats: number of comparisons done during suppression list
115 static UWord em_supplist_cmps
= 0;
117 /*------------------------------------------------------------*/
118 /*--- Error type ---*/
119 /*------------------------------------------------------------*/
121 /* Errors. Extensible (via the 'extra' field). Tools can use a normal
122 enum (with element values in the normal range (0..)) for 'ekind'.
123 Functions for getting/setting the tool-relevant fields are in
124 include/pub_tool_errormgr.h.
126 When errors are found and recorded with VG_(maybe_record_error)(), all
127 the tool must do is pass in the four parameters; core will
128 allocate/initialise the error record.
132 // Unique tag. This gives the error a unique identity (handle) by
133 // which it can be referred to afterwords. Currently only used for
136 // NULL if unsuppressed; or ptr to suppression record.
140 // The tool-specific part
141 ThreadId tid
; // Initialised by core
142 ExeContext
* where
; // Initialised by core
143 ErrorKind ekind
; // Used by ALL. Must be in the range (0..)
144 Addr addr
; // Used frequently
145 const HChar
* string
; // Used frequently
146 void* extra
; // For any tool-specific extras
150 ExeContext
* VG_(get_error_where
) ( const Error
* err
)
155 ErrorKind
VG_(get_error_kind
) ( const Error
* err
)
160 Addr
VG_(get_error_address
) ( const Error
* err
)
165 const HChar
* VG_(get_error_string
) ( const Error
* err
)
170 void* VG_(get_error_extra
) ( const Error
* err
)
175 UInt
VG_(get_n_errs_found
)( void )
180 UInt
VG_(get_n_errs_shown
)( void )
185 /*------------------------------------------------------------*/
186 /*--- Suppression type ---*/
187 /*------------------------------------------------------------*/
189 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools
190 * effectively extend it by defining their own enums in the (0..) range. */
193 // Nb: thread errors are a relic of the time when Valgrind's core
194 // could detect them. This example is left commented-out as an
195 // example should new core errors ever be added.
196 ThreadSupp
= -1, /* Matches ThreadErr */
200 /* Max number of callers for context in a suppression. */
201 #define VG_MAX_SUPP_CALLERS 24
203 /* For each caller specified for a suppression, record the nature of
204 the caller name. Not of interest to tools. */
207 NoName
, /* Error case */
208 ObjName
, /* Name is of an shared object file. */
209 FunName
, /* Name is of a function. */
210 DotDotDot
/* Frame-level wildcard */
217 Bool name_is_simple_str
; /* True if name is a string without
218 '?' and '*' wildcard characters. */
219 HChar
* name
; /* NULL for NoName and DotDotDot */
223 /* Suppressions. Tools can get/set tool-relevant parts with functions
224 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field.
225 Tools can use a normal enum (with element values in the normal range
226 (0..)) for 'skind'. */
229 Int count
; // The number of times this error has been suppressed.
230 HChar
* sname
; // The name by which the suppression is referred to.
232 // Index in VG_(clo_suppressions) giving filename from which suppression
233 // was read, and the lineno in this file where sname was read.
234 Int clo_suppressions_i
;
237 // Length of 'callers'
239 // Array of callers, for matching stack traces. First one (name of fn
240 // where err occurs) is mandatory; rest are optional.
243 /* The tool-specific part */
244 SuppKind skind
; // What kind of suppression. Must use the range (0..).
245 HChar
* string
; // String -- use is optional. NULL by default.
246 void* extra
; // Anything else -- use is optional. NULL by default.
249 SuppKind
VG_(get_supp_kind
) ( const Supp
* su
)
254 HChar
* VG_(get_supp_string
) ( const Supp
* su
)
259 void* VG_(get_supp_extra
) ( const Supp
* su
)
265 void VG_(set_supp_kind
) ( Supp
* su
, SuppKind skind
)
270 void VG_(set_supp_string
) ( Supp
* su
, HChar
* string
)
275 void VG_(set_supp_extra
) ( Supp
* su
, void* extra
)
281 /*------------------------------------------------------------*/
282 /*--- Helper fns ---*/
283 /*------------------------------------------------------------*/
285 // Only show core errors if the tool wants to, we're not running with -q,
286 // and were not outputting XML.
287 Bool
VG_(showing_core_errors
)(void)
289 return VG_(needs
).core_errors
&& VG_(clo_verbosity
) >= 1 && !VG_(clo_xml
);
292 /* Compare errors, to detect duplicates.
294 static Bool
eq_Error ( VgRes res
, const Error
* e1
, const Error
* e2
)
296 if (e1
->ekind
!= e2
->ekind
)
298 if (!VG_(eq_ExeContext
)(res
, e1
->where
, e2
->where
))
302 //(example code, see comment on CoreSuppKind above)
304 // vg_assert(VG_(needs).core_errors);
305 // return <something>
307 if (VG_(needs
).tool_errors
) {
308 return VG_TDICT_CALL(tool_eq_Error
, res
, e1
, e2
);
310 VG_(printf
)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
311 "probably needs to be set.\n",
313 VG_(core_panic
)("unhandled error type");
319 /* Helper functions for suppression generation: print a single line of
320 a suppression pseudo-stack-trace, either in XML or text mode. It's
321 important that the behaviour of these two functions exactly
324 #define ERRTXT_LEN 4096
326 static void printSuppForIp_XML(UInt n
, Addr ip
, void* uu_opaque
)
329 InlIPCursor
* iipc
= VG_(new_IIPC
)(ip
);
331 if ( VG_(get_fnname_no_cxx_demangle
) (ip
, &buf
, iipc
) ) {
332 VG_(printf_xml
)(" <sframe> <fun>%pS</fun> </sframe>\n", buf
);
334 if ( VG_(get_objname
)(ip
, &buf
) ) {
335 VG_(printf_xml
)(" <sframe> <obj>%pS</obj> </sframe>\n", buf
);
337 VG_(printf_xml
)(" <sframe> <obj>*</obj> </sframe>\n");
339 } while (VG_(next_IIPC
)(iipc
));
340 VG_(delete_IIPC
)(iipc
);
343 static void printSuppForIp_nonXML(UInt n
, Addr ip
, void* textV
)
346 XArray
* /* of HChar */ text
= (XArray
*)textV
;
347 InlIPCursor
* iipc
= VG_(new_IIPC
)(ip
);
349 if ( VG_(get_fnname_no_cxx_demangle
) (ip
, &buf
, iipc
) ) {
350 VG_(xaprintf
)(text
, " fun:%s\n", buf
);
352 if ( VG_(get_objname
)(ip
, &buf
) ) {
353 VG_(xaprintf
)(text
, " obj:%s\n", buf
);
355 VG_(xaprintf
)(text
, " obj:*\n");
357 } while (VG_(next_IIPC
)(iipc
));
358 VG_(delete_IIPC
)(iipc
);
361 /* Generate a suppression for an error, either in text or XML mode.
363 static void gen_suppression(const Error
* err
)
367 XArray
* /* HChar */ text
;
369 const HChar
* dummy_name
= "insert_a_suppression_name_here";
373 ec
= VG_(get_error_where
)(err
);
376 name
= VG_TDICT_CALL(tool_get_error_name
, err
);
378 VG_(umsg
)("(%s does not allow error to be suppressed)\n",
383 /* In XML mode, we also need to print the plain text version of the
384 suppresion in a CDATA section. What that really means is, we
385 need to generate the plaintext version both in XML and text
386 mode. So generate it into TEXT. */
387 text
= VG_(newXA
)( VG_(malloc
), "errormgr.gen_suppression.1",
388 VG_(free
), sizeof(HChar
) );
390 /* Ok. Generate the plain text version into TEXT. */
391 VG_(xaprintf
)(text
, "{\n");
392 VG_(xaprintf
)(text
, " <%s>\n", dummy_name
);
393 VG_(xaprintf
)(text
, " %s:%s\n", VG_(details
).name
, name
);
401 xtra
= VG_(realloc
)("errormgr.gen_suppression.2", xtra
,xtra_size
);
402 num_written
= VG_TDICT_CALL(tool_get_extra_suppression_info
,
403 err
, xtra
, xtra_size
);
404 } while (num_written
== xtra_size
); // resize buffer and retry
406 // Ensure buffer is properly terminated
407 vg_assert(xtra
[num_written
] == '\0');
410 VG_(xaprintf
)(text
, " %s\n", xtra
);
412 // Print stack trace elements
413 UInt n_ips
= VG_(get_ExeContext_n_ips
)(ec
);
414 vg_assert(n_ips
> 0);
415 if (n_ips
> VG_MAX_SUPP_CALLERS
)
416 n_ips
= VG_MAX_SUPP_CALLERS
;
417 VG_(apply_StackTrace
)(printSuppForIp_nonXML
,
419 VG_(get_ExeContext_StackTrace
)(ec
),
422 VG_(xaprintf
)(text
, "}\n");
424 VG_(xaprintf
)(text
, "%c", (HChar
)0 );
425 // VG_(printf) of text
427 /* And now display it. */
428 if (! VG_(clo_xml
) ) {
431 VG_(printf
)("%s", (HChar
*) VG_(indexXA
)(text
, 0) );
435 /* Now we have to print the XML directly. No need to go to the
436 effort of stuffing it in an XArray, since we won't need it
438 VG_(printf_xml
)(" <suppression>\n");
439 VG_(printf_xml
)(" <sname>%s</sname>\n", dummy_name
);
441 " <skind>%pS:%pS</skind>\n", VG_(details
).name
, name
);
443 VG_(printf_xml
)(" <skaux>%pS</skaux>\n", xtra
);
445 // Print stack trace elements
446 VG_(apply_StackTrace
)(printSuppForIp_XML
,
448 VG_(get_ExeContext_StackTrace
)(ec
),
449 VG_(get_ExeContext_n_ips
)(ec
));
451 // And now the cdata bit
452 // XXX FIXME! properly handle the case where the raw text
453 // itself contains "]]>", as specified in Protocol 4.
454 VG_(printf_xml
)(" <rawtext>\n");
455 VG_(printf_xml
)("<![CDATA[\n");
456 VG_(printf_xml
)("%s", (HChar
*) VG_(indexXA
)(text
, 0) );
457 VG_(printf_xml
)("]]>\n");
458 VG_(printf_xml
)(" </rawtext>\n");
459 VG_(printf_xml
)(" </suppression>\n");
468 /* Figure out if we want to perform a given action for this error,
469 possibly by asking the user.
471 Bool
VG_(is_action_requested
) ( const HChar
* action
, Bool
* clo
)
476 /* First off, we shouldn't be asking the user anything if
477 we're in XML mode. */
479 return False
; /* That's a Nein, oder Nay as they say down here in B-W */
489 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
490 VG_(getpid
)(), action
493 res
= VG_(read
)(VG_(clo_input_fd
), &ch
, 1);
494 if (res
!= 1) goto ioerror
;
496 if (ch
== '\n') return False
;
497 if (ch
!= 'N' && ch
!= 'n' && ch
!= 'Y' && ch
!= 'y'
498 && ch
!= 'C' && ch
!= 'c') goto again
;
500 res
= VG_(read
)(VG_(clo_input_fd
), &ch2
, 1);
501 if (res
!= 1) goto ioerror
;
502 if (ch2
!= '\n') goto again
;
504 /* No, don't want to do action. */
505 if (ch
== 'n' || ch
== 'N') return False
;
506 /* Yes, want to do action. */
507 if (ch
== 'y' || ch
== 'Y') return True
;
508 /* No, don't want to do action, and don't ask again either. */
509 vg_assert(ch
== 'c' || ch
== 'C');
517 /* Do text-mode actions on error, that is, immediately after an error
518 is printed. These are:
519 * possibly, attach to a debugger
520 * possibly, generate a suppression.
521 Note this should not be called in XML mode!
524 void do_actions_on_error(const Error
* err
, Bool allow_db_attach
)
526 Bool still_noisy
= True
;
528 /* Should be assured by caller */
529 vg_assert( ! VG_(clo_xml
) );
531 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
532 if (VG_(clo_vgdb
) != Vg_VgdbNo
534 && VG_(dyn_vgdb_error
) <= n_errs_shown
) {
535 VG_(umsg
)("(action on error) vgdb me ... \n");
536 VG_(gdbserver
)( err
->tid
);
537 VG_(umsg
)("Continuing ...\n");
540 /* Perhaps we want a debugger attach at this point? */
541 /* GDBTD ??? maybe we should/could remove the below assuming the
542 gdbserver interface is better ??? */
543 if (allow_db_attach
&&
544 VG_(is_action_requested
)( "Attach to debugger", & VG_(clo_db_attach
) ))
546 if (0) VG_(printf
)("starting debugger\n");
547 VG_(start_debugger
)( err
->tid
);
549 /* Or maybe we want to generate the error's suppression? */
550 if (VG_(clo_gen_suppressions
) == 2
551 || (VG_(clo_gen_suppressions
) == 1
552 && VG_(is_action_requested
)( "Print suppression", &still_noisy
))
554 gen_suppression(err
);
556 if (VG_(clo_gen_suppressions
) == 1 && !still_noisy
)
557 VG_(clo_gen_suppressions
) = 0;
561 /* Prints an error. Not entirely simple because of the differences
562 between XML and text mode output.
566 * calls the tool's pre-show method, so the tool can create any
567 preamble ahead of the message, if it wants.
569 * prints the opening tag, and the <unique> and <tid> fields
571 * prints the tool-specific parts of the message
573 * if suppression generation is required, a suppression
579 * calls the tool's pre-show method, so the tool can create any
580 preamble ahead of the message, if it wants.
582 * prints the tool-specific parts of the message
584 * calls do_actions_on_error. This optionally does a debugger
585 attach (and detach), and optionally prints a suppression; both
586 of these may require user input.
588 static void pp_Error ( const Error
* err
, Bool allow_db_attach
, Bool xml
)
590 /* If this fails, you probably specified your tool's method
591 dictionary incorrectly. */
592 vg_assert(VG_(needs
).tool_errors
);
596 /* Note, allow_db_attach is ignored in here. */
598 /* Ensure that suppression generation is either completely
599 enabled or completely disabled; either way, we won't require
600 any user input. m_main.process_cmd_line_options should
601 ensure the asserted condition holds. */
602 vg_assert( VG_(clo_gen_suppressions
) == 0 /* disabled */
603 || VG_(clo_gen_suppressions
) == 2 /* for all errors */ );
605 /* Pre-show it to the tool */
606 VG_TDICT_CALL( tool_before_pp_Error
, err
);
608 /* standard preamble */
609 VG_(printf_xml
)("<error>\n");
610 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
611 VG_(printf_xml
)(" <tid>%d</tid>\n", err
->tid
);
612 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
613 if (tst
->thread_name
) {
614 VG_(printf_xml
)(" <threadname>%s</threadname>\n", tst
->thread_name
);
617 /* actually print it */
618 VG_TDICT_CALL( tool_pp_Error
, err
);
620 if (VG_(clo_gen_suppressions
) > 0)
621 gen_suppression(err
);
624 VG_(printf_xml
)("</error>\n");
625 VG_(printf_xml
)("\n");
629 if (VG_(clo_error_markers
)[0])
630 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[0]);
631 VG_TDICT_CALL( tool_before_pp_Error
, err
);
633 if (VG_(tdict
).tool_show_ThreadIDs_for_errors
634 && err
->tid
> 0 && err
->tid
!= last_tid_printed
) {
635 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
636 if (tst
->thread_name
) {
637 VG_(umsg
)("Thread %d %s:\n", err
->tid
, tst
->thread_name
);
639 VG_(umsg
)("Thread %d:\n", err
->tid
);
641 last_tid_printed
= err
->tid
;
644 VG_TDICT_CALL( tool_pp_Error
, err
);
646 if (VG_(clo_error_markers
)[1])
647 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[1]);
649 do_actions_on_error(err
, allow_db_attach
);
654 /* Construct an error */
656 void construct_error ( Error
* err
, ThreadId tid
, ErrorKind ekind
, Addr a
,
657 const HChar
* s
, void* extra
, ExeContext
* where
)
659 /* DO NOT MAKE unique_counter NON-STATIC */
660 static UInt unique_counter
= 0;
662 vg_assert(tid
< VG_N_THREADS
);
664 /* Core-only parts */
665 err
->unique
= unique_counter
++;
671 err
->where
= VG_(record_ExeContext
)( tid
, 0 );
675 /* Tool-relevant parts */
682 vg_assert( tid
< VG_N_THREADS
);
687 /* Top-level entry point to the error management subsystem.
688 All detected errors are notified here; this routine decides if/when the
689 user should see the error. */
690 void VG_(maybe_record_error
) ( ThreadId tid
,
691 ErrorKind ekind
, Addr a
,
692 const HChar
* s
, void* extra
)
698 VgRes exe_res
= Vg_MedRes
;
699 static Bool stopping_message
= False
;
700 static Bool slowdown_message
= False
;
702 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
703 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
704 have been found, just refuse to collect any more. This stops
705 the burden of the error-management system becoming excessive in
706 extremely buggy programs, although it does make it pretty
707 pointless to continue the Valgrind run after this point. */
708 if (VG_(clo_error_limit
)
709 && (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
710 || n_errs_found
>= M_COLLECT_NO_ERRORS_AFTER_FOUND
)
712 if (!stopping_message
) {
715 if (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
) {
717 "More than %d different errors detected. "
718 "I'm not reporting any more.\n",
719 M_COLLECT_NO_ERRORS_AFTER_SHOWN
);
722 "More than %d total errors detected. "
723 "I'm not reporting any more.\n",
724 M_COLLECT_NO_ERRORS_AFTER_FOUND
);
727 VG_(umsg
)("Final error counts will be inaccurate. "
728 "Go fix your program!\n");
729 VG_(umsg
)("Rerun with --error-limit=no to disable "
730 "this cutoff. Note\n");
731 VG_(umsg
)("that errors may occur in your program without "
732 "prior warning from\n");
733 VG_(umsg
)("Valgrind, because errors are no longer "
734 "being displayed.\n");
736 stopping_message
= True
;
741 /* Ignore it if error acquisition is disabled for this thread. */
742 { ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
743 if (tst
->err_disablement_level
> 0)
747 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
748 been found, be much more conservative about collecting new
750 if (n_errs_shown
>= M_COLLECT_ERRORS_SLOWLY_AFTER
753 if (!slowdown_message
) {
755 VG_(umsg
)("More than %d errors detected. Subsequent errors\n",
756 M_COLLECT_ERRORS_SLOWLY_AFTER
);
757 VG_(umsg
)("will still be recorded, but in less "
758 "detail than before.\n");
759 slowdown_message
= True
;
763 /* Build ourselves the error */
764 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, NULL
);
766 /* First, see if we've got an error record matching this one. */
767 em_errlist_searches
++;
772 if (eq_Error(exe_res
, p
, &err
)) {
775 if (p
->supp
!= NULL
) {
776 /* Deal correctly with suppressed errors. */
783 /* Move p to the front of the list so that future searches
784 for it are faster. It also allows to print the last
785 error (see VG_(show_last_error). */
786 if (p_prev
!= NULL
) {
787 vg_assert(p_prev
->next
== p
);
788 p_prev
->next
= p
->next
;
799 /* Didn't see it. Copy and add. */
801 /* OK, we're really going to collect it. The context is on the stack and
802 will disappear shortly, so we must copy it. First do the main
805 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
806 is for when there are more details to fill in which take time to work
807 out but don't affect our earlier decision to include the error -- by
808 postponing those details until now, we avoid the extra work in the
809 case where we ignore the error. Ugly.
811 Then, if there is an 'extra' part, copy it too, using the size that
812 VG_(tdict).tool_update_extra returned. Also allow for people using
813 the void* extra field for a scalar value like an integer.
817 p
= VG_(malloc
)("errormgr.mre.1", sizeof(Error
));
822 //(example code, see comment on CoreSuppKind above)
824 // vg_assert(VG_(needs).core_errors);
825 // extra_size = <something>
828 vg_assert(VG_(needs
).tool_errors
);
829 extra_size
= VG_TDICT_CALL(tool_update_extra
, p
);
833 /* copy the error string, if there is one.
834 note: if we would have many errors with big strings, using a
835 DedupPoolAlloc for these strings will avoid duplicating
836 such string in each error using it. */
837 if (NULL
!= p
->string
) {
838 p
->string
= VG_(strdup
)("errormgr.mre.2", p
->string
);
841 /* copy block pointed to by 'extra', if there is one */
842 if (NULL
!= p
->extra
&& 0 != extra_size
) {
843 void* new_extra
= VG_(malloc
)("errormgr.mre.3", extra_size
);
844 VG_(memcpy
)(new_extra
, p
->extra
, extra_size
);
845 p
->extra
= new_extra
;
849 p
->supp
= is_suppressible_error(&err
);
851 if (p
->supp
== NULL
) {
856 /* Actually show the error; more complex than you might think. */
857 pp_Error( p
, /*allow_db_attach*/True
, VG_(clo_xml
) );
865 /* Second top-level entry point to the error management subsystem, for
866 errors that the tool wants to report immediately, eg. because they're
867 guaranteed to only happen once. This avoids all the recording and
868 comparing stuff. But they can be suppressed; returns True if it is
869 suppressed. Bool 'print_error' dictates whether to print the error.
870 Bool 'count_error' dictates whether to count the error in n_errs_found.
872 Bool
VG_(unique_error
) ( ThreadId tid
, ErrorKind ekind
, Addr a
, const HChar
* s
,
873 void* extra
, ExeContext
* where
, Bool print_error
,
874 Bool allow_db_attach
, Bool count_error
)
879 /* Ignore it if error acquisition is disabled for this thread. */
880 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
881 if (tst
->err_disablement_level
> 0)
882 return False
; /* ignored, not suppressed */
884 /* Build ourselves the error */
885 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, where
);
887 /* Unless it's suppressed, we're going to show it. Don't need to make
888 a copy, because it's only temporary anyway.
890 Then update the 'extra' part with VG_(tdict).tool_update_extra),
891 because that can have an affect on whether it's suppressed. Ignore
892 the size return value of VG_(tdict).tool_update_extra, because we're
893 not copying 'extra'. Similarly, 's' is also not copied. */
894 (void)VG_TDICT_CALL(tool_update_extra
, &err
);
896 su
= is_suppressible_error(&err
);
906 /* Actually show the error; more complex than you might think. */
907 pp_Error(&err
, allow_db_attach
, VG_(clo_xml
));
922 /*------------------------------------------------------------*/
923 /*--- Exported fns ---*/
924 /*------------------------------------------------------------*/
926 /* Show the used suppressions. Returns False if no suppression
928 static Bool
show_used_suppressions ( void )
934 VG_(printf_xml
)("<suppcounts>\n");
937 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
941 VG_(printf_xml
)( " <pair>\n"
942 " <count>%d</count>\n"
943 " <name>%pS</name>\n"
945 su
->count
, su
->sname
);
950 // blank line before the first shown suppression, if any
956 xtra
= VG_(realloc
)("errormgr.sus.1", xtra
, xtra_size
);
957 num_written
= VG_TDICT_CALL(tool_print_extra_suppression_use
,
958 su
, xtra
, xtra_size
);
959 } while (num_written
== xtra_size
); // resize buffer and retry
961 // Ensure buffer is properly terminated
962 vg_assert(xtra
[num_written
] == '\0');
964 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
965 su
->clo_suppressions_i
);
966 VG_(dmsg
)("used_suppression: %6d %s %s:%d%s%s\n", su
->count
, su
->sname
,
969 num_written
? " " : "", xtra
);
976 VG_(printf_xml
)("</suppcounts>\n");
981 /* Show all the errors that occurred, and possibly also the
982 suppressions used. */
983 void VG_(show_all_errors
) ( Int verbosity
, Bool xml
)
992 /* If we're printing XML, just show the suppressions and stop. */
994 (void)show_used_suppressions();
998 /* We only get here if not printing XML. */
999 VG_(umsg
)("ERROR SUMMARY: "
1000 "%d errors from %d contexts (suppressed: %d from %d)\n",
1001 n_errs_found
, n_err_contexts
,
1002 n_errs_suppressed
, n_supp_contexts
);
1007 // We do the following only at -v or above, and only in non-XML
1010 /* Print the contexts in order of increasing error count.
1011 Once an error is shown, we add a huge value to its count to filter it
1013 After having shown all errors, we reset count to the original value. */
1014 for (i
= 0; i
< n_err_contexts
; i
++) {
1015 n_min
= (1 << 30) - 1;
1017 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1018 if (p
->supp
!= NULL
) continue;
1019 if (p
->count
< n_min
) {
1024 // XXX: this isn't right. See bug 203651.
1025 if (p_min
== NULL
) continue; //VG_(core_panic)("show_all_errors()");
1028 VG_(umsg
)("%d errors in context %d of %d:\n",
1029 p_min
->count
, i
+1, n_err_contexts
);
1030 pp_Error( p_min
, False
/*allow_db_attach*/, False
/* xml */ );
1032 // We're not printing XML -- we'd have exited above if so.
1035 if ((i
+1 == VG_(clo_dump_error
))) {
1036 StackTrace ips
= VG_(get_ExeContext_StackTrace
)(p_min
->where
);
1037 VG_(translate
) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1038 ips
[0], /*debugging*/True
, 0xFE/*verbosity*/,
1040 /*allow redir?*/True
);
1043 p_min
->count
= p_min
->count
+ (1 << 30);
1046 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1047 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1048 if (p
->count
>= (1 << 30))
1049 p
->count
= p
->count
- (1 << 30);
1053 any_supp
= show_used_suppressions();
1057 // reprint this, so users don't have to scroll way up to find
1058 // the first printing
1059 VG_(umsg
)("ERROR SUMMARY: "
1060 "%d errors from %d contexts (suppressed: %d from %d)\n",
1061 n_errs_found
, n_err_contexts
, n_errs_suppressed
,
1065 void VG_(show_last_error
) ( void )
1067 if (n_err_contexts
== 0) {
1068 VG_(umsg
)("No errors yet\n");
1072 pp_Error( errors
, False
/*allow_db_attach*/, False
/*xml*/ );
1076 /* Show occurrence counts of all errors, in XML form. */
1077 void VG_(show_error_counts_as_XML
) ( void )
1080 VG_(printf_xml
)("<errorcounts>\n");
1081 for (err
= errors
; err
!= NULL
; err
= err
->next
) {
1082 if (err
->supp
!= NULL
)
1084 if (err
->count
<= 0)
1086 VG_(printf_xml
)(" <pair>\n");
1087 VG_(printf_xml
)(" <count>%d</count>\n", err
->count
);
1088 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
1089 VG_(printf_xml
)(" </pair>\n");
1091 VG_(printf_xml
)("</errorcounts>\n");
1092 VG_(printf_xml
)("\n");
1096 /*------------------------------------------------------------*/
1097 /*--- Suppression parsing ---*/
1098 /*------------------------------------------------------------*/
1100 /* Get the next char from fd into *out_buf. Returns 1 if success,
1101 0 if eof or < 0 if error. */
1103 static Int
get_char ( Int fd
, HChar
* out_buf
)
1106 static HChar buf
[256];
1107 static Int buf_size
= 0;
1108 static Int buf_used
= 0;
1109 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1110 vg_assert(buf_used
>= 0 && buf_used
<= buf_size
);
1111 if (buf_used
== buf_size
) {
1112 r
= VG_(read
)(fd
, buf
, sizeof buf
);
1113 if (r
< 0) return r
; /* read failed */
1114 vg_assert(r
>= 0 && r
<= sizeof buf
);
1120 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1121 vg_assert(buf_used
>= 0 && buf_used
< buf_size
);
1122 *out_buf
= buf
[buf_used
];
1127 // Get a non blank non comment line.
1128 // Returns True if eof.
1129 static Bool
get_nbnc_line ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1131 HChar
* buf
= *bufpp
;
1132 SizeT nBuf
= *nBufp
;
1136 vg_assert(lineno
); // lineno needed to correctly track line numbers.
1140 /* First, read until a non-blank char appears. */
1142 n
= get_char(fd
, &ch
);
1143 if (n
== 1 && !VG_(isspace
)(ch
)) break;
1144 if (n
== 1 && ch
== '\n')
1146 if (n
<= 0) return True
;
1149 /* Now, read the line into buf. */
1151 buf
[i
++] = ch
; buf
[i
] = 0;
1153 n
= get_char(fd
, &ch
);
1154 if (n
<= 0) return False
; /* the next call will return True */
1157 if (ch
== '\n') break;
1158 if (i
> 0 && i
== nBuf
-1) {
1159 *nBufp
= nBuf
= nBuf
* 2;
1160 #define RIDICULOUS 100000
1161 vg_assert2(nBuf
< RIDICULOUS
, // Just a sanity check, really.
1162 "VG_(get_line): line longer than %d chars, aborting\n",
1164 *bufpp
= buf
= VG_(realloc
)("errormgr.get_line.1", buf
, nBuf
);
1166 buf
[i
++] = ch
; buf
[i
] = 0;
1168 while (i
> 1 && VG_(isspace
)(buf
[i
-1])) {
1172 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1173 /* Ok, we have a line. If a non-comment line, return.
1174 If a comment line, start all over again. */
1175 if (buf
[0] != '#') return False
;
1179 // True if buf starts with fun: or obj: or is ...
1180 static Bool
is_location_line (const HChar
* buf
)
1182 return VG_(strncmp
)(buf
, "fun:", 4) == 0
1183 || VG_(strncmp
)(buf
, "obj:", 4) == 0
1184 || VG_(strcmp
)(buf
, "...") == 0;
1187 Bool
VG_(get_line
) ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1189 Bool eof
= get_nbnc_line (fd
, bufpp
, nBufp
, lineno
);
1194 if (is_location_line(*bufpp
))
1195 return True
; // Not a extra suppr line
1197 return False
; // A suppression extra line
1200 /* True if s contains no wildcard (?, *) characters. */
1201 static Bool
is_simple_str (const HChar
*s
)
1204 if (*s
== '?' || *s
== '*')
1211 /* buf contains the raw name of a caller, supposedly either
1212 fun:some_function_name or
1213 obj:some_object_name or
1215 Set p->ty and p->name accordingly.
1216 p->name is allocated and set to the string
1217 after the descriptor (fun: or obj:) part.
1218 Returns False if failed.
1220 static Bool
setLocationTy ( SuppLoc
* p
, const HChar
*buf
)
1222 if (VG_(strncmp
)(buf
, "fun:", 4) == 0) {
1223 p
->name
= VG_(strdup
)("errormgr.sLTy.1", buf
+4);
1224 p
->name_is_simple_str
= is_simple_str (p
->name
);
1228 if (VG_(strncmp
)(buf
, "obj:", 4) == 0) {
1229 p
->name
= VG_(strdup
)("errormgr.sLTy.2", buf
+4);
1230 p
->name_is_simple_str
= is_simple_str (p
->name
);
1234 if (VG_(strcmp
)(buf
, "...") == 0) {
1236 p
->name_is_simple_str
= False
;
1240 VG_(printf
)("location should be \"...\", or should start "
1241 "with \"fun:\" or \"obj:\"\n");
1246 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1247 static Bool
tool_name_present(const HChar
*name
, const HChar
*names
)
1250 HChar
*s
= NULL
; /* Shut gcc up */
1251 Int len
= VG_(strlen
)(name
);
1253 found
= (NULL
!= (s
= VG_(strstr
)(names
, name
)) &&
1254 (s
== names
|| *(s
-1) == ',') &&
1255 (*(s
+len
) == ',' || *(s
+len
) == '\0')
1261 /* Read suppressions from the file specified in
1262 VG_(clo_suppressions)[clo_suppressions_i]
1263 and place them in the suppressions list. If there's any difficulty
1264 doing this, just give up -- there's no point in trying to recover.
1266 static void load_one_suppressions_file ( Int clo_suppressions_i
)
1268 const HChar
* filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1269 clo_suppressions_i
);
1271 Int fd
, i
, j
, lineno
= 0;
1272 Bool got_a_location_line_read_by_tool
;
1275 HChar
* buf
= VG_(malloc
)("errormgr.losf.1", nBuf
);
1278 const HChar
* err_str
= NULL
;
1279 SuppLoc tmp_callers
[VG_MAX_SUPP_CALLERS
];
1281 // Check it's not a directory.
1282 if (VG_(is_dir
)( filename
)) {
1284 VG_(printf_xml
)("</valgrindoutput>\n");
1285 VG_(umsg
)("FATAL: suppressions file \"%s\" is a directory\n", filename
);
1289 // Open the suppression file.
1290 sres
= VG_(open
)( filename
, VKI_O_RDONLY
, 0 );
1291 if (sr_isError(sres
)) {
1293 VG_(printf_xml
)("</valgrindoutput>\n");
1294 VG_(umsg
)("FATAL: can't open suppressions file \"%s\"\n", filename
);
1299 # define BOMB(S) { err_str = S; goto syntax_error; }
1302 /* Assign and initialise the two suppression halves (core and tool) */
1304 supp
= VG_(malloc
)("errormgr.losf.1", sizeof(Supp
));
1307 // Initialise temporary reading-in buffer.
1308 for (i
= 0; i
< VG_MAX_SUPP_CALLERS
; i
++) {
1309 tmp_callers
[i
].ty
= NoName
;
1310 tmp_callers
[i
].name_is_simple_str
= False
;
1311 tmp_callers
[i
].name
= NULL
;
1314 supp
->string
= supp
->extra
= NULL
;
1316 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1322 if (!VG_STREQ(buf
, "{")) BOMB("expected '{' or end-of-file");
1324 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1326 if (eof
|| VG_STREQ(buf
, "}")) BOMB("unexpected '}'");
1328 supp
->sname
= VG_(strdup
)("errormgr.losf.2", buf
);
1329 supp
->clo_suppressions_i
= clo_suppressions_i
;
1330 supp
->sname_lineno
= lineno
;
1332 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1334 if (eof
) BOMB("unexpected end-of-file (expecting tool:suppr)");
1336 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1339 if (buf
[i
] == ':') break;
1340 if (buf
[i
] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1343 buf
[i
] = '\0'; /* Replace ':', splitting into two strings */
1345 tool_names
= & buf
[0];
1346 supp_name
= & buf
[i
+1];
1348 if (VG_(needs
).core_errors
&& tool_name_present("core", tool_names
))
1350 // A core suppression
1351 //(example code, see comment on CoreSuppKind above)
1352 //if (VG_STREQ(supp_name, "Thread"))
1353 // supp->skind = ThreadSupp;
1355 BOMB("unknown core suppression type");
1357 else if (VG_(needs
).tool_errors
&&
1358 tool_name_present(VG_(details
).name
, tool_names
))
1360 // A tool suppression
1361 if (VG_TDICT_CALL(tool_recognised_suppression
, supp_name
, supp
)) {
1362 /* Do nothing, function fills in supp->skind */
1364 BOMB("unknown tool suppression type");
1368 // Ignore rest of suppression
1370 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1371 if (eof
) BOMB("unexpected end-of-file (when skipping suppression)");
1372 if (VG_STREQ(buf
, "}"))
1375 VG_(free
)(supp
->sname
);
1381 // tool_read_extra_suppression_info might read lines
1382 // from fd till a location line.
1383 if (VG_(needs
).tool_errors
&&
1384 !VG_TDICT_CALL(tool_read_extra_suppression_info
,
1385 fd
, &buf
, &nBuf
, &lineno
, supp
))
1387 BOMB("bad or missing extra suppression info");
1390 got_a_location_line_read_by_tool
= buf
[0] != 0 && is_location_line(buf
);
1392 /* the main frame-descriptor reading loop */
1395 if (got_a_location_line_read_by_tool
) {
1396 got_a_location_line_read_by_tool
= False
;
1399 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1402 BOMB("unexpected end-of-file (when reading stack trace)");
1403 if (VG_STREQ(buf
, "}")) {
1407 BOMB("missing stack trace");
1410 if (i
== VG_MAX_SUPP_CALLERS
)
1411 BOMB("too many callers in stack trace");
1412 if (i
> 0 && i
>= VG_(clo_backtrace_size
))
1414 if (!setLocationTy(&(tmp_callers
[i
]), buf
))
1415 BOMB("location should be \"...\", or should start "
1416 "with \"fun:\" or \"obj:\"");
1420 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1421 // lines and grab the '}'.
1422 if (!VG_STREQ(buf
, "}")) {
1424 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1425 } while (!eof
&& !VG_STREQ(buf
, "}"));
1428 // Reject entries which are entirely composed of frame
1430 vg_assert(i
> 0); // guaranteed by frame-descriptor reading loop
1431 for (j
= 0; j
< i
; j
++) {
1432 if (tmp_callers
[j
].ty
== FunName
|| tmp_callers
[j
].ty
== ObjName
)
1434 vg_assert(tmp_callers
[j
].ty
== DotDotDot
);
1436 vg_assert(j
>= 0 && j
<= i
);
1438 // we didn't find any non-"..." entries
1439 BOMB("suppression must contain at least one location "
1440 "line which is not \"...\"");
1443 // Copy tmp_callers[] into supp->callers[]
1444 supp
->n_callers
= i
;
1445 supp
->callers
= VG_(malloc
)("errormgr.losf.4", i
* sizeof(SuppLoc
));
1446 for (i
= 0; i
< supp
->n_callers
; i
++) {
1447 supp
->callers
[i
] = tmp_callers
[i
];
1450 supp
->next
= suppressions
;
1451 suppressions
= supp
;
1459 VG_(printf_xml
)("</valgrindoutput>\n");
1460 VG_(umsg
)("FATAL: in suppressions file \"%s\" near line %d:\n",
1462 VG_(umsg
)(" %s\n", err_str
);
1465 VG_(umsg
)("exiting now.\n");
1472 void VG_(load_suppressions
) ( void )
1475 suppressions
= NULL
;
1476 for (i
= 0; i
< VG_(sizeXA
)(VG_(clo_suppressions
)); i
++) {
1477 if (VG_(clo_verbosity
) > 1) {
1478 VG_(dmsg
)("Reading suppressions file: %s\n",
1479 *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
), i
));
1481 load_one_suppressions_file( i
);
1486 /*------------------------------------------------------------*/
1487 /*--- Matching errors to suppressions ---*/
1488 /*------------------------------------------------------------*/
1490 /* Parameterising functions for the use of VG_(generic_match) in
1491 suppression-vs-error matching. The suppression frames (SuppLoc)
1492 play the role of 'pattern'-element, and the error frames (IPs,
1493 hence simply Addrs) play the role of 'input'. In short then, we're
1494 matching a sequence of Addrs against a pattern composed of a
1495 sequence of SuppLocs.
1497 static Bool
supploc_IsStar ( const void* supplocV
)
1499 const SuppLoc
* supploc
= supplocV
;
1500 return supploc
->ty
== DotDotDot
;
1503 static Bool
supploc_IsQuery ( const void* supplocV
)
1505 return False
; /* there's no '?' equivalent in the supp syntax */
1508 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1509 needed to match an error with the suppression patterns.
1510 The matching between an IP and a suppression pattern is done either
1511 with the IP function name or with the IP object name.
1512 First time the fun or obj name is needed for an IP member
1513 of a stack trace, it will be computed and stored in names.
1514 Also, if the IP corresponds to one or more inlined function calls,
1515 the inlined function names are expanded.
1516 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1517 allocations and the nr of debuginfo search. */
1520 StackTrace ips
; // stack trace we are lazily completing.
1521 UWord n_ips
; // nr of elements in ips.
1523 // VG_(generic_match) calls haveInputInpC to check
1524 // for the presence of an input element identified by ixInput
1525 // (i.e. a number that identifies the ixInput element of the
1526 // input sequence). It calls supp_pattEQinp to match this input
1527 // element with a pattern.
1528 // When inlining info is used to provide inlined function calls
1529 // in stacktraces, one IP in ips can be expanded in several
1530 // function names. So, each time input (or presence of input)
1531 // is requested by VG_(generic_match), we will expand
1532 // more IP of ips till we have expanded enough to reach the
1533 // input element requested (or we cannot expand anymore).
1535 UWord n_ips_expanded
;
1536 // n_ips_expanded maintains the nr of elements in ips that we have
1537 // already expanded.
1539 // n_expanded maintains the nr of elements resulting from the expansion
1540 // of the n_ips_expanded IPs. Without inlined function calls,
1541 // n_expanded == n_ips_expanded. With inlining info,
1542 // n_expanded >= n_ips_expanded.
1544 Int
* n_offsets_per_ip
;
1545 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1546 // obj_offsets resulting of the expansion of ips[i].
1547 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1548 // This array allows to retrieve the position in ips corresponding to
1551 // size (in elements) of fun_offsets and obj_offsets.
1552 // (fun|obj)_offsets are reallocated if more space is needed
1557 // fun_offsets[ixInput] is the offset in names where the
1558 // function name for the ixInput element of the input sequence
1559 // can be found. As one IP of ips can be expanded in several
1560 // function calls due to inlined function calls, we can have more
1561 // elements in fun_offsets than in ips.
1562 // An offset -1 means the function name has not yet been computed.
1564 // Similarly, obj_offsets[ixInput] gives the offset for the
1565 // object name for ips[ixInput]
1566 // (-1 meaning object name not yet been computed).
1568 // All function names and object names will be concatenated
1569 // in names. names is reallocated on demand.
1571 Int names_szB
; // size of names.
1572 Int names_free
; // offset first free HChar in names.
1574 IPtoFunOrObjCompleter
;
1576 static void pp_ip2fo (const IPtoFunOrObjCompleter
* ip2fo
)
1581 VG_(printf
)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1582 ip2fo
->n_ips
, ip2fo
->n_ips_expanded
, ip2fo
->n_expanded
);
1583 for (i
= 0; i
< ip2fo
->n_ips_expanded
; i
++) {
1585 for (j
= 0; j
< i
; j
++)
1586 o
+= ip2fo
->n_offsets_per_ip
[j
];
1587 VG_(printf
)("ips %d 0x08%lx offset [%d,%d] ",
1589 o
, o
+ip2fo
->n_offsets_per_ip
[i
]-1);
1590 for (j
= 0; j
< ip2fo
->n_offsets_per_ip
[i
]; j
++) {
1591 VG_(printf
)("%sfun:%s obj:%s\n",
1593 ip2fo
->fun_offsets
[o
+j
] == -1 ?
1594 "<not expanded>" : &ip2fo
->names
[ip2fo
->fun_offsets
[o
+j
]],
1595 ip2fo
->obj_offsets
[o
+j
] == -1 ?
1596 "<not expanded>" : &ip2fo
->names
[ip2fo
->obj_offsets
[o
+j
]]);
1601 /* free the memory in ip2fo.
1602 At debuglog 4, su (or NULL) will be used to show the matching
1603 (or non matching) with ip2fo. */
1604 static void clearIPtoFunOrObjCompleter ( const Supp
*su
,
1605 IPtoFunOrObjCompleter
* ip2fo
)
1607 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4) {
1609 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1610 su
->clo_suppressions_i
);
1611 VG_(dmsg
)("errormgr matching end suppression %s %s:%d matched:\n",
1616 VG_(dmsg
)("errormgr matching end no suppression matched:\n");
1617 VG_(pp_StackTrace
) (ip2fo
->ips
, ip2fo
->n_ips
);
1620 if (ip2fo
->n_offsets_per_ip
) VG_(free
)(ip2fo
->n_offsets_per_ip
);
1621 if (ip2fo
->fun_offsets
) VG_(free
)(ip2fo
->fun_offsets
);
1622 if (ip2fo
->obj_offsets
) VG_(free
)(ip2fo
->obj_offsets
);
1623 if (ip2fo
->names
) VG_(free
)(ip2fo
->names
);
1626 /* Grow ip2fo->names to ensure we have NEEDED characters available
1627 in ip2fo->names and returns a pointer to the first free char. */
1628 static HChar
* grow_names(IPtoFunOrObjCompleter
* ip2fo
, SizeT needed
)
1630 if (ip2fo
->names_szB
1631 < ip2fo
->names_free
+ needed
) {
1632 if (needed
< ERRTXT_LEN
) needed
= ERRTXT_LEN
;
1635 = VG_(realloc
)("foc_names",
1637 ip2fo
->names_szB
+ needed
);
1638 ip2fo
->names_szB
+= needed
;
1640 return ip2fo
->names
+ ip2fo
->names_free
;
1643 /* foComplete returns the function name or object name for ixInput.
1644 If needFun, returns the function name for this input
1645 else returns the object name for this input.
1646 The function name or object name will be computed and added in
1647 names if not yet done. */
1648 static HChar
* foComplete(IPtoFunOrObjCompleter
* ip2fo
,
1649 Int ixInput
, Bool needFun
)
1651 vg_assert (ixInput
< ip2fo
->n_expanded
);
1652 vg_assert (VG_(clo_read_inline_info
) || ixInput
< ip2fo
->n_ips
);
1654 // ptr to the offset array for function offsets (if needFun)
1655 // or object offsets (if !needFun).
1658 offsets
= &ip2fo
->fun_offsets
;
1660 offsets
= &ip2fo
->obj_offsets
;
1662 // Complete Fun name or Obj name for IP if not yet done.
1663 if ((*offsets
)[ixInput
] == -1) {
1664 const HChar
* caller
;
1666 (*offsets
)[ixInput
] = ip2fo
->names_free
;
1667 if (DEBUG_ERRORMGR
) VG_(printf
)("marking %s ixInput %d offset %d\n",
1668 needFun
? "fun" : "obj",
1669 ixInput
, ip2fo
->names_free
);
1671 // With inline info, fn names must have been completed already.
1672 vg_assert (!VG_(clo_read_inline_info
));
1673 /* Get the function name into 'caller_name', or "???"
1675 // Nb: C++-mangled names are used in suppressions. Do, though,
1676 // Z-demangle them, since otherwise it's possible to wind
1677 // up comparing "malloc" in the suppression against
1678 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1679 // two of them need to be made to match.
1680 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->ips
[ixInput
],
1685 /* Get the object name into 'caller_name', or "???"
1688 UWord last_expand_pos_ips
= 0;
1691 /* First get the pos in ips corresponding to ixInput */
1692 for (pos_ips
= 0; pos_ips
< ip2fo
->n_expanded
; pos_ips
++) {
1693 last_expand_pos_ips
+= ip2fo
->n_offsets_per_ip
[pos_ips
];
1694 if (ixInput
< last_expand_pos_ips
)
1697 /* pos_ips is the position in ips corresponding to ixInput.
1698 last_expand_pos_ips is the last offset in fun/obj where
1699 ips[pos_ips] has been expanded. */
1701 if (!VG_(get_objname
)(ip2fo
->ips
[pos_ips
], &caller
))
1704 // Have all inlined calls pointing at this object name
1705 for (i
= last_expand_pos_ips
- ip2fo
->n_offsets_per_ip
[pos_ips
] + 1;
1706 i
< last_expand_pos_ips
;
1708 ip2fo
->obj_offsets
[i
] = ip2fo
->names_free
;
1710 VG_(printf
) (" set obj_offset %lu to %d\n",
1711 i
, ip2fo
->names_free
);
1714 SizeT caller_len
= VG_(strlen
)(caller
);
1715 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1716 VG_(strcpy
)(caller_name
, caller
);
1717 ip2fo
->names_free
+= caller_len
+ 1;
1718 if (DEBUG_ERRORMGR
) pp_ip2fo(ip2fo
);
1721 return ip2fo
->names
+ (*offsets
)[ixInput
];
1724 // Grow fun and obj _offsets arrays to have at least n_req elements.
1725 // Ensure n_offsets_per_ip is allocated.
1726 static void grow_offsets(IPtoFunOrObjCompleter
* ip2fo
, Int n_req
)
1730 // n_offsets_per_ip must always have the size of the ips array
1731 if (ip2fo
->n_offsets_per_ip
== NULL
) {
1732 ip2fo
->n_offsets_per_ip
= VG_(malloc
)("grow_offsets",
1733 ip2fo
->n_ips
* sizeof(Int
));
1734 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1735 ip2fo
->n_offsets_per_ip
[i
] = 0;
1738 if (ip2fo
->sz_offsets
>= n_req
)
1741 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1742 // elements and at least a few more elements than the current size.
1743 if (n_req
< ip2fo
->n_ips
)
1744 n_req
= ip2fo
->n_ips
;
1745 if (n_req
< ip2fo
->sz_offsets
+ 5)
1746 n_req
= ip2fo
->sz_offsets
+ 5;
1748 ip2fo
->fun_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->fun_offsets
,
1749 n_req
* sizeof(Int
));
1750 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1751 ip2fo
->fun_offsets
[i
] = -1;
1753 ip2fo
->obj_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->obj_offsets
,
1754 n_req
* sizeof(Int
));
1755 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1756 ip2fo
->obj_offsets
[i
] = -1;
1758 ip2fo
->sz_offsets
= n_req
;
1761 // Expands more IPs from ip2fo->ips.
1762 static void expandInput (IPtoFunOrObjCompleter
* ip2fo
, UWord ixInput
)
1764 while (ip2fo
->n_ips_expanded
< ip2fo
->n_ips
1765 && ip2fo
->n_expanded
<= ixInput
) {
1766 if (VG_(clo_read_inline_info
)) {
1767 // Expand one more IP in one or more calls.
1768 const Addr IP
= ip2fo
->ips
[ip2fo
->n_ips_expanded
];
1771 iipc
= VG_(new_IIPC
)(IP
);
1772 // The only thing we really need is the nr of inlined fn calls
1773 // corresponding to the IP we will expand.
1774 // However, computing this is mostly the same as finding
1775 // the function name. So, let's directly complete the function name.
1777 const HChar
*caller
;
1778 grow_offsets(ip2fo
, ip2fo
->n_expanded
+1);
1779 ip2fo
->fun_offsets
[ip2fo
->n_expanded
] = ip2fo
->names_free
;
1780 if (!VG_(get_fnname_no_cxx_demangle
)(IP
,
1784 SizeT caller_len
= VG_(strlen
)(caller
);
1785 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1786 VG_(strcpy
)(caller_name
, caller
);
1787 ip2fo
->names_free
+= caller_len
+ 1;
1788 ip2fo
->n_expanded
++;
1789 ip2fo
->n_offsets_per_ip
[ip2fo
->n_ips_expanded
]++;
1790 } while (VG_(next_IIPC
)(iipc
));
1791 ip2fo
->n_ips_expanded
++;
1792 VG_(delete_IIPC
) (iipc
);
1794 // Without inlined fn call info, expansion simply
1795 // consists in allocating enough elements in (fun|obj)_offsets.
1796 // The function or object names themselves will be completed
1799 grow_offsets(ip2fo
, ip2fo
->n_ips
);
1800 ip2fo
->n_ips_expanded
= ip2fo
->n_ips
;
1801 ip2fo
->n_expanded
= ip2fo
->n_ips
;
1802 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1803 ip2fo
->n_offsets_per_ip
[i
] = 1;
1808 static Bool
haveInputInpC (void* inputCompleter
, UWord ixInput
)
1810 IPtoFunOrObjCompleter
* ip2fo
= inputCompleter
;
1811 expandInput(ip2fo
, ixInput
);
1812 return ixInput
< ip2fo
->n_expanded
;
1815 static Bool
supp_pattEQinp ( const void* supplocV
, const void* addrV
,
1816 void* inputCompleter
, UWord ixInput
)
1818 const SuppLoc
* supploc
= supplocV
; /* PATTERN */
1819 IPtoFunOrObjCompleter
* ip2fo
= inputCompleter
;
1820 HChar
* funobj_name
; // Fun or Obj name.
1823 expandInput(ip2fo
, ixInput
);
1824 vg_assert(ixInput
< ip2fo
->n_expanded
);
1826 /* So, does this IP address match this suppression-line? */
1827 switch (supploc
->ty
) {
1829 /* supp_pattEQinp is a callback from VG_(generic_match). As
1830 per the spec thereof (see include/pub_tool_seqmatch.h), we
1831 should never get called with a pattern value for which the
1832 _IsStar or _IsQuery function would return True. Hence
1833 this can't happen. */
1836 funobj_name
= foComplete(ip2fo
, ixInput
, False
/*needFun*/);
1839 funobj_name
= foComplete(ip2fo
, ixInput
, True
/*needFun*/);
1845 /* So now we have the function or object name in funobj_name, and
1846 the pattern (at the character level) to match against is in
1847 supploc->name. Hence (and leading to a re-entrant call of
1848 VG_(generic_match) if there is a wildcard character): */
1849 if (supploc
->name_is_simple_str
)
1850 ret
= VG_(strcmp
) (supploc
->name
, funobj_name
) == 0;
1852 ret
= VG_(string_match
)(supploc
->name
, funobj_name
);
1854 VG_(printf
) ("supp_pattEQinp %s patt %s ixUnput %lu value:%s match:%s\n",
1855 supploc
->ty
== FunName
? "fun" : "obj",
1856 supploc
->name
, ixInput
, funobj_name
,
1857 ret
? "yes" : "no");
1861 /////////////////////////////////////////////////////
1863 static Bool
supp_matches_callers(IPtoFunOrObjCompleter
* ip2fo
,
1866 /* Unwrap the args and set up the correct parameterisation of
1867 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1869 /* note, StackTrace ip2fo->ips === Addr* */
1870 SuppLoc
* supps
= su
->callers
;
1871 UWord n_supps
= su
->n_callers
;
1872 UWord szbPatt
= sizeof(SuppLoc
);
1873 Bool matchAll
= False
; /* we just want to match a prefix */
1874 if (DEBUG_ERRORMGR
) {
1875 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1876 su
->clo_suppressions_i
);
1877 VG_(dmsg
)(" errormgr Checking match with %s %s:%d\n",
1885 /*PATT*/supps
, szbPatt
, n_supps
, 0/*initial ixPatt*/,
1887 NULL
, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
1888 0/*initial ixInput*/,
1889 supploc_IsStar
, supploc_IsQuery
, supp_pattEQinp
,
1890 ip2fo
, haveInputInpC
1894 /////////////////////////////////////////////////////
1897 Bool
supp_matches_error(const Supp
* su
, const Error
* err
)
1899 switch (su
->skind
) {
1900 //(example code, see comment on CoreSuppKind above)
1902 // return (err->ekind == ThreadErr);
1904 if (VG_(needs
).tool_errors
) {
1905 return VG_TDICT_CALL(tool_error_matches_suppression
, err
, su
);
1908 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
1909 "probably needs to be set.\n",
1911 VG_(core_panic
)("unhandled suppression type");
1916 /////////////////////////////////////////////////////
1918 /* Does an error context match a suppression? ie is this a suppressible
1919 error? If so, return a pointer to the Supp record, otherwise NULL.
1920 Tries to minimise the number of symbol searches since they are expensive.
1922 static Supp
* is_suppressible_error ( const Error
* err
)
1927 IPtoFunOrObjCompleter ip2fo
;
1928 /* Conceptually, ip2fo contains an array of function names and an array of
1929 object names, corresponding to the array of IP of err->where.
1930 These names are just computed 'on demand' (so once maximum),
1931 then stored (efficiently, avoiding too many allocs) in ip2fo to be
1932 re-usable for the matching of the same IP with the next suppression
1935 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
1936 of its arguments. It will then pass it to the function
1937 supp_pattEQinp which will then lazily complete the IP function name or
1938 object name inside ip2fo. Next time the fun or obj name for the same
1939 IP is needed (i.e. for the matching with the next suppr pattern), then
1940 the fun or obj name will not be searched again in the debug info. */
1942 /* stats gathering */
1943 em_supplist_searches
++;
1945 /* Prepare the lazy input completer. */
1946 ip2fo
.ips
= VG_(get_ExeContext_StackTrace
)(err
->where
);
1947 ip2fo
.n_ips
= VG_(get_ExeContext_n_ips
)(err
->where
);
1948 ip2fo
.n_ips_expanded
= 0;
1949 ip2fo
.n_expanded
= 0;
1950 ip2fo
.sz_offsets
= 0;
1951 ip2fo
.n_offsets_per_ip
= NULL
;
1952 ip2fo
.fun_offsets
= NULL
;
1953 ip2fo
.obj_offsets
= NULL
;
1955 ip2fo
.names_szB
= 0;
1956 ip2fo
.names_free
= 0;
1958 /* See if the error context matches any suppression. */
1959 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4)
1960 VG_(dmsg
)("errormgr matching begin\n");
1962 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
1964 if (supp_matches_error(su
, err
)
1965 && supp_matches_callers(&ip2fo
, su
)) {
1967 /* Inform the tool that err is suppressed by su. */
1968 (void)VG_TDICT_CALL(tool_update_extra_suppression_use
, err
, su
);
1969 /* Move this entry to the head of the list
1970 in the hope of making future searches cheaper. */
1972 vg_assert(su_prev
->next
== su
);
1973 su_prev
->next
= su
->next
;
1974 su
->next
= suppressions
;
1977 clearIPtoFunOrObjCompleter(su
, &ip2fo
);
1982 clearIPtoFunOrObjCompleter(NULL
, &ip2fo
);
1983 return NULL
; /* no matches */
1986 /* Show accumulated error-list and suppression-list search stats.
1988 void VG_(print_errormgr_stats
) ( void )
1991 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
1992 em_supplist_searches
, em_supplist_cmps
1995 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
1996 em_errlist_searches
, em_errlist_cmps
2000 /*--------------------------------------------------------------------*/
2002 /*--------------------------------------------------------------------*/