blob: 6bc9482cc8c01924b5a0852356e289173f714f1a [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
113static Lock* mk_LockP_from_LockN ( Lock* lkn )
114{
115 Lock* lkp = NULL;
116 HG_(stats__LockN_to_P_queries)++;
117 tl_assert( HG_(is_sane_LockN)(lkn) );
118 if (!map_LockN_to_P) {
119 map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1",
120 HG_(free), lock_unique_cmp );
121 tl_assert(map_LockN_to_P);
122 }
123 if (!VG_(lookupFM)( map_LockN_to_P, NULL, (Word*)&lkp, (Word)lkn)) {
124 lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
125 *lkp = *lkn;
sewardj1d7c3322011-02-28 09:22:51 +0000126 lkp->admin_next = NULL;
127 lkp->admin_prev = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000128 lkp->magic = LockP_MAGIC;
129 /* Forget about the bag of lock holders - don't copy that.
130 Also, acquired_at should be NULL whenever heldBy is, and vice
131 versa. Also forget about the associated libhb synch object. */
132 lkp->heldW = False;
133 lkp->heldBy = NULL;
134 lkp->acquired_at = NULL;
135 lkp->hbso = NULL;
136 VG_(addToFM)( map_LockN_to_P, (Word)lkp, (Word)lkp );
137 }
138 tl_assert( HG_(is_sane_LockP)(lkp) );
139 return lkp;
140}
141
142/* Errors:
143
144 race: program counter
145 read or write
146 data size
147 previous state
148 current state
149
150 FIXME: how does state printing interact with lockset gc?
151 Are the locksets in prev/curr state always valid?
152 Ditto question for the threadsets
153 ThreadSets - probably are always valid if Threads
154 are never thrown away.
155 LockSets - could at least print the lockset elements that
156 correspond to actual locks at the time of printing. Hmm.
157*/
158
159/* Error kinds */
160typedef
161 enum {
162 XE_Race=1101, // race
sewardjf98e1c02008-10-25 16:22:41 +0000163 XE_UnlockUnlocked, // unlocking a not-locked lock
164 XE_UnlockForeign, // unlocking a lock held by some other thread
165 XE_UnlockBogus, // unlocking an address not known to be a lock
166 XE_PthAPIerror, // error from the POSIX pthreads API
167 XE_LockOrder, // lock order error
168 XE_Misc // misc other error (w/ string to describe it)
169 }
170 XErrorTag;
171
172/* Extra contexts for kinds */
173typedef
174 struct {
175 XErrorTag tag;
176 union {
177 struct {
sewardj23f12002009-07-24 08:45:08 +0000178 Addr data_addr;
179 Int szB;
180 Bool isWrite;
181 Thread* thr;
sewardj095d61e2010-03-11 13:43:18 +0000182 /* descr1/2 provide a description of stack/global locs */
sewardj23f12002009-07-24 08:45:08 +0000183 XArray* descr1; /* XArray* of HChar */
184 XArray* descr2; /* XArray* of HChar */
sewardj095d61e2010-03-11 13:43:18 +0000185 /* halloc/haddr/hszB describe the addr if it is a heap block. */
186 ExeContext* hctxt;
187 Addr haddr;
188 SizeT hszB;
189 /* h1_* and h2_* provide some description of a previously
190 observed access with which we are conflicting. */
sewardj23f12002009-07-24 08:45:08 +0000191 Thread* h1_ct; /* non-NULL means h1 info present */
192 ExeContext* h1_ct_mbsegstartEC;
193 ExeContext* h1_ct_mbsegendEC;
194 Thread* h2_ct; /* non-NULL means h2 info present */
195 ExeContext* h2_ct_accEC;
196 Int h2_ct_accSzB;
197 Bool h2_ct_accIsW;
sewardjf98e1c02008-10-25 16:22:41 +0000198 } Race;
199 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000200 Thread* thr; /* doing the unlocking */
201 Lock* lock; /* lock (that is already unlocked) */
202 } UnlockUnlocked;
203 struct {
204 Thread* thr; /* doing the unlocking */
205 Thread* owner; /* thread that actually holds the lock */
206 Lock* lock; /* lock (that is held by 'owner') */
207 } UnlockForeign;
208 struct {
209 Thread* thr; /* doing the unlocking */
210 Addr lock_ga; /* purported address of the lock */
211 } UnlockBogus;
212 struct {
213 Thread* thr;
214 HChar* fnname; /* persistent, in tool-arena */
215 Word err; /* pth error code */
216 HChar* errstr; /* persistent, in tool-arena */
217 } PthAPIerror;
218 struct {
219 Thread* thr;
220 Addr before_ga; /* always locked first in prog. history */
221 Addr after_ga;
222 ExeContext* before_ec;
223 ExeContext* after_ec;
224 } LockOrder;
225 struct {
sewardj8fef6252010-07-29 05:28:02 +0000226 Thread* thr;
227 HChar* errstr; /* persistent, in tool-arena */
228 HChar* auxstr; /* optional, persistent, in tool-arena */
229 ExeContext* auxctx; /* optional */
sewardjf98e1c02008-10-25 16:22:41 +0000230 } Misc;
231 } XE;
232 }
233 XError;
234
235static void init_XError ( XError* xe ) {
236 VG_(memset)(xe, 0, sizeof(*xe) );
237 xe->tag = XE_Race-1; /* bogus */
238}
239
240
241/* Extensions of suppressions */
242typedef
243 enum {
244 XS_Race=1201, /* race */
245 XS_FreeMemLock,
246 XS_UnlockUnlocked,
247 XS_UnlockForeign,
248 XS_UnlockBogus,
249 XS_PthAPIerror,
250 XS_LockOrder,
251 XS_Misc
252 }
253 XSuppTag;
254
255
256/* Updates the copy with address info if necessary. */
257UInt HG_(update_extra) ( Error* err )
258{
259 XError* xe = (XError*)VG_(get_error_extra)(err);
260 tl_assert(xe);
261 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
262 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
263 //}
264
265 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000266
sewardjf98e1c02008-10-25 16:22:41 +0000267 /* See if we can come up with a source level description of the
268 raced-upon address. This is potentially expensive, which is
269 why it's only done at the update_extra point, not when the
270 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000271 static Int xxx = 0;
272 xxx++;
273 if (0)
274 VG_(printf)("HG_(update_extra): "
275 "%d conflicting-event queries\n", xxx);
sewardj095d61e2010-03-11 13:43:18 +0000276
277 tl_assert(!xe->XE.Race.hctxt);
sewardj24118492009-07-15 14:50:02 +0000278 tl_assert(!xe->XE.Race.descr1);
279 tl_assert(!xe->XE.Race.descr2);
280
sewardj095d61e2010-03-11 13:43:18 +0000281 /* First, see if it's in any heap block. Unfortunately this
sewardjc8028ad2010-05-05 09:34:42 +0000282 means a linear search through all allocated heap blocks. The
283 assertion says that if it's detected as a heap block, then we
284 must have an allocation context for it, since all heap blocks
285 should have an allocation context. */
286 Bool is_heapblock
287 = HG_(mm_find_containing_block)(
288 &xe->XE.Race.hctxt, &xe->XE.Race.haddr, &xe->XE.Race.hszB,
289 xe->XE.Race.data_addr
290 );
291 tl_assert(is_heapblock == (xe->XE.Race.hctxt != NULL));
sewardj24118492009-07-15 14:50:02 +0000292
sewardj095d61e2010-03-11 13:43:18 +0000293 if (!xe->XE.Race.hctxt) {
294 /* It's not in any heap block. See if we can map it to a
295 stack or global symbol. */
sewardj24118492009-07-15 14:50:02 +0000296
sewardj095d61e2010-03-11 13:43:18 +0000297 xe->XE.Race.descr1
298 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr1",
299 HG_(free), sizeof(HChar) );
300 xe->XE.Race.descr2
301 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr2",
302 HG_(free), sizeof(HChar) );
303
304 (void) VG_(get_data_description)( xe->XE.Race.descr1,
305 xe->XE.Race.descr2,
306 xe->XE.Race.data_addr );
307
308 /* If there's nothing in descr1/2, free it. Why is it safe to
309 to VG_(indexXA) at zero here? Because
310 VG_(get_data_description) guarantees to zero terminate
311 descr1/2 regardless of the outcome of the call. So there's
312 always at least one element in each XA after the call.
313 */
314 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr1, 0 ))) {
315 VG_(deleteXA)( xe->XE.Race.descr1 );
316 xe->XE.Race.descr1 = NULL;
317 }
318 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr2, 0 ))) {
319 VG_(deleteXA)( xe->XE.Race.descr2 );
320 xe->XE.Race.descr2 = NULL;
321 }
sewardj24118492009-07-15 14:50:02 +0000322 }
323
324 /* And poke around in the conflicting-event map, to see if we
325 can rustle up a plausible-looking conflicting memory access
326 to show. */
sewardj23f12002009-07-24 08:45:08 +0000327 if (HG_(clo_history_level) >= 2) {
328 Thr* thrp = NULL;
329 ExeContext* wherep = NULL;
330 Addr acc_addr = xe->XE.Race.data_addr;
331 Int acc_szB = xe->XE.Race.szB;
332 Thr* acc_thr = xe->XE.Race.thr->hbthr;
333 Bool acc_isW = xe->XE.Race.isWrite;
334 SizeT conf_szB = 0;
335 Bool conf_isW = False;
336 tl_assert(!xe->XE.Race.h2_ct_accEC);
337 tl_assert(!xe->XE.Race.h2_ct);
338 if (libhb_event_map_lookup(
339 &wherep, &thrp, &conf_szB, &conf_isW,
340 acc_thr, acc_addr, acc_szB, acc_isW )) {
341 Thread* threadp;
342 tl_assert(wherep);
343 tl_assert(thrp);
344 threadp = libhb_get_Thr_opaque( thrp );
345 tl_assert(threadp);
346 xe->XE.Race.h2_ct_accEC = wherep;
347 xe->XE.Race.h2_ct = threadp;
348 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
349 xe->XE.Race.h2_ct_accIsW = conf_isW;
sewardjc5ea9962008-12-07 01:41:46 +0000350 }
351 }
sewardj23f12002009-07-24 08:45:08 +0000352
353 // both NULL or both non-NULL
354 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
sewardjf98e1c02008-10-25 16:22:41 +0000355 }
356
357 return sizeof(XError);
358}
359
360void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000361 Addr data_addr, Int szB, Bool isWrite,
sewardj23f12002009-07-24 08:45:08 +0000362 Thread* h1_ct,
363 ExeContext* h1_ct_segstart,
364 ExeContext* h1_ct_mbsegendEC )
sewardjf98e1c02008-10-25 16:22:41 +0000365{
366 XError xe;
367 tl_assert( HG_(is_sane_Thread)(thr) );
368
369# if defined(VGO_linux)
370 /* Skip any races on locations apparently in GOTPLT sections. This
371 is said to be caused by ld.so poking PLT table entries (or
372 whatever) when it writes the resolved address of a dynamically
373 linked routine, into the table (or whatever) when it is called
374 for the first time. */
375 {
sewardje3f1e592009-07-31 09:41:29 +0000376 VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr );
sewardjf98e1c02008-10-25 16:22:41 +0000377 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
378 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000379 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000380 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000381 /* SectPLT is required on ppc32/64-linux */
382 if (sect == Vg_SectPLT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000383 }
384# endif
385
386 init_XError(&xe);
387 xe.tag = XE_Race;
388 xe.XE.Race.data_addr = data_addr;
389 xe.XE.Race.szB = szB;
390 xe.XE.Race.isWrite = isWrite;
sewardjf98e1c02008-10-25 16:22:41 +0000391 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000392 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000393 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000394 /* Skip on the detailed description of the raced-on address at this
395 point; it's expensive. Leave it for the update_extra function
396 if we ever make it that far. */
397 tl_assert(xe.XE.Race.descr1 == NULL);
398 tl_assert(xe.XE.Race.descr2 == NULL);
sewardjf98e1c02008-10-25 16:22:41 +0000399 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000400 // Skip on any of the conflicting-access info at this point.
401 // It's expensive to obtain, and this error is more likely than
402 // not to be discarded. We'll fill these fields in in
403 // HG_(update_extra) just above, assuming the error ever makes
404 // it that far (unlikely).
sewardj23f12002009-07-24 08:45:08 +0000405 xe.XE.Race.h2_ct_accSzB = 0;
406 xe.XE.Race.h2_ct_accIsW = False;
407 xe.XE.Race.h2_ct_accEC = NULL;
408 xe.XE.Race.h2_ct = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000409 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
410 tl_assert( thr->coretid != VG_INVALID_THREADID );
sewardj23f12002009-07-24 08:45:08 +0000411
412 xe.XE.Race.h1_ct = h1_ct;
413 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
414 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC;
415
sewardjf98e1c02008-10-25 16:22:41 +0000416 VG_(maybe_record_error)( thr->coretid,
417 XE_Race, data_addr, NULL, &xe );
418}
419
sewardjf98e1c02008-10-25 16:22:41 +0000420void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
421{
422 XError xe;
423 tl_assert( HG_(is_sane_Thread)(thr) );
424 tl_assert( HG_(is_sane_LockN)(lk) );
425 init_XError(&xe);
426 xe.tag = XE_UnlockUnlocked;
427 xe.XE.UnlockUnlocked.thr = thr;
428 xe.XE.UnlockUnlocked.lock = mk_LockP_from_LockN(lk);
429 // FIXME: tid vs thr
430 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
431 tl_assert( thr->coretid != VG_INVALID_THREADID );
432 VG_(maybe_record_error)( thr->coretid,
433 XE_UnlockUnlocked, 0, NULL, &xe );
434}
435
436void HG_(record_error_UnlockForeign) ( Thread* thr,
437 Thread* owner, Lock* lk )
438{
439 XError xe;
440 tl_assert( HG_(is_sane_Thread)(thr) );
441 tl_assert( HG_(is_sane_Thread)(owner) );
442 tl_assert( HG_(is_sane_LockN)(lk) );
443 init_XError(&xe);
444 xe.tag = XE_UnlockForeign;
445 xe.XE.UnlockForeign.thr = thr;
446 xe.XE.UnlockForeign.owner = owner;
447 xe.XE.UnlockForeign.lock = mk_LockP_from_LockN(lk);
448 // FIXME: tid vs thr
449 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
450 tl_assert( thr->coretid != VG_INVALID_THREADID );
451 VG_(maybe_record_error)( thr->coretid,
452 XE_UnlockForeign, 0, NULL, &xe );
453}
454
455void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
456{
457 XError xe;
458 tl_assert( HG_(is_sane_Thread)(thr) );
459 init_XError(&xe);
460 xe.tag = XE_UnlockBogus;
461 xe.XE.UnlockBogus.thr = thr;
462 xe.XE.UnlockBogus.lock_ga = lock_ga;
463 // FIXME: tid vs thr
464 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
465 tl_assert( thr->coretid != VG_INVALID_THREADID );
466 VG_(maybe_record_error)( thr->coretid,
467 XE_UnlockBogus, 0, NULL, &xe );
468}
469
470void HG_(record_error_LockOrder)(
471 Thread* thr, Addr before_ga, Addr after_ga,
472 ExeContext* before_ec, ExeContext* after_ec
473 )
474{
475 XError xe;
476 tl_assert( HG_(is_sane_Thread)(thr) );
sewardjc1fb9d22011-02-28 09:03:44 +0000477 tl_assert(HG_(clo_track_lockorders));
sewardjf98e1c02008-10-25 16:22:41 +0000478 init_XError(&xe);
479 xe.tag = XE_LockOrder;
480 xe.XE.LockOrder.thr = thr;
481 xe.XE.LockOrder.before_ga = before_ga;
482 xe.XE.LockOrder.before_ec = before_ec;
483 xe.XE.LockOrder.after_ga = after_ga;
484 xe.XE.LockOrder.after_ec = after_ec;
485 // FIXME: tid vs thr
486 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
487 tl_assert( thr->coretid != VG_INVALID_THREADID );
488 VG_(maybe_record_error)( thr->coretid,
489 XE_LockOrder, 0, NULL, &xe );
490}
491
492void HG_(record_error_PthAPIerror) ( Thread* thr, HChar* fnname,
493 Word err, HChar* errstr )
494{
495 XError xe;
496 tl_assert( HG_(is_sane_Thread)(thr) );
497 tl_assert(fnname);
498 tl_assert(errstr);
499 init_XError(&xe);
500 xe.tag = XE_PthAPIerror;
501 xe.XE.PthAPIerror.thr = thr;
502 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
503 xe.XE.PthAPIerror.err = err;
504 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
505 // FIXME: tid vs thr
506 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
507 tl_assert( thr->coretid != VG_INVALID_THREADID );
508 VG_(maybe_record_error)( thr->coretid,
509 XE_PthAPIerror, 0, NULL, &xe );
510}
511
sewardj8fef6252010-07-29 05:28:02 +0000512void HG_(record_error_Misc_w_aux) ( Thread* thr, HChar* errstr,
513 HChar* auxstr, ExeContext* auxctx )
sewardjf98e1c02008-10-25 16:22:41 +0000514{
515 XError xe;
516 tl_assert( HG_(is_sane_Thread)(thr) );
517 tl_assert(errstr);
518 init_XError(&xe);
519 xe.tag = XE_Misc;
520 xe.XE.Misc.thr = thr;
521 xe.XE.Misc.errstr = string_table_strdup(errstr);
sewardj8fef6252010-07-29 05:28:02 +0000522 xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
523 xe.XE.Misc.auxctx = auxctx;
sewardjf98e1c02008-10-25 16:22:41 +0000524 // FIXME: tid vs thr
525 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
526 tl_assert( thr->coretid != VG_INVALID_THREADID );
527 VG_(maybe_record_error)( thr->coretid,
528 XE_Misc, 0, NULL, &xe );
529}
530
sewardj8fef6252010-07-29 05:28:02 +0000531void HG_(record_error_Misc) ( Thread* thr, HChar* errstr )
532{
533 HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
534}
535
sewardjf98e1c02008-10-25 16:22:41 +0000536Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 )
537{
538 XError *xe1, *xe2;
539
540 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
541
542 xe1 = (XError*)VG_(get_error_extra)(e1);
543 xe2 = (XError*)VG_(get_error_extra)(e2);
544 tl_assert(xe1);
545 tl_assert(xe2);
546
547 switch (VG_(get_error_kind)(e1)) {
548 case XE_Race:
549 return xe1->XE.Race.szB == xe2->XE.Race.szB
550 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
551 && (HG_(clo_cmp_race_err_addrs)
552 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
553 : True);
sewardjf98e1c02008-10-25 16:22:41 +0000554 case XE_UnlockUnlocked:
555 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
556 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
557 case XE_UnlockForeign:
558 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
559 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
560 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
561 case XE_UnlockBogus:
562 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
563 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
564 case XE_PthAPIerror:
565 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
566 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
567 xe2->XE.PthAPIerror.fnname)
568 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
569 case XE_LockOrder:
570 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
571 case XE_Misc:
572 return xe1->XE.Misc.thr == xe2->XE.Misc.thr
573 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
574 default:
575 tl_assert(0);
576 }
577
578 /*NOTREACHED*/
579 tl_assert(0);
580}
581
582
sewardj24118492009-07-15 14:50:02 +0000583/*----------------------------------------------------------------*/
584/*--- Error management -- printing ---*/
585/*----------------------------------------------------------------*/
586
587/* Do a printf-style operation on either the XML or normal output
588 channel, depending on the setting of VG_(clo_xml).
589*/
590static void emit_WRK ( HChar* format, va_list vargs )
591{
592 if (VG_(clo_xml)) {
593 VG_(vprintf_xml)(format, vargs);
594 } else {
595 VG_(vmessage)(Vg_UserMsg, format, vargs);
596 }
597}
598static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
599static void emit ( HChar* format, ... )
600{
601 va_list vargs;
602 va_start(vargs, format);
603 emit_WRK(format, vargs);
604 va_end(vargs);
605}
606static void emit_no_f_c ( HChar* format, ... )
607{
608 va_list vargs;
609 va_start(vargs, format);
610 emit_WRK(format, vargs);
611 va_end(vargs);
612}
613
614
sewardjf98e1c02008-10-25 16:22:41 +0000615/* Announce (that is, print the point-of-creation) of 'thr'. Only do
616 this once, as we only want to see these announcements once per
sewardj24118492009-07-15 14:50:02 +0000617 thread. Returned Bool indicates whether or not an announcement was
618 made.
619*/
620static Bool announce_one_thread ( Thread* thr )
sewardjf98e1c02008-10-25 16:22:41 +0000621{
622 tl_assert(HG_(is_sane_Thread)(thr));
623 tl_assert(thr->errmsg_index >= 1);
sewardj24118492009-07-15 14:50:02 +0000624 if (thr->announced)
625 return False;
626
627 if (VG_(clo_xml)) {
628
629 VG_(printf_xml)("<announcethread>\n");
sewardj11b5c6d2009-09-03 10:29:57 +0000630 VG_(printf_xml)(" <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
sewardjf98e1c02008-10-25 16:22:41 +0000631 if (thr->errmsg_index == 1) {
632 tl_assert(thr->created_at == NULL);
sewardj24118492009-07-15 14:50:02 +0000633 VG_(printf_xml)(" <isrootthread></isrootthread>\n");
sewardjf98e1c02008-10-25 16:22:41 +0000634 } else {
635 tl_assert(thr->created_at != NULL);
sewardj24118492009-07-15 14:50:02 +0000636 VG_(pp_ExeContext)( thr->created_at );
637 }
638 VG_(printf_xml)("</announcethread>\n\n");
639
640 } else {
641
642 if (thr->errmsg_index == 1) {
643 tl_assert(thr->created_at == NULL);
644 VG_(message)(Vg_UserMsg,
645 "Thread #%d is the program's root thread\n",
646 thr->errmsg_index);
647 } else {
648 tl_assert(thr->created_at != NULL);
649 VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
sewardjf98e1c02008-10-25 16:22:41 +0000650 thr->errmsg_index);
651 VG_(pp_ExeContext)( thr->created_at );
652 }
sewardj24118492009-07-15 14:50:02 +0000653 VG_(message)(Vg_UserMsg, "\n");
654
655 }
656
657 thr->announced = True;
658 return True;
659}
660
661
662/* This is the "this error is due to be printed shortly; so have a
663 look at it any print any preamble you want" function. We use it to
664 announce any previously un-announced threads in the upcoming error
665 message.
666*/
667void HG_(before_pp_Error) ( Error* err )
668{
669 XError* xe;
670 tl_assert(err);
671 xe = (XError*)VG_(get_error_extra)(err);
672 tl_assert(xe);
673
674 switch (VG_(get_error_kind)(err)) {
675 case XE_Misc:
676 announce_one_thread( xe->XE.Misc.thr );
677 break;
678 case XE_LockOrder:
679 announce_one_thread( xe->XE.LockOrder.thr );
680 break;
681 case XE_PthAPIerror:
682 announce_one_thread( xe->XE.PthAPIerror.thr );
683 break;
684 case XE_UnlockBogus:
685 announce_one_thread( xe->XE.UnlockBogus.thr );
686 break;
687 case XE_UnlockForeign:
688 announce_one_thread( xe->XE.UnlockForeign.thr );
689 announce_one_thread( xe->XE.UnlockForeign.owner );
690 break;
691 case XE_UnlockUnlocked:
692 announce_one_thread( xe->XE.UnlockUnlocked.thr );
693 break;
694 case XE_Race:
695 announce_one_thread( xe->XE.Race.thr );
sewardj23f12002009-07-24 08:45:08 +0000696 if (xe->XE.Race.h2_ct)
697 announce_one_thread( xe->XE.Race.h2_ct );
698 if (xe->XE.Race.h1_ct)
699 announce_one_thread( xe->XE.Race.h1_ct );
sewardj24118492009-07-15 14:50:02 +0000700 break;
701 default:
702 tl_assert(0);
sewardjf98e1c02008-10-25 16:22:41 +0000703 }
704}
705
sewardjf98e1c02008-10-25 16:22:41 +0000706void HG_(pp_Error) ( Error* err )
707{
sewardj24118492009-07-15 14:50:02 +0000708 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
709
sewardjf98e1c02008-10-25 16:22:41 +0000710 XError *xe = (XError*)VG_(get_error_extra)(err);
sewardj24118492009-07-15 14:50:02 +0000711 tl_assert(xe);
sewardjf98e1c02008-10-25 16:22:41 +0000712
713 switch (VG_(get_error_kind)(err)) {
714
715 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000716 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000717
718 if (xml) {
719
720 emit( " <kind>Misc</kind>\n");
721 emit( " <xwhat>\n" );
722 emit( " <text>Thread #%d: %s</text>\n",
723 (Int)xe->XE.Misc.thr->errmsg_index,
724 xe->XE.Misc.errstr );
725 emit( " <hthreadid>%d</hthreadid>\n",
726 (Int)xe->XE.Misc.thr->errmsg_index );
727 emit( " </xwhat>\n" );
728 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000729 if (xe->XE.Misc.auxstr) {
730 emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
731 if (xe->XE.Misc.auxctx)
732 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
733 }
sewardj24118492009-07-15 14:50:02 +0000734
735 } else {
736
737 emit( "Thread #%d: %s\n",
738 (Int)xe->XE.Misc.thr->errmsg_index,
739 xe->XE.Misc.errstr );
740 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj8fef6252010-07-29 05:28:02 +0000741 if (xe->XE.Misc.auxstr) {
742 emit(" %s\n", xe->XE.Misc.auxstr);
743 if (xe->XE.Misc.auxctx)
744 VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
745 }
sewardj24118492009-07-15 14:50:02 +0000746
747 }
sewardjf98e1c02008-10-25 16:22:41 +0000748 break;
749 }
750
751 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000752 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000753
754 if (xml) {
755
756 emit( " <kind>LockOrder</kind>\n");
757 emit( " <xwhat>\n" );
758 emit( " <text>Thread #%d: lock order \"%p before %p\" "
759 "violated</text>\n",
760 (Int)xe->XE.LockOrder.thr->errmsg_index,
761 (void*)xe->XE.LockOrder.before_ga,
762 (void*)xe->XE.LockOrder.after_ga );
763 emit( " <hthreadid>%d</hthreadid>\n",
764 (Int)xe->XE.LockOrder.thr->errmsg_index );
765 emit( " </xwhat>\n" );
766 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
767 if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
768 emit( " <auxwhat>Required order was established by "
769 "acquisition of lock at %p</auxwhat>\n",
770 (void*)xe->XE.LockOrder.before_ga );
771 VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
772 emit( " <auxwhat>followed by a later acquisition "
773 "of lock at %p</auxwhat>\n",
774 (void*)xe->XE.LockOrder.after_ga );
775 VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
776 }
777
778 } else {
779
780 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
781 (Int)xe->XE.LockOrder.thr->errmsg_index,
782 (void*)xe->XE.LockOrder.before_ga,
783 (void*)xe->XE.LockOrder.after_ga );
784 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
785 if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
786 emit( " Required order was established by "
787 "acquisition of lock at %p\n",
788 (void*)xe->XE.LockOrder.before_ga );
789 VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
790 emit( " followed by a later acquisition of lock at %p\n",
791 (void*)xe->XE.LockOrder.after_ga );
792 VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
793 }
794
sewardjf98e1c02008-10-25 16:22:41 +0000795 }
sewardj24118492009-07-15 14:50:02 +0000796
sewardjf98e1c02008-10-25 16:22:41 +0000797 break;
798 }
799
800 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +0000801 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +0000802
803 if (xml) {
804
805 emit( " <kind>PthAPIerror</kind>\n");
806 emit( " <xwhat>\n" );
807 emit_no_f_c(
808 " <text>Thread #%d's call to %t failed</text>\n",
809 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
810 xe->XE.PthAPIerror.fnname );
811 emit( " <hthreadid>%d</hthreadid>\n",
812 (Int)xe->XE.PthAPIerror.thr->errmsg_index );
813 emit( " </xwhat>\n" );
814 emit( " <what>with error code %ld (%s)</what>\n",
815 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
816 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
817
818 } else {
819
820 emit_no_f_c( "Thread #%d's call to %t failed\n",
821 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
822 xe->XE.PthAPIerror.fnname );
823 emit( " with error code %ld (%s)\n",
824 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
825 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
826
827 }
828
sewardjf98e1c02008-10-25 16:22:41 +0000829 break;
830 }
831
832 case XE_UnlockBogus: {
sewardjf98e1c02008-10-25 16:22:41 +0000833 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
sewardj24118492009-07-15 14:50:02 +0000834
835 if (xml) {
836
837 emit( " <kind>UnlockBogus</kind>\n");
838 emit( " <xwhat>\n" );
839 emit( " <text>Thread #%d unlocked an invalid "
840 "lock at %p</text>\n",
841 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
842 (void*)xe->XE.UnlockBogus.lock_ga );
843 emit( " <hthreadid>%d</hthreadid>\n",
844 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
845 emit( " </xwhat>\n" );
846 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
847
848 } else {
849
850 emit( "Thread #%d unlocked an invalid lock at %p\n",
851 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
852 (void*)xe->XE.UnlockBogus.lock_ga );
853 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
854
855 }
856
sewardjf98e1c02008-10-25 16:22:41 +0000857 break;
858 }
859
860 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +0000861 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
862 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
863 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +0000864
865 if (xml) {
866
867 emit( " <kind>UnlockForeign</kind>\n");
868 emit( " <xwhat>\n" );
869 emit( " <text>Thread #%d unlocked lock at %p "
870 "currently held by thread #%d</text>\n",
871 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
872 (void*)xe->XE.UnlockForeign.lock->guestaddr,
873 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
874 emit( " <hthreadid>%d</hthreadid>\n",
875 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
876 emit( " <hthreadid>%d</hthreadid>\n",
877 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
878 emit( " </xwhat>\n" );
879 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
880
881 if (xe->XE.UnlockForeign.lock->appeared_at) {
882 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
883 (void*)xe->XE.UnlockForeign.lock->guestaddr );
884 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
885 }
886
887 } else {
888
889 emit( "Thread #%d unlocked lock at %p "
890 "currently held by thread #%d\n",
891 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
892 (void*)xe->XE.UnlockForeign.lock->guestaddr,
893 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
894 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
895 if (xe->XE.UnlockForeign.lock->appeared_at) {
896 emit( " Lock at %p was first observed\n",
897 (void*)xe->XE.UnlockForeign.lock->guestaddr );
898 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
899 }
900
sewardjf98e1c02008-10-25 16:22:41 +0000901 }
sewardj24118492009-07-15 14:50:02 +0000902
sewardjf98e1c02008-10-25 16:22:41 +0000903 break;
904 }
905
906 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +0000907 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
908 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +0000909
sewardj24118492009-07-15 14:50:02 +0000910 if (xml) {
911
912 emit( " <kind>UnlockUnlocked</kind>\n");
913 emit( " <xwhat>\n" );
914 emit( " <text>Thread #%d unlocked a "
915 "not-locked lock at %p</text>\n",
916 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
917 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
918 emit( " <hthreadid>%d</hthreadid>\n",
919 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
920 emit( " </xwhat>\n" );
921 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
922 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
923 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
924 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
925 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
926 }
927
928 } else {
929
930 emit( "Thread #%d unlocked a not-locked lock at %p\n",
931 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
932 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
933 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
934 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
935 emit( " Lock at %p was first observed\n",
936 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
937 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
938 }
939
sewardjf98e1c02008-10-25 16:22:41 +0000940 }
sewardj24118492009-07-15 14:50:02 +0000941
sewardjf98e1c02008-10-25 16:22:41 +0000942 break;
943 }
944
945 case XE_Race: {
946 Addr err_ga;
947 HChar* what;
948 Int szB;
949 what = xe->XE.Race.isWrite ? "write" : "read";
950 szB = xe->XE.Race.szB;
951 err_ga = VG_(get_error_address)(err);
952
sewardj24118492009-07-15 14:50:02 +0000953 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardj23f12002009-07-24 08:45:08 +0000954 if (xe->XE.Race.h2_ct)
955 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
sewardj24118492009-07-15 14:50:02 +0000956
957 if (xml) {
958
959 /* ------ XML ------ */
960 emit( " <kind>Race</kind>\n" );
961 emit( " <xwhat>\n" );
962 emit( " <text>Possible data race during %s of size %d "
963 "at %#lx by thread #%d</text>\n",
964 what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
965 emit( " <hthreadid>%d</hthreadid>\n",
966 (Int)xe->XE.Race.thr->errmsg_index );
967 emit( " </xwhat>\n" );
968 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
969
sewardj23f12002009-07-24 08:45:08 +0000970 if (xe->XE.Race.h2_ct) {
971 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
972 emit( " <xauxwhat>\n");
973 emit( " <text>This conflicts with a previous %s of size %d "
974 "by thread #%d</text>\n",
975 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
976 xe->XE.Race.h2_ct_accSzB,
977 xe->XE.Race.h2_ct->errmsg_index );
978 emit( " <hthreadid>%d</hthreadid>\n",
979 xe->XE.Race.h2_ct->errmsg_index);
980 emit(" </xauxwhat>\n");
981 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
982 }
983
984 if (xe->XE.Race.h1_ct) {
985 emit( " <xauxwhat>\n");
986 emit( " <text>This conflicts with a previous access "
987 "by thread #%d, after</text>\n",
988 xe->XE.Race.h1_ct->errmsg_index );
989 emit( " <hthreadid>%d</hthreadid>\n",
990 xe->XE.Race.h1_ct->errmsg_index );
991 emit(" </xauxwhat>\n");
992 if (xe->XE.Race.h1_ct_mbsegstartEC) {
993 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +0000994 } else {
sewardj23f12002009-07-24 08:45:08 +0000995 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" );
sewardj24118492009-07-15 14:50:02 +0000996 }
sewardj23f12002009-07-24 08:45:08 +0000997 emit( " <auxwhat>but before</auxwhat>\n" );
998 if (xe->XE.Race.h1_ct_mbsegendEC) {
999 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1000 } else {
1001 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" );
1002 }
sewardjf98e1c02008-10-25 16:22:41 +00001003 }
sewardj24118492009-07-15 14:50:02 +00001004
1005 } else {
1006
1007 /* ------ Text ------ */
1008 emit( "Possible data race during %s of size %d "
1009 "at %#lx by thread #%d\n",
1010 what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1011 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj23f12002009-07-24 08:45:08 +00001012
1013 if (xe->XE.Race.h2_ct) {
1014 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1015 emit( " This conflicts with a previous %s of size %d "
1016 "by thread #%d\n",
1017 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
1018 xe->XE.Race.h2_ct_accSzB,
1019 xe->XE.Race.h2_ct->errmsg_index );
1020 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
1021 }
1022
1023 if (xe->XE.Race.h1_ct) {
1024 emit( " This conflicts with a previous access by thread #%d, "
1025 "after\n",
1026 xe->XE.Race.h1_ct->errmsg_index );
1027 if (xe->XE.Race.h1_ct_mbsegstartEC) {
1028 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +00001029 } else {
sewardj23f12002009-07-24 08:45:08 +00001030 emit( " (the start of the thread)\n" );
sewardj24118492009-07-15 14:50:02 +00001031 }
sewardj23f12002009-07-24 08:45:08 +00001032 emit( " but before\n" );
1033 if (xe->XE.Race.h1_ct_mbsegendEC) {
1034 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
1035 } else {
1036 emit( " (the end of the the thread)\n" );
1037 }
sewardj24118492009-07-15 14:50:02 +00001038 }
1039
sewardjf98e1c02008-10-25 16:22:41 +00001040 }
1041
sewardj095d61e2010-03-11 13:43:18 +00001042 /* If we have a description of the address in terms of a heap
1043 block, show it. */
1044 if (xe->XE.Race.hctxt) {
1045 SizeT delta = err_ga - xe->XE.Race.haddr;
1046 if (xml) {
1047 emit(" <auxwhat>Address %#lx is %ld bytes inside a block "
1048 "of size %ld alloc'd</auxwhat>\n", err_ga, delta,
1049 xe->XE.Race.hszB);
1050 VG_(pp_ExeContext)( xe->XE.Race.hctxt );
1051 } else {
1052 emit(" Address %#lx is %ld bytes inside a block "
1053 "of size %ld alloc'd\n", err_ga, delta,
1054 xe->XE.Race.hszB);
1055 VG_(pp_ExeContext)( xe->XE.Race.hctxt );
1056 }
1057 }
1058
sewardj24118492009-07-15 14:50:02 +00001059 /* If we have a better description of the address, show it.
1060 Note that in XML mode, it will already by nicely wrapped up
1061 in tags, either <auxwhat> or <xauxwhat>, so we can just emit
1062 it verbatim. */
1063 if (xe->XE.Race.descr1)
1064 emit( "%s%s\n", xml ? " " : " ",
1065 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
1066 if (xe->XE.Race.descr2)
1067 emit( "%s%s\n", xml ? " " : " ",
1068 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
sewardjf98e1c02008-10-25 16:22:41 +00001069
1070 break; /* case XE_Race */
1071 } /* case XE_Race */
1072
1073 default:
1074 tl_assert(0);
1075 } /* switch (VG_(get_error_kind)(err)) */
1076}
1077
1078Char* HG_(get_error_name) ( Error* err )
1079{
1080 switch (VG_(get_error_kind)(err)) {
1081 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +00001082 case XE_UnlockUnlocked: return "UnlockUnlocked";
1083 case XE_UnlockForeign: return "UnlockForeign";
1084 case XE_UnlockBogus: return "UnlockBogus";
1085 case XE_PthAPIerror: return "PthAPIerror";
1086 case XE_LockOrder: return "LockOrder";
1087 case XE_Misc: return "Misc";
1088 default: tl_assert(0); /* fill in missing case */
1089 }
1090}
1091
1092Bool HG_(recognised_suppression) ( Char* name, Supp *su )
1093{
1094# define TRY(_name,_xskind) \
1095 if (0 == VG_(strcmp)(name, (_name))) { \
1096 VG_(set_supp_kind)(su, (_xskind)); \
1097 return True; \
1098 }
1099 TRY("Race", XS_Race);
1100 TRY("FreeMemLock", XS_FreeMemLock);
1101 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1102 TRY("UnlockForeign", XS_UnlockForeign);
1103 TRY("UnlockBogus", XS_UnlockBogus);
1104 TRY("PthAPIerror", XS_PthAPIerror);
1105 TRY("LockOrder", XS_LockOrder);
1106 TRY("Misc", XS_Misc);
1107 return False;
1108# undef TRY
1109}
1110
njn35db56c2009-07-24 07:38:29 +00001111Bool HG_(read_extra_suppression_info) ( Int fd, Char** bufpp, SizeT* nBufp,
sewardjf98e1c02008-10-25 16:22:41 +00001112 Supp* su )
1113{
1114 /* do nothing -- no extra suppression info present. Return True to
1115 indicate nothing bad happened. */
1116 return True;
1117}
1118
1119Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
1120{
1121 switch (VG_(get_supp_kind)(su)) {
1122 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001123 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1124 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1125 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1126 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1127 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1128 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1129 //case XS_: return VG_(get_error_kind)(err) == XE_;
1130 default: tl_assert(0); /* fill in missing cases */
1131 }
1132}
1133
sewardj588adef2009-08-15 22:41:51 +00001134Bool HG_(get_extra_suppression_info) ( Error* err,
1135 /*OUT*/Char* buf, Int nBuf )
sewardjf98e1c02008-10-25 16:22:41 +00001136{
1137 /* Do nothing */
sewardj588adef2009-08-15 22:41:51 +00001138 return False;
sewardjf98e1c02008-10-25 16:22:41 +00001139}
1140
1141
1142/*--------------------------------------------------------------------*/
1143/*--- end hg_errors.c ---*/
1144/*--------------------------------------------------------------------*/