• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2017 OpenWorks Ltd
12       info@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_stacktrace.h"
37 #include "pub_tool_execontext.h"
38 #include "pub_tool_errormgr.h"
39 #include "pub_tool_wordfm.h"
40 #include "pub_tool_xarray.h"
41 #include "pub_tool_debuginfo.h"
42 #include "pub_tool_threadstate.h"
43 #include "pub_tool_options.h"     // VG_(clo_xml)
44 #include "pub_tool_aspacemgr.h"
45 #include "pub_tool_addrinfo.h"
46 
47 #include "hg_basics.h"
48 #include "hg_addrdescr.h"
49 #include "hg_wordset.h"
50 #include "hg_lock_n_thread.h"
51 #include "libhb.h"
52 #include "hg_errors.h"            /* self */
53 
54 
55 /*----------------------------------------------------------------*/
56 /*--- Error management -- storage                              ---*/
57 /*----------------------------------------------------------------*/
58 
59 /* maps (by value) strings to a copy of them in ARENA_TOOL */
60 
61 static WordFM* string_table = NULL;
62 
63 ULong HG_(stats__string_table_queries) = 0;
64 
HG_(stats__string_table_get_map_size)65 ULong HG_(stats__string_table_get_map_size) ( void ) {
66    return string_table ? (ULong)VG_(sizeFM)(string_table) : 0;
67 }
68 
string_table_cmp(UWord s1,UWord s2)69 static Word string_table_cmp ( UWord s1, UWord s2 ) {
70    return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
71 }
72 
string_table_strdup(const HChar * str)73 static HChar* string_table_strdup ( const HChar* str ) {
74    HChar* copy = NULL;
75    HG_(stats__string_table_queries)++;
76    if (!str)
77       str = "(null)";
78    if (!string_table) {
79       string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1",
80                                  HG_(free), string_table_cmp );
81    }
82    if (VG_(lookupFM)( string_table,
83                       NULL, (UWord*)&copy, (UWord)str )) {
84       tl_assert(copy);
85       if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
86       return copy;
87    } else {
88       copy = HG_(strdup)("hg.sts.2", str);
89       VG_(addToFM)( string_table, (UWord)copy, (UWord)copy );
90       return copy;
91    }
92 }
93 
94 /* maps from Lock .unique fields to LockP*s */
95 
96 static WordFM* map_LockN_to_P = NULL;
97 
98 ULong HG_(stats__LockN_to_P_queries) = 0;
99 
HG_(stats__LockN_to_P_get_map_size)100 ULong HG_(stats__LockN_to_P_get_map_size) ( void ) {
101    return map_LockN_to_P ? (ULong)VG_(sizeFM)(map_LockN_to_P) : 0;
102 }
103 
lock_unique_cmp(UWord lk1W,UWord lk2W)104 static Word lock_unique_cmp ( UWord lk1W, UWord lk2W )
105 {
106    Lock* lk1 = (Lock*)lk1W;
107    Lock* lk2 = (Lock*)lk2W;
108    tl_assert( HG_(is_sane_LockNorP)(lk1) );
109    tl_assert( HG_(is_sane_LockNorP)(lk2) );
110    if (lk1->unique < lk2->unique) return -1;
111    if (lk1->unique > lk2->unique) return 1;
112    return 0;
113 }
114 
115 /* Given a normal Lock (LockN), convert it to a persistent Lock
116    (LockP).  In some cases the LockN could be invalid (if it's been
117    freed), so we enquire, in hg_main.c's admin_locks list, whether it
118    is in fact valid.  If allowed_to_be_invalid is True, then it's OK
119    for the LockN to be invalid, in which case Lock_INVALID is
120    returned.  In all other cases, we insist that the LockN is a valid
121    lock, and return its corresponding LockP.
122 
123    Why can LockNs sometimes be invalid?  Because they are harvested
124    from locksets that are attached to the OldRef info for conflicting
125    threads.  By the time we detect a race, the some of the elements of
126    the lockset may have been destroyed by the client, in which case
127    the corresponding Lock structures we maintain will have been freed.
128 
129    So we check that each LockN is a member of the admin_locks double
130    linked list of all Lock structures.  That stops us prodding around
131    in potentially freed-up Lock structures.  However, it's not quite a
132    proper check: if a new Lock has been reallocated at the same
133    address as one which was previously freed, we'll wind up copying
134    the new one as the basis for the LockP, which is completely bogus
135    because it is unrelated to the previous Lock that lived there.
136    Let's hope that doesn't happen too often.
137 */
mk_LockP_from_LockN(Lock * lkn,Bool allowed_to_be_invalid)138 static Lock* mk_LockP_from_LockN ( Lock* lkn,
139                                    Bool allowed_to_be_invalid )
140 {
141    Lock* lkp = NULL;
142    HG_(stats__LockN_to_P_queries)++;
143 
144    /* First off, let's do some sanity checks.  If
145       allowed_to_be_invalid is False, we _must_ be able to find 'lkn'
146       in admin_locks; else we must assert.  If it is True, it's OK for
147       it not to be findable, but in that case we must return
148       Lock_INVALID right away. */
149    Lock* lock_list = HG_(get_admin_locks)();
150    while (lock_list) {
151       if (lock_list == lkn)
152          break;
153       lock_list = lock_list->admin_next;
154    }
155    if (lock_list == NULL) {
156       /* We didn't find it.  That possibility has to be OK'd by the
157          caller. */
158       tl_assert(allowed_to_be_invalid);
159       return Lock_INVALID;
160    }
161 
162    /* So we must be looking at a valid LockN. */
163    tl_assert( HG_(is_sane_LockN)(lkn) );
164 
165    if (!map_LockN_to_P) {
166       map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1",
167                                    HG_(free), lock_unique_cmp );
168    }
169    if (!VG_(lookupFM)( map_LockN_to_P, NULL, (UWord*)&lkp, (UWord)lkn)) {
170       lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
171       *lkp = *lkn;
172       lkp->admin_next = NULL;
173       lkp->admin_prev = NULL;
174       lkp->magic = LockP_MAGIC;
175       /* Forget about the bag of lock holders - don't copy that.
176          Also, acquired_at should be NULL whenever heldBy is, and vice
177          versa.  Also forget about the associated libhb synch object. */
178       lkp->heldW  = False;
179       lkp->heldBy = NULL;
180       lkp->acquired_at = NULL;
181       lkp->hbso = NULL;
182       VG_(addToFM)( map_LockN_to_P, (UWord)lkp, (UWord)lkp );
183    }
184    tl_assert( HG_(is_sane_LockP)(lkp) );
185    return lkp;
186 }
187 
sort_by_guestaddr(const void * n1,const void * n2)188 static Int sort_by_guestaddr(const void* n1, const void* n2)
189 {
190    const Lock* l1 = *(const Lock *const *)n1;
191    const Lock* l2 = *(const Lock *const *)n2;
192 
193    Addr a1 = l1 == Lock_INVALID ? 0 : l1->guestaddr;
194    Addr a2 = l2 == Lock_INVALID ? 0 : l2->guestaddr;
195    if (a1 < a2) return -1;
196    if (a1 > a2) return 1;
197    return 0;
198 }
199 
200 /* Expand a WordSet of LockN*'s into a NULL-terminated vector of
201    LockP*'s.  Any LockN's that can't be converted into a LockP
202    (because they have been freed, see comment on mk_LockP_from_LockN)
203    are converted instead into the value Lock_INVALID.  Hence the
204    returned vector is a sequence: zero or more (valid LockP* or
205    LockN_INVALID), terminated by a NULL. */
206 static
enumerate_WordSet_into_LockP_vector(WordSetU * univ_lsets,WordSetID lockset,Bool allowed_to_be_invalid)207 Lock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets,
208                                             WordSetID lockset,
209                                             Bool allowed_to_be_invalid )
210 {
211    tl_assert(univ_lsets);
212    tl_assert( HG_(plausibleWS)(univ_lsets, lockset) );
213    UWord  nLocks = HG_(cardinalityWS)(univ_lsets, lockset);
214    Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa",
215                                 (nLocks+1) * sizeof(Lock*) );
216    tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */
217    UWord* lockNs  = NULL;
218    UWord  nLockNs = 0;
219    if (nLocks > 0)  {
220       /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the
221          lockset is empty; hence the guarding "if".  Sigh. */
222       HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset );
223       tl_assert(lockNs);
224    }
225    UWord i;
226    /* Convert to LockPs. */
227    for (i = 0; i < nLockNs; i++) {
228       lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i],
229                                        allowed_to_be_invalid );
230    }
231    /* Sort the locks by increasing Lock::guestaddr to avoid jitters
232       in the output. */
233    VG_(ssort)(lockPs, nLockNs, sizeof lockPs[0], sort_by_guestaddr);
234 
235    return lockPs;
236 }
237 
238 /* Get the number of useful elements in a vector created by
239    enumerate_WordSet_into_LockP_vector.  Returns both the total number
240    of elements (not including the terminating NULL) and the number of
241    non-Lock_INVALID elements. */
count_LockP_vector(UWord * nLocks,UWord * nLocksValid,Lock ** vec)242 static void count_LockP_vector ( /*OUT*/UWord* nLocks,
243                                  /*OUT*/UWord* nLocksValid,
244                                  Lock** vec )
245 {
246    tl_assert(vec);
247    *nLocks = *nLocksValid = 0;
248    UWord n = 0;
249    while (vec[n]) {
250       (*nLocks)++;
251       if (vec[n] != Lock_INVALID)
252          (*nLocksValid)++;
253       n++;
254    }
255 }
256 
257 /* Find out whether 'lk' is in 'vec'. */
elem_LockP_vector(Lock ** vec,Lock * lk)258 static Bool elem_LockP_vector ( Lock** vec, Lock* lk )
259 {
260    tl_assert(vec);
261    tl_assert(lk);
262    UWord n = 0;
263    while (vec[n]) {
264       if (vec[n] == lk)
265          return True;
266       n++;
267    }
268    return False;
269 }
270 
271 
272 /* Errors:
273 
274       race: program counter
275             read or write
276             data size
277             previous state
278             current state
279 
280       FIXME: how does state printing interact with lockset gc?
281       Are the locksets in prev/curr state always valid?
282       Ditto question for the threadsets
283           ThreadSets - probably are always valid if Threads
284           are never thrown away.
285           LockSets - could at least print the lockset elements that
286           correspond to actual locks at the time of printing.  Hmm.
287 */
288 
289 /* Error kinds */
290 typedef
291    enum {
292       XE_Race=1101,      // race
293       XE_UnlockUnlocked, // unlocking a not-locked lock
294       XE_UnlockForeign,  // unlocking a lock held by some other thread
295       XE_UnlockBogus,    // unlocking an address not known to be a lock
296       XE_PthAPIerror,    // error from the POSIX pthreads API
297       XE_LockOrder,      // lock order error
298       XE_Misc            // misc other error (w/ string to describe it)
299    }
300    XErrorTag;
301 
302 /* Extra contexts for kinds */
303 typedef
304    struct  {
305       XErrorTag tag;
306       union {
307          struct {
308             Addr        data_addr;
309             Int         szB;
310             AddrInfo    data_addrinfo;
311             Bool        isWrite;
312             Thread*     thr;
313             Lock**      locksHeldW;
314             /* h1_* and h2_* provide some description of a previously
315                observed access with which we are conflicting. */
316             Thread*     h1_ct; /* non-NULL means h1 info present */
317             ExeContext* h1_ct_mbsegstartEC;
318             ExeContext* h1_ct_mbsegendEC;
319             Thread*     h2_ct; /* non-NULL means h2 info present */
320             ExeContext* h2_ct_accEC;
321             Int         h2_ct_accSzB;
322             Bool        h2_ct_accIsW;
323             Lock**      h2_ct_locksHeldW;
324          } Race;
325          struct {
326             Thread* thr;  /* doing the unlocking */
327             Lock*   lock; /* lock (that is already unlocked) */
328          } UnlockUnlocked;
329          struct {
330             Thread* thr;    /* doing the unlocking */
331             Thread* owner;  /* thread that actually holds the lock */
332             Lock*   lock;   /* lock (that is held by 'owner') */
333          } UnlockForeign;
334          struct {
335             Thread* thr;     /* doing the unlocking */
336             Addr    lock_ga; /* purported address of the lock */
337          } UnlockBogus;
338          struct {
339             Thread* thr;
340             HChar*  fnname; /* persistent, in tool-arena */
341             Word    err;    /* pth error code */
342             HChar*  errstr; /* persistent, in tool-arena */
343          } PthAPIerror;
344          struct {
345             Thread*     thr;
346             /* The first 4 fields describe the previously observed
347                (should-be) ordering. */
348             Lock*       shouldbe_earlier_lk;
349             Lock*       shouldbe_later_lk;
350             ExeContext* shouldbe_earlier_ec;
351             ExeContext* shouldbe_later_ec;
352             /* In principle we need to record two more stacks, from
353                this thread, when acquiring the locks in the "wrong"
354                order.  In fact the wallclock-later acquisition by this
355                thread is recorded in the main stack for this error.
356                So we only need a stack for the earlier acquisition by
357                this thread. */
358             ExeContext* actual_earlier_ec;
359          } LockOrder;
360          struct {
361             Thread*     thr;
362             HChar*      errstr; /* persistent, in tool-arena */
363             HChar*      auxstr; /* optional, persistent, in tool-arena */
364             ExeContext* auxctx; /* optional */
365          } Misc;
366       } XE;
367    }
368    XError;
369 
init_XError(XError * xe)370 static void init_XError ( XError* xe ) {
371    VG_(memset)(xe, 0, sizeof(*xe) );
372    xe->tag = XE_Race-1; /* bogus */
373 }
374 
375 
376 /* Extensions of suppressions */
377 typedef
378    enum {
379       XS_Race=1201, /* race */
380       XS_FreeMemLock,
381       XS_UnlockUnlocked,
382       XS_UnlockForeign,
383       XS_UnlockBogus,
384       XS_PthAPIerror,
385       XS_LockOrder,
386       XS_Misc
387    }
388    XSuppTag;
389 
390 
391 /* Updates the copy with address info if necessary. */
HG_(update_extra)392 UInt HG_(update_extra) ( const Error* err )
393 {
394    XError* xe = (XError*)VG_(get_error_extra)(err);
395    tl_assert(xe);
396    //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
397    //   describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
398    //}
399 
400    if (xe->tag == XE_Race) {
401 
402       /* Note the set of locks that the thread is (w-)holding.
403          Convert the WordSetID of LockN*'s into a NULL-terminated
404          vector of LockP*'s.  We don't expect to encounter any invalid
405          LockNs in this conversion. */
406       tl_assert(xe->XE.Race.thr);
407       xe->XE.Race.locksHeldW
408          = enumerate_WordSet_into_LockP_vector(
409               HG_(get_univ_lsets)(),
410               xe->XE.Race.thr->locksetW,
411               False/*!allowed_to_be_invalid*/
412            );
413 
414       /* See if we can come up with a source level description of the
415          raced-upon address.  This is potentially expensive, which is
416          why it's only done at the update_extra point, not when the
417          error is initially created. */
418       static Int xxx = 0;
419       xxx++;
420       if (0)
421          VG_(printf)("HG_(update_extra): "
422                      "%d conflicting-event queries\n", xxx);
423 
424       HG_(describe_addr) (xe->XE.Race.data_addr, &xe->XE.Race.data_addrinfo);
425 
426       /* And poke around in the conflicting-event map, to see if we
427          can rustle up a plausible-looking conflicting memory access
428          to show. */
429       if (HG_(clo_history_level) >= 2) {
430          Thr*        thrp            = NULL;
431          ExeContext* wherep          = NULL;
432          Addr        acc_addr        = xe->XE.Race.data_addr;
433          Int         acc_szB         = xe->XE.Race.szB;
434          Thr*        acc_thr         = xe->XE.Race.thr->hbthr;
435          Bool        acc_isW         = xe->XE.Race.isWrite;
436          SizeT       conf_szB        = 0;
437          Bool        conf_isW        = False;
438          WordSetID   conf_locksHeldW = 0;
439          tl_assert(!xe->XE.Race.h2_ct_accEC);
440          tl_assert(!xe->XE.Race.h2_ct);
441          if (libhb_event_map_lookup(
442                 &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW,
443                 acc_thr, acc_addr, acc_szB, acc_isW )) {
444             Thread* threadp;
445             tl_assert(wherep);
446             tl_assert(thrp);
447             threadp = libhb_get_Thr_hgthread( thrp );
448             tl_assert(threadp);
449             xe->XE.Race.h2_ct_accEC  = wherep;
450             xe->XE.Race.h2_ct        = threadp;
451             xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
452             xe->XE.Race.h2_ct_accIsW = conf_isW;
453             xe->XE.Race.h2_ct_locksHeldW
454                = enumerate_WordSet_into_LockP_vector(
455                     HG_(get_univ_lsets)(),
456                     conf_locksHeldW,
457                     True/*allowed_to_be_invalid*/
458                  );
459         }
460       }
461 
462       // both NULL or both non-NULL
463       tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
464    }
465 
466    return sizeof(XError);
467 }
468 
HG_(record_error_Race)469 void HG_(record_error_Race) ( Thread* thr,
470                               Addr data_addr, Int szB, Bool isWrite,
471                               Thread* h1_ct,
472                               ExeContext* h1_ct_segstart,
473                               ExeContext* h1_ct_mbsegendEC )
474 {
475    XError xe;
476    tl_assert( HG_(is_sane_Thread)(thr) );
477 
478 #  if defined(VGO_linux)
479    /* Skip any races on locations apparently in GOTPLT sections.  This
480       is said to be caused by ld.so poking PLT table entries (or
481       whatever) when it writes the resolved address of a dynamically
482       linked routine, into the table (or whatever) when it is called
483       for the first time. */
484    {
485      VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, data_addr );
486      if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
487                         data_addr, VG_(pp_SectKind)(sect));
488      /* SectPLT is required on ???-linux */
489      if (sect == Vg_SectGOTPLT) return;
490      /* SectPLT is required on ppc32/64-linux */
491      if (sect == Vg_SectPLT) return;
492      /* SectGOT is required on arm-linux */
493      if (sect == Vg_SectGOT) return;
494    }
495 #  endif
496 
497    init_XError(&xe);
498    xe.tag = XE_Race;
499    xe.XE.Race.data_addr   = data_addr;
500    xe.XE.Race.szB         = szB;
501    xe.XE.Race.isWrite     = isWrite;
502    xe.XE.Race.thr         = thr;
503    tl_assert(isWrite == False || isWrite == True);
504    tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
505    /* Skip on the detailed description of the raced-on address at this
506       point; it's expensive.  Leave it for the update_extra function
507       if we ever make it that far. */
508    xe.XE.Race.data_addrinfo.tag = Addr_Undescribed;
509    // FIXME: tid vs thr
510    // Skip on any of the conflicting-access info at this point.
511    // It's expensive to obtain, and this error is more likely than
512    // not to be discarded.  We'll fill these fields in in
513    // HG_(update_extra) just above, assuming the error ever makes
514    // it that far (unlikely).
515    xe.XE.Race.h2_ct_accSzB = 0;
516    xe.XE.Race.h2_ct_accIsW = False;
517    xe.XE.Race.h2_ct_accEC  = NULL;
518    xe.XE.Race.h2_ct        = NULL;
519    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
520    tl_assert( thr->coretid != VG_INVALID_THREADID );
521 
522    xe.XE.Race.h1_ct              = h1_ct;
523    xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
524    xe.XE.Race.h1_ct_mbsegendEC   = h1_ct_mbsegendEC;
525 
526    VG_(maybe_record_error)( thr->coretid,
527                             XE_Race, data_addr, NULL, &xe );
528 }
529 
HG_(record_error_UnlockUnlocked)530 void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
531 {
532    XError xe;
533    tl_assert( HG_(is_sane_Thread)(thr) );
534    tl_assert( HG_(is_sane_LockN)(lk) );
535    init_XError(&xe);
536    xe.tag = XE_UnlockUnlocked;
537    xe.XE.UnlockUnlocked.thr
538       = thr;
539    xe.XE.UnlockUnlocked.lock
540       = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
541    // FIXME: tid vs thr
542    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
543    tl_assert( thr->coretid != VG_INVALID_THREADID );
544    VG_(maybe_record_error)( thr->coretid,
545                             XE_UnlockUnlocked, 0, NULL, &xe );
546 }
547 
HG_(record_error_UnlockForeign)548 void HG_(record_error_UnlockForeign) ( Thread* thr,
549                                        Thread* owner, Lock* lk )
550 {
551    XError xe;
552    tl_assert( HG_(is_sane_Thread)(thr) );
553    tl_assert( HG_(is_sane_Thread)(owner) );
554    tl_assert( HG_(is_sane_LockN)(lk) );
555    init_XError(&xe);
556    xe.tag = XE_UnlockForeign;
557    xe.XE.UnlockForeign.thr   = thr;
558    xe.XE.UnlockForeign.owner = owner;
559    xe.XE.UnlockForeign.lock
560       = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
561    // FIXME: tid vs thr
562    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
563    tl_assert( thr->coretid != VG_INVALID_THREADID );
564    VG_(maybe_record_error)( thr->coretid,
565                             XE_UnlockForeign, 0, NULL, &xe );
566 }
567 
HG_(record_error_UnlockBogus)568 void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
569 {
570    XError xe;
571    tl_assert( HG_(is_sane_Thread)(thr) );
572    init_XError(&xe);
573    xe.tag = XE_UnlockBogus;
574    xe.XE.UnlockBogus.thr     = thr;
575    xe.XE.UnlockBogus.lock_ga = lock_ga;
576    // FIXME: tid vs thr
577    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
578    tl_assert( thr->coretid != VG_INVALID_THREADID );
579    VG_(maybe_record_error)( thr->coretid,
580                             XE_UnlockBogus, 0, NULL, &xe );
581 }
582 
HG_(record_error_LockOrder)583 void HG_(record_error_LockOrder)(
584         Thread*     thr,
585         Lock*       shouldbe_earlier_lk,
586         Lock*       shouldbe_later_lk,
587         ExeContext* shouldbe_earlier_ec,
588         ExeContext* shouldbe_later_ec,
589         ExeContext* actual_earlier_ec
590      )
591 {
592    XError xe;
593    tl_assert( HG_(is_sane_Thread)(thr) );
594    tl_assert(HG_(clo_track_lockorders));
595    init_XError(&xe);
596    xe.tag = XE_LockOrder;
597    xe.XE.LockOrder.thr       = thr;
598    xe.XE.LockOrder.shouldbe_earlier_lk
599       = mk_LockP_from_LockN(shouldbe_earlier_lk,
600                             False/*!allowed_to_be_invalid*/);
601    xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec;
602    xe.XE.LockOrder.shouldbe_later_lk
603       = mk_LockP_from_LockN(shouldbe_later_lk,
604                             False/*!allowed_to_be_invalid*/);
605    xe.XE.LockOrder.shouldbe_later_ec   = shouldbe_later_ec;
606    xe.XE.LockOrder.actual_earlier_ec   = actual_earlier_ec;
607    // FIXME: tid vs thr
608    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
609    tl_assert( thr->coretid != VG_INVALID_THREADID );
610    VG_(maybe_record_error)( thr->coretid,
611                             XE_LockOrder, 0, NULL, &xe );
612 }
613 
HG_(record_error_PthAPIerror)614 void HG_(record_error_PthAPIerror) ( Thread* thr, const HChar* fnname,
615                                      Word err, const HChar* errstr )
616 {
617    XError xe;
618    tl_assert( HG_(is_sane_Thread)(thr) );
619    tl_assert(fnname);
620    tl_assert(errstr);
621    init_XError(&xe);
622    xe.tag = XE_PthAPIerror;
623    xe.XE.PthAPIerror.thr    = thr;
624    xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
625    xe.XE.PthAPIerror.err    = err;
626    xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
627    // FIXME: tid vs thr
628    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
629    tl_assert( thr->coretid != VG_INVALID_THREADID );
630    VG_(maybe_record_error)( thr->coretid,
631                             XE_PthAPIerror, 0, NULL, &xe );
632 }
633 
HG_(record_error_Misc_w_aux)634 void HG_(record_error_Misc_w_aux) ( Thread* thr, const HChar* errstr,
635                                     const HChar* auxstr, ExeContext* auxctx )
636 {
637    XError xe;
638    tl_assert( HG_(is_sane_Thread)(thr) );
639    tl_assert(errstr);
640    init_XError(&xe);
641    xe.tag = XE_Misc;
642    xe.XE.Misc.thr    = thr;
643    xe.XE.Misc.errstr = string_table_strdup(errstr);
644    xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
645    xe.XE.Misc.auxctx = auxctx;
646    // FIXME: tid vs thr
647    tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
648    tl_assert( thr->coretid != VG_INVALID_THREADID );
649    VG_(maybe_record_error)( thr->coretid,
650                             XE_Misc, 0, NULL, &xe );
651 }
652 
HG_(record_error_Misc)653 void HG_(record_error_Misc) ( Thread* thr, const HChar* errstr )
654 {
655    HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
656 }
657 
HG_(eq_Error)658 Bool HG_(eq_Error) ( VgRes not_used, const Error* e1, const Error* e2 )
659 {
660    XError *xe1, *xe2;
661 
662    tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
663 
664    xe1 = (XError*)VG_(get_error_extra)(e1);
665    xe2 = (XError*)VG_(get_error_extra)(e2);
666    tl_assert(xe1);
667    tl_assert(xe2);
668 
669    switch (VG_(get_error_kind)(e1)) {
670       case XE_Race:
671          return xe1->XE.Race.szB == xe2->XE.Race.szB
672                 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
673                 && (HG_(clo_cmp_race_err_addrs)
674                        ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
675                        : True);
676       case XE_UnlockUnlocked:
677          return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
678                 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
679       case XE_UnlockForeign:
680          return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
681                 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
682                 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
683       case XE_UnlockBogus:
684          return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
685                 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
686       case XE_PthAPIerror:
687          return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
688                 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
689                                   xe2->XE.PthAPIerror.fnname)
690                 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
691       case XE_LockOrder:
692          return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
693       case XE_Misc:
694          return xe1->XE.Misc.thr == xe2->XE.Misc.thr
695                 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
696       default:
697          tl_assert(0);
698    }
699 
700    /*NOTREACHED*/
701    tl_assert(0);
702 }
703 
704 
705 /*----------------------------------------------------------------*/
706 /*--- Error management -- printing                             ---*/
707 /*----------------------------------------------------------------*/
708 
709 /* Do a printf-style operation on either the XML or normal output
710    channel, depending on the setting of VG_(clo_xml).
711 */
emit_WRK(const HChar * format,va_list vargs)712 static void emit_WRK ( const HChar* format, va_list vargs )
713 {
714    if (VG_(clo_xml)) {
715       VG_(vprintf_xml)(format, vargs);
716    } else {
717       VG_(vmessage)(Vg_UserMsg, format, vargs);
718    }
719 }
720 static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
emit(const HChar * format,...)721 static void emit ( const HChar* format, ... )
722 {
723    va_list vargs;
724    va_start(vargs, format);
725    emit_WRK(format, vargs);
726    va_end(vargs);
727 }
728 
729 
730 /* Announce (that is, print the point-of-creation) of 'thr'.  Only do
731    this once, as we only want to see these announcements once per
732    thread.  Returned Bool indicates whether or not an announcement was
733    made.
734 */
announce_one_thread(Thread * thr)735 static Bool announce_one_thread ( Thread* thr )
736 {
737    tl_assert(HG_(is_sane_Thread)(thr));
738    tl_assert(thr->errmsg_index >= 1);
739    if (thr->announced)
740       return False;
741 
742    if (VG_(clo_xml)) {
743 
744       VG_(printf_xml)("<announcethread>\n");
745       VG_(printf_xml)("  <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
746       if (thr->errmsg_index == 1) {
747          tl_assert(thr->created_at == NULL);
748          VG_(printf_xml)("  <isrootthread></isrootthread>\n");
749       } else {
750          tl_assert(thr->created_at != NULL);
751          VG_(pp_ExeContext)( thr->created_at );
752       }
753       VG_(printf_xml)("</announcethread>\n\n");
754 
755    } else {
756 
757       VG_(umsg)("---Thread-Announcement----------"
758                 "--------------------------------" "\n");
759       VG_(umsg)("\n");
760 
761       if (thr->errmsg_index == 1) {
762          tl_assert(thr->created_at == NULL);
763          VG_(message)(Vg_UserMsg,
764                       "Thread #%d is the program's root thread\n",
765                        thr->errmsg_index);
766       } else {
767          tl_assert(thr->created_at != NULL);
768          VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
769                                   thr->errmsg_index);
770          VG_(pp_ExeContext)( thr->created_at );
771       }
772       VG_(message)(Vg_UserMsg, "\n");
773 
774    }
775 
776    thr->announced = True;
777    return True;
778 }
779 
780 /* Announce 'lk'. */
announce_LockP(Lock * lk)781 static void announce_LockP ( Lock* lk )
782 {
783    tl_assert(lk);
784    if (lk == Lock_INVALID)
785       return; /* Can't be announced -- we know nothing about it. */
786    tl_assert(lk->magic == LockP_MAGIC);
787 
788    if (VG_(clo_xml)) {
789       if (lk->appeared_at) {
790          emit( "  <auxwhat>Lock at %p was first observed</auxwhat>\n",
791                (void*)lk );
792          VG_(pp_ExeContext)( lk->appeared_at );
793       }
794 
795    } else {
796       if (lk->appeared_at) {
797          VG_(umsg)( " Lock at %p was first observed\n",
798                     (void*)lk->guestaddr );
799          VG_(pp_ExeContext)( lk->appeared_at );
800       } else {
801          VG_(umsg)( " Lock at %p : no stacktrace for first observation\n",
802                     (void*)lk->guestaddr );
803       }
804       HG_(get_and_pp_addrdescr) (lk->guestaddr);
805       VG_(umsg)("\n");
806    }
807 }
808 
809 /* Announce (that is, print point-of-first-observation) for the
810    locks in 'lockvec' and, if non-NULL, 'lockvec2'. */
announce_combined_LockP_vecs(Lock ** lockvec,Lock ** lockvec2)811 static void announce_combined_LockP_vecs ( Lock** lockvec,
812                                            Lock** lockvec2 )
813 {
814    UWord i;
815    tl_assert(lockvec);
816    for (i = 0; lockvec[i]; i++) {
817       announce_LockP(lockvec[i]);
818    }
819    if (lockvec2) {
820       for (i = 0; lockvec2[i]; i++) {
821          Lock* lk = lockvec2[i];
822          if (!elem_LockP_vector(lockvec, lk))
823             announce_LockP(lk);
824       }
825    }
826 }
827 
828 
show_LockP_summary_textmode(Lock ** locks,const HChar * pre)829 static void show_LockP_summary_textmode ( Lock** locks, const HChar* pre )
830 {
831    tl_assert(locks);
832    UWord i;
833    UWord nLocks = 0, nLocksValid = 0;
834    count_LockP_vector(&nLocks, &nLocksValid, locks);
835    tl_assert(nLocksValid <= nLocks);
836 
837    if (nLocks == 0) {
838       VG_(umsg)( "%sLocks held: none", pre );
839    } else {
840       VG_(umsg)( "%sLocks held: %lu, at address%s ",
841                  pre, nLocks, nLocksValid == 1 ? "" : "es" );
842    }
843 
844    if (nLocks > 0) {
845       for (i = 0; i < nLocks; i++) {
846          if (locks[i] == Lock_INVALID)
847             continue;
848          VG_(umsg)( "%p", (void*)locks[i]->guestaddr);
849          if (locks[i+1] != NULL)
850             VG_(umsg)(" ");
851       }
852       if (nLocksValid < nLocks)
853          VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid);
854    }
855    VG_(umsg)("\n");
856 }
857 
858 
859 /* This is the "this error is due to be printed shortly; so have a
860    look at it any print any preamble you want" function.  We use it to
861    announce any previously un-announced threads in the upcoming error
862    message.
863 */
HG_(before_pp_Error)864 void HG_(before_pp_Error) ( const Error* err )
865 {
866    XError* xe;
867    tl_assert(err);
868    xe = (XError*)VG_(get_error_extra)(err);
869    tl_assert(xe);
870 
871    switch (VG_(get_error_kind)(err)) {
872       case XE_Misc:
873          announce_one_thread( xe->XE.Misc.thr );
874          break;
875       case XE_LockOrder:
876          announce_one_thread( xe->XE.LockOrder.thr );
877          break;
878       case XE_PthAPIerror:
879          announce_one_thread( xe->XE.PthAPIerror.thr );
880          break;
881       case XE_UnlockBogus:
882          announce_one_thread( xe->XE.UnlockBogus.thr );
883          break;
884       case XE_UnlockForeign:
885          announce_one_thread( xe->XE.UnlockForeign.thr );
886          announce_one_thread( xe->XE.UnlockForeign.owner );
887          break;
888       case XE_UnlockUnlocked:
889          announce_one_thread( xe->XE.UnlockUnlocked.thr );
890          break;
891       case XE_Race:
892          announce_one_thread( xe->XE.Race.thr );
893          if (xe->XE.Race.h2_ct)
894             announce_one_thread( xe->XE.Race.h2_ct );
895          if (xe->XE.Race.h1_ct)
896             announce_one_thread( xe->XE.Race.h1_ct );
897          if (xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
898             Thread* thr = get_admin_threads();
899             while (thr) {
900                if (thr->errmsg_index
901                    == xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
902                   announce_one_thread (thr);
903                   break;
904                }
905                thr = thr->admin;
906             }
907          }
908          break;
909       default:
910          tl_assert(0);
911    }
912 }
913 
HG_(pp_Error)914 void HG_(pp_Error) ( const Error* err )
915 {
916    const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
917 
918    if (!xml) {
919       VG_(umsg)("--------------------------------"
920                 "--------------------------------" "\n");
921       VG_(umsg)("\n");
922    }
923 
924    XError *xe = (XError*)VG_(get_error_extra)(err);
925    tl_assert(xe);
926 
927    if (xml)
928       emit( "  <kind>%s</kind>\n", HG_(get_error_name)(err));
929 
930    switch (VG_(get_error_kind)(err)) {
931 
932    case XE_Misc: {
933       tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
934 
935       if (xml) {
936 
937          emit( "  <xwhat>\n" );
938          emit( "    <text>Thread #%d: %s</text>\n",
939                (Int)xe->XE.Misc.thr->errmsg_index,
940                xe->XE.Misc.errstr );
941          emit( "    <hthreadid>%d</hthreadid>\n",
942                (Int)xe->XE.Misc.thr->errmsg_index );
943          emit( "  </xwhat>\n" );
944          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
945          if (xe->XE.Misc.auxstr) {
946             emit("  <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
947             if (xe->XE.Misc.auxctx)
948                VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
949          }
950 
951       } else {
952 
953          emit( "Thread #%d: %s\n",
954                (Int)xe->XE.Misc.thr->errmsg_index,
955                xe->XE.Misc.errstr );
956          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
957          if (xe->XE.Misc.auxstr) {
958             emit(" %s\n", xe->XE.Misc.auxstr);
959             if (xe->XE.Misc.auxctx)
960                VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
961          }
962 
963       }
964       break;
965    }
966 
967    case XE_LockOrder: {
968       tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
969 
970       if (xml) {
971 
972          emit( "  <xwhat>\n" );
973          emit( "    <text>Thread #%d: lock order \"%p before %p\" "
974                     "violated</text>\n",
975                (Int)xe->XE.LockOrder.thr->errmsg_index,
976                (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
977                (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
978          emit( "    <hthreadid>%d</hthreadid>\n",
979                (Int)xe->XE.LockOrder.thr->errmsg_index );
980          emit( "  </xwhat>\n" );
981          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
982          if (xe->XE.LockOrder.shouldbe_earlier_ec
983              && xe->XE.LockOrder.shouldbe_later_ec) {
984             emit( "  <auxwhat>Required order was established by "
985                   "acquisition of lock at %p</auxwhat>\n",
986                   (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
987             VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
988             emit( "  <auxwhat>followed by a later acquisition "
989                   "of lock at %p</auxwhat>\n",
990                   (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
991             VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
992          }
993          announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
994          announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
995 
996       } else {
997 
998          emit( "Thread #%d: lock order \"%p before %p\" violated\n",
999                (Int)xe->XE.LockOrder.thr->errmsg_index,
1000                (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
1001                (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
1002          emit( "\n" );
1003          emit( "Observed (incorrect) order is: "
1004                "acquisition of lock at %p\n",
1005                (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr);
1006          if (xe->XE.LockOrder.actual_earlier_ec) {
1007              VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
1008          } else {
1009             emit("   (stack unavailable)\n");
1010          }
1011          emit( "\n" );
1012          emit(" followed by a later acquisition of lock at %p\n",
1013               (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr);
1014          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1015          if (xe->XE.LockOrder.shouldbe_earlier_ec
1016              && xe->XE.LockOrder.shouldbe_later_ec) {
1017             emit("\n");
1018             emit( "Required order was established by "
1019                   "acquisition of lock at %p\n",
1020                   (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
1021             VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
1022             emit( "\n" );
1023             emit( " followed by a later acquisition of lock at %p\n",
1024                   (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
1025             VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
1026          }
1027          emit("\n");
1028          announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
1029          announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
1030 
1031       }
1032 
1033       break;
1034    }
1035 
1036    case XE_PthAPIerror: {
1037       tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
1038 
1039       if (xml) {
1040 
1041          emit( "  <xwhat>\n" );
1042          emit(
1043             "    <text>Thread #%d's call to %pS failed</text>\n",
1044             (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1045             xe->XE.PthAPIerror.fnname );
1046          emit( "    <hthreadid>%d</hthreadid>\n",
1047                (Int)xe->XE.PthAPIerror.thr->errmsg_index );
1048          emit( "  </xwhat>\n" );
1049          emit( "  <what>with error code %ld (%s)</what>\n",
1050                xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1051          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1052 
1053       } else {
1054 
1055          emit( "Thread #%d's call to %pS failed\n",
1056                       (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1057                       xe->XE.PthAPIerror.fnname );
1058          emit( "   with error code %ld (%s)\n",
1059                xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1060          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1061 
1062       }
1063 
1064       break;
1065    }
1066 
1067    case XE_UnlockBogus: {
1068       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
1069 
1070       if (xml) {
1071 
1072          emit( "  <xwhat>\n" );
1073          emit( "    <text>Thread #%d unlocked an invalid "
1074                     "lock at %p</text>\n",
1075                (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1076                (void*)xe->XE.UnlockBogus.lock_ga );
1077          emit( "    <hthreadid>%d</hthreadid>\n",
1078                (Int)xe->XE.UnlockBogus.thr->errmsg_index );
1079          emit( "  </xwhat>\n" );
1080          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1081 
1082       } else {
1083 
1084          emit( "Thread #%d unlocked an invalid lock at %p\n",
1085                (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1086                (void*)xe->XE.UnlockBogus.lock_ga );
1087          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1088 
1089       }
1090 
1091       break;
1092    }
1093 
1094    case XE_UnlockForeign: {
1095       tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
1096       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
1097       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
1098 
1099       if (xml) {
1100 
1101          emit( "  <xwhat>\n" );
1102          emit( "    <text>Thread #%d unlocked lock at %p "
1103                     "currently held by thread #%d</text>\n",
1104                (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1105                (void*)xe->XE.UnlockForeign.lock->guestaddr,
1106                (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1107          emit( "    <hthreadid>%d</hthreadid>\n",
1108                (Int)xe->XE.UnlockForeign.thr->errmsg_index );
1109          emit( "    <hthreadid>%d</hthreadid>\n",
1110                (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1111          emit( "  </xwhat>\n" );
1112          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1113          announce_LockP ( xe->XE.UnlockForeign.lock );
1114 
1115       } else {
1116 
1117          emit( "Thread #%d unlocked lock at %p "
1118                "currently held by thread #%d\n",
1119                (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1120                (void*)xe->XE.UnlockForeign.lock->guestaddr,
1121                (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1122          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1123          announce_LockP ( xe->XE.UnlockForeign.lock );
1124 
1125       }
1126 
1127       break;
1128    }
1129 
1130    case XE_UnlockUnlocked: {
1131       tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
1132       tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
1133 
1134       if (xml) {
1135 
1136          emit( "  <xwhat>\n" );
1137          emit( "    <text>Thread #%d unlocked a "
1138                     "not-locked lock at %p</text>\n",
1139                (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1140                (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1141          emit( "    <hthreadid>%d</hthreadid>\n",
1142                (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
1143          emit( "  </xwhat>\n" );
1144          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1145          announce_LockP ( xe->XE.UnlockUnlocked.lock);
1146 
1147       } else {
1148 
1149          emit( "Thread #%d unlocked a not-locked lock at %p\n",
1150                (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1151                (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1152          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1153          announce_LockP ( xe->XE.UnlockUnlocked.lock);
1154 
1155       }
1156 
1157       break;
1158    }
1159 
1160    case XE_Race: {
1161       Addr      err_ga;
1162       const HChar* what;
1163       Int       szB;
1164       what      = xe->XE.Race.isWrite ? "write" : "read";
1165       szB       = xe->XE.Race.szB;
1166       err_ga = VG_(get_error_address)(err);
1167 
1168       tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
1169       if (xe->XE.Race.h2_ct)
1170          tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
1171 
1172       if (xml) {
1173 
1174          /* ------ XML ------ */
1175          emit( "  <xwhat>\n" );
1176          emit( "    <text>Possible data race during %s of size %d "
1177                     "at %p by thread #%d</text>\n",
1178                what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1179          emit( "    <hthreadid>%d</hthreadid>\n",
1180                (Int)xe->XE.Race.thr->errmsg_index );
1181          emit( "  </xwhat>\n" );
1182          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1183 
1184          if (xe->XE.Race.h2_ct) {
1185             tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1186             emit( "  <xauxwhat>\n");
1187             emit( "    <text>This conflicts with a previous %s of size %d "
1188                             "by thread #%d</text>\n",
1189                   xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1190                   xe->XE.Race.h2_ct_accSzB,
1191                   xe->XE.Race.h2_ct->errmsg_index );
1192             emit( "    <hthreadid>%d</hthreadid>\n",
1193                   xe->XE.Race.h2_ct->errmsg_index);
1194             emit("  </xauxwhat>\n");
1195             VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1196          }
1197 
1198          if (xe->XE.Race.h1_ct) {
1199             emit( "  <xauxwhat>\n");
1200             emit( "    <text>This conflicts with a previous access "
1201                   "by thread #%d, after</text>\n",
1202                   xe->XE.Race.h1_ct->errmsg_index );
1203             emit( "    <hthreadid>%d</hthreadid>\n",
1204                   xe->XE.Race.h1_ct->errmsg_index );
1205             emit("  </xauxwhat>\n");
1206             if (xe->XE.Race.h1_ct_mbsegstartEC) {
1207                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
1208             } else {
1209                emit( "  <auxwhat>(the start of the thread)</auxwhat>\n" );
1210             }
1211             emit( "  <auxwhat>but before</auxwhat>\n" );
1212             if (xe->XE.Race.h1_ct_mbsegendEC) {
1213                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1214             } else {
1215                emit( "  <auxwhat>(the end of the thread)</auxwhat>\n" );
1216             }
1217          }
1218 
1219       } else {
1220 
1221          /* ------ Text ------ */
1222          announce_combined_LockP_vecs( xe->XE.Race.locksHeldW,
1223                                        xe->XE.Race.h2_ct_locksHeldW );
1224 
1225          emit( "Possible data race during %s of size %d "
1226                "at %p by thread #%d\n",
1227                what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1228 
1229          tl_assert(xe->XE.Race.locksHeldW);
1230          show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" );
1231          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1232 
1233          if (xe->XE.Race.h2_ct) {
1234             tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1235             tl_assert(xe->XE.Race.h2_ct_locksHeldW);
1236             emit( "\n" );
1237             emit( "This conflicts with a previous %s of size %d "
1238                   "by thread #%d\n",
1239                   xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1240                   xe->XE.Race.h2_ct_accSzB,
1241                   xe->XE.Race.h2_ct->errmsg_index );
1242             show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" );
1243             VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1244          }
1245 
1246          if (xe->XE.Race.h1_ct) {
1247             emit( " This conflicts with a previous access by thread #%d, "
1248                   "after\n",
1249                   xe->XE.Race.h1_ct->errmsg_index );
1250             if (xe->XE.Race.h1_ct_mbsegstartEC) {
1251                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
1252             } else {
1253                emit( "   (the start of the thread)\n" );
1254             }
1255             emit( " but before\n" );
1256             if (xe->XE.Race.h1_ct_mbsegendEC) {
1257                VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1258             } else {
1259                emit( "   (the end of the thread)\n" );
1260             }
1261          }
1262 
1263       }
1264       VG_(pp_addrinfo) (err_ga, &xe->XE.Race.data_addrinfo);
1265       break; /* case XE_Race */
1266    } /* case XE_Race */
1267 
1268    default:
1269       tl_assert(0);
1270    } /* switch (VG_(get_error_kind)(err)) */
1271 }
1272 
HG_(print_access)1273 void HG_(print_access) (StackTrace ips, UInt n_ips,
1274                         Thr* thr_a,
1275                         Addr  ga,
1276                         SizeT SzB,
1277                         Bool  isW,
1278                         WordSetID locksHeldW )
1279 {
1280    Thread* threadp;
1281 
1282    threadp = libhb_get_Thr_hgthread( thr_a );
1283    tl_assert(threadp);
1284    if (!threadp->announced) {
1285       /* This is for interactive use. We announce the thread if needed,
1286          but reset it to not announced afterwards, because we want
1287          the thread to be announced on the error output/log if needed. */
1288       announce_one_thread (threadp);
1289       threadp->announced = False;
1290    }
1291 
1292    announce_one_thread (threadp);
1293    VG_(printf) ("%s of size %d at %p by thread #%d",
1294                 isW ? "write" : "read",
1295                 (int)SzB, (void*)ga, threadp->errmsg_index);
1296    if (threadp->coretid == VG_INVALID_THREADID)
1297       VG_(printf)(" tid (exited)\n");
1298    else
1299       VG_(printf)(" tid %u\n", threadp->coretid);
1300    {
1301       Lock** locksHeldW_P;
1302       locksHeldW_P = enumerate_WordSet_into_LockP_vector(
1303                        HG_(get_univ_lsets)(),
1304                        locksHeldW,
1305                        True/*allowed_to_be_invalid*/
1306                     );
1307       show_LockP_summary_textmode( locksHeldW_P, "" );
1308       HG_(free) (locksHeldW_P);
1309    }
1310    VG_(pp_StackTrace) (ips, n_ips);
1311    VG_(printf) ("\n");
1312 }
1313 
HG_(get_error_name)1314 const HChar* HG_(get_error_name) ( const Error* err )
1315 {
1316    switch (VG_(get_error_kind)(err)) {
1317       case XE_Race:           return "Race";
1318       case XE_UnlockUnlocked: return "UnlockUnlocked";
1319       case XE_UnlockForeign:  return "UnlockForeign";
1320       case XE_UnlockBogus:    return "UnlockBogus";
1321       case XE_PthAPIerror:    return "PthAPIerror";
1322       case XE_LockOrder:      return "LockOrder";
1323       case XE_Misc:           return "Misc";
1324       default: tl_assert(0); /* fill in missing case */
1325    }
1326 }
1327 
HG_(recognised_suppression)1328 Bool HG_(recognised_suppression) ( const HChar* name, Supp *su )
1329 {
1330 #  define TRY(_name,_xskind)                   \
1331       if (0 == VG_(strcmp)(name, (_name))) {   \
1332          VG_(set_supp_kind)(su, (_xskind));    \
1333          return True;                          \
1334       }
1335    TRY("Race",           XS_Race);
1336    TRY("FreeMemLock",    XS_FreeMemLock);
1337    TRY("UnlockUnlocked", XS_UnlockUnlocked);
1338    TRY("UnlockForeign",  XS_UnlockForeign);
1339    TRY("UnlockBogus",    XS_UnlockBogus);
1340    TRY("PthAPIerror",    XS_PthAPIerror);
1341    TRY("LockOrder",      XS_LockOrder);
1342    TRY("Misc",           XS_Misc);
1343    return False;
1344 #  undef TRY
1345 }
1346 
HG_(read_extra_suppression_info)1347 Bool HG_(read_extra_suppression_info) ( Int fd, HChar** bufpp, SizeT* nBufp,
1348                                         Int* lineno, Supp* su )
1349 {
1350    /* do nothing -- no extra suppression info present.  Return True to
1351       indicate nothing bad happened. */
1352    return True;
1353 }
1354 
HG_(error_matches_suppression)1355 Bool HG_(error_matches_suppression) ( const Error* err, const Supp* su )
1356 {
1357    switch (VG_(get_supp_kind)(su)) {
1358    case XS_Race:           return VG_(get_error_kind)(err) == XE_Race;
1359    case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1360    case XS_UnlockForeign:  return VG_(get_error_kind)(err) == XE_UnlockForeign;
1361    case XS_UnlockBogus:    return VG_(get_error_kind)(err) == XE_UnlockBogus;
1362    case XS_PthAPIerror:    return VG_(get_error_kind)(err) == XE_PthAPIerror;
1363    case XS_LockOrder:      return VG_(get_error_kind)(err) == XE_LockOrder;
1364    case XS_Misc:           return VG_(get_error_kind)(err) == XE_Misc;
1365    //case XS_: return VG_(get_error_kind)(err) == XE_;
1366    default: tl_assert(0); /* fill in missing cases */
1367    }
1368 }
1369 
HG_(get_extra_suppression_info)1370 SizeT HG_(get_extra_suppression_info) ( const Error* err,
1371                                        /*OUT*/HChar* buf, Int nBuf )
1372 {
1373    tl_assert(nBuf >= 1);
1374    /* Do nothing */
1375    buf[0] = '\0';
1376    return 0;
1377 }
1378 
HG_(print_extra_suppression_use)1379 SizeT HG_(print_extra_suppression_use) ( const Supp* su,
1380                                         /*OUT*/HChar* buf, Int nBuf )
1381 {
1382    tl_assert(nBuf >= 1);
1383    /* Do nothing */
1384    buf[0] = '\0';
1385    return 0;
1386 }
1387 
HG_(update_extra_suppression_use)1388 void HG_(update_extra_suppression_use) ( const Error* err, const Supp* su )
1389 {
1390    /* Do nothing */
1391    return;
1392 }
1393 
1394 
1395 /*--------------------------------------------------------------------*/
1396 /*--- end                                              hg_errors.c ---*/
1397 /*--------------------------------------------------------------------*/
1398