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