blob: 0e96d7e76317f26b31afbd98ae81ab82a4244a4a [file] [log] [blame]
sewardjf98e1c02008-10-25 16:22:41 +00001
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
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2007-2013 OpenWorks Ltd
sewardjf98e1c02008-10-25 16:22:41 +000012 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_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"
sewardj24118492009-07-15 14:50:02 +000042#include "pub_tool_options.h" // VG_(clo_xml)
philippe07c08522014-05-14 20:39:27 +000043#include "pub_tool_addrinfo.h"
sewardjf98e1c02008-10-25 16:22:41 +000044
45#include "hg_basics.h"
philippef5774342014-05-03 11:12:50 +000046#include "hg_addrdescr.h"
sewardjf98e1c02008-10-25 16:22:41 +000047#include "hg_wordset.h"
48#include "hg_lock_n_thread.h"
sewardjc5ea9962008-12-07 01:41:46 +000049#include "libhb.h"
sewardjf98e1c02008-10-25 16:22:41 +000050#include "hg_errors.h" /* self */
51
52
53/*----------------------------------------------------------------*/
sewardj24118492009-07-15 14:50:02 +000054/*--- Error management -- storage ---*/
sewardjf98e1c02008-10-25 16:22:41 +000055/*----------------------------------------------------------------*/
56
57/* maps (by value) strings to a copy of them in ARENA_TOOL */
58
59static WordFM* string_table = NULL;
60
61ULong HG_(stats__string_table_queries) = 0;
62
63ULong HG_(stats__string_table_get_map_size) ( void ) {
64 return string_table ? (ULong)VG_(sizeFM)(string_table) : 0;
65}
66
67static Word string_table_cmp ( UWord s1, UWord s2 ) {
68 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
69}
70
florian19f91bb2012-11-10 22:29:54 +000071static HChar* string_table_strdup ( const HChar* str ) {
sewardjf98e1c02008-10-25 16:22:41 +000072 HChar* copy = NULL;
73 HG_(stats__string_table_queries)++;
74 if (!str)
75 str = "(null)";
76 if (!string_table) {
77 string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1",
78 HG_(free), string_table_cmp );
sewardjf98e1c02008-10-25 16:22:41 +000079 }
80 if (VG_(lookupFM)( string_table,
florian6bf37262012-10-21 03:23:36 +000081 NULL, (UWord*)&copy, (UWord)str )) {
sewardjf98e1c02008-10-25 16:22:41 +000082 tl_assert(copy);
83 if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
84 return copy;
85 } else {
86 copy = HG_(strdup)("hg.sts.2", str);
florian19f91bb2012-11-10 22:29:54 +000087 VG_(addToFM)( string_table, (UWord)copy, (UWord)copy );
sewardjf98e1c02008-10-25 16:22:41 +000088 return copy;
89 }
90}
91
92/* maps from Lock .unique fields to LockP*s */
93
94static WordFM* map_LockN_to_P = NULL;
95
96ULong HG_(stats__LockN_to_P_queries) = 0;
97
98ULong 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
102static 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
sewardjffce8152011-06-24 10:09:41 +0000113/* Given a normal Lock (LockN), convert it to a persistent Lock
114 (LockP). In some cases the LockN could be invalid (if it's been
115 freed), so we enquire, in hg_main.c's admin_locks list, whether it
116 is in fact valid. If allowed_to_be_invalid is True, then it's OK
117 for the LockN to be invalid, in which case Lock_INVALID is
118 returned. In all other cases, we insist that the LockN is a valid
119 lock, and return its corresponding LockP.
120
121 Why can LockNs sometimes be invalid? Because they are harvested
122 from locksets that are attached to the OldRef info for conflicting
123 threads. By the time we detect a race, the some of the elements of
124 the lockset may have been destroyed by the client, in which case
125 the corresponding Lock structures we maintain will have been freed.
126
127 So we check that each LockN is a member of the admin_locks double
128 linked list of all Lock structures. That stops us prodding around
129 in potentially freed-up Lock structures. However, it's not quite a
130 proper check: if a new Lock has been reallocated at the same
131 address as one which was previously freed, we'll wind up copying
132 the new one as the basis for the LockP, which is completely bogus
133 because it is unrelated to the previous Lock that lived there.
134 Let's hope that doesn't happen too often.
135*/
136static Lock* mk_LockP_from_LockN ( Lock* lkn,
137 Bool allowed_to_be_invalid )
sewardjf98e1c02008-10-25 16:22:41 +0000138{
139 Lock* lkp = NULL;
140 HG_(stats__LockN_to_P_queries)++;
sewardjffce8152011-06-24 10:09:41 +0000141
142 /* First off, let's do some sanity checks. If
143 allowed_to_be_invalid is False, we _must_ be able to find 'lkn'
144 in admin_locks; else we must assert. If it is True, it's OK for
145 it not to be findable, but in that case we must return
146 Lock_INVALID right away. */
147 Lock* lock_list = HG_(get_admin_locks)();
148 while (lock_list) {
149 if (lock_list == lkn)
150 break;
151 lock_list = lock_list->admin_next;
152 }
153 if (lock_list == NULL) {
154 /* We didn't find it. That possibility has to be OK'd by the
155 caller. */
156 tl_assert(allowed_to_be_invalid);
157 return Lock_INVALID;
158 }
159
160 /* So we must be looking at a valid LockN. */
sewardjf98e1c02008-10-25 16:22:41 +0000161 tl_assert( HG_(is_sane_LockN)(lkn) );
sewardjffce8152011-06-24 10:09:41 +0000162
sewardjf98e1c02008-10-25 16:22:41 +0000163 if (!map_LockN_to_P) {
164 map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1",
165 HG_(free), lock_unique_cmp );
sewardjf98e1c02008-10-25 16:22:41 +0000166 }
florian6bf37262012-10-21 03:23:36 +0000167 if (!VG_(lookupFM)( map_LockN_to_P, NULL, (UWord*)&lkp, (UWord)lkn)) {
sewardjf98e1c02008-10-25 16:22:41 +0000168 lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
169 *lkp = *lkn;
sewardj1d7c3322011-02-28 09:22:51 +0000170 lkp->admin_next = NULL;
171 lkp->admin_prev = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000172 lkp->magic = LockP_MAGIC;
173 /* Forget about the bag of lock holders - don't copy that.
174 Also, acquired_at should be NULL whenever heldBy is, and vice
175 versa. Also forget about the associated libhb synch object. */
176 lkp->heldW = False;
177 lkp->heldBy = NULL;
178 lkp->acquired_at = NULL;
179 lkp->hbso = NULL;
florian6bf37262012-10-21 03:23:36 +0000180 VG_(addToFM)( map_LockN_to_P, (UWord)lkp, (UWord)lkp );
sewardjf98e1c02008-10-25 16:22:41 +0000181 }
182 tl_assert( HG_(is_sane_LockP)(lkp) );
183 return lkp;
184}
185
sewardjffce8152011-06-24 10:09:41 +0000186/* Expand a WordSet of LockN*'s into a NULL-terminated vector of
187 LockP*'s. Any LockN's that can't be converted into a LockP
188 (because they have been freed, see comment on mk_LockP_from_LockN)
189 are converted instead into the value Lock_INVALID. Hence the
190 returned vector is a sequence: zero or more (valid LockP* or
191 LockN_INVALID), terminated by a NULL. */
192static
193Lock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets,
194 WordSetID lockset,
195 Bool allowed_to_be_invalid )
196{
197 tl_assert(univ_lsets);
198 tl_assert( HG_(plausibleWS)(univ_lsets, lockset) );
199 UWord nLocks = HG_(cardinalityWS)(univ_lsets, lockset);
200 Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa",
201 (nLocks+1) * sizeof(Lock*) );
sewardjffce8152011-06-24 10:09:41 +0000202 tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */
203 UWord* lockNs = NULL;
204 UWord nLockNs = 0;
205 if (nLocks > 0) {
206 /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the
207 lockset is empty; hence the guarding "if". Sigh. */
208 HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset );
209 tl_assert(lockNs);
210 }
211 UWord i;
212 /* Convert to LockPs. */
213 for (i = 0; i < nLockNs; i++) {
214 lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i],
215 allowed_to_be_invalid );
216 }
217 return lockPs;
218}
219
220/* Get the number of useful elements in a vector created by
221 enumerate_WordSet_into_LockP_vector. Returns both the total number
222 of elements (not including the terminating NULL) and the number of
223 non-Lock_INVALID elements. */
224static void count_LockP_vector ( /*OUT*/UWord* nLocks,
225 /*OUT*/UWord* nLocksValid,
226 Lock** vec )
227{
228 tl_assert(vec);
229 *nLocks = *nLocksValid = 0;
230 UWord n = 0;
231 while (vec[n]) {
232 (*nLocks)++;
233 if (vec[n] != Lock_INVALID)
234 (*nLocksValid)++;
235 n++;
236 }
237}
238
239/* Find out whether 'lk' is in 'vec'. */
240static Bool elem_LockP_vector ( Lock** vec, Lock* lk )
241{
242 tl_assert(vec);
243 tl_assert(lk);
244 UWord n = 0;
245 while (vec[n]) {
246 if (vec[n] == lk)
247 return True;
248 n++;
249 }
250 return False;
251}
252
253
sewardjf98e1c02008-10-25 16:22:41 +0000254/* Errors:
255
256 race: program counter
257 read or write
258 data size
259 previous state
260 current state
261
262 FIXME: how does state printing interact with lockset gc?
263 Are the locksets in prev/curr state always valid?
264 Ditto question for the threadsets
265 ThreadSets - probably are always valid if Threads
266 are never thrown away.
267 LockSets - could at least print the lockset elements that
268 correspond to actual locks at the time of printing. Hmm.
269*/
270
271/* Error kinds */
272typedef
273 enum {
274 XE_Race=1101, // race
sewardjf98e1c02008-10-25 16:22:41 +0000275 XE_UnlockUnlocked, // unlocking a not-locked lock
276 XE_UnlockForeign, // unlocking a lock held by some other thread
277 XE_UnlockBogus, // unlocking an address not known to be a lock
278 XE_PthAPIerror, // error from the POSIX pthreads API
279 XE_LockOrder, // lock order error
280 XE_Misc // misc other error (w/ string to describe it)
281 }
282 XErrorTag;
283
284/* Extra contexts for kinds */
285typedef
286 struct {
287 XErrorTag tag;
288 union {
289 struct {
sewardj23f12002009-07-24 08:45:08 +0000290 Addr data_addr;
291 Int szB;
philippe07c08522014-05-14 20:39:27 +0000292 AddrInfo data_addrinfo;
sewardj23f12002009-07-24 08:45:08 +0000293 Bool isWrite;
294 Thread* thr;
sewardjffce8152011-06-24 10:09:41 +0000295 Lock** locksHeldW;
sewardj095d61e2010-03-11 13:43:18 +0000296 /* h1_* and h2_* provide some description of a previously
297 observed access with which we are conflicting. */
sewardj23f12002009-07-24 08:45:08 +0000298 Thread* h1_ct; /* non-NULL means h1 info present */
299 ExeContext* h1_ct_mbsegstartEC;
300 ExeContext* h1_ct_mbsegendEC;
301 Thread* h2_ct; /* non-NULL means h2 info present */
302 ExeContext* h2_ct_accEC;
303 Int h2_ct_accSzB;
304 Bool h2_ct_accIsW;
sewardjffce8152011-06-24 10:09:41 +0000305 Lock** h2_ct_locksHeldW;
sewardjf98e1c02008-10-25 16:22:41 +0000306 } Race;
307 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000308 Thread* thr; /* doing the unlocking */
309 Lock* lock; /* lock (that is already unlocked) */
310 } UnlockUnlocked;
311 struct {
312 Thread* thr; /* doing the unlocking */
313 Thread* owner; /* thread that actually holds the lock */
314 Lock* lock; /* lock (that is held by 'owner') */
315 } UnlockForeign;
316 struct {
317 Thread* thr; /* doing the unlocking */
318 Addr lock_ga; /* purported address of the lock */
319 } UnlockBogus;
320 struct {
321 Thread* thr;
322 HChar* fnname; /* persistent, in tool-arena */
323 Word err; /* pth error code */
324 HChar* errstr; /* persistent, in tool-arena */
325 } PthAPIerror;
326 struct {
327 Thread* thr;
sewardjffce8152011-06-24 10:09:41 +0000328 /* The first 4 fields describe the previously observed
329 (should-be) ordering. */
philippe46daf0d2014-07-29 20:08:15 +0000330 Lock* shouldbe_earlier_lk;
331 Lock* shouldbe_later_lk;
sewardjffce8152011-06-24 10:09:41 +0000332 ExeContext* shouldbe_earlier_ec;
333 ExeContext* shouldbe_later_ec;
334 /* In principle we need to record two more stacks, from
335 this thread, when acquiring the locks in the "wrong"
336 order. In fact the wallclock-later acquisition by this
337 thread is recorded in the main stack for this error.
338 So we only need a stack for the earlier acquisition by
339 this thread. */
340 ExeContext* actual_earlier_ec;
sewardjf98e1c02008-10-25 16:22:41 +0000341 } LockOrder;
342 struct {
sewardj8fef6252010-07-29 05:28:02 +0000343 Thread* thr;
344 HChar* errstr; /* persistent, in tool-arena */
345 HChar* auxstr; /* optional, persistent, in tool-arena */
346 ExeContext* auxctx; /* optional */
sewardjf98e1c02008-10-25 16:22:41 +0000347 } Misc;
348 } XE;
349 }
350 XError;
351
352static void init_XError ( XError* xe ) {
353 VG_(memset)(xe, 0, sizeof(*xe) );
354 xe->tag = XE_Race-1; /* bogus */
355}
356
357
358/* Extensions of suppressions */
359typedef
360 enum {
361 XS_Race=1201, /* race */
362 XS_FreeMemLock,
363 XS_UnlockUnlocked,
364 XS_UnlockForeign,
365 XS_UnlockBogus,
366 XS_PthAPIerror,
367 XS_LockOrder,
368 XS_Misc
369 }
370 XSuppTag;
371
372
373/* Updates the copy with address info if necessary. */
florian8e3fbb52014-10-20 19:02:38 +0000374UInt HG_(update_extra) ( const Error* err )
sewardjf98e1c02008-10-25 16:22:41 +0000375{
376 XError* xe = (XError*)VG_(get_error_extra)(err);
377 tl_assert(xe);
378 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
379 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
380 //}
381
382 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000383
sewardjffce8152011-06-24 10:09:41 +0000384 /* Note the set of locks that the thread is (w-)holding.
385 Convert the WordSetID of LockN*'s into a NULL-terminated
386 vector of LockP*'s. We don't expect to encounter any invalid
387 LockNs in this conversion. */
388 tl_assert(xe->XE.Race.thr);
389 xe->XE.Race.locksHeldW
390 = enumerate_WordSet_into_LockP_vector(
391 HG_(get_univ_lsets)(),
392 xe->XE.Race.thr->locksetW,
393 False/*!allowed_to_be_invalid*/
394 );
395
sewardjf98e1c02008-10-25 16:22:41 +0000396 /* See if we can come up with a source level description of the
397 raced-upon address. This is potentially expensive, which is
398 why it's only done at the update_extra point, not when the
399 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000400 static Int xxx = 0;
401 xxx++;
402 if (0)
403 VG_(printf)("HG_(update_extra): "
404 "%d conflicting-event queries\n", xxx);
sewardj095d61e2010-03-11 13:43:18 +0000405
philippe07c08522014-05-14 20:39:27 +0000406 HG_(describe_addr) (xe->XE.Race.data_addr, &xe->XE.Race.data_addrinfo);
sewardj24118492009-07-15 14:50:02 +0000407
408 /* And poke around in the conflicting-event map, to see if we
409 can rustle up a plausible-looking conflicting memory access
410 to show. */
sewardj23f12002009-07-24 08:45:08 +0000411 if (HG_(clo_history_level) >= 2) {
sewardjffce8152011-06-24 10:09:41 +0000412 Thr* thrp = NULL;
413 ExeContext* wherep = NULL;
414 Addr acc_addr = xe->XE.Race.data_addr;
415 Int acc_szB = xe->XE.Race.szB;
416 Thr* acc_thr = xe->XE.Race.thr->hbthr;
417 Bool acc_isW = xe->XE.Race.isWrite;
418 SizeT conf_szB = 0;
419 Bool conf_isW = False;
420 WordSetID conf_locksHeldW = 0;
sewardj23f12002009-07-24 08:45:08 +0000421 tl_assert(!xe->XE.Race.h2_ct_accEC);
422 tl_assert(!xe->XE.Race.h2_ct);
423 if (libhb_event_map_lookup(
sewardjffce8152011-06-24 10:09:41 +0000424 &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW,
sewardj23f12002009-07-24 08:45:08 +0000425 acc_thr, acc_addr, acc_szB, acc_isW )) {
426 Thread* threadp;
427 tl_assert(wherep);
428 tl_assert(thrp);
sewardj60626642011-03-10 15:14:37 +0000429 threadp = libhb_get_Thr_hgthread( thrp );
sewardj23f12002009-07-24 08:45:08 +0000430 tl_assert(threadp);
431 xe->XE.Race.h2_ct_accEC = wherep;
432 xe->XE.Race.h2_ct = threadp;
433 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
434 xe->XE.Race.h2_ct_accIsW = conf_isW;
sewardjffce8152011-06-24 10:09:41 +0000435 xe->XE.Race.h2_ct_locksHeldW
436 = enumerate_WordSet_into_LockP_vector(
437 HG_(get_univ_lsets)(),
438 conf_locksHeldW,
439 True/*allowed_to_be_invalid*/
440 );
sewardjc5ea9962008-12-07 01:41:46 +0000441 }
442 }
sewardj23f12002009-07-24 08:45:08 +0000443
444 // both NULL or both non-NULL
445 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
sewardjf98e1c02008-10-25 16:22:41 +0000446 }
447
448 return sizeof(XError);
449}
450
451void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000452 Addr data_addr, Int szB, Bool isWrite,
sewardj23f12002009-07-24 08:45:08 +0000453 Thread* h1_ct,
454 ExeContext* h1_ct_segstart,
455 ExeContext* h1_ct_mbsegendEC )
sewardjf98e1c02008-10-25 16:22:41 +0000456{
457 XError xe;
458 tl_assert( HG_(is_sane_Thread)(thr) );
459
460# if defined(VGO_linux)
461 /* Skip any races on locations apparently in GOTPLT sections. This
462 is said to be caused by ld.so poking PLT table entries (or
463 whatever) when it writes the resolved address of a dynamically
464 linked routine, into the table (or whatever) when it is called
465 for the first time. */
466 {
sewardje3f1e592009-07-31 09:41:29 +0000467 VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr );
sewardjf98e1c02008-10-25 16:22:41 +0000468 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
469 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000470 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000471 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000472 /* SectPLT is required on ppc32/64-linux */
473 if (sect == Vg_SectPLT) return;
mjw4fa71082014-09-01 15:29:55 +0000474 /* SectGOT is required on arm-linux */
475 if (sect == Vg_SectGOT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000476 }
477# endif
478
479 init_XError(&xe);
480 xe.tag = XE_Race;
481 xe.XE.Race.data_addr = data_addr;
482 xe.XE.Race.szB = szB;
483 xe.XE.Race.isWrite = isWrite;
sewardjf98e1c02008-10-25 16:22:41 +0000484 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000485 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000486 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000487 /* Skip on the detailed description of the raced-on address at this
488 point; it's expensive. Leave it for the update_extra function
489 if we ever make it that far. */
philippe07c08522014-05-14 20:39:27 +0000490 xe.XE.Race.data_addrinfo.tag = Addr_Undescribed;
sewardjf98e1c02008-10-25 16:22:41 +0000491 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000492 // Skip on any of the conflicting-access info at this point.
493 // It's expensive to obtain, and this error is more likely than
494 // not to be discarded. We'll fill these fields in in
495 // HG_(update_extra) just above, assuming the error ever makes
496 // it that far (unlikely).
sewardj23f12002009-07-24 08:45:08 +0000497 xe.XE.Race.h2_ct_accSzB = 0;
498 xe.XE.Race.h2_ct_accIsW = False;
499 xe.XE.Race.h2_ct_accEC = NULL;
500 xe.XE.Race.h2_ct = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000501 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
502 tl_assert( thr->coretid != VG_INVALID_THREADID );
sewardj23f12002009-07-24 08:45:08 +0000503
504 xe.XE.Race.h1_ct = h1_ct;
505 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
506 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC;
507
sewardjf98e1c02008-10-25 16:22:41 +0000508 VG_(maybe_record_error)( thr->coretid,
509 XE_Race, data_addr, NULL, &xe );
510}
511
sewardjf98e1c02008-10-25 16:22:41 +0000512void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
513{
514 XError xe;
515 tl_assert( HG_(is_sane_Thread)(thr) );
516 tl_assert( HG_(is_sane_LockN)(lk) );
517 init_XError(&xe);
518 xe.tag = XE_UnlockUnlocked;
sewardjffce8152011-06-24 10:09:41 +0000519 xe.XE.UnlockUnlocked.thr
520 = thr;
521 xe.XE.UnlockUnlocked.lock
522 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
sewardjf98e1c02008-10-25 16:22:41 +0000523 // FIXME: tid vs thr
524 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
525 tl_assert( thr->coretid != VG_INVALID_THREADID );
526 VG_(maybe_record_error)( thr->coretid,
527 XE_UnlockUnlocked, 0, NULL, &xe );
528}
529
530void HG_(record_error_UnlockForeign) ( Thread* thr,
531 Thread* owner, Lock* lk )
532{
533 XError xe;
534 tl_assert( HG_(is_sane_Thread)(thr) );
535 tl_assert( HG_(is_sane_Thread)(owner) );
536 tl_assert( HG_(is_sane_LockN)(lk) );
537 init_XError(&xe);
538 xe.tag = XE_UnlockForeign;
539 xe.XE.UnlockForeign.thr = thr;
540 xe.XE.UnlockForeign.owner = owner;
sewardjffce8152011-06-24 10:09:41 +0000541 xe.XE.UnlockForeign.lock
542 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
sewardjf98e1c02008-10-25 16:22:41 +0000543 // FIXME: tid vs thr
544 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
545 tl_assert( thr->coretid != VG_INVALID_THREADID );
546 VG_(maybe_record_error)( thr->coretid,
547 XE_UnlockForeign, 0, NULL, &xe );
548}
549
550void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
551{
552 XError xe;
553 tl_assert( HG_(is_sane_Thread)(thr) );
554 init_XError(&xe);
555 xe.tag = XE_UnlockBogus;
556 xe.XE.UnlockBogus.thr = thr;
557 xe.XE.UnlockBogus.lock_ga = lock_ga;
558 // FIXME: tid vs thr
559 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
560 tl_assert( thr->coretid != VG_INVALID_THREADID );
561 VG_(maybe_record_error)( thr->coretid,
562 XE_UnlockBogus, 0, NULL, &xe );
563}
564
565void HG_(record_error_LockOrder)(
sewardjffce8152011-06-24 10:09:41 +0000566 Thread* thr,
philippe46daf0d2014-07-29 20:08:15 +0000567 Lock* shouldbe_earlier_lk,
568 Lock* shouldbe_later_lk,
sewardjffce8152011-06-24 10:09:41 +0000569 ExeContext* shouldbe_earlier_ec,
570 ExeContext* shouldbe_later_ec,
571 ExeContext* actual_earlier_ec
sewardjf98e1c02008-10-25 16:22:41 +0000572 )
573{
574 XError xe;
575 tl_assert( HG_(is_sane_Thread)(thr) );
sewardjc1fb9d22011-02-28 09:03:44 +0000576 tl_assert(HG_(clo_track_lockorders));
sewardjf98e1c02008-10-25 16:22:41 +0000577 init_XError(&xe);
578 xe.tag = XE_LockOrder;
579 xe.XE.LockOrder.thr = thr;
philippe46daf0d2014-07-29 20:08:15 +0000580 xe.XE.LockOrder.shouldbe_earlier_lk
581 = mk_LockP_from_LockN(shouldbe_earlier_lk,
582 False/*!allowed_to_be_invalid*/);
sewardjffce8152011-06-24 10:09:41 +0000583 xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec;
philippe46daf0d2014-07-29 20:08:15 +0000584 xe.XE.LockOrder.shouldbe_later_lk
585 = mk_LockP_from_LockN(shouldbe_later_lk,
586 False/*!allowed_to_be_invalid*/);
sewardjffce8152011-06-24 10:09:41 +0000587 xe.XE.LockOrder.shouldbe_later_ec = shouldbe_later_ec;
588 xe.XE.LockOrder.actual_earlier_ec = actual_earlier_ec;
sewardjf98e1c02008-10-25 16:22:41 +0000589 // FIXME: tid vs thr
590 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
591 tl_assert( thr->coretid != VG_INVALID_THREADID );
592 VG_(maybe_record_error)( thr->coretid,
593 XE_LockOrder, 0, NULL, &xe );
594}
595
florian6bd9dc12012-11-23 16:17:43 +0000596void HG_(record_error_PthAPIerror) ( Thread* thr, const HChar* fnname,
597 Word err, const HChar* errstr )
sewardjf98e1c02008-10-25 16:22:41 +0000598{
599 XError xe;
600 tl_assert( HG_(is_sane_Thread)(thr) );
601 tl_assert(fnname);
602 tl_assert(errstr);
603 init_XError(&xe);
604 xe.tag = XE_PthAPIerror;
605 xe.XE.PthAPIerror.thr = thr;
606 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
607 xe.XE.PthAPIerror.err = err;
608 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
609 // FIXME: tid vs thr
610 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
611 tl_assert( thr->coretid != VG_INVALID_THREADID );
612 VG_(maybe_record_error)( thr->coretid,
613 XE_PthAPIerror, 0, NULL, &xe );
614}
615
florian6bd9dc12012-11-23 16:17:43 +0000616void HG_(record_error_Misc_w_aux) ( Thread* thr, const HChar* errstr,
617 const HChar* auxstr, ExeContext* auxctx )
sewardjf98e1c02008-10-25 16:22:41 +0000618{
619 XError xe;
620 tl_assert( HG_(is_sane_Thread)(thr) );
621 tl_assert(errstr);
622 init_XError(&xe);
623 xe.tag = XE_Misc;
624 xe.XE.Misc.thr = thr;
625 xe.XE.Misc.errstr = string_table_strdup(errstr);
sewardj8fef6252010-07-29 05:28:02 +0000626 xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
627 xe.XE.Misc.auxctx = auxctx;
sewardjf98e1c02008-10-25 16:22:41 +0000628 // FIXME: tid vs thr
629 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
630 tl_assert( thr->coretid != VG_INVALID_THREADID );
631 VG_(maybe_record_error)( thr->coretid,
632 XE_Misc, 0, NULL, &xe );
633}
634
florian6bd9dc12012-11-23 16:17:43 +0000635void HG_(record_error_Misc) ( Thread* thr, const HChar* errstr )
sewardj8fef6252010-07-29 05:28:02 +0000636{
637 HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
638}
639
florian8e3fbb52014-10-20 19:02:38 +0000640Bool HG_(eq_Error) ( VgRes not_used, const Error* e1, const Error* e2 )
sewardjf98e1c02008-10-25 16:22:41 +0000641{
642 XError *xe1, *xe2;
643
644 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
645
646 xe1 = (XError*)VG_(get_error_extra)(e1);
647 xe2 = (XError*)VG_(get_error_extra)(e2);
648 tl_assert(xe1);
649 tl_assert(xe2);
650
651 switch (VG_(get_error_kind)(e1)) {
652 case XE_Race:
653 return xe1->XE.Race.szB == xe2->XE.Race.szB
654 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
655 && (HG_(clo_cmp_race_err_addrs)
656 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
657 : True);
sewardjf98e1c02008-10-25 16:22:41 +0000658 case XE_UnlockUnlocked:
659 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
660 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
661 case XE_UnlockForeign:
662 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
663 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
664 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
665 case XE_UnlockBogus:
666 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
667 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
668 case XE_PthAPIerror:
669 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
670 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
671 xe2->XE.PthAPIerror.fnname)
672 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
673 case XE_LockOrder:
674 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
675 case XE_Misc:
676 return xe1->XE.Misc.thr == xe2->XE.Misc.thr
677 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
678 default:
679 tl_assert(0);
680 }
681
682 /*NOTREACHED*/
683 tl_assert(0);
684}
685
686
sewardj24118492009-07-15 14:50:02 +0000687/*----------------------------------------------------------------*/
688/*--- Error management -- printing ---*/
689/*----------------------------------------------------------------*/
690
691/* Do a printf-style operation on either the XML or normal output
692 channel, depending on the setting of VG_(clo_xml).
693*/
florian6bf37262012-10-21 03:23:36 +0000694static void emit_WRK ( const HChar* format, va_list vargs )
sewardj24118492009-07-15 14:50:02 +0000695{
696 if (VG_(clo_xml)) {
697 VG_(vprintf_xml)(format, vargs);
698 } else {
699 VG_(vmessage)(Vg_UserMsg, format, vargs);
700 }
701}
florian6bf37262012-10-21 03:23:36 +0000702static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
703static void emit ( const HChar* format, ... )
sewardj24118492009-07-15 14:50:02 +0000704{
705 va_list vargs;
706 va_start(vargs, format);
707 emit_WRK(format, vargs);
708 va_end(vargs);
709}
sewardj24118492009-07-15 14:50:02 +0000710
711
sewardjf98e1c02008-10-25 16:22:41 +0000712/* Announce (that is, print the point-of-creation) of 'thr'. Only do
713 this once, as we only want to see these announcements once per
sewardj24118492009-07-15 14:50:02 +0000714 thread. Returned Bool indicates whether or not an announcement was
715 made.
716*/
717static Bool announce_one_thread ( Thread* thr )
sewardjf98e1c02008-10-25 16:22:41 +0000718{
719 tl_assert(HG_(is_sane_Thread)(thr));
720 tl_assert(thr->errmsg_index >= 1);
sewardj24118492009-07-15 14:50:02 +0000721 if (thr->announced)
722 return False;
723
724 if (VG_(clo_xml)) {
725
726 VG_(printf_xml)("<announcethread>\n");
sewardj11b5c6d2009-09-03 10:29:57 +0000727 VG_(printf_xml)(" <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
sewardjf98e1c02008-10-25 16:22:41 +0000728 if (thr->errmsg_index == 1) {
729 tl_assert(thr->created_at == NULL);
sewardj24118492009-07-15 14:50:02 +0000730 VG_(printf_xml)(" <isrootthread></isrootthread>\n");
sewardjf98e1c02008-10-25 16:22:41 +0000731 } else {
732 tl_assert(thr->created_at != NULL);
sewardj24118492009-07-15 14:50:02 +0000733 VG_(pp_ExeContext)( thr->created_at );
734 }
735 VG_(printf_xml)("</announcethread>\n\n");
736
737 } else {
738
sewardjffce8152011-06-24 10:09:41 +0000739 VG_(umsg)("---Thread-Announcement----------"
740 "--------------------------------" "\n");
741 VG_(umsg)("\n");
742
sewardj24118492009-07-15 14:50:02 +0000743 if (thr->errmsg_index == 1) {
744 tl_assert(thr->created_at == NULL);
745 VG_(message)(Vg_UserMsg,
746 "Thread #%d is the program's root thread\n",
747 thr->errmsg_index);
748 } else {
749 tl_assert(thr->created_at != NULL);
750 VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
sewardjf98e1c02008-10-25 16:22:41 +0000751 thr->errmsg_index);
752 VG_(pp_ExeContext)( thr->created_at );
753 }
sewardj24118492009-07-15 14:50:02 +0000754 VG_(message)(Vg_UserMsg, "\n");
755
756 }
757
758 thr->announced = True;
759 return True;
760}
761
sewardjffce8152011-06-24 10:09:41 +0000762/* Announce 'lk'. */
763static void announce_LockP ( Lock* lk )
764{
765 tl_assert(lk);
766 if (lk == Lock_INVALID)
767 return; /* Can't be announced -- we know nothing about it. */
768 tl_assert(lk->magic == LockP_MAGIC);
sewardjffce8152011-06-24 10:09:41 +0000769
770 if (VG_(clo_xml)) {
philippe46daf0d2014-07-29 20:08:15 +0000771 if (lk->appeared_at) {
772 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
773 (void*)lk );
774 VG_(pp_ExeContext)( lk->appeared_at );
775 }
776
sewardjffce8152011-06-24 10:09:41 +0000777 } else {
philippe80612012014-07-24 21:00:24 +0000778 if (lk->appeared_at) {
philippe46daf0d2014-07-29 20:08:15 +0000779 VG_(umsg)( " Lock at %p was first observed\n",
philippe80612012014-07-24 21:00:24 +0000780 (void*)lk->guestaddr );
781 VG_(pp_ExeContext)( lk->appeared_at );
782 } else {
philippe46daf0d2014-07-29 20:08:15 +0000783 VG_(umsg)( " Lock at %p : no stacktrace for first observation\n",
philippe80612012014-07-24 21:00:24 +0000784 (void*)lk->guestaddr );
785 }
786 HG_(get_and_pp_addrdescr) (lk->guestaddr);
sewardjffce8152011-06-24 10:09:41 +0000787 VG_(umsg)("\n");
788 }
789}
790
791/* Announce (that is, print point-of-first-observation) for the
792 locks in 'lockvec' and, if non-NULL, 'lockvec2'. */
793static void announce_combined_LockP_vecs ( Lock** lockvec,
794 Lock** lockvec2 )
795{
796 UWord i;
797 tl_assert(lockvec);
798 for (i = 0; lockvec[i]; i++) {
799 announce_LockP(lockvec[i]);
800 }
801 if (lockvec2) {
802 for (i = 0; lockvec2[i]; i++) {
803 Lock* lk = lockvec2[i];
804 if (!elem_LockP_vector(lockvec, lk))
805 announce_LockP(lk);
806 }
807 }
808}
809
810
florian6bd9dc12012-11-23 16:17:43 +0000811static void show_LockP_summary_textmode ( Lock** locks, const HChar* pre )
sewardjffce8152011-06-24 10:09:41 +0000812{
813 tl_assert(locks);
814 UWord i;
815 UWord nLocks = 0, nLocksValid = 0;
816 count_LockP_vector(&nLocks, &nLocksValid, locks);
817 tl_assert(nLocksValid <= nLocks);
818
819 if (nLocks == 0) {
820 VG_(umsg)( "%sLocks held: none", pre );
821 } else {
822 VG_(umsg)( "%sLocks held: %lu, at address%s ",
823 pre, nLocks, nLocksValid == 1 ? "" : "es" );
824 }
825
826 if (nLocks > 0) {
827 for (i = 0; i < nLocks; i++) {
828 if (locks[i] == Lock_INVALID)
829 continue;
830 VG_(umsg)( "%p", (void*)locks[i]->guestaddr);
831 if (locks[i+1] != NULL)
832 VG_(umsg)(" ");
833 }
834 if (nLocksValid < nLocks)
835 VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid);
836 }
837 VG_(umsg)("\n");
838}
839
840
sewardj24118492009-07-15 14:50:02 +0000841/* This is the "this error is due to be printed shortly; so have a
842 look at it any print any preamble you want" function. We use it to
843 announce any previously un-announced threads in the upcoming error
844 message.
845*/
florian8e3fbb52014-10-20 19:02:38 +0000846void HG_(before_pp_Error) ( const Error* err )
sewardj24118492009-07-15 14:50:02 +0000847{
848 XError* xe;
849 tl_assert(err);
850 xe = (XError*)VG_(get_error_extra)(err);
851 tl_assert(xe);
852
853 switch (VG_(get_error_kind)(err)) {
854 case XE_Misc:
855 announce_one_thread( xe->XE.Misc.thr );
856 break;
857 case XE_LockOrder:
858 announce_one_thread( xe->XE.LockOrder.thr );
859 break;
860 case XE_PthAPIerror:
861 announce_one_thread( xe->XE.PthAPIerror.thr );
862 break;
863 case XE_UnlockBogus:
864 announce_one_thread( xe->XE.UnlockBogus.thr );
865 break;
866 case XE_UnlockForeign:
867 announce_one_thread( xe->XE.UnlockForeign.thr );
868 announce_one_thread( xe->XE.UnlockForeign.owner );
869 break;
870 case XE_UnlockUnlocked:
871 announce_one_thread( xe->XE.UnlockUnlocked.thr );
872 break;
873 case XE_Race:
874 announce_one_thread( xe->XE.Race.thr );
sewardj23f12002009-07-24 08:45:08 +0000875 if (xe->XE.Race.h2_ct)
876 announce_one_thread( xe->XE.Race.h2_ct );
877 if (xe->XE.Race.h1_ct)
878 announce_one_thread( xe->XE.Race.h1_ct );
philippe0c9ac8d2014-07-18 00:03:58 +0000879 if (xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
880 Thread* thr = get_admin_threads();
881 while (thr) {
882 if (thr->errmsg_index
883 == xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
884 announce_one_thread (thr);
885 break;
886 }
887 thr = thr->admin;
888 }
889 }
sewardj24118492009-07-15 14:50:02 +0000890 break;
891 default:
892 tl_assert(0);
sewardjf98e1c02008-10-25 16:22:41 +0000893 }
894}
895
florian8e3fbb52014-10-20 19:02:38 +0000896void HG_(pp_Error) ( const Error* err )
sewardjf98e1c02008-10-25 16:22:41 +0000897{
sewardj24118492009-07-15 14:50:02 +0000898 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
899
sewardjffce8152011-06-24 10:09:41 +0000900 if (!xml) {
901 VG_(umsg)("--------------------------------"
902 "--------------------------------" "\n");
903 VG_(umsg)("\n");
904 }
905
sewardjf98e1c02008-10-25 16:22:41 +0000906 XError *xe = (XError*)VG_(get_error_extra)(err);
sewardj24118492009-07-15 14:50:02 +0000907 tl_assert(xe);
sewardjf98e1c02008-10-25 16:22:41 +0000908
bart2fa18d92011-10-04 16:28:42 +0000909 if (xml)
910 emit( " <kind>%s</kind>\n", HG_(get_error_name)(err));
911
sewardjf98e1c02008-10-25 16:22:41 +0000912 switch (VG_(get_error_kind)(err)) {
913
914 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000915 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000916
917 if (xml) {
918
sewardj24118492009-07-15 14:50:02 +0000919 emit( " <xwhat>\n" );
920 emit( " <text>Thread #%d: %s</text>\n",
921 (Int)xe->XE.Misc.thr->errmsg_index,
922 xe->XE.Misc.errstr );
923 emit( " <hthreadid>%d</hthreadid>\n",
924 (Int)xe->XE.Misc.thr->errmsg_index );
925 emit( " </xwhat>\n" );
926 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000927 if (xe->XE.Misc.auxstr) {
928 emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
929 if (xe->XE.Misc.auxctx)
930 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
931 }
sewardj24118492009-07-15 14:50:02 +0000932
933 } else {
934
935 emit( "Thread #%d: %s\n",
936 (Int)xe->XE.Misc.thr->errmsg_index,
937 xe->XE.Misc.errstr );
938 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000939 if (xe->XE.Misc.auxstr) {
940 emit(" %s\n", xe->XE.Misc.auxstr);
941 if (xe->XE.Misc.auxctx)
942 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
943 }
sewardj24118492009-07-15 14:50:02 +0000944
945 }
sewardjf98e1c02008-10-25 16:22:41 +0000946 break;
947 }
948
949 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000950 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000951
952 if (xml) {
953
sewardj24118492009-07-15 14:50:02 +0000954 emit( " <xwhat>\n" );
955 emit( " <text>Thread #%d: lock order \"%p before %p\" "
956 "violated</text>\n",
957 (Int)xe->XE.LockOrder.thr->errmsg_index,
philippe46daf0d2014-07-29 20:08:15 +0000958 (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
959 (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
sewardj24118492009-07-15 14:50:02 +0000960 emit( " <hthreadid>%d</hthreadid>\n",
961 (Int)xe->XE.LockOrder.thr->errmsg_index );
962 emit( " </xwhat>\n" );
963 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +0000964 if (xe->XE.LockOrder.shouldbe_earlier_ec
965 && xe->XE.LockOrder.shouldbe_later_ec) {
sewardj24118492009-07-15 14:50:02 +0000966 emit( " <auxwhat>Required order was established by "
967 "acquisition of lock at %p</auxwhat>\n",
philippe46daf0d2014-07-29 20:08:15 +0000968 (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
sewardjffce8152011-06-24 10:09:41 +0000969 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
sewardj24118492009-07-15 14:50:02 +0000970 emit( " <auxwhat>followed by a later acquisition "
971 "of lock at %p</auxwhat>\n",
philippe46daf0d2014-07-29 20:08:15 +0000972 (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
sewardjffce8152011-06-24 10:09:41 +0000973 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +0000974 }
philippe46daf0d2014-07-29 20:08:15 +0000975 announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
976 announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
sewardj24118492009-07-15 14:50:02 +0000977
978 } else {
979
980 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
981 (Int)xe->XE.LockOrder.thr->errmsg_index,
philippe46daf0d2014-07-29 20:08:15 +0000982 (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
983 (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
sewardjffce8152011-06-24 10:09:41 +0000984 emit( "\n" );
985 emit( "Observed (incorrect) order is: "
986 "acquisition of lock at %p\n",
philippe46daf0d2014-07-29 20:08:15 +0000987 (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr);
sewardjffce8152011-06-24 10:09:41 +0000988 if (xe->XE.LockOrder.actual_earlier_ec) {
989 VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
990 } else {
991 emit(" (stack unavailable)\n");
992 }
993 emit( "\n" );
994 emit(" followed by a later acquisition of lock at %p\n",
philippe46daf0d2014-07-29 20:08:15 +0000995 (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr);
sewardj24118492009-07-15 14:50:02 +0000996 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +0000997 if (xe->XE.LockOrder.shouldbe_earlier_ec
998 && xe->XE.LockOrder.shouldbe_later_ec) {
999 emit("\n");
1000 emit( "Required order was established by "
sewardj24118492009-07-15 14:50:02 +00001001 "acquisition of lock at %p\n",
philippe46daf0d2014-07-29 20:08:15 +00001002 (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
sewardjffce8152011-06-24 10:09:41 +00001003 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
1004 emit( "\n" );
1005 emit( " followed by a later acquisition of lock at %p\n",
philippe46daf0d2014-07-29 20:08:15 +00001006 (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
sewardjffce8152011-06-24 10:09:41 +00001007 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +00001008 }
philippe46daf0d2014-07-29 20:08:15 +00001009 emit("\n");
1010 announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
1011 announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
sewardj24118492009-07-15 14:50:02 +00001012
sewardjf98e1c02008-10-25 16:22:41 +00001013 }
sewardj24118492009-07-15 14:50:02 +00001014
sewardjf98e1c02008-10-25 16:22:41 +00001015 break;
1016 }
1017
1018 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +00001019 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +00001020
1021 if (xml) {
1022
sewardj24118492009-07-15 14:50:02 +00001023 emit( " <xwhat>\n" );
bartb3af9cf2011-10-06 19:08:37 +00001024 emit(
1025 " <text>Thread #%d's call to %pS failed</text>\n",
sewardj24118492009-07-15 14:50:02 +00001026 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1027 xe->XE.PthAPIerror.fnname );
1028 emit( " <hthreadid>%d</hthreadid>\n",
1029 (Int)xe->XE.PthAPIerror.thr->errmsg_index );
1030 emit( " </xwhat>\n" );
1031 emit( " <what>with error code %ld (%s)</what>\n",
1032 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1033 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1034
1035 } else {
1036
bartb3af9cf2011-10-06 19:08:37 +00001037 emit( "Thread #%d's call to %pS failed\n",
sewardj24118492009-07-15 14:50:02 +00001038 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1039 xe->XE.PthAPIerror.fnname );
1040 emit( " with error code %ld (%s)\n",
1041 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1042 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1043
1044 }
1045
sewardjf98e1c02008-10-25 16:22:41 +00001046 break;
1047 }
1048
1049 case XE_UnlockBogus: {
sewardjf98e1c02008-10-25 16:22:41 +00001050 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
sewardj24118492009-07-15 14:50:02 +00001051
1052 if (xml) {
1053
sewardj24118492009-07-15 14:50:02 +00001054 emit( " <xwhat>\n" );
1055 emit( " <text>Thread #%d unlocked an invalid "
1056 "lock at %p</text>\n",
1057 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1058 (void*)xe->XE.UnlockBogus.lock_ga );
1059 emit( " <hthreadid>%d</hthreadid>\n",
1060 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
1061 emit( " </xwhat>\n" );
1062 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1063
1064 } else {
1065
1066 emit( "Thread #%d unlocked an invalid lock at %p\n",
1067 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1068 (void*)xe->XE.UnlockBogus.lock_ga );
1069 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1070
1071 }
1072
sewardjf98e1c02008-10-25 16:22:41 +00001073 break;
1074 }
1075
1076 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +00001077 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
1078 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
1079 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +00001080
1081 if (xml) {
1082
sewardj24118492009-07-15 14:50:02 +00001083 emit( " <xwhat>\n" );
1084 emit( " <text>Thread #%d unlocked lock at %p "
1085 "currently held by thread #%d</text>\n",
1086 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1087 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1088 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1089 emit( " <hthreadid>%d</hthreadid>\n",
1090 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
1091 emit( " <hthreadid>%d</hthreadid>\n",
1092 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1093 emit( " </xwhat>\n" );
1094 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe46daf0d2014-07-29 20:08:15 +00001095 announce_LockP ( xe->XE.UnlockForeign.lock );
sewardj24118492009-07-15 14:50:02 +00001096
1097 } else {
1098
1099 emit( "Thread #%d unlocked lock at %p "
1100 "currently held by thread #%d\n",
1101 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1102 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1103 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1104 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe46daf0d2014-07-29 20:08:15 +00001105 announce_LockP ( xe->XE.UnlockForeign.lock );
sewardj24118492009-07-15 14:50:02 +00001106
sewardjf98e1c02008-10-25 16:22:41 +00001107 }
sewardj24118492009-07-15 14:50:02 +00001108
sewardjf98e1c02008-10-25 16:22:41 +00001109 break;
1110 }
1111
1112 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +00001113 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
1114 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +00001115
sewardj24118492009-07-15 14:50:02 +00001116 if (xml) {
1117
sewardj24118492009-07-15 14:50:02 +00001118 emit( " <xwhat>\n" );
1119 emit( " <text>Thread #%d unlocked a "
1120 "not-locked lock at %p</text>\n",
1121 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1122 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1123 emit( " <hthreadid>%d</hthreadid>\n",
1124 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
1125 emit( " </xwhat>\n" );
1126 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe46daf0d2014-07-29 20:08:15 +00001127 announce_LockP ( xe->XE.UnlockUnlocked.lock);
sewardj24118492009-07-15 14:50:02 +00001128
1129 } else {
1130
1131 emit( "Thread #%d unlocked a not-locked lock at %p\n",
1132 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1133 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1134 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe46daf0d2014-07-29 20:08:15 +00001135 announce_LockP ( xe->XE.UnlockUnlocked.lock);
sewardj24118492009-07-15 14:50:02 +00001136
sewardjf98e1c02008-10-25 16:22:41 +00001137 }
sewardj24118492009-07-15 14:50:02 +00001138
sewardjf98e1c02008-10-25 16:22:41 +00001139 break;
1140 }
1141
1142 case XE_Race: {
1143 Addr err_ga;
florian6bf37262012-10-21 03:23:36 +00001144 const HChar* what;
sewardjf98e1c02008-10-25 16:22:41 +00001145 Int szB;
1146 what = xe->XE.Race.isWrite ? "write" : "read";
1147 szB = xe->XE.Race.szB;
1148 err_ga = VG_(get_error_address)(err);
1149
sewardj24118492009-07-15 14:50:02 +00001150 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardj23f12002009-07-24 08:45:08 +00001151 if (xe->XE.Race.h2_ct)
1152 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
sewardj24118492009-07-15 14:50:02 +00001153
1154 if (xml) {
1155
1156 /* ------ XML ------ */
sewardj24118492009-07-15 14:50:02 +00001157 emit( " <xwhat>\n" );
1158 emit( " <text>Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001159 "at %p by thread #%d</text>\n",
1160 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
sewardj24118492009-07-15 14:50:02 +00001161 emit( " <hthreadid>%d</hthreadid>\n",
1162 (Int)xe->XE.Race.thr->errmsg_index );
1163 emit( " </xwhat>\n" );
1164 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1165
sewardj23f12002009-07-24 08:45:08 +00001166 if (xe->XE.Race.h2_ct) {
1167 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1168 emit( " <xauxwhat>\n");
1169 emit( " <text>This conflicts with a previous %s of size %d "
1170 "by thread #%d</text>\n",
1171 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1172 xe->XE.Race.h2_ct_accSzB,
1173 xe->XE.Race.h2_ct->errmsg_index );
1174 emit( " <hthreadid>%d</hthreadid>\n",
1175 xe->XE.Race.h2_ct->errmsg_index);
1176 emit(" </xauxwhat>\n");
1177 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1178 }
1179
1180 if (xe->XE.Race.h1_ct) {
1181 emit( " <xauxwhat>\n");
1182 emit( " <text>This conflicts with a previous access "
1183 "by thread #%d, after</text>\n",
1184 xe->XE.Race.h1_ct->errmsg_index );
1185 emit( " <hthreadid>%d</hthreadid>\n",
1186 xe->XE.Race.h1_ct->errmsg_index );
1187 emit(" </xauxwhat>\n");
1188 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1189 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001190 } else {
sewardj23f12002009-07-24 08:45:08 +00001191 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" );
sewardj24118492009-07-15 14:50:02 +00001192 }
sewardj23f12002009-07-24 08:45:08 +00001193 emit( " <auxwhat>but before</auxwhat>\n" );
1194 if (xe->XE.Race.h1_ct_mbsegendEC) {
1195 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1196 } else {
1197 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" );
1198 }
sewardjf98e1c02008-10-25 16:22:41 +00001199 }
sewardj24118492009-07-15 14:50:02 +00001200
1201 } else {
1202
1203 /* ------ Text ------ */
sewardjffce8152011-06-24 10:09:41 +00001204 announce_combined_LockP_vecs( xe->XE.Race.locksHeldW,
1205 xe->XE.Race.h2_ct_locksHeldW );
1206
sewardj24118492009-07-15 14:50:02 +00001207 emit( "Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001208 "at %p by thread #%d\n",
1209 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1210
1211 tl_assert(xe->XE.Race.locksHeldW);
1212 show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" );
sewardj24118492009-07-15 14:50:02 +00001213 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj23f12002009-07-24 08:45:08 +00001214
1215 if (xe->XE.Race.h2_ct) {
1216 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
sewardjffce8152011-06-24 10:09:41 +00001217 tl_assert(xe->XE.Race.h2_ct_locksHeldW);
1218 emit( "\n" );
1219 emit( "This conflicts with a previous %s of size %d "
sewardj23f12002009-07-24 08:45:08 +00001220 "by thread #%d\n",
1221 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1222 xe->XE.Race.h2_ct_accSzB,
1223 xe->XE.Race.h2_ct->errmsg_index );
sewardjffce8152011-06-24 10:09:41 +00001224 show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" );
sewardj23f12002009-07-24 08:45:08 +00001225 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1226 }
1227
1228 if (xe->XE.Race.h1_ct) {
1229 emit( " This conflicts with a previous access by thread #%d, "
1230 "after\n",
1231 xe->XE.Race.h1_ct->errmsg_index );
1232 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1233 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001234 } else {
sewardj23f12002009-07-24 08:45:08 +00001235 emit( " (the start of the thread)\n" );
sewardj24118492009-07-15 14:50:02 +00001236 }
sewardj23f12002009-07-24 08:45:08 +00001237 emit( " but before\n" );
1238 if (xe->XE.Race.h1_ct_mbsegendEC) {
1239 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1240 } else {
1241 emit( " (the end of the the thread)\n" );
1242 }
sewardj24118492009-07-15 14:50:02 +00001243 }
1244
sewardjf98e1c02008-10-25 16:22:41 +00001245 }
philippe07c08522014-05-14 20:39:27 +00001246 VG_(pp_addrinfo) (err_ga, &xe->XE.Race.data_addrinfo);
sewardjf98e1c02008-10-25 16:22:41 +00001247 break; /* case XE_Race */
1248 } /* case XE_Race */
1249
1250 default:
1251 tl_assert(0);
1252 } /* switch (VG_(get_error_kind)(err)) */
1253}
1254
florian8e3fbb52014-10-20 19:02:38 +00001255const HChar* HG_(get_error_name) ( const Error* err )
sewardjf98e1c02008-10-25 16:22:41 +00001256{
1257 switch (VG_(get_error_kind)(err)) {
1258 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +00001259 case XE_UnlockUnlocked: return "UnlockUnlocked";
1260 case XE_UnlockForeign: return "UnlockForeign";
1261 case XE_UnlockBogus: return "UnlockBogus";
1262 case XE_PthAPIerror: return "PthAPIerror";
1263 case XE_LockOrder: return "LockOrder";
1264 case XE_Misc: return "Misc";
1265 default: tl_assert(0); /* fill in missing case */
1266 }
1267}
1268
florian19f91bb2012-11-10 22:29:54 +00001269Bool HG_(recognised_suppression) ( const HChar* name, Supp *su )
sewardjf98e1c02008-10-25 16:22:41 +00001270{
1271# define TRY(_name,_xskind) \
1272 if (0 == VG_(strcmp)(name, (_name))) { \
1273 VG_(set_supp_kind)(su, (_xskind)); \
1274 return True; \
1275 }
1276 TRY("Race", XS_Race);
1277 TRY("FreeMemLock", XS_FreeMemLock);
1278 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1279 TRY("UnlockForeign", XS_UnlockForeign);
1280 TRY("UnlockBogus", XS_UnlockBogus);
1281 TRY("PthAPIerror", XS_PthAPIerror);
1282 TRY("LockOrder", XS_LockOrder);
1283 TRY("Misc", XS_Misc);
1284 return False;
1285# undef TRY
1286}
1287
florian19f91bb2012-11-10 22:29:54 +00001288Bool HG_(read_extra_suppression_info) ( Int fd, HChar** bufpp, SizeT* nBufp,
philippe362441d2013-07-22 22:00:13 +00001289 Int* lineno, Supp* su )
sewardjf98e1c02008-10-25 16:22:41 +00001290{
1291 /* do nothing -- no extra suppression info present. Return True to
1292 indicate nothing bad happened. */
1293 return True;
1294}
1295
florian8e3fbb52014-10-20 19:02:38 +00001296Bool HG_(error_matches_suppression) ( const Error* err, const Supp* su )
sewardjf98e1c02008-10-25 16:22:41 +00001297{
1298 switch (VG_(get_supp_kind)(su)) {
1299 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001300 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1301 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1302 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1303 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1304 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1305 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1306 //case XS_: return VG_(get_error_kind)(err) == XE_;
1307 default: tl_assert(0); /* fill in missing cases */
1308 }
1309}
1310
florian8e3fbb52014-10-20 19:02:38 +00001311SizeT HG_(get_extra_suppression_info) ( const Error* err,
floriandbb35842012-10-27 18:39:11 +00001312 /*OUT*/HChar* buf, Int nBuf )
sewardjf98e1c02008-10-25 16:22:41 +00001313{
florian3e81b8b2014-10-07 14:28:52 +00001314 tl_assert(nBuf >= 1);
sewardjf98e1c02008-10-25 16:22:41 +00001315 /* Do nothing */
florian3e81b8b2014-10-07 14:28:52 +00001316 buf[0] = '\0';
1317 return 0;
sewardjf98e1c02008-10-25 16:22:41 +00001318}
1319
florian8e3fbb52014-10-20 19:02:38 +00001320SizeT HG_(print_extra_suppression_use) ( const Supp* su,
philippe4e32d672013-10-17 22:10:41 +00001321 /*OUT*/HChar* buf, Int nBuf )
1322{
florian3e81b8b2014-10-07 14:28:52 +00001323 tl_assert(nBuf >= 1);
philippe4e32d672013-10-17 22:10:41 +00001324 /* Do nothing */
florian3e81b8b2014-10-07 14:28:52 +00001325 buf[0] = '\0';
1326 return 0;
philippe4e32d672013-10-17 22:10:41 +00001327}
1328
florian8e3fbb52014-10-20 19:02:38 +00001329void HG_(update_extra_suppression_use) ( const Error* err, const Supp* su )
philippe4e32d672013-10-17 22:10:41 +00001330{
1331 /* Do nothing */
1332 return;
1333}
1334
sewardjf98e1c02008-10-25 16:22:41 +00001335
1336/*--------------------------------------------------------------------*/
1337/*--- end hg_errors.c ---*/
1338/*--------------------------------------------------------------------*/