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