blob: 92416915ddbb8a11f799b6cd39051f8294e5fbfc [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
njn9f207462009-03-10 22:02:09 +000011 Copyright (C) 2007-2009 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;
181 XArray* descr1; /* XArray* of HChar */
182 XArray* descr2; /* XArray* of HChar */
183 Thread* h1_ct; /* non-NULL means h1 info present */
184 ExeContext* h1_ct_mbsegstartEC;
185 ExeContext* h1_ct_mbsegendEC;
186 Thread* h2_ct; /* non-NULL means h2 info present */
187 ExeContext* h2_ct_accEC;
188 Int h2_ct_accSzB;
189 Bool h2_ct_accIsW;
sewardjf98e1c02008-10-25 16:22:41 +0000190 } Race;
191 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000192 Thread* thr; /* doing the unlocking */
193 Lock* lock; /* lock (that is already unlocked) */
194 } UnlockUnlocked;
195 struct {
196 Thread* thr; /* doing the unlocking */
197 Thread* owner; /* thread that actually holds the lock */
198 Lock* lock; /* lock (that is held by 'owner') */
199 } UnlockForeign;
200 struct {
201 Thread* thr; /* doing the unlocking */
202 Addr lock_ga; /* purported address of the lock */
203 } UnlockBogus;
204 struct {
205 Thread* thr;
206 HChar* fnname; /* persistent, in tool-arena */
207 Word err; /* pth error code */
208 HChar* errstr; /* persistent, in tool-arena */
209 } PthAPIerror;
210 struct {
211 Thread* thr;
212 Addr before_ga; /* always locked first in prog. history */
213 Addr after_ga;
214 ExeContext* before_ec;
215 ExeContext* after_ec;
216 } LockOrder;
217 struct {
218 Thread* thr;
219 HChar* errstr; /* persistent, in tool-arena */
220 } Misc;
221 } XE;
222 }
223 XError;
224
225static void init_XError ( XError* xe ) {
226 VG_(memset)(xe, 0, sizeof(*xe) );
227 xe->tag = XE_Race-1; /* bogus */
228}
229
230
231/* Extensions of suppressions */
232typedef
233 enum {
234 XS_Race=1201, /* race */
235 XS_FreeMemLock,
236 XS_UnlockUnlocked,
237 XS_UnlockForeign,
238 XS_UnlockBogus,
239 XS_PthAPIerror,
240 XS_LockOrder,
241 XS_Misc
242 }
243 XSuppTag;
244
245
246/* Updates the copy with address info if necessary. */
247UInt HG_(update_extra) ( Error* err )
248{
249 XError* xe = (XError*)VG_(get_error_extra)(err);
250 tl_assert(xe);
251 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
252 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
253 //}
254
255 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000256
sewardjf98e1c02008-10-25 16:22:41 +0000257 /* See if we can come up with a source level description of the
258 raced-upon address. This is potentially expensive, which is
259 why it's only done at the update_extra point, not when the
260 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000261 static Int xxx = 0;
262 xxx++;
263 if (0)
264 VG_(printf)("HG_(update_extra): "
265 "%d conflicting-event queries\n", xxx);
sewardj24118492009-07-15 14:50:02 +0000266 tl_assert(!xe->XE.Race.descr1);
267 tl_assert(!xe->XE.Race.descr2);
268
269 xe->XE.Race.descr1
270 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr1",
271 HG_(free), sizeof(HChar) );
272 xe->XE.Race.descr2
273 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr2",
274 HG_(free), sizeof(HChar) );
275
276 (void) VG_(get_data_description)( xe->XE.Race.descr1,
277 xe->XE.Race.descr2,
278 xe->XE.Race.data_addr );
279
280 /* If there's nothing in descr1/2, free it. Why is it safe to
281 to VG_(indexXA) at zero here? Because
282 VG_(get_data_description) guarantees to zero terminate
283 descr1/2 regardless of the outcome of the call. So there's
284 always at least one element in each XA after the call.
285 */
286 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr1, 0 ))) {
287 VG_(deleteXA)( xe->XE.Race.descr1 );
288 xe->XE.Race.descr1 = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000289 }
sewardj24118492009-07-15 14:50:02 +0000290 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr2, 0 ))) {
291 VG_(deleteXA)( xe->XE.Race.descr2 );
292 xe->XE.Race.descr2 = NULL;
293 }
294
295 /* And poke around in the conflicting-event map, to see if we
296 can rustle up a plausible-looking conflicting memory access
297 to show. */
sewardj23f12002009-07-24 08:45:08 +0000298 if (HG_(clo_history_level) >= 2) {
299 Thr* thrp = NULL;
300 ExeContext* wherep = NULL;
301 Addr acc_addr = xe->XE.Race.data_addr;
302 Int acc_szB = xe->XE.Race.szB;
303 Thr* acc_thr = xe->XE.Race.thr->hbthr;
304 Bool acc_isW = xe->XE.Race.isWrite;
305 SizeT conf_szB = 0;
306 Bool conf_isW = False;
307 tl_assert(!xe->XE.Race.h2_ct_accEC);
308 tl_assert(!xe->XE.Race.h2_ct);
309 if (libhb_event_map_lookup(
310 &wherep, &thrp, &conf_szB, &conf_isW,
311 acc_thr, acc_addr, acc_szB, acc_isW )) {
312 Thread* threadp;
313 tl_assert(wherep);
314 tl_assert(thrp);
315 threadp = libhb_get_Thr_opaque( thrp );
316 tl_assert(threadp);
317 xe->XE.Race.h2_ct_accEC = wherep;
318 xe->XE.Race.h2_ct = threadp;
319 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
320 xe->XE.Race.h2_ct_accIsW = conf_isW;
sewardjc5ea9962008-12-07 01:41:46 +0000321 }
322 }
sewardj23f12002009-07-24 08:45:08 +0000323
324 // both NULL or both non-NULL
325 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
sewardjf98e1c02008-10-25 16:22:41 +0000326 }
327
328 return sizeof(XError);
329}
330
331void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000332 Addr data_addr, Int szB, Bool isWrite,
sewardj23f12002009-07-24 08:45:08 +0000333 Thread* h1_ct,
334 ExeContext* h1_ct_segstart,
335 ExeContext* h1_ct_mbsegendEC )
sewardjf98e1c02008-10-25 16:22:41 +0000336{
337 XError xe;
338 tl_assert( HG_(is_sane_Thread)(thr) );
339
340# if defined(VGO_linux)
341 /* Skip any races on locations apparently in GOTPLT sections. This
342 is said to be caused by ld.so poking PLT table entries (or
343 whatever) when it writes the resolved address of a dynamically
344 linked routine, into the table (or whatever) when it is called
345 for the first time. */
346 {
347 VgSectKind sect = VG_(seginfo_sect_kind)( NULL, 0, data_addr );
348 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
349 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000350 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000351 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000352 /* SectPLT is required on ppc32/64-linux */
353 if (sect == Vg_SectPLT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000354 }
355# endif
356
357 init_XError(&xe);
358 xe.tag = XE_Race;
359 xe.XE.Race.data_addr = data_addr;
360 xe.XE.Race.szB = szB;
361 xe.XE.Race.isWrite = isWrite;
sewardjf98e1c02008-10-25 16:22:41 +0000362 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000363 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000364 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000365 /* Skip on the detailed description of the raced-on address at this
366 point; it's expensive. Leave it for the update_extra function
367 if we ever make it that far. */
368 tl_assert(xe.XE.Race.descr1 == NULL);
369 tl_assert(xe.XE.Race.descr2 == NULL);
sewardjf98e1c02008-10-25 16:22:41 +0000370 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000371 // Skip on any of the conflicting-access info at this point.
372 // It's expensive to obtain, and this error is more likely than
373 // not to be discarded. We'll fill these fields in in
374 // HG_(update_extra) just above, assuming the error ever makes
375 // it that far (unlikely).
sewardj23f12002009-07-24 08:45:08 +0000376 xe.XE.Race.h2_ct_accSzB = 0;
377 xe.XE.Race.h2_ct_accIsW = False;
378 xe.XE.Race.h2_ct_accEC = NULL;
379 xe.XE.Race.h2_ct = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000380 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
381 tl_assert( thr->coretid != VG_INVALID_THREADID );
sewardj23f12002009-07-24 08:45:08 +0000382
383 xe.XE.Race.h1_ct = h1_ct;
384 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
385 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC;
386
sewardjf98e1c02008-10-25 16:22:41 +0000387 VG_(maybe_record_error)( thr->coretid,
388 XE_Race, data_addr, NULL, &xe );
389}
390
sewardjf98e1c02008-10-25 16:22:41 +0000391void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
392{
393 XError xe;
394 tl_assert( HG_(is_sane_Thread)(thr) );
395 tl_assert( HG_(is_sane_LockN)(lk) );
396 init_XError(&xe);
397 xe.tag = XE_UnlockUnlocked;
398 xe.XE.UnlockUnlocked.thr = thr;
399 xe.XE.UnlockUnlocked.lock = mk_LockP_from_LockN(lk);
400 // FIXME: tid vs thr
401 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
402 tl_assert( thr->coretid != VG_INVALID_THREADID );
403 VG_(maybe_record_error)( thr->coretid,
404 XE_UnlockUnlocked, 0, NULL, &xe );
405}
406
407void HG_(record_error_UnlockForeign) ( Thread* thr,
408 Thread* owner, Lock* lk )
409{
410 XError xe;
411 tl_assert( HG_(is_sane_Thread)(thr) );
412 tl_assert( HG_(is_sane_Thread)(owner) );
413 tl_assert( HG_(is_sane_LockN)(lk) );
414 init_XError(&xe);
415 xe.tag = XE_UnlockForeign;
416 xe.XE.UnlockForeign.thr = thr;
417 xe.XE.UnlockForeign.owner = owner;
418 xe.XE.UnlockForeign.lock = mk_LockP_from_LockN(lk);
419 // FIXME: tid vs thr
420 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
421 tl_assert( thr->coretid != VG_INVALID_THREADID );
422 VG_(maybe_record_error)( thr->coretid,
423 XE_UnlockForeign, 0, NULL, &xe );
424}
425
426void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
427{
428 XError xe;
429 tl_assert( HG_(is_sane_Thread)(thr) );
430 init_XError(&xe);
431 xe.tag = XE_UnlockBogus;
432 xe.XE.UnlockBogus.thr = thr;
433 xe.XE.UnlockBogus.lock_ga = lock_ga;
434 // FIXME: tid vs thr
435 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
436 tl_assert( thr->coretid != VG_INVALID_THREADID );
437 VG_(maybe_record_error)( thr->coretid,
438 XE_UnlockBogus, 0, NULL, &xe );
439}
440
441void HG_(record_error_LockOrder)(
442 Thread* thr, Addr before_ga, Addr after_ga,
443 ExeContext* before_ec, ExeContext* after_ec
444 )
445{
446 XError xe;
447 tl_assert( HG_(is_sane_Thread)(thr) );
448 if (!HG_(clo_track_lockorders))
449 return;
450 init_XError(&xe);
451 xe.tag = XE_LockOrder;
452 xe.XE.LockOrder.thr = thr;
453 xe.XE.LockOrder.before_ga = before_ga;
454 xe.XE.LockOrder.before_ec = before_ec;
455 xe.XE.LockOrder.after_ga = after_ga;
456 xe.XE.LockOrder.after_ec = after_ec;
457 // FIXME: tid vs thr
458 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
459 tl_assert( thr->coretid != VG_INVALID_THREADID );
460 VG_(maybe_record_error)( thr->coretid,
461 XE_LockOrder, 0, NULL, &xe );
462}
463
464void HG_(record_error_PthAPIerror) ( Thread* thr, HChar* fnname,
465 Word err, HChar* errstr )
466{
467 XError xe;
468 tl_assert( HG_(is_sane_Thread)(thr) );
469 tl_assert(fnname);
470 tl_assert(errstr);
471 init_XError(&xe);
472 xe.tag = XE_PthAPIerror;
473 xe.XE.PthAPIerror.thr = thr;
474 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
475 xe.XE.PthAPIerror.err = err;
476 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
477 // FIXME: tid vs thr
478 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
479 tl_assert( thr->coretid != VG_INVALID_THREADID );
480 VG_(maybe_record_error)( thr->coretid,
481 XE_PthAPIerror, 0, NULL, &xe );
482}
483
484void HG_(record_error_Misc) ( Thread* thr, HChar* errstr )
485{
486 XError xe;
487 tl_assert( HG_(is_sane_Thread)(thr) );
488 tl_assert(errstr);
489 init_XError(&xe);
490 xe.tag = XE_Misc;
491 xe.XE.Misc.thr = thr;
492 xe.XE.Misc.errstr = string_table_strdup(errstr);
493 // FIXME: tid vs thr
494 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
495 tl_assert( thr->coretid != VG_INVALID_THREADID );
496 VG_(maybe_record_error)( thr->coretid,
497 XE_Misc, 0, NULL, &xe );
498}
499
500Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 )
501{
502 XError *xe1, *xe2;
503
504 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
505
506 xe1 = (XError*)VG_(get_error_extra)(e1);
507 xe2 = (XError*)VG_(get_error_extra)(e2);
508 tl_assert(xe1);
509 tl_assert(xe2);
510
511 switch (VG_(get_error_kind)(e1)) {
512 case XE_Race:
513 return xe1->XE.Race.szB == xe2->XE.Race.szB
514 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
515 && (HG_(clo_cmp_race_err_addrs)
516 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
517 : True);
sewardjf98e1c02008-10-25 16:22:41 +0000518 case XE_UnlockUnlocked:
519 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
520 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
521 case XE_UnlockForeign:
522 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
523 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
524 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
525 case XE_UnlockBogus:
526 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
527 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
528 case XE_PthAPIerror:
529 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
530 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
531 xe2->XE.PthAPIerror.fnname)
532 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
533 case XE_LockOrder:
534 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
535 case XE_Misc:
536 return xe1->XE.Misc.thr == xe2->XE.Misc.thr
537 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
538 default:
539 tl_assert(0);
540 }
541
542 /*NOTREACHED*/
543 tl_assert(0);
544}
545
546
sewardj24118492009-07-15 14:50:02 +0000547/*----------------------------------------------------------------*/
548/*--- Error management -- printing ---*/
549/*----------------------------------------------------------------*/
550
551/* Do a printf-style operation on either the XML or normal output
552 channel, depending on the setting of VG_(clo_xml).
553*/
554static void emit_WRK ( HChar* format, va_list vargs )
555{
556 if (VG_(clo_xml)) {
557 VG_(vprintf_xml)(format, vargs);
558 } else {
559 VG_(vmessage)(Vg_UserMsg, format, vargs);
560 }
561}
562static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
563static void emit ( HChar* format, ... )
564{
565 va_list vargs;
566 va_start(vargs, format);
567 emit_WRK(format, vargs);
568 va_end(vargs);
569}
570static void emit_no_f_c ( HChar* format, ... )
571{
572 va_list vargs;
573 va_start(vargs, format);
574 emit_WRK(format, vargs);
575 va_end(vargs);
576}
577
578
sewardjf98e1c02008-10-25 16:22:41 +0000579/* Announce (that is, print the point-of-creation) of 'thr'. Only do
580 this once, as we only want to see these announcements once per
sewardj24118492009-07-15 14:50:02 +0000581 thread. Returned Bool indicates whether or not an announcement was
582 made.
583*/
584static Bool announce_one_thread ( Thread* thr )
sewardjf98e1c02008-10-25 16:22:41 +0000585{
586 tl_assert(HG_(is_sane_Thread)(thr));
587 tl_assert(thr->errmsg_index >= 1);
sewardj24118492009-07-15 14:50:02 +0000588 if (thr->announced)
589 return False;
590
591 if (VG_(clo_xml)) {
592
593 VG_(printf_xml)("<announcethread>\n");
594 VG_(printf_xml)(" <hthreadid>%d</threadid>\n", thr->errmsg_index);
sewardjf98e1c02008-10-25 16:22:41 +0000595 if (thr->errmsg_index == 1) {
596 tl_assert(thr->created_at == NULL);
sewardj24118492009-07-15 14:50:02 +0000597 VG_(printf_xml)(" <isrootthread></isrootthread>\n");
sewardjf98e1c02008-10-25 16:22:41 +0000598 } else {
599 tl_assert(thr->created_at != NULL);
sewardj24118492009-07-15 14:50:02 +0000600 VG_(pp_ExeContext)( thr->created_at );
601 }
602 VG_(printf_xml)("</announcethread>\n\n");
603
604 } else {
605
606 if (thr->errmsg_index == 1) {
607 tl_assert(thr->created_at == NULL);
608 VG_(message)(Vg_UserMsg,
609 "Thread #%d is the program's root thread\n",
610 thr->errmsg_index);
611 } else {
612 tl_assert(thr->created_at != NULL);
613 VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
sewardjf98e1c02008-10-25 16:22:41 +0000614 thr->errmsg_index);
615 VG_(pp_ExeContext)( thr->created_at );
616 }
sewardj24118492009-07-15 14:50:02 +0000617 VG_(message)(Vg_UserMsg, "\n");
618
619 }
620
621 thr->announced = True;
622 return True;
623}
624
625
626/* This is the "this error is due to be printed shortly; so have a
627 look at it any print any preamble you want" function. We use it to
628 announce any previously un-announced threads in the upcoming error
629 message.
630*/
631void HG_(before_pp_Error) ( Error* err )
632{
633 XError* xe;
634 tl_assert(err);
635 xe = (XError*)VG_(get_error_extra)(err);
636 tl_assert(xe);
637
638 switch (VG_(get_error_kind)(err)) {
639 case XE_Misc:
640 announce_one_thread( xe->XE.Misc.thr );
641 break;
642 case XE_LockOrder:
643 announce_one_thread( xe->XE.LockOrder.thr );
644 break;
645 case XE_PthAPIerror:
646 announce_one_thread( xe->XE.PthAPIerror.thr );
647 break;
648 case XE_UnlockBogus:
649 announce_one_thread( xe->XE.UnlockBogus.thr );
650 break;
651 case XE_UnlockForeign:
652 announce_one_thread( xe->XE.UnlockForeign.thr );
653 announce_one_thread( xe->XE.UnlockForeign.owner );
654 break;
655 case XE_UnlockUnlocked:
656 announce_one_thread( xe->XE.UnlockUnlocked.thr );
657 break;
658 case XE_Race:
659 announce_one_thread( xe->XE.Race.thr );
sewardj23f12002009-07-24 08:45:08 +0000660 if (xe->XE.Race.h2_ct)
661 announce_one_thread( xe->XE.Race.h2_ct );
662 if (xe->XE.Race.h1_ct)
663 announce_one_thread( xe->XE.Race.h1_ct );
sewardj24118492009-07-15 14:50:02 +0000664 break;
665 default:
666 tl_assert(0);
sewardjf98e1c02008-10-25 16:22:41 +0000667 }
668}
669
sewardjf98e1c02008-10-25 16:22:41 +0000670void HG_(pp_Error) ( Error* err )
671{
sewardj24118492009-07-15 14:50:02 +0000672 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
673
sewardjf98e1c02008-10-25 16:22:41 +0000674 XError *xe = (XError*)VG_(get_error_extra)(err);
sewardj24118492009-07-15 14:50:02 +0000675 tl_assert(xe);
sewardjf98e1c02008-10-25 16:22:41 +0000676
677 switch (VG_(get_error_kind)(err)) {
678
679 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000680 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000681
682 if (xml) {
683
684 emit( " <kind>Misc</kind>\n");
685 emit( " <xwhat>\n" );
686 emit( " <text>Thread #%d: %s</text>\n",
687 (Int)xe->XE.Misc.thr->errmsg_index,
688 xe->XE.Misc.errstr );
689 emit( " <hthreadid>%d</hthreadid>\n",
690 (Int)xe->XE.Misc.thr->errmsg_index );
691 emit( " </xwhat>\n" );
692 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
693
694 } else {
695
696 emit( "Thread #%d: %s\n",
697 (Int)xe->XE.Misc.thr->errmsg_index,
698 xe->XE.Misc.errstr );
699 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
700
701 }
sewardjf98e1c02008-10-25 16:22:41 +0000702 break;
703 }
704
705 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000706 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000707
708 if (xml) {
709
710 emit( " <kind>LockOrder</kind>\n");
711 emit( " <xwhat>\n" );
712 emit( " <text>Thread #%d: lock order \"%p before %p\" "
713 "violated</text>\n",
714 (Int)xe->XE.LockOrder.thr->errmsg_index,
715 (void*)xe->XE.LockOrder.before_ga,
716 (void*)xe->XE.LockOrder.after_ga );
717 emit( " <hthreadid>%d</hthreadid>\n",
718 (Int)xe->XE.LockOrder.thr->errmsg_index );
719 emit( " </xwhat>\n" );
720 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
721 if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
722 emit( " <auxwhat>Required order was established by "
723 "acquisition of lock at %p</auxwhat>\n",
724 (void*)xe->XE.LockOrder.before_ga );
725 VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
726 emit( " <auxwhat>followed by a later acquisition "
727 "of lock at %p</auxwhat>\n",
728 (void*)xe->XE.LockOrder.after_ga );
729 VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
730 }
731
732 } else {
733
734 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
735 (Int)xe->XE.LockOrder.thr->errmsg_index,
736 (void*)xe->XE.LockOrder.before_ga,
737 (void*)xe->XE.LockOrder.after_ga );
738 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
739 if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
740 emit( " Required order was established by "
741 "acquisition of lock at %p\n",
742 (void*)xe->XE.LockOrder.before_ga );
743 VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
744 emit( " followed by a later acquisition of lock at %p\n",
745 (void*)xe->XE.LockOrder.after_ga );
746 VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
747 }
748
sewardjf98e1c02008-10-25 16:22:41 +0000749 }
sewardj24118492009-07-15 14:50:02 +0000750
sewardjf98e1c02008-10-25 16:22:41 +0000751 break;
752 }
753
754 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +0000755 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +0000756
757 if (xml) {
758
759 emit( " <kind>PthAPIerror</kind>\n");
760 emit( " <xwhat>\n" );
761 emit_no_f_c(
762 " <text>Thread #%d's call to %t failed</text>\n",
763 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
764 xe->XE.PthAPIerror.fnname );
765 emit( " <hthreadid>%d</hthreadid>\n",
766 (Int)xe->XE.PthAPIerror.thr->errmsg_index );
767 emit( " </xwhat>\n" );
768 emit( " <what>with error code %ld (%s)</what>\n",
769 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
770 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
771
772 } else {
773
774 emit_no_f_c( "Thread #%d's call to %t failed\n",
775 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
776 xe->XE.PthAPIerror.fnname );
777 emit( " with error code %ld (%s)\n",
778 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
779 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
780
781 }
782
sewardjf98e1c02008-10-25 16:22:41 +0000783 break;
784 }
785
786 case XE_UnlockBogus: {
sewardjf98e1c02008-10-25 16:22:41 +0000787 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
sewardj24118492009-07-15 14:50:02 +0000788
789 if (xml) {
790
791 emit( " <kind>UnlockBogus</kind>\n");
792 emit( " <xwhat>\n" );
793 emit( " <text>Thread #%d unlocked an invalid "
794 "lock at %p</text>\n",
795 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
796 (void*)xe->XE.UnlockBogus.lock_ga );
797 emit( " <hthreadid>%d</hthreadid>\n",
798 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
799 emit( " </xwhat>\n" );
800 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
801
802 } else {
803
804 emit( "Thread #%d unlocked an invalid lock at %p\n",
805 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
806 (void*)xe->XE.UnlockBogus.lock_ga );
807 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
808
809 }
810
sewardjf98e1c02008-10-25 16:22:41 +0000811 break;
812 }
813
814 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +0000815 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
816 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
817 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +0000818
819 if (xml) {
820
821 emit( " <kind>UnlockForeign</kind>\n");
822 emit( " <xwhat>\n" );
823 emit( " <text>Thread #%d unlocked lock at %p "
824 "currently held by thread #%d</text>\n",
825 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
826 (void*)xe->XE.UnlockForeign.lock->guestaddr,
827 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
828 emit( " <hthreadid>%d</hthreadid>\n",
829 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
830 emit( " <hthreadid>%d</hthreadid>\n",
831 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
832 emit( " </xwhat>\n" );
833 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
834
835 if (xe->XE.UnlockForeign.lock->appeared_at) {
836 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
837 (void*)xe->XE.UnlockForeign.lock->guestaddr );
838 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
839 }
840
841 } else {
842
843 emit( "Thread #%d unlocked lock at %p "
844 "currently held by thread #%d\n",
845 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
846 (void*)xe->XE.UnlockForeign.lock->guestaddr,
847 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
848 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
849 if (xe->XE.UnlockForeign.lock->appeared_at) {
850 emit( " Lock at %p was first observed\n",
851 (void*)xe->XE.UnlockForeign.lock->guestaddr );
852 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
853 }
854
sewardjf98e1c02008-10-25 16:22:41 +0000855 }
sewardj24118492009-07-15 14:50:02 +0000856
sewardjf98e1c02008-10-25 16:22:41 +0000857 break;
858 }
859
860 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +0000861 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
862 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +0000863
sewardj24118492009-07-15 14:50:02 +0000864 if (xml) {
865
866 emit( " <kind>UnlockUnlocked</kind>\n");
867 emit( " <xwhat>\n" );
868 emit( " <text>Thread #%d unlocked a "
869 "not-locked lock at %p</text>\n",
870 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
871 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
872 emit( " <hthreadid>%d</hthreadid>\n",
873 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
874 emit( " </xwhat>\n" );
875 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
876 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
877 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
878 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
879 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
880 }
881
882 } else {
883
884 emit( "Thread #%d unlocked a not-locked lock at %p\n",
885 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
886 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
887 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
888 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
889 emit( " Lock at %p was first observed\n",
890 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
891 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
892 }
893
sewardjf98e1c02008-10-25 16:22:41 +0000894 }
sewardj24118492009-07-15 14:50:02 +0000895
sewardjf98e1c02008-10-25 16:22:41 +0000896 break;
897 }
898
899 case XE_Race: {
900 Addr err_ga;
901 HChar* what;
902 Int szB;
903 what = xe->XE.Race.isWrite ? "write" : "read";
904 szB = xe->XE.Race.szB;
905 err_ga = VG_(get_error_address)(err);
906
sewardj24118492009-07-15 14:50:02 +0000907 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardj23f12002009-07-24 08:45:08 +0000908 if (xe->XE.Race.h2_ct)
909 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
sewardj24118492009-07-15 14:50:02 +0000910
911 if (xml) {
912
913 /* ------ XML ------ */
914 emit( " <kind>Race</kind>\n" );
915 emit( " <xwhat>\n" );
916 emit( " <text>Possible data race during %s of size %d "
917 "at %#lx by thread #%d</text>\n",
918 what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
919 emit( " <hthreadid>%d</hthreadid>\n",
920 (Int)xe->XE.Race.thr->errmsg_index );
921 emit( " </xwhat>\n" );
922 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
923
sewardj23f12002009-07-24 08:45:08 +0000924 if (xe->XE.Race.h2_ct) {
925 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
926 emit( " <xauxwhat>\n");
927 emit( " <text>This conflicts with a previous %s of size %d "
928 "by thread #%d</text>\n",
929 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
930 xe->XE.Race.h2_ct_accSzB,
931 xe->XE.Race.h2_ct->errmsg_index );
932 emit( " <hthreadid>%d</hthreadid>\n",
933 xe->XE.Race.h2_ct->errmsg_index);
934 emit(" </xauxwhat>\n");
935 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
936 }
937
938 if (xe->XE.Race.h1_ct) {
939 emit( " <xauxwhat>\n");
940 emit( " <text>This conflicts with a previous access "
941 "by thread #%d, after</text>\n",
942 xe->XE.Race.h1_ct->errmsg_index );
943 emit( " <hthreadid>%d</hthreadid>\n",
944 xe->XE.Race.h1_ct->errmsg_index );
945 emit(" </xauxwhat>\n");
946 if (xe->XE.Race.h1_ct_mbsegstartEC) {
947 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +0000948 } else {
sewardj23f12002009-07-24 08:45:08 +0000949 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" );
sewardj24118492009-07-15 14:50:02 +0000950 }
sewardj23f12002009-07-24 08:45:08 +0000951 emit( " <auxwhat>but before</auxwhat>\n" );
952 if (xe->XE.Race.h1_ct_mbsegendEC) {
953 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
954 } else {
955 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" );
956 }
sewardjf98e1c02008-10-25 16:22:41 +0000957 }
sewardj24118492009-07-15 14:50:02 +0000958
959 } else {
960
961 /* ------ Text ------ */
962 emit( "Possible data race during %s of size %d "
963 "at %#lx by thread #%d\n",
964 what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
965 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
sewardj23f12002009-07-24 08:45:08 +0000966
967 if (xe->XE.Race.h2_ct) {
968 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
969 emit( " This conflicts with a previous %s of size %d "
970 "by thread #%d\n",
971 xe->XE.Race.h2_ct_accIsW ? "write" : "read",
972 xe->XE.Race.h2_ct_accSzB,
973 xe->XE.Race.h2_ct->errmsg_index );
974 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
975 }
976
977 if (xe->XE.Race.h1_ct) {
978 emit( " This conflicts with a previous access by thread #%d, "
979 "after\n",
980 xe->XE.Race.h1_ct->errmsg_index );
981 if (xe->XE.Race.h1_ct_mbsegstartEC) {
982 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
sewardj24118492009-07-15 14:50:02 +0000983 } else {
sewardj23f12002009-07-24 08:45:08 +0000984 emit( " (the start of the thread)\n" );
sewardj24118492009-07-15 14:50:02 +0000985 }
sewardj23f12002009-07-24 08:45:08 +0000986 emit( " but before\n" );
987 if (xe->XE.Race.h1_ct_mbsegendEC) {
988 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
989 } else {
990 emit( " (the end of the the thread)\n" );
991 }
sewardj24118492009-07-15 14:50:02 +0000992 }
993
sewardjf98e1c02008-10-25 16:22:41 +0000994 }
995
sewardj24118492009-07-15 14:50:02 +0000996 /* If we have a better description of the address, show it.
997 Note that in XML mode, it will already by nicely wrapped up
998 in tags, either <auxwhat> or <xauxwhat>, so we can just emit
999 it verbatim. */
1000 if (xe->XE.Race.descr1)
1001 emit( "%s%s\n", xml ? " " : " ",
1002 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
1003 if (xe->XE.Race.descr2)
1004 emit( "%s%s\n", xml ? " " : " ",
1005 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
sewardjf98e1c02008-10-25 16:22:41 +00001006
1007 break; /* case XE_Race */
1008 } /* case XE_Race */
1009
1010 default:
1011 tl_assert(0);
1012 } /* switch (VG_(get_error_kind)(err)) */
1013}
1014
1015Char* HG_(get_error_name) ( Error* err )
1016{
1017 switch (VG_(get_error_kind)(err)) {
1018 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +00001019 case XE_UnlockUnlocked: return "UnlockUnlocked";
1020 case XE_UnlockForeign: return "UnlockForeign";
1021 case XE_UnlockBogus: return "UnlockBogus";
1022 case XE_PthAPIerror: return "PthAPIerror";
1023 case XE_LockOrder: return "LockOrder";
1024 case XE_Misc: return "Misc";
1025 default: tl_assert(0); /* fill in missing case */
1026 }
1027}
1028
1029Bool HG_(recognised_suppression) ( Char* name, Supp *su )
1030{
1031# define TRY(_name,_xskind) \
1032 if (0 == VG_(strcmp)(name, (_name))) { \
1033 VG_(set_supp_kind)(su, (_xskind)); \
1034 return True; \
1035 }
1036 TRY("Race", XS_Race);
1037 TRY("FreeMemLock", XS_FreeMemLock);
1038 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1039 TRY("UnlockForeign", XS_UnlockForeign);
1040 TRY("UnlockBogus", XS_UnlockBogus);
1041 TRY("PthAPIerror", XS_PthAPIerror);
1042 TRY("LockOrder", XS_LockOrder);
1043 TRY("Misc", XS_Misc);
1044 return False;
1045# undef TRY
1046}
1047
njn35db56c2009-07-24 07:38:29 +00001048Bool HG_(read_extra_suppression_info) ( Int fd, Char** bufpp, SizeT* nBufp,
sewardjf98e1c02008-10-25 16:22:41 +00001049 Supp* su )
1050{
1051 /* do nothing -- no extra suppression info present. Return True to
1052 indicate nothing bad happened. */
1053 return True;
1054}
1055
1056Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
1057{
1058 switch (VG_(get_supp_kind)(su)) {
1059 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001060 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1061 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1062 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1063 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1064 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1065 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1066 //case XS_: return VG_(get_error_kind)(err) == XE_;
1067 default: tl_assert(0); /* fill in missing cases */
1068 }
1069}
1070
1071void HG_(print_extra_suppression_info) ( Error* err )
1072{
1073 /* Do nothing */
1074}
1075
1076
1077/*--------------------------------------------------------------------*/
1078/*--- end hg_errors.c ---*/
1079/*--------------------------------------------------------------------*/