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