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