• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
VG_(get_error_where)142 ExeContext* VG_(get_error_where) ( Error* err )
143 {
144    return err->where;
145 }
146 
VG_(get_error_kind)147 ErrorKind VG_(get_error_kind) ( Error* err )
148 {
149    return err->ekind;
150 }
151 
VG_(get_error_address)152 Addr VG_(get_error_address) ( Error* err )
153 {
154    return err->addr;
155 }
156 
VG_(get_error_string)157 Char* VG_(get_error_string) ( Error* err )
158 {
159    return err->string;
160 }
161 
VG_(get_error_extra)162 void* VG_(get_error_extra)  ( Error* err )
163 {
164    return err->extra;
165 }
166 
VG_(get_n_errs_found)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 
VG_(get_supp_kind)229 SuppKind VG_(get_supp_kind) ( Supp* su )
230 {
231    return su->skind;
232 }
233 
VG_(get_supp_string)234 Char* VG_(get_supp_string) ( Supp* su )
235 {
236    return su->string;
237 }
238 
VG_(get_supp_extra)239 void* VG_(get_supp_extra)  ( Supp* su )
240 {
241    return su->extra;
242 }
243 
244 
VG_(set_supp_kind)245 void VG_(set_supp_kind)   ( Supp* su, SuppKind skind )
246 {
247    su->skind = skind;
248 }
249 
VG_(set_supp_string)250 void VG_(set_supp_string) ( Supp* su, Char* string )
251 {
252    su->string = string;
253 }
254 
VG_(set_supp_extra)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.
VG_(showing_core_errors)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 */
eq_Error(VgRes res,Error * e1,Error * e2)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 
printSuppForIp_XML(UInt n,Addr ip,void * uu_opaque)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 
printSuppForIp_nonXML(UInt n,Addr ip,void * textV)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 */
gen_suppression(Error * err)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    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 */
VG_(is_action_requested)436 Bool 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 */
488 static
do_actions_on_error(Error * err,Bool allow_db_attach)489 void 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
515 static Bool seen_pc_with_no_function_name_nor_object_file_name = False;
516 
ErrHasNoFunctionNamesNorObjectFileNames(Error * err)517 static 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 */
pp_Error(Error * err,Bool allow_db_attach)570 static 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 */
624 static
construct_error(Error * err,ThreadId tid,ErrorKind ekind,Addr a,Char * s,void * extra,ExeContext * where)625 void 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 
656 static 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. */
VG_(maybe_record_error)661 void 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 */
VG_(unique_error)836 Bool 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. */
show_used_suppressions(void)887 static 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. */
VG_(show_all_errors)923 void 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. */
VG_(show_error_counts_as_XML)997 void 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 
get_char(Int fd,Char * out_buf)1023 static 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 
VG_(get_line)1047 Bool 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 */
setLocationTy(SuppLoc * p)1101 static 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" */
tool_name_present(Char * name,Char * names)1125 static 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 */
load_one_suppressions_file(Char * filename)1143 static 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 
VG_(load_suppressions)1332 void 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 */
supploc_IsStar(void * supplocV)1357 static Bool supploc_IsStar ( void* supplocV )
1358 {
1359    SuppLoc* supploc = (SuppLoc*)supplocV;
1360    return supploc->ty == DotDotDot;
1361 }
1362 
supploc_IsQuery(void * supplocV)1363 static Bool supploc_IsQuery ( void* supplocV )
1364 {
1365    return False; /* there's no '?' equivalent in the supp syntax */
1366 }
1367 
supp_pattEQinp(void * supplocV,void * addrV)1368 static 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 
supp_matches_callers(Error * err,Supp * su)1415 static 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 
1439 static
supp_matches_error(Supp * su,Error * err)1440 Bool 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 */
is_suppressible_error(Error * err)1465 static 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 */
VG_(print_errormgr_stats)1495 void 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