blob: c017a9136aaaa6c6eb4dfeb025a3eb4f421a71fc [file] [log] [blame]
sewardjf98e1c02008-10-25 16:22:41 +00001
2/*--------------------------------------------------------------------*/
3/*--- Error management for Helgrind. ---*/
4/*--- hg_errors.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Helgrind, a Valgrind tool for detecting errors
9 in threaded programs.
10
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2007-2013 OpenWorks Ltd
sewardjf98e1c02008-10-25 16:22:41 +000012 info@open-works.co.uk
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#include "pub_tool_basics.h"
33#include "pub_tool_libcbase.h"
34#include "pub_tool_libcassert.h"
35#include "pub_tool_libcprint.h"
36#include "pub_tool_execontext.h"
37#include "pub_tool_errormgr.h"
38#include "pub_tool_wordfm.h"
39#include "pub_tool_xarray.h"
40#include "pub_tool_debuginfo.h"
41#include "pub_tool_threadstate.h"
sewardj24118492009-07-15 14:50:02 +000042#include "pub_tool_options.h" // VG_(clo_xml)
philippe07c08522014-05-14 20:39:27 +000043#include "pub_tool_addrinfo.h"
sewardjf98e1c02008-10-25 16:22:41 +000044
45#include "hg_basics.h"
philippef5774342014-05-03 11:12:50 +000046#include "hg_addrdescr.h"
sewardjf98e1c02008-10-25 16:22:41 +000047#include "hg_wordset.h"
48#include "hg_lock_n_thread.h"
sewardjc5ea9962008-12-07 01:41:46 +000049#include "libhb.h"
sewardjf98e1c02008-10-25 16:22:41 +000050#include "hg_errors.h" /* self */
51
52
53/*----------------------------------------------------------------*/
sewardj24118492009-07-15 14:50:02 +000054/*--- Error management -- storage ---*/
sewardjf98e1c02008-10-25 16:22:41 +000055/*----------------------------------------------------------------*/
56
57/* maps (by value) strings to a copy of them in ARENA_TOOL */
58
59static WordFM* string_table = NULL;
60
61ULong HG_(stats__string_table_queries) = 0;
62
63ULong HG_(stats__string_table_get_map_size) ( void ) {
64 return string_table ? (ULong)VG_(sizeFM)(string_table) : 0;
65}
66
67static Word string_table_cmp ( UWord s1, UWord s2 ) {
68 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
69}
70
florian19f91bb2012-11-10 22:29:54 +000071static HChar* string_table_strdup ( const HChar* str ) {
sewardjf98e1c02008-10-25 16:22:41 +000072 HChar* copy = NULL;
73 HG_(stats__string_table_queries)++;
74 if (!str)
75 str = "(null)";
76 if (!string_table) {
77 string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1",
78 HG_(free), string_table_cmp );
79 tl_assert(string_table);
80 }
81 if (VG_(lookupFM)( string_table,
florian6bf37262012-10-21 03:23:36 +000082 NULL, (UWord*)&copy, (UWord)str )) {
sewardjf98e1c02008-10-25 16:22:41 +000083 tl_assert(copy);
84 if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
85 return copy;
86 } else {
87 copy = HG_(strdup)("hg.sts.2", str);
88 tl_assert(copy);
florian19f91bb2012-11-10 22:29:54 +000089 VG_(addToFM)( string_table, (UWord)copy, (UWord)copy );
sewardjf98e1c02008-10-25 16:22:41 +000090 return copy;
91 }
92}
93
94/* maps from Lock .unique fields to LockP*s */
95
96static WordFM* map_LockN_to_P = NULL;
97
98ULong HG_(stats__LockN_to_P_queries) = 0;
99
100ULong HG_(stats__LockN_to_P_get_map_size) ( void ) {
101 return map_LockN_to_P ? (ULong)VG_(sizeFM)(map_LockN_to_P) : 0;
102}
103
104static Word lock_unique_cmp ( UWord lk1W, UWord lk2W )
105{
106 Lock* lk1 = (Lock*)lk1W;
107 Lock* lk2 = (Lock*)lk2W;
108 tl_assert( HG_(is_sane_LockNorP)(lk1) );
109 tl_assert( HG_(is_sane_LockNorP)(lk2) );
110 if (lk1->unique < lk2->unique) return -1;
111 if (lk1->unique > lk2->unique) return 1;
112 return 0;
113}
114
sewardjffce8152011-06-24 10:09:41 +0000115/* Given a normal Lock (LockN), convert it to a persistent Lock
116 (LockP). In some cases the LockN could be invalid (if it's been
117 freed), so we enquire, in hg_main.c's admin_locks list, whether it
118 is in fact valid. If allowed_to_be_invalid is True, then it's OK
119 for the LockN to be invalid, in which case Lock_INVALID is
120 returned. In all other cases, we insist that the LockN is a valid
121 lock, and return its corresponding LockP.
122
123 Why can LockNs sometimes be invalid? Because they are harvested
124 from locksets that are attached to the OldRef info for conflicting
125 threads. By the time we detect a race, the some of the elements of
126 the lockset may have been destroyed by the client, in which case
127 the corresponding Lock structures we maintain will have been freed.
128
129 So we check that each LockN is a member of the admin_locks double
130 linked list of all Lock structures. That stops us prodding around
131 in potentially freed-up Lock structures. However, it's not quite a
132 proper check: if a new Lock has been reallocated at the same
133 address as one which was previously freed, we'll wind up copying
134 the new one as the basis for the LockP, which is completely bogus
135 because it is unrelated to the previous Lock that lived there.
136 Let's hope that doesn't happen too often.
137*/
138static Lock* mk_LockP_from_LockN ( Lock* lkn,
139 Bool allowed_to_be_invalid )
sewardjf98e1c02008-10-25 16:22:41 +0000140{
141 Lock* lkp = NULL;
142 HG_(stats__LockN_to_P_queries)++;
sewardjffce8152011-06-24 10:09:41 +0000143
144 /* First off, let's do some sanity checks. If
145 allowed_to_be_invalid is False, we _must_ be able to find 'lkn'
146 in admin_locks; else we must assert. If it is True, it's OK for
147 it not to be findable, but in that case we must return
148 Lock_INVALID right away. */
149 Lock* lock_list = HG_(get_admin_locks)();
150 while (lock_list) {
151 if (lock_list == lkn)
152 break;
153 lock_list = lock_list->admin_next;
154 }
155 if (lock_list == NULL) {
156 /* We didn't find it. That possibility has to be OK'd by the
157 caller. */
158 tl_assert(allowed_to_be_invalid);
159 return Lock_INVALID;
160 }
161
162 /* So we must be looking at a valid LockN. */
sewardjf98e1c02008-10-25 16:22:41 +0000163 tl_assert( HG_(is_sane_LockN)(lkn) );
sewardjffce8152011-06-24 10:09:41 +0000164
sewardjf98e1c02008-10-25 16:22:41 +0000165 if (!map_LockN_to_P) {
166 map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1",
167 HG_(free), lock_unique_cmp );
168 tl_assert(map_LockN_to_P);
169 }
florian6bf37262012-10-21 03:23:36 +0000170 if (!VG_(lookupFM)( map_LockN_to_P, NULL, (UWord*)&lkp, (UWord)lkn)) {
sewardjf98e1c02008-10-25 16:22:41 +0000171 lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
172 *lkp = *lkn;
sewardj1d7c3322011-02-28 09:22:51 +0000173 lkp->admin_next = NULL;
174 lkp->admin_prev = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000175 lkp->magic = LockP_MAGIC;
176 /* Forget about the bag of lock holders - don't copy that.
177 Also, acquired_at should be NULL whenever heldBy is, and vice
178 versa. Also forget about the associated libhb synch object. */
179 lkp->heldW = False;
180 lkp->heldBy = NULL;
181 lkp->acquired_at = NULL;
182 lkp->hbso = NULL;
florian6bf37262012-10-21 03:23:36 +0000183 VG_(addToFM)( map_LockN_to_P, (UWord)lkp, (UWord)lkp );
sewardjf98e1c02008-10-25 16:22:41 +0000184 }
185 tl_assert( HG_(is_sane_LockP)(lkp) );
186 return lkp;
187}
188
sewardjffce8152011-06-24 10:09:41 +0000189/* Expand a WordSet of LockN*'s into a NULL-terminated vector of
190 LockP*'s. Any LockN's that can't be converted into a LockP
191 (because they have been freed, see comment on mk_LockP_from_LockN)
192 are converted instead into the value Lock_INVALID. Hence the
193 returned vector is a sequence: zero or more (valid LockP* or
194 LockN_INVALID), terminated by a NULL. */
195static
196Lock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets,
197 WordSetID lockset,
198 Bool allowed_to_be_invalid )
199{
200 tl_assert(univ_lsets);
201 tl_assert( HG_(plausibleWS)(univ_lsets, lockset) );
202 UWord nLocks = HG_(cardinalityWS)(univ_lsets, lockset);
203 Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa",
204 (nLocks+1) * sizeof(Lock*) );
205 tl_assert(lockPs);
206 tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */
207 UWord* lockNs = NULL;
208 UWord nLockNs = 0;
209 if (nLocks > 0) {
210 /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the
211 lockset is empty; hence the guarding "if". Sigh. */
212 HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset );
213 tl_assert(lockNs);
214 }
215 UWord i;
216 /* Convert to LockPs. */
217 for (i = 0; i < nLockNs; i++) {
218 lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i],
219 allowed_to_be_invalid );
220 }
221 return lockPs;
222}
223
224/* Get the number of useful elements in a vector created by
225 enumerate_WordSet_into_LockP_vector. Returns both the total number
226 of elements (not including the terminating NULL) and the number of
227 non-Lock_INVALID elements. */
228static void count_LockP_vector ( /*OUT*/UWord* nLocks,
229 /*OUT*/UWord* nLocksValid,
230 Lock** vec )
231{
232 tl_assert(vec);
233 *nLocks = *nLocksValid = 0;
234 UWord n = 0;
235 while (vec[n]) {
236 (*nLocks)++;
237 if (vec[n] != Lock_INVALID)
238 (*nLocksValid)++;
239 n++;
240 }
241}
242
243/* Find out whether 'lk' is in 'vec'. */
244static Bool elem_LockP_vector ( Lock** vec, Lock* lk )
245{
246 tl_assert(vec);
247 tl_assert(lk);
248 UWord n = 0;
249 while (vec[n]) {
250 if (vec[n] == lk)
251 return True;
252 n++;
253 }
254 return False;
255}
256
257
sewardjf98e1c02008-10-25 16:22:41 +0000258/* Errors:
259
260 race: program counter
261 read or write
262 data size
263 previous state
264 current state
265
266 FIXME: how does state printing interact with lockset gc?
267 Are the locksets in prev/curr state always valid?
268 Ditto question for the threadsets
269 ThreadSets - probably are always valid if Threads
270 are never thrown away.
271 LockSets - could at least print the lockset elements that
272 correspond to actual locks at the time of printing. Hmm.
273*/
274
275/* Error kinds */
276typedef
277 enum {
278 XE_Race=1101, // race
sewardjf98e1c02008-10-25 16:22:41 +0000279 XE_UnlockUnlocked, // unlocking a not-locked lock
280 XE_UnlockForeign, // unlocking a lock held by some other thread
281 XE_UnlockBogus, // unlocking an address not known to be a lock
282 XE_PthAPIerror, // error from the POSIX pthreads API
283 XE_LockOrder, // lock order error
284 XE_Misc // misc other error (w/ string to describe it)
285 }
286 XErrorTag;
287
288/* Extra contexts for kinds */
289typedef
290 struct {
291 XErrorTag tag;
292 union {
293 struct {
sewardj23f12002009-07-24 08:45:08 +0000294 Addr data_addr;
295 Int szB;
philippe07c08522014-05-14 20:39:27 +0000296 AddrInfo data_addrinfo;
sewardj23f12002009-07-24 08:45:08 +0000297 Bool isWrite;
298 Thread* thr;
sewardjffce8152011-06-24 10:09:41 +0000299 Lock** locksHeldW;
sewardj095d61e2010-03-11 13:43:18 +0000300 /* h1_* and h2_* provide some description of a previously
301 observed access with which we are conflicting. */
sewardj23f12002009-07-24 08:45:08 +0000302 Thread* h1_ct; /* non-NULL means h1 info present */
303 ExeContext* h1_ct_mbsegstartEC;
304 ExeContext* h1_ct_mbsegendEC;
305 Thread* h2_ct; /* non-NULL means h2 info present */
306 ExeContext* h2_ct_accEC;
307 Int h2_ct_accSzB;
308 Bool h2_ct_accIsW;
sewardjffce8152011-06-24 10:09:41 +0000309 Lock** h2_ct_locksHeldW;
sewardjf98e1c02008-10-25 16:22:41 +0000310 } Race;
311 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000312 Thread* thr; /* doing the unlocking */
313 Lock* lock; /* lock (that is already unlocked) */
314 } UnlockUnlocked;
315 struct {
316 Thread* thr; /* doing the unlocking */
317 Thread* owner; /* thread that actually holds the lock */
318 Lock* lock; /* lock (that is held by 'owner') */
319 } UnlockForeign;
320 struct {
321 Thread* thr; /* doing the unlocking */
322 Addr lock_ga; /* purported address of the lock */
323 } UnlockBogus;
324 struct {
325 Thread* thr;
326 HChar* fnname; /* persistent, in tool-arena */
327 Word err; /* pth error code */
328 HChar* errstr; /* persistent, in tool-arena */
329 } PthAPIerror;
330 struct {
331 Thread* thr;
sewardjffce8152011-06-24 10:09:41 +0000332 /* The first 4 fields describe the previously observed
333 (should-be) ordering. */
334 Addr shouldbe_earlier_ga;
335 Addr shouldbe_later_ga;
336 ExeContext* shouldbe_earlier_ec;
337 ExeContext* shouldbe_later_ec;
338 /* In principle we need to record two more stacks, from
339 this thread, when acquiring the locks in the "wrong"
340 order. In fact the wallclock-later acquisition by this
341 thread is recorded in the main stack for this error.
342 So we only need a stack for the earlier acquisition by
343 this thread. */
344 ExeContext* actual_earlier_ec;
sewardjf98e1c02008-10-25 16:22:41 +0000345 } LockOrder;
346 struct {
sewardj8fef6252010-07-29 05:28:02 +0000347 Thread* thr;
348 HChar* errstr; /* persistent, in tool-arena */
349 HChar* auxstr; /* optional, persistent, in tool-arena */
350 ExeContext* auxctx; /* optional */
sewardjf98e1c02008-10-25 16:22:41 +0000351 } Misc;
352 } XE;
353 }
354 XError;
355
356static void init_XError ( XError* xe ) {
357 VG_(memset)(xe, 0, sizeof(*xe) );
358 xe->tag = XE_Race-1; /* bogus */
359}
360
361
362/* Extensions of suppressions */
363typedef
364 enum {
365 XS_Race=1201, /* race */
366 XS_FreeMemLock,
367 XS_UnlockUnlocked,
368 XS_UnlockForeign,
369 XS_UnlockBogus,
370 XS_PthAPIerror,
371 XS_LockOrder,
372 XS_Misc
373 }
374 XSuppTag;
375
376
377/* Updates the copy with address info if necessary. */
378UInt HG_(update_extra) ( Error* err )
379{
380 XError* xe = (XError*)VG_(get_error_extra)(err);
381 tl_assert(xe);
382 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
383 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
384 //}
385
386 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000387
sewardjffce8152011-06-24 10:09:41 +0000388 /* Note the set of locks that the thread is (w-)holding.
389 Convert the WordSetID of LockN*'s into a NULL-terminated
390 vector of LockP*'s. We don't expect to encounter any invalid
391 LockNs in this conversion. */
392 tl_assert(xe->XE.Race.thr);
393 xe->XE.Race.locksHeldW
394 = enumerate_WordSet_into_LockP_vector(
395 HG_(get_univ_lsets)(),
396 xe->XE.Race.thr->locksetW,
397 False/*!allowed_to_be_invalid*/
398 );
399
sewardjf98e1c02008-10-25 16:22:41 +0000400 /* See if we can come up with a source level description of the
401 raced-upon address. This is potentially expensive, which is
402 why it's only done at the update_extra point, not when the
403 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000404 static Int xxx = 0;
405 xxx++;
406 if (0)
407 VG_(printf)("HG_(update_extra): "
408 "%d conflicting-event queries\n", xxx);
sewardj095d61e2010-03-11 13:43:18 +0000409
philippe07c08522014-05-14 20:39:27 +0000410 HG_(describe_addr) (xe->XE.Race.data_addr, &xe->XE.Race.data_addrinfo);
sewardj24118492009-07-15 14:50:02 +0000411
412 /* And poke around in the conflicting-event map, to see if we
413 can rustle up a plausible-looking conflicting memory access
414 to show. */
sewardj23f12002009-07-24 08:45:08 +0000415 if (HG_(clo_history_level) >= 2) {
sewardjffce8152011-06-24 10:09:41 +0000416 Thr* thrp = NULL;
417 ExeContext* wherep = NULL;
418 Addr acc_addr = xe->XE.Race.data_addr;
419 Int acc_szB = xe->XE.Race.szB;
420 Thr* acc_thr = xe->XE.Race.thr->hbthr;
421 Bool acc_isW = xe->XE.Race.isWrite;
422 SizeT conf_szB = 0;
423 Bool conf_isW = False;
424 WordSetID conf_locksHeldW = 0;
sewardj23f12002009-07-24 08:45:08 +0000425 tl_assert(!xe->XE.Race.h2_ct_accEC);
426 tl_assert(!xe->XE.Race.h2_ct);
427 if (libhb_event_map_lookup(
sewardjffce8152011-06-24 10:09:41 +0000428 &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW,
sewardj23f12002009-07-24 08:45:08 +0000429 acc_thr, acc_addr, acc_szB, acc_isW )) {
430 Thread* threadp;
431 tl_assert(wherep);
432 tl_assert(thrp);
sewardj60626642011-03-10 15:14:37 +0000433 threadp = libhb_get_Thr_hgthread( thrp );
sewardj23f12002009-07-24 08:45:08 +0000434 tl_assert(threadp);
435 xe->XE.Race.h2_ct_accEC = wherep;
436 xe->XE.Race.h2_ct = threadp;
437 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
438 xe->XE.Race.h2_ct_accIsW = conf_isW;
sewardjffce8152011-06-24 10:09:41 +0000439 xe->XE.Race.h2_ct_locksHeldW
440 = enumerate_WordSet_into_LockP_vector(
441 HG_(get_univ_lsets)(),
442 conf_locksHeldW,
443 True/*allowed_to_be_invalid*/
444 );
sewardjc5ea9962008-12-07 01:41:46 +0000445 }
446 }
sewardj23f12002009-07-24 08:45:08 +0000447
448 // both NULL or both non-NULL
449 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
sewardjf98e1c02008-10-25 16:22:41 +0000450 }
451
452 return sizeof(XError);
453}
454
455void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000456 Addr data_addr, Int szB, Bool isWrite,
sewardj23f12002009-07-24 08:45:08 +0000457 Thread* h1_ct,
458 ExeContext* h1_ct_segstart,
459 ExeContext* h1_ct_mbsegendEC )
sewardjf98e1c02008-10-25 16:22:41 +0000460{
461 XError xe;
462 tl_assert( HG_(is_sane_Thread)(thr) );
463
464# if defined(VGO_linux)
465 /* Skip any races on locations apparently in GOTPLT sections. This
466 is said to be caused by ld.so poking PLT table entries (or
467 whatever) when it writes the resolved address of a dynamically
468 linked routine, into the table (or whatever) when it is called
469 for the first time. */
470 {
sewardje3f1e592009-07-31 09:41:29 +0000471 VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr );
sewardjf98e1c02008-10-25 16:22:41 +0000472 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
473 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000474 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000475 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000476 /* SectPLT is required on ppc32/64-linux */
477 if (sect == Vg_SectPLT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000478 }
479# endif
480
481 init_XError(&xe);
482 xe.tag = XE_Race;
483 xe.XE.Race.data_addr = data_addr;
484 xe.XE.Race.szB = szB;
485 xe.XE.Race.isWrite = isWrite;
sewardjf98e1c02008-10-25 16:22:41 +0000486 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000487 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000488 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000489 /* Skip on the detailed description of the raced-on address at this
490 point; it's expensive. Leave it for the update_extra function
491 if we ever make it that far. */
philippe07c08522014-05-14 20:39:27 +0000492 xe.XE.Race.data_addrinfo.tag = Addr_Undescribed;
sewardjf98e1c02008-10-25 16:22:41 +0000493 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000494 // Skip on any of the conflicting-access info at this point.
495 // It's expensive to obtain, and this error is more likely than
496 // not to be discarded. We'll fill these fields in in
497 // HG_(update_extra) just above, assuming the error ever makes
498 // it that far (unlikely).
sewardj23f12002009-07-24 08:45:08 +0000499 xe.XE.Race.h2_ct_accSzB = 0;
500 xe.XE.Race.h2_ct_accIsW = False;
501 xe.XE.Race.h2_ct_accEC = NULL;
502 xe.XE.Race.h2_ct = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000503 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
504 tl_assert( thr->coretid != VG_INVALID_THREADID );
sewardj23f12002009-07-24 08:45:08 +0000505
506 xe.XE.Race.h1_ct = h1_ct;
507 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
508 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC;
509
sewardjf98e1c02008-10-25 16:22:41 +0000510 VG_(maybe_record_error)( thr->coretid,
511 XE_Race, data_addr, NULL, &xe );
512}
513
sewardjf98e1c02008-10-25 16:22:41 +0000514void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
515{
516 XError xe;
517 tl_assert( HG_(is_sane_Thread)(thr) );
518 tl_assert( HG_(is_sane_LockN)(lk) );
519 init_XError(&xe);
520 xe.tag = XE_UnlockUnlocked;
sewardjffce8152011-06-24 10:09:41 +0000521 xe.XE.UnlockUnlocked.thr
522 = thr;
523 xe.XE.UnlockUnlocked.lock
524 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
sewardjf98e1c02008-10-25 16:22:41 +0000525 // FIXME: tid vs thr
526 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
527 tl_assert( thr->coretid != VG_INVALID_THREADID );
528 VG_(maybe_record_error)( thr->coretid,
529 XE_UnlockUnlocked, 0, NULL, &xe );
530}
531
532void HG_(record_error_UnlockForeign) ( Thread* thr,
533 Thread* owner, Lock* lk )
534{
535 XError xe;
536 tl_assert( HG_(is_sane_Thread)(thr) );
537 tl_assert( HG_(is_sane_Thread)(owner) );
538 tl_assert( HG_(is_sane_LockN)(lk) );
539 init_XError(&xe);
540 xe.tag = XE_UnlockForeign;
541 xe.XE.UnlockForeign.thr = thr;
542 xe.XE.UnlockForeign.owner = owner;
sewardjffce8152011-06-24 10:09:41 +0000543 xe.XE.UnlockForeign.lock
544 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
sewardjf98e1c02008-10-25 16:22:41 +0000545 // FIXME: tid vs thr
546 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
547 tl_assert( thr->coretid != VG_INVALID_THREADID );
548 VG_(maybe_record_error)( thr->coretid,
549 XE_UnlockForeign, 0, NULL, &xe );
550}
551
552void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
553{
554 XError xe;
555 tl_assert( HG_(is_sane_Thread)(thr) );
556 init_XError(&xe);
557 xe.tag = XE_UnlockBogus;
558 xe.XE.UnlockBogus.thr = thr;
559 xe.XE.UnlockBogus.lock_ga = lock_ga;
560 // FIXME: tid vs thr
561 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
562 tl_assert( thr->coretid != VG_INVALID_THREADID );
563 VG_(maybe_record_error)( thr->coretid,
564 XE_UnlockBogus, 0, NULL, &xe );
565}
566
567void HG_(record_error_LockOrder)(
sewardjffce8152011-06-24 10:09:41 +0000568 Thread* thr,
569 Addr shouldbe_earlier_ga,
570 Addr shouldbe_later_ga,
571 ExeContext* shouldbe_earlier_ec,
572 ExeContext* shouldbe_later_ec,
573 ExeContext* actual_earlier_ec
sewardjf98e1c02008-10-25 16:22:41 +0000574 )
575{
576 XError xe;
577 tl_assert( HG_(is_sane_Thread)(thr) );
sewardjc1fb9d22011-02-28 09:03:44 +0000578 tl_assert(HG_(clo_track_lockorders));
sewardjf98e1c02008-10-25 16:22:41 +0000579 init_XError(&xe);
580 xe.tag = XE_LockOrder;
581 xe.XE.LockOrder.thr = thr;
sewardjffce8152011-06-24 10:09:41 +0000582 xe.XE.LockOrder.shouldbe_earlier_ga = shouldbe_earlier_ga;
583 xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec;
584 xe.XE.LockOrder.shouldbe_later_ga = shouldbe_later_ga;
585 xe.XE.LockOrder.shouldbe_later_ec = shouldbe_later_ec;
586 xe.XE.LockOrder.actual_earlier_ec = actual_earlier_ec;
sewardjf98e1c02008-10-25 16:22:41 +0000587 // FIXME: tid vs thr
588 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
589 tl_assert( thr->coretid != VG_INVALID_THREADID );
590 VG_(maybe_record_error)( thr->coretid,
591 XE_LockOrder, 0, NULL, &xe );
592}
593
florian6bd9dc12012-11-23 16:17:43 +0000594void HG_(record_error_PthAPIerror) ( Thread* thr, const HChar* fnname,
595 Word err, const HChar* errstr )
sewardjf98e1c02008-10-25 16:22:41 +0000596{
597 XError xe;
598 tl_assert( HG_(is_sane_Thread)(thr) );
599 tl_assert(fnname);
600 tl_assert(errstr);
601 init_XError(&xe);
602 xe.tag = XE_PthAPIerror;
603 xe.XE.PthAPIerror.thr = thr;
604 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
605 xe.XE.PthAPIerror.err = err;
606 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
607 // FIXME: tid vs thr
608 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
609 tl_assert( thr->coretid != VG_INVALID_THREADID );
610 VG_(maybe_record_error)( thr->coretid,
611 XE_PthAPIerror, 0, NULL, &xe );
612}
613
florian6bd9dc12012-11-23 16:17:43 +0000614void HG_(record_error_Misc_w_aux) ( Thread* thr, const HChar* errstr,
615 const HChar* auxstr, ExeContext* auxctx )
sewardjf98e1c02008-10-25 16:22:41 +0000616{
617 XError xe;
618 tl_assert( HG_(is_sane_Thread)(thr) );
619 tl_assert(errstr);
620 init_XError(&xe);
621 xe.tag = XE_Misc;
622 xe.XE.Misc.thr = thr;
623 xe.XE.Misc.errstr = string_table_strdup(errstr);
sewardj8fef6252010-07-29 05:28:02 +0000624 xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
625 xe.XE.Misc.auxctx = auxctx;
sewardjf98e1c02008-10-25 16:22:41 +0000626 // FIXME: tid vs thr
627 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
628 tl_assert( thr->coretid != VG_INVALID_THREADID );
629 VG_(maybe_record_error)( thr->coretid,
630 XE_Misc, 0, NULL, &xe );
631}
632
florian6bd9dc12012-11-23 16:17:43 +0000633void HG_(record_error_Misc) ( Thread* thr, const HChar* errstr )
sewardj8fef6252010-07-29 05:28:02 +0000634{
635 HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
636}
637
sewardjf98e1c02008-10-25 16:22:41 +0000638Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 )
639{
640 XError *xe1, *xe2;
641
642 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
643
644 xe1 = (XError*)VG_(get_error_extra)(e1);
645 xe2 = (XError*)VG_(get_error_extra)(e2);
646 tl_assert(xe1);
647 tl_assert(xe2);
648
649 switch (VG_(get_error_kind)(e1)) {
650 case XE_Race:
651 return xe1->XE.Race.szB == xe2->XE.Race.szB
652 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
653 && (HG_(clo_cmp_race_err_addrs)
654 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
655 : True);
sewardjf98e1c02008-10-25 16:22:41 +0000656 case XE_UnlockUnlocked:
657 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
658 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
659 case XE_UnlockForeign:
660 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
661 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
662 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
663 case XE_UnlockBogus:
664 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
665 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
666 case XE_PthAPIerror:
667 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
668 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
669 xe2->XE.PthAPIerror.fnname)
670 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
671 case XE_LockOrder:
672 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
673 case XE_Misc:
674 return xe1->XE.Misc.thr == xe2->XE.Misc.thr
675 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
676 default:
677 tl_assert(0);
678 }
679
680 /*NOTREACHED*/
681 tl_assert(0);
682}
683
684
sewardj24118492009-07-15 14:50:02 +0000685/*----------------------------------------------------------------*/
686/*--- Error management -- printing ---*/
687/*----------------------------------------------------------------*/
688
689/* Do a printf-style operation on either the XML or normal output
690 channel, depending on the setting of VG_(clo_xml).
691*/
florian6bf37262012-10-21 03:23:36 +0000692static void emit_WRK ( const HChar* format, va_list vargs )
sewardj24118492009-07-15 14:50:02 +0000693{
694 if (VG_(clo_xml)) {
695 VG_(vprintf_xml)(format, vargs);
696 } else {
697 VG_(vmessage)(Vg_UserMsg, format, vargs);
698 }
699}
florian6bf37262012-10-21 03:23:36 +0000700static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
701static void emit ( const HChar* format, ... )
sewardj24118492009-07-15 14:50:02 +0000702{
703 va_list vargs;
704 va_start(vargs, format);
705 emit_WRK(format, vargs);
706 va_end(vargs);
707}
sewardj24118492009-07-15 14:50:02 +0000708
709
sewardjf98e1c02008-10-25 16:22:41 +0000710/* Announce (that is, print the point-of-creation) of 'thr'. Only do
711 this once, as we only want to see these announcements once per
sewardj24118492009-07-15 14:50:02 +0000712 thread. Returned Bool indicates whether or not an announcement was
713 made.
714*/
715static Bool announce_one_thread ( Thread* thr )
sewardjf98e1c02008-10-25 16:22:41 +0000716{
717 tl_assert(HG_(is_sane_Thread)(thr));
718 tl_assert(thr->errmsg_index >= 1);
sewardj24118492009-07-15 14:50:02 +0000719 if (thr->announced)
720 return False;
721
722 if (VG_(clo_xml)) {
723
724 VG_(printf_xml)("<announcethread>\n");
sewardj11b5c6d2009-09-03 10:29:57 +0000725 VG_(printf_xml)(" <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
sewardjf98e1c02008-10-25 16:22:41 +0000726 if (thr->errmsg_index == 1) {
727 tl_assert(thr->created_at == NULL);
sewardj24118492009-07-15 14:50:02 +0000728 VG_(printf_xml)(" <isrootthread></isrootthread>\n");
sewardjf98e1c02008-10-25 16:22:41 +0000729 } else {
730 tl_assert(thr->created_at != NULL);
sewardj24118492009-07-15 14:50:02 +0000731 VG_(pp_ExeContext)( thr->created_at );
732 }
733 VG_(printf_xml)("</announcethread>\n\n");
734
735 } else {
736
sewardjffce8152011-06-24 10:09:41 +0000737 VG_(umsg)("---Thread-Announcement----------"
738 "--------------------------------" "\n");
739 VG_(umsg)("\n");
740
sewardj24118492009-07-15 14:50:02 +0000741 if (thr->errmsg_index == 1) {
742 tl_assert(thr->created_at == NULL);
743 VG_(message)(Vg_UserMsg,
744 "Thread #%d is the program's root thread\n",
745 thr->errmsg_index);
746 } else {
747 tl_assert(thr->created_at != NULL);
748 VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
sewardjf98e1c02008-10-25 16:22:41 +0000749 thr->errmsg_index);
750 VG_(pp_ExeContext)( thr->created_at );
751 }
sewardj24118492009-07-15 14:50:02 +0000752 VG_(message)(Vg_UserMsg, "\n");
753
754 }
755
756 thr->announced = True;
757 return True;
758}
759
sewardjffce8152011-06-24 10:09:41 +0000760/* Announce 'lk'. */
761static void announce_LockP ( Lock* lk )
762{
763 tl_assert(lk);
764 if (lk == Lock_INVALID)
765 return; /* Can't be announced -- we know nothing about it. */
766 tl_assert(lk->magic == LockP_MAGIC);
767 if (!lk->appeared_at)
768 return; /* There's nothing we can show */
769
770 if (VG_(clo_xml)) {
771 /* fixme: add announcement */
772 } else {
773 VG_(umsg)( "Lock at %p was first observed\n",
774 (void*)lk->guestaddr );
775 VG_(pp_ExeContext)( lk->appeared_at );
776 VG_(umsg)("\n");
777 }
778}
779
780/* Announce (that is, print point-of-first-observation) for the
781 locks in 'lockvec' and, if non-NULL, 'lockvec2'. */
782static void announce_combined_LockP_vecs ( Lock** lockvec,
783 Lock** lockvec2 )
784{
785 UWord i;
786 tl_assert(lockvec);
787 for (i = 0; lockvec[i]; i++) {
788 announce_LockP(lockvec[i]);
789 }
790 if (lockvec2) {
791 for (i = 0; lockvec2[i]; i++) {
792 Lock* lk = lockvec2[i];
793 if (!elem_LockP_vector(lockvec, lk))
794 announce_LockP(lk);
795 }
796 }
797}
798
799
florian6bd9dc12012-11-23 16:17:43 +0000800static void show_LockP_summary_textmode ( Lock** locks, const HChar* pre )
sewardjffce8152011-06-24 10:09:41 +0000801{
802 tl_assert(locks);
803 UWord i;
804 UWord nLocks = 0, nLocksValid = 0;
805 count_LockP_vector(&nLocks, &nLocksValid, locks);
806 tl_assert(nLocksValid <= nLocks);
807
808 if (nLocks == 0) {
809 VG_(umsg)( "%sLocks held: none", pre );
810 } else {
811 VG_(umsg)( "%sLocks held: %lu, at address%s ",
812 pre, nLocks, nLocksValid == 1 ? "" : "es" );
813 }
814
815 if (nLocks > 0) {
816 for (i = 0; i < nLocks; i++) {
817 if (locks[i] == Lock_INVALID)
818 continue;
819 VG_(umsg)( "%p", (void*)locks[i]->guestaddr);
820 if (locks[i+1] != NULL)
821 VG_(umsg)(" ");
822 }
823 if (nLocksValid < nLocks)
824 VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid);
825 }
826 VG_(umsg)("\n");
827}
828
829
sewardj24118492009-07-15 14:50:02 +0000830/* This is the "this error is due to be printed shortly; so have a
831 look at it any print any preamble you want" function. We use it to
832 announce any previously un-announced threads in the upcoming error
833 message.
834*/
835void HG_(before_pp_Error) ( Error* err )
836{
837 XError* xe;
838 tl_assert(err);
839 xe = (XError*)VG_(get_error_extra)(err);
840 tl_assert(xe);
841
842 switch (VG_(get_error_kind)(err)) {
843 case XE_Misc:
844 announce_one_thread( xe->XE.Misc.thr );
845 break;
846 case XE_LockOrder:
847 announce_one_thread( xe->XE.LockOrder.thr );
848 break;
849 case XE_PthAPIerror:
850 announce_one_thread( xe->XE.PthAPIerror.thr );
851 break;
852 case XE_UnlockBogus:
853 announce_one_thread( xe->XE.UnlockBogus.thr );
854 break;
855 case XE_UnlockForeign:
856 announce_one_thread( xe->XE.UnlockForeign.thr );
857 announce_one_thread( xe->XE.UnlockForeign.owner );
858 break;
859 case XE_UnlockUnlocked:
860 announce_one_thread( xe->XE.UnlockUnlocked.thr );
861 break;
862 case XE_Race:
863 announce_one_thread( xe->XE.Race.thr );
sewardj23f12002009-07-24 08:45:08 +0000864 if (xe->XE.Race.h2_ct)
865 announce_one_thread( xe->XE.Race.h2_ct );
866 if (xe->XE.Race.h1_ct)
867 announce_one_thread( xe->XE.Race.h1_ct );
philippe0c9ac8d2014-07-18 00:03:58 +0000868 if (xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
869 Thread* thr = get_admin_threads();
870 while (thr) {
871 if (thr->errmsg_index
872 == xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
873 announce_one_thread (thr);
874 break;
875 }
876 thr = thr->admin;
877 }
878 }
sewardj24118492009-07-15 14:50:02 +0000879 break;
880 default:
881 tl_assert(0);
sewardjf98e1c02008-10-25 16:22:41 +0000882 }
883}
884
sewardjf98e1c02008-10-25 16:22:41 +0000885void HG_(pp_Error) ( Error* err )
886{
sewardj24118492009-07-15 14:50:02 +0000887 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
888
sewardjffce8152011-06-24 10:09:41 +0000889 if (!xml) {
890 VG_(umsg)("--------------------------------"
891 "--------------------------------" "\n");
892 VG_(umsg)("\n");
893 }
894
sewardjf98e1c02008-10-25 16:22:41 +0000895 XError *xe = (XError*)VG_(get_error_extra)(err);
sewardj24118492009-07-15 14:50:02 +0000896 tl_assert(xe);
sewardjf98e1c02008-10-25 16:22:41 +0000897
bart2fa18d92011-10-04 16:28:42 +0000898 if (xml)
899 emit( " <kind>%s</kind>\n", HG_(get_error_name)(err));
900
sewardjf98e1c02008-10-25 16:22:41 +0000901 switch (VG_(get_error_kind)(err)) {
902
903 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000904 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000905
906 if (xml) {
907
sewardj24118492009-07-15 14:50:02 +0000908 emit( " <xwhat>\n" );
909 emit( " <text>Thread #%d: %s</text>\n",
910 (Int)xe->XE.Misc.thr->errmsg_index,
911 xe->XE.Misc.errstr );
912 emit( " <hthreadid>%d</hthreadid>\n",
913 (Int)xe->XE.Misc.thr->errmsg_index );
914 emit( " </xwhat>\n" );
915 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000916 if (xe->XE.Misc.auxstr) {
917 emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
918 if (xe->XE.Misc.auxctx)
919 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
920 }
sewardj24118492009-07-15 14:50:02 +0000921
922 } else {
923
924 emit( "Thread #%d: %s\n",
925 (Int)xe->XE.Misc.thr->errmsg_index,
926 xe->XE.Misc.errstr );
927 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000928 if (xe->XE.Misc.auxstr) {
929 emit(" %s\n", xe->XE.Misc.auxstr);
930 if (xe->XE.Misc.auxctx)
931 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
932 }
sewardj24118492009-07-15 14:50:02 +0000933
934 }
sewardjf98e1c02008-10-25 16:22:41 +0000935 break;
936 }
937
938 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000939 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000940
941 if (xml) {
942
sewardj24118492009-07-15 14:50:02 +0000943 emit( " <xwhat>\n" );
944 emit( " <text>Thread #%d: lock order \"%p before %p\" "
945 "violated</text>\n",
946 (Int)xe->XE.LockOrder.thr->errmsg_index,
sewardjffce8152011-06-24 10:09:41 +0000947 (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
948 (void*)xe->XE.LockOrder.shouldbe_later_ga );
sewardj24118492009-07-15 14:50:02 +0000949 emit( " <hthreadid>%d</hthreadid>\n",
950 (Int)xe->XE.LockOrder.thr->errmsg_index );
951 emit( " </xwhat>\n" );
952 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +0000953 if (xe->XE.LockOrder.shouldbe_earlier_ec
954 && xe->XE.LockOrder.shouldbe_later_ec) {
sewardj24118492009-07-15 14:50:02 +0000955 emit( " <auxwhat>Required order was established by "
956 "acquisition of lock at %p</auxwhat>\n",
sewardjffce8152011-06-24 10:09:41 +0000957 (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
958 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
sewardj24118492009-07-15 14:50:02 +0000959 emit( " <auxwhat>followed by a later acquisition "
960 "of lock at %p</auxwhat>\n",
sewardjffce8152011-06-24 10:09:41 +0000961 (void*)xe->XE.LockOrder.shouldbe_later_ga );
962 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +0000963 }
964
965 } else {
966
967 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
968 (Int)xe->XE.LockOrder.thr->errmsg_index,
sewardjffce8152011-06-24 10:09:41 +0000969 (void*)xe->XE.LockOrder.shouldbe_earlier_ga,
970 (void*)xe->XE.LockOrder.shouldbe_later_ga );
971 emit( "\n" );
972 emit( "Observed (incorrect) order is: "
973 "acquisition of lock at %p\n",
974 (void*)xe->XE.LockOrder.shouldbe_later_ga);
975 if (xe->XE.LockOrder.actual_earlier_ec) {
976 VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
977 } else {
978 emit(" (stack unavailable)\n");
979 }
980 emit( "\n" );
981 emit(" followed by a later acquisition of lock at %p\n",
982 (void*)xe->XE.LockOrder.shouldbe_earlier_ga);
sewardj24118492009-07-15 14:50:02 +0000983 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardjffce8152011-06-24 10:09:41 +0000984 if (xe->XE.LockOrder.shouldbe_earlier_ec
985 && xe->XE.LockOrder.shouldbe_later_ec) {
986 emit("\n");
987 emit( "Required order was established by "
sewardj24118492009-07-15 14:50:02 +0000988 "acquisition of lock at %p\n",
sewardjffce8152011-06-24 10:09:41 +0000989 (void*)xe->XE.LockOrder.shouldbe_earlier_ga );
990 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
991 emit( "\n" );
992 emit( " followed by a later acquisition of lock at %p\n",
993 (void*)xe->XE.LockOrder.shouldbe_later_ga );
994 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
sewardj24118492009-07-15 14:50:02 +0000995 }
996
sewardjf98e1c02008-10-25 16:22:41 +0000997 }
sewardj24118492009-07-15 14:50:02 +0000998
sewardjf98e1c02008-10-25 16:22:41 +0000999 break;
1000 }
1001
1002 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +00001003 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +00001004
1005 if (xml) {
1006
sewardj24118492009-07-15 14:50:02 +00001007 emit( " <xwhat>\n" );
bartb3af9cf2011-10-06 19:08:37 +00001008 emit(
1009 " <text>Thread #%d's call to %pS failed</text>\n",
sewardj24118492009-07-15 14:50:02 +00001010 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1011 xe->XE.PthAPIerror.fnname );
1012 emit( " <hthreadid>%d</hthreadid>\n",
1013 (Int)xe->XE.PthAPIerror.thr->errmsg_index );
1014 emit( " </xwhat>\n" );
1015 emit( " <what>with error code %ld (%s)</what>\n",
1016 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1017 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1018
1019 } else {
1020
bartb3af9cf2011-10-06 19:08:37 +00001021 emit( "Thread #%d's call to %pS failed\n",
sewardj24118492009-07-15 14:50:02 +00001022 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
1023 xe->XE.PthAPIerror.fnname );
1024 emit( " with error code %ld (%s)\n",
1025 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
1026 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1027
1028 }
1029
sewardjf98e1c02008-10-25 16:22:41 +00001030 break;
1031 }
1032
1033 case XE_UnlockBogus: {
sewardjf98e1c02008-10-25 16:22:41 +00001034 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
sewardj24118492009-07-15 14:50:02 +00001035
1036 if (xml) {
1037
sewardj24118492009-07-15 14:50:02 +00001038 emit( " <xwhat>\n" );
1039 emit( " <text>Thread #%d unlocked an invalid "
1040 "lock at %p</text>\n",
1041 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1042 (void*)xe->XE.UnlockBogus.lock_ga );
1043 emit( " <hthreadid>%d</hthreadid>\n",
1044 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
1045 emit( " </xwhat>\n" );
1046 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1047
1048 } else {
1049
1050 emit( "Thread #%d unlocked an invalid lock at %p\n",
1051 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
1052 (void*)xe->XE.UnlockBogus.lock_ga );
1053 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1054
1055 }
1056
sewardjf98e1c02008-10-25 16:22:41 +00001057 break;
1058 }
1059
1060 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +00001061 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
1062 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
1063 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +00001064
1065 if (xml) {
1066
sewardj24118492009-07-15 14:50:02 +00001067 emit( " <xwhat>\n" );
1068 emit( " <text>Thread #%d unlocked lock at %p "
1069 "currently held by thread #%d</text>\n",
1070 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1071 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1072 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1073 emit( " <hthreadid>%d</hthreadid>\n",
1074 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
1075 emit( " <hthreadid>%d</hthreadid>\n",
1076 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1077 emit( " </xwhat>\n" );
1078 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1079
1080 if (xe->XE.UnlockForeign.lock->appeared_at) {
1081 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
1082 (void*)xe->XE.UnlockForeign.lock->guestaddr );
1083 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
1084 }
1085
1086 } else {
1087
1088 emit( "Thread #%d unlocked lock at %p "
1089 "currently held by thread #%d\n",
1090 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
1091 (void*)xe->XE.UnlockForeign.lock->guestaddr,
1092 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
1093 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1094 if (xe->XE.UnlockForeign.lock->appeared_at) {
1095 emit( " Lock at %p was first observed\n",
1096 (void*)xe->XE.UnlockForeign.lock->guestaddr );
1097 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
1098 }
1099
sewardjf98e1c02008-10-25 16:22:41 +00001100 }
sewardj24118492009-07-15 14:50:02 +00001101
sewardjf98e1c02008-10-25 16:22:41 +00001102 break;
1103 }
1104
1105 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +00001106 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
1107 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +00001108
sewardj24118492009-07-15 14:50:02 +00001109 if (xml) {
1110
sewardj24118492009-07-15 14:50:02 +00001111 emit( " <xwhat>\n" );
1112 emit( " <text>Thread #%d unlocked a "
1113 "not-locked lock at %p</text>\n",
1114 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1115 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1116 emit( " <hthreadid>%d</hthreadid>\n",
1117 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
1118 emit( " </xwhat>\n" );
1119 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1120 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
1121 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
1122 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1123 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
1124 }
1125
1126 } else {
1127
1128 emit( "Thread #%d unlocked a not-locked lock at %p\n",
1129 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
1130 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1131 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1132 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
1133 emit( " Lock at %p was first observed\n",
1134 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
1135 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
1136 }
1137
sewardjf98e1c02008-10-25 16:22:41 +00001138 }
sewardj24118492009-07-15 14:50:02 +00001139
sewardjf98e1c02008-10-25 16:22:41 +00001140 break;
1141 }
1142
1143 case XE_Race: {
1144 Addr err_ga;
florian6bf37262012-10-21 03:23:36 +00001145 const HChar* what;
sewardjf98e1c02008-10-25 16:22:41 +00001146 Int szB;
1147 what = xe->XE.Race.isWrite ? "write" : "read";
1148 szB = xe->XE.Race.szB;
1149 err_ga = VG_(get_error_address)(err);
1150
sewardj24118492009-07-15 14:50:02 +00001151 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardj23f12002009-07-24 08:45:08 +00001152 if (xe->XE.Race.h2_ct)
1153 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
sewardj24118492009-07-15 14:50:02 +00001154
1155 if (xml) {
1156
1157 /* ------ XML ------ */
sewardj24118492009-07-15 14:50:02 +00001158 emit( " <xwhat>\n" );
1159 emit( " <text>Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001160 "at %p by thread #%d</text>\n",
1161 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
sewardj24118492009-07-15 14:50:02 +00001162 emit( " <hthreadid>%d</hthreadid>\n",
1163 (Int)xe->XE.Race.thr->errmsg_index );
1164 emit( " </xwhat>\n" );
1165 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1166
sewardj23f12002009-07-24 08:45:08 +00001167 if (xe->XE.Race.h2_ct) {
1168 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1169 emit( " <xauxwhat>\n");
1170 emit( " <text>This conflicts with a previous %s of size %d "
1171 "by thread #%d</text>\n",
1172 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1173 xe->XE.Race.h2_ct_accSzB,
1174 xe->XE.Race.h2_ct->errmsg_index );
1175 emit( " <hthreadid>%d</hthreadid>\n",
1176 xe->XE.Race.h2_ct->errmsg_index);
1177 emit(" </xauxwhat>\n");
1178 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1179 }
1180
1181 if (xe->XE.Race.h1_ct) {
1182 emit( " <xauxwhat>\n");
1183 emit( " <text>This conflicts with a previous access "
1184 "by thread #%d, after</text>\n",
1185 xe->XE.Race.h1_ct->errmsg_index );
1186 emit( " <hthreadid>%d</hthreadid>\n",
1187 xe->XE.Race.h1_ct->errmsg_index );
1188 emit(" </xauxwhat>\n");
1189 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1190 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001191 } else {
sewardj23f12002009-07-24 08:45:08 +00001192 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" );
sewardj24118492009-07-15 14:50:02 +00001193 }
sewardj23f12002009-07-24 08:45:08 +00001194 emit( " <auxwhat>but before</auxwhat>\n" );
1195 if (xe->XE.Race.h1_ct_mbsegendEC) {
1196 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1197 } else {
1198 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" );
1199 }
sewardjf98e1c02008-10-25 16:22:41 +00001200 }
sewardj24118492009-07-15 14:50:02 +00001201
1202 } else {
1203
1204 /* ------ Text ------ */
sewardjffce8152011-06-24 10:09:41 +00001205 announce_combined_LockP_vecs( xe->XE.Race.locksHeldW,
1206 xe->XE.Race.h2_ct_locksHeldW );
1207
sewardj24118492009-07-15 14:50:02 +00001208 emit( "Possible data race during %s of size %d "
sewardjffce8152011-06-24 10:09:41 +00001209 "at %p by thread #%d\n",
1210 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1211
1212 tl_assert(xe->XE.Race.locksHeldW);
1213 show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" );
sewardj24118492009-07-15 14:50:02 +00001214 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj23f12002009-07-24 08:45:08 +00001215
1216 if (xe->XE.Race.h2_ct) {
1217 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
sewardjffce8152011-06-24 10:09:41 +00001218 tl_assert(xe->XE.Race.h2_ct_locksHeldW);
1219 emit( "\n" );
1220 emit( "This conflicts with a previous %s of size %d "
sewardj23f12002009-07-24 08:45:08 +00001221 "by thread #%d\n",
1222 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1223 xe->XE.Race.h2_ct_accSzB,
1224 xe->XE.Race.h2_ct->errmsg_index );
sewardjffce8152011-06-24 10:09:41 +00001225 show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" );
sewardj23f12002009-07-24 08:45:08 +00001226 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1227 }
1228
1229 if (xe->XE.Race.h1_ct) {
1230 emit( " This conflicts with a previous access by thread #%d, "
1231 "after\n",
1232 xe->XE.Race.h1_ct->errmsg_index );
1233 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1234 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001235 } else {
sewardj23f12002009-07-24 08:45:08 +00001236 emit( " (the start of the thread)\n" );
sewardj24118492009-07-15 14:50:02 +00001237 }
sewardj23f12002009-07-24 08:45:08 +00001238 emit( " but before\n" );
1239 if (xe->XE.Race.h1_ct_mbsegendEC) {
1240 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1241 } else {
1242 emit( " (the end of the the thread)\n" );
1243 }
sewardj24118492009-07-15 14:50:02 +00001244 }
1245
sewardjf98e1c02008-10-25 16:22:41 +00001246 }
philippe07c08522014-05-14 20:39:27 +00001247 VG_(pp_addrinfo) (err_ga, &xe->XE.Race.data_addrinfo);
sewardjf98e1c02008-10-25 16:22:41 +00001248 break; /* case XE_Race */
1249 } /* case XE_Race */
1250
1251 default:
1252 tl_assert(0);
1253 } /* switch (VG_(get_error_kind)(err)) */
1254}
1255
floriane543f302012-10-21 19:43:43 +00001256const HChar* HG_(get_error_name) ( Error* err )
sewardjf98e1c02008-10-25 16:22:41 +00001257{
1258 switch (VG_(get_error_kind)(err)) {
1259 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +00001260 case XE_UnlockUnlocked: return "UnlockUnlocked";
1261 case XE_UnlockForeign: return "UnlockForeign";
1262 case XE_UnlockBogus: return "UnlockBogus";
1263 case XE_PthAPIerror: return "PthAPIerror";
1264 case XE_LockOrder: return "LockOrder";
1265 case XE_Misc: return "Misc";
1266 default: tl_assert(0); /* fill in missing case */
1267 }
1268}
1269
florian19f91bb2012-11-10 22:29:54 +00001270Bool HG_(recognised_suppression) ( const HChar* name, Supp *su )
sewardjf98e1c02008-10-25 16:22:41 +00001271{
1272# define TRY(_name,_xskind) \
1273 if (0 == VG_(strcmp)(name, (_name))) { \
1274 VG_(set_supp_kind)(su, (_xskind)); \
1275 return True; \
1276 }
1277 TRY("Race", XS_Race);
1278 TRY("FreeMemLock", XS_FreeMemLock);
1279 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1280 TRY("UnlockForeign", XS_UnlockForeign);
1281 TRY("UnlockBogus", XS_UnlockBogus);
1282 TRY("PthAPIerror", XS_PthAPIerror);
1283 TRY("LockOrder", XS_LockOrder);
1284 TRY("Misc", XS_Misc);
1285 return False;
1286# undef TRY
1287}
1288
florian19f91bb2012-11-10 22:29:54 +00001289Bool HG_(read_extra_suppression_info) ( Int fd, HChar** bufpp, SizeT* nBufp,
philippe362441d2013-07-22 22:00:13 +00001290 Int* lineno, Supp* su )
sewardjf98e1c02008-10-25 16:22:41 +00001291{
1292 /* do nothing -- no extra suppression info present. Return True to
1293 indicate nothing bad happened. */
1294 return True;
1295}
1296
1297Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
1298{
1299 switch (VG_(get_supp_kind)(su)) {
1300 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001301 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1302 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1303 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1304 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1305 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1306 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1307 //case XS_: return VG_(get_error_kind)(err) == XE_;
1308 default: tl_assert(0); /* fill in missing cases */
1309 }
1310}
1311
sewardj588adef2009-08-15 22:41:51 +00001312Bool HG_(get_extra_suppression_info) ( Error* err,
floriandbb35842012-10-27 18:39:11 +00001313 /*OUT*/HChar* buf, Int nBuf )
sewardjf98e1c02008-10-25 16:22:41 +00001314{
1315 /* Do nothing */
sewardj588adef2009-08-15 22:41:51 +00001316 return False;
sewardjf98e1c02008-10-25 16:22:41 +00001317}
1318
philippe4e32d672013-10-17 22:10:41 +00001319Bool HG_(print_extra_suppression_use) ( Supp* su,
1320 /*OUT*/HChar* buf, Int nBuf )
1321{
1322 /* Do nothing */
1323 return False;
1324}
1325
1326void HG_(update_extra_suppression_use) ( Error* err, Supp* su )
1327{
1328 /* Do nothing */
1329 return;
1330}
1331
sewardjf98e1c02008-10-25 16:22:41 +00001332
1333/*--------------------------------------------------------------------*/
1334/*--- end hg_errors.c ---*/
1335/*--------------------------------------------------------------------*/