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