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