blob: 010f5e0bcd6642499872408018eb8755b103cce0 [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
bart2fa18d92011-10-04 16:28:42 +0000945 if (xml)
946 emit( " <kind>%s</kind>\n", HG_(get_error_name)(err));
947
sewardjf98e1c02008-10-25 16:22:41 +0000948 switch (VG_(get_error_kind)(err)) {
949
950 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000951 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000952
953 if (xml) {
954
sewardj24118492009-07-15 14:50:02 +0000955 emit( " <xwhat>\n" );
956 emit( " <text>Thread #%d: %s</text>\n",
957 (Int)xe->XE.Misc.thr->errmsg_index,
958 xe->XE.Misc.errstr );
959 emit( " <hthreadid>%d</hthreadid>\n",
960 (Int)xe->XE.Misc.thr->errmsg_index );
961 emit( " </xwhat>\n" );
962 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000963 if (xe->XE.Misc.auxstr) {
964 emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
965 if (xe->XE.Misc.auxctx)
966 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
967 }
sewardj24118492009-07-15 14:50:02 +0000968
969 } else {
970
971 emit( "Thread #%d: %s\n",
972 (Int)xe->XE.Misc.thr->errmsg_index,
973 xe->XE.Misc.errstr );
974 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000975 if (xe->XE.Misc.auxstr) {
976 emit(" %s\n", xe->XE.Misc.auxstr);
977 if (xe->XE.Misc.auxctx)
978 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
979 }
sewardj24118492009-07-15 14:50:02 +0000980
981 }
sewardjf98e1c02008-10-25 16:22:41 +0000982 break;
983 }
984
985 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000986 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000987
988 if (xml) {
989
sewardj24118492009-07-15 14:50:02 +0000990 emit( " <xwhat>\n" );
991 emit( " <text>Thread #%d: lock order \"%p before %p\" "
992 "violated</text>\n",
993 (Int)xe->XE.LockOrder.thr->errmsg_index,
sewardjffce8152011-06-24 10:09:41 +0000994 (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
995 (void*)xe->XE.LockOrder.shouldbe_later_ga );
sewardj24118492009-07-15 14:50:02 +0000996 emit( " <hthreadid>%d</hthreadid>\n",
997 (Int)xe->XE.LockOrder.thr->errmsg_index );
998 emit( " </xwhat>\n" );
999 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +00001000 if (xe->XE.LockOrder.shouldbe_earlier_ec
1001 && xe->XE.LockOrder.shouldbe_later_ec) {
sewardj24118492009-07-15 14:50:02 +00001002 emit( " <auxwhat>Required order was established by "
1003 "acquisition of lock at %p</auxwhat>\n",
sewardjffce8152011-06-24 10:09:41 +00001004 (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
1005 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
sewardj24118492009-07-15 14:50:02 +00001006 emit( " <auxwhat>followed by a later acquisition "
1007 "of lock at %p</auxwhat>\n",
sewardjffce8152011-06-24 10:09:41 +00001008 (void*)xe->XE.LockOrder.shouldbe_later_ga );
1009 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +00001010 }
1011
1012 } else {
1013
1014 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
1015 (Int)xe->XE.LockOrder.thr->errmsg_index,
sewardjffce8152011-06-24 10:09:41 +00001016 (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
1017 (void*)xe->XE.LockOrder.shouldbe_later_ga );
1018 emit( "\n" );
1019 emit( "Observed (incorrect) order is: "
1020 "acquisition of lock at %p\n",
1021 (void*)xe->XE.LockOrder.shouldbe_later_ga);
1022 if (xe->XE.LockOrder.actual_earlier_ec) {
1023 VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
1024 } else {
1025 emit(" (stack unavailable)\n");
1026 }
1027 emit( "\n" );
1028 emit(" followed by a later acquisition of lock at %p\n",
1029 (void*)xe->XE.LockOrder.shouldbe_earlier_ga);
sewardj24118492009-07-15 14:50:02 +00001030 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +00001031 if (xe->XE.LockOrder.shouldbe_earlier_ec
1032 && xe->XE.LockOrder.shouldbe_later_ec) {
1033 emit("\n");
1034 emit( "Required order was established by "
sewardj24118492009-07-15 14:50:02 +00001035 "acquisition of lock at %p\n",
sewardjffce8152011-06-24 10:09:41 +00001036 (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
1037 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
1038 emit( "\n" );
1039 emit( " followed by a later acquisition of lock at %p\n",
1040 (void*)xe->XE.LockOrder.shouldbe_later_ga );
1041 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +00001042 }
1043
sewardjf98e1c02008-10-25 16:22:41 +00001044 }
sewardj24118492009-07-15 14:50:02 +00001045
sewardjf98e1c02008-10-25 16:22:41 +00001046 break;
1047 }
1048
1049 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +00001050 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +00001051
1052 if (xml) {
1053
sewardj24118492009-07-15 14:50:02 +00001054 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
sewardj24118492009-07-15 14:50:02 +00001085 emit( " <xwhat>\n" );
1086 emit( " <text>Thread #%d unlocked an invalid "
1087 "lock at %p</text>\n",
1088 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1089 (void*)xe->XE.UnlockBogus.lock_ga );
1090 emit( " <hthreadid>%d</hthreadid>\n",
1091 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
1092 emit( " </xwhat>\n" );
1093 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1094
1095 } else {
1096
1097 emit( "Thread #%d unlocked an invalid lock at %p\n",
1098 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1099 (void*)xe->XE.UnlockBogus.lock_ga );
1100 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1101
1102 }
1103
sewardjf98e1c02008-10-25 16:22:41 +00001104 break;
1105 }
1106
1107 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +00001108 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
1109 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
1110 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +00001111
1112 if (xml) {
1113
sewardj24118492009-07-15 14:50:02 +00001114 emit( " <xwhat>\n" );
1115 emit( " <text>Thread #%d unlocked lock at %p "
1116 "currently held by thread #%d</text>\n",
1117 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1118 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1119 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1120 emit( " <hthreadid>%d</hthreadid>\n",
1121 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
1122 emit( " <hthreadid>%d</hthreadid>\n",
1123 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1124 emit( " </xwhat>\n" );
1125 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1126
1127 if (xe->XE.UnlockForeign.lock->appeared_at) {
1128 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
1129 (void*)xe->XE.UnlockForeign.lock->guestaddr );
1130 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
1131 }
1132
1133 } else {
1134
1135 emit( "Thread #%d unlocked lock at %p "
1136 "currently held by thread #%d\n",
1137 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1138 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1139 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1140 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1141 if (xe->XE.UnlockForeign.lock->appeared_at) {
1142 emit( " Lock at %p was first observed\n",
1143 (void*)xe->XE.UnlockForeign.lock->guestaddr );
1144 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
1145 }
1146
sewardjf98e1c02008-10-25 16:22:41 +00001147 }
sewardj24118492009-07-15 14:50:02 +00001148
sewardjf98e1c02008-10-25 16:22:41 +00001149 break;
1150 }
1151
1152 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +00001153 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
1154 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +00001155
sewardj24118492009-07-15 14:50:02 +00001156 if (xml) {
1157
sewardj24118492009-07-15 14:50:02 +00001158 emit( " <xwhat>\n" );
1159 emit( " <text>Thread #%d unlocked a "
1160 "not-locked lock at %p</text>\n",
1161 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1162 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1163 emit( " <hthreadid>%d</hthreadid>\n",
1164 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
1165 emit( " </xwhat>\n" );
1166 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1167 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
1168 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
1169 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1170 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
1171 }
1172
1173 } else {
1174
1175 emit( "Thread #%d unlocked a not-locked lock at %p\n",
1176 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1177 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1178 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1179 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
1180 emit( " Lock at %p was first observed\n",
1181 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1182 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
1183 }
1184
sewardjf98e1c02008-10-25 16:22:41 +00001185 }
sewardj24118492009-07-15 14:50:02 +00001186
sewardjf98e1c02008-10-25 16:22:41 +00001187 break;
1188 }
1189
1190 case XE_Race: {
1191 Addr err_ga;
1192 HChar* what;
1193 Int szB;
1194 what = xe->XE.Race.isWrite ? "write" : "read";
1195 szB = xe->XE.Race.szB;
1196 err_ga = VG_(get_error_address)(err);
1197
sewardj24118492009-07-15 14:50:02 +00001198 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardj23f12002009-07-24 08:45:08 +00001199 if (xe->XE.Race.h2_ct)
1200 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
sewardj24118492009-07-15 14:50:02 +00001201
1202 if (xml) {
1203
1204 /* ------ XML ------ */
sewardj24118492009-07-15 14:50:02 +00001205 emit( " <xwhat>\n" );
1206 emit( " <text>Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001207 "at %p by thread #%d</text>\n",
1208 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
sewardj24118492009-07-15 14:50:02 +00001209 emit( " <hthreadid>%d</hthreadid>\n",
1210 (Int)xe->XE.Race.thr->errmsg_index );
1211 emit( " </xwhat>\n" );
1212 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1213
sewardj23f12002009-07-24 08:45:08 +00001214 if (xe->XE.Race.h2_ct) {
1215 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1216 emit( " <xauxwhat>\n");
1217 emit( " <text>This conflicts with a previous %s of size %d "
1218 "by thread #%d</text>\n",
1219 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1220 xe->XE.Race.h2_ct_accSzB,
1221 xe->XE.Race.h2_ct->errmsg_index );
1222 emit( " <hthreadid>%d</hthreadid>\n",
1223 xe->XE.Race.h2_ct->errmsg_index);
1224 emit(" </xauxwhat>\n");
1225 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1226 }
1227
1228 if (xe->XE.Race.h1_ct) {
1229 emit( " <xauxwhat>\n");
1230 emit( " <text>This conflicts with a previous access "
1231 "by thread #%d, after</text>\n",
1232 xe->XE.Race.h1_ct->errmsg_index );
1233 emit( " <hthreadid>%d</hthreadid>\n",
1234 xe->XE.Race.h1_ct->errmsg_index );
1235 emit(" </xauxwhat>\n");
1236 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1237 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001238 } else {
sewardj23f12002009-07-24 08:45:08 +00001239 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" );
sewardj24118492009-07-15 14:50:02 +00001240 }
sewardj23f12002009-07-24 08:45:08 +00001241 emit( " <auxwhat>but before</auxwhat>\n" );
1242 if (xe->XE.Race.h1_ct_mbsegendEC) {
1243 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1244 } else {
1245 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" );
1246 }
sewardjf98e1c02008-10-25 16:22:41 +00001247 }
sewardj24118492009-07-15 14:50:02 +00001248
1249 } else {
1250
1251 /* ------ Text ------ */
sewardjffce8152011-06-24 10:09:41 +00001252 announce_combined_LockP_vecs( xe->XE.Race.locksHeldW,
1253 xe->XE.Race.h2_ct_locksHeldW );
1254
sewardj24118492009-07-15 14:50:02 +00001255 emit( "Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001256 "at %p by thread #%d\n",
1257 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1258
1259 tl_assert(xe->XE.Race.locksHeldW);
1260 show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" );
sewardj24118492009-07-15 14:50:02 +00001261 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj23f12002009-07-24 08:45:08 +00001262
1263 if (xe->XE.Race.h2_ct) {
1264 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
sewardjffce8152011-06-24 10:09:41 +00001265 tl_assert(xe->XE.Race.h2_ct_locksHeldW);
1266 emit( "\n" );
1267 emit( "This conflicts with a previous %s of size %d "
sewardj23f12002009-07-24 08:45:08 +00001268 "by thread #%d\n",
1269 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1270 xe->XE.Race.h2_ct_accSzB,
1271 xe->XE.Race.h2_ct->errmsg_index );
sewardjffce8152011-06-24 10:09:41 +00001272 show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" );
sewardj23f12002009-07-24 08:45:08 +00001273 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1274 }
1275
1276 if (xe->XE.Race.h1_ct) {
1277 emit( " This conflicts with a previous access by thread #%d, "
1278 "after\n",
1279 xe->XE.Race.h1_ct->errmsg_index );
1280 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1281 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001282 } else {
sewardj23f12002009-07-24 08:45:08 +00001283 emit( " (the start of the thread)\n" );
sewardj24118492009-07-15 14:50:02 +00001284 }
sewardj23f12002009-07-24 08:45:08 +00001285 emit( " but before\n" );
1286 if (xe->XE.Race.h1_ct_mbsegendEC) {
1287 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1288 } else {
1289 emit( " (the end of the the thread)\n" );
1290 }
sewardj24118492009-07-15 14:50:02 +00001291 }
1292
sewardjf98e1c02008-10-25 16:22:41 +00001293 }
1294
sewardj095d61e2010-03-11 13:43:18 +00001295 /* If we have a description of the address in terms of a heap
1296 block, show it. */
1297 if (xe->XE.Race.hctxt) {
1298 SizeT delta = err_ga - xe->XE.Race.haddr;
1299 if (xml) {
sewardjffce8152011-06-24 10:09:41 +00001300 emit(" <auxwhat>Address %p is %ld bytes inside a block "
1301 "of size %ld alloc'd</auxwhat>\n", (void*)err_ga, delta,
sewardj095d61e2010-03-11 13:43:18 +00001302 xe->XE.Race.hszB);
1303 VG_(pp_ExeContext)( xe->XE.Race.hctxt );
1304 } else {
sewardjffce8152011-06-24 10:09:41 +00001305 emit("\n");
1306 emit("Address %p is %ld bytes inside a block "
1307 "of size %ld alloc'd\n", (void*)err_ga, delta,
sewardj095d61e2010-03-11 13:43:18 +00001308 xe->XE.Race.hszB);
1309 VG_(pp_ExeContext)( xe->XE.Race.hctxt );
1310 }
1311 }
1312
sewardj24118492009-07-15 14:50:02 +00001313 /* If we have a better description of the address, show it.
1314 Note that in XML mode, it will already by nicely wrapped up
1315 in tags, either <auxwhat> or <xauxwhat>, so we can just emit
1316 it verbatim. */
sewardjffce8152011-06-24 10:09:41 +00001317 if (xml) {
1318 if (xe->XE.Race.descr1)
1319 emit( " %s\n",
1320 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
1321 if (xe->XE.Race.descr2)
1322 emit( " %s\n",
1323 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
1324 } else {
1325 if (xe->XE.Race.descr1 || xe->XE.Race.descr2)
1326 emit("\n");
1327 if (xe->XE.Race.descr1)
1328 emit( "%s\n",
1329 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
1330 if (xe->XE.Race.descr2)
1331 emit( "%s\n",
1332 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
1333 }
sewardjf98e1c02008-10-25 16:22:41 +00001334
1335 break; /* case XE_Race */
1336 } /* case XE_Race */
1337
1338 default:
1339 tl_assert(0);
1340 } /* switch (VG_(get_error_kind)(err)) */
1341}
1342
1343Char* HG_(get_error_name) ( Error* err )
1344{
1345 switch (VG_(get_error_kind)(err)) {
1346 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +00001347 case XE_UnlockUnlocked: return "UnlockUnlocked";
1348 case XE_UnlockForeign: return "UnlockForeign";
1349 case XE_UnlockBogus: return "UnlockBogus";
1350 case XE_PthAPIerror: return "PthAPIerror";
1351 case XE_LockOrder: return "LockOrder";
1352 case XE_Misc: return "Misc";
1353 default: tl_assert(0); /* fill in missing case */
1354 }
1355}
1356
1357Bool HG_(recognised_suppression) ( Char* name, Supp *su )
1358{
1359# define TRY(_name,_xskind) \
1360 if (0 == VG_(strcmp)(name, (_name))) { \
1361 VG_(set_supp_kind)(su, (_xskind)); \
1362 return True; \
1363 }
1364 TRY("Race", XS_Race);
1365 TRY("FreeMemLock", XS_FreeMemLock);
1366 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1367 TRY("UnlockForeign", XS_UnlockForeign);
1368 TRY("UnlockBogus", XS_UnlockBogus);
1369 TRY("PthAPIerror", XS_PthAPIerror);
1370 TRY("LockOrder", XS_LockOrder);
1371 TRY("Misc", XS_Misc);
1372 return False;
1373# undef TRY
1374}
1375
njn35db56c2009-07-24 07:38:29 +00001376Bool HG_(read_extra_suppression_info) ( Int fd, Char** bufpp, SizeT* nBufp,
sewardjf98e1c02008-10-25 16:22:41 +00001377 Supp* su )
1378{
1379 /* do nothing -- no extra suppression info present. Return True to
1380 indicate nothing bad happened. */
1381 return True;
1382}
1383
1384Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
1385{
1386 switch (VG_(get_supp_kind)(su)) {
1387 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001388 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1389 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1390 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1391 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1392 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1393 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1394 //case XS_: return VG_(get_error_kind)(err) == XE_;
1395 default: tl_assert(0); /* fill in missing cases */
1396 }
1397}
1398
sewardj588adef2009-08-15 22:41:51 +00001399Bool HG_(get_extra_suppression_info) ( Error* err,
1400 /*OUT*/Char* buf, Int nBuf )
sewardjf98e1c02008-10-25 16:22:41 +00001401{
1402 /* Do nothing */
sewardj588adef2009-08-15 22:41:51 +00001403 return False;
sewardjf98e1c02008-10-25 16:22:41 +00001404}
1405
1406
1407/*--------------------------------------------------------------------*/
1408/*--- end hg_errors.c ---*/
1409/*--------------------------------------------------------------------*/