blob: 497fe58f0124173f9dc10c32b529758c4f3ffc25 [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;
126 lkp->admin = NULL;
127 lkp->magic = LockP_MAGIC;
128 /* Forget about the bag of lock holders - don't copy that.
129 Also, acquired_at should be NULL whenever heldBy is, and vice
130 versa. Also forget about the associated libhb synch object. */
131 lkp->heldW = False;
132 lkp->heldBy = NULL;
133 lkp->acquired_at = NULL;
134 lkp->hbso = NULL;
135 VG_(addToFM)( map_LockN_to_P, (Word)lkp, (Word)lkp );
136 }
137 tl_assert( HG_(is_sane_LockP)(lkp) );
138 return lkp;
139}
140
141/* Errors:
142
143 race: program counter
144 read or write
145 data size
146 previous state
147 current state
148
149 FIXME: how does state printing interact with lockset gc?
150 Are the locksets in prev/curr state always valid?
151 Ditto question for the threadsets
152 ThreadSets - probably are always valid if Threads
153 are never thrown away.
154 LockSets - could at least print the lockset elements that
155 correspond to actual locks at the time of printing. Hmm.
156*/
157
158/* Error kinds */
159typedef
160 enum {
161 XE_Race=1101, // race
sewardjf98e1c02008-10-25 16:22:41 +0000162 XE_UnlockUnlocked, // unlocking a not-locked lock
163 XE_UnlockForeign, // unlocking a lock held by some other thread
164 XE_UnlockBogus, // unlocking an address not known to be a lock
165 XE_PthAPIerror, // error from the POSIX pthreads API
166 XE_LockOrder, // lock order error
167 XE_Misc // misc other error (w/ string to describe it)
168 }
169 XErrorTag;
170
171/* Extra contexts for kinds */
172typedef
173 struct {
174 XErrorTag tag;
175 union {
176 struct {
sewardj23f12002009-07-24 08:45:08 +0000177 Addr data_addr;
178 Int szB;
179 Bool isWrite;
180 Thread* thr;
sewardj095d61e2010-03-11 13:43:18 +0000181 /* descr1/2 provide a description of stack/global locs */
sewardj23f12002009-07-24 08:45:08 +0000182 XArray* descr1; /* XArray* of HChar */
183 XArray* descr2; /* XArray* of HChar */
sewardj095d61e2010-03-11 13:43:18 +0000184 /* halloc/haddr/hszB describe the addr if it is a heap block. */
185 ExeContext* hctxt;
186 Addr haddr;
187 SizeT hszB;
188 /* h1_* and h2_* provide some description of a previously
189 observed access with which we are conflicting. */
sewardj23f12002009-07-24 08:45:08 +0000190 Thread* h1_ct; /* non-NULL means h1 info present */
191 ExeContext* h1_ct_mbsegstartEC;
192 ExeContext* h1_ct_mbsegendEC;
193 Thread* h2_ct; /* non-NULL means h2 info present */
194 ExeContext* h2_ct_accEC;
195 Int h2_ct_accSzB;
196 Bool h2_ct_accIsW;
sewardjf98e1c02008-10-25 16:22:41 +0000197 } Race;
198 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000199 Thread* thr; /* doing the unlocking */
200 Lock* lock; /* lock (that is already unlocked) */
201 } UnlockUnlocked;
202 struct {
203 Thread* thr; /* doing the unlocking */
204 Thread* owner; /* thread that actually holds the lock */
205 Lock* lock; /* lock (that is held by 'owner') */
206 } UnlockForeign;
207 struct {
208 Thread* thr; /* doing the unlocking */
209 Addr lock_ga; /* purported address of the lock */
210 } UnlockBogus;
211 struct {
212 Thread* thr;
213 HChar* fnname; /* persistent, in tool-arena */
214 Word err; /* pth error code */
215 HChar* errstr; /* persistent, in tool-arena */
216 } PthAPIerror;
217 struct {
218 Thread* thr;
219 Addr before_ga; /* always locked first in prog. history */
220 Addr after_ga;
221 ExeContext* before_ec;
222 ExeContext* after_ec;
223 } LockOrder;
224 struct {
sewardj8fef6252010-07-29 05:28:02 +0000225 Thread* thr;
226 HChar* errstr; /* persistent, in tool-arena */
227 HChar* auxstr; /* optional, persistent, in tool-arena */
228 ExeContext* auxctx; /* optional */
sewardjf98e1c02008-10-25 16:22:41 +0000229 } Misc;
230 } XE;
231 }
232 XError;
233
234static void init_XError ( XError* xe ) {
235 VG_(memset)(xe, 0, sizeof(*xe) );
236 xe->tag = XE_Race-1; /* bogus */
237}
238
239
240/* Extensions of suppressions */
241typedef
242 enum {
243 XS_Race=1201, /* race */
244 XS_FreeMemLock,
245 XS_UnlockUnlocked,
246 XS_UnlockForeign,
247 XS_UnlockBogus,
248 XS_PthAPIerror,
249 XS_LockOrder,
250 XS_Misc
251 }
252 XSuppTag;
253
254
255/* Updates the copy with address info if necessary. */
256UInt HG_(update_extra) ( Error* err )
257{
258 XError* xe = (XError*)VG_(get_error_extra)(err);
259 tl_assert(xe);
260 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
261 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
262 //}
263
264 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000265
sewardjf98e1c02008-10-25 16:22:41 +0000266 /* See if we can come up with a source level description of the
267 raced-upon address. This is potentially expensive, which is
268 why it's only done at the update_extra point, not when the
269 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000270 static Int xxx = 0;
271 xxx++;
272 if (0)
273 VG_(printf)("HG_(update_extra): "
274 "%d conflicting-event queries\n", xxx);
sewardj095d61e2010-03-11 13:43:18 +0000275
276 tl_assert(!xe->XE.Race.hctxt);
sewardj24118492009-07-15 14:50:02 +0000277 tl_assert(!xe->XE.Race.descr1);
278 tl_assert(!xe->XE.Race.descr2);
279
sewardj095d61e2010-03-11 13:43:18 +0000280 /* First, see if it's in any heap block. Unfortunately this
sewardjc8028ad2010-05-05 09:34:42 +0000281 means a linear search through all allocated heap blocks. The
282 assertion says that if it's detected as a heap block, then we
283 must have an allocation context for it, since all heap blocks
284 should have an allocation context. */
285 Bool is_heapblock
286 = HG_(mm_find_containing_block)(
287 &xe->XE.Race.hctxt, &xe->XE.Race.haddr, &xe->XE.Race.hszB,
288 xe->XE.Race.data_addr
289 );
290 tl_assert(is_heapblock == (xe->XE.Race.hctxt != NULL));
sewardj24118492009-07-15 14:50:02 +0000291
sewardj095d61e2010-03-11 13:43:18 +0000292 if (!xe->XE.Race.hctxt) {
293 /* It's not in any heap block. See if we can map it to a
294 stack or global symbol. */
sewardj24118492009-07-15 14:50:02 +0000295
sewardj095d61e2010-03-11 13:43:18 +0000296 xe->XE.Race.descr1
297 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr1",
298 HG_(free), sizeof(HChar) );
299 xe->XE.Race.descr2
300 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr2",
301 HG_(free), sizeof(HChar) );
302
303 (void) VG_(get_data_description)( xe->XE.Race.descr1,
304 xe->XE.Race.descr2,
305 xe->XE.Race.data_addr );
306
307 /* If there's nothing in descr1/2, free it. Why is it safe to
308 to VG_(indexXA) at zero here? Because
309 VG_(get_data_description) guarantees to zero terminate
310 descr1/2 regardless of the outcome of the call. So there's
311 always at least one element in each XA after the call.
312 */
313 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr1, 0 ))) {
314 VG_(deleteXA)( xe->XE.Race.descr1 );
315 xe->XE.Race.descr1 = NULL;
316 }
317 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr2, 0 ))) {
318 VG_(deleteXA)( xe->XE.Race.descr2 );
319 xe->XE.Race.descr2 = NULL;
320 }
sewardj24118492009-07-15 14:50:02 +0000321 }
322
323 /* And poke around in the conflicting-event map, to see if we
324 can rustle up a plausible-looking conflicting memory access
325 to show. */
sewardj23f12002009-07-24 08:45:08 +0000326 if (HG_(clo_history_level) >= 2) {
327 Thr* thrp = NULL;
328 ExeContext* wherep = NULL;
329 Addr acc_addr = xe->XE.Race.data_addr;
330 Int acc_szB = xe->XE.Race.szB;
331 Thr* acc_thr = xe->XE.Race.thr->hbthr;
332 Bool acc_isW = xe->XE.Race.isWrite;
333 SizeT conf_szB = 0;
334 Bool conf_isW = False;
335 tl_assert(!xe->XE.Race.h2_ct_accEC);
336 tl_assert(!xe->XE.Race.h2_ct);
337 if (libhb_event_map_lookup(
338 &wherep, &thrp, &conf_szB, &conf_isW,
339 acc_thr, acc_addr, acc_szB, acc_isW )) {
340 Thread* threadp;
341 tl_assert(wherep);
342 tl_assert(thrp);
343 threadp = libhb_get_Thr_opaque( thrp );
344 tl_assert(threadp);
345 xe->XE.Race.h2_ct_accEC = wherep;
346 xe->XE.Race.h2_ct = threadp;
347 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
348 xe->XE.Race.h2_ct_accIsW = conf_isW;
sewardjc5ea9962008-12-07 01:41:46 +0000349 }
350 }
sewardj23f12002009-07-24 08:45:08 +0000351
352 // both NULL or both non-NULL
353 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
sewardjf98e1c02008-10-25 16:22:41 +0000354 }
355
356 return sizeof(XError);
357}
358
359void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000360 Addr data_addr, Int szB, Bool isWrite,
sewardj23f12002009-07-24 08:45:08 +0000361 Thread* h1_ct,
362 ExeContext* h1_ct_segstart,
363 ExeContext* h1_ct_mbsegendEC )
sewardjf98e1c02008-10-25 16:22:41 +0000364{
365 XError xe;
366 tl_assert( HG_(is_sane_Thread)(thr) );
367
368# if defined(VGO_linux)
369 /* Skip any races on locations apparently in GOTPLT sections. This
370 is said to be caused by ld.so poking PLT table entries (or
371 whatever) when it writes the resolved address of a dynamically
372 linked routine, into the table (or whatever) when it is called
373 for the first time. */
374 {
sewardje3f1e592009-07-31 09:41:29 +0000375 VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr );
sewardjf98e1c02008-10-25 16:22:41 +0000376 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
377 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000378 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000379 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000380 /* SectPLT is required on ppc32/64-linux */
381 if (sect == Vg_SectPLT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000382 }
383# endif
384
385 init_XError(&xe);
386 xe.tag = XE_Race;
387 xe.XE.Race.data_addr = data_addr;
388 xe.XE.Race.szB = szB;
389 xe.XE.Race.isWrite = isWrite;
sewardjf98e1c02008-10-25 16:22:41 +0000390 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000391 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000392 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000393 /* Skip on the detailed description of the raced-on address at this
394 point; it's expensive. Leave it for the update_extra function
395 if we ever make it that far. */
396 tl_assert(xe.XE.Race.descr1 == NULL);
397 tl_assert(xe.XE.Race.descr2 == NULL);
sewardjf98e1c02008-10-25 16:22:41 +0000398 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000399 // Skip on any of the conflicting-access info at this point.
400 // It's expensive to obtain, and this error is more likely than
401 // not to be discarded. We'll fill these fields in in
402 // HG_(update_extra) just above, assuming the error ever makes
403 // it that far (unlikely).
sewardj23f12002009-07-24 08:45:08 +0000404 xe.XE.Race.h2_ct_accSzB = 0;
405 xe.XE.Race.h2_ct_accIsW = False;
406 xe.XE.Race.h2_ct_accEC = NULL;
407 xe.XE.Race.h2_ct = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000408 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
409 tl_assert( thr->coretid != VG_INVALID_THREADID );
sewardj23f12002009-07-24 08:45:08 +0000410
411 xe.XE.Race.h1_ct = h1_ct;
412 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
413 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC;
414
sewardjf98e1c02008-10-25 16:22:41 +0000415 VG_(maybe_record_error)( thr->coretid,
416 XE_Race, data_addr, NULL, &xe );
417}
418
sewardjf98e1c02008-10-25 16:22:41 +0000419void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
420{
421 XError xe;
422 tl_assert( HG_(is_sane_Thread)(thr) );
423 tl_assert( HG_(is_sane_LockN)(lk) );
424 init_XError(&xe);
425 xe.tag = XE_UnlockUnlocked;
426 xe.XE.UnlockUnlocked.thr = thr;
427 xe.XE.UnlockUnlocked.lock = mk_LockP_from_LockN(lk);
428 // FIXME: tid vs thr
429 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
430 tl_assert( thr->coretid != VG_INVALID_THREADID );
431 VG_(maybe_record_error)( thr->coretid,
432 XE_UnlockUnlocked, 0, NULL, &xe );
433}
434
435void HG_(record_error_UnlockForeign) ( Thread* thr,
436 Thread* owner, Lock* lk )
437{
438 XError xe;
439 tl_assert( HG_(is_sane_Thread)(thr) );
440 tl_assert( HG_(is_sane_Thread)(owner) );
441 tl_assert( HG_(is_sane_LockN)(lk) );
442 init_XError(&xe);
443 xe.tag = XE_UnlockForeign;
444 xe.XE.UnlockForeign.thr = thr;
445 xe.XE.UnlockForeign.owner = owner;
446 xe.XE.UnlockForeign.lock = mk_LockP_from_LockN(lk);
447 // FIXME: tid vs thr
448 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
449 tl_assert( thr->coretid != VG_INVALID_THREADID );
450 VG_(maybe_record_error)( thr->coretid,
451 XE_UnlockForeign, 0, NULL, &xe );
452}
453
454void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
455{
456 XError xe;
457 tl_assert( HG_(is_sane_Thread)(thr) );
458 init_XError(&xe);
459 xe.tag = XE_UnlockBogus;
460 xe.XE.UnlockBogus.thr = thr;
461 xe.XE.UnlockBogus.lock_ga = lock_ga;
462 // FIXME: tid vs thr
463 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
464 tl_assert( thr->coretid != VG_INVALID_THREADID );
465 VG_(maybe_record_error)( thr->coretid,
466 XE_UnlockBogus, 0, NULL, &xe );
467}
468
469void HG_(record_error_LockOrder)(
470 Thread* thr, Addr before_ga, Addr after_ga,
471 ExeContext* before_ec, ExeContext* after_ec
472 )
473{
474 XError xe;
475 tl_assert( HG_(is_sane_Thread)(thr) );
476 if (!HG_(clo_track_lockorders))
477 return;
478 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/*--------------------------------------------------------------------*/