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