]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_errormgr.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_errormgr.c
1
2 /*--------------------------------------------------------------------*/
3 /*--- Management of error messages.                   m_errormgr.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2000-2010 Julian Seward 
11       jseward@acm.org
12
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.
17
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.
22
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
26    02111-1307, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29 */
30
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_errormgr.h"
38 #include "pub_core_execontext.h"
39 #include "pub_core_gdbserver.h"
40 #include "pub_core_libcbase.h"
41 #include "pub_core_libcassert.h"
42 #include "pub_core_libcfile.h"
43 #include "pub_core_libcprint.h"
44 #include "pub_core_libcproc.h"         // For VG_(getpid)()
45 #include "pub_core_seqmatch.h"
46 #include "pub_core_mallocfree.h"
47 #include "pub_core_options.h"
48 #include "pub_core_stacktrace.h"
49 #include "pub_core_tooliface.h"
50 #include "pub_core_translate.h"        // for VG_(translate)()
51 #include "pub_core_xarray.h"           // VG_(xaprintf) et al
52
53 /*------------------------------------------------------------*/
54 /*--- Globals                                              ---*/
55 /*------------------------------------------------------------*/
56
57 /* After this many different unsuppressed errors have been observed,
58    be more conservative about collecting new ones. */
59 #define M_COLLECT_ERRORS_SLOWLY_AFTER 100
60
61 /* After this many different unsuppressed errors have been observed,
62    stop collecting errors at all, and tell the user their program is
63    evidently a steaming pile of camel dung. */
64 #define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000
65
66 /* After this many total errors have been observed, stop collecting
67    errors at all.  Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */
68 #define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000
69
70 /* The list of error contexts found, both suppressed and unsuppressed.
71    Initially empty, and grows as errors are detected. */
72 static Error* errors = NULL;
73
74 /* The list of suppression directives, as read from the specified
75    suppressions file.  Note that the list gets rearranged as a result
76    of the searches done by is_suppressible_error(). */
77 static Supp* suppressions = NULL;
78
79 /* Running count of unsuppressed errors detected. */
80 static UInt n_errs_found = 0;
81
82 /* Running count of suppressed errors detected. */
83 static UInt n_errs_suppressed = 0;
84
85 /* Running count of unsuppressed error contexts. */
86 static UInt n_err_contexts = 0;
87
88 /* Running count of suppressed error contexts. */
89 static UInt n_supp_contexts = 0;
90
91
92 /* forwards ... */
93 static Supp* is_suppressible_error ( Error* err );
94
95 static ThreadId last_tid_printed = 1;
96
97 /* Stats: number of searches of the error list initiated. */
98 static UWord em_errlist_searches = 0;
99
100 /* Stats: number of comparisons done during error list
101    searching. */
102 static UWord em_errlist_cmps = 0;
103
104 /* Stats: number of searches of the suppression list initiated. */
105 static UWord em_supplist_searches = 0;
106
107 /* Stats: number of comparisons done during suppression list
108    searching. */
109 static UWord em_supplist_cmps = 0;
110
111 /*------------------------------------------------------------*/
112 /*--- Error type                                           ---*/
113 /*------------------------------------------------------------*/
114
115 /* Errors.  Extensible (via the 'extra' field).  Tools can use a normal
116    enum (with element values in the normal range (0..)) for 'ekind'. 
117    Functions for getting/setting the tool-relevant fields are in
118    include/pub_tool_errormgr.h.
119
120    When errors are found and recorded with VG_(maybe_record_error)(), all
121    the tool must do is pass in the four parameters;  core will
122    allocate/initialise the error record.
123 */
124 struct _Error {
125    struct _Error* next;
126    // Unique tag.  This gives the error a unique identity (handle) by
127    // which it can be referred to afterwords.  Currently only used for
128    // XML printing.
129    UInt unique;
130    // NULL if unsuppressed; or ptr to suppression record.
131    Supp* supp;
132    Int count;
133
134    // The tool-specific part
135    ThreadId tid;           // Initialised by core
136    ExeContext* where;      // Initialised by core
137    ErrorKind ekind;        // Used by ALL.  Must be in the range (0..)
138    Addr addr;              // Used frequently
139    Char* string;           // Used frequently
140    void* extra;            // For any tool-specific extras
141 };
142
143
144 ExeContext* VG_(get_error_where) ( Error* err )
145 {
146    return err->where;
147 }
148
149 ErrorKind VG_(get_error_kind) ( Error* err )
150 {
151    return err->ekind;
152 }
153
154 Addr VG_(get_error_address) ( Error* err )
155 {
156    return err->addr;
157 }
158
159 Char* VG_(get_error_string) ( Error* err )
160 {
161    return err->string;
162 }
163
164 void* VG_(get_error_extra)  ( Error* err )
165 {
166    return err->extra;
167 }
168
169 UInt VG_(get_n_errs_found)( void )
170 {
171    return n_errs_found;
172 }
173
174 /*------------------------------------------------------------*/
175 /*--- Suppression type                                     ---*/
176 /*------------------------------------------------------------*/
177
178 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools
179  * effectively extend it by defining their own enums in the (0..) range. */
180 typedef
181    enum {
182       // Nb: thread errors are a relic of the time when Valgrind's core
183       // could detect them.  This example is left commented-out as an
184       // example should new core errors ever be added.
185       ThreadSupp = -1,    /* Matches ThreadErr */
186    }
187    CoreSuppKind;
188
189 /* Max number of callers for context in a suppression. */
190 #define VG_MAX_SUPP_CALLERS  24
191
192 /* For each caller specified for a suppression, record the nature of
193    the caller name.  Not of interest to tools. */
194 typedef
195    enum { 
196       NoName,     /* Error case */
197       ObjName,    /* Name is of an shared object file. */
198       FunName,    /* Name is of a function. */
199       DotDotDot   /* Frame-level wildcard */
200    }
201    SuppLocTy;
202
203 typedef
204    struct {
205       SuppLocTy ty;
206       Char*     name; /* NULL for NoName and DotDotDot */
207    }
208    SuppLoc;
209
210 /* Suppressions.  Tools can get/set tool-relevant parts with functions
211    declared in include/pub_tool_errormgr.h.  Extensible via the 'extra' field. 
212    Tools can use a normal enum (with element values in the normal range
213    (0..)) for 'skind'. */
214 struct _Supp {
215    struct _Supp* next;
216    Int count;     // The number of times this error has been suppressed.
217    Char* sname;   // The name by which the suppression is referred to.
218
219    // Length of 'callers'
220    Int n_callers;
221    // Array of callers, for matching stack traces.  First one (name of fn
222    // where err occurs) is mandatory;  rest are optional.
223    SuppLoc* callers;
224
225    /* The tool-specific part */
226    SuppKind skind;   // What kind of suppression.  Must use the range (0..).
227    Char* string;     // String -- use is optional.  NULL by default.
228    void* extra;      // Anything else -- use is optional.  NULL by default.
229 };
230
231 SuppKind VG_(get_supp_kind) ( Supp* su )
232 {
233    return su->skind;
234 }
235
236 Char* VG_(get_supp_string) ( Supp* su )
237 {
238    return su->string;
239 }
240
241 void* VG_(get_supp_extra)  ( Supp* su )
242 {
243    return su->extra;
244 }
245
246
247 void VG_(set_supp_kind)   ( Supp* su, SuppKind skind )
248 {
249    su->skind = skind;
250 }
251
252 void VG_(set_supp_string) ( Supp* su, Char* string )
253 {
254    su->string = string;
255 }
256
257 void VG_(set_supp_extra)  ( Supp* su, void* extra )
258 {
259    su->extra = extra;
260 }
261
262
263 /*------------------------------------------------------------*/
264 /*--- Helper fns                                           ---*/
265 /*------------------------------------------------------------*/
266
267 // Only show core errors if the tool wants to, we're not running with -q,
268 // and were not outputting XML.
269 Bool VG_(showing_core_errors)(void)
270 {
271    return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml);
272 }
273
274 /* Compare errors, to detect duplicates. 
275 */
276 static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
277 {
278    if (e1->ekind != e2->ekind) 
279       return False;
280    if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
281       return False;
282
283    switch (e1->ekind) {
284       //(example code, see comment on CoreSuppKind above)
285       //case ThreadErr:
286       //   vg_assert(VG_(needs).core_errors);
287       //   return <something>
288       default: 
289          if (VG_(needs).tool_errors) {
290             return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
291          } else {
292             VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
293                         "probably needs to be set.\n",
294                         e1->ekind);
295             VG_(tool_panic)("unhandled error type");
296          }
297    }
298 }
299
300
301 /* Helper functions for suppression generation: print a single line of
302    a suppression pseudo-stack-trace, either in XML or text mode.  It's
303    important that the behaviour of these two functions exactly
304    corresponds.
305 */
306 #define ERRTXT_LEN   4096
307
308 static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque)
309 {
310    static UChar buf[ERRTXT_LEN];
311    if ( VG_(get_fnname_no_cxx_demangle) (ip, buf,  ERRTXT_LEN) ) {
312       VG_(printf_xml_no_f_c)("    <sframe> <fun>%t</fun> </sframe>\n", buf);
313    } else
314    if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
315       VG_(printf_xml_no_f_c)("    <sframe> <obj>%t</obj> </sframe>\n", buf);
316    } else {
317       VG_(printf_xml_no_f_c)("    <sframe> <obj>*</obj> </sframe>\n");
318    }
319 }
320
321 static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV)
322 {
323    static UChar buf[ERRTXT_LEN];
324    XArray* /* of HChar */ text = (XArray*)textV;
325    if ( VG_(get_fnname_no_cxx_demangle) (ip, buf,  ERRTXT_LEN) ) {
326       VG_(xaprintf)(text, "   fun:%s\n", buf);
327    } else
328    if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
329       VG_(xaprintf)(text, "   obj:%s\n", buf);
330    } else {
331       VG_(xaprintf)(text, "   obj:*\n");
332    }
333 }
334
335 /* Generate a suppression for an error, either in text or XML mode.
336 */
337 static void gen_suppression(Error* err)
338 {
339    Char        xtra[256]; /* assumed big enough (is overrun-safe) */
340    Bool        anyXtra;
341    Char*       name;
342    ExeContext* ec;
343    XArray* /* HChar */ text;
344
345    const HChar* dummy_name = "insert_a_suppression_name_here";
346
347    vg_assert(err);
348
349    /* In XML mode, we also need to print the plain text version of the
350       suppresion in a CDATA section.  What that really means is, we
351       need to generate the plaintext version both in XML and text
352       mode.  So generate it into TEXT. */
353    text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1",
354                       VG_(free), sizeof(HChar) );
355    vg_assert(text);
356
357    ec = VG_(get_error_where)(err);
358    vg_assert(ec);
359
360    name = VG_TDICT_CALL(tool_get_error_name, err);
361    if (NULL == name) {
362       VG_(umsg)("(%s does not allow error to be suppressed)\n",
363                 VG_(details).name);
364       return;
365    }
366
367    /* Ok.  Generate the plain text version into TEXT. */
368    VG_(xaprintf)(text, "{\n");
369    VG_(xaprintf)(text, "   <%s>\n", dummy_name);
370    VG_(xaprintf)(text, "   %s:%s\n", VG_(details).name, name);
371
372    VG_(memset)(xtra, 0, sizeof(xtra));
373    anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info,
374                            err, xtra, sizeof(xtra));
375    vg_assert(xtra[sizeof(xtra)-1] == 0);
376
377    if (anyXtra)
378       VG_(xaprintf)(text, "   %s\n", xtra);
379
380    // Print stack trace elements
381    UInt n_ips = VG_(get_ExeContext_n_ips)(ec);
382    tl_assert(n_ips > 0);
383    if (n_ips > VG_MAX_SUPP_CALLERS)
384       n_ips = VG_MAX_SUPP_CALLERS;
385    VG_(apply_StackTrace)(printSuppForIp_nonXML,
386                          text,
387                          VG_(get_ExeContext_StackTrace)(ec),
388                          n_ips);
389
390    VG_(xaprintf)(text, "}\n");
391    // zero terminate
392    VG_(xaprintf)(text, "%c", (HChar)0 );
393    // VG_(printf) of text
394
395    /* And now display it. */
396    if (! VG_(clo_xml) ) {
397
398       // the simple case
399       VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) );
400
401    } else {
402
403       /* Now we have to print the XML directly.  No need to go to the
404          effort of stuffing it in an XArray, since we won't need it
405          again. */
406       VG_(printf_xml)("  <suppression>\n");
407       VG_(printf_xml)("    <sname>%s</sname>\n", dummy_name);
408       VG_(printf_xml_no_f_c)(
409                       "    <skind>%t:%t</skind>\n", VG_(details).name, name);
410       if (anyXtra)
411          VG_(printf_xml_no_f_c)("    <skaux>%t</skaux>\n", xtra);
412
413       // Print stack trace elements
414       VG_(apply_StackTrace)(printSuppForIp_XML,
415                             NULL,
416                             VG_(get_ExeContext_StackTrace)(ec),
417                             VG_(get_ExeContext_n_ips)(ec));
418
419       // And now the cdata bit
420       // XXX FIXME!  properly handle the case where the raw text
421       // itself contains "]]>", as specified in Protocol 4.
422       VG_(printf_xml)("    <rawtext>\n");
423       VG_(printf_xml)("<![CDATA[\n");
424       VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) );
425       VG_(printf_xml)("]]>\n");
426       VG_(printf_xml)("    </rawtext>\n");
427       VG_(printf_xml)("  </suppression>\n");
428
429    }
430
431    VG_(deleteXA)(text);
432 }
433
434
435 /* Figure out if we want to perform a given action for this error,
436    possibly by asking the user.
437 */
438 Bool VG_(is_action_requested) ( Char* action, Bool* clo )
439 {
440    Char ch, ch2;
441    Int res;
442
443    /* First off, we shouldn't be asking the user anything if
444       we're in XML mode. */
445    if (VG_(clo_xml))
446       return False; /* That's a Nein, oder Nay as they say down here in B-W */
447
448    if (*clo == False)
449       return False;
450
451    VG_(umsg)("\n");
452
453   again:
454    VG_(printf)(
455       "==%d== "
456       "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ", 
457       VG_(getpid)(), action
458    );
459
460    res = VG_(read)(VG_(clo_input_fd), &ch, 1);
461    if (res != 1) goto ioerror;
462    /* res == 1 */
463    if (ch == '\n') return False;
464    if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y' 
465       && ch != 'C' && ch != 'c') goto again;
466
467    res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
468    if (res != 1) goto ioerror;
469    if (ch2 != '\n') goto again;
470
471    /* No, don't want to do action. */
472    if (ch == 'n' || ch == 'N') return False;
473    /* Yes, want to do action. */
474    if (ch == 'y' || ch == 'Y') return True;
475    /* No, don't want to do action, and don't ask again either. */
476    vg_assert(ch == 'c' || ch == 'C');
477
478   ioerror:
479    *clo = False;
480    return False;
481 }
482
483
484 /* Do text-mode actions on error, that is, immediately after an error
485    is printed.  These are:
486    * possibly, attach to a debugger
487    * possibly, generate a suppression.
488    Note this should not be called in XML mode! 
489 */
490 static 
491 void do_actions_on_error(Error* err, Bool allow_db_attach)
492 {
493    Bool still_noisy = True;
494
495    /* Should be assured by caller */
496    vg_assert( ! VG_(clo_xml) );
497
498    /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */
499    if (VG_(clo_vgdb) != Vg_VgdbNo
500        && allow_db_attach 
501        && VG_(dyn_vgdb_error) <= n_errs_found) {
502       VG_(umsg)("(action on error) vgdb me ... \n");
503       VG_(gdbserver)( err->tid );
504       VG_(umsg)("Continuing ...\n");
505    }
506
507    /* Perhaps we want a debugger attach at this point? */
508    /* GDBTD ??? maybe we should/could remove the below assuming the
509       gdbserver interface is better ??? */
510    if (allow_db_attach &&
511        VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
512    {   
513       if (0) VG_(printf)("starting debugger\n");
514       VG_(start_debugger)( err->tid );
515    }  
516    /* Or maybe we want to generate the error's suppression? */
517    if (VG_(clo_gen_suppressions) == 2
518        || (VG_(clo_gen_suppressions) == 1
519            && VG_(is_action_requested)( "Print suppression", &still_noisy ))
520       ) {
521       gen_suppression(err);
522    }
523    if (VG_(clo_gen_suppressions) == 1 && !still_noisy)
524       VG_(clo_gen_suppressions) = 0;
525 }
526
527
528 /* Prints an error.  Not entirely simple because of the differences
529    between XML and text mode output.
530  
531    In XML mode:
532
533    * calls the tool's pre-show method, so the tool can create any
534      preamble ahead of the message, if it wants.
535
536    * prints the opening tag, and the <unique> and <tid> fields
537
538    * prints the tool-specific parts of the message
539
540    * if suppression generation is required, a suppression
541
542    * the closing tag
543
544    In text mode:
545
546    * calls the tool's pre-show method, so the tool can create any
547      preamble ahead of the message, if it wants.
548
549    * prints the tool-specific parts of the message
550
551    * calls do_actions_on_error.  This optionally does a debugger
552      attach (and detach), and optionally prints a suppression; both
553      of these may require user input.
554 */
555 static void pp_Error ( Error* err, Bool allow_db_attach, Bool xml )
556 {
557    /* If this fails, you probably specified your tool's method
558       dictionary incorrectly. */
559    vg_assert(VG_(needs).tool_errors);
560
561    if (xml) {
562
563       /* Note, allow_db_attach is ignored in here. */
564  
565       /* Ensure that suppression generation is either completely
566          enabled or completely disabled; either way, we won't require
567          any user input.  m_main.process_cmd_line_options should
568          ensure the asserted condition holds. */
569       vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */
570                  || VG_(clo_gen_suppressions) == 2 /* for all errors */ );
571
572       /* Pre-show it to the tool */
573       VG_TDICT_CALL( tool_before_pp_Error, err );
574    
575       /* standard preamble */
576       VG_(printf_xml)("<error>\n");
577       VG_(printf_xml)("  <unique>0x%x</unique>\n", err->unique);
578       VG_(printf_xml)("  <tid>%d</tid>\n", err->tid);
579
580       /* actually print it */
581       VG_TDICT_CALL( tool_pp_Error, err );
582
583       if (VG_(clo_gen_suppressions) > 0)
584         gen_suppression(err);
585
586       /* postamble */
587       VG_(printf_xml)("</error>\n");
588       VG_(printf_xml)("\n");
589
590    } else {
591
592       VG_TDICT_CALL( tool_before_pp_Error, err );
593
594       if (VG_(tdict).tool_show_ThreadIDs_for_errors
595           && err->tid > 0 && err->tid != last_tid_printed) {
596          VG_(umsg)("Thread %d:\n", err->tid );
597          last_tid_printed = err->tid;
598       }
599    
600       VG_TDICT_CALL( tool_pp_Error, err );
601       VG_(umsg)("\n");
602
603       do_actions_on_error(err, allow_db_attach);
604    }
605 }
606
607
608 /* Construct an error */
609 static
610 void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
611                        Char* s, void* extra, ExeContext* where )
612 {
613    /* DO NOT MAKE unique_counter NON-STATIC */
614    static UInt unique_counter = 0;
615
616    tl_assert(tid < VG_N_THREADS);
617
618    /* Core-only parts */
619    err->unique   = unique_counter++;
620    err->next     = NULL;
621    err->supp     = NULL;
622    err->count    = 1;
623    err->tid      = tid;
624    if (NULL == where)
625      err->where = VG_(record_ExeContext)( tid, 0 );
626    else
627       err->where = where;
628
629    /* Tool-relevant parts */
630    err->ekind  = ekind;
631    err->addr   = a;
632    err->extra  = extra;
633    err->string = s;
634
635    /* sanity... */
636    vg_assert( tid < VG_N_THREADS );
637 }
638
639
640
641 static Int  n_errs_shown = 0;
642
643 /* Top-level entry point to the error management subsystem.
644    All detected errors are notified here; this routine decides if/when the
645    user should see the error. */
646 void VG_(maybe_record_error) ( ThreadId tid, 
647                                ErrorKind ekind, Addr a, Char* s, void* extra )
648 {
649           Error  err;
650           Error* p;
651           Error* p_prev;
652           UInt   extra_size;
653           VgRes  exe_res          = Vg_MedRes;
654    static Bool   stopping_message = False;
655    static Bool   slowdown_message = False;
656
657    /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
658       been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors
659       have been found, just refuse to collect any more.  This stops
660       the burden of the error-management system becoming excessive in
661       extremely buggy programs, although it does make it pretty
662       pointless to continue the Valgrind run after this point. */
663    if (VG_(clo_error_limit) 
664        && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN
665            || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND)
666        && !VG_(clo_xml)) {
667       if (!stopping_message) {
668          VG_(umsg)("\n");
669
670          if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) {
671             VG_(umsg)(
672                "More than %d different errors detected.  "
673                "I'm not reporting any more.\n",
674                M_COLLECT_NO_ERRORS_AFTER_SHOWN );
675          } else {
676             VG_(umsg)(
677                "More than %d total errors detected.  "
678                "I'm not reporting any more.\n",
679                M_COLLECT_NO_ERRORS_AFTER_FOUND );
680          }
681
682          VG_(umsg)("Final error counts will be inaccurate.  "
683                    "Go fix your program!\n");
684          VG_(umsg)("Rerun with --error-limit=no to disable "
685                    "this cutoff.  Note\n");
686          VG_(umsg)("that errors may occur in your program without "
687                    "prior warning from\n");
688          VG_(umsg)("Valgrind, because errors are no longer "
689                    "being displayed.\n");
690          VG_(umsg)("\n");
691          stopping_message = True;
692       }
693       return;
694    }
695
696    /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have
697       been found, be much more conservative about collecting new
698       ones. */
699    if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER
700        && !VG_(clo_xml)) {
701       exe_res = Vg_LowRes;
702       if (!slowdown_message) {
703          VG_(umsg)("\n");
704          VG_(umsg)("More than %d errors detected.  Subsequent errors\n",
705                    M_COLLECT_ERRORS_SLOWLY_AFTER);
706          VG_(umsg)("will still be recorded, but in less "
707                    "detail than before.\n");
708          slowdown_message = True;
709       }
710    }
711
712    /* Build ourselves the error */
713    construct_error ( &err, tid, ekind, a, s, extra, NULL );
714
715    /* First, see if we've got an error record matching this one. */
716    em_errlist_searches++;
717    p       = errors;
718    p_prev  = NULL;
719    while (p != NULL) {
720       em_errlist_cmps++;
721       if (eq_Error(exe_res, p, &err)) {
722          /* Found it. */
723          p->count++;
724          if (p->supp != NULL) {
725             /* Deal correctly with suppressed errors. */
726             p->supp->count++;
727             n_errs_suppressed++;         
728          } else {
729             n_errs_found++;
730          }
731
732          /* Move p to the front of the list so that future searches
733             for it are faster. It also allows to print the last
734             error (see VG_(show_last_error). */
735          if (p_prev != NULL) {
736             vg_assert(p_prev->next == p);
737             p_prev->next = p->next;
738             p->next      = errors;
739             errors       = p;
740          }
741
742          return;
743       }
744       p_prev = p;
745       p      = p->next;
746    }
747
748    /* Didn't see it.  Copy and add. */
749
750    /* OK, we're really going to collect it.  The context is on the stack and
751       will disappear shortly, so we must copy it.  First do the main
752       (non-'extra') part.
753      
754       Then VG_(tdict).tool_update_extra can update the 'extra' part.  This
755       is for when there are more details to fill in which take time to work
756       out but don't affect our earlier decision to include the error -- by
757       postponing those details until now, we avoid the extra work in the
758       case where we ignore the error.  Ugly.
759
760       Then, if there is an 'extra' part, copy it too, using the size that
761       VG_(tdict).tool_update_extra returned.  Also allow for people using
762       the void* extra field for a scalar value like an integer.
763    */
764
765    /* copy main part */
766    p = VG_(arena_malloc)(VG_AR_ERRORS, "errormgr.mre.1", sizeof(Error));
767    *p = err;
768
769    /* update 'extra' */
770    switch (ekind) {
771       //(example code, see comment on CoreSuppKind above)
772       //case ThreadErr:
773       //   vg_assert(VG_(needs).core_errors);
774       //   extra_size = <something>
775       //   break;
776       default:
777          vg_assert(VG_(needs).tool_errors);
778          extra_size = VG_TDICT_CALL(tool_update_extra, p);
779          break;
780    }
781
782    /* copy block pointed to by 'extra', if there is one */
783    if (NULL != p->extra && 0 != extra_size) { 
784       void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size);
785       VG_(memcpy)(new_extra, p->extra, extra_size);
786       p->extra = new_extra;
787    }
788
789    p->next = errors;
790    p->supp = is_suppressible_error(&err);
791    errors  = p;
792    if (p->supp == NULL) {
793       n_err_contexts++;
794       n_errs_found++;
795       /* Actually show the error; more complex than you might think. */
796       pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml) );
797       /* update stats */
798       n_errs_shown++;
799    } else {
800       n_supp_contexts++;
801       n_errs_suppressed++;
802       p->supp->count++;
803    }
804 }
805
806 /* Second top-level entry point to the error management subsystem, for
807    errors that the tool wants to report immediately, eg. because they're
808    guaranteed to only happen once.  This avoids all the recording and
809    comparing stuff.  But they can be suppressed;  returns True if it is
810    suppressed.  Bool 'print_error' dictates whether to print the error. 
811    Bool 'count_error' dictates whether to count the error in n_errs_found.
812 */
813 Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
814                          void* extra, ExeContext* where, Bool print_error,
815                          Bool allow_db_attach, Bool count_error )
816 {
817    Error err;
818    Supp *su;
819
820    /* Build ourselves the error */
821    construct_error ( &err, tid, ekind, a, s, extra, where );
822
823    /* Unless it's suppressed, we're going to show it.  Don't need to make
824       a copy, because it's only temporary anyway.
825
826       Then update the 'extra' part with VG_(tdict).tool_update_extra),
827       because that can have an affect on whether it's suppressed.  Ignore
828       the size return value of VG_(tdict).tool_update_extra, because we're
829       not copying 'extra'. */
830    (void)VG_TDICT_CALL(tool_update_extra, &err);
831
832    su = is_suppressible_error(&err);
833    if (NULL == su) {
834       if (count_error) {
835          n_errs_found++;
836          n_err_contexts++;
837       }
838
839       if (print_error) {
840          /* Actually show the error; more complex than you might think. */
841          pp_Error(&err, allow_db_attach, VG_(clo_xml));
842          /* update stats */
843          n_errs_shown++;
844       }
845       return False;
846
847    } else {
848       if (count_error) {
849          n_errs_suppressed++;
850          n_supp_contexts++;
851       }
852       su->count++;
853       return True;
854    }
855 }
856
857
858 /*------------------------------------------------------------*/
859 /*--- Exported fns                                         ---*/
860 /*------------------------------------------------------------*/
861
862 /* Show the used suppressions.  Returns False if no suppression
863    got used. */
864 static Bool show_used_suppressions ( void )
865 {
866    Supp  *su;
867    Bool  any_supp;
868
869    if (VG_(clo_xml))
870       VG_(printf_xml)("<suppcounts>\n");
871
872    any_supp = False;
873    for (su = suppressions; su != NULL; su = su->next) {
874       if (su->count <= 0)
875          continue;
876       if (VG_(clo_xml)) {
877          VG_(printf_xml_no_f_c)( "  <pair>\n"
878                                  "    <count>%d</count>\n"
879                                  "    <name>%t</name>\n"
880                                  "  </pair>\n",
881                                  su->count, su->sname );
882       } else {
883          // blank line before the first shown suppression, if any
884          if (!any_supp)
885             VG_(dmsg)("\n");
886          VG_(dmsg)("used_suppression: %6d %s\n", su->count, su->sname);
887       }
888       any_supp = True;
889    }
890
891    if (VG_(clo_xml))
892       VG_(printf_xml)("</suppcounts>\n");
893
894    return any_supp;
895 }
896
897 /* Show all the errors that occurred, and possibly also the
898    suppressions used. */
899 void VG_(show_all_errors) (  Int verbosity, Bool xml )
900 {
901    Int    i, n_min;
902    Error *p, *p_min;
903    Bool   any_supp;
904
905    if (verbosity == 0)
906       return;
907
908    /* If we're printing XML, just show the suppressions and stop. */
909    if (xml) {
910       (void)show_used_suppressions();
911       return;
912    }
913
914    /* We only get here if not printing XML. */
915    VG_(umsg)("ERROR SUMMARY: "
916              "%d errors from %d contexts (suppressed: %d from %d)\n",
917              n_errs_found, n_err_contexts, 
918              n_errs_suppressed, n_supp_contexts );
919
920    if (verbosity <= 1)
921       return;
922
923    // We do the following only at -v or above, and only in non-XML
924    // mode
925
926    /* Print the contexts in order of increasing error count. 
927       Once an error is shown, we add a huge value to its count to filter it
928       out. After having shown all errors, we reset count to the original value. */
929    for (i = 0; i < n_err_contexts; i++) {
930       n_min = (1 << 30) - 1;
931       p_min = NULL;
932       for (p = errors; p != NULL; p = p->next) {
933          if (p->supp != NULL) continue;
934          if (p->count < n_min) {
935             n_min = p->count;
936             p_min = p;
937          }
938       }
939       // XXX: this isn't right.  See bug 203651.
940       if (p_min == NULL) continue; //VG_(tool_panic)("show_all_errors()");
941
942       VG_(umsg)("\n");
943       VG_(umsg)("%d errors in context %d of %d:\n",
944                 p_min->count, i+1, n_err_contexts);
945       pp_Error( p_min, False/*allow_db_attach*/, False /* xml */ );
946
947       // We're not printing XML -- we'd have exited above if so.
948       vg_assert(! xml);
949
950       if ((i+1 == VG_(clo_dump_error))) {
951          StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where);
952          VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
953                           ips[0], /*debugging*/True, 0xFE/*verbosity*/,
954                           /*bbs_done*/0,
955                           /*allow redir?*/True);
956       }
957
958       p_min->count = p_min->count + (1 << 30);
959    } 
960
961    /* reset the counts, otherwise a 2nd call does not show anything anymore */ 
962    for (p = errors; p != NULL; p = p->next) {
963       if (p->count >= (1 << 30))
964          p->count = p->count - (1 << 30);
965    }
966
967
968    any_supp = show_used_suppressions();
969
970    if (any_supp) 
971       VG_(umsg)("\n");
972    // reprint this, so users don't have to scroll way up to find
973    // the first printing
974    VG_(umsg)("ERROR SUMMARY: "
975              "%d errors from %d contexts (suppressed: %d from %d)\n",
976              n_errs_found, n_err_contexts, n_errs_suppressed,
977              n_supp_contexts );
978 }
979
980 void VG_(show_last_error) ( void )
981 {
982    if (n_err_contexts == 0) {
983       VG_(umsg)("No errors yet\n");
984       return;
985    }
986
987    pp_Error( errors, False/*allow_db_attach*/, False/*xml*/ );
988 }
989
990
991 /* Show occurrence counts of all errors, in XML form. */
992 void VG_(show_error_counts_as_XML) ( void )
993 {
994    Error* err;
995    VG_(printf_xml)("<errorcounts>\n");
996    for (err = errors; err != NULL; err = err->next) {
997       if (err->supp != NULL)
998          continue;
999       if (err->count <= 0)
1000          continue;
1001       VG_(printf_xml)("  <pair>\n");
1002       VG_(printf_xml)("    <count>%d</count>\n", err->count);
1003       VG_(printf_xml)("    <unique>0x%x</unique>\n", err->unique);
1004       VG_(printf_xml)("  </pair>\n");
1005    }
1006    VG_(printf_xml)("</errorcounts>\n");
1007    VG_(printf_xml)("\n");
1008 }
1009
1010
1011 /*------------------------------------------------------------*/
1012 /*--- Suppression parsing                                  ---*/
1013 /*------------------------------------------------------------*/
1014
1015 /* Get the next char from fd into *out_buf.  Returns 1 if success,
1016    0 if eof or < 0 if error. */
1017
1018 static Int get_char ( Int fd, Char* out_buf )
1019 {
1020    Int r;
1021    static Char buf[256];
1022    static Int buf_size = 0;
1023    static Int buf_used = 0;
1024    vg_assert(buf_size >= 0 && buf_size <= 256);
1025    vg_assert(buf_used >= 0 && buf_used <= buf_size);
1026    if (buf_used == buf_size) {
1027       r = VG_(read)(fd, buf, 256);
1028       if (r < 0) return r; /* read failed */
1029       vg_assert(r >= 0 && r <= 256);
1030       buf_size = r;
1031       buf_used = 0;
1032    }
1033    if (buf_size == 0)
1034      return 0; /* eof */
1035    vg_assert(buf_size >= 0 && buf_size <= 256);
1036    vg_assert(buf_used >= 0 && buf_used < buf_size);
1037    *out_buf = buf[buf_used];
1038    buf_used++;
1039    return 1;
1040 }
1041
1042 Bool VG_(get_line) ( Int fd, Char** bufpp, SizeT* nBufp, Int* lineno )
1043 {
1044    Char* buf  = *bufpp;
1045    SizeT nBuf = *nBufp;
1046    Char  ch;
1047    Int   n, i;
1048    while (True) {
1049       /* First, read until a non-blank char appears. */
1050       while (True) {
1051          n = get_char(fd, &ch);
1052          if (n == 1 && !VG_(isspace)(ch)) break;
1053          if (n == 1 && ch == '\n' && lineno)
1054             (*lineno)++;
1055          if (n <= 0) return True;
1056       }
1057
1058       /* Now, read the line into buf. */
1059       i = 0;
1060       buf[i++] = ch; buf[i] = 0;
1061       while (True) {
1062          n = get_char(fd, &ch);
1063          if (n <= 0) return False; /* the next call will return True */
1064          if (ch == '\n' && lineno)
1065             (*lineno)++;
1066          if (ch == '\n') break;
1067          if (i > 0 && i == nBuf-1) {
1068             *nBufp = nBuf = nBuf * 2;
1069             #define RIDICULOUS   100000
1070             vg_assert2(nBuf < RIDICULOUS,  // Just a sanity check, really.
1071                "VG_(get_line): line longer than %d chars, aborting\n",
1072                RIDICULOUS);
1073             *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf);
1074          }
1075          buf[i++] = ch; buf[i] = 0;
1076       }
1077       while (i > 1 && VG_(isspace)(buf[i-1])) { 
1078          i--; buf[i] = 0; 
1079       };
1080
1081       /* VG_(printf)("The line is '%s'\n", buf); */
1082       /* Ok, we have a line.  If a non-comment line, return.
1083          If a comment line, start all over again. */
1084       if (buf[0] != '#') return False;
1085    }
1086 }
1087
1088
1089 /* *p_caller contains the raw name of a caller, supposedly either
1090        fun:some_function_name   or
1091        obj:some_object_name.
1092    Set *p_ty accordingly and advance *p_caller over the descriptor
1093    (fun: or obj:) part.
1094    Returns False if failed.
1095 */
1096 static Bool setLocationTy ( SuppLoc* p )
1097 {
1098    if (VG_(strncmp)(p->name, "fun:", 4) == 0) {
1099       p->name += 4;
1100       p->ty = FunName;
1101       return True;
1102    }
1103    if (VG_(strncmp)(p->name, "obj:", 4) == 0) {
1104       p->name += 4;
1105       p->ty = ObjName;
1106       return True;
1107    }
1108    if (VG_(strcmp)(p->name, "...") == 0) {
1109       p->name = NULL;
1110       p->ty = DotDotDot;
1111       return True;
1112    }
1113    VG_(printf)("location should be \"...\", or should start "
1114                "with \"fun:\" or \"obj:\"\n");
1115    return False;
1116 }
1117
1118
1119 /* Look for "tool" in a string like "tool1,tool2,tool3" */
1120 static Bool tool_name_present(Char *name, Char *names)
1121 {
1122    Bool  found;
1123    Char *s = NULL;   /* Shut gcc up */
1124    Int   len = VG_(strlen)(name);
1125
1126    found = (NULL != (s = VG_(strstr)(names, name)) &&
1127             (s        == names || *(s-1)   == ',') &&
1128             (*(s+len) == ','   || *(s+len) == '\0')
1129            );
1130
1131    return found;
1132 }
1133
1134 /* Read suppressions from the file specified in VG_(clo_suppressions)
1135    and place them in the suppressions list.  If there's any difficulty
1136    doing this, just give up -- there's no point in trying to recover.  
1137 */
1138 static void load_one_suppressions_file ( Char* filename )
1139 {
1140    SysRes sres;
1141    Int    fd, i, j, lineno = 0;
1142    Bool   eof;
1143    SizeT  nBuf = 200;
1144    Char*  buf = VG_(malloc)("errormgr.losf.1", nBuf);
1145    Char*  tool_names;
1146    Char*  supp_name;
1147    Char*  err_str = NULL;
1148    SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS];
1149
1150    // Check it's not a directory.
1151    if (VG_(is_dir)( filename )) {
1152       if (VG_(clo_xml))
1153          VG_(printf_xml)("</valgrindoutput>\n");
1154       VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename );
1155       VG_(exit)(1);
1156    }
1157
1158    // Open the suppression file.
1159    sres = VG_(open)( filename, VKI_O_RDONLY, 0 );
1160    if (sr_isError(sres)) {
1161       if (VG_(clo_xml))
1162          VG_(printf_xml)("</valgrindoutput>\n");
1163       VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename );
1164       VG_(exit)(1);
1165    }
1166    fd = sr_Res(sres);
1167
1168 #  define BOMB(S)  { err_str = S;  goto syntax_error; }
1169
1170    while (True) {
1171       /* Assign and initialise the two suppression halves (core and tool) */
1172       Supp* supp;
1173       supp        = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1",
1174                                       sizeof(Supp));
1175       supp->count = 0;
1176
1177       // Initialise temporary reading-in buffer.
1178       for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) {
1179          tmp_callers[i].ty   = NoName;
1180          tmp_callers[i].name = NULL;
1181       }
1182
1183       supp->string = supp->extra = NULL;
1184
1185       eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1186       if (eof) break;
1187
1188       if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file");
1189       
1190       eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1191
1192       if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'");
1193
1194       supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf);
1195
1196       eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1197
1198       if (eof) BOMB("unexpected end-of-file");
1199
1200       /* Check it has the "tool1,tool2,...:supp" form (look for ':') */
1201       i = 0;
1202       while (True) {
1203          if (buf[i] == ':')  break;
1204          if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line");
1205          i++;
1206       }
1207       buf[i]    = '\0';    /* Replace ':', splitting into two strings */
1208
1209       tool_names = & buf[0];
1210       supp_name  = & buf[i+1];
1211
1212       if (VG_(needs).core_errors && tool_name_present("core", tool_names))
1213       {
1214          // A core suppression
1215          //(example code, see comment on CoreSuppKind above)
1216          //if (VG_STREQ(supp_name, "Thread"))
1217          //   supp->skind = ThreadSupp;
1218          //else
1219             BOMB("unknown core suppression type");
1220       }
1221       else if (VG_(needs).tool_errors && 
1222                tool_name_present(VG_(details).name, tool_names))
1223       {
1224          // A tool suppression
1225          if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
1226             /* Do nothing, function fills in supp->skind */
1227          } else {
1228             BOMB("unknown tool suppression type");
1229          }
1230       }
1231       else {
1232          // Ignore rest of suppression
1233          while (True) {
1234             eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1235             if (eof) BOMB("unexpected end-of-file");
1236             if (VG_STREQ(buf, "}"))
1237                break;
1238          }
1239          continue;
1240       }
1241
1242       if (VG_(needs).tool_errors && 
1243           !VG_TDICT_CALL(tool_read_extra_suppression_info,
1244                          fd, &buf, &nBuf, supp))
1245       {
1246          BOMB("bad or missing extra suppression info");
1247       }
1248
1249       /* the main frame-descriptor reading loop */
1250       i = 0;
1251       while (True) {
1252          eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1253          if (eof)
1254             BOMB("unexpected end-of-file");
1255          if (VG_STREQ(buf, "}")) {
1256             if (i > 0) {
1257                break;
1258             } else {
1259                BOMB("missing stack trace");
1260             }
1261          }
1262          if (i == VG_MAX_SUPP_CALLERS)
1263             BOMB("too many callers in stack trace");
1264          if (i > 0 && i >= VG_(clo_backtrace_size)) 
1265             break;
1266          tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE,
1267                                                  "errormgr.losf.3", buf);
1268          if (!setLocationTy(&(tmp_callers[i])))
1269             BOMB("location should be \"...\", or should start "
1270                  "with \"fun:\" or \"obj:\"");
1271          i++;
1272       }
1273
1274       // If the num callers is >= VG_(clo_backtrace_size), ignore any extra
1275       // lines and grab the '}'.
1276       if (!VG_STREQ(buf, "}")) {
1277          do {
1278             eof = VG_(get_line) ( fd, &buf, &nBuf, &lineno );
1279          } while (!eof && !VG_STREQ(buf, "}"));
1280       }
1281
1282       // Reject entries which are entirely composed of frame
1283       // level wildcards.
1284       vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
1285       for (j = 0; j < i; j++) {
1286          if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
1287             break;
1288          vg_assert(tmp_callers[j].ty == DotDotDot);
1289       }
1290       vg_assert(j >= 0 && j <= i);
1291       if (j == i) {
1292          // we didn't find any non-"..." entries
1293          BOMB("suppression must contain at least one location "
1294               "line which is not \"...\"");
1295       } 
1296
1297       // Copy tmp_callers[] into supp->callers[]
1298       supp->n_callers = i;
1299       supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4",
1300                                         i*sizeof(SuppLoc));
1301       for (i = 0; i < supp->n_callers; i++) {
1302          supp->callers[i] = tmp_callers[i];
1303       }
1304
1305       supp->next = suppressions;
1306       suppressions = supp;
1307    }
1308    VG_(free)(buf);
1309    VG_(close)(fd);
1310    return;
1311
1312   syntax_error:
1313    if (VG_(clo_xml))
1314       VG_(printf_xml)("</valgrindoutput>\n");
1315    VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n",
1316            filename, lineno );
1317    VG_(umsg)("   %s\n", err_str );
1318    
1319    VG_(close)(fd);
1320    VG_(umsg)("exiting now.\n");
1321    VG_(exit)(1);
1322
1323 #  undef BOMB
1324 }
1325
1326
1327 void VG_(load_suppressions) ( void )
1328 {
1329    Int i;
1330    suppressions = NULL;
1331    for (i = 0; i < VG_(clo_n_suppressions); i++) {
1332       if (VG_(clo_verbosity) > 1) {
1333          VG_(dmsg)("Reading suppressions file: %s\n", 
1334                    VG_(clo_suppressions)[i] );
1335       }
1336       load_one_suppressions_file( VG_(clo_suppressions)[i] );
1337    }
1338 }
1339
1340
1341 /*------------------------------------------------------------*/
1342 /*--- Matching errors to suppressions                      ---*/
1343 /*------------------------------------------------------------*/
1344
1345 /* Parameterising functions for the use of VG_(generic_match) in
1346    suppression-vs-error matching.  The suppression frames (SuppLoc)
1347    play the role of 'pattern'-element, and the error frames (IPs,
1348    hence simply Addrs) play the role of 'input'.  In short then, we're
1349    matching a sequence of Addrs against a pattern composed of a
1350    sequence of SuppLocs.
1351 */
1352 static Bool supploc_IsStar ( void* supplocV )
1353 {
1354    SuppLoc* supploc = (SuppLoc*)supplocV;
1355    return supploc->ty == DotDotDot;
1356 }
1357
1358 static Bool supploc_IsQuery ( void* supplocV )
1359 {
1360    return False; /* there's no '?' equivalent in the supp syntax */
1361 }
1362
1363 static Bool supp_pattEQinp ( void* supplocV, void* addrV )
1364 {
1365    SuppLoc* supploc = (SuppLoc*)supplocV; /* PATTERN */
1366    Addr     ip      = *(Addr*)addrV; /* INPUT */
1367
1368    Char caller_name[ERRTXT_LEN];
1369    caller_name[0] = 0;
1370
1371    /* So, does this IP address match this suppression-line? */
1372    switch (supploc->ty) {
1373       case DotDotDot:
1374          /* supp_pattEQinp is a callback from VG_(generic_match).  As
1375             per the spec thereof (see include/pub_tool_seqmatch.h), we
1376             should never get called with a pattern value for which the
1377             _IsStar or _IsQuery function would return True.  Hence
1378             this can't happen. */
1379          vg_assert(0);
1380       case ObjName:
1381          /* Get the object name into 'caller_name', or "???"
1382             if unknown. */
1383          if (!VG_(get_objname)(ip, caller_name, ERRTXT_LEN))
1384             VG_(strcpy)(caller_name, "???");
1385          break; 
1386       case FunName: 
1387          /* Get the function name into 'caller_name', or "???"
1388             if unknown. */
1389          // Nb: C++-mangled names are used in suppressions.  Do, though,
1390          // Z-demangle them, since otherwise it's possible to wind
1391          // up comparing "malloc" in the suppression against
1392          // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
1393          // two of them need to be made to match.
1394          if (!VG_(get_fnname_no_cxx_demangle)(ip, caller_name, ERRTXT_LEN))
1395             VG_(strcpy)(caller_name, "???");
1396          break;
1397       default:
1398         vg_assert(0);
1399    }
1400
1401    /* So now we have the function or object name in caller_name, and
1402       the pattern (at the character level) to match against is in
1403       supploc->name.  Hence (and leading to a re-entrant call of
1404       VG_(generic_match)): */
1405    return VG_(string_match)(supploc->name, caller_name);
1406 }
1407
1408 /////////////////////////////////////////////////////
1409
1410 static Bool supp_matches_callers(Error* err, Supp* su)
1411 {
1412    /* Unwrap the args and set up the correct parameterisation of
1413       VG_(generic_match), using supploc_IsStar, supploc_IsQuery and
1414       supp_pattEQinp. */
1415    /* note, StackTrace === Addr* */
1416    StackTrace ips      = VG_(get_ExeContext_StackTrace)(err->where);
1417    UWord      n_ips    = VG_(get_ExeContext_n_ips)(err->where);
1418    SuppLoc*   supps    = su->callers;
1419    UWord      n_supps  = su->n_callers;
1420    UWord      szbPatt  = sizeof(SuppLoc);
1421    UWord      szbInput = sizeof(Addr);
1422    Bool       matchAll = False; /* we just want to match a prefix */
1423    return
1424       VG_(generic_match)(
1425          matchAll,
1426          /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/,
1427          /*INPUT*/ips, szbInput, n_ips,  0/*initial Ix*/,
1428          supploc_IsStar, supploc_IsQuery, supp_pattEQinp
1429       );
1430 }
1431
1432 /////////////////////////////////////////////////////
1433
1434 static
1435 Bool supp_matches_error(Supp* su, Error* err)
1436 {
1437    switch (su->skind) {
1438       //(example code, see comment on CoreSuppKind above)
1439       //case ThreadSupp:
1440       //   return (err->ekind == ThreadErr);
1441       default:
1442          if (VG_(needs).tool_errors) {
1443             return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
1444          } else {
1445             VG_(printf)(
1446                "\nUnhandled suppression type: %u.  VG_(needs).tool_errors\n"
1447                "probably needs to be set.\n",
1448                err->ekind);
1449             VG_(tool_panic)("unhandled suppression type");
1450          }
1451    }
1452 }
1453
1454 /////////////////////////////////////////////////////
1455
1456 /* Does an error context match a suppression?  ie is this a suppressible
1457    error?  If so, return a pointer to the Supp record, otherwise NULL.
1458    Tries to minimise the number of symbol searches since they are expensive.  
1459 */
1460 static Supp* is_suppressible_error ( Error* err )
1461 {
1462    Supp* su;
1463    Supp* su_prev;
1464
1465    /* stats gathering */
1466    em_supplist_searches++;
1467
1468    /* See if the error context matches any suppression. */
1469    su_prev = NULL;
1470    for (su = suppressions; su != NULL; su = su->next) {
1471       em_supplist_cmps++;
1472       if (supp_matches_error(su, err) && supp_matches_callers(err, su)) {
1473          /* got a match.  Move this entry to the head of the list
1474             in the hope of making future searches cheaper. */
1475          if (su_prev) {
1476             vg_assert(su_prev->next == su);
1477             su_prev->next = su->next;
1478             su->next = suppressions;
1479             suppressions = su;
1480          }
1481          return su;
1482       }
1483       su_prev = su;
1484    }
1485    return NULL;      /* no matches */
1486 }
1487
1488 /* Show accumulated error-list and suppression-list search stats. 
1489 */
1490 void VG_(print_errormgr_stats) ( void )
1491 {
1492    VG_(dmsg)(
1493       " errormgr: %'lu supplist searches, %'lu comparisons during search\n",
1494       em_supplist_searches, em_supplist_cmps
1495    );
1496    VG_(dmsg)(
1497       " errormgr: %'lu errlist searches, %'lu comparisons during search\n",
1498       em_errlist_searches, em_errlist_cmps
1499    );
1500 }
1501
1502 /*--------------------------------------------------------------------*/
1503 /*--- end                                                          ---*/
1504 /*--------------------------------------------------------------------*/