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