1 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 11 Copyright (C) 2007-2013 OpenWorks Ltd 12 info (at) 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" 42 #include "pub_tool_options.h" // VG_(clo_xml) 43 #include "pub_tool_addrinfo.h" 44 45 #include "hg_basics.h" 46 #include "hg_addrdescr.h" 47 #include "hg_wordset.h" 48 #include "hg_lock_n_thread.h" 49 #include "libhb.h" 50 #include "hg_errors.h" /* self */ 51 52 53 /*----------------------------------------------------------------*/ 54 /*--- Error management -- storage ---*/ 55 /*----------------------------------------------------------------*/ 56 57 /* maps (by value) strings to a copy of them in ARENA_TOOL */ 58 59 static WordFM* string_table = NULL; 60 61 ULong HG_(stats__string_table_queries) = 0; 62 63 ULong HG_(stats__string_table_get_map_size) ( void ) { 64 return string_table ? (ULong)VG_(sizeFM)(string_table) : 0; 65 } 66 67 static Word string_table_cmp ( UWord s1, UWord s2 ) { 68 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 ); 69 } 70 71 static HChar* string_table_strdup ( const HChar* str ) { 72 HChar* copy = NULL; 73 HG_(stats__string_table_queries)++; 74 if (!str) 75 str = "(null)"; 76 if (!string_table) { 77 string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1", 78 HG_(free), string_table_cmp ); 79 tl_assert(string_table); 80 } 81 if (VG_(lookupFM)( string_table, 82 NULL, (UWord*)©, (UWord)str )) { 83 tl_assert(copy); 84 if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy ); 85 return copy; 86 } else { 87 copy = HG_(strdup)("hg.sts.2", str); 88 tl_assert(copy); 89 VG_(addToFM)( string_table, (UWord)copy, (UWord)copy ); 90 return copy; 91 } 92 } 93 94 /* maps from Lock .unique fields to LockP*s */ 95 96 static WordFM* map_LockN_to_P = NULL; 97 98 ULong HG_(stats__LockN_to_P_queries) = 0; 99 100 ULong HG_(stats__LockN_to_P_get_map_size) ( void ) { 101 return map_LockN_to_P ? (ULong)VG_(sizeFM)(map_LockN_to_P) : 0; 102 } 103 104 static Word lock_unique_cmp ( UWord lk1W, UWord lk2W ) 105 { 106 Lock* lk1 = (Lock*)lk1W; 107 Lock* lk2 = (Lock*)lk2W; 108 tl_assert( HG_(is_sane_LockNorP)(lk1) ); 109 tl_assert( HG_(is_sane_LockNorP)(lk2) ); 110 if (lk1->unique < lk2->unique) return -1; 111 if (lk1->unique > lk2->unique) return 1; 112 return 0; 113 } 114 115 /* Given a normal Lock (LockN), convert it to a persistent Lock 116 (LockP). In some cases the LockN could be invalid (if it's been 117 freed), so we enquire, in hg_main.c's admin_locks list, whether it 118 is in fact valid. If allowed_to_be_invalid is True, then it's OK 119 for the LockN to be invalid, in which case Lock_INVALID is 120 returned. In all other cases, we insist that the LockN is a valid 121 lock, and return its corresponding LockP. 122 123 Why can LockNs sometimes be invalid? Because they are harvested 124 from locksets that are attached to the OldRef info for conflicting 125 threads. By the time we detect a race, the some of the elements of 126 the lockset may have been destroyed by the client, in which case 127 the corresponding Lock structures we maintain will have been freed. 128 129 So we check that each LockN is a member of the admin_locks double 130 linked list of all Lock structures. That stops us prodding around 131 in potentially freed-up Lock structures. However, it's not quite a 132 proper check: if a new Lock has been reallocated at the same 133 address as one which was previously freed, we'll wind up copying 134 the new one as the basis for the LockP, which is completely bogus 135 because it is unrelated to the previous Lock that lived there. 136 Let's hope that doesn't happen too often. 137 */ 138 static Lock* mk_LockP_from_LockN ( Lock* lkn, 139 Bool allowed_to_be_invalid ) 140 { 141 Lock* lkp = NULL; 142 HG_(stats__LockN_to_P_queries)++; 143 144 /* First off, let's do some sanity checks. If 145 allowed_to_be_invalid is False, we _must_ be able to find 'lkn' 146 in admin_locks; else we must assert. If it is True, it's OK for 147 it not to be findable, but in that case we must return 148 Lock_INVALID right away. */ 149 Lock* lock_list = HG_(get_admin_locks)(); 150 while (lock_list) { 151 if (lock_list == lkn) 152 break; 153 lock_list = lock_list->admin_next; 154 } 155 if (lock_list == NULL) { 156 /* We didn't find it. That possibility has to be OK'd by the 157 caller. */ 158 tl_assert(allowed_to_be_invalid); 159 return Lock_INVALID; 160 } 161 162 /* So we must be looking at a valid LockN. */ 163 tl_assert( HG_(is_sane_LockN)(lkn) ); 164 165 if (!map_LockN_to_P) { 166 map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1", 167 HG_(free), lock_unique_cmp ); 168 tl_assert(map_LockN_to_P); 169 } 170 if (!VG_(lookupFM)( map_LockN_to_P, NULL, (UWord*)&lkp, (UWord)lkn)) { 171 lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) ); 172 *lkp = *lkn; 173 lkp->admin_next = NULL; 174 lkp->admin_prev = NULL; 175 lkp->magic = LockP_MAGIC; 176 /* Forget about the bag of lock holders - don't copy that. 177 Also, acquired_at should be NULL whenever heldBy is, and vice 178 versa. Also forget about the associated libhb synch object. */ 179 lkp->heldW = False; 180 lkp->heldBy = NULL; 181 lkp->acquired_at = NULL; 182 lkp->hbso = NULL; 183 VG_(addToFM)( map_LockN_to_P, (UWord)lkp, (UWord)lkp ); 184 } 185 tl_assert( HG_(is_sane_LockP)(lkp) ); 186 return lkp; 187 } 188 189 /* Expand a WordSet of LockN*'s into a NULL-terminated vector of 190 LockP*'s. Any LockN's that can't be converted into a LockP 191 (because they have been freed, see comment on mk_LockP_from_LockN) 192 are converted instead into the value Lock_INVALID. Hence the 193 returned vector is a sequence: zero or more (valid LockP* or 194 LockN_INVALID), terminated by a NULL. */ 195 static 196 Lock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets, 197 WordSetID lockset, 198 Bool allowed_to_be_invalid ) 199 { 200 tl_assert(univ_lsets); 201 tl_assert( HG_(plausibleWS)(univ_lsets, lockset) ); 202 UWord nLocks = HG_(cardinalityWS)(univ_lsets, lockset); 203 Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa", 204 (nLocks+1) * sizeof(Lock*) ); 205 tl_assert(lockPs); 206 tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */ 207 UWord* lockNs = NULL; 208 UWord nLockNs = 0; 209 if (nLocks > 0) { 210 /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the 211 lockset is empty; hence the guarding "if". Sigh. */ 212 HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset ); 213 tl_assert(lockNs); 214 } 215 UWord i; 216 /* Convert to LockPs. */ 217 for (i = 0; i < nLockNs; i++) { 218 lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i], 219 allowed_to_be_invalid ); 220 } 221 return lockPs; 222 } 223 224 /* Get the number of useful elements in a vector created by 225 enumerate_WordSet_into_LockP_vector. Returns both the total number 226 of elements (not including the terminating NULL) and the number of 227 non-Lock_INVALID elements. */ 228 static void count_LockP_vector ( /*OUT*/UWord* nLocks, 229 /*OUT*/UWord* nLocksValid, 230 Lock** vec ) 231 { 232 tl_assert(vec); 233 *nLocks = *nLocksValid = 0; 234 UWord n = 0; 235 while (vec[n]) { 236 (*nLocks)++; 237 if (vec[n] != Lock_INVALID) 238 (*nLocksValid)++; 239 n++; 240 } 241 } 242 243 /* Find out whether 'lk' is in 'vec'. */ 244 static Bool elem_LockP_vector ( Lock** vec, Lock* lk ) 245 { 246 tl_assert(vec); 247 tl_assert(lk); 248 UWord n = 0; 249 while (vec[n]) { 250 if (vec[n] == lk) 251 return True; 252 n++; 253 } 254 return False; 255 } 256 257 258 /* Errors: 259 260 race: program counter 261 read or write 262 data size 263 previous state 264 current state 265 266 FIXME: how does state printing interact with lockset gc? 267 Are the locksets in prev/curr state always valid? 268 Ditto question for the threadsets 269 ThreadSets - probably are always valid if Threads 270 are never thrown away. 271 LockSets - could at least print the lockset elements that 272 correspond to actual locks at the time of printing. Hmm. 273 */ 274 275 /* Error kinds */ 276 typedef 277 enum { 278 XE_Race=1101, // race 279 XE_UnlockUnlocked, // unlocking a not-locked lock 280 XE_UnlockForeign, // unlocking a lock held by some other thread 281 XE_UnlockBogus, // unlocking an address not known to be a lock 282 XE_PthAPIerror, // error from the POSIX pthreads API 283 XE_LockOrder, // lock order error 284 XE_Misc // misc other error (w/ string to describe it) 285 } 286 XErrorTag; 287 288 /* Extra contexts for kinds */ 289 typedef 290 struct { 291 XErrorTag tag; 292 union { 293 struct { 294 Addr data_addr; 295 Int szB; 296 AddrInfo data_addrinfo; 297 Bool isWrite; 298 Thread* thr; 299 Lock** locksHeldW; 300 /* h1_* and h2_* provide some description of a previously 301 observed access with which we are conflicting. */ 302 Thread* h1_ct; /* non-NULL means h1 info present */ 303 ExeContext* h1_ct_mbsegstartEC; 304 ExeContext* h1_ct_mbsegendEC; 305 Thread* h2_ct; /* non-NULL means h2 info present */ 306 ExeContext* h2_ct_accEC; 307 Int h2_ct_accSzB; 308 Bool h2_ct_accIsW; 309 Lock** h2_ct_locksHeldW; 310 } Race; 311 struct { 312 Thread* thr; /* doing the unlocking */ 313 Lock* lock; /* lock (that is already unlocked) */ 314 } UnlockUnlocked; 315 struct { 316 Thread* thr; /* doing the unlocking */ 317 Thread* owner; /* thread that actually holds the lock */ 318 Lock* lock; /* lock (that is held by 'owner') */ 319 } UnlockForeign; 320 struct { 321 Thread* thr; /* doing the unlocking */ 322 Addr lock_ga; /* purported address of the lock */ 323 } UnlockBogus; 324 struct { 325 Thread* thr; 326 HChar* fnname; /* persistent, in tool-arena */ 327 Word err; /* pth error code */ 328 HChar* errstr; /* persistent, in tool-arena */ 329 } PthAPIerror; 330 struct { 331 Thread* thr; 332 /* The first 4 fields describe the previously observed 333 (should-be) ordering. */ 334 Addr shouldbe_earlier_ga; 335 Addr shouldbe_later_ga; 336 ExeContext* shouldbe_earlier_ec; 337 ExeContext* shouldbe_later_ec; 338 /* In principle we need to record two more stacks, from 339 this thread, when acquiring the locks in the "wrong" 340 order. In fact the wallclock-later acquisition by this 341 thread is recorded in the main stack for this error. 342 So we only need a stack for the earlier acquisition by 343 this thread. */ 344 ExeContext* actual_earlier_ec; 345 } LockOrder; 346 struct { 347 Thread* thr; 348 HChar* errstr; /* persistent, in tool-arena */ 349 HChar* auxstr; /* optional, persistent, in tool-arena */ 350 ExeContext* auxctx; /* optional */ 351 } Misc; 352 } XE; 353 } 354 XError; 355 356 static void init_XError ( XError* xe ) { 357 VG_(memset)(xe, 0, sizeof(*xe) ); 358 xe->tag = XE_Race-1; /* bogus */ 359 } 360 361 362 /* Extensions of suppressions */ 363 typedef 364 enum { 365 XS_Race=1201, /* race */ 366 XS_FreeMemLock, 367 XS_UnlockUnlocked, 368 XS_UnlockForeign, 369 XS_UnlockBogus, 370 XS_PthAPIerror, 371 XS_LockOrder, 372 XS_Misc 373 } 374 XSuppTag; 375 376 377 /* Updates the copy with address info if necessary. */ 378 UInt HG_(update_extra) ( Error* err ) 379 { 380 XError* xe = (XError*)VG_(get_error_extra)(err); 381 tl_assert(xe); 382 //if (extra != NULL && Undescribed == extra->addrinfo.akind) { 383 // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) ); 384 //} 385 386 if (xe->tag == XE_Race) { 387 388 /* Note the set of locks that the thread is (w-)holding. 389 Convert the WordSetID of LockN*'s into a NULL-terminated 390 vector of LockP*'s. We don't expect to encounter any invalid 391 LockNs in this conversion. */ 392 tl_assert(xe->XE.Race.thr); 393 xe->XE.Race.locksHeldW 394 = enumerate_WordSet_into_LockP_vector( 395 HG_(get_univ_lsets)(), 396 xe->XE.Race.thr->locksetW, 397 False/*!allowed_to_be_invalid*/ 398 ); 399 400 /* See if we can come up with a source level description of the 401 raced-upon address. This is potentially expensive, which is 402 why it's only done at the update_extra point, not when the 403 error is initially created. */ 404 static Int xxx = 0; 405 xxx++; 406 if (0) 407 VG_(printf)("HG_(update_extra): " 408 "%d conflicting-event queries\n", xxx); 409 410 HG_(describe_addr) (xe->XE.Race.data_addr, &xe->XE.Race.data_addrinfo); 411 412 /* And poke around in the conflicting-event map, to see if we 413 can rustle up a plausible-looking conflicting memory access 414 to show. */ 415 if (HG_(clo_history_level) >= 2) { 416 Thr* thrp = NULL; 417 ExeContext* wherep = NULL; 418 Addr acc_addr = xe->XE.Race.data_addr; 419 Int acc_szB = xe->XE.Race.szB; 420 Thr* acc_thr = xe->XE.Race.thr->hbthr; 421 Bool acc_isW = xe->XE.Race.isWrite; 422 SizeT conf_szB = 0; 423 Bool conf_isW = False; 424 WordSetID conf_locksHeldW = 0; 425 tl_assert(!xe->XE.Race.h2_ct_accEC); 426 tl_assert(!xe->XE.Race.h2_ct); 427 if (libhb_event_map_lookup( 428 &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW, 429 acc_thr, acc_addr, acc_szB, acc_isW )) { 430 Thread* threadp; 431 tl_assert(wherep); 432 tl_assert(thrp); 433 threadp = libhb_get_Thr_hgthread( thrp ); 434 tl_assert(threadp); 435 xe->XE.Race.h2_ct_accEC = wherep; 436 xe->XE.Race.h2_ct = threadp; 437 xe->XE.Race.h2_ct_accSzB = (Int)conf_szB; 438 xe->XE.Race.h2_ct_accIsW = conf_isW; 439 xe->XE.Race.h2_ct_locksHeldW 440 = enumerate_WordSet_into_LockP_vector( 441 HG_(get_univ_lsets)(), 442 conf_locksHeldW, 443 True/*allowed_to_be_invalid*/ 444 ); 445 } 446 } 447 448 // both NULL or both non-NULL 449 tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) ); 450 } 451 452 return sizeof(XError); 453 } 454 455 void HG_(record_error_Race) ( Thread* thr, 456 Addr data_addr, Int szB, Bool isWrite, 457 Thread* h1_ct, 458 ExeContext* h1_ct_segstart, 459 ExeContext* h1_ct_mbsegendEC ) 460 { 461 XError xe; 462 tl_assert( HG_(is_sane_Thread)(thr) ); 463 464 # if defined(VGO_linux) 465 /* Skip any races on locations apparently in GOTPLT sections. This 466 is said to be caused by ld.so poking PLT table entries (or 467 whatever) when it writes the resolved address of a dynamically 468 linked routine, into the table (or whatever) when it is called 469 for the first time. */ 470 { 471 VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr ); 472 if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n", 473 data_addr, VG_(pp_SectKind)(sect)); 474 /* SectPLT is required on ???-linux */ 475 if (sect == Vg_SectGOTPLT) return; 476 /* SectPLT is required on ppc32/64-linux */ 477 if (sect == Vg_SectPLT) return; 478 } 479 # endif 480 481 init_XError(&xe); 482 xe.tag = XE_Race; 483 xe.XE.Race.data_addr = data_addr; 484 xe.XE.Race.szB = szB; 485 xe.XE.Race.isWrite = isWrite; 486 xe.XE.Race.thr = thr; 487 tl_assert(isWrite == False || isWrite == True); 488 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1); 489 /* Skip on the detailed description of the raced-on address at this 490 point; it's expensive. Leave it for the update_extra function 491 if we ever make it that far. */ 492 xe.XE.Race.data_addrinfo.tag = Addr_Undescribed; 493 // FIXME: tid vs thr 494 // Skip on any of the conflicting-access info at this point. 495 // It's expensive to obtain, and this error is more likely than 496 // not to be discarded. We'll fill these fields in in 497 // HG_(update_extra) just above, assuming the error ever makes 498 // it that far (unlikely). 499 xe.XE.Race.h2_ct_accSzB = 0; 500 xe.XE.Race.h2_ct_accIsW = False; 501 xe.XE.Race.h2_ct_accEC = NULL; 502 xe.XE.Race.h2_ct = NULL; 503 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 504 tl_assert( thr->coretid != VG_INVALID_THREADID ); 505 506 xe.XE.Race.h1_ct = h1_ct; 507 xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart; 508 xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC; 509 510 VG_(maybe_record_error)( thr->coretid, 511 XE_Race, data_addr, NULL, &xe ); 512 } 513 514 void HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk ) 515 { 516 XError xe; 517 tl_assert( HG_(is_sane_Thread)(thr) ); 518 tl_assert( HG_(is_sane_LockN)(lk) ); 519 init_XError(&xe); 520 xe.tag = XE_UnlockUnlocked; 521 xe.XE.UnlockUnlocked.thr 522 = thr; 523 xe.XE.UnlockUnlocked.lock 524 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/); 525 // FIXME: tid vs thr 526 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 527 tl_assert( thr->coretid != VG_INVALID_THREADID ); 528 VG_(maybe_record_error)( thr->coretid, 529 XE_UnlockUnlocked, 0, NULL, &xe ); 530 } 531 532 void HG_(record_error_UnlockForeign) ( Thread* thr, 533 Thread* owner, Lock* lk ) 534 { 535 XError xe; 536 tl_assert( HG_(is_sane_Thread)(thr) ); 537 tl_assert( HG_(is_sane_Thread)(owner) ); 538 tl_assert( HG_(is_sane_LockN)(lk) ); 539 init_XError(&xe); 540 xe.tag = XE_UnlockForeign; 541 xe.XE.UnlockForeign.thr = thr; 542 xe.XE.UnlockForeign.owner = owner; 543 xe.XE.UnlockForeign.lock 544 = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/); 545 // FIXME: tid vs thr 546 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 547 tl_assert( thr->coretid != VG_INVALID_THREADID ); 548 VG_(maybe_record_error)( thr->coretid, 549 XE_UnlockForeign, 0, NULL, &xe ); 550 } 551 552 void HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga ) 553 { 554 XError xe; 555 tl_assert( HG_(is_sane_Thread)(thr) ); 556 init_XError(&xe); 557 xe.tag = XE_UnlockBogus; 558 xe.XE.UnlockBogus.thr = thr; 559 xe.XE.UnlockBogus.lock_ga = lock_ga; 560 // FIXME: tid vs thr 561 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 562 tl_assert( thr->coretid != VG_INVALID_THREADID ); 563 VG_(maybe_record_error)( thr->coretid, 564 XE_UnlockBogus, 0, NULL, &xe ); 565 } 566 567 void HG_(record_error_LockOrder)( 568 Thread* thr, 569 Addr shouldbe_earlier_ga, 570 Addr shouldbe_later_ga, 571 ExeContext* shouldbe_earlier_ec, 572 ExeContext* shouldbe_later_ec, 573 ExeContext* actual_earlier_ec 574 ) 575 { 576 XError xe; 577 tl_assert( HG_(is_sane_Thread)(thr) ); 578 tl_assert(HG_(clo_track_lockorders)); 579 init_XError(&xe); 580 xe.tag = XE_LockOrder; 581 xe.XE.LockOrder.thr = thr; 582 xe.XE.LockOrder.shouldbe_earlier_ga = shouldbe_earlier_ga; 583 xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec; 584 xe.XE.LockOrder.shouldbe_later_ga = shouldbe_later_ga; 585 xe.XE.LockOrder.shouldbe_later_ec = shouldbe_later_ec; 586 xe.XE.LockOrder.actual_earlier_ec = actual_earlier_ec; 587 // FIXME: tid vs thr 588 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 589 tl_assert( thr->coretid != VG_INVALID_THREADID ); 590 VG_(maybe_record_error)( thr->coretid, 591 XE_LockOrder, 0, NULL, &xe ); 592 } 593 594 void HG_(record_error_PthAPIerror) ( Thread* thr, const HChar* fnname, 595 Word err, const HChar* errstr ) 596 { 597 XError xe; 598 tl_assert( HG_(is_sane_Thread)(thr) ); 599 tl_assert(fnname); 600 tl_assert(errstr); 601 init_XError(&xe); 602 xe.tag = XE_PthAPIerror; 603 xe.XE.PthAPIerror.thr = thr; 604 xe.XE.PthAPIerror.fnname = string_table_strdup(fnname); 605 xe.XE.PthAPIerror.err = err; 606 xe.XE.PthAPIerror.errstr = string_table_strdup(errstr); 607 // FIXME: tid vs thr 608 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 609 tl_assert( thr->coretid != VG_INVALID_THREADID ); 610 VG_(maybe_record_error)( thr->coretid, 611 XE_PthAPIerror, 0, NULL, &xe ); 612 } 613 614 void HG_(record_error_Misc_w_aux) ( Thread* thr, const HChar* errstr, 615 const HChar* auxstr, ExeContext* auxctx ) 616 { 617 XError xe; 618 tl_assert( HG_(is_sane_Thread)(thr) ); 619 tl_assert(errstr); 620 init_XError(&xe); 621 xe.tag = XE_Misc; 622 xe.XE.Misc.thr = thr; 623 xe.XE.Misc.errstr = string_table_strdup(errstr); 624 xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL; 625 xe.XE.Misc.auxctx = auxctx; 626 // FIXME: tid vs thr 627 tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 628 tl_assert( thr->coretid != VG_INVALID_THREADID ); 629 VG_(maybe_record_error)( thr->coretid, 630 XE_Misc, 0, NULL, &xe ); 631 } 632 633 void HG_(record_error_Misc) ( Thread* thr, const HChar* errstr ) 634 { 635 HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL); 636 } 637 638 Bool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 ) 639 { 640 XError *xe1, *xe2; 641 642 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2)); 643 644 xe1 = (XError*)VG_(get_error_extra)(e1); 645 xe2 = (XError*)VG_(get_error_extra)(e2); 646 tl_assert(xe1); 647 tl_assert(xe2); 648 649 switch (VG_(get_error_kind)(e1)) { 650 case XE_Race: 651 return xe1->XE.Race.szB == xe2->XE.Race.szB 652 && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite 653 && (HG_(clo_cmp_race_err_addrs) 654 ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr 655 : True); 656 case XE_UnlockUnlocked: 657 return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr 658 && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock; 659 case XE_UnlockForeign: 660 return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr 661 && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner 662 && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock; 663 case XE_UnlockBogus: 664 return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr 665 && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga; 666 case XE_PthAPIerror: 667 return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr 668 && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname, 669 xe2->XE.PthAPIerror.fnname) 670 && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err; 671 case XE_LockOrder: 672 return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr; 673 case XE_Misc: 674 return xe1->XE.Misc.thr == xe2->XE.Misc.thr 675 && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr); 676 default: 677 tl_assert(0); 678 } 679 680 /*NOTREACHED*/ 681 tl_assert(0); 682 } 683 684 685 /*----------------------------------------------------------------*/ 686 /*--- Error management -- printing ---*/ 687 /*----------------------------------------------------------------*/ 688 689 /* Do a printf-style operation on either the XML or normal output 690 channel, depending on the setting of VG_(clo_xml). 691 */ 692 static void emit_WRK ( const HChar* format, va_list vargs ) 693 { 694 if (VG_(clo_xml)) { 695 VG_(vprintf_xml)(format, vargs); 696 } else { 697 VG_(vmessage)(Vg_UserMsg, format, vargs); 698 } 699 } 700 static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2); 701 static void emit ( const HChar* format, ... ) 702 { 703 va_list vargs; 704 va_start(vargs, format); 705 emit_WRK(format, vargs); 706 va_end(vargs); 707 } 708 709 710 /* Announce (that is, print the point-of-creation) of 'thr'. Only do 711 this once, as we only want to see these announcements once per 712 thread. Returned Bool indicates whether or not an announcement was 713 made. 714 */ 715 static Bool announce_one_thread ( Thread* thr ) 716 { 717 tl_assert(HG_(is_sane_Thread)(thr)); 718 tl_assert(thr->errmsg_index >= 1); 719 if (thr->announced) 720 return False; 721 722 if (VG_(clo_xml)) { 723 724 VG_(printf_xml)("<announcethread>\n"); 725 VG_(printf_xml)(" <hthreadid>%d</hthreadid>\n", thr->errmsg_index); 726 if (thr->errmsg_index == 1) { 727 tl_assert(thr->created_at == NULL); 728 VG_(printf_xml)(" <isrootthread></isrootthread>\n"); 729 } else { 730 tl_assert(thr->created_at != NULL); 731 VG_(pp_ExeContext)( thr->created_at ); 732 } 733 VG_(printf_xml)("</announcethread>\n\n"); 734 735 } else { 736 737 VG_(umsg)("---Thread-Announcement----------" 738 "--------------------------------" "\n"); 739 VG_(umsg)("\n"); 740 741 if (thr->errmsg_index == 1) { 742 tl_assert(thr->created_at == NULL); 743 VG_(message)(Vg_UserMsg, 744 "Thread #%d is the program's root thread\n", 745 thr->errmsg_index); 746 } else { 747 tl_assert(thr->created_at != NULL); 748 VG_(message)(Vg_UserMsg, "Thread #%d was created\n", 749 thr->errmsg_index); 750 VG_(pp_ExeContext)( thr->created_at ); 751 } 752 VG_(message)(Vg_UserMsg, "\n"); 753 754 } 755 756 thr->announced = True; 757 return True; 758 } 759 760 /* Announce 'lk'. */ 761 static void announce_LockP ( Lock* lk ) 762 { 763 tl_assert(lk); 764 if (lk == Lock_INVALID) 765 return; /* Can't be announced -- we know nothing about it. */ 766 tl_assert(lk->magic == LockP_MAGIC); 767 if (!lk->appeared_at) 768 return; /* There's nothing we can show */ 769 770 if (VG_(clo_xml)) { 771 /* fixme: add announcement */ 772 } else { 773 VG_(umsg)( "Lock at %p was first observed\n", 774 (void*)lk->guestaddr ); 775 VG_(pp_ExeContext)( lk->appeared_at ); 776 VG_(umsg)("\n"); 777 } 778 } 779 780 /* Announce (that is, print point-of-first-observation) for the 781 locks in 'lockvec' and, if non-NULL, 'lockvec2'. */ 782 static void announce_combined_LockP_vecs ( Lock** lockvec, 783 Lock** lockvec2 ) 784 { 785 UWord i; 786 tl_assert(lockvec); 787 for (i = 0; lockvec[i]; i++) { 788 announce_LockP(lockvec[i]); 789 } 790 if (lockvec2) { 791 for (i = 0; lockvec2[i]; i++) { 792 Lock* lk = lockvec2[i]; 793 if (!elem_LockP_vector(lockvec, lk)) 794 announce_LockP(lk); 795 } 796 } 797 } 798 799 800 static void show_LockP_summary_textmode ( Lock** locks, const HChar* pre ) 801 { 802 tl_assert(locks); 803 UWord i; 804 UWord nLocks = 0, nLocksValid = 0; 805 count_LockP_vector(&nLocks, &nLocksValid, locks); 806 tl_assert(nLocksValid <= nLocks); 807 808 if (nLocks == 0) { 809 VG_(umsg)( "%sLocks held: none", pre ); 810 } else { 811 VG_(umsg)( "%sLocks held: %lu, at address%s ", 812 pre, nLocks, nLocksValid == 1 ? "" : "es" ); 813 } 814 815 if (nLocks > 0) { 816 for (i = 0; i < nLocks; i++) { 817 if (locks[i] == Lock_INVALID) 818 continue; 819 VG_(umsg)( "%p", (void*)locks[i]->guestaddr); 820 if (locks[i+1] != NULL) 821 VG_(umsg)(" "); 822 } 823 if (nLocksValid < nLocks) 824 VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid); 825 } 826 VG_(umsg)("\n"); 827 } 828 829 830 /* This is the "this error is due to be printed shortly; so have a 831 look at it any print any preamble you want" function. We use it to 832 announce any previously un-announced threads in the upcoming error 833 message. 834 */ 835 void HG_(before_pp_Error) ( Error* err ) 836 { 837 XError* xe; 838 tl_assert(err); 839 xe = (XError*)VG_(get_error_extra)(err); 840 tl_assert(xe); 841 842 switch (VG_(get_error_kind)(err)) { 843 case XE_Misc: 844 announce_one_thread( xe->XE.Misc.thr ); 845 break; 846 case XE_LockOrder: 847 announce_one_thread( xe->XE.LockOrder.thr ); 848 break; 849 case XE_PthAPIerror: 850 announce_one_thread( xe->XE.PthAPIerror.thr ); 851 break; 852 case XE_UnlockBogus: 853 announce_one_thread( xe->XE.UnlockBogus.thr ); 854 break; 855 case XE_UnlockForeign: 856 announce_one_thread( xe->XE.UnlockForeign.thr ); 857 announce_one_thread( xe->XE.UnlockForeign.owner ); 858 break; 859 case XE_UnlockUnlocked: 860 announce_one_thread( xe->XE.UnlockUnlocked.thr ); 861 break; 862 case XE_Race: 863 announce_one_thread( xe->XE.Race.thr ); 864 if (xe->XE.Race.h2_ct) 865 announce_one_thread( xe->XE.Race.h2_ct ); 866 if (xe->XE.Race.h1_ct) 867 announce_one_thread( xe->XE.Race.h1_ct ); 868 break; 869 default: 870 tl_assert(0); 871 } 872 } 873 874 void HG_(pp_Error) ( Error* err ) 875 { 876 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */ 877 878 if (!xml) { 879 VG_(umsg)("--------------------------------" 880 "--------------------------------" "\n"); 881 VG_(umsg)("\n"); 882 } 883 884 XError *xe = (XError*)VG_(get_error_extra)(err); 885 tl_assert(xe); 886 887 if (xml) 888 emit( " <kind>%s</kind>\n", HG_(get_error_name)(err)); 889 890 switch (VG_(get_error_kind)(err)) { 891 892 case XE_Misc: { 893 tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) ); 894 895 if (xml) { 896 897 emit( " <xwhat>\n" ); 898 emit( " <text>Thread #%d: %s</text>\n", 899 (Int)xe->XE.Misc.thr->errmsg_index, 900 xe->XE.Misc.errstr ); 901 emit( " <hthreadid>%d</hthreadid>\n", 902 (Int)xe->XE.Misc.thr->errmsg_index ); 903 emit( " </xwhat>\n" ); 904 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 905 if (xe->XE.Misc.auxstr) { 906 emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr); 907 if (xe->XE.Misc.auxctx) 908 VG_(pp_ExeContext)( xe->XE.Misc.auxctx ); 909 } 910 911 } else { 912 913 emit( "Thread #%d: %s\n", 914 (Int)xe->XE.Misc.thr->errmsg_index, 915 xe->XE.Misc.errstr ); 916 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 917 if (xe->XE.Misc.auxstr) { 918 emit(" %s\n", xe->XE.Misc.auxstr); 919 if (xe->XE.Misc.auxctx) 920 VG_(pp_ExeContext)( xe->XE.Misc.auxctx ); 921 } 922 923 } 924 break; 925 } 926 927 case XE_LockOrder: { 928 tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) ); 929 930 if (xml) { 931 932 emit( " <xwhat>\n" ); 933 emit( " <text>Thread #%d: lock order \"%p before %p\" " 934 "violated</text>\n", 935 (Int)xe->XE.LockOrder.thr->errmsg_index, 936 (void*)xe->XE.LockOrder.shouldbe_earlier_ga, 937 (void*)xe->XE.LockOrder.shouldbe_later_ga ); 938 emit( " <hthreadid>%d</hthreadid>\n", 939 (Int)xe->XE.LockOrder.thr->errmsg_index ); 940 emit( " </xwhat>\n" ); 941 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 942 if (xe->XE.LockOrder.shouldbe_earlier_ec 943 && xe->XE.LockOrder.shouldbe_later_ec) { 944 emit( " <auxwhat>Required order was established by " 945 "acquisition of lock at %p</auxwhat>\n", 946 (void*)xe->XE.LockOrder.shouldbe_earlier_ga ); 947 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec ); 948 emit( " <auxwhat>followed by a later acquisition " 949 "of lock at %p</auxwhat>\n", 950 (void*)xe->XE.LockOrder.shouldbe_later_ga ); 951 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec ); 952 } 953 954 } else { 955 956 emit( "Thread #%d: lock order \"%p before %p\" violated\n", 957 (Int)xe->XE.LockOrder.thr->errmsg_index, 958 (void*)xe->XE.LockOrder.shouldbe_earlier_ga, 959 (void*)xe->XE.LockOrder.shouldbe_later_ga ); 960 emit( "\n" ); 961 emit( "Observed (incorrect) order is: " 962 "acquisition of lock at %p\n", 963 (void*)xe->XE.LockOrder.shouldbe_later_ga); 964 if (xe->XE.LockOrder.actual_earlier_ec) { 965 VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec); 966 } else { 967 emit(" (stack unavailable)\n"); 968 } 969 emit( "\n" ); 970 emit(" followed by a later acquisition of lock at %p\n", 971 (void*)xe->XE.LockOrder.shouldbe_earlier_ga); 972 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 973 if (xe->XE.LockOrder.shouldbe_earlier_ec 974 && xe->XE.LockOrder.shouldbe_later_ec) { 975 emit("\n"); 976 emit( "Required order was established by " 977 "acquisition of lock at %p\n", 978 (void*)xe->XE.LockOrder.shouldbe_earlier_ga ); 979 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec ); 980 emit( "\n" ); 981 emit( " followed by a later acquisition of lock at %p\n", 982 (void*)xe->XE.LockOrder.shouldbe_later_ga ); 983 VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec ); 984 } 985 986 } 987 988 break; 989 } 990 991 case XE_PthAPIerror: { 992 tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) ); 993 994 if (xml) { 995 996 emit( " <xwhat>\n" ); 997 emit( 998 " <text>Thread #%d's call to %pS failed</text>\n", 999 (Int)xe->XE.PthAPIerror.thr->errmsg_index, 1000 xe->XE.PthAPIerror.fnname ); 1001 emit( " <hthreadid>%d</hthreadid>\n", 1002 (Int)xe->XE.PthAPIerror.thr->errmsg_index ); 1003 emit( " </xwhat>\n" ); 1004 emit( " <what>with error code %ld (%s)</what>\n", 1005 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr ); 1006 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1007 1008 } else { 1009 1010 emit( "Thread #%d's call to %pS failed\n", 1011 (Int)xe->XE.PthAPIerror.thr->errmsg_index, 1012 xe->XE.PthAPIerror.fnname ); 1013 emit( " with error code %ld (%s)\n", 1014 xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr ); 1015 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1016 1017 } 1018 1019 break; 1020 } 1021 1022 case XE_UnlockBogus: { 1023 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) ); 1024 1025 if (xml) { 1026 1027 emit( " <xwhat>\n" ); 1028 emit( " <text>Thread #%d unlocked an invalid " 1029 "lock at %p</text>\n", 1030 (Int)xe->XE.UnlockBogus.thr->errmsg_index, 1031 (void*)xe->XE.UnlockBogus.lock_ga ); 1032 emit( " <hthreadid>%d</hthreadid>\n", 1033 (Int)xe->XE.UnlockBogus.thr->errmsg_index ); 1034 emit( " </xwhat>\n" ); 1035 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1036 1037 } else { 1038 1039 emit( "Thread #%d unlocked an invalid lock at %p\n", 1040 (Int)xe->XE.UnlockBogus.thr->errmsg_index, 1041 (void*)xe->XE.UnlockBogus.lock_ga ); 1042 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1043 1044 } 1045 1046 break; 1047 } 1048 1049 case XE_UnlockForeign: { 1050 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) ); 1051 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) ); 1052 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) ); 1053 1054 if (xml) { 1055 1056 emit( " <xwhat>\n" ); 1057 emit( " <text>Thread #%d unlocked lock at %p " 1058 "currently held by thread #%d</text>\n", 1059 (Int)xe->XE.UnlockForeign.thr->errmsg_index, 1060 (void*)xe->XE.UnlockForeign.lock->guestaddr, 1061 (Int)xe->XE.UnlockForeign.owner->errmsg_index ); 1062 emit( " <hthreadid>%d</hthreadid>\n", 1063 (Int)xe->XE.UnlockForeign.thr->errmsg_index ); 1064 emit( " <hthreadid>%d</hthreadid>\n", 1065 (Int)xe->XE.UnlockForeign.owner->errmsg_index ); 1066 emit( " </xwhat>\n" ); 1067 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1068 1069 if (xe->XE.UnlockForeign.lock->appeared_at) { 1070 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n", 1071 (void*)xe->XE.UnlockForeign.lock->guestaddr ); 1072 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at ); 1073 } 1074 1075 } else { 1076 1077 emit( "Thread #%d unlocked lock at %p " 1078 "currently held by thread #%d\n", 1079 (Int)xe->XE.UnlockForeign.thr->errmsg_index, 1080 (void*)xe->XE.UnlockForeign.lock->guestaddr, 1081 (Int)xe->XE.UnlockForeign.owner->errmsg_index ); 1082 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1083 if (xe->XE.UnlockForeign.lock->appeared_at) { 1084 emit( " Lock at %p was first observed\n", 1085 (void*)xe->XE.UnlockForeign.lock->guestaddr ); 1086 VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at ); 1087 } 1088 1089 } 1090 1091 break; 1092 } 1093 1094 case XE_UnlockUnlocked: { 1095 tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) ); 1096 tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) ); 1097 1098 if (xml) { 1099 1100 emit( " <xwhat>\n" ); 1101 emit( " <text>Thread #%d unlocked a " 1102 "not-locked lock at %p</text>\n", 1103 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index, 1104 (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1105 emit( " <hthreadid>%d</hthreadid>\n", 1106 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index ); 1107 emit( " </xwhat>\n" ); 1108 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1109 if (xe->XE.UnlockUnlocked.lock->appeared_at) { 1110 emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n", 1111 (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1112 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at ); 1113 } 1114 1115 } else { 1116 1117 emit( "Thread #%d unlocked a not-locked lock at %p\n", 1118 (Int)xe->XE.UnlockUnlocked.thr->errmsg_index, 1119 (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1120 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1121 if (xe->XE.UnlockUnlocked.lock->appeared_at) { 1122 emit( " Lock at %p was first observed\n", 1123 (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1124 VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at ); 1125 } 1126 1127 } 1128 1129 break; 1130 } 1131 1132 case XE_Race: { 1133 Addr err_ga; 1134 const HChar* what; 1135 Int szB; 1136 what = xe->XE.Race.isWrite ? "write" : "read"; 1137 szB = xe->XE.Race.szB; 1138 err_ga = VG_(get_error_address)(err); 1139 1140 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr )); 1141 if (xe->XE.Race.h2_ct) 1142 tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct )); 1143 1144 if (xml) { 1145 1146 /* ------ XML ------ */ 1147 emit( " <xwhat>\n" ); 1148 emit( " <text>Possible data race during %s of size %d " 1149 "at %p by thread #%d</text>\n", 1150 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index ); 1151 emit( " <hthreadid>%d</hthreadid>\n", 1152 (Int)xe->XE.Race.thr->errmsg_index ); 1153 emit( " </xwhat>\n" ); 1154 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1155 1156 if (xe->XE.Race.h2_ct) { 1157 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra 1158 emit( " <xauxwhat>\n"); 1159 emit( " <text>This conflicts with a previous %s of size %d " 1160 "by thread #%d</text>\n", 1161 xe->XE.Race.h2_ct_accIsW ? "write" : "read", 1162 xe->XE.Race.h2_ct_accSzB, 1163 xe->XE.Race.h2_ct->errmsg_index ); 1164 emit( " <hthreadid>%d</hthreadid>\n", 1165 xe->XE.Race.h2_ct->errmsg_index); 1166 emit(" </xauxwhat>\n"); 1167 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC ); 1168 } 1169 1170 if (xe->XE.Race.h1_ct) { 1171 emit( " <xauxwhat>\n"); 1172 emit( " <text>This conflicts with a previous access " 1173 "by thread #%d, after</text>\n", 1174 xe->XE.Race.h1_ct->errmsg_index ); 1175 emit( " <hthreadid>%d</hthreadid>\n", 1176 xe->XE.Race.h1_ct->errmsg_index ); 1177 emit(" </xauxwhat>\n"); 1178 if (xe->XE.Race.h1_ct_mbsegstartEC) { 1179 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC ); 1180 } else { 1181 emit( " <auxwhat>(the start of the thread)</auxwhat>\n" ); 1182 } 1183 emit( " <auxwhat>but before</auxwhat>\n" ); 1184 if (xe->XE.Race.h1_ct_mbsegendEC) { 1185 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC ); 1186 } else { 1187 emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" ); 1188 } 1189 } 1190 1191 } else { 1192 1193 /* ------ Text ------ */ 1194 announce_combined_LockP_vecs( xe->XE.Race.locksHeldW, 1195 xe->XE.Race.h2_ct_locksHeldW ); 1196 1197 emit( "Possible data race during %s of size %d " 1198 "at %p by thread #%d\n", 1199 what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index ); 1200 1201 tl_assert(xe->XE.Race.locksHeldW); 1202 show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" ); 1203 VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1204 1205 if (xe->XE.Race.h2_ct) { 1206 tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra 1207 tl_assert(xe->XE.Race.h2_ct_locksHeldW); 1208 emit( "\n" ); 1209 emit( "This conflicts with a previous %s of size %d " 1210 "by thread #%d\n", 1211 xe->XE.Race.h2_ct_accIsW ? "write" : "read", 1212 xe->XE.Race.h2_ct_accSzB, 1213 xe->XE.Race.h2_ct->errmsg_index ); 1214 show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" ); 1215 VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC ); 1216 } 1217 1218 if (xe->XE.Race.h1_ct) { 1219 emit( " This conflicts with a previous access by thread #%d, " 1220 "after\n", 1221 xe->XE.Race.h1_ct->errmsg_index ); 1222 if (xe->XE.Race.h1_ct_mbsegstartEC) { 1223 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC ); 1224 } else { 1225 emit( " (the start of the thread)\n" ); 1226 } 1227 emit( " but before\n" ); 1228 if (xe->XE.Race.h1_ct_mbsegendEC) { 1229 VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC ); 1230 } else { 1231 emit( " (the end of the the thread)\n" ); 1232 } 1233 } 1234 1235 } 1236 VG_(pp_addrinfo) (err_ga, &xe->XE.Race.data_addrinfo); 1237 break; /* case XE_Race */ 1238 } /* case XE_Race */ 1239 1240 default: 1241 tl_assert(0); 1242 } /* switch (VG_(get_error_kind)(err)) */ 1243 } 1244 1245 const HChar* HG_(get_error_name) ( Error* err ) 1246 { 1247 switch (VG_(get_error_kind)(err)) { 1248 case XE_Race: return "Race"; 1249 case XE_UnlockUnlocked: return "UnlockUnlocked"; 1250 case XE_UnlockForeign: return "UnlockForeign"; 1251 case XE_UnlockBogus: return "UnlockBogus"; 1252 case XE_PthAPIerror: return "PthAPIerror"; 1253 case XE_LockOrder: return "LockOrder"; 1254 case XE_Misc: return "Misc"; 1255 default: tl_assert(0); /* fill in missing case */ 1256 } 1257 } 1258 1259 Bool HG_(recognised_suppression) ( const HChar* name, Supp *su ) 1260 { 1261 # define TRY(_name,_xskind) \ 1262 if (0 == VG_(strcmp)(name, (_name))) { \ 1263 VG_(set_supp_kind)(su, (_xskind)); \ 1264 return True; \ 1265 } 1266 TRY("Race", XS_Race); 1267 TRY("FreeMemLock", XS_FreeMemLock); 1268 TRY("UnlockUnlocked", XS_UnlockUnlocked); 1269 TRY("UnlockForeign", XS_UnlockForeign); 1270 TRY("UnlockBogus", XS_UnlockBogus); 1271 TRY("PthAPIerror", XS_PthAPIerror); 1272 TRY("LockOrder", XS_LockOrder); 1273 TRY("Misc", XS_Misc); 1274 return False; 1275 # undef TRY 1276 } 1277 1278 Bool HG_(read_extra_suppression_info) ( Int fd, HChar** bufpp, SizeT* nBufp, 1279 Int* lineno, Supp* su ) 1280 { 1281 /* do nothing -- no extra suppression info present. Return True to 1282 indicate nothing bad happened. */ 1283 return True; 1284 } 1285 1286 Bool HG_(error_matches_suppression) ( Error* err, Supp* su ) 1287 { 1288 switch (VG_(get_supp_kind)(su)) { 1289 case XS_Race: return VG_(get_error_kind)(err) == XE_Race; 1290 case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked; 1291 case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign; 1292 case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus; 1293 case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror; 1294 case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder; 1295 case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc; 1296 //case XS_: return VG_(get_error_kind)(err) == XE_; 1297 default: tl_assert(0); /* fill in missing cases */ 1298 } 1299 } 1300 1301 Bool HG_(get_extra_suppression_info) ( Error* err, 1302 /*OUT*/HChar* buf, Int nBuf ) 1303 { 1304 /* Do nothing */ 1305 return False; 1306 } 1307 1308 Bool HG_(print_extra_suppression_use) ( Supp* su, 1309 /*OUT*/HChar* buf, Int nBuf ) 1310 { 1311 /* Do nothing */ 1312 return False; 1313 } 1314 1315 void HG_(update_extra_suppression_use) ( Error* err, Supp* su ) 1316 { 1317 /* Do nothing */ 1318 return; 1319 } 1320 1321 1322 /*--------------------------------------------------------------------*/ 1323 /*--- end hg_errors.c ---*/ 1324 /*--------------------------------------------------------------------*/ 1325