blob: 1d1acc2244786db7a77d97403e8a418956d83364 [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 {
177 Addr data_addr;
178 Int szB;
179 Bool isWrite;
180 ExeContext* mb_lastlock;
181 ExeContext* mb_confacc;
182 Thread* thr;
183 Thread* mb_confaccthr;
sewardjc5ea9962008-12-07 01:41:46 +0000184 Int mb_confaccSzB;
185 Bool mb_confaccIsW;
sewardj24118492009-07-15 14:50:02 +0000186 XArray* descr1; /* XArray* of HChar */
187 XArray* descr2; /* XArray* of HChar */
sewardjf98e1c02008-10-25 16:22:41 +0000188 } Race;
189 struct {
sewardjf98e1c02008-10-25 16:22:41 +0000190 Thread* thr; /* doing the unlocking */
191 Lock* lock; /* lock (that is already unlocked) */
192 } UnlockUnlocked;
193 struct {
194 Thread* thr; /* doing the unlocking */
195 Thread* owner; /* thread that actually holds the lock */
196 Lock* lock; /* lock (that is held by 'owner') */
197 } UnlockForeign;
198 struct {
199 Thread* thr; /* doing the unlocking */
200 Addr lock_ga; /* purported address of the lock */
201 } UnlockBogus;
202 struct {
203 Thread* thr;
204 HChar* fnname; /* persistent, in tool-arena */
205 Word err; /* pth error code */
206 HChar* errstr; /* persistent, in tool-arena */
207 } PthAPIerror;
208 struct {
209 Thread* thr;
210 Addr before_ga; /* always locked first in prog. history */
211 Addr after_ga;
212 ExeContext* before_ec;
213 ExeContext* after_ec;
214 } LockOrder;
215 struct {
216 Thread* thr;
217 HChar* errstr; /* persistent, in tool-arena */
218 } Misc;
219 } XE;
220 }
221 XError;
222
223static void init_XError ( XError* xe ) {
224 VG_(memset)(xe, 0, sizeof(*xe) );
225 xe->tag = XE_Race-1; /* bogus */
226}
227
228
229/* Extensions of suppressions */
230typedef
231 enum {
232 XS_Race=1201, /* race */
233 XS_FreeMemLock,
234 XS_UnlockUnlocked,
235 XS_UnlockForeign,
236 XS_UnlockBogus,
237 XS_PthAPIerror,
238 XS_LockOrder,
239 XS_Misc
240 }
241 XSuppTag;
242
243
244/* Updates the copy with address info if necessary. */
245UInt HG_(update_extra) ( Error* err )
246{
247 XError* xe = (XError*)VG_(get_error_extra)(err);
248 tl_assert(xe);
249 //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
250 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
251 //}
252
253 if (xe->tag == XE_Race) {
sewardj24118492009-07-15 14:50:02 +0000254
sewardjf98e1c02008-10-25 16:22:41 +0000255 /* See if we can come up with a source level description of the
256 raced-upon address. This is potentially expensive, which is
257 why it's only done at the update_extra point, not when the
258 error is initially created. */
sewardjc5ea9962008-12-07 01:41:46 +0000259 static Int xxx = 0;
260 xxx++;
261 if (0)
262 VG_(printf)("HG_(update_extra): "
263 "%d conflicting-event queries\n", xxx);
sewardj24118492009-07-15 14:50:02 +0000264 tl_assert(!xe->XE.Race.descr1);
265 tl_assert(!xe->XE.Race.descr2);
266
267 xe->XE.Race.descr1
268 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr1",
269 HG_(free), sizeof(HChar) );
270 xe->XE.Race.descr2
271 = VG_(newXA)( HG_(zalloc), "hg.update_extra.Race.descr2",
272 HG_(free), sizeof(HChar) );
273
274 (void) VG_(get_data_description)( xe->XE.Race.descr1,
275 xe->XE.Race.descr2,
276 xe->XE.Race.data_addr );
277
278 /* If there's nothing in descr1/2, free it. Why is it safe to
279 to VG_(indexXA) at zero here? Because
280 VG_(get_data_description) guarantees to zero terminate
281 descr1/2 regardless of the outcome of the call. So there's
282 always at least one element in each XA after the call.
283 */
284 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr1, 0 ))) {
285 VG_(deleteXA)( xe->XE.Race.descr1 );
286 xe->XE.Race.descr1 = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000287 }
sewardj24118492009-07-15 14:50:02 +0000288 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Race.descr2, 0 ))) {
289 VG_(deleteXA)( xe->XE.Race.descr2 );
290 xe->XE.Race.descr2 = NULL;
291 }
292
293 /* And poke around in the conflicting-event map, to see if we
294 can rustle up a plausible-looking conflicting memory access
295 to show. */
sewardjc5ea9962008-12-07 01:41:46 +0000296 { Thr* thrp = NULL;
297 ExeContext* wherep = NULL;
298 Addr acc_addr = xe->XE.Race.data_addr;
299 Int acc_szB = xe->XE.Race.szB;
300 Thr* acc_thr = xe->XE.Race.thr->hbthr;
301 Bool acc_isW = xe->XE.Race.isWrite;
302 SizeT conf_szB = 0;
303 Bool conf_isW = False;
304 tl_assert(!xe->XE.Race.mb_confacc);
305 tl_assert(!xe->XE.Race.mb_confaccthr);
306 if (libhb_event_map_lookup(
307 &wherep, &thrp, &conf_szB, &conf_isW,
308 acc_thr, acc_addr, acc_szB, acc_isW )) {
309 Thread* threadp;
310 tl_assert(wherep);
311 tl_assert(thrp);
312 threadp = libhb_get_Thr_opaque( thrp );
313 tl_assert(threadp);
314 xe->XE.Race.mb_confacc = wherep;
315 xe->XE.Race.mb_confaccthr = threadp;
316 xe->XE.Race.mb_confaccSzB = (Int)conf_szB;
317 xe->XE.Race.mb_confaccIsW = conf_isW;
318 }
319 }
sewardjf98e1c02008-10-25 16:22:41 +0000320 }
321
322 return sizeof(XError);
323}
324
325void HG_(record_error_Race) ( Thread* thr,
sewardja781be62008-12-08 00:12:28 +0000326 Addr data_addr, Int szB, Bool isWrite,
sewardjc5ea9962008-12-07 01:41:46 +0000327 ExeContext* mb_lastlock )
sewardjf98e1c02008-10-25 16:22:41 +0000328{
329 XError xe;
330 tl_assert( HG_(is_sane_Thread)(thr) );
331
332# if defined(VGO_linux)
333 /* Skip any races on locations apparently in GOTPLT sections. This
334 is said to be caused by ld.so poking PLT table entries (or
335 whatever) when it writes the resolved address of a dynamically
336 linked routine, into the table (or whatever) when it is called
337 for the first time. */
338 {
339 VgSectKind sect = VG_(seginfo_sect_kind)( NULL, 0, data_addr );
340 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
341 data_addr, VG_(pp_SectKind)(sect));
sewardj52104132008-12-23 00:10:26 +0000342 /* SectPLT is required on ???-linux */
sewardjf98e1c02008-10-25 16:22:41 +0000343 if (sect == Vg_SectGOTPLT) return;
sewardj52104132008-12-23 00:10:26 +0000344 /* SectPLT is required on ppc32/64-linux */
345 if (sect == Vg_SectPLT) return;
sewardjf98e1c02008-10-25 16:22:41 +0000346 }
347# endif
348
349 init_XError(&xe);
350 xe.tag = XE_Race;
351 xe.XE.Race.data_addr = data_addr;
352 xe.XE.Race.szB = szB;
353 xe.XE.Race.isWrite = isWrite;
354 xe.XE.Race.mb_lastlock = mb_lastlock;
sewardjf98e1c02008-10-25 16:22:41 +0000355 xe.XE.Race.thr = thr;
sewardjf98e1c02008-10-25 16:22:41 +0000356 tl_assert(isWrite == False || isWrite == True);
sewardja781be62008-12-08 00:12:28 +0000357 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
sewardj24118492009-07-15 14:50:02 +0000358 /* Skip on the detailed description of the raced-on address at this
359 point; it's expensive. Leave it for the update_extra function
360 if we ever make it that far. */
361 tl_assert(xe.XE.Race.descr1 == NULL);
362 tl_assert(xe.XE.Race.descr2 == NULL);
sewardjf98e1c02008-10-25 16:22:41 +0000363 // FIXME: tid vs thr
sewardjc5ea9962008-12-07 01:41:46 +0000364 // Skip on any of the conflicting-access info at this point.
365 // It's expensive to obtain, and this error is more likely than
366 // not to be discarded. We'll fill these fields in in
367 // HG_(update_extra) just above, assuming the error ever makes
368 // it that far (unlikely).
369 xe.XE.Race.mb_confaccSzB = 0;
370 xe.XE.Race.mb_confaccIsW = False;
371 xe.XE.Race.mb_confacc = NULL;
372 xe.XE.Race.mb_confaccthr = NULL;
sewardjf98e1c02008-10-25 16:22:41 +0000373 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
374 tl_assert( thr->coretid != VG_INVALID_THREADID );
375 VG_(maybe_record_error)( thr->coretid,
376 XE_Race, data_addr, NULL, &xe );
377}
378
sewardjf98e1c02008-10-25 16:22:41 +0000379void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
380{
381 XError xe;
382 tl_assert( HG_(is_sane_Thread)(thr) );
383 tl_assert( HG_(is_sane_LockN)(lk) );
384 init_XError(&xe);
385 xe.tag = XE_UnlockUnlocked;
386 xe.XE.UnlockUnlocked.thr = thr;
387 xe.XE.UnlockUnlocked.lock = mk_LockP_from_LockN(lk);
388 // FIXME: tid vs thr
389 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
390 tl_assert( thr->coretid != VG_INVALID_THREADID );
391 VG_(maybe_record_error)( thr->coretid,
392 XE_UnlockUnlocked, 0, NULL, &xe );
393}
394
395void HG_(record_error_UnlockForeign) ( Thread* thr,
396 Thread* owner, Lock* lk )
397{
398 XError xe;
399 tl_assert( HG_(is_sane_Thread)(thr) );
400 tl_assert( HG_(is_sane_Thread)(owner) );
401 tl_assert( HG_(is_sane_LockN)(lk) );
402 init_XError(&xe);
403 xe.tag = XE_UnlockForeign;
404 xe.XE.UnlockForeign.thr = thr;
405 xe.XE.UnlockForeign.owner = owner;
406 xe.XE.UnlockForeign.lock = mk_LockP_from_LockN(lk);
407 // FIXME: tid vs thr
408 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
409 tl_assert( thr->coretid != VG_INVALID_THREADID );
410 VG_(maybe_record_error)( thr->coretid,
411 XE_UnlockForeign, 0, NULL, &xe );
412}
413
414void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
415{
416 XError xe;
417 tl_assert( HG_(is_sane_Thread)(thr) );
418 init_XError(&xe);
419 xe.tag = XE_UnlockBogus;
420 xe.XE.UnlockBogus.thr = thr;
421 xe.XE.UnlockBogus.lock_ga = lock_ga;
422 // FIXME: tid vs thr
423 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
424 tl_assert( thr->coretid != VG_INVALID_THREADID );
425 VG_(maybe_record_error)( thr->coretid,
426 XE_UnlockBogus, 0, NULL, &xe );
427}
428
429void HG_(record_error_LockOrder)(
430 Thread* thr, Addr before_ga, Addr after_ga,
431 ExeContext* before_ec, ExeContext* after_ec
432 )
433{
434 XError xe;
435 tl_assert( HG_(is_sane_Thread)(thr) );
436 if (!HG_(clo_track_lockorders))
437 return;
438 init_XError(&xe);
439 xe.tag = XE_LockOrder;
440 xe.XE.LockOrder.thr = thr;
441 xe.XE.LockOrder.before_ga = before_ga;
442 xe.XE.LockOrder.before_ec = before_ec;
443 xe.XE.LockOrder.after_ga = after_ga;
444 xe.XE.LockOrder.after_ec = after_ec;
445 // FIXME: tid vs thr
446 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
447 tl_assert( thr->coretid != VG_INVALID_THREADID );
448 VG_(maybe_record_error)( thr->coretid,
449 XE_LockOrder, 0, NULL, &xe );
450}
451
452void HG_(record_error_PthAPIerror) ( Thread* thr, HChar* fnname,
453 Word err, HChar* errstr )
454{
455 XError xe;
456 tl_assert( HG_(is_sane_Thread)(thr) );
457 tl_assert(fnname);
458 tl_assert(errstr);
459 init_XError(&xe);
460 xe.tag = XE_PthAPIerror;
461 xe.XE.PthAPIerror.thr = thr;
462 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
463 xe.XE.PthAPIerror.err = err;
464 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
465 // FIXME: tid vs thr
466 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
467 tl_assert( thr->coretid != VG_INVALID_THREADID );
468 VG_(maybe_record_error)( thr->coretid,
469 XE_PthAPIerror, 0, NULL, &xe );
470}
471
472void HG_(record_error_Misc) ( Thread* thr, HChar* errstr )
473{
474 XError xe;
475 tl_assert( HG_(is_sane_Thread)(thr) );
476 tl_assert(errstr);
477 init_XError(&xe);
478 xe.tag = XE_Misc;
479 xe.XE.Misc.thr = thr;
480 xe.XE.Misc.errstr = string_table_strdup(errstr);
481 // FIXME: tid vs thr
482 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
483 tl_assert( thr->coretid != VG_INVALID_THREADID );
484 VG_(maybe_record_error)( thr->coretid,
485 XE_Misc, 0, NULL, &xe );
486}
487
488Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 )
489{
490 XError *xe1, *xe2;
491
492 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
493
494 xe1 = (XError*)VG_(get_error_extra)(e1);
495 xe2 = (XError*)VG_(get_error_extra)(e2);
496 tl_assert(xe1);
497 tl_assert(xe2);
498
499 switch (VG_(get_error_kind)(e1)) {
500 case XE_Race:
501 return xe1->XE.Race.szB == xe2->XE.Race.szB
502 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
503 && (HG_(clo_cmp_race_err_addrs)
504 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
505 : True);
sewardjf98e1c02008-10-25 16:22:41 +0000506 case XE_UnlockUnlocked:
507 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
508 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
509 case XE_UnlockForeign:
510 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
511 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
512 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
513 case XE_UnlockBogus:
514 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
515 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
516 case XE_PthAPIerror:
517 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
518 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
519 xe2->XE.PthAPIerror.fnname)
520 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
521 case XE_LockOrder:
522 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
523 case XE_Misc:
524 return xe1->XE.Misc.thr == xe2->XE.Misc.thr
525 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
526 default:
527 tl_assert(0);
528 }
529
530 /*NOTREACHED*/
531 tl_assert(0);
532}
533
534
sewardj24118492009-07-15 14:50:02 +0000535/*----------------------------------------------------------------*/
536/*--- Error management -- printing ---*/
537/*----------------------------------------------------------------*/
538
539/* Do a printf-style operation on either the XML or normal output
540 channel, depending on the setting of VG_(clo_xml).
541*/
542static void emit_WRK ( HChar* format, va_list vargs )
543{
544 if (VG_(clo_xml)) {
545 VG_(vprintf_xml)(format, vargs);
546 } else {
547 VG_(vmessage)(Vg_UserMsg, format, vargs);
548 }
549}
550static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
551static void emit ( HChar* format, ... )
552{
553 va_list vargs;
554 va_start(vargs, format);
555 emit_WRK(format, vargs);
556 va_end(vargs);
557}
558static void emit_no_f_c ( HChar* format, ... )
559{
560 va_list vargs;
561 va_start(vargs, format);
562 emit_WRK(format, vargs);
563 va_end(vargs);
564}
565
566
sewardjf98e1c02008-10-25 16:22:41 +0000567/* Announce (that is, print the point-of-creation) of 'thr'. Only do
568 this once, as we only want to see these announcements once per
sewardj24118492009-07-15 14:50:02 +0000569 thread. Returned Bool indicates whether or not an announcement was
570 made.
571*/
572static Bool announce_one_thread ( Thread* thr )
sewardjf98e1c02008-10-25 16:22:41 +0000573{
574 tl_assert(HG_(is_sane_Thread)(thr));
575 tl_assert(thr->errmsg_index >= 1);
sewardj24118492009-07-15 14:50:02 +0000576 if (thr->announced)
577 return False;
578
579 if (VG_(clo_xml)) {
580
581 VG_(printf_xml)("<announcethread>\n");
582 VG_(printf_xml)(" <hthreadid>%d</threadid>\n", thr->errmsg_index);
sewardjf98e1c02008-10-25 16:22:41 +0000583 if (thr->errmsg_index == 1) {
584 tl_assert(thr->created_at == NULL);
sewardj24118492009-07-15 14:50:02 +0000585 VG_(printf_xml)(" <isrootthread></isrootthread>\n");
sewardjf98e1c02008-10-25 16:22:41 +0000586 } else {
587 tl_assert(thr->created_at != NULL);
sewardj24118492009-07-15 14:50:02 +0000588 VG_(pp_ExeContext)( thr->created_at );
589 }
590 VG_(printf_xml)("</announcethread>\n\n");
591
592 } else {
593
594 if (thr->errmsg_index == 1) {
595 tl_assert(thr->created_at == NULL);
596 VG_(message)(Vg_UserMsg,
597 "Thread #%d is the program's root thread\n",
598 thr->errmsg_index);
599 } else {
600 tl_assert(thr->created_at != NULL);
601 VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
sewardjf98e1c02008-10-25 16:22:41 +0000602 thr->errmsg_index);
603 VG_(pp_ExeContext)( thr->created_at );
604 }
sewardj24118492009-07-15 14:50:02 +0000605 VG_(message)(Vg_UserMsg, "\n");
606
607 }
608
609 thr->announced = True;
610 return True;
611}
612
613
614/* This is the "this error is due to be printed shortly; so have a
615 look at it any print any preamble you want" function. We use it to
616 announce any previously un-announced threads in the upcoming error
617 message.
618*/
619void HG_(before_pp_Error) ( Error* err )
620{
621 XError* xe;
622 tl_assert(err);
623 xe = (XError*)VG_(get_error_extra)(err);
624 tl_assert(xe);
625
626 switch (VG_(get_error_kind)(err)) {
627 case XE_Misc:
628 announce_one_thread( xe->XE.Misc.thr );
629 break;
630 case XE_LockOrder:
631 announce_one_thread( xe->XE.LockOrder.thr );
632 break;
633 case XE_PthAPIerror:
634 announce_one_thread( xe->XE.PthAPIerror.thr );
635 break;
636 case XE_UnlockBogus:
637 announce_one_thread( xe->XE.UnlockBogus.thr );
638 break;
639 case XE_UnlockForeign:
640 announce_one_thread( xe->XE.UnlockForeign.thr );
641 announce_one_thread( xe->XE.UnlockForeign.owner );
642 break;
643 case XE_UnlockUnlocked:
644 announce_one_thread( xe->XE.UnlockUnlocked.thr );
645 break;
646 case XE_Race:
647 announce_one_thread( xe->XE.Race.thr );
648 if (xe->XE.Race.mb_confaccthr)
649 announce_one_thread( xe->XE.Race.mb_confaccthr );
650 break;
651 default:
652 tl_assert(0);
sewardjf98e1c02008-10-25 16:22:41 +0000653 }
654}
655
656
657void HG_(pp_Error) ( Error* err )
658{
sewardj24118492009-07-15 14:50:02 +0000659 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
660
sewardjf98e1c02008-10-25 16:22:41 +0000661 XError *xe = (XError*)VG_(get_error_extra)(err);
sewardj24118492009-07-15 14:50:02 +0000662 tl_assert(xe);
sewardjf98e1c02008-10-25 16:22:41 +0000663
664 switch (VG_(get_error_kind)(err)) {
665
666 case XE_Misc: {
sewardjf98e1c02008-10-25 16:22:41 +0000667 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
sewardj24118492009-07-15 14:50:02 +0000668
669 if (xml) {
670
671 emit( " <kind>Misc</kind>\n");
672 emit( " <xwhat>\n" );
673 emit( " <text>Thread #%d: %s</text>\n",
674 (Int)xe->XE.Misc.thr->errmsg_index,
675 xe->XE.Misc.errstr );
676 emit( " <hthreadid>%d</hthreadid>\n",
677 (Int)xe->XE.Misc.thr->errmsg_index );
678 emit( " </xwhat>\n" );
679 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
680
681 } else {
682
683 emit( "Thread #%d: %s\n",
684 (Int)xe->XE.Misc.thr->errmsg_index,
685 xe->XE.Misc.errstr );
686 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
687
688 }
sewardjf98e1c02008-10-25 16:22:41 +0000689 break;
690 }
691
692 case XE_LockOrder: {
sewardjf98e1c02008-10-25 16:22:41 +0000693 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
sewardj24118492009-07-15 14:50:02 +0000694
695 if (xml) {
696
697 emit( " <kind>LockOrder</kind>\n");
698 emit( " <xwhat>\n" );
699 emit( " <text>Thread #%d: lock order \"%p before %p\" "
700 "violated</text>\n",
701 (Int)xe->XE.LockOrder.thr->errmsg_index,
702 (void*)xe->XE.LockOrder.before_ga,
703 (void*)xe->XE.LockOrder.after_ga );
704 emit( " <hthreadid>%d</hthreadid>\n",
705 (Int)xe->XE.LockOrder.thr->errmsg_index );
706 emit( " </xwhat>\n" );
707 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
708 if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
709 emit( " <auxwhat>Required order was established by "
710 "acquisition of lock at %p</auxwhat>\n",
711 (void*)xe->XE.LockOrder.before_ga );
712 VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
713 emit( " <auxwhat>followed by a later acquisition "
714 "of lock at %p</auxwhat>\n",
715 (void*)xe->XE.LockOrder.after_ga );
716 VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
717 }
718
719 } else {
720
721 emit( "Thread #%d: lock order \"%p before %p\" violated\n",
722 (Int)xe->XE.LockOrder.thr->errmsg_index,
723 (void*)xe->XE.LockOrder.before_ga,
724 (void*)xe->XE.LockOrder.after_ga );
725 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
726 if (xe->XE.LockOrder.before_ec && xe->XE.LockOrder.after_ec) {
727 emit( " Required order was established by "
728 "acquisition of lock at %p\n",
729 (void*)xe->XE.LockOrder.before_ga );
730 VG_(pp_ExeContext)( xe->XE.LockOrder.before_ec );
731 emit( " followed by a later acquisition of lock at %p\n",
732 (void*)xe->XE.LockOrder.after_ga );
733 VG_(pp_ExeContext)( xe->XE.LockOrder.after_ec );
734 }
735
sewardjf98e1c02008-10-25 16:22:41 +0000736 }
sewardj24118492009-07-15 14:50:02 +0000737
sewardjf98e1c02008-10-25 16:22:41 +0000738 break;
739 }
740
741 case XE_PthAPIerror: {
sewardjf98e1c02008-10-25 16:22:41 +0000742 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
sewardj24118492009-07-15 14:50:02 +0000743
744 if (xml) {
745
746 emit( " <kind>PthAPIerror</kind>\n");
747 emit( " <xwhat>\n" );
748 emit_no_f_c(
749 " <text>Thread #%d's call to %t failed</text>\n",
750 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
751 xe->XE.PthAPIerror.fnname );
752 emit( " <hthreadid>%d</hthreadid>\n",
753 (Int)xe->XE.PthAPIerror.thr->errmsg_index );
754 emit( " </xwhat>\n" );
755 emit( " <what>with error code %ld (%s)</what>\n",
756 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
757 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
758
759 } else {
760
761 emit_no_f_c( "Thread #%d's call to %t failed\n",
762 (Int)xe->XE.PthAPIerror.thr->errmsg_index,
763 xe->XE.PthAPIerror.fnname );
764 emit( " with error code %ld (%s)\n",
765 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
766 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
767
768 }
769
sewardjf98e1c02008-10-25 16:22:41 +0000770 break;
771 }
772
773 case XE_UnlockBogus: {
sewardjf98e1c02008-10-25 16:22:41 +0000774 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
sewardj24118492009-07-15 14:50:02 +0000775
776 if (xml) {
777
778 emit( " <kind>UnlockBogus</kind>\n");
779 emit( " <xwhat>\n" );
780 emit( " <text>Thread #%d unlocked an invalid "
781 "lock at %p</text>\n",
782 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
783 (void*)xe->XE.UnlockBogus.lock_ga );
784 emit( " <hthreadid>%d</hthreadid>\n",
785 (Int)xe->XE.UnlockBogus.thr->errmsg_index );
786 emit( " </xwhat>\n" );
787 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
788
789 } else {
790
791 emit( "Thread #%d unlocked an invalid lock at %p\n",
792 (Int)xe->XE.UnlockBogus.thr->errmsg_index,
793 (void*)xe->XE.UnlockBogus.lock_ga );
794 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
795
796 }
797
sewardjf98e1c02008-10-25 16:22:41 +0000798 break;
799 }
800
801 case XE_UnlockForeign: {
sewardjf98e1c02008-10-25 16:22:41 +0000802 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
803 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
804 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
sewardj24118492009-07-15 14:50:02 +0000805
806 if (xml) {
807
808 emit( " <kind>UnlockForeign</kind>\n");
809 emit( " <xwhat>\n" );
810 emit( " <text>Thread #%d unlocked lock at %p "
811 "currently held by thread #%d</text>\n",
812 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
813 (void*)xe->XE.UnlockForeign.lock->guestaddr,
814 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
815 emit( " <hthreadid>%d</hthreadid>\n",
816 (Int)xe->XE.UnlockForeign.thr->errmsg_index );
817 emit( " <hthreadid>%d</hthreadid>\n",
818 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
819 emit( " </xwhat>\n" );
820 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
821
822 if (xe->XE.UnlockForeign.lock->appeared_at) {
823 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
824 (void*)xe->XE.UnlockForeign.lock->guestaddr );
825 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
826 }
827
828 } else {
829
830 emit( "Thread #%d unlocked lock at %p "
831 "currently held by thread #%d\n",
832 (Int)xe->XE.UnlockForeign.thr->errmsg_index,
833 (void*)xe->XE.UnlockForeign.lock->guestaddr,
834 (Int)xe->XE.UnlockForeign.owner->errmsg_index );
835 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
836 if (xe->XE.UnlockForeign.lock->appeared_at) {
837 emit( " Lock at %p was first observed\n",
838 (void*)xe->XE.UnlockForeign.lock->guestaddr );
839 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at );
840 }
841
sewardjf98e1c02008-10-25 16:22:41 +0000842 }
sewardj24118492009-07-15 14:50:02 +0000843
sewardjf98e1c02008-10-25 16:22:41 +0000844 break;
845 }
846
847 case XE_UnlockUnlocked: {
sewardjf98e1c02008-10-25 16:22:41 +0000848 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
849 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
sewardjf98e1c02008-10-25 16:22:41 +0000850
sewardj24118492009-07-15 14:50:02 +0000851 if (xml) {
852
853 emit( " <kind>UnlockUnlocked</kind>\n");
854 emit( " <xwhat>\n" );
855 emit( " <text>Thread #%d unlocked a "
856 "not-locked lock at %p</text>\n",
857 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
858 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
859 emit( " <hthreadid>%d</hthreadid>\n",
860 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
861 emit( " </xwhat>\n" );
862 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
863 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
864 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n",
865 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
866 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
867 }
868
869 } else {
870
871 emit( "Thread #%d unlocked a not-locked lock at %p\n",
872 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
873 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
874 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
875 if (xe->XE.UnlockUnlocked.lock->appeared_at) {
876 emit( " Lock at %p was first observed\n",
877 (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
878 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at );
879 }
880
sewardjf98e1c02008-10-25 16:22:41 +0000881 }
sewardj24118492009-07-15 14:50:02 +0000882
sewardjf98e1c02008-10-25 16:22:41 +0000883 break;
884 }
885
886 case XE_Race: {
887 Addr err_ga;
888 HChar* what;
889 Int szB;
890 what = xe->XE.Race.isWrite ? "write" : "read";
891 szB = xe->XE.Race.szB;
892 err_ga = VG_(get_error_address)(err);
893
sewardj24118492009-07-15 14:50:02 +0000894 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
sewardjf98e1c02008-10-25 16:22:41 +0000895 if (xe->XE.Race.mb_confaccthr)
sewardj24118492009-07-15 14:50:02 +0000896 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.mb_confaccthr ));
897
898 if (xml) {
899
900 /* ------ XML ------ */
901 emit( " <kind>Race</kind>\n" );
902 emit( " <xwhat>\n" );
903 emit( " <text>Possible data race during %s of size %d "
904 "at %#lx by thread #%d</text>\n",
905 what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
906 emit( " <hthreadid>%d</hthreadid>\n",
907 (Int)xe->XE.Race.thr->errmsg_index );
908 emit( " </xwhat>\n" );
909 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
910
911 if (xe->XE.Race.mb_confacc) {
912 if (xe->XE.Race.mb_confaccthr) {
913 emit( " <xauxwhat>\n");
914 emit( " <text>This conflicts with a previous %s of size %d "
915 "by thread #%d</text>\n",
916 xe->XE.Race.mb_confaccIsW ? "write" : "read",
917 xe->XE.Race.mb_confaccSzB,
918 xe->XE.Race.mb_confaccthr->errmsg_index );
919 emit( " <hthreadid>%d</hthreadid>\n",
920 xe->XE.Race.mb_confaccthr->errmsg_index);
921 emit(" </xauxwhat>\n");
922 } else {
923 // FIXME: can this ever happen?
924 emit( " <auxwhat>This conflicts with a previous %s "
925 "of size %d</auxwhat>\n",
926 xe->XE.Race.mb_confaccIsW ? "write" : "read",
927 xe->XE.Race.mb_confaccSzB );
928 }
929 VG_(pp_ExeContext)( xe->XE.Race.mb_confacc );
sewardjf98e1c02008-10-25 16:22:41 +0000930 }
sewardj24118492009-07-15 14:50:02 +0000931
932 } else {
933
934 /* ------ Text ------ */
935 emit( "Possible data race during %s of size %d "
936 "at %#lx by thread #%d\n",
937 what, szB, err_ga, (Int)xe->XE.Race.thr->errmsg_index );
938 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
939 if (xe->XE.Race.mb_confacc) {
940 if (xe->XE.Race.mb_confaccthr) {
941 emit( " This conflicts with a previous %s of size %d "
942 "by thread #%d\n",
943 xe->XE.Race.mb_confaccIsW ? "write" : "read",
944 xe->XE.Race.mb_confaccSzB,
945 xe->XE.Race.mb_confaccthr->errmsg_index );
946 } else {
947 // FIXME: can this ever happen?
948 emit( " This conflicts with a previous %s of size %d\n",
949 xe->XE.Race.mb_confaccIsW ? "write" : "read",
950 xe->XE.Race.mb_confaccSzB );
951 }
952 VG_(pp_ExeContext)( xe->XE.Race.mb_confacc );
953 }
954
sewardjf98e1c02008-10-25 16:22:41 +0000955 }
956
sewardj24118492009-07-15 14:50:02 +0000957 /* If we have a better description of the address, show it.
958 Note that in XML mode, it will already by nicely wrapped up
959 in tags, either <auxwhat> or <xauxwhat>, so we can just emit
960 it verbatim. */
961 if (xe->XE.Race.descr1)
962 emit( "%s%s\n", xml ? " " : " ",
963 (HChar*)VG_(indexXA)( xe->XE.Race.descr1, 0 ) );
964 if (xe->XE.Race.descr2)
965 emit( "%s%s\n", xml ? " " : " ",
966 (HChar*)VG_(indexXA)( xe->XE.Race.descr2, 0 ) );
sewardjf98e1c02008-10-25 16:22:41 +0000967
968 break; /* case XE_Race */
969 } /* case XE_Race */
970
971 default:
972 tl_assert(0);
973 } /* switch (VG_(get_error_kind)(err)) */
974}
975
976Char* HG_(get_error_name) ( Error* err )
977{
978 switch (VG_(get_error_kind)(err)) {
979 case XE_Race: return "Race";
sewardjf98e1c02008-10-25 16:22:41 +0000980 case XE_UnlockUnlocked: return "UnlockUnlocked";
981 case XE_UnlockForeign: return "UnlockForeign";
982 case XE_UnlockBogus: return "UnlockBogus";
983 case XE_PthAPIerror: return "PthAPIerror";
984 case XE_LockOrder: return "LockOrder";
985 case XE_Misc: return "Misc";
986 default: tl_assert(0); /* fill in missing case */
987 }
988}
989
990Bool HG_(recognised_suppression) ( Char* name, Supp *su )
991{
992# define TRY(_name,_xskind) \
993 if (0 == VG_(strcmp)(name, (_name))) { \
994 VG_(set_supp_kind)(su, (_xskind)); \
995 return True; \
996 }
997 TRY("Race", XS_Race);
998 TRY("FreeMemLock", XS_FreeMemLock);
999 TRY("UnlockUnlocked", XS_UnlockUnlocked);
1000 TRY("UnlockForeign", XS_UnlockForeign);
1001 TRY("UnlockBogus", XS_UnlockBogus);
1002 TRY("PthAPIerror", XS_PthAPIerror);
1003 TRY("LockOrder", XS_LockOrder);
1004 TRY("Misc", XS_Misc);
1005 return False;
1006# undef TRY
1007}
1008
1009Bool HG_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf,
1010 Supp* su )
1011{
1012 /* do nothing -- no extra suppression info present. Return True to
1013 indicate nothing bad happened. */
1014 return True;
1015}
1016
1017Bool HG_(error_matches_suppression) ( Error* err, Supp* su )
1018{
1019 switch (VG_(get_supp_kind)(su)) {
1020 case XS_Race: return VG_(get_error_kind)(err) == XE_Race;
sewardjf98e1c02008-10-25 16:22:41 +00001021 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1022 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign;
1023 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus;
1024 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror;
1025 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder;
1026 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc;
1027 //case XS_: return VG_(get_error_kind)(err) == XE_;
1028 default: tl_assert(0); /* fill in missing cases */
1029 }
1030}
1031
1032void HG_(print_extra_suppression_info) ( Error* err )
1033{
1034 /* Do nothing */
1035}
1036
1037
1038/*--------------------------------------------------------------------*/
1039/*--- end hg_errors.c ---*/
1040/*--------------------------------------------------------------------*/