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