blob: 41d99e26951cc44e91c03cce487d3fd17f0eb953 [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
sewardj9eecbbb2010-05-03 21:37:12 +000011 Copyright (C) 2007-2010 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)
sewardjf98e1c02008-10-25 16:22:41 +000043
44#include "hg_basics.h"
45#include "hg_wordset.h"
46#include "hg_lock_n_thread.h"
sewardjc5ea9962008-12-07 01:41:46 +000047#include "libhb.h"
sewardjf98e1c02008-10-25 16:22:41 +000048#include "hg_errors.h" /* self */
49
50
51/*----------------------------------------------------------------*/
sewardj24118492009-07-15 14:50:02 +000052/*--- Error management -- storage ---*/
sewardjf98e1c02008-10-25 16:22:41 +000053/*----------------------------------------------------------------*/
54
55/* maps (by value) strings to a copy of them in ARENA_TOOL */
56
57static WordFM* string_table = NULL;
58
59ULong HG_(stats__string_table_queries) = 0;
60
61ULong HG_(stats__string_table_get_map_size) ( void ) {
62 return string_table ? (ULong)VG_(sizeFM)(string_table) : 0;
63}
64
65static Word string_table_cmp ( UWord s1, UWord s2 ) {
66 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
67}
68
69static HChar* string_table_strdup ( HChar* str ) {
70 HChar* copy = NULL;
71 HG_(stats__string_table_queries)++;
72 if (!str)
73 str = "(null)";
74 if (!string_table) {
75 string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1",
76 HG_(free), string_table_cmp );
77 tl_assert(string_table);
78 }
79 if (VG_(lookupFM)( string_table,
80 NULL, (Word*)&copy, (Word)str )) {
81 tl_assert(copy);
82 if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
83 return copy;
84 } else {
85 copy = HG_(strdup)("hg.sts.2", str);
86 tl_assert(copy);
87 VG_(addToFM)( string_table, (Word)copy, (Word)copy );
88 return copy;
89 }
90}
91
92/* maps from Lock .unique fields to LockP*s */
93
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 );
166 tl_assert(map_LockN_to_P);
167 }
168 if (!VG_(lookupFM)( map_LockN_to_P, NULL, (Word*)&lkp, (Word)lkn)) {
169 lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
170 *lkp = *lkn;
sewardj1d7c3322011-02-28 09:22:51 +0000171 lkp->admin_next = NULL;
172 lkp->admin_prev = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000173 lkp->magic = LockP_MAGIC;
174 /* Forget about the bag of lock holders - don't copy that.
175 Also, acquired_at should be NULL whenever heldBy is, and vice
176 versa. Also forget about the associated libhb synch object. */
177 lkp->heldW = False;
178 lkp->heldBy = NULL;
179 lkp->acquired_at = NULL;
180 lkp->hbso = NULL;
181 VG_(addToFM)( map_LockN_to_P, (Word)lkp, (Word)lkp );
182 }
183 tl_assert( HG_(is_sane_LockP)(lkp) );
184 return lkp;
185}
186
sewardjffce8152011-06-24 10:09:41 +0000187/* Expand a WordSet of LockN*'s into a NULL-terminated vector of
188 LockP*'s. Any LockN's that can't be converted into a LockP
189 (because they have been freed, see comment on mk_LockP_from_LockN)
190 are converted instead into the value Lock_INVALID. Hence the
191 returned vector is a sequence: zero or more (valid LockP* or
192 LockN_INVALID), terminated by a NULL. */
193static
194Lock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets,
195 WordSetID lockset,
196 Bool allowed_to_be_invalid )
197{
198 tl_assert(univ_lsets);
199 tl_assert( HG_(plausibleWS)(univ_lsets, lockset) );
200 UWord nLocks = HG_(cardinalityWS)(univ_lsets, lockset);
201 Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa",
202 (nLocks+1) * sizeof(Lock*) );
203 tl_assert(lockPs);
204 tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */
205 UWord* lockNs = NULL;
206 UWord nLockNs = 0;
207 if (nLocks > 0) {
208 /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the
209 lockset is empty; hence the guarding "if". Sigh. */
210 HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset );
211 tl_assert(lockNs);
212 }
213 UWord i;
214 /* Convert to LockPs. */
215 for (i = 0; i < nLockNs; i++) {
216 lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i],
217 allowed_to_be_invalid );
218 }
219 return lockPs;
220}
221
222/* Get the number of useful elements in a vector created by
223 enumerate_WordSet_into_LockP_vector. Returns both the total number
224 of elements (not including the terminating NULL) and the number of
225 non-Lock_INVALID elements. */
226static void count_LockP_vector ( /*OUT*/UWord* nLocks,
227 /*OUT*/UWord* nLocksValid,
228 Lock** vec )
229{
230 tl_assert(vec);
231 *nLocks = *nLocksValid = 0;
232 UWord n = 0;
233 while (vec[n]) {
234 (*nLocks)++;
235 if (vec[n] != Lock_INVALID)
236 (*nLocksValid)++;
237 n++;
238 }
239}
240
241/* Find out whether 'lk' is in 'vec'. */
242static Bool elem_LockP_vector ( Lock** vec, Lock* lk )
243{
244 tl_assert(vec);
245 tl_assert(lk);
246 UWord n = 0;
247 while (vec[n]) {
248 if (vec[n] == lk)
249 return True;
250 n++;
251 }
252 return False;
253}
254
255
sewardjf98e1c02008-10-25 16:22:41 +0000256/* Errors:
257
258 race: program counter
259 read or write
260 data size
261 previous state
262 current state
263
264 FIXME: how does state printing interact with lockset gc?
265 Are the locksets in prev/curr state always valid?
266 Ditto question for the threadsets
267 ThreadSets - probably are always valid if Threads
268 are never thrown away.
269 LockSets - could at least print the lockset elements that
270 correspond to actual locks at the time of printing. Hmm.
271*/
272
273/* Error kinds */
274typedef
275 enum {
276 XE_Race=1101, // race
sewardjf98e1c02008-10-25 16:22:41 +0000277 XE_UnlockUnlocked, // unlocking a not-locked lock
278 XE_UnlockForeign, // unlocking a lock held by some other thread
279 XE_UnlockBogus, // unlocking an address not known to be a lock
280 XE_PthAPIerror, // error from the POSIX pthreads API
281 XE_LockOrder, // lock order error
282 XE_Misc // misc other error (w/ string to describe it)
283 }
284 XErrorTag;
285
286/* Extra contexts for kinds */
287typedef
288 struct {
289 XErrorTag tag;
290 union {
291 struct {
sewardj23f12002009-07-24 08:45:08 +0000292 Addr data_addr;
293 Int szB;
294 Bool isWrite;
295 Thread* thr;
sewardjffce8152011-06-24 10:09:41 +0000296 Lock** locksHeldW;
sewardj095d61e2010-03-11 13:43:18 +0000297 /* descr1/2 provide a description of stack/global locs */
sewardj23f12002009-07-24 08:45:08 +0000298 XArray* descr1; /* XArray* of HChar */
299 XArray* descr2; /* XArray* of HChar */
sewardj095d61e2010-03-11 13:43:18 +0000300 /* halloc/haddr/hszB describe the addr if it is a heap block. */
301 ExeContext* hctxt;
302 Addr haddr;
303 SizeT hszB;
304 /* h1_* and h2_* provide some description of a previously
305 observed access with which we are conflicting. */
sewardj23f12002009-07-24 08:45:08 +0000306 Thread* h1_ct; /* non-NULL means h1 info present */
307 ExeContext* h1_ct_mbsegstartEC;
308 ExeContext* h1_ct_mbsegendEC;
309 Thread* h2_ct; /* non-NULL means h2 info present */
310 ExeContext* h2_ct_accEC;
311 Int h2_ct_accSzB;
312 Bool h2_ct_accIsW;
sewardjffce8152011-06-24 10:09:41 +0000313 Lock** h2_ct_locksHeldW;
sewardjf98e1c02008-10-25 16:22:41 +0000314 } Race;
315 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000316 Thread* thr; /* doing the unlocking */
317 Lock* lock; /* lock (that is already unlocked) */
318 } UnlockUnlocked;
319 struct {
320 Thread* thr; /* doing the unlocking */
321 Thread* owner; /* thread that actually holds the lock */
322 Lock* lock; /* lock (that is held by 'owner') */
323 } UnlockForeign;
324 struct {
325 Thread* thr; /* doing the unlocking */
326 Addr lock_ga; /* purported address of the lock */
327 } UnlockBogus;
328 struct {
329 Thread* thr;
330 HChar* fnname; /* persistent, in tool-arena */
331 Word err; /* pth error code */
332 HChar* errstr; /* persistent, in tool-arena */
333 } PthAPIerror;
334 struct {
335 Thread* thr;
sewardjffce8152011-06-24 10:09:41 +0000336 /* The first 4 fields describe the previously observed
337 (should-be) ordering. */
338 Addr shouldbe_earlier_ga;
339 Addr shouldbe_later_ga;
340 ExeContext* shouldbe_earlier_ec;
341 ExeContext* shouldbe_later_ec;
342 /* In principle we need to record two more stacks, from
343 this thread, when acquiring the locks in the "wrong"
344 order. In fact the wallclock-later acquisition by this
345 thread is recorded in the main stack for this error.
346 So we only need a stack for the earlier acquisition by
347 this thread. */
348 ExeContext* actual_earlier_ec;
sewardjf98e1c02008-10-25 16:22:41 +0000349 } LockOrder;
350 struct {
sewardj8fef6252010-07-29 05:28:02 +0000351 Thread* thr;
352 HChar* errstr; /* persistent, in tool-arena */
353 HChar* auxstr; /* optional, persistent, in tool-arena */
354 ExeContext* auxctx; /* optional */
sewardjf98e1c02008-10-25 16:22:41 +0000355 } Misc;
356 } XE;
357 }
358 XError;
359
360static void init_XError ( XError* xe ) {
361 VG_(memset)(xe, 0, sizeof(*xe) );
362 xe->tag = XE_Race-1; /* bogus */
363}
364
365
366/* Extensions of suppressions */
367typedef
368 enum {
369 XS_Race=1201, /* race */
370 XS_FreeMemLock,
371 XS_UnlockUnlocked,
372 XS_UnlockForeign,
373 XS_UnlockBogus,
374 XS_PthAPIerror,
375 XS_LockOrder,
376 XS_Misc
377 }
378 XSuppTag;
379
380
381/* Updates the copy with address info if necessary. */
382UInt HG_(update_extra) ( Error* err )
383{
384 XError* xe = (XError*)VG_(get_error_extra)(err);
385 tl_assert(xe);
386 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
387 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
388 //}
389
390 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000391
sewardjffce8152011-06-24 10:09:41 +0000392 /* Note the set of locks that the thread is (w-)holding.
393 Convert the WordSetID of LockN*'s into a NULL-terminated
394 vector of LockP*'s. We don't expect to encounter any invalid
395 LockNs in this conversion. */
396 tl_assert(xe->XE.Race.thr);
397 xe->XE.Race.locksHeldW
398 = enumerate_WordSet_into_LockP_vector(
399 HG_(get_univ_lsets)(),
400 xe->XE.Race.thr->locksetW,
401 False/*!allowed_to_be_invalid*/
402 );
403
sewardjf98e1c02008-10-25 16:22:41 +0000404 /* See if we can come up with a source level description of the
405 raced-upon address. This is potentially expensive, which is
406 why it's only done at the update_extra point, not when the
407 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000408 static Int xxx = 0;
409 xxx++;
410 if (0)
411 VG_(printf)("HG_(update_extra): "
412 "%d conflicting-event queries\n", xxx);
sewardj095d61e2010-03-11 13:43:18 +0000413
414 tl_assert(!xe->XE.Race.hctxt);
sewardj24118492009-07-15 14:50:02 +0000415 tl_assert(!xe->XE.Race.descr1);
416 tl_assert(!xe->XE.Race.descr2);
417
sewardj095d61e2010-03-11 13:43:18 +0000418 /* First, see if it's in any heap block. Unfortunately this
sewardjc8028ad2010-05-05 09:34:42 +0000419 means a linear search through all allocated heap blocks. The
420 assertion says that if it's detected as a heap block, then we
421 must have an allocation context for it, since all heap blocks
422 should have an allocation context. */
423 Bool is_heapblock
424 = HG_(mm_find_containing_block)(
425 &xe->XE.Race.hctxt, &xe->XE.Race.haddr, &xe->XE.Race.hszB,
426 xe->XE.Race.data_addr
427 );
428 tl_assert(is_heapblock == (xe->XE.Race.hctxt != NULL));
sewardj24118492009-07-15 14:50:02 +0000429
sewardj095d61e2010-03-11 13:43:18 +0000430 if (!xe->XE.Race.hctxt) {
431 /* It's not in any heap block. See if we can map it to a
432 stack or global symbol. */
sewardj24118492009-07-15 14:50:02 +0000433
sewardj095d61e2010-03-11 13:43:18 +0000434 xe->XE.Race.descr1
435 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr1",
436 HG_(free), sizeof(HChar) );
437 xe->XE.Race.descr2
438 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr2",
439 HG_(free), sizeof(HChar) );
440
441 (void) VG_(get_data_description)( xe->XE.Race.descr1,
442 xe->XE.Race.descr2,
443 xe->XE.Race.data_addr );
444
445 /* If there's nothing in descr1/2, free it. Why is it safe to
446 to VG_(indexXA) at zero here? Because
447 VG_(get_data_description) guarantees to zero terminate
448 descr1/2 regardless of the outcome of the call. So there's
449 always at least one element in each XA after the call.
450 */
451 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr1, 0 ))) {
452 VG_(deleteXA)( xe->XE.Race.descr1 );
453 xe->XE.Race.descr1 = NULL;
454 }
455 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr2, 0 ))) {
456 VG_(deleteXA)( xe->XE.Race.descr2 );
457 xe->XE.Race.descr2 = NULL;
458 }
sewardj24118492009-07-15 14:50:02 +0000459 }
460
461 /* And poke around in the conflicting-event map, to see if we
462 can rustle up a plausible-looking conflicting memory access
463 to show. */
sewardj23f12002009-07-24 08:45:08 +0000464 if (HG_(clo_history_level) >= 2) {
sewardjffce8152011-06-24 10:09:41 +0000465 Thr* thrp = NULL;
466 ExeContext* wherep = NULL;
467 Addr acc_addr = xe->XE.Race.data_addr;
468 Int acc_szB = xe->XE.Race.szB;
469 Thr* acc_thr = xe->XE.Race.thr->hbthr;
470 Bool acc_isW = xe->XE.Race.isWrite;
471 SizeT conf_szB = 0;
472 Bool conf_isW = False;
473 WordSetID conf_locksHeldW = 0;
sewardj23f12002009-07-24 08:45:08 +0000474 tl_assert(!xe->XE.Race.h2_ct_accEC);
475 tl_assert(!xe->XE.Race.h2_ct);
476 if (libhb_event_map_lookup(
sewardjffce8152011-06-24 10:09:41 +0000477 &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW,
sewardj23f12002009-07-24 08:45:08 +0000478 acc_thr, acc_addr, acc_szB, acc_isW )) {
479 Thread* threadp;
480 tl_assert(wherep);
481 tl_assert(thrp);
sewardj60626642011-03-10 15:14:37 +0000482 threadp = libhb_get_Thr_hgthread( thrp );
sewardj23f12002009-07-24 08:45:08 +0000483 tl_assert(threadp);
484 xe->XE.Race.h2_ct_accEC = wherep;
485 xe->XE.Race.h2_ct = threadp;
486 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
487 xe->XE.Race.h2_ct_accIsW = conf_isW;
sewardjffce8152011-06-24 10:09:41 +0000488 xe->XE.Race.h2_ct_locksHeldW
489 = enumerate_WordSet_into_LockP_vector(
490 HG_(get_univ_lsets)(),
491 conf_locksHeldW,
492 True/*allowed_to_be_invalid*/
493 );
sewardjc5ea9962008-12-07 01:41:46 +0000494 }
495 }
sewardj23f12002009-07-24 08:45:08 +0000496
497 // both NULL or both non-NULL
498 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
sewardjf98e1c02008-10-25 16:22:41 +0000499 }
500
501 return sizeof(XError);
502}
503
504void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000505 Addr data_addr, Int szB, Bool isWrite,
sewardj23f12002009-07-24 08:45:08 +0000506 Thread* h1_ct,
507 ExeContext* h1_ct_segstart,
508 ExeContext* h1_ct_mbsegendEC )
sewardjf98e1c02008-10-25 16:22:41 +0000509{
510 XError xe;
511 tl_assert( HG_(is_sane_Thread)(thr) );
512
513# if defined(VGO_linux)
514 /* Skip any races on locations apparently in GOTPLT sections. This
515 is said to be caused by ld.so poking PLT table entries (or
516 whatever) when it writes the resolved address of a dynamically
517 linked routine, into the table (or whatever) when it is called
518 for the first time. */
519 {
sewardje3f1e592009-07-31 09:41:29 +0000520 VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr );
sewardjf98e1c02008-10-25 16:22:41 +0000521 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
522 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000523 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000524 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000525 /* SectPLT is required on ppc32/64-linux */
526 if (sect == Vg_SectPLT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000527 }
528# endif
529
530 init_XError(&xe);
531 xe.tag = XE_Race;
532 xe.XE.Race.data_addr = data_addr;
533 xe.XE.Race.szB = szB;
534 xe.XE.Race.isWrite = isWrite;
sewardjf98e1c02008-10-25 16:22:41 +0000535 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000536 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000537 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000538 /* Skip on the detailed description of the raced-on address at this
539 point; it's expensive. Leave it for the update_extra function
540 if we ever make it that far. */
541 tl_assert(xe.XE.Race.descr1 == NULL);
542 tl_assert(xe.XE.Race.descr2 == NULL);
sewardjf98e1c02008-10-25 16:22:41 +0000543 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000544 // Skip on any of the conflicting-access info at this point.
545 // It's expensive to obtain, and this error is more likely than
546 // not to be discarded. We'll fill these fields in in
547 // HG_(update_extra) just above, assuming the error ever makes
548 // it that far (unlikely).
sewardj23f12002009-07-24 08:45:08 +0000549 xe.XE.Race.h2_ct_accSzB = 0;
550 xe.XE.Race.h2_ct_accIsW = False;
551 xe.XE.Race.h2_ct_accEC = NULL;
552 xe.XE.Race.h2_ct = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000553 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
554 tl_assert( thr->coretid != VG_INVALID_THREADID );
sewardj23f12002009-07-24 08:45:08 +0000555
556 xe.XE.Race.h1_ct = h1_ct;
557 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
558 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC;
559
sewardjf98e1c02008-10-25 16:22:41 +0000560 VG_(maybe_record_error)( thr->coretid,
561 XE_Race, data_addr, NULL, &xe );
562}
563
sewardjf98e1c02008-10-25 16:22:41 +0000564void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
565{
566 XError xe;
567 tl_assert( HG_(is_sane_Thread)(thr) );
568 tl_assert( HG_(is_sane_LockN)(lk) );
569 init_XError(&xe);
570 xe.tag = XE_UnlockUnlocked;
sewardjffce8152011-06-24 10:09:41 +0000571 xe.XE.UnlockUnlocked.thr
572 = thr;
573 xe.XE.UnlockUnlocked.lock
574 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
sewardjf98e1c02008-10-25 16:22:41 +0000575 // FIXME: tid vs thr
576 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
577 tl_assert( thr->coretid != VG_INVALID_THREADID );
578 VG_(maybe_record_error)( thr->coretid,
579 XE_UnlockUnlocked, 0, NULL, &xe );
580}
581
582void HG_(record_error_UnlockForeign) ( Thread* thr,
583 Thread* owner, Lock* lk )
584{
585 XError xe;
586 tl_assert( HG_(is_sane_Thread)(thr) );
587 tl_assert( HG_(is_sane_Thread)(owner) );
588 tl_assert( HG_(is_sane_LockN)(lk) );
589 init_XError(&xe);
590 xe.tag = XE_UnlockForeign;
591 xe.XE.UnlockForeign.thr = thr;
592 xe.XE.UnlockForeign.owner = owner;
sewardjffce8152011-06-24 10:09:41 +0000593 xe.XE.UnlockForeign.lock
594 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
sewardjf98e1c02008-10-25 16:22:41 +0000595 // FIXME: tid vs thr
596 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
597 tl_assert( thr->coretid != VG_INVALID_THREADID );
598 VG_(maybe_record_error)( thr->coretid,
599 XE_UnlockForeign, 0, NULL, &xe );
600}
601
602void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
603{
604 XError xe;
605 tl_assert( HG_(is_sane_Thread)(thr) );
606 init_XError(&xe);
607 xe.tag = XE_UnlockBogus;
608 xe.XE.UnlockBogus.thr = thr;
609 xe.XE.UnlockBogus.lock_ga = lock_ga;
610 // FIXME: tid vs thr
611 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
612 tl_assert( thr->coretid != VG_INVALID_THREADID );
613 VG_(maybe_record_error)( thr->coretid,
614 XE_UnlockBogus, 0, NULL, &xe );
615}
616
617void HG_(record_error_LockOrder)(
sewardjffce8152011-06-24 10:09:41 +0000618 Thread* thr,
619 Addr shouldbe_earlier_ga,
620 Addr shouldbe_later_ga,
621 ExeContext* shouldbe_earlier_ec,
622 ExeContext* shouldbe_later_ec,
623 ExeContext* actual_earlier_ec
sewardjf98e1c02008-10-25 16:22:41 +0000624 )
625{
626 XError xe;
627 tl_assert( HG_(is_sane_Thread)(thr) );
sewardjc1fb9d22011-02-28 09:03:44 +0000628 tl_assert(HG_(clo_track_lockorders));
sewardjf98e1c02008-10-25 16:22:41 +0000629 init_XError(&xe);
630 xe.tag = XE_LockOrder;
631 xe.XE.LockOrder.thr = thr;
sewardjffce8152011-06-24 10:09:41 +0000632 xe.XE.LockOrder.shouldbe_earlier_ga = shouldbe_earlier_ga;
633 xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec;
634 xe.XE.LockOrder.shouldbe_later_ga = shouldbe_later_ga;
635 xe.XE.LockOrder.shouldbe_later_ec = shouldbe_later_ec;
636 xe.XE.LockOrder.actual_earlier_ec = actual_earlier_ec;
sewardjf98e1c02008-10-25 16:22:41 +0000637 // FIXME: tid vs thr
638 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
639 tl_assert( thr->coretid != VG_INVALID_THREADID );
640 VG_(maybe_record_error)( thr->coretid,
641 XE_LockOrder, 0, NULL, &xe );
642}
643
644void HG_(record_error_PthAPIerror) ( Thread* thr, HChar* fnname,
645 Word err, HChar* errstr )
646{
647 XError xe;
648 tl_assert( HG_(is_sane_Thread)(thr) );
649 tl_assert(fnname);
650 tl_assert(errstr);
651 init_XError(&xe);
652 xe.tag = XE_PthAPIerror;
653 xe.XE.PthAPIerror.thr = thr;
654 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
655 xe.XE.PthAPIerror.err = err;
656 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
657 // FIXME: tid vs thr
658 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
659 tl_assert( thr->coretid != VG_INVALID_THREADID );
660 VG_(maybe_record_error)( thr->coretid,
661 XE_PthAPIerror, 0, NULL, &xe );
662}
663
sewardj8fef6252010-07-29 05:28:02 +0000664void HG_(record_error_Misc_w_aux) ( Thread* thr, HChar* errstr,
665 HChar* auxstr, ExeContext* auxctx )
sewardjf98e1c02008-10-25 16:22:41 +0000666{
667 XError xe;
668 tl_assert( HG_(is_sane_Thread)(thr) );
669 tl_assert(errstr);
670 init_XError(&xe);
671 xe.tag = XE_Misc;
672 xe.XE.Misc.thr = thr;
673 xe.XE.Misc.errstr = string_table_strdup(errstr);
sewardj8fef6252010-07-29 05:28:02 +0000674 xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
675 xe.XE.Misc.auxctx = auxctx;
sewardjf98e1c02008-10-25 16:22:41 +0000676 // FIXME: tid vs thr
677 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
678 tl_assert( thr->coretid != VG_INVALID_THREADID );
679 VG_(maybe_record_error)( thr->coretid,
680 XE_Misc, 0, NULL, &xe );
681}
682
sewardj8fef6252010-07-29 05:28:02 +0000683void HG_(record_error_Misc) ( Thread* thr, HChar* errstr )
684{
685 HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
686}
687
sewardjf98e1c02008-10-25 16:22:41 +0000688Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 )
689{
690 XError *xe1, *xe2;
691
692 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
693
694 xe1 = (XError*)VG_(get_error_extra)(e1);
695 xe2 = (XError*)VG_(get_error_extra)(e2);
696 tl_assert(xe1);
697 tl_assert(xe2);
698
699 switch (VG_(get_error_kind)(e1)) {
700 case XE_Race:
701 return xe1->XE.Race.szB == xe2->XE.Race.szB
702 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
703 && (HG_(clo_cmp_race_err_addrs)
704 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
705 : True);
sewardjf98e1c02008-10-25 16:22:41 +0000706 case XE_UnlockUnlocked:
707 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
708 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
709 case XE_UnlockForeign:
710 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
711 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
712 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
713 case XE_UnlockBogus:
714 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
715 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
716 case XE_PthAPIerror:
717 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
718 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
719 xe2->XE.PthAPIerror.fnname)
720 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
721 case XE_LockOrder:
722 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
723 case XE_Misc:
724 return xe1->XE.Misc.thr == xe2->XE.Misc.thr
725 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
726 default:
727 tl_assert(0);
728 }
729
730 /*NOTREACHED*/
731 tl_assert(0);
732}
733
734
sewardj24118492009-07-15 14:50:02 +0000735/*----------------------------------------------------------------*/
736/*--- Error management -- printing ---*/
737/*----------------------------------------------------------------*/
738
739/* Do a printf-style operation on either the XML or normal output
740 channel, depending on the setting of VG_(clo_xml).
741*/
742static void emit_WRK ( HChar* format, va_list vargs )
743{
744 if (VG_(clo_xml)) {
745 VG_(vprintf_xml)(format, vargs);
746 } else {
747 VG_(vmessage)(Vg_UserMsg, format, vargs);
748 }
749}
750static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
751static void emit ( HChar* format, ... )
752{
753 va_list vargs;
754 va_start(vargs, format);
755 emit_WRK(format, vargs);
756 va_end(vargs);
757}
758static void emit_no_f_c ( HChar* format, ... )
759{
760 va_list vargs;
761 va_start(vargs, format);
762 emit_WRK(format, vargs);
763 va_end(vargs);
764}
765
766
sewardjf98e1c02008-10-25 16:22:41 +0000767/* Announce (that is, print the point-of-creation) of 'thr'. Only do
768 this once, as we only want to see these announcements once per
sewardj24118492009-07-15 14:50:02 +0000769 thread. Returned Bool indicates whether or not an announcement was
770 made.
771*/
772static Bool announce_one_thread ( Thread* thr )
sewardjf98e1c02008-10-25 16:22:41 +0000773{
774 tl_assert(HG_(is_sane_Thread)(thr));
775 tl_assert(thr->errmsg_index >= 1);
sewardj24118492009-07-15 14:50:02 +0000776 if (thr->announced)
777 return False;
778
779 if (VG_(clo_xml)) {
780
781 VG_(printf_xml)("<announcethread>\n");
sewardj11b5c6d2009-09-03 10:29:57 +0000782 VG_(printf_xml)(" <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
sewardjf98e1c02008-10-25 16:22:41 +0000783 if (thr->errmsg_index == 1) {
784 tl_assert(thr->created_at == NULL);
sewardj24118492009-07-15 14:50:02 +0000785 VG_(printf_xml)(" <isrootthread></isrootthread>\n");
sewardjf98e1c02008-10-25 16:22:41 +0000786 } else {
787 tl_assert(thr->created_at != NULL);
sewardj24118492009-07-15 14:50:02 +0000788 VG_(pp_ExeContext)( thr->created_at );
789 }
790 VG_(printf_xml)("</announcethread>\n\n");
791
792 } else {
793
sewardjffce8152011-06-24 10:09:41 +0000794 VG_(umsg)("---Thread-Announcement----------"
795 "--------------------------------" "\n");
796 VG_(umsg)("\n");
797
sewardj24118492009-07-15 14:50:02 +0000798 if (thr->errmsg_index == 1) {
799 tl_assert(thr->created_at == NULL);
800 VG_(message)(Vg_UserMsg,
801 "Thread #%d is the program's root thread\n",
802 thr->errmsg_index);
803 } else {
804 tl_assert(thr->created_at != NULL);
805 VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
sewardjf98e1c02008-10-25 16:22:41 +0000806 thr->errmsg_index);
807 VG_(pp_ExeContext)( thr->created_at );
808 }
sewardj24118492009-07-15 14:50:02 +0000809 VG_(message)(Vg_UserMsg, "\n");
810
811 }
812
813 thr->announced = True;
814 return True;
815}
816
817
sewardjffce8152011-06-24 10:09:41 +0000818/* Announce 'lk'. */
819static void announce_LockP ( Lock* lk )
820{
821 tl_assert(lk);
822 if (lk == Lock_INVALID)
823 return; /* Can't be announced -- we know nothing about it. */
824 tl_assert(lk->magic == LockP_MAGIC);
825 if (!lk->appeared_at)
826 return; /* There's nothing we can show */
827
828 if (VG_(clo_xml)) {
829 /* fixme: add announcement */
830 } else {
831 VG_(umsg)( "Lock at %p was first observed\n",
832 (void*)lk->guestaddr );
833 VG_(pp_ExeContext)( lk->appeared_at );
834 VG_(umsg)("\n");
835 }
836}
837
838/* Announce (that is, print point-of-first-observation) for the
839 locks in 'lockvec' and, if non-NULL, 'lockvec2'. */
840static void announce_combined_LockP_vecs ( Lock** lockvec,
841 Lock** lockvec2 )
842{
843 UWord i;
844 tl_assert(lockvec);
845 for (i = 0; lockvec[i]; i++) {
846 announce_LockP(lockvec[i]);
847 }
848 if (lockvec2) {
849 for (i = 0; lockvec2[i]; i++) {
850 Lock* lk = lockvec2[i];
851 if (!elem_LockP_vector(lockvec, lk))
852 announce_LockP(lk);
853 }
854 }
855}
856
857
858static void show_LockP_summary_textmode ( Lock** locks, HChar* pre )
859{
860 tl_assert(locks);
861 UWord i;
862 UWord nLocks = 0, nLocksValid = 0;
863 count_LockP_vector(&nLocks, &nLocksValid, locks);
864 tl_assert(nLocksValid <= nLocks);
865
866 if (nLocks == 0) {
867 VG_(umsg)( "%sLocks held: none", pre );
868 } else {
869 VG_(umsg)( "%sLocks held: %lu, at address%s ",
870 pre, nLocks, nLocksValid == 1 ? "" : "es" );
871 }
872
873 if (nLocks > 0) {
874 for (i = 0; i < nLocks; i++) {
875 if (locks[i] == Lock_INVALID)
876 continue;
877 VG_(umsg)( "%p", (void*)locks[i]->guestaddr);
878 if (locks[i+1] != NULL)
879 VG_(umsg)(" ");
880 }
881 if (nLocksValid < nLocks)
882 VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid);
883 }
884 VG_(umsg)("\n");
885}
886
887
sewardj24118492009-07-15 14:50:02 +0000888/* This is the "this error is due to be printed shortly; so have a
889 look at it any print any preamble you want" function. We use it to
890 announce any previously un-announced threads in the upcoming error
891 message.
892*/
893void HG_(before_pp_Error) ( Error* err )
894{
895 XError* xe;
896 tl_assert(err);
897 xe = (XError*)VG_(get_error_extra)(err);
898 tl_assert(xe);
899
900 switch (VG_(get_error_kind)(err)) {
901 case XE_Misc:
902 announce_one_thread( xe->XE.Misc.thr );
903 break;
904 case XE_LockOrder:
905 announce_one_thread( xe->XE.LockOrder.thr );
906 break;
907 case XE_PthAPIerror:
908 announce_one_thread( xe->XE.PthAPIerror.thr );
909 break;
910 case XE_UnlockBogus:
911 announce_one_thread( xe->XE.UnlockBogus.thr );
912 break;
913 case XE_UnlockForeign:
914 announce_one_thread( xe->XE.UnlockForeign.thr );
915 announce_one_thread( xe->XE.UnlockForeign.owner );
916 break;
917 case XE_UnlockUnlocked:
918 announce_one_thread( xe->XE.UnlockUnlocked.thr );
919 break;
920 case XE_Race:
921 announce_one_thread( xe->XE.Race.thr );
sewardj23f12002009-07-24 08:45:08 +0000922 if (xe->XE.Race.h2_ct)
923 announce_one_thread( xe->XE.Race.h2_ct );
924 if (xe->XE.Race.h1_ct)
925 announce_one_thread( xe->XE.Race.h1_ct );
sewardj24118492009-07-15 14:50:02 +0000926 break;
927 default:
928 tl_assert(0);
sewardjf98e1c02008-10-25 16:22:41 +0000929 }
930}
931
sewardjf98e1c02008-10-25 16:22:41 +0000932void HG_(pp_Error) ( Error* err )
933{
sewardj24118492009-07-15 14:50:02 +0000934 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
935
sewardjffce8152011-06-24 10:09:41 +0000936 if (!xml) {
937 VG_(umsg)("--------------------------------"
938 "--------------------------------" "\n");
939 VG_(umsg)("\n");
940 }
941
sewardjf98e1c02008-10-25 16:22:41 +0000942 XError *xe = (XError*)VG_(get_error_extra)(err);
sewardj24118492009-07-15 14:50:02 +0000943 tl_assert(xe);
sewardjf98e1c02008-10-25 16:22:41 +0000944
945 switch (VG_(get_error_kind)(err)) {
946
947 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000948 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000949
950 if (xml) {
951
952 emit( " <kind>Misc</kind>\n");
953 emit( " <xwhat>\n" );
954 emit( " <text>Thread #%d: %s</text>\n",
955 (Int)xe->XE.Misc.thr->errmsg_index,
956 xe->XE.Misc.errstr );
957 emit( " <hthreadid>%d</hthreadid>\n",
958 (Int)xe->XE.Misc.thr->errmsg_index );
959 emit( " </xwhat>\n" );
960 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000961 if (xe->XE.Misc.auxstr) {
962 emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
963 if (xe->XE.Misc.auxctx)
964 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
965 }
sewardj24118492009-07-15 14:50:02 +0000966
967 } else {
968
969 emit( "Thread #%d: %s\n",
970 (Int)xe->XE.Misc.thr->errmsg_index,
971 xe->XE.Misc.errstr );
972 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000973 if (xe->XE.Misc.auxstr) {
974 emit(" %s\n", xe->XE.Misc.auxstr);
975 if (xe->XE.Misc.auxctx)
976 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
977 }
sewardj24118492009-07-15 14:50:02 +0000978
979 }
sewardjf98e1c02008-10-25 16:22:41 +0000980 break;
981 }
982
983 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000984 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000985
986 if (xml) {
987
988 emit( " <kind>LockOrder</kind>\n");
989 emit( " <xwhat>\n" );
990 emit( " <text>Thread #%d: lock order \"%p before %p\" "
991 "violated</text>\n",
992 (Int)xe->XE.LockOrder.thr->errmsg_index,
sewardjffce8152011-06-24 10:09:41 +0000993 (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
994 (void*)xe->XE.LockOrder.shouldbe_later_ga );
sewardj24118492009-07-15 14:50:02 +0000995 emit( " <hthreadid>%d</hthreadid>\n",
996 (Int)xe->XE.LockOrder.thr->errmsg_index );
997 emit( " </xwhat>\n" );
998 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +0000999 if (xe->XE.LockOrder.shouldbe_earlier_ec
1000 && xe->XE.LockOrder.shouldbe_later_ec) {
sewardj24118492009-07-15 14:50:02 +00001001 emit( " <auxwhat>Required order was established by "
1002 "acquisition of lock at %p</auxwhat>\n",
sewardjffce8152011-06-24 10:09:41 +00001003 (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
1004 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
sewardj24118492009-07-15 14:50:02 +00001005 emit( " <auxwhat>followed by a later acquisition "
1006 "of lock at %p</auxwhat>\n",
sewardjffce8152011-06-24 10:09:41 +00001007 (void*)xe->XE.LockOrder.shouldbe_later_ga );
1008 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +00001009 }
1010
1011 } else {
1012
1013 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
1014 (Int)xe->XE.LockOrder.thr->errmsg_index,
sewardjffce8152011-06-24 10:09:41 +00001015 (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
1016 (void*)xe->XE.LockOrder.shouldbe_later_ga );
1017 emit( "\n" );
1018 emit( "Observed (incorrect) order is: "
1019 "acquisition of lock at %p\n",
1020 (void*)xe->XE.LockOrder.shouldbe_later_ga);
1021 if (xe->XE.LockOrder.actual_earlier_ec) {
1022 VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
1023 } else {
1024 emit(" (stack unavailable)\n");
1025 }
1026 emit( "\n" );
1027 emit(" followed by a later acquisition of lock at %p\n",
1028 (void*)xe->XE.LockOrder.shouldbe_earlier_ga);
sewardj24118492009-07-15 14:50:02 +00001029 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +00001030 if (xe->XE.LockOrder.shouldbe_earlier_ec
1031 && xe->XE.LockOrder.shouldbe_later_ec) {
1032 emit("\n");
1033 emit( "Required order was established by "
sewardj24118492009-07-15 14:50:02 +00001034 "acquisition of lock at %p\n",
sewardjffce8152011-06-24 10:09:41 +00001035 (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
1036 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
1037 emit( "\n" );
1038 emit( " followed by a later acquisition of lock at %p\n",
1039 (void*)xe->XE.LockOrder.shouldbe_later_ga );
1040 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +00001041 }
1042
sewardjf98e1c02008-10-25 16:22:41 +00001043 }
sewardj24118492009-07-15 14:50:02 +00001044
sewardjf98e1c02008-10-25 16:22:41 +00001045 break;
1046 }
1047
1048 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +00001049 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +00001050
1051 if (xml) {
1052
1053 emit( " <kind>PthAPIerror</kind>\n");
1054 emit( " <xwhat>\n" );
1055 emit_no_f_c(
1056 " <text>Thread #%d's call to %t failed</text>\n",
1057 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1058 xe->XE.PthAPIerror.fnname );
1059 emit( " <hthreadid>%d</hthreadid>\n",
1060 (Int)xe->XE.PthAPIerror.thr->errmsg_index );
1061 emit( " </xwhat>\n" );
1062 emit( " <what>with error code %ld (%s)</what>\n",
1063 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1064 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1065
1066 } else {
1067
1068 emit_no_f_c( "Thread #%d's call to %t failed\n",
1069 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1070 xe->XE.PthAPIerror.fnname );
1071 emit( " with error code %ld (%s)\n",
1072 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1073 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1074
1075 }
1076
sewardjf98e1c02008-10-25 16:22:41 +00001077 break;
1078 }
1079
1080 case XE_UnlockBogus: {
sewardjf98e1c02008-10-25 16:22:41 +00001081 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
sewardj24118492009-07-15 14:50:02 +00001082
1083 if (xml) {
1084
1085 emit( " <kind>UnlockBogus</kind>\n");
1086 emit( " <xwhat>\n" );
1087 emit( " <text>Thread #%d unlocked an invalid "
1088 "lock at %p</text>\n",
1089 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1090 (void*)xe->XE.UnlockBogus.lock_ga );
1091 emit( " <hthreadid>%d</hthreadid>\n",
1092 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
1093 emit( " </xwhat>\n" );
1094 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1095
1096 } else {
1097
1098 emit( "Thread #%d unlocked an invalid lock at %p\n",
1099 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1100 (void*)xe->XE.UnlockBogus.lock_ga );
1101 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1102
1103 }
1104
sewardjf98e1c02008-10-25 16:22:41 +00001105 break;
1106 }
1107
1108 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +00001109 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
1110 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
1111 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +00001112
1113 if (xml) {
1114
1115 emit( " <kind>UnlockForeign</kind>\n");
1116 emit( " <xwhat>\n" );
1117 emit( " <text>Thread #%d unlocked lock at %p "
1118 "currently held by thread #%d</text>\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 emit( " <hthreadid>%d</hthreadid>\n",
1123 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
1124 emit( " <hthreadid>%d</hthreadid>\n",
1125 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1126 emit( " </xwhat>\n" );
1127 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1128
1129 if (xe->XE.UnlockForeign.lock->appeared_at) {
1130 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
1131 (void*)xe->XE.UnlockForeign.lock->guestaddr );
1132 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
1133 }
1134
1135 } else {
1136
1137 emit( "Thread #%d unlocked lock at %p "
1138 "currently held by thread #%d\n",
1139 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1140 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1141 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1142 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1143 if (xe->XE.UnlockForeign.lock->appeared_at) {
1144 emit( " Lock at %p was first observed\n",
1145 (void*)xe->XE.UnlockForeign.lock->guestaddr );
1146 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
1147 }
1148
sewardjf98e1c02008-10-25 16:22:41 +00001149 }
sewardj24118492009-07-15 14:50:02 +00001150
sewardjf98e1c02008-10-25 16:22:41 +00001151 break;
1152 }
1153
1154 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +00001155 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
1156 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +00001157
sewardj24118492009-07-15 14:50:02 +00001158 if (xml) {
1159
1160 emit( " <kind>UnlockUnlocked</kind>\n");
1161 emit( " <xwhat>\n" );
1162 emit( " <text>Thread #%d unlocked a "
1163 "not-locked lock at %p</text>\n",
1164 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1165 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1166 emit( " <hthreadid>%d</hthreadid>\n",
1167 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
1168 emit( " </xwhat>\n" );
1169 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1170 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
1171 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
1172 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1173 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
1174 }
1175
1176 } else {
1177
1178 emit( "Thread #%d unlocked a not-locked lock at %p\n",
1179 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1180 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1181 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1182 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
1183 emit( " Lock at %p was first observed\n",
1184 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1185 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
1186 }
1187
sewardjf98e1c02008-10-25 16:22:41 +00001188 }
sewardj24118492009-07-15 14:50:02 +00001189
sewardjf98e1c02008-10-25 16:22:41 +00001190 break;
1191 }
1192
1193 case XE_Race: {
1194 Addr err_ga;
1195 HChar* what;
1196 Int szB;
1197 what = xe->XE.Race.isWrite ? "write" : "read";
1198 szB = xe->XE.Race.szB;
1199 err_ga = VG_(get_error_address)(err);
1200
sewardj24118492009-07-15 14:50:02 +00001201 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardj23f12002009-07-24 08:45:08 +00001202 if (xe->XE.Race.h2_ct)
1203 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
sewardj24118492009-07-15 14:50:02 +00001204
1205 if (xml) {
1206
1207 /* ------ XML ------ */
1208 emit( " <kind>Race</kind>\n" );
1209 emit( " <xwhat>\n" );
1210 emit( " <text>Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001211 "at %p by thread #%d</text>\n",
1212 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
sewardj24118492009-07-15 14:50:02 +00001213 emit( " <hthreadid>%d</hthreadid>\n",
1214 (Int)xe->XE.Race.thr->errmsg_index );
1215 emit( " </xwhat>\n" );
1216 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1217
sewardj23f12002009-07-24 08:45:08 +00001218 if (xe->XE.Race.h2_ct) {
1219 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1220 emit( " <xauxwhat>\n");
1221 emit( " <text>This conflicts with a previous %s of size %d "
1222 "by thread #%d</text>\n",
1223 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1224 xe->XE.Race.h2_ct_accSzB,
1225 xe->XE.Race.h2_ct->errmsg_index );
1226 emit( " <hthreadid>%d</hthreadid>\n",
1227 xe->XE.Race.h2_ct->errmsg_index);
1228 emit(" </xauxwhat>\n");
1229 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1230 }
1231
1232 if (xe->XE.Race.h1_ct) {
1233 emit( " <xauxwhat>\n");
1234 emit( " <text>This conflicts with a previous access "
1235 "by thread #%d, after</text>\n",
1236 xe->XE.Race.h1_ct->errmsg_index );
1237 emit( " <hthreadid>%d</hthreadid>\n",
1238 xe->XE.Race.h1_ct->errmsg_index );
1239 emit(" </xauxwhat>\n");
1240 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1241 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001242 } else {
sewardj23f12002009-07-24 08:45:08 +00001243 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" );
sewardj24118492009-07-15 14:50:02 +00001244 }
sewardj23f12002009-07-24 08:45:08 +00001245 emit( " <auxwhat>but before</auxwhat>\n" );
1246 if (xe->XE.Race.h1_ct_mbsegendEC) {
1247 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1248 } else {
1249 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" );
1250 }
sewardjf98e1c02008-10-25 16:22:41 +00001251 }
sewardj24118492009-07-15 14:50:02 +00001252
1253 } else {
1254
1255 /* ------ Text ------ */
sewardjffce8152011-06-24 10:09:41 +00001256 announce_combined_LockP_vecs( xe->XE.Race.locksHeldW,
1257 xe->XE.Race.h2_ct_locksHeldW );
1258
sewardj24118492009-07-15 14:50:02 +00001259 emit( "Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001260 "at %p by thread #%d\n",
1261 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1262
1263 tl_assert(xe->XE.Race.locksHeldW);
1264 show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" );
sewardj24118492009-07-15 14:50:02 +00001265 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj23f12002009-07-24 08:45:08 +00001266
1267 if (xe->XE.Race.h2_ct) {
1268 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
sewardjffce8152011-06-24 10:09:41 +00001269 tl_assert(xe->XE.Race.h2_ct_locksHeldW);
1270 emit( "\n" );
1271 emit( "This conflicts with a previous %s of size %d "
sewardj23f12002009-07-24 08:45:08 +00001272 "by thread #%d\n",
1273 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1274 xe->XE.Race.h2_ct_accSzB,
1275 xe->XE.Race.h2_ct->errmsg_index );
sewardjffce8152011-06-24 10:09:41 +00001276 show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" );
sewardj23f12002009-07-24 08:45:08 +00001277 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1278 }
1279
1280 if (xe->XE.Race.h1_ct) {
1281 emit( " This conflicts with a previous access by thread #%d, "
1282 "after\n",
1283 xe->XE.Race.h1_ct->errmsg_index );
1284 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1285 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001286 } else {
sewardj23f12002009-07-24 08:45:08 +00001287 emit( " (the start of the thread)\n" );
sewardj24118492009-07-15 14:50:02 +00001288 }
sewardj23f12002009-07-24 08:45:08 +00001289 emit( " but before\n" );
1290 if (xe->XE.Race.h1_ct_mbsegendEC) {
1291 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1292 } else {
1293 emit( " (the end of the the thread)\n" );
1294 }
sewardj24118492009-07-15 14:50:02 +00001295 }
1296
sewardjf98e1c02008-10-25 16:22:41 +00001297 }
1298
sewardj095d61e2010-03-11 13:43:18 +00001299 /* If we have a description of the address in terms of a heap
1300 block, show it. */
1301 if (xe->XE.Race.hctxt) {
1302 SizeT delta = err_ga - xe->XE.Race.haddr;
1303 if (xml) {
sewardjffce8152011-06-24 10:09:41 +00001304 emit(" <auxwhat>Address %p is %ld bytes inside a block "
1305 "of size %ld alloc'd</auxwhat>\n", (void*)err_ga, delta,
sewardj095d61e2010-03-11 13:43:18 +00001306 xe->XE.Race.hszB);
1307 VG_(pp_ExeContext)( xe->XE.Race.hctxt );
1308 } else {
sewardjffce8152011-06-24 10:09:41 +00001309 emit("\n");
1310 emit("Address %p is %ld bytes inside a block "
1311 "of size %ld alloc'd\n", (void*)err_ga, delta,
sewardj095d61e2010-03-11 13:43:18 +00001312 xe->XE.Race.hszB);
1313 VG_(pp_ExeContext)( xe->XE.Race.hctxt );
1314 }
1315 }
1316
sewardj24118492009-07-15 14:50:02 +00001317 /* If we have a better description of the address, show it.
1318 Note that in XML mode, it will already by nicely wrapped up
1319 in tags, either <auxwhat> or <xauxwhat>, so we can just emit
1320 it verbatim. */
sewardjffce8152011-06-24 10:09:41 +00001321 if (xml) {
1322 if (xe->XE.Race.descr1)
1323 emit( " %s\n",
1324 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
1325 if (xe->XE.Race.descr2)
1326 emit( " %s\n",
1327 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
1328 } else {
1329 if (xe->XE.Race.descr1 || xe->XE.Race.descr2)
1330 emit("\n");
1331 if (xe->XE.Race.descr1)
1332 emit( "%s\n",
1333 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
1334 if (xe->XE.Race.descr2)
1335 emit( "%s\n",
1336 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
1337 }
sewardjf98e1c02008-10-25 16:22:41 +00001338
1339 break; /* case XE_Race */
1340 } /* case XE_Race */
1341
1342 default:
1343 tl_assert(0);
1344 } /* switch (VG_(get_error_kind)(err)) */
1345}
1346
1347Char* HG_(get_error_name) ( Error* err )
1348{
1349 switch (VG_(get_error_kind)(err)) {
1350 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +00001351 case XE_UnlockUnlocked: return "UnlockUnlocked";
1352 case XE_UnlockForeign: return "UnlockForeign";
1353 case XE_UnlockBogus: return "UnlockBogus";
1354 case XE_PthAPIerror: return "PthAPIerror";
1355 case XE_LockOrder: return "LockOrder";
1356 case XE_Misc: return "Misc";
1357 default: tl_assert(0); /* fill in missing case */
1358 }
1359}
1360
1361Bool HG_(recognised_suppression) ( Char* name, Supp *su )
1362{
1363# define TRY(_name,_xskind) \
1364 if (0 == VG_(strcmp)(name, (_name))) { \
1365 VG_(set_supp_kind)(su, (_xskind)); \
1366 return True; \
1367 }
1368 TRY("Race", XS_Race);
1369 TRY("FreeMemLock", XS_FreeMemLock);
1370 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1371 TRY("UnlockForeign", XS_UnlockForeign);
1372 TRY("UnlockBogus", XS_UnlockBogus);
1373 TRY("PthAPIerror", XS_PthAPIerror);
1374 TRY("LockOrder", XS_LockOrder);
1375 TRY("Misc", XS_Misc);
1376 return False;
1377# undef TRY
1378}
1379
njn35db56c2009-07-24 07:38:29 +00001380Bool HG_(read_extra_suppression_info) ( Int fd, Char** bufpp, SizeT* nBufp,
sewardjf98e1c02008-10-25 16:22:41 +00001381 Supp* su )
1382{
1383 /* do nothing -- no extra suppression info present. Return True to
1384 indicate nothing bad happened. */
1385 return True;
1386}
1387
1388Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
1389{
1390 switch (VG_(get_supp_kind)(su)) {
1391 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001392 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1393 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1394 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1395 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1396 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1397 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1398 //case XS_: return VG_(get_error_kind)(err) == XE_;
1399 default: tl_assert(0); /* fill in missing cases */
1400 }
1401}
1402
sewardj588adef2009-08-15 22:41:51 +00001403Bool HG_(get_extra_suppression_info) ( Error* err,
1404 /*OUT*/Char* buf, Int nBuf )
sewardjf98e1c02008-10-25 16:22:41 +00001405{
1406 /* Do nothing */
sewardj588adef2009-08-15 22:41:51 +00001407 return False;
sewardjf98e1c02008-10-25 16:22:41 +00001408}
1409
1410
1411/*--------------------------------------------------------------------*/
1412/*--- end hg_errors.c ---*/
1413/*--------------------------------------------------------------------*/