Home | History | Annotate | Download | only in helgrind
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Error management for Helgrind.                               ---*/
      4 /*---                                                  hg_errors.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Helgrind, a Valgrind tool for detecting errors
      9    in threaded programs.
     10 
     11    Copyright (C) 2007-2010 OpenWorks Ltd
     12       info (at) open-works.co.uk
     13 
     14    This program is free software; you can redistribute it and/or
     15    modify it under the terms of the GNU General Public License as
     16    published by the Free Software Foundation; either version 2 of the
     17    License, or (at your option) any later version.
     18 
     19    This program is distributed in the hope that it will be useful, but
     20    WITHOUT ANY WARRANTY; without even the implied warranty of
     21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22    General Public License for more details.
     23 
     24    You should have received a copy of the GNU General Public License
     25    along with this program; if not, write to the Free Software
     26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     27    02111-1307, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 */
     31 
     32 #include "pub_tool_basics.h"
     33 #include "pub_tool_libcbase.h"
     34 #include "pub_tool_libcassert.h"
     35 #include "pub_tool_libcprint.h"
     36 #include "pub_tool_execontext.h"
     37 #include "pub_tool_errormgr.h"
     38 #include "pub_tool_wordfm.h"
     39 #include "pub_tool_xarray.h"
     40 #include "pub_tool_debuginfo.h"
     41 #include "pub_tool_threadstate.h"
     42 #include "pub_tool_options.h"     // VG_(clo_xml)
     43 
     44 #include "hg_basics.h"
     45 #include "hg_wordset.h"
     46 #include "hg_lock_n_thread.h"
     47 #include "libhb.h"
     48 #include "hg_errors.h"            /* self */
     49 
     50 
     51 /*----------------------------------------------------------------*/
     52 /*--- Error management -- storage                              ---*/
     53 /*----------------------------------------------------------------*/
     54 
     55 /* maps (by value) strings to a copy of them in ARENA_TOOL */
     56 
     57 static WordFM* string_table = NULL;
     58 
     59 ULong HG_(stats__string_table_queries) = 0;
     60 
     61 ULong HG_(stats__string_table_get_map_size) ( void ) {
     62    return string_table ? (ULong)VG_(sizeFM)(string_table) : 0;
     63 }
     64 
     65 static Word string_table_cmp ( UWord s1, UWord s2 ) {
     66    return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
     67 }
     68 
     69 static HChar* string_table_strdup ( HChar* str ) {
     70    HChar* copy = NULL;
     71    HG_(stats__string_table_queries)++;
     72    if (!str)
     73       str = "(null)";
     74    if (!string_table) {
     75       string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1",
     76                                  HG_(free), string_table_cmp );
     77       tl_assert(string_table);
     78    }
     79    if (VG_(lookupFM)( string_table,
     80                       NULL, (Word*)&copy, (Word)str )) {
     81       tl_assert(copy);
     82       if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
     83       return copy;
     84    } else {
     85       copy = HG_(strdup)("hg.sts.2", str);
     86       tl_assert(copy);
     87       VG_(addToFM)( string_table, (Word)copy, (Word)copy );
     88       return copy;
     89    }
     90 }
     91 
     92 /* maps from Lock .unique fields to LockP*s */
     93 
     94 static WordFM* map_LockN_to_P = NULL;
     95 
     96 ULong HG_(stats__LockN_to_P_queries) = 0;
     97 
     98 ULong HG_(stats__LockN_to_P_get_map_size) ( void ) {
     99    return map_LockN_to_P ? (ULong)VG_(sizeFM)(map_LockN_to_P) : 0;
    100 }
    101 
    102 static Word lock_unique_cmp ( UWord lk1W, UWord lk2W )
    103 {
    104    Lock* lk1 = (Lock*)lk1W;
    105    Lock* lk2 = (Lock*)lk2W;
    106    tl_assert( HG_(is_sane_LockNorP)(lk1) );
    107    tl_assert( HG_(is_sane_LockNorP)(lk2) );
    108    if (lk1->unique < lk2->unique) return -1;
    109    if (lk1->unique > lk2->unique) return 1;
    110    return 0;
    111 }
    112 
    113 static Lock* mk_LockP_from_LockN ( Lock* lkn )
    114 {
    115    Lock* lkp = NULL;
    116    HG_(stats__LockN_to_P_queries)++;
    117    tl_assert( HG_(is_sane_LockN)(lkn) );
    118    if (!map_LockN_to_P) {
    119       map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1",
    120                                    HG_(free), lock_unique_cmp );
    121       tl_assert(map_LockN_to_P);
    122    }
    123    if (!VG_(lookupFM)( map_LockN_to_P, NULL, (Word*)&lkp, (Word)lkn)) {
    124       lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
    125       *lkp = *lkn;
    126       lkp->admin = NULL;
    127       lkp->magic = LockP_MAGIC;
    128       /* Forget about the bag of lock holders - don't copy that.
    129          Also, acquired_at should be NULL whenever heldBy is, and vice
    130          versa.  Also forget about the associated libhb synch object. */
    131       lkp->heldW  = False;
    132       lkp->heldBy = NULL;
    133       lkp->acquired_at = NULL;
    134       lkp->hbso = NULL;
    135       VG_(addToFM)( map_LockN_to_P, (Word)lkp, (Word)lkp );
    136    }
    137    tl_assert( HG_(is_sane_LockP)(lkp) );
    138    return lkp;
    139 }
    140 
    141 /* Errors:
    142 
    143       race: program counter
    144             read or write
    145             data size
    146             previous state
    147             current state
    148 
    149       FIXME: how does state printing interact with lockset gc?
    150       Are the locksets in prev/curr state always valid?
    151       Ditto question for the threadsets
    152           ThreadSets - probably are always valid if Threads
    153           are never thrown away.
    154           LockSets - could at least print the lockset elements that
    155           correspond to actual locks at the time of printing.  Hmm.
    156 */
    157 
    158 /* Error kinds */
    159 typedef
    160    enum {
    161       XE_Race=1101,      // race
    162       XE_UnlockUnlocked, // unlocking a not-locked lock
    163       XE_UnlockForeign,  // unlocking a lock held by some other thread
    164       XE_UnlockBogus,    // unlocking an address not known to be a lock
    165       XE_PthAPIerror,    // error from the POSIX pthreads API
    166       XE_LockOrder,      // lock order error
    167       XE_Misc            // misc other error (w/ string to describe it)
    168    }
    169    XErrorTag;
    170 
    171 /* Extra contexts for kinds */
    172 typedef
    173    struct  {
    174       XErrorTag tag;
    175       union {
    176          struct {
    177             Addr        data_addr;
    178             Int         szB;
    179             Bool        isWrite;
    180             Thread*     thr;
    181             /* descr1/2 provide a description of stack/global locs */
    182             XArray*     descr1; /* XArray* of HChar */
    183             XArray*     descr2; /* XArray* of HChar */
    184             /* halloc/haddr/hszB describe the addr if it is a heap block. */
    185             ExeContext* hctxt;
    186             Addr        haddr;
    187             SizeT       hszB;
    188             /* h1_* and h2_* provide some description of a previously
    189                observed access with which we are conflicting. */
    190             Thread*     h1_ct; /* non-NULL means h1 info present */
    191             ExeContext* h1_ct_mbsegstartEC;
    192             ExeContext* h1_ct_mbsegendEC;
    193             Thread*     h2_ct; /* non-NULL means h2 info present */
    194             ExeContext* h2_ct_accEC;
    195             Int         h2_ct_accSzB;
    196             Bool        h2_ct_accIsW;
    197          } Race;
    198          struct {
    199             Thread* thr;  /* doing the unlocking */
    200             Lock*   lock; /* lock (that is already unlocked) */
    201          } UnlockUnlocked;
    202          struct {
    203             Thread* thr;    /* doing the unlocking */
    204             Thread* owner;  /* thread that actually holds the lock */
    205             Lock*   lock;   /* lock (that is held by 'owner') */
    206          } UnlockForeign;
    207          struct {
    208             Thread* thr;     /* doing the unlocking */
    209             Addr    lock_ga; /* purported address of the lock */
    210          } UnlockBogus;
    211          struct {
    212             Thread* thr;
    213             HChar*  fnname; /* persistent, in tool-arena */
    214             Word    err;    /* pth error code */
    215             HChar*  errstr; /* persistent, in tool-arena */
    216          } PthAPIerror;
    217          struct {
    218             Thread*     thr;
    219             Addr        before_ga; /* always locked first in prog. history */
    220             Addr        after_ga;
    221             ExeContext* before_ec;
    222             ExeContext* after_ec;
    223          } LockOrder;
    224          struct {
    225             Thread*     thr;
    226             HChar*      errstr; /* persistent, in tool-arena */
    227             HChar*      auxstr; /* optional, persistent, in tool-arena */
    228             ExeContext* auxctx; /* optional */
    229          } Misc;
    230       } XE;
    231    }
    232    XError;
    233 
    234 static void init_XError ( XError* xe ) {
    235    VG_(memset)(xe, 0, sizeof(*xe) );
    236    xe->tag = XE_Race-1; /* bogus */
    237 }
    238 
    239 
    240 /* Extensions of suppressions */
    241 typedef
    242    enum {
    243       XS_Race=1201, /* race */
    244       XS_FreeMemLock,
    245       XS_UnlockUnlocked,
    246       XS_UnlockForeign,
    247       XS_UnlockBogus,
    248       XS_PthAPIerror,
    249       XS_LockOrder,
    250       XS_Misc
    251    }
    252    XSuppTag;
    253 
    254 
    255 /* Updates the copy with address info if necessary. */
    256 UInt HG_(update_extra) ( Error* err )
    257 {
    258    XError* xe = (XError*)VG_(get_error_extra)(err);
    259    tl_assert(xe);
    260    //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
    261    //   describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
    262    //}
    263 
    264    if (xe->tag == XE_Race) {
    265 
    266       /* See if we can come up with a source level description of the
    267          raced-upon address.  This is potentially expensive, which is
    268          why it's only done at the update_extra point, not when the
    269          error is initially created. */
    270       static Int xxx = 0;
    271       xxx++;
    272       if (0)
    273          VG_(printf)("HG_(update_extra): "
    274                      "%d conflicting-event queries\n", xxx);
    275 
    276       tl_assert(!xe->XE.Race.hctxt);
    277       tl_assert(!xe->XE.Race.descr1);
    278       tl_assert(!xe->XE.Race.descr2);
    279 
    280       /* First, see if it's in any heap block.  Unfortunately this
    281          means a linear search through all allocated heap blocks.  The
    282          assertion says that if it's detected as a heap block, then we
    283          must have an allocation context for it, since all heap blocks
    284          should have an allocation context. */
    285       Bool is_heapblock
    286          = HG_(mm_find_containing_block)(
    287               &xe->XE.Race.hctxt, &xe->XE.Race.haddr, &xe->XE.Race.hszB,
    288               xe->XE.Race.data_addr
    289            );
    290       tl_assert(is_heapblock == (xe->XE.Race.hctxt != NULL));
    291 
    292       if (!xe->XE.Race.hctxt) {
    293          /* It's not in any heap block.  See if we can map it to a
    294             stack or global symbol. */
    295 
    296          xe->XE.Race.descr1
    297             = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr1",
    298                           HG_(free), sizeof(HChar) );
    299          xe->XE.Race.descr2
    300             = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr2",
    301                           HG_(free), sizeof(HChar) );
    302 
    303          (void) VG_(get_data_description)( xe->XE.Race.descr1,
    304                                            xe->XE.Race.descr2,
    305                                            xe->XE.Race.data_addr );
    306 
    307          /* If there's nothing in descr1/2, free it.  Why is it safe to
    308             to VG_(indexXA) at zero here?  Because
    309             VG_(get_data_description) guarantees to zero terminate
    310             descr1/2 regardless of the outcome of the call.  So there's
    311             always at least one element in each XA after the call.
    312          */
    313          if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr1, 0 ))) {
    314             VG_(deleteXA)( xe->XE.Race.descr1 );
    315             xe->XE.Race.descr1 = NULL;
    316          }
    317          if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr2, 0 ))) {
    318             VG_(deleteXA)( xe->XE.Race.descr2 );
    319             xe->XE.Race.descr2 = NULL;
    320          }
    321       }
    322 
    323       /* And poke around in the conflicting-event map, to see if we
    324          can rustle up a plausible-looking conflicting memory access
    325          to show. */
    326       if (HG_(clo_history_level) >= 2) {
    327          Thr* thrp = NULL;
    328          ExeContext* wherep = NULL;
    329          Addr  acc_addr = xe->XE.Race.data_addr;
    330          Int   acc_szB  = xe->XE.Race.szB;
    331          Thr*  acc_thr  = xe->XE.Race.thr->hbthr;
    332          Bool  acc_isW  = xe->XE.Race.isWrite;
    333          SizeT conf_szB = 0;
    334          Bool  conf_isW = False;
    335          tl_assert(!xe->XE.Race.h2_ct_accEC);
    336          tl_assert(!xe->XE.Race.h2_ct);
    337          if (libhb_event_map_lookup(
    338                 &wherep, &thrp, &conf_szB, &conf_isW,
    339                 acc_thr, acc_addr, acc_szB, acc_isW )) {
    340             Thread* threadp;
    341             tl_assert(wherep);
    342             tl_assert(thrp);
    343             threadp = libhb_get_Thr_opaque( thrp );
    344             tl_assert(threadp);
    345             xe->XE.Race.h2_ct_accEC  = wherep;
    346             xe->XE.Race.h2_ct        = threadp;
    347             xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
    348             xe->XE.Race.h2_ct_accIsW = conf_isW;
    349         }
    350       }
    351 
    352       // both NULL or both non-NULL
    353       tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
    354    }
    355 
    356    return sizeof(XError);
    357 }
    358 
    359 void HG_(record_error_Race) ( Thread* thr,
    360                               Addr data_addr, Int szB, Bool isWrite,
    361                               Thread* h1_ct,
    362                               ExeContext* h1_ct_segstart,
    363                               ExeContext* h1_ct_mbsegendEC )
    364 {
    365    XError xe;
    366    tl_assert( HG_(is_sane_Thread)(thr) );
    367 
    368 #  if defined(VGO_linux)
    369    /* Skip any races on locations apparently in GOTPLT sections.  This
    370       is said to be caused by ld.so poking PLT table entries (or
    371       whatever) when it writes the resolved address of a dynamically
    372       linked routine, into the table (or whatever) when it is called
    373       for the first time. */
    374    {
    375      VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr );
    376      if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
    377                         data_addr, VG_(pp_SectKind)(sect));
    378      /* SectPLT is required on ???-linux */
    379      if (sect == Vg_SectGOTPLT) return;
    380      /* SectPLT is required on ppc32/64-linux */
    381      if (sect == Vg_SectPLT) return;
    382    }
    383 #  endif
    384 
    385    init_XError(&xe);
    386    xe.tag = XE_Race;
    387    xe.XE.Race.data_addr   = data_addr;
    388    xe.XE.Race.szB         = szB;
    389    xe.XE.Race.isWrite     = isWrite;
    390    xe.XE.Race.thr         = thr;
    391    tl_assert(isWrite == False || isWrite == True);
    392    tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
    393    /* Skip on the detailed description of the raced-on address at this
    394       point; it's expensive.  Leave it for the update_extra function
    395       if we ever make it that far. */
    396    tl_assert(xe.XE.Race.descr1 == NULL);
    397    tl_assert(xe.XE.Race.descr2 == NULL);
    398    // FIXME: tid vs thr
    399    // Skip on any of the conflicting-access info at this point.
    400    // It's expensive to obtain, and this error is more likely than
    401    // not to be discarded.  We'll fill these fields in in
    402    // HG_(update_extra) just above, assuming the error ever makes
    403    // it that far (unlikely).
    404    xe.XE.Race.h2_ct_accSzB = 0;
    405    xe.XE.Race.h2_ct_accIsW = False;
    406    xe.XE.Race.h2_ct_accEC  = NULL;
    407    xe.XE.Race.h2_ct        = NULL;
    408    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    409    tl_assert( thr->coretid != VG_INVALID_THREADID );
    410 
    411    xe.XE.Race.h1_ct              = h1_ct;
    412    xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
    413    xe.XE.Race.h1_ct_mbsegendEC   = h1_ct_mbsegendEC;
    414 
    415    VG_(maybe_record_error)( thr->coretid,
    416                             XE_Race, data_addr, NULL, &xe );
    417 }
    418 
    419 void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
    420 {
    421    XError xe;
    422    tl_assert( HG_(is_sane_Thread)(thr) );
    423    tl_assert( HG_(is_sane_LockN)(lk) );
    424    init_XError(&xe);
    425    xe.tag = XE_UnlockUnlocked;
    426    xe.XE.UnlockUnlocked.thr  = thr;
    427    xe.XE.UnlockUnlocked.lock = mk_LockP_from_LockN(lk);
    428    // FIXME: tid vs thr
    429    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    430    tl_assert( thr->coretid != VG_INVALID_THREADID );
    431    VG_(maybe_record_error)( thr->coretid,
    432                             XE_UnlockUnlocked, 0, NULL, &xe );
    433 }
    434 
    435 void HG_(record_error_UnlockForeign) ( Thread* thr,
    436                                        Thread* owner, Lock* lk )
    437 {
    438    XError xe;
    439    tl_assert( HG_(is_sane_Thread)(thr) );
    440    tl_assert( HG_(is_sane_Thread)(owner) );
    441    tl_assert( HG_(is_sane_LockN)(lk) );
    442    init_XError(&xe);
    443    xe.tag = XE_UnlockForeign;
    444    xe.XE.UnlockForeign.thr   = thr;
    445    xe.XE.UnlockForeign.owner = owner;
    446    xe.XE.UnlockForeign.lock  = mk_LockP_from_LockN(lk);
    447    // FIXME: tid vs thr
    448    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    449    tl_assert( thr->coretid != VG_INVALID_THREADID );
    450    VG_(maybe_record_error)( thr->coretid,
    451                             XE_UnlockForeign, 0, NULL, &xe );
    452 }
    453 
    454 void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
    455 {
    456    XError xe;
    457    tl_assert( HG_(is_sane_Thread)(thr) );
    458    init_XError(&xe);
    459    xe.tag = XE_UnlockBogus;
    460    xe.XE.UnlockBogus.thr     = thr;
    461    xe.XE.UnlockBogus.lock_ga = lock_ga;
    462    // FIXME: tid vs thr
    463    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    464    tl_assert( thr->coretid != VG_INVALID_THREADID );
    465    VG_(maybe_record_error)( thr->coretid,
    466                             XE_UnlockBogus, 0, NULL, &xe );
    467 }
    468 
    469 void HG_(record_error_LockOrder)(
    470         Thread* thr, Addr before_ga, Addr after_ga,
    471         ExeContext* before_ec, ExeContext* after_ec
    472      )
    473 {
    474    XError xe;
    475    tl_assert( HG_(is_sane_Thread)(thr) );
    476    if (!HG_(clo_track_lockorders))
    477       return;
    478    init_XError(&xe);
    479    xe.tag = XE_LockOrder;
    480    xe.XE.LockOrder.thr       = thr;
    481    xe.XE.LockOrder.before_ga = before_ga;
    482    xe.XE.LockOrder.before_ec = before_ec;
    483    xe.XE.LockOrder.after_ga  = after_ga;
    484    xe.XE.LockOrder.after_ec  = after_ec;
    485    // FIXME: tid vs thr
    486    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    487    tl_assert( thr->coretid != VG_INVALID_THREADID );
    488    VG_(maybe_record_error)( thr->coretid,
    489                             XE_LockOrder, 0, NULL, &xe );
    490 }
    491 
    492 void HG_(record_error_PthAPIerror) ( Thread* thr, HChar* fnname,
    493                                      Word err, HChar* errstr )
    494 {
    495    XError xe;
    496    tl_assert( HG_(is_sane_Thread)(thr) );
    497    tl_assert(fnname);
    498    tl_assert(errstr);
    499    init_XError(&xe);
    500    xe.tag = XE_PthAPIerror;
    501    xe.XE.PthAPIerror.thr    = thr;
    502    xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
    503    xe.XE.PthAPIerror.err    = err;
    504    xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
    505    // FIXME: tid vs thr
    506    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    507    tl_assert( thr->coretid != VG_INVALID_THREADID );
    508    VG_(maybe_record_error)( thr->coretid,
    509                             XE_PthAPIerror, 0, NULL, &xe );
    510 }
    511 
    512 void HG_(record_error_Misc_w_aux) ( Thread* thr, HChar* errstr,
    513                                     HChar* auxstr, ExeContext* auxctx )
    514 {
    515    XError xe;
    516    tl_assert( HG_(is_sane_Thread)(thr) );
    517    tl_assert(errstr);
    518    init_XError(&xe);
    519    xe.tag = XE_Misc;
    520    xe.XE.Misc.thr    = thr;
    521    xe.XE.Misc.errstr = string_table_strdup(errstr);
    522    xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
    523    xe.XE.Misc.auxctx = auxctx;
    524    // FIXME: tid vs thr
    525    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
    526    tl_assert( thr->coretid != VG_INVALID_THREADID );
    527    VG_(maybe_record_error)( thr->coretid,
    528                             XE_Misc, 0, NULL, &xe );
    529 }
    530 
    531 void HG_(record_error_Misc) ( Thread* thr, HChar* errstr )
    532 {
    533    HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
    534 }
    535 
    536 Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 )
    537 {
    538    XError *xe1, *xe2;
    539 
    540    tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
    541 
    542    xe1 = (XError*)VG_(get_error_extra)(e1);
    543    xe2 = (XError*)VG_(get_error_extra)(e2);
    544    tl_assert(xe1);
    545    tl_assert(xe2);
    546 
    547    switch (VG_(get_error_kind)(e1)) {
    548       case XE_Race:
    549          return xe1->XE.Race.szB == xe2->XE.Race.szB
    550                 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
    551                 && (HG_(clo_cmp_race_err_addrs)
    552                        ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
    553                        : True);
    554       case XE_UnlockUnlocked:
    555          return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
    556                 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
    557       case XE_UnlockForeign:
    558          return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
    559                 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
    560                 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
    561       case XE_UnlockBogus:
    562          return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
    563                 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
    564       case XE_PthAPIerror:
    565          return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
    566                 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
    567                                   xe2->XE.PthAPIerror.fnname)
    568                 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
    569       case XE_LockOrder:
    570          return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
    571       case XE_Misc:
    572          return xe1->XE.Misc.thr == xe2->XE.Misc.thr
    573                 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
    574       default:
    575          tl_assert(0);
    576    }
    577 
    578    /*NOTREACHED*/
    579    tl_assert(0);
    580 }
    581 
    582 
    583 /*----------------------------------------------------------------*/
    584 /*--- Error management -- printing                             ---*/
    585 /*----------------------------------------------------------------*/
    586 
    587 /* Do a printf-style operation on either the XML or normal output
    588    channel, depending on the setting of VG_(clo_xml).
    589 */
    590 static void emit_WRK ( HChar* format, va_list vargs )
    591 {
    592    if (VG_(clo_xml)) {
    593       VG_(vprintf_xml)(format, vargs);
    594    } else {
    595       VG_(vmessage)(Vg_UserMsg, format, vargs);
    596    }
    597 }
    598 static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
    599 static void emit ( HChar* format, ... )
    600 {
    601    va_list vargs;
    602    va_start(vargs, format);
    603    emit_WRK(format, vargs);
    604    va_end(vargs);
    605 }
    606 static void emit_no_f_c ( HChar* format, ... )
    607 {
    608    va_list vargs;
    609    va_start(vargs, format);
    610    emit_WRK(format, vargs);
    611    va_end(vargs);
    612 }
    613 
    614 
    615 /* Announce (that is, print the point-of-creation) of 'thr'.  Only do
    616    this once, as we only want to see these announcements once per
    617    thread.  Returned Bool indicates whether or not an announcement was
    618    made.
    619 */
    620 static Bool announce_one_thread ( Thread* thr )
    621 {
    622    tl_assert(HG_(is_sane_Thread)(thr));
    623    tl_assert(thr->errmsg_index >= 1);
    624    if (thr->announced)
    625       return False;
    626 
    627    if (VG_(clo_xml)) {
    628 
    629       VG_(printf_xml)("<announcethread>\n");
    630       VG_(printf_xml)("  <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
    631       if (thr->errmsg_index == 1) {
    632          tl_assert(thr->created_at == NULL);
    633          VG_(printf_xml)("  <isrootthread></isrootthread>\n");
    634       } else {
    635          tl_assert(thr->created_at != NULL);
    636          VG_(pp_ExeContext)( thr->created_at );
    637       }
    638       VG_(printf_xml)("</announcethread>\n\n");
    639 
    640    } else {
    641 
    642       if (thr->errmsg_index == 1) {
    643          tl_assert(thr->created_at == NULL);
    644          VG_(message)(Vg_UserMsg,
    645                       "Thread #%d is the program's root thread\n",
    646                        thr->errmsg_index);
    647       } else {
    648          tl_assert(thr->created_at != NULL);
    649          VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
    650                                   thr->errmsg_index);
    651          VG_(pp_ExeContext)( thr->created_at );
    652       }
    653       VG_(message)(Vg_UserMsg, "\n");
    654 
    655    }
    656 
    657    thr->announced = True;
    658    return True;
    659 }
    660 
    661 
    662 /* This is the "this error is due to be printed shortly; so have a
    663    look at it any print any preamble you want" function.  We use it to
    664    announce any previously un-announced threads in the upcoming error
    665    message.
    666 */
    667 void HG_(before_pp_Error) ( Error* err )
    668 {
    669    XError* xe;
    670    tl_assert(err);
    671    xe = (XError*)VG_(get_error_extra)(err);
    672    tl_assert(xe);
    673 
    674    switch (VG_(get_error_kind)(err)) {
    675       case XE_Misc:
    676          announce_one_thread( xe->XE.Misc.thr );
    677          break;
    678       case XE_LockOrder:
    679          announce_one_thread( xe->XE.LockOrder.thr );
    680          break;
    681       case XE_PthAPIerror:
    682          announce_one_thread( xe->XE.PthAPIerror.thr );
    683          break;
    684       case XE_UnlockBogus:
    685          announce_one_thread( xe->XE.UnlockBogus.thr );
    686          break;
    687       case XE_UnlockForeign:
    688          announce_one_thread( xe->XE.UnlockForeign.thr );
    689          announce_one_thread( xe->XE.UnlockForeign.owner );
    690          break;
    691       case XE_UnlockUnlocked:
    692          announce_one_thread( xe->XE.UnlockUnlocked.thr );
    693          break;
    694       case XE_Race:
    695          announce_one_thread( xe->XE.Race.thr );
    696          if (xe->XE.Race.h2_ct)
    697             announce_one_thread( xe->XE.Race.h2_ct );
    698          if (xe->XE.Race.h1_ct)
    699             announce_one_thread( xe->XE.Race.h1_ct );
    700          break;
    701       default:
    702          tl_assert(0);
    703    }
    704 }
    705 
    706 void HG_(pp_Error) ( Error* err )
    707 {
    708    const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
    709 
    710    XError *xe = (XError*)VG_(get_error_extra)(err);
    711    tl_assert(xe);
    712 
    713    switch (VG_(get_error_kind)(err)) {
    714 
    715    case XE_Misc: {
    716       tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
    717 
    718       if (xml) {
    719 
    720          emit( "  <kind>Misc</kind>\n");
    721          emit( "  <xwhat>\n" );
    722          emit( "    <text>Thread #%d: %s</text>\n",
    723                (Int)xe->XE.Misc.thr->errmsg_index,
    724                xe->XE.Misc.errstr );
    725          emit( "    <hthreadid>%d</hthreadid>\n",
    726                (Int)xe->XE.Misc.thr->errmsg_index );
    727          emit( "  </xwhat>\n" );
    728          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    729          if (xe->XE.Misc.auxstr) {
    730             emit("  <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
    731             if (xe->XE.Misc.auxctx)
    732                VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
    733          }
    734 
    735       } else {
    736 
    737          emit( "Thread #%d: %s\n",
    738                (Int)xe->XE.Misc.thr->errmsg_index,
    739                xe->XE.Misc.errstr );
    740          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    741          if (xe->XE.Misc.auxstr) {
    742             emit(" %s\n", xe->XE.Misc.auxstr);
    743             if (xe->XE.Misc.auxctx)
    744                VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
    745          }
    746 
    747       }
    748       break;
    749    }
    750 
    751    case XE_LockOrder: {
    752       tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
    753 
    754       if (xml) {
    755 
    756          emit( "  <kind>LockOrder</kind>\n");
    757          emit( "  <xwhat>\n" );
    758          emit( "    <text>Thread #%d: lock order \"%p before %p\" "
    759                     "violated</text>\n",
    760                (Int)xe->XE.LockOrder.thr->errmsg_index,
    761                (void*)xe->XE.LockOrder.before_ga,
    762                (void*)xe->XE.LockOrder.after_ga );
    763          emit( "    <hthreadid>%d</hthreadid>\n",
    764                (Int)xe->XE.LockOrder.thr->errmsg_index );
    765          emit( "  </xwhat>\n" );
    766          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    767          if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
    768             emit( "  <auxwhat>Required order was established by "
    769                   "acquisition of lock at %p</auxwhat>\n",
    770                   (void*)xe->XE.LockOrder.before_ga );
    771             VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
    772             emit( "  <auxwhat>followed by a later acquisition "
    773                   "of lock at %p</auxwhat>\n",
    774                   (void*)xe->XE.LockOrder.after_ga );
    775             VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
    776          }
    777 
    778       } else {
    779 
    780          emit( "Thread #%d: lock order \"%p before %p\" violated\n",
    781                (Int)xe->XE.LockOrder.thr->errmsg_index,
    782                (void*)xe->XE.LockOrder.before_ga,
    783                (void*)xe->XE.LockOrder.after_ga );
    784          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    785          if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
    786             emit( "  Required order was established by "
    787                   "acquisition of lock at %p\n",
    788                   (void*)xe->XE.LockOrder.before_ga );
    789             VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
    790             emit( "  followed by a later acquisition of lock at %p\n",
    791                   (void*)xe->XE.LockOrder.after_ga );
    792             VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
    793          }
    794 
    795       }
    796 
    797       break;
    798    }
    799 
    800    case XE_PthAPIerror: {
    801       tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
    802 
    803       if (xml) {
    804 
    805          emit( "  <kind>PthAPIerror</kind>\n");
    806          emit( "  <xwhat>\n" );
    807          emit_no_f_c(
    808             "    <text>Thread #%d's call to %t failed</text>\n",
    809             (Int)xe->XE.PthAPIerror.thr->errmsg_index,
    810             xe->XE.PthAPIerror.fnname );
    811          emit( "    <hthreadid>%d</hthreadid>\n",
    812                (Int)xe->XE.PthAPIerror.thr->errmsg_index );
    813          emit( "  </xwhat>\n" );
    814          emit( "  <what>with error code %ld (%s)</what>\n",
    815                xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
    816          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    817 
    818       } else {
    819 
    820          emit_no_f_c( "Thread #%d's call to %t failed\n",
    821                       (Int)xe->XE.PthAPIerror.thr->errmsg_index,
    822                       xe->XE.PthAPIerror.fnname );
    823          emit( "   with error code %ld (%s)\n",
    824                xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
    825          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    826 
    827       }
    828 
    829       break;
    830    }
    831 
    832    case XE_UnlockBogus: {
    833       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
    834 
    835       if (xml) {
    836 
    837          emit( "  <kind>UnlockBogus</kind>\n");
    838          emit( "  <xwhat>\n" );
    839          emit( "    <text>Thread #%d unlocked an invalid "
    840                     "lock at %p</text>\n",
    841                (Int)xe->XE.UnlockBogus.thr->errmsg_index,
    842                (void*)xe->XE.UnlockBogus.lock_ga );
    843          emit( "    <hthreadid>%d</hthreadid>\n",
    844                (Int)xe->XE.UnlockBogus.thr->errmsg_index );
    845          emit( "  </xwhat>\n" );
    846          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    847 
    848       } else {
    849 
    850          emit( "Thread #%d unlocked an invalid lock at %p\n",
    851                (Int)xe->XE.UnlockBogus.thr->errmsg_index,
    852                (void*)xe->XE.UnlockBogus.lock_ga );
    853          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    854 
    855       }
    856 
    857       break;
    858    }
    859 
    860    case XE_UnlockForeign: {
    861       tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
    862       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
    863       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
    864 
    865       if (xml) {
    866 
    867          emit( "  <kind>UnlockForeign</kind>\n");
    868          emit( "  <xwhat>\n" );
    869          emit( "    <text>Thread #%d unlocked lock at %p "
    870                     "currently held by thread #%d</text>\n",
    871                (Int)xe->XE.UnlockForeign.thr->errmsg_index,
    872                (void*)xe->XE.UnlockForeign.lock->guestaddr,
    873                (Int)xe->XE.UnlockForeign.owner->errmsg_index );
    874          emit( "    <hthreadid>%d</hthreadid>\n",
    875                (Int)xe->XE.UnlockForeign.thr->errmsg_index );
    876          emit( "    <hthreadid>%d</hthreadid>\n",
    877                (Int)xe->XE.UnlockForeign.owner->errmsg_index );
    878          emit( "  </xwhat>\n" );
    879          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    880 
    881          if (xe->XE.UnlockForeign.lock->appeared_at) {
    882             emit( "  <auxwhat>Lock at %p was first observed</auxwhat>\n",
    883                   (void*)xe->XE.UnlockForeign.lock->guestaddr );
    884             VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
    885          }
    886 
    887       } else {
    888 
    889          emit( "Thread #%d unlocked lock at %p "
    890                "currently held by thread #%d\n",
    891                (Int)xe->XE.UnlockForeign.thr->errmsg_index,
    892                (void*)xe->XE.UnlockForeign.lock->guestaddr,
    893                (Int)xe->XE.UnlockForeign.owner->errmsg_index );
    894          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    895          if (xe->XE.UnlockForeign.lock->appeared_at) {
    896             emit( "  Lock at %p was first observed\n",
    897                   (void*)xe->XE.UnlockForeign.lock->guestaddr );
    898             VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
    899          }
    900 
    901       }
    902 
    903       break;
    904    }
    905 
    906    case XE_UnlockUnlocked: {
    907       tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
    908       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
    909 
    910       if (xml) {
    911 
    912          emit( "  <kind>UnlockUnlocked</kind>\n");
    913          emit( "  <xwhat>\n" );
    914          emit( "    <text>Thread #%d unlocked a "
    915                     "not-locked lock at %p</text>\n",
    916                (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
    917                (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
    918          emit( "    <hthreadid>%d</hthreadid>\n",
    919                (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
    920          emit( "  </xwhat>\n" );
    921          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    922          if (xe->XE.UnlockUnlocked.lock->appeared_at) {
    923             emit( "  <auxwhat>Lock at %p was first observed</auxwhat>\n",
    924                   (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
    925             VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
    926          }
    927 
    928       } else {
    929 
    930          emit( "Thread #%d unlocked a not-locked lock at %p\n",
    931                (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
    932                (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
    933          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    934          if (xe->XE.UnlockUnlocked.lock->appeared_at) {
    935             emit( "  Lock at %p was first observed\n",
    936                   (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
    937             VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
    938          }
    939 
    940       }
    941 
    942       break;
    943    }
    944 
    945    case XE_Race: {
    946       Addr      err_ga;
    947       HChar*    what;
    948       Int       szB;
    949       what      = xe->XE.Race.isWrite ? "write" : "read";
    950       szB       = xe->XE.Race.szB;
    951       err_ga = VG_(get_error_address)(err);
    952 
    953       tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
    954       if (xe->XE.Race.h2_ct)
    955          tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
    956 
    957       if (xml) {
    958 
    959          /* ------ XML ------ */
    960          emit( "  <kind>Race</kind>\n" );
    961          emit( "  <xwhat>\n" );
    962          emit( "    <text>Possible data race during %s of size %d "
    963                     "at %#lx by thread #%d</text>\n",
    964               what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
    965          emit( "    <hthreadid>%d</hthreadid>\n",
    966                (Int)xe->XE.Race.thr->errmsg_index );
    967          emit( "  </xwhat>\n" );
    968          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    969 
    970          if (xe->XE.Race.h2_ct) {
    971             tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
    972             emit( "  <xauxwhat>\n");
    973             emit( "    <text>This conflicts with a previous %s of size %d "
    974                             "by thread #%d</text>\n",
    975                   xe->XE.Race.h2_ct_accIsW ? "write" : "read",
    976                   xe->XE.Race.h2_ct_accSzB,
    977                   xe->XE.Race.h2_ct->errmsg_index );
    978             emit( "    <hthreadid>%d</hthreadid>\n",
    979                   xe->XE.Race.h2_ct->errmsg_index);
    980             emit("  </xauxwhat>\n");
    981             VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
    982          }
    983 
    984          if (xe->XE.Race.h1_ct) {
    985             emit( "  <xauxwhat>\n");
    986             emit( "    <text>This conflicts with a previous access "
    987                   "by thread #%d, after</text>\n",
    988                   xe->XE.Race.h1_ct->errmsg_index );
    989             emit( "    <hthreadid>%d</hthreadid>\n",
    990                   xe->XE.Race.h1_ct->errmsg_index );
    991             emit("  </xauxwhat>\n");
    992             if (xe->XE.Race.h1_ct_mbsegstartEC) {
    993                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
    994             } else {
    995                emit( "  <auxwhat>(the start of the thread)</auxwhat>\n" );
    996             }
    997             emit( "  <auxwhat>but before</auxwhat>\n" );
    998             if (xe->XE.Race.h1_ct_mbsegendEC) {
    999                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
   1000             } else {
   1001                emit( "  <auxwhat>(the end of the the thread)</auxwhat>\n" );
   1002             }
   1003          }
   1004 
   1005       } else {
   1006 
   1007          /* ------ Text ------ */
   1008          emit( "Possible data race during %s of size %d "
   1009                "at %#lx by thread #%d\n",
   1010                what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
   1011          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
   1012 
   1013          if (xe->XE.Race.h2_ct) {
   1014             tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
   1015             emit( " This conflicts with a previous %s of size %d "
   1016                   "by thread #%d\n",
   1017                   xe->XE.Race.h2_ct_accIsW ? "write" : "read",
   1018                   xe->XE.Race.h2_ct_accSzB,
   1019                   xe->XE.Race.h2_ct->errmsg_index );
   1020             VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
   1021          }
   1022 
   1023          if (xe->XE.Race.h1_ct) {
   1024             emit( " This conflicts with a previous access by thread #%d, "
   1025                   "after\n",
   1026                   xe->XE.Race.h1_ct->errmsg_index );
   1027             if (xe->XE.Race.h1_ct_mbsegstartEC) {
   1028                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
   1029             } else {
   1030                emit( "   (the start of the thread)\n" );
   1031             }
   1032             emit( " but before\n" );
   1033             if (xe->XE.Race.h1_ct_mbsegendEC) {
   1034                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
   1035             } else {
   1036                emit( "   (the end of the the thread)\n" );
   1037             }
   1038          }
   1039 
   1040       }
   1041 
   1042       /* If we have a description of the address in terms of a heap
   1043          block, show it. */
   1044       if (xe->XE.Race.hctxt) {
   1045          SizeT delta = err_ga - xe->XE.Race.haddr;
   1046          if (xml) {
   1047             emit("  <auxwhat>Address %#lx is %ld bytes inside a block "
   1048                  "of size %ld alloc'd</auxwhat>\n", err_ga, delta,
   1049                  xe->XE.Race.hszB);
   1050             VG_(pp_ExeContext)( xe->XE.Race.hctxt );
   1051          } else {
   1052             emit(" Address %#lx is %ld bytes inside a block "
   1053                  "of size %ld alloc'd\n", err_ga, delta,
   1054                  xe->XE.Race.hszB);
   1055             VG_(pp_ExeContext)( xe->XE.Race.hctxt );
   1056          }
   1057       }
   1058 
   1059       /* If we have a better description of the address, show it.
   1060          Note that in XML mode, it will already by nicely wrapped up
   1061          in tags, either <auxwhat> or <xauxwhat>, so we can just emit
   1062          it verbatim. */
   1063       if (xe->XE.Race.descr1)
   1064          emit( "%s%s\n", xml ? "  " : " ",
   1065                          (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
   1066       if (xe->XE.Race.descr2)
   1067          emit( "%s%s\n", xml ? "  " : " ",
   1068                          (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
   1069 
   1070       break; /* case XE_Race */
   1071    } /* case XE_Race */
   1072 
   1073    default:
   1074       tl_assert(0);
   1075    } /* switch (VG_(get_error_kind)(err)) */
   1076 }
   1077 
   1078 Char* HG_(get_error_name) ( Error* err )
   1079 {
   1080    switch (VG_(get_error_kind)(err)) {
   1081       case XE_Race:           return "Race";
   1082       case XE_UnlockUnlocked: return "UnlockUnlocked";
   1083       case XE_UnlockForeign:  return "UnlockForeign";
   1084       case XE_UnlockBogus:    return "UnlockBogus";
   1085       case XE_PthAPIerror:    return "PthAPIerror";
   1086       case XE_LockOrder:      return "LockOrder";
   1087       case XE_Misc:           return "Misc";
   1088       default: tl_assert(0); /* fill in missing case */
   1089    }
   1090 }
   1091 
   1092 Bool HG_(recognised_suppression) ( Char* name, Supp *su )
   1093 {
   1094 #  define TRY(_name,_xskind)                   \
   1095       if (0 == VG_(strcmp)(name, (_name))) {   \
   1096          VG_(set_supp_kind)(su, (_xskind));    \
   1097          return True;                          \
   1098       }
   1099    TRY("Race",           XS_Race);
   1100    TRY("FreeMemLock",    XS_FreeMemLock);
   1101    TRY("UnlockUnlocked", XS_UnlockUnlocked);
   1102    TRY("UnlockForeign",  XS_UnlockForeign);
   1103    TRY("UnlockBogus",    XS_UnlockBogus);
   1104    TRY("PthAPIerror",    XS_PthAPIerror);
   1105    TRY("LockOrder",      XS_LockOrder);
   1106    TRY("Misc",           XS_Misc);
   1107    return False;
   1108 #  undef TRY
   1109 }
   1110 
   1111 Bool HG_(read_extra_suppression_info) ( Int fd, Char** bufpp, SizeT* nBufp,
   1112                                         Supp* su )
   1113 {
   1114    /* do nothing -- no extra suppression info present.  Return True to
   1115       indicate nothing bad happened. */
   1116    return True;
   1117 }
   1118 
   1119 Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
   1120 {
   1121    switch (VG_(get_supp_kind)(su)) {
   1122    case XS_Race:           return VG_(get_error_kind)(err) == XE_Race;
   1123    case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
   1124    case XS_UnlockForeign:  return VG_(get_error_kind)(err) == XE_UnlockForeign;
   1125    case XS_UnlockBogus:    return VG_(get_error_kind)(err) == XE_UnlockBogus;
   1126    case XS_PthAPIerror:    return VG_(get_error_kind)(err) == XE_PthAPIerror;
   1127    case XS_LockOrder:      return VG_(get_error_kind)(err) == XE_LockOrder;
   1128    case XS_Misc:           return VG_(get_error_kind)(err) == XE_Misc;
   1129    //case XS_: return VG_(get_error_kind)(err) == XE_;
   1130    default: tl_assert(0); /* fill in missing cases */
   1131    }
   1132 }
   1133 
   1134 Bool HG_(get_extra_suppression_info) ( Error* err,
   1135                                        /*OUT*/Char* buf, Int nBuf )
   1136 {
   1137    /* Do nothing */
   1138    return False;
   1139 }
   1140 
   1141 
   1142 /*--------------------------------------------------------------------*/
   1143 /*--- end                                              hg_errors.c ---*/
   1144 /*--------------------------------------------------------------------*/
   1145