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-2015 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
, Addr ip
, void* uu_opaque
)
327 InlIPCursor
* iipc
= VG_(new_IIPC
)(ip
);
329 if ( VG_(get_fnname_no_cxx_demangle
) (ip
, &buf
, iipc
) ) {
330 VG_(printf_xml
)(" <sframe> <fun>%pS</fun> </sframe>\n", buf
);
332 if ( VG_(get_objname
)(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
, Addr ip
, void* textV
)
344 XArray
* /* of HChar */ text
= (XArray
*)textV
;
345 InlIPCursor
* iipc
= VG_(new_IIPC
)(ip
);
347 if ( VG_(get_fnname_no_cxx_demangle
) (ip
, &buf
, iipc
) ) {
348 VG_(xaprintf
)(text
, " fun:%s\n", buf
);
350 if ( VG_(get_objname
)(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
,
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
,
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 text-mode actions on error, that is, immediately after an error
515 is printed. These are:
516 * possibly, call the GDB server
517 * possibly, generate a suppression.
518 Note this should not be called in XML mode!
521 void do_actions_on_error(const Error
* err
, Bool allow_db_attach
)
523 Bool still_noisy
= True
;
525 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
526 if (VG_(clo_vgdb
) != Vg_VgdbNo
528 && VG_(dyn_vgdb_error
) <= n_errs_shown
) {
529 VG_(umsg
)("(action on error) vgdb me ... \n");
530 VG_(gdbserver
)( err
->tid
);
531 VG_(umsg
)("Continuing ...\n");
534 /* Or maybe we want to generate the error's suppression? */
535 if (VG_(clo_gen_suppressions
) == 2
536 || (VG_(clo_gen_suppressions
) == 1
537 && VG_(is_action_requested
)( "Print suppression", &still_noisy
))
539 gen_suppression(err
);
541 if (VG_(clo_gen_suppressions
) == 1 && !still_noisy
)
542 VG_(clo_gen_suppressions
) = 0;
546 /* Prints an error. Not entirely simple because of the differences
547 between XML and text mode output.
551 * calls the tool's pre-show method, so the tool can create any
552 preamble ahead of the message, if it wants.
554 * prints the opening tag, and the <unique> and <tid> fields
556 * prints the tool-specific parts of the message
558 * if suppression generation is required, a suppression
564 * calls the tool's pre-show method, so the tool can create any
565 preamble ahead of the message, if it wants.
567 * prints the tool-specific parts of the message
569 * calls do_actions_on_error. This optionally does a gdbserver call
570 and optionally prints a suppression; both of these may require user input.
572 static void pp_Error ( const Error
* err
, Bool allow_db_attach
, Bool xml
)
574 /* If this fails, you probably specified your tool's method
575 dictionary incorrectly. */
576 vg_assert(VG_(needs
).tool_errors
);
580 /* Ensure that suppression generation is either completely
581 enabled or completely disabled; either way, we won't require
582 any user input. m_main.process_cmd_line_options should
583 ensure the asserted condition holds. */
584 vg_assert( VG_(clo_gen_suppressions
) == 0 /* disabled */
585 || VG_(clo_gen_suppressions
) == 2 /* for all errors */ );
587 /* Pre-show it to the tool */
588 VG_TDICT_CALL( tool_before_pp_Error
, err
);
590 /* standard preamble */
591 VG_(printf_xml
)("<error>\n");
592 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
593 VG_(printf_xml
)(" <tid>%u</tid>\n", err
->tid
);
594 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
595 if (tst
->thread_name
) {
596 VG_(printf_xml
)(" <threadname>%s</threadname>\n", tst
->thread_name
);
599 /* actually print it */
600 VG_TDICT_CALL( tool_pp_Error
, err
);
602 if (VG_(clo_gen_suppressions
) > 0)
603 gen_suppression(err
);
606 VG_(printf_xml
)("</error>\n");
607 VG_(printf_xml
)("\n");
611 if (VG_(clo_error_markers
)[0])
612 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[0]);
613 VG_TDICT_CALL( tool_before_pp_Error
, err
);
615 if (VG_(tdict
).tool_show_ThreadIDs_for_errors
616 && err
->tid
> 0 && err
->tid
!= last_tid_printed
) {
617 ThreadState
* tst
= VG_(get_ThreadState
)(err
->tid
);
618 if (tst
->thread_name
) {
619 VG_(umsg
)("Thread %u %s:\n", err
->tid
, tst
->thread_name
);
621 VG_(umsg
)("Thread %u:\n", err
->tid
);
623 last_tid_printed
= err
->tid
;
626 VG_TDICT_CALL( tool_pp_Error
, err
);
628 if (VG_(clo_error_markers
)[1])
629 VG_(umsg
)("%s\n", VG_(clo_error_markers
)[1]);
633 do_actions_on_error(err
, allow_db_attach
);
637 /* Construct an error */
639 void construct_error ( Error
* err
, ThreadId tid
, ErrorKind ekind
, Addr a
,
640 const HChar
* s
, void* extra
, ExeContext
* where
)
642 /* DO NOT MAKE unique_counter NON-STATIC */
643 static UInt unique_counter
= 0;
645 vg_assert(tid
< VG_N_THREADS
);
647 /* Core-only parts */
648 err
->unique
= unique_counter
++;
654 err
->where
= VG_(record_ExeContext
)( tid
, 0 );
658 /* Tool-relevant parts */
665 vg_assert( tid
< VG_N_THREADS
);
670 /* Top-level entry point to the error management subsystem.
671 All detected errors are notified here; this routine decides if/when the
672 user should see the error. */
673 void VG_(maybe_record_error
) ( ThreadId tid
,
674 ErrorKind ekind
, Addr a
,
675 const HChar
* s
, void* extra
)
681 VgRes exe_res
= Vg_MedRes
;
682 static Bool stopping_message
= False
;
683 static Bool slowdown_message
= False
;
685 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
686 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
687 have been found, just refuse to collect any more. This stops
688 the burden of the error-management system becoming excessive in
689 extremely buggy programs, although it does make it pretty
690 pointless to continue the Valgrind run after this point. */
691 if (VG_(clo_error_limit
)
692 && (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
693 || n_errs_found
>= M_COLLECT_NO_ERRORS_AFTER_FOUND
)
695 if (!stopping_message
) {
698 if (n_errs_shown
>= M_COLLECT_NO_ERRORS_AFTER_SHOWN
) {
700 "More than %d different errors detected. "
701 "I'm not reporting any more.\n",
702 M_COLLECT_NO_ERRORS_AFTER_SHOWN
);
705 "More than %d total errors detected. "
706 "I'm not reporting any more.\n",
707 M_COLLECT_NO_ERRORS_AFTER_FOUND
);
710 VG_(umsg
)("Final error counts will be inaccurate. "
711 "Go fix your program!\n");
712 VG_(umsg
)("Rerun with --error-limit=no to disable "
713 "this cutoff. Note\n");
714 VG_(umsg
)("that errors may occur in your program without "
715 "prior warning from\n");
716 VG_(umsg
)("Valgrind, because errors are no longer "
717 "being displayed.\n");
719 stopping_message
= True
;
724 /* Ignore it if error acquisition is disabled for this thread. */
725 { ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
726 if (tst
->err_disablement_level
> 0)
730 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
731 been found, be much more conservative about collecting new
733 if (n_errs_shown
>= M_COLLECT_ERRORS_SLOWLY_AFTER
736 if (!slowdown_message
) {
738 VG_(umsg
)("More than %d errors detected. Subsequent errors\n",
739 M_COLLECT_ERRORS_SLOWLY_AFTER
);
740 VG_(umsg
)("will still be recorded, but in less "
741 "detail than before.\n");
742 slowdown_message
= True
;
746 /* Build ourselves the error */
747 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, NULL
);
749 /* First, see if we've got an error record matching this one. */
750 em_errlist_searches
++;
755 if (eq_Error(exe_res
, p
, &err
)) {
758 if (p
->supp
!= NULL
) {
759 /* Deal correctly with suppressed errors. */
766 /* Move p to the front of the list so that future searches
767 for it are faster. It also allows to print the last
768 error (see VG_(show_last_error). */
769 if (p_prev
!= NULL
) {
770 vg_assert(p_prev
->next
== p
);
771 p_prev
->next
= p
->next
;
782 /* Didn't see it. Copy and add. */
784 /* OK, we're really going to collect it. The context is on the stack and
785 will disappear shortly, so we must copy it. First do the main
788 Then VG_(tdict).tool_update_extra can update the 'extra' part. This
789 is for when there are more details to fill in which take time to work
790 out but don't affect our earlier decision to include the error -- by
791 postponing those details until now, we avoid the extra work in the
792 case where we ignore the error. Ugly.
794 Then, if there is an 'extra' part, copy it too, using the size that
795 VG_(tdict).tool_update_extra returned. Also allow for people using
796 the void* extra field for a scalar value like an integer.
800 p
= VG_(malloc
)("errormgr.mre.1", sizeof(Error
));
805 //(example code, see comment on CoreSuppKind above)
807 // vg_assert(VG_(needs).core_errors);
808 // extra_size = <something>
811 vg_assert(VG_(needs
).tool_errors
);
812 extra_size
= VG_TDICT_CALL(tool_update_extra
, p
);
816 /* copy the error string, if there is one.
817 note: if we would have many errors with big strings, using a
818 DedupPoolAlloc for these strings will avoid duplicating
819 such string in each error using it. */
820 if (NULL
!= p
->string
) {
821 p
->string
= VG_(strdup
)("errormgr.mre.2", p
->string
);
824 /* copy block pointed to by 'extra', if there is one */
825 if (NULL
!= p
->extra
&& 0 != extra_size
) {
826 void* new_extra
= VG_(malloc
)("errormgr.mre.3", extra_size
);
827 VG_(memcpy
)(new_extra
, p
->extra
, extra_size
);
828 p
->extra
= new_extra
;
832 p
->supp
= is_suppressible_error(&err
);
834 if (p
->supp
== NULL
) {
839 /* Actually show the error; more complex than you might think. */
840 pp_Error( p
, /*allow_db_attach*/True
, VG_(clo_xml
) );
848 /* Second top-level entry point to the error management subsystem, for
849 errors that the tool wants to report immediately, eg. because they're
850 guaranteed to only happen once. This avoids all the recording and
851 comparing stuff. But they can be suppressed; returns True if it is
852 suppressed. Bool 'print_error' dictates whether to print the error.
853 Bool 'count_error' dictates whether to count the error in n_errs_found.
855 Bool
VG_(unique_error
) ( ThreadId tid
, ErrorKind ekind
, Addr a
, const HChar
* s
,
856 void* extra
, ExeContext
* where
, Bool print_error
,
857 Bool allow_db_attach
, Bool count_error
)
862 /* Ignore it if error acquisition is disabled for this thread. */
863 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
864 if (tst
->err_disablement_level
> 0)
865 return False
; /* ignored, not suppressed */
867 /* Build ourselves the error */
868 construct_error ( &err
, tid
, ekind
, a
, s
, extra
, where
);
870 /* Unless it's suppressed, we're going to show it. Don't need to make
871 a copy, because it's only temporary anyway.
873 Then update the 'extra' part with VG_(tdict).tool_update_extra),
874 because that can have an affect on whether it's suppressed. Ignore
875 the size return value of VG_(tdict).tool_update_extra, because we're
876 not copying 'extra'. Similarly, 's' is also not copied. */
877 (void)VG_TDICT_CALL(tool_update_extra
, &err
);
879 su
= is_suppressible_error(&err
);
889 /* Actually show the error; more complex than you might think. */
890 pp_Error(&err
, allow_db_attach
, VG_(clo_xml
));
905 /*------------------------------------------------------------*/
906 /*--- Exported fns ---*/
907 /*------------------------------------------------------------*/
909 /* Show the used suppressions. Returns False if no suppression
911 static Bool
show_used_suppressions ( void )
917 VG_(printf_xml
)("<suppcounts>\n");
920 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
924 VG_(printf_xml
)( " <pair>\n"
925 " <count>%d</count>\n"
926 " <name>%pS</name>\n"
928 su
->count
, su
->sname
);
933 // blank line before the first shown suppression, if any
939 xtra
= VG_(realloc
)("errormgr.sus.1", xtra
, xtra_size
);
940 num_written
= VG_TDICT_CALL(tool_print_extra_suppression_use
,
941 su
, xtra
, xtra_size
);
942 } while (num_written
== xtra_size
); // resize buffer and retry
944 // Ensure buffer is properly terminated
945 vg_assert(xtra
[num_written
] == '\0');
947 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
948 su
->clo_suppressions_i
);
949 VG_(dmsg
)("used_suppression: %6d %s %s:%d%s%s\n", su
->count
, su
->sname
,
952 num_written
? " " : "", xtra
);
959 VG_(printf_xml
)("</suppcounts>\n");
964 /* Show all the errors that occurred, and possibly also the
965 suppressions used. */
966 void VG_(show_all_errors
) ( Int verbosity
, Bool xml
)
975 /* If we're printing XML, just show the suppressions and stop. */
977 (void)show_used_suppressions();
981 /* We only get here if not printing XML. */
982 VG_(umsg
)("ERROR SUMMARY: "
983 "%u errors from %u contexts (suppressed: %u from %u)\n",
984 n_errs_found
, n_err_contexts
,
985 n_errs_suppressed
, n_supp_contexts
);
990 // We do the following only at -v or above, and only in non-XML
993 /* Print the contexts in order of increasing error count.
994 Once an error is shown, we add a huge value to its count to filter it
996 After having shown all errors, we reset count to the original value. */
997 for (i
= 0; i
< n_err_contexts
; i
++) {
998 n_min
= (1 << 30) - 1;
1000 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1001 if (p
->supp
!= NULL
) continue;
1002 if (p
->count
< n_min
) {
1007 // XXX: this isn't right. See bug 203651.
1008 if (p_min
== NULL
) continue; //VG_(core_panic)("show_all_errors()");
1011 VG_(umsg
)("%d errors in context %d of %u:\n",
1012 p_min
->count
, i
+1, n_err_contexts
);
1013 pp_Error( p_min
, False
/*allow_db_attach*/, False
/* xml */ );
1015 // We're not printing XML -- we'd have exited above if so.
1018 if ((i
+1 == VG_(clo_dump_error
))) {
1019 StackTrace ips
= VG_(get_ExeContext_StackTrace
)(p_min
->where
);
1020 VG_(translate
) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
1021 ips
[0], /*debugging*/True
, 0xFE/*verbosity*/,
1023 /*allow redir?*/True
);
1026 p_min
->count
= p_min
->count
+ (1 << 30);
1029 /* reset the counts, otherwise a 2nd call does not show anything anymore */
1030 for (p
= errors
; p
!= NULL
; p
= p
->next
) {
1031 if (p
->count
>= (1 << 30))
1032 p
->count
= p
->count
- (1 << 30);
1036 any_supp
= show_used_suppressions();
1040 // reprint this, so users don't have to scroll way up to find
1041 // the first printing
1042 VG_(umsg
)("ERROR SUMMARY: "
1043 "%u errors from %u contexts (suppressed: %u from %u)\n",
1044 n_errs_found
, n_err_contexts
, n_errs_suppressed
,
1048 void VG_(show_last_error
) ( void )
1050 if (n_err_contexts
== 0) {
1051 VG_(umsg
)("No errors yet\n");
1055 pp_Error( errors
, False
/*allow_db_attach*/, False
/*xml*/ );
1059 /* Show occurrence counts of all errors, in XML form. */
1060 void VG_(show_error_counts_as_XML
) ( void )
1063 VG_(printf_xml
)("<errorcounts>\n");
1064 for (err
= errors
; err
!= NULL
; err
= err
->next
) {
1065 if (err
->supp
!= NULL
)
1067 if (err
->count
<= 0)
1069 VG_(printf_xml
)(" <pair>\n");
1070 VG_(printf_xml
)(" <count>%d</count>\n", err
->count
);
1071 VG_(printf_xml
)(" <unique>0x%x</unique>\n", err
->unique
);
1072 VG_(printf_xml
)(" </pair>\n");
1074 VG_(printf_xml
)("</errorcounts>\n");
1075 VG_(printf_xml
)("\n");
1079 /*------------------------------------------------------------*/
1080 /*--- Suppression parsing ---*/
1081 /*------------------------------------------------------------*/
1083 /* Get the next char from fd into *out_buf. Returns 1 if success,
1084 0 if eof or < 0 if error. */
1086 static Int
get_char ( Int fd
, HChar
* out_buf
)
1089 static HChar buf
[256];
1090 static Int buf_size
= 0;
1091 static Int buf_used
= 0;
1092 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1093 vg_assert(buf_used
>= 0 && buf_used
<= buf_size
);
1094 if (buf_used
== buf_size
) {
1095 r
= VG_(read
)(fd
, buf
, sizeof buf
);
1096 if (r
< 0) return r
; /* read failed */
1097 vg_assert(r
>= 0 && r
<= sizeof buf
);
1103 vg_assert(buf_size
>= 0 && buf_size
<= sizeof buf
);
1104 vg_assert(buf_used
>= 0 && buf_used
< buf_size
);
1105 *out_buf
= buf
[buf_used
];
1110 // Get a non blank non comment line.
1111 // Returns True if eof.
1112 static Bool
get_nbnc_line ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1114 HChar
* buf
= *bufpp
;
1115 SizeT nBuf
= *nBufp
;
1119 vg_assert(lineno
); // lineno needed to correctly track line numbers.
1123 /* First, read until a non-blank char appears. */
1125 n
= get_char(fd
, &ch
);
1126 if (n
== 1 && !VG_(isspace
)(ch
)) break;
1127 if (n
== 1 && ch
== '\n')
1129 if (n
<= 0) return True
;
1132 /* Now, read the line into buf. */
1134 buf
[i
++] = ch
; buf
[i
] = 0;
1136 n
= get_char(fd
, &ch
);
1137 if (n
<= 0) return False
; /* the next call will return True */
1140 if (ch
== '\n') break;
1141 if (i
> 0 && i
== nBuf
-1) {
1142 *nBufp
= nBuf
= nBuf
* 2;
1143 #define RIDICULOUS 100000
1144 vg_assert2(nBuf
< RIDICULOUS
, // Just a sanity check, really.
1145 "VG_(get_line): line longer than %d chars, aborting\n",
1147 *bufpp
= buf
= VG_(realloc
)("errormgr.get_line.1", buf
, nBuf
);
1149 buf
[i
++] = ch
; buf
[i
] = 0;
1151 while (i
> 1 && VG_(isspace
)(buf
[i
-1])) {
1155 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf);
1156 /* Ok, we have a line. If a non-comment line, return.
1157 If a comment line, start all over again. */
1158 if (buf
[0] != '#') return False
;
1162 // True if buf starts with fun: or obj: or is ...
1163 static Bool
is_location_line (const HChar
* buf
)
1165 return VG_(strncmp
)(buf
, "fun:", 4) == 0
1166 || VG_(strncmp
)(buf
, "obj:", 4) == 0
1167 || VG_(strcmp
)(buf
, "...") == 0;
1170 Bool
VG_(get_line
) ( Int fd
, HChar
** bufpp
, SizeT
* nBufp
, Int
* lineno
)
1172 Bool eof
= get_nbnc_line (fd
, bufpp
, nBufp
, lineno
);
1177 if (is_location_line(*bufpp
))
1178 return True
; // Not a extra suppr line
1180 return False
; // A suppression extra line
1183 /* True if s contains no wildcard (?, *) characters. */
1184 static Bool
is_simple_str (const HChar
*s
)
1187 if (*s
== '?' || *s
== '*')
1194 /* buf contains the raw name of a caller, supposedly either
1195 fun:some_function_name or
1196 obj:some_object_name or
1198 Set p->ty and p->name accordingly.
1199 p->name is allocated and set to the string
1200 after the descriptor (fun: or obj:) part.
1201 Returns False if failed.
1203 static Bool
setLocationTy ( SuppLoc
* p
, const HChar
*buf
)
1205 if (VG_(strncmp
)(buf
, "fun:", 4) == 0) {
1206 p
->name
= VG_(strdup
)("errormgr.sLTy.1", buf
+4);
1207 p
->name_is_simple_str
= is_simple_str (p
->name
);
1211 if (VG_(strncmp
)(buf
, "obj:", 4) == 0) {
1212 p
->name
= VG_(strdup
)("errormgr.sLTy.2", buf
+4);
1213 p
->name_is_simple_str
= is_simple_str (p
->name
);
1217 if (VG_(strcmp
)(buf
, "...") == 0) {
1219 p
->name_is_simple_str
= False
;
1223 VG_(printf
)("location should be \"...\", or should start "
1224 "with \"fun:\" or \"obj:\"\n");
1229 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1230 static Bool
tool_name_present(const HChar
*name
, const HChar
*names
)
1233 HChar
*s
= NULL
; /* Shut gcc up */
1234 Int len
= VG_(strlen
)(name
);
1236 found
= (NULL
!= (s
= VG_(strstr
)(names
, name
)) &&
1237 (s
== names
|| *(s
-1) == ',') &&
1238 (*(s
+len
) == ',' || *(s
+len
) == '\0')
1244 /* Read suppressions from the file specified in
1245 VG_(clo_suppressions)[clo_suppressions_i]
1246 and place them in the suppressions list. If there's any difficulty
1247 doing this, just give up -- there's no point in trying to recover.
1249 static void load_one_suppressions_file ( Int clo_suppressions_i
)
1251 const HChar
* filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1252 clo_suppressions_i
);
1254 Int fd
, i
, j
, lineno
= 0;
1255 Bool got_a_location_line_read_by_tool
;
1258 HChar
* buf
= VG_(malloc
)("errormgr.losf.1", nBuf
);
1261 const HChar
* err_str
= NULL
;
1262 SuppLoc tmp_callers
[VG_DEEPEST_BACKTRACE
];
1264 // Check it's not a directory.
1265 if (VG_(is_dir
)( filename
)) {
1267 VG_(printf_xml
)("</valgrindoutput>\n");
1268 VG_(umsg
)("FATAL: suppressions file \"%s\" is a directory\n", filename
);
1272 // Open the suppression file.
1273 sres
= VG_(open
)( filename
, VKI_O_RDONLY
, 0 );
1274 if (sr_isError(sres
)) {
1276 VG_(printf_xml
)("</valgrindoutput>\n");
1277 VG_(umsg
)("FATAL: can't open suppressions file \"%s\"\n", filename
);
1282 # define BOMB(S) { err_str = S; goto syntax_error; }
1285 /* Assign and initialise the two suppression halves (core and tool) */
1287 supp
= VG_(malloc
)("errormgr.losf.1", sizeof(Supp
));
1290 // Initialise temporary reading-in buffer.
1291 for (i
= 0; i
< VG_DEEPEST_BACKTRACE
; i
++) {
1292 tmp_callers
[i
].ty
= NoName
;
1293 tmp_callers
[i
].name_is_simple_str
= False
;
1294 tmp_callers
[i
].name
= NULL
;
1297 supp
->string
= supp
->extra
= NULL
;
1299 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1305 if (!VG_STREQ(buf
, "{")) BOMB("expected '{' or end-of-file");
1307 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1309 if (eof
|| VG_STREQ(buf
, "}")) BOMB("unexpected '}'");
1311 supp
->sname
= VG_(strdup
)("errormgr.losf.2", buf
);
1312 supp
->clo_suppressions_i
= clo_suppressions_i
;
1313 supp
->sname_lineno
= lineno
;
1315 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1317 if (eof
) BOMB("unexpected end-of-file (expecting tool:suppr)");
1319 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1322 if (buf
[i
] == ':') break;
1323 if (buf
[i
] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1326 buf
[i
] = '\0'; /* Replace ':', splitting into two strings */
1328 tool_names
= & buf
[0];
1329 supp_name
= & buf
[i
+1];
1331 if (VG_(needs
).core_errors
&& tool_name_present("core", tool_names
))
1333 // A core suppression
1334 //(example code, see comment on CoreSuppKind above)
1335 //if (VG_STREQ(supp_name, "Thread"))
1336 // supp->skind = ThreadSupp;
1338 BOMB("unknown core suppression type");
1340 else if (VG_(needs
).tool_errors
&&
1341 tool_name_present(VG_(details
).name
, tool_names
))
1343 // A tool suppression
1344 if (VG_TDICT_CALL(tool_recognised_suppression
, supp_name
, supp
)) {
1345 /* Do nothing, function fills in supp->skind */
1347 BOMB("unknown tool suppression type");
1351 // Ignore rest of suppression
1353 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1354 if (eof
) BOMB("unexpected end-of-file (when skipping suppression)");
1355 if (VG_STREQ(buf
, "}"))
1358 VG_(free
)(supp
->sname
);
1364 // tool_read_extra_suppression_info might read lines
1365 // from fd till a location line.
1366 if (VG_(needs
).tool_errors
&&
1367 !VG_TDICT_CALL(tool_read_extra_suppression_info
,
1368 fd
, &buf
, &nBuf
, &lineno
, supp
))
1370 BOMB("bad or missing extra suppression info");
1373 got_a_location_line_read_by_tool
= buf
[0] != 0 && is_location_line(buf
);
1375 /* the main frame-descriptor reading loop */
1378 if (got_a_location_line_read_by_tool
) {
1379 got_a_location_line_read_by_tool
= False
;
1382 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1385 BOMB("unexpected end-of-file (when reading stack trace)");
1386 if (VG_STREQ(buf
, "}")) {
1390 BOMB("missing stack trace");
1393 if (i
== VG_DEEPEST_BACKTRACE
)
1394 BOMB("too many callers in stack trace");
1395 if (i
> 0 && i
>= VG_(clo_backtrace_size
))
1397 if (!setLocationTy(&(tmp_callers
[i
]), buf
))
1398 BOMB("location should be \"...\", or should start "
1399 "with \"fun:\" or \"obj:\"");
1403 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1404 // lines and grab the '}'.
1405 if (!VG_STREQ(buf
, "}")) {
1407 eof
= get_nbnc_line ( fd
, &buf
, &nBuf
, &lineno
);
1408 } while (!eof
&& !VG_STREQ(buf
, "}"));
1411 // Reject entries which are entirely composed of frame
1413 vg_assert(i
> 0); // guaranteed by frame-descriptor reading loop
1414 for (j
= 0; j
< i
; j
++) {
1415 if (tmp_callers
[j
].ty
== FunName
|| tmp_callers
[j
].ty
== ObjName
)
1417 vg_assert(tmp_callers
[j
].ty
== DotDotDot
);
1419 vg_assert(j
>= 0 && j
<= i
);
1421 // we didn't find any non-"..." entries
1422 BOMB("suppression must contain at least one location "
1423 "line which is not \"...\"");
1426 // Copy tmp_callers[] into supp->callers[]
1427 supp
->n_callers
= i
;
1428 supp
->callers
= VG_(malloc
)("errormgr.losf.4", i
* sizeof(SuppLoc
));
1429 for (i
= 0; i
< supp
->n_callers
; i
++) {
1430 supp
->callers
[i
] = tmp_callers
[i
];
1433 supp
->next
= suppressions
;
1434 suppressions
= supp
;
1442 VG_(printf_xml
)("</valgrindoutput>\n");
1443 VG_(umsg
)("FATAL: in suppressions file \"%s\" near line %d:\n",
1445 VG_(umsg
)(" %s\n", err_str
);
1448 VG_(umsg
)("exiting now.\n");
1455 void VG_(load_suppressions
) ( void )
1458 suppressions
= NULL
;
1459 for (i
= 0; i
< VG_(sizeXA
)(VG_(clo_suppressions
)); i
++) {
1460 if (VG_(clo_verbosity
) > 1) {
1461 VG_(dmsg
)("Reading suppressions file: %s\n",
1462 *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
), i
));
1464 load_one_suppressions_file( i
);
1469 /*------------------------------------------------------------*/
1470 /*--- Matching errors to suppressions ---*/
1471 /*------------------------------------------------------------*/
1473 /* Parameterising functions for the use of VG_(generic_match) in
1474 suppression-vs-error matching. The suppression frames (SuppLoc)
1475 play the role of 'pattern'-element, and the error frames (IPs,
1476 hence simply Addrs) play the role of 'input'. In short then, we're
1477 matching a sequence of Addrs against a pattern composed of a
1478 sequence of SuppLocs.
1480 static Bool
supploc_IsStar ( const void* supplocV
)
1482 const SuppLoc
* supploc
= supplocV
;
1483 return supploc
->ty
== DotDotDot
;
1486 static Bool
supploc_IsQuery ( const void* supplocV
)
1488 return False
; /* there's no '?' equivalent in the supp syntax */
1491 /* IPtoFunOrObjCompleter is a lazy completer of the IPs
1492 needed to match an error with the suppression patterns.
1493 The matching between an IP and a suppression pattern is done either
1494 with the IP function name or with the IP object name.
1495 First time the fun or obj name is needed for an IP member
1496 of a stack trace, it will be computed and stored in names.
1497 Also, if the IP corresponds to one or more inlined function calls,
1498 the inlined function names are expanded.
1499 The IPtoFunOrObjCompleter type is designed to minimise the nr of
1500 allocations and the nr of debuginfo search. */
1503 StackTrace ips
; // stack trace we are lazily completing.
1504 UWord n_ips
; // nr of elements in ips.
1506 // VG_(generic_match) calls haveInputInpC to check
1507 // for the presence of an input element identified by ixInput
1508 // (i.e. a number that identifies the ixInput element of the
1509 // input sequence). It calls supp_pattEQinp to match this input
1510 // element with a pattern.
1511 // When inlining info is used to provide inlined function calls
1512 // in stacktraces, one IP in ips can be expanded in several
1513 // function names. So, each time input (or presence of input)
1514 // is requested by VG_(generic_match), we will expand
1515 // more IP of ips till we have expanded enough to reach the
1516 // input element requested (or we cannot expand anymore).
1518 UWord n_ips_expanded
;
1519 // n_ips_expanded maintains the nr of elements in ips that we have
1520 // already expanded.
1522 // n_expanded maintains the nr of elements resulting from the expansion
1523 // of the n_ips_expanded IPs. Without inlined function calls,
1524 // n_expanded == n_ips_expanded. With inlining info,
1525 // n_expanded >= n_ips_expanded.
1527 Int
* n_offsets_per_ip
;
1528 // n_offsets_per_ip[i] gives the nr of offsets in fun_offsets and
1529 // obj_offsets resulting of the expansion of ips[i].
1530 // The sum of all n_expanded_per_ip must be equal to n_expanded.
1531 // This array allows to retrieve the position in ips corresponding to
1534 // size (in elements) of fun_offsets and obj_offsets.
1535 // (fun|obj)_offsets are reallocated if more space is needed
1540 // fun_offsets[ixInput] is the offset in names where the
1541 // function name for the ixInput element of the input sequence
1542 // can be found. As one IP of ips can be expanded in several
1543 // function calls due to inlined function calls, we can have more
1544 // elements in fun_offsets than in ips.
1545 // An offset -1 means the function name has not yet been computed.
1547 // Similarly, obj_offsets[ixInput] gives the offset for the
1548 // object name for ips[ixInput]
1549 // (-1 meaning object name not yet been computed).
1551 // All function names and object names will be concatenated
1552 // in names. names is reallocated on demand.
1554 Int names_szB
; // size of names.
1555 Int names_free
; // offset first free HChar in names.
1557 IPtoFunOrObjCompleter
;
1559 static void pp_ip2fo (const IPtoFunOrObjCompleter
* ip2fo
)
1564 VG_(printf
)("n_ips %lu n_ips_expanded %lu resulting in n_expanded %lu\n",
1565 ip2fo
->n_ips
, ip2fo
->n_ips_expanded
, ip2fo
->n_expanded
);
1566 for (i
= 0; i
< ip2fo
->n_ips_expanded
; i
++) {
1568 for (j
= 0; j
< i
; j
++)
1569 o
+= ip2fo
->n_offsets_per_ip
[j
];
1570 VG_(printf
)("ips %d 0x08%lx offset [%d,%d] ",
1572 o
, o
+ip2fo
->n_offsets_per_ip
[i
]-1);
1573 for (j
= 0; j
< ip2fo
->n_offsets_per_ip
[i
]; j
++) {
1574 VG_(printf
)("%sfun:%s obj:%s\n",
1576 ip2fo
->fun_offsets
[o
+j
] == -1 ?
1577 "<not expanded>" : &ip2fo
->names
[ip2fo
->fun_offsets
[o
+j
]],
1578 ip2fo
->obj_offsets
[o
+j
] == -1 ?
1579 "<not expanded>" : &ip2fo
->names
[ip2fo
->obj_offsets
[o
+j
]]);
1584 /* free the memory in ip2fo.
1585 At debuglog 4, su (or NULL) will be used to show the matching
1586 (or non matching) with ip2fo. */
1587 static void clearIPtoFunOrObjCompleter ( const Supp
*su
,
1588 IPtoFunOrObjCompleter
* ip2fo
)
1590 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4) {
1592 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1593 su
->clo_suppressions_i
);
1594 VG_(dmsg
)("errormgr matching end suppression %s %s:%d matched:\n",
1599 VG_(dmsg
)("errormgr matching end no suppression matched:\n");
1600 VG_(pp_StackTrace
) (ip2fo
->ips
, ip2fo
->n_ips
);
1603 if (ip2fo
->n_offsets_per_ip
) VG_(free
)(ip2fo
->n_offsets_per_ip
);
1604 if (ip2fo
->fun_offsets
) VG_(free
)(ip2fo
->fun_offsets
);
1605 if (ip2fo
->obj_offsets
) VG_(free
)(ip2fo
->obj_offsets
);
1606 if (ip2fo
->names
) VG_(free
)(ip2fo
->names
);
1609 /* Grow ip2fo->names to ensure we have NEEDED characters available
1610 in ip2fo->names and returns a pointer to the first free char. */
1611 static HChar
* grow_names(IPtoFunOrObjCompleter
* ip2fo
, SizeT needed
)
1613 if (ip2fo
->names_szB
1614 < ip2fo
->names_free
+ needed
) {
1615 if (needed
< ERRTXT_LEN
) needed
= ERRTXT_LEN
;
1618 = VG_(realloc
)("foc_names",
1620 ip2fo
->names_szB
+ needed
);
1621 ip2fo
->names_szB
+= needed
;
1623 return ip2fo
->names
+ ip2fo
->names_free
;
1626 /* foComplete returns the function name or object name for ixInput.
1627 If needFun, returns the function name for this input
1628 else returns the object name for this input.
1629 The function name or object name will be computed and added in
1630 names if not yet done. */
1631 static HChar
* foComplete(IPtoFunOrObjCompleter
* ip2fo
,
1632 Int ixInput
, Bool needFun
)
1634 vg_assert (ixInput
< ip2fo
->n_expanded
);
1635 vg_assert (VG_(clo_read_inline_info
) || ixInput
< ip2fo
->n_ips
);
1637 // ptr to the offset array for function offsets (if needFun)
1638 // or object offsets (if !needFun).
1641 offsets
= &ip2fo
->fun_offsets
;
1643 offsets
= &ip2fo
->obj_offsets
;
1645 // Complete Fun name or Obj name for IP if not yet done.
1646 if ((*offsets
)[ixInput
] == -1) {
1647 const HChar
* caller
;
1649 (*offsets
)[ixInput
] = ip2fo
->names_free
;
1650 if (DEBUG_ERRORMGR
) VG_(printf
)("marking %s ixInput %d offset %d\n",
1651 needFun
? "fun" : "obj",
1652 ixInput
, ip2fo
->names_free
);
1654 // With inline info, fn names must have been completed already.
1655 vg_assert (!VG_(clo_read_inline_info
));
1656 /* Get the function name into 'caller_name', or "???"
1658 // Nb: C++-mangled names are used in suppressions. Do, though,
1659 // Z-demangle them, since otherwise it's possible to wind
1660 // up comparing "malloc" in the suppression against
1661 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1662 // two of them need to be made to match.
1663 if (!VG_(get_fnname_no_cxx_demangle
)(ip2fo
->ips
[ixInput
],
1668 /* Get the object name into 'caller_name', or "???"
1671 UWord last_expand_pos_ips
= 0;
1674 /* First get the pos in ips corresponding to ixInput */
1675 for (pos_ips
= 0; pos_ips
< ip2fo
->n_expanded
; pos_ips
++) {
1676 last_expand_pos_ips
+= ip2fo
->n_offsets_per_ip
[pos_ips
];
1677 if (ixInput
< last_expand_pos_ips
)
1680 /* pos_ips is the position in ips corresponding to ixInput.
1681 last_expand_pos_ips is the last offset in fun/obj where
1682 ips[pos_ips] has been expanded. */
1684 if (!VG_(get_objname
)(ip2fo
->ips
[pos_ips
], &caller
))
1687 // Have all inlined calls pointing at this object name
1688 for (i
= last_expand_pos_ips
- ip2fo
->n_offsets_per_ip
[pos_ips
] + 1;
1689 i
< last_expand_pos_ips
;
1691 ip2fo
->obj_offsets
[i
] = ip2fo
->names_free
;
1693 VG_(printf
) (" set obj_offset %lu to %d\n",
1694 i
, ip2fo
->names_free
);
1697 SizeT caller_len
= VG_(strlen
)(caller
);
1698 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1699 VG_(strcpy
)(caller_name
, caller
);
1700 ip2fo
->names_free
+= caller_len
+ 1;
1701 if (DEBUG_ERRORMGR
) pp_ip2fo(ip2fo
);
1704 return ip2fo
->names
+ (*offsets
)[ixInput
];
1707 // Grow fun and obj _offsets arrays to have at least n_req elements.
1708 // Ensure n_offsets_per_ip is allocated.
1709 static void grow_offsets(IPtoFunOrObjCompleter
* ip2fo
, Int n_req
)
1713 // n_offsets_per_ip must always have the size of the ips array
1714 if (ip2fo
->n_offsets_per_ip
== NULL
) {
1715 ip2fo
->n_offsets_per_ip
= VG_(malloc
)("grow_offsets",
1716 ip2fo
->n_ips
* sizeof(Int
));
1717 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1718 ip2fo
->n_offsets_per_ip
[i
] = 0;
1721 if (ip2fo
->sz_offsets
>= n_req
)
1724 // Avoid too much re-allocation by allocating at least ip2fo->n_ips
1725 // elements and at least a few more elements than the current size.
1726 if (n_req
< ip2fo
->n_ips
)
1727 n_req
= ip2fo
->n_ips
;
1728 if (n_req
< ip2fo
->sz_offsets
+ 5)
1729 n_req
= ip2fo
->sz_offsets
+ 5;
1731 ip2fo
->fun_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->fun_offsets
,
1732 n_req
* sizeof(Int
));
1733 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1734 ip2fo
->fun_offsets
[i
] = -1;
1736 ip2fo
->obj_offsets
= VG_(realloc
)("grow_offsets", ip2fo
->obj_offsets
,
1737 n_req
* sizeof(Int
));
1738 for (i
= ip2fo
->sz_offsets
; i
< n_req
; i
++)
1739 ip2fo
->obj_offsets
[i
] = -1;
1741 ip2fo
->sz_offsets
= n_req
;
1744 // Expands more IPs from ip2fo->ips.
1745 static void expandInput (IPtoFunOrObjCompleter
* ip2fo
, UWord ixInput
)
1747 while (ip2fo
->n_ips_expanded
< ip2fo
->n_ips
1748 && ip2fo
->n_expanded
<= ixInput
) {
1749 if (VG_(clo_read_inline_info
)) {
1750 // Expand one more IP in one or more calls.
1751 const Addr IP
= ip2fo
->ips
[ip2fo
->n_ips_expanded
];
1754 iipc
= VG_(new_IIPC
)(IP
);
1755 // The only thing we really need is the nr of inlined fn calls
1756 // corresponding to the IP we will expand.
1757 // However, computing this is mostly the same as finding
1758 // the function name. So, let's directly complete the function name.
1760 const HChar
*caller
;
1761 grow_offsets(ip2fo
, ip2fo
->n_expanded
+1);
1762 ip2fo
->fun_offsets
[ip2fo
->n_expanded
] = ip2fo
->names_free
;
1763 if (!VG_(get_fnname_no_cxx_demangle
)(IP
,
1767 SizeT caller_len
= VG_(strlen
)(caller
);
1768 HChar
* caller_name
= grow_names(ip2fo
, caller_len
+ 1);
1769 VG_(strcpy
)(caller_name
, caller
);
1770 ip2fo
->names_free
+= caller_len
+ 1;
1771 ip2fo
->n_expanded
++;
1772 ip2fo
->n_offsets_per_ip
[ip2fo
->n_ips_expanded
]++;
1773 } while (VG_(next_IIPC
)(iipc
));
1774 ip2fo
->n_ips_expanded
++;
1775 VG_(delete_IIPC
) (iipc
);
1777 // Without inlined fn call info, expansion simply
1778 // consists in allocating enough elements in (fun|obj)_offsets.
1779 // The function or object names themselves will be completed
1782 grow_offsets(ip2fo
, ip2fo
->n_ips
);
1783 ip2fo
->n_ips_expanded
= ip2fo
->n_ips
;
1784 ip2fo
->n_expanded
= ip2fo
->n_ips
;
1785 for (i
= 0; i
< ip2fo
->n_ips
; i
++)
1786 ip2fo
->n_offsets_per_ip
[i
] = 1;
1791 static Bool
haveInputInpC (void* inputCompleter
, UWord ixInput
)
1793 IPtoFunOrObjCompleter
* ip2fo
= inputCompleter
;
1794 expandInput(ip2fo
, ixInput
);
1795 return ixInput
< ip2fo
->n_expanded
;
1798 static Bool
supp_pattEQinp ( const void* supplocV
, const void* addrV
,
1799 void* inputCompleter
, UWord ixInput
)
1801 const SuppLoc
* supploc
= supplocV
; /* PATTERN */
1802 IPtoFunOrObjCompleter
* ip2fo
= inputCompleter
;
1803 HChar
* funobj_name
; // Fun or Obj name.
1806 expandInput(ip2fo
, ixInput
);
1807 vg_assert(ixInput
< ip2fo
->n_expanded
);
1809 /* So, does this IP address match this suppression-line? */
1810 switch (supploc
->ty
) {
1812 /* supp_pattEQinp is a callback from VG_(generic_match). As
1813 per the spec thereof (see include/pub_tool_seqmatch.h), we
1814 should never get called with a pattern value for which the
1815 _IsStar or _IsQuery function would return True. Hence
1816 this can't happen. */
1819 funobj_name
= foComplete(ip2fo
, ixInput
, False
/*needFun*/);
1822 funobj_name
= foComplete(ip2fo
, ixInput
, True
/*needFun*/);
1828 /* So now we have the function or object name in funobj_name, and
1829 the pattern (at the character level) to match against is in
1830 supploc->name. Hence (and leading to a re-entrant call of
1831 VG_(generic_match) if there is a wildcard character): */
1832 if (supploc
->name_is_simple_str
)
1833 ret
= VG_(strcmp
) (supploc
->name
, funobj_name
) == 0;
1835 ret
= VG_(string_match
)(supploc
->name
, funobj_name
);
1837 VG_(printf
) ("supp_pattEQinp %s patt %s ixUnput %lu value:%s match:%s\n",
1838 supploc
->ty
== FunName
? "fun" : "obj",
1839 supploc
->name
, ixInput
, funobj_name
,
1840 ret
? "yes" : "no");
1844 /////////////////////////////////////////////////////
1846 static Bool
supp_matches_callers(IPtoFunOrObjCompleter
* ip2fo
,
1849 /* Unwrap the args and set up the correct parameterisation of
1850 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1852 /* note, StackTrace ip2fo->ips === Addr* */
1853 SuppLoc
* supps
= su
->callers
;
1854 UWord n_supps
= su
->n_callers
;
1855 UWord szbPatt
= sizeof(SuppLoc
);
1856 Bool matchAll
= False
; /* we just want to match a prefix */
1857 if (DEBUG_ERRORMGR
) {
1858 HChar
*filename
= *(HChar
**) VG_(indexXA
)(VG_(clo_suppressions
),
1859 su
->clo_suppressions_i
);
1860 VG_(dmsg
)(" errormgr Checking match with %s %s:%d\n",
1868 /*PATT*/supps
, szbPatt
, n_supps
, 0/*initial ixPatt*/,
1870 NULL
, 0, 0, /* input/szbInput/nInput 0, as using an inputCompleter */
1871 0/*initial ixInput*/,
1872 supploc_IsStar
, supploc_IsQuery
, supp_pattEQinp
,
1873 ip2fo
, haveInputInpC
1877 /////////////////////////////////////////////////////
1880 Bool
supp_matches_error(const Supp
* su
, const Error
* err
)
1882 switch (su
->skind
) {
1883 //(example code, see comment on CoreSuppKind above)
1885 // return (err->ekind == ThreadErr);
1887 if (VG_(needs
).tool_errors
) {
1888 return VG_TDICT_CALL(tool_error_matches_suppression
, err
, su
);
1891 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n"
1892 "probably needs to be set.\n",
1894 VG_(core_panic
)("unhandled suppression type");
1899 /////////////////////////////////////////////////////
1901 /* Does an error context match a suppression? ie is this a suppressible
1902 error? If so, return a pointer to the Supp record, otherwise NULL.
1903 Tries to minimise the number of symbol searches since they are expensive.
1905 static Supp
* is_suppressible_error ( const Error
* err
)
1910 IPtoFunOrObjCompleter ip2fo
;
1911 /* Conceptually, ip2fo contains an array of function names and an array of
1912 object names, corresponding to the array of IP of err->where.
1913 These names are just computed 'on demand' (so once maximum),
1914 then stored (efficiently, avoiding too many allocs) in ip2fo to be
1915 re-usable for the matching of the same IP with the next suppression
1918 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one
1919 of its arguments. It will then pass it to the function
1920 supp_pattEQinp which will then lazily complete the IP function name or
1921 object name inside ip2fo. Next time the fun or obj name for the same
1922 IP is needed (i.e. for the matching with the next suppr pattern), then
1923 the fun or obj name will not be searched again in the debug info. */
1925 /* stats gathering */
1926 em_supplist_searches
++;
1928 /* Prepare the lazy input completer. */
1929 ip2fo
.ips
= VG_(get_ExeContext_StackTrace
)(err
->where
);
1930 ip2fo
.n_ips
= VG_(get_ExeContext_n_ips
)(err
->where
);
1931 ip2fo
.n_ips_expanded
= 0;
1932 ip2fo
.n_expanded
= 0;
1933 ip2fo
.sz_offsets
= 0;
1934 ip2fo
.n_offsets_per_ip
= NULL
;
1935 ip2fo
.fun_offsets
= NULL
;
1936 ip2fo
.obj_offsets
= NULL
;
1938 ip2fo
.names_szB
= 0;
1939 ip2fo
.names_free
= 0;
1941 /* See if the error context matches any suppression. */
1942 if (DEBUG_ERRORMGR
|| VG_(debugLog_getLevel
)() >= 4)
1943 VG_(dmsg
)("errormgr matching begin\n");
1945 for (su
= suppressions
; su
!= NULL
; su
= su
->next
) {
1947 if (supp_matches_error(su
, err
)
1948 && supp_matches_callers(&ip2fo
, su
)) {
1950 /* Inform the tool that err is suppressed by su. */
1951 (void)VG_TDICT_CALL(tool_update_extra_suppression_use
, err
, su
);
1952 /* Move this entry to the head of the list
1953 in the hope of making future searches cheaper. */
1955 vg_assert(su_prev
->next
== su
);
1956 su_prev
->next
= su
->next
;
1957 su
->next
= suppressions
;
1960 clearIPtoFunOrObjCompleter(su
, &ip2fo
);
1965 clearIPtoFunOrObjCompleter(NULL
, &ip2fo
);
1966 return NULL
; /* no matches */
1969 /* Show accumulated error-list and suppression-list search stats.
1971 void VG_(print_errormgr_stats
) ( void )
1974 " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
1975 em_supplist_searches
, em_supplist_cmps
1978 " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
1979 em_errlist_searches
, em_errlist_cmps
1983 /*--------------------------------------------------------------------*/
1985 /*--------------------------------------------------------------------*/