1 2 /*--------------------------------------------------------------------*/ 3 /*--- Helgrind: a Valgrind tool for detecting errors ---*/ 4 /*--- in threaded programs. hg_main.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-2017 OpenWorks LLP 12 info (at) open-works.co.uk 13 14 Copyright (C) 2007-2017 Apple, Inc. 15 16 This program is free software; you can redistribute it and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of the 19 License, or (at your option) any later version. 20 21 This program is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received a copy of the GNU General Public License 27 along with this program; if not, write to the Free Software 28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 02111-1307, USA. 30 31 The GNU General Public License is contained in the file COPYING. 32 33 Neither the names of the U.S. Department of Energy nor the 34 University of California nor the names of its contributors may be 35 used to endorse or promote products derived from this software 36 without prior written permission. 37 */ 38 39 #include "pub_tool_basics.h" 40 #include "pub_tool_gdbserver.h" 41 #include "pub_tool_libcassert.h" 42 #include "pub_tool_libcbase.h" 43 #include "pub_tool_libcprint.h" 44 #include "pub_tool_threadstate.h" 45 #include "pub_tool_tooliface.h" 46 #include "pub_tool_hashtable.h" 47 #include "pub_tool_replacemalloc.h" 48 #include "pub_tool_machine.h" 49 #include "pub_tool_options.h" 50 #include "pub_tool_xarray.h" 51 #include "pub_tool_stacktrace.h" 52 #include "pub_tool_wordfm.h" 53 #include "pub_tool_debuginfo.h" // VG_(find_seginfo), VG_(seginfo_soname) 54 #include "pub_tool_redir.h" // sonames for the dynamic linkers 55 #include "pub_tool_vki.h" // VKI_PAGE_SIZE 56 #include "pub_tool_libcproc.h" 57 #include "pub_tool_aspacemgr.h" // VG_(am_is_valid_for_client) 58 #include "pub_tool_poolalloc.h" 59 #include "pub_tool_addrinfo.h" 60 #include "pub_tool_xtree.h" 61 #include "pub_tool_xtmemory.h" 62 63 #include "hg_basics.h" 64 #include "hg_wordset.h" 65 #include "hg_addrdescr.h" 66 #include "hg_lock_n_thread.h" 67 #include "hg_errors.h" 68 69 #include "libhb.h" 70 71 #include "helgrind.h" 72 73 74 // FIXME: new_mem_w_tid ignores the supplied tid. (wtf?!) 75 76 // FIXME: when client destroys a lock or a CV, remove these 77 // from our mappings, so that the associated SO can be freed up 78 79 /*----------------------------------------------------------------*/ 80 /*--- ---*/ 81 /*----------------------------------------------------------------*/ 82 83 /* Note this needs to be compiled with -fno-strict-aliasing, since it 84 contains a whole bunch of calls to lookupFM etc which cast between 85 Word and pointer types. gcc rightly complains this breaks ANSI C 86 strict aliasing rules, at -O2. No complaints at -O, but -O2 gives 87 worthwhile performance benefits over -O. 88 */ 89 90 // FIXME what is supposed to happen to locks in memory which 91 // is relocated as a result of client realloc? 92 93 // FIXME put referencing ThreadId into Thread and get 94 // rid of the slow reverse mapping function. 95 96 // FIXME accesses to NoAccess areas: change state to Excl? 97 98 // FIXME report errors for accesses of NoAccess memory? 99 100 // FIXME pth_cond_wait/timedwait wrappers. Even if these fail, 101 // the thread still holds the lock. 102 103 /* ------------ Debug/trace options ------------ */ 104 105 // 0 for silent, 1 for some stuff, 2 for lots of stuff 106 #define SHOW_EVENTS 0 107 108 109 static void all__sanity_check ( const HChar* who ); /* fwds */ 110 111 #define HG_CLI__DEFAULT_MALLOC_REDZONE_SZB 16 /* let's say */ 112 113 // 0 for none, 1 for dump at end of run 114 #define SHOW_DATA_STRUCTURES 0 115 116 117 /* ------------ Misc comments ------------ */ 118 119 // FIXME: don't hardwire initial entries for root thread. 120 // Instead, let the pre_thread_ll_create handler do this. 121 122 123 /*----------------------------------------------------------------*/ 124 /*--- Primary data structures ---*/ 125 /*----------------------------------------------------------------*/ 126 127 /* Admin linked list of Threads */ 128 static Thread* admin_threads = NULL; 129 Thread* get_admin_threads ( void ) { return admin_threads; } 130 131 /* Admin double linked list of Locks */ 132 /* We need a double linked list to properly and efficiently 133 handle del_LockN. */ 134 static Lock* admin_locks = NULL; 135 136 /* Mapping table for core ThreadIds to Thread* */ 137 static Thread** map_threads = NULL; /* Array[VG_N_THREADS] of Thread* */ 138 139 /* Mapping table for lock guest addresses to Lock* */ 140 static WordFM* map_locks = NULL; /* WordFM LockAddr Lock* */ 141 142 /* The word-set universes for lock sets. */ 143 static WordSetU* univ_lsets = NULL; /* sets of Lock* */ 144 static WordSetU* univ_laog = NULL; /* sets of Lock*, for LAOG */ 145 static Int next_gc_univ_laog = 1; 146 /* univ_laog will be garbaged collected when the nr of element in univ_laog is 147 >= next_gc_univ_laog. */ 148 149 /* Allow libhb to get at the universe of locksets stored 150 here. Sigh. */ 151 WordSetU* HG_(get_univ_lsets) ( void ) { return univ_lsets; } 152 153 /* Allow libhb to get at the list of locks stored here. Ditto 154 sigh. */ 155 Lock* HG_(get_admin_locks) ( void ) { return admin_locks; } 156 157 158 /*----------------------------------------------------------------*/ 159 /*--- Simple helpers for the data structures ---*/ 160 /*----------------------------------------------------------------*/ 161 162 static UWord stats__lockN_acquires = 0; 163 static UWord stats__lockN_releases = 0; 164 165 #if defined(VGO_solaris) 166 Bool HG_(clo_ignore_thread_creation) = True; 167 #else 168 Bool HG_(clo_ignore_thread_creation) = False; 169 #endif /* VGO_solaris */ 170 171 static 172 ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* thr ); /*fwds*/ 173 174 /* --------- Constructors --------- */ 175 176 static Thread* mk_Thread ( Thr* hbthr ) { 177 static Int indx = 1; 178 Thread* thread = HG_(zalloc)( "hg.mk_Thread.1", sizeof(Thread) ); 179 thread->locksetA = HG_(emptyWS)( univ_lsets ); 180 thread->locksetW = HG_(emptyWS)( univ_lsets ); 181 thread->magic = Thread_MAGIC; 182 thread->hbthr = hbthr; 183 thread->coretid = VG_INVALID_THREADID; 184 thread->created_at = NULL; 185 thread->announced = False; 186 thread->errmsg_index = indx++; 187 thread->admin = admin_threads; 188 thread->synchr_nesting = 0; 189 thread->pthread_create_nesting_level = 0; 190 #if defined(VGO_solaris) 191 thread->bind_guard_flag = 0; 192 #endif /* VGO_solaris */ 193 194 admin_threads = thread; 195 return thread; 196 } 197 198 // Make a new lock which is unlocked (hence ownerless) 199 // and insert the new lock in admin_locks double linked list. 200 static Lock* mk_LockN ( LockKind kind, Addr guestaddr ) { 201 static ULong unique = 0; 202 Lock* lock = HG_(zalloc)( "hg.mk_Lock.1", sizeof(Lock) ); 203 /* begin: add to double linked list */ 204 if (admin_locks) 205 admin_locks->admin_prev = lock; 206 lock->admin_next = admin_locks; 207 lock->admin_prev = NULL; 208 admin_locks = lock; 209 /* end: add */ 210 lock->unique = unique++; 211 lock->magic = LockN_MAGIC; 212 lock->appeared_at = NULL; 213 lock->acquired_at = NULL; 214 lock->hbso = libhb_so_alloc(); 215 lock->guestaddr = guestaddr; 216 lock->kind = kind; 217 lock->heldW = False; 218 lock->heldBy = NULL; 219 tl_assert(HG_(is_sane_LockN)(lock)); 220 return lock; 221 } 222 223 /* Release storage for a Lock. Also release storage in .heldBy, if 224 any. Removes from admin_locks double linked list. */ 225 static void del_LockN ( Lock* lk ) 226 { 227 tl_assert(HG_(is_sane_LockN)(lk)); 228 tl_assert(lk->hbso); 229 libhb_so_dealloc(lk->hbso); 230 if (lk->heldBy) 231 VG_(deleteBag)( lk->heldBy ); 232 /* begin: del lock from double linked list */ 233 if (lk == admin_locks) { 234 tl_assert(lk->admin_prev == NULL); 235 if (lk->admin_next) 236 lk->admin_next->admin_prev = NULL; 237 admin_locks = lk->admin_next; 238 } 239 else { 240 tl_assert(lk->admin_prev != NULL); 241 lk->admin_prev->admin_next = lk->admin_next; 242 if (lk->admin_next) 243 lk->admin_next->admin_prev = lk->admin_prev; 244 } 245 /* end: del */ 246 VG_(memset)(lk, 0xAA, sizeof(*lk)); 247 HG_(free)(lk); 248 } 249 250 /* Update 'lk' to reflect that 'thr' now has a write-acquisition of 251 it. This is done strictly: only combinations resulting from 252 correct program and libpthread behaviour are allowed. */ 253 static void lockN_acquire_writer ( Lock* lk, Thread* thr ) 254 { 255 tl_assert(HG_(is_sane_LockN)(lk)); 256 tl_assert(HG_(is_sane_Thread)(thr)); 257 258 stats__lockN_acquires++; 259 260 /* EXPOSITION only */ 261 /* We need to keep recording snapshots of where the lock was 262 acquired, so as to produce better lock-order error messages. */ 263 if (lk->acquired_at == NULL) { 264 ThreadId tid; 265 tl_assert(lk->heldBy == NULL); 266 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 267 lk->acquired_at 268 = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 269 } else { 270 tl_assert(lk->heldBy != NULL); 271 } 272 /* end EXPOSITION only */ 273 274 switch (lk->kind) { 275 case LK_nonRec: 276 case_LK_nonRec: 277 tl_assert(lk->heldBy == NULL); /* can't w-lock recursively */ 278 tl_assert(!lk->heldW); 279 lk->heldW = True; 280 lk->heldBy = VG_(newBag)( HG_(zalloc), "hg.lNaw.1", HG_(free) ); 281 VG_(addToBag)( lk->heldBy, (UWord)thr ); 282 break; 283 case LK_mbRec: 284 if (lk->heldBy == NULL) 285 goto case_LK_nonRec; 286 /* 2nd and subsequent locking of a lock by its owner */ 287 tl_assert(lk->heldW); 288 /* assert: lk is only held by one thread .. */ 289 tl_assert(VG_(sizeUniqueBag)(lk->heldBy) == 1); 290 /* assert: .. and that thread is 'thr'. */ 291 tl_assert(VG_(elemBag)(lk->heldBy, (UWord)thr) 292 == VG_(sizeTotalBag)(lk->heldBy)); 293 VG_(addToBag)(lk->heldBy, (UWord)thr); 294 break; 295 case LK_rdwr: 296 tl_assert(lk->heldBy == NULL && !lk->heldW); /* must be unheld */ 297 goto case_LK_nonRec; 298 default: 299 tl_assert(0); 300 } 301 tl_assert(HG_(is_sane_LockN)(lk)); 302 } 303 304 static void lockN_acquire_reader ( Lock* lk, Thread* thr ) 305 { 306 tl_assert(HG_(is_sane_LockN)(lk)); 307 tl_assert(HG_(is_sane_Thread)(thr)); 308 /* can only add reader to a reader-writer lock. */ 309 tl_assert(lk->kind == LK_rdwr); 310 /* lk must be free or already r-held. */ 311 tl_assert(lk->heldBy == NULL 312 || (lk->heldBy != NULL && !lk->heldW)); 313 314 stats__lockN_acquires++; 315 316 /* EXPOSITION only */ 317 /* We need to keep recording snapshots of where the lock was 318 acquired, so as to produce better lock-order error messages. */ 319 if (lk->acquired_at == NULL) { 320 ThreadId tid; 321 tl_assert(lk->heldBy == NULL); 322 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 323 lk->acquired_at 324 = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 325 } else { 326 tl_assert(lk->heldBy != NULL); 327 } 328 /* end EXPOSITION only */ 329 330 if (lk->heldBy) { 331 VG_(addToBag)(lk->heldBy, (UWord)thr); 332 } else { 333 lk->heldW = False; 334 lk->heldBy = VG_(newBag)( HG_(zalloc), "hg.lNar.1", HG_(free) ); 335 VG_(addToBag)( lk->heldBy, (UWord)thr ); 336 } 337 tl_assert(!lk->heldW); 338 tl_assert(HG_(is_sane_LockN)(lk)); 339 } 340 341 /* Update 'lk' to reflect a release of it by 'thr'. This is done 342 strictly: only combinations resulting from correct program and 343 libpthread behaviour are allowed. */ 344 345 static void lockN_release ( Lock* lk, Thread* thr ) 346 { 347 Bool b; 348 tl_assert(HG_(is_sane_LockN)(lk)); 349 tl_assert(HG_(is_sane_Thread)(thr)); 350 /* lock must be held by someone */ 351 tl_assert(lk->heldBy); 352 stats__lockN_releases++; 353 /* Remove it from the holder set */ 354 b = VG_(delFromBag)(lk->heldBy, (UWord)thr); 355 /* thr must actually have been a holder of lk */ 356 tl_assert(b); 357 /* normalise */ 358 tl_assert(lk->acquired_at); 359 if (VG_(isEmptyBag)(lk->heldBy)) { 360 VG_(deleteBag)(lk->heldBy); 361 lk->heldBy = NULL; 362 lk->heldW = False; 363 lk->acquired_at = NULL; 364 } 365 tl_assert(HG_(is_sane_LockN)(lk)); 366 } 367 368 static void remove_Lock_from_locksets_of_all_owning_Threads( Lock* lk ) 369 { 370 Thread* thr; 371 if (!lk->heldBy) { 372 tl_assert(!lk->heldW); 373 return; 374 } 375 /* for each thread that holds this lock do ... */ 376 VG_(initIterBag)( lk->heldBy ); 377 while (VG_(nextIterBag)( lk->heldBy, (UWord*)&thr, NULL )) { 378 tl_assert(HG_(is_sane_Thread)(thr)); 379 tl_assert(HG_(elemWS)( univ_lsets, 380 thr->locksetA, (UWord)lk )); 381 thr->locksetA 382 = HG_(delFromWS)( univ_lsets, thr->locksetA, (UWord)lk ); 383 384 if (lk->heldW) { 385 tl_assert(HG_(elemWS)( univ_lsets, 386 thr->locksetW, (UWord)lk )); 387 thr->locksetW 388 = HG_(delFromWS)( univ_lsets, thr->locksetW, (UWord)lk ); 389 } 390 } 391 VG_(doneIterBag)( lk->heldBy ); 392 } 393 394 395 /*----------------------------------------------------------------*/ 396 /*--- Print out the primary data structures ---*/ 397 /*----------------------------------------------------------------*/ 398 399 #define PP_THREADS (1<<1) 400 #define PP_LOCKS (1<<2) 401 #define PP_ALL (PP_THREADS | PP_LOCKS) 402 403 404 static const Int sHOW_ADMIN = 0; 405 406 static void space ( Int n ) 407 { 408 Int i; 409 HChar spaces[128+1]; 410 tl_assert(n >= 0 && n < 128); 411 if (n == 0) 412 return; 413 for (i = 0; i < n; i++) 414 spaces[i] = ' '; 415 spaces[i] = 0; 416 tl_assert(i < 128+1); 417 VG_(printf)("%s", spaces); 418 } 419 420 static void pp_Thread ( Int d, Thread* t ) 421 { 422 space(d+0); VG_(printf)("Thread %p {\n", t); 423 if (sHOW_ADMIN) { 424 space(d+3); VG_(printf)("admin %p\n", t->admin); 425 space(d+3); VG_(printf)("magic 0x%x\n", (UInt)t->magic); 426 } 427 space(d+3); VG_(printf)("locksetA %d\n", (Int)t->locksetA); 428 space(d+3); VG_(printf)("locksetW %d\n", (Int)t->locksetW); 429 space(d+0); VG_(printf)("}\n"); 430 } 431 432 static void pp_admin_threads ( Int d ) 433 { 434 Int i, n; 435 Thread* t; 436 for (n = 0, t = admin_threads; t; n++, t = t->admin) { 437 /* nothing */ 438 } 439 space(d); VG_(printf)("admin_threads (%d records) {\n", n); 440 for (i = 0, t = admin_threads; t; i++, t = t->admin) { 441 if (0) { 442 space(n); 443 VG_(printf)("admin_threads record %d of %d:\n", i, n); 444 } 445 pp_Thread(d+3, t); 446 } 447 space(d); VG_(printf)("}\n"); 448 } 449 450 static void pp_map_threads ( Int d ) 451 { 452 Int i, n = 0; 453 space(d); VG_(printf)("map_threads "); 454 for (i = 0; i < VG_N_THREADS; i++) { 455 if (map_threads[i] != NULL) 456 n++; 457 } 458 VG_(printf)("(%d entries) {\n", n); 459 for (i = 0; i < VG_N_THREADS; i++) { 460 if (map_threads[i] == NULL) 461 continue; 462 space(d+3); 463 VG_(printf)("coretid %d -> Thread %p\n", i, map_threads[i]); 464 } 465 space(d); VG_(printf)("}\n"); 466 } 467 468 static const HChar* show_LockKind ( LockKind lkk ) { 469 switch (lkk) { 470 case LK_mbRec: return "mbRec"; 471 case LK_nonRec: return "nonRec"; 472 case LK_rdwr: return "rdwr"; 473 default: tl_assert(0); 474 } 475 } 476 477 /* Pretty Print lock lk. 478 if show_lock_addrdescr, describes the (guest) lock address. 479 (this description will be more complete with --read-var-info=yes). 480 if show_internal_data, shows also helgrind internal information. 481 d is the level at which output is indented. */ 482 static void pp_Lock ( Int d, Lock* lk, 483 Bool show_lock_addrdescr, 484 Bool show_internal_data) 485 { 486 space(d+0); 487 if (show_internal_data) 488 VG_(printf)("Lock %p (ga %#lx) {\n", lk, lk->guestaddr); 489 else 490 VG_(printf)("Lock ga %#lx {\n", lk->guestaddr); 491 if (!show_lock_addrdescr 492 || !HG_(get_and_pp_addrdescr) ((Addr) lk->guestaddr)) 493 VG_(printf)("\n"); 494 495 if (sHOW_ADMIN) { 496 space(d+3); VG_(printf)("admin_n %p\n", lk->admin_next); 497 space(d+3); VG_(printf)("admin_p %p\n", lk->admin_prev); 498 space(d+3); VG_(printf)("magic 0x%x\n", (UInt)lk->magic); 499 } 500 if (show_internal_data) { 501 space(d+3); VG_(printf)("unique %llu\n", lk->unique); 502 } 503 space(d+3); VG_(printf)("kind %s\n", show_LockKind(lk->kind)); 504 if (show_internal_data) { 505 space(d+3); VG_(printf)("heldW %s\n", lk->heldW ? "yes" : "no"); 506 } 507 if (show_internal_data) { 508 space(d+3); VG_(printf)("heldBy %p", lk->heldBy); 509 } 510 if (lk->heldBy) { 511 Thread* thr; 512 UWord count; 513 VG_(printf)(" { "); 514 VG_(initIterBag)( lk->heldBy ); 515 while (VG_(nextIterBag)( lk->heldBy, (UWord*)&thr, &count )) { 516 if (show_internal_data) 517 VG_(printf)("%lu:%p ", count, thr); 518 else { 519 VG_(printf)("%c%lu:thread #%d ", 520 lk->heldW ? 'W' : 'R', 521 count, thr->errmsg_index); 522 if (thr->coretid == VG_INVALID_THREADID) 523 VG_(printf)("tid (exited) "); 524 else 525 VG_(printf)("tid %u ", thr->coretid); 526 527 } 528 } 529 VG_(doneIterBag)( lk->heldBy ); 530 VG_(printf)("}\n"); 531 } 532 space(d+0); VG_(printf)("}\n"); 533 } 534 535 static void pp_admin_locks ( Int d ) 536 { 537 Int i, n; 538 Lock* lk; 539 for (n = 0, lk = admin_locks; lk; n++, lk = lk->admin_next) { 540 /* nothing */ 541 } 542 space(d); VG_(printf)("admin_locks (%d records) {\n", n); 543 for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin_next) { 544 if (0) { 545 space(n); 546 VG_(printf)("admin_locks record %d of %d:\n", i, n); 547 } 548 pp_Lock(d+3, lk, 549 False /* show_lock_addrdescr */, 550 True /* show_internal_data */); 551 } 552 space(d); VG_(printf)("}\n"); 553 } 554 555 static void pp_map_locks ( Int d) 556 { 557 void* gla; 558 Lock* lk; 559 space(d); VG_(printf)("map_locks (%d entries) {\n", 560 (Int)VG_(sizeFM)( map_locks )); 561 VG_(initIterFM)( map_locks ); 562 while (VG_(nextIterFM)( map_locks, (UWord*)&gla, 563 (UWord*)&lk )) { 564 space(d+3); 565 VG_(printf)("guest %p -> Lock %p\n", gla, lk); 566 } 567 VG_(doneIterFM)( map_locks ); 568 space(d); VG_(printf)("}\n"); 569 } 570 571 static void pp_everything ( Int flags, const HChar* caller ) 572 { 573 Int d = 0; 574 VG_(printf)("\n"); 575 VG_(printf)("All_Data_Structures (caller = \"%s\") {\n", caller); 576 if (flags & PP_THREADS) { 577 VG_(printf)("\n"); 578 pp_admin_threads(d+3); 579 VG_(printf)("\n"); 580 pp_map_threads(d+3); 581 } 582 if (flags & PP_LOCKS) { 583 VG_(printf)("\n"); 584 pp_admin_locks(d+3); 585 VG_(printf)("\n"); 586 pp_map_locks(d+3); 587 } 588 589 VG_(printf)("\n"); 590 VG_(printf)("}\n"); 591 VG_(printf)("\n"); 592 } 593 594 #undef SHOW_ADMIN 595 596 597 /*----------------------------------------------------------------*/ 598 /*--- Initialise the primary data structures ---*/ 599 /*----------------------------------------------------------------*/ 600 601 static void initialise_data_structures ( Thr* hbthr_root ) 602 { 603 Thread* thr; 604 WordSetID wsid; 605 606 /* Get everything initialised and zeroed. */ 607 tl_assert(admin_threads == NULL); 608 tl_assert(admin_locks == NULL); 609 610 tl_assert(map_threads == NULL); 611 map_threads = HG_(zalloc)( "hg.ids.1", VG_N_THREADS * sizeof(Thread*) ); 612 613 tl_assert(sizeof(Addr) == sizeof(UWord)); 614 tl_assert(map_locks == NULL); 615 map_locks = VG_(newFM)( HG_(zalloc), "hg.ids.2", HG_(free), 616 NULL/*unboxed Word cmp*/); 617 618 tl_assert(univ_lsets == NULL); 619 univ_lsets = HG_(newWordSetU)( HG_(zalloc), "hg.ids.4", HG_(free), 620 8/*cacheSize*/ ); 621 tl_assert(univ_lsets != NULL); 622 /* Ensure that univ_lsets is non-empty, with lockset zero being the 623 empty lockset. hg_errors.c relies on the assumption that 624 lockset number zero in univ_lsets is always valid. */ 625 wsid = HG_(emptyWS)(univ_lsets); 626 tl_assert(wsid == 0); 627 628 tl_assert(univ_laog == NULL); 629 if (HG_(clo_track_lockorders)) { 630 univ_laog = HG_(newWordSetU)( HG_(zalloc), "hg.ids.5 (univ_laog)", 631 HG_(free), 24/*cacheSize*/ ); 632 tl_assert(univ_laog != NULL); 633 } 634 635 /* Set up entries for the root thread */ 636 // FIXME: this assumes that the first real ThreadId is 1 637 638 /* a Thread for the new thread ... */ 639 thr = mk_Thread(hbthr_root); 640 thr->coretid = 1; /* FIXME: hardwires an assumption about the 641 identity of the root thread. */ 642 tl_assert( libhb_get_Thr_hgthread(hbthr_root) == NULL ); 643 libhb_set_Thr_hgthread(hbthr_root, thr); 644 645 /* and bind it in the thread-map table. */ 646 tl_assert(HG_(is_sane_ThreadId)(thr->coretid)); 647 tl_assert(thr->coretid != VG_INVALID_THREADID); 648 649 map_threads[thr->coretid] = thr; 650 651 tl_assert(VG_INVALID_THREADID == 0); 652 653 all__sanity_check("initialise_data_structures"); 654 } 655 656 657 /*----------------------------------------------------------------*/ 658 /*--- map_threads :: array[core-ThreadId] of Thread* ---*/ 659 /*----------------------------------------------------------------*/ 660 661 /* Doesn't assert if the relevant map_threads entry is NULL. */ 662 static Thread* map_threads_maybe_lookup ( ThreadId coretid ) 663 { 664 Thread* thr; 665 tl_assert( HG_(is_sane_ThreadId)(coretid) ); 666 thr = map_threads[coretid]; 667 return thr; 668 } 669 670 /* Asserts if the relevant map_threads entry is NULL. */ 671 static inline Thread* map_threads_lookup ( ThreadId coretid ) 672 { 673 Thread* thr; 674 tl_assert( HG_(is_sane_ThreadId)(coretid) ); 675 thr = map_threads[coretid]; 676 tl_assert(thr); 677 return thr; 678 } 679 680 /* Do a reverse lookup. Does not assert if 'thr' is not found in 681 map_threads. */ 682 static ThreadId map_threads_maybe_reverse_lookup_SLOW ( Thread* thr ) 683 { 684 ThreadId tid; 685 tl_assert(HG_(is_sane_Thread)(thr)); 686 /* Check nobody used the invalid-threadid slot */ 687 tl_assert(VG_INVALID_THREADID >= 0 && VG_INVALID_THREADID < VG_N_THREADS); 688 tl_assert(map_threads[VG_INVALID_THREADID] == NULL); 689 tid = thr->coretid; 690 tl_assert(HG_(is_sane_ThreadId)(tid)); 691 return tid; 692 } 693 694 /* Do a reverse lookup. Warning: POTENTIALLY SLOW. Asserts if 'thr' 695 is not found in map_threads. */ 696 static ThreadId map_threads_reverse_lookup_SLOW ( Thread* thr ) 697 { 698 ThreadId tid = map_threads_maybe_reverse_lookup_SLOW( thr ); 699 tl_assert(tid != VG_INVALID_THREADID); 700 tl_assert(map_threads[tid]); 701 tl_assert(map_threads[tid]->coretid == tid); 702 return tid; 703 } 704 705 static void map_threads_delete ( ThreadId coretid ) 706 { 707 Thread* thr; 708 tl_assert(coretid != 0); 709 tl_assert( HG_(is_sane_ThreadId)(coretid) ); 710 thr = map_threads[coretid]; 711 tl_assert(thr); 712 map_threads[coretid] = NULL; 713 } 714 715 static void HG_(thread_enter_synchr)(Thread *thr) { 716 tl_assert(thr->synchr_nesting >= 0); 717 #if defined(VGO_solaris) 718 thr->synchr_nesting += 1; 719 #endif /* VGO_solaris */ 720 } 721 722 static void HG_(thread_leave_synchr)(Thread *thr) { 723 #if defined(VGO_solaris) 724 thr->synchr_nesting -= 1; 725 #endif /* VGO_solaris */ 726 tl_assert(thr->synchr_nesting >= 0); 727 } 728 729 static void HG_(thread_enter_pthread_create)(Thread *thr) { 730 tl_assert(thr->pthread_create_nesting_level >= 0); 731 thr->pthread_create_nesting_level += 1; 732 } 733 734 static void HG_(thread_leave_pthread_create)(Thread *thr) { 735 tl_assert(thr->pthread_create_nesting_level > 0); 736 thr->pthread_create_nesting_level -= 1; 737 } 738 739 static Int HG_(get_pthread_create_nesting_level)(ThreadId tid) { 740 Thread *thr = map_threads_maybe_lookup(tid); 741 return thr->pthread_create_nesting_level; 742 } 743 744 /*----------------------------------------------------------------*/ 745 /*--- map_locks :: WordFM guest-Addr-of-lock Lock* ---*/ 746 /*----------------------------------------------------------------*/ 747 748 /* Make sure there is a lock table entry for the given (lock) guest 749 address. If not, create one of the stated 'kind' in unheld state. 750 In any case, return the address of the existing or new Lock. */ 751 static 752 Lock* map_locks_lookup_or_create ( LockKind lkk, Addr ga, ThreadId tid ) 753 { 754 Bool found; 755 Lock* oldlock = NULL; 756 tl_assert(HG_(is_sane_ThreadId)(tid)); 757 found = VG_(lookupFM)( map_locks, 758 NULL, (UWord*)&oldlock, (UWord)ga ); 759 if (!found) { 760 Lock* lock = mk_LockN(lkk, ga); 761 lock->appeared_at = VG_(record_ExeContext)( tid, 0 ); 762 tl_assert(HG_(is_sane_LockN)(lock)); 763 VG_(addToFM)( map_locks, (UWord)ga, (UWord)lock ); 764 tl_assert(oldlock == NULL); 765 return lock; 766 } else { 767 tl_assert(oldlock != NULL); 768 tl_assert(HG_(is_sane_LockN)(oldlock)); 769 tl_assert(oldlock->guestaddr == ga); 770 return oldlock; 771 } 772 } 773 774 static Lock* map_locks_maybe_lookup ( Addr ga ) 775 { 776 Bool found; 777 Lock* lk = NULL; 778 found = VG_(lookupFM)( map_locks, NULL, (UWord*)&lk, (UWord)ga ); 779 tl_assert(found ? lk != NULL : lk == NULL); 780 return lk; 781 } 782 783 static void map_locks_delete ( Addr ga ) 784 { 785 Addr ga2 = 0; 786 Lock* lk = NULL; 787 VG_(delFromFM)( map_locks, 788 (UWord*)&ga2, (UWord*)&lk, (UWord)ga ); 789 /* delFromFM produces the val which is being deleted, if it is 790 found. So assert it is non-null; that in effect asserts that we 791 are deleting a (ga, Lock) pair which actually exists. */ 792 tl_assert(lk != NULL); 793 tl_assert(ga2 == ga); 794 } 795 796 797 798 /*----------------------------------------------------------------*/ 799 /*--- Sanity checking the data structures ---*/ 800 /*----------------------------------------------------------------*/ 801 802 static UWord stats__sanity_checks = 0; 803 804 static void laog__sanity_check ( const HChar* who ); /* fwds */ 805 806 /* REQUIRED INVARIANTS: 807 808 Thread vs Segment/Lock/SecMaps 809 810 for each t in Threads { 811 812 // Thread.lockset: each element is really a valid Lock 813 814 // Thread.lockset: each Lock in set is actually held by that thread 815 for lk in Thread.lockset 816 lk == LockedBy(t) 817 818 // Thread.csegid is a valid SegmentID 819 // and the associated Segment has .thr == t 820 821 } 822 823 all thread Locksets are pairwise empty under intersection 824 (that is, no lock is claimed to be held by more than one thread) 825 -- this is guaranteed if all locks in locksets point back to their 826 owner threads 827 828 Lock vs Thread/Segment/SecMaps 829 830 for each entry (gla, la) in map_locks 831 gla == la->guest_addr 832 833 for each lk in Locks { 834 835 lk->tag is valid 836 lk->guest_addr does not have shadow state NoAccess 837 if lk == LockedBy(t), then t->lockset contains lk 838 if lk == UnlockedBy(segid) then segid is valid SegmentID 839 and can be mapped to a valid Segment(seg) 840 and seg->thr->lockset does not contain lk 841 if lk == UnlockedNew then (no lockset contains lk) 842 843 secmaps for lk has .mbHasLocks == True 844 845 } 846 847 Segment vs Thread/Lock/SecMaps 848 849 the Segment graph is a dag (no cycles) 850 all of the Segment graph must be reachable from the segids 851 mentioned in the Threads 852 853 for seg in Segments { 854 855 seg->thr is a sane Thread 856 857 } 858 859 SecMaps vs Segment/Thread/Lock 860 861 for sm in SecMaps { 862 863 sm properly aligned 864 if any shadow word is ShR or ShM then .mbHasShared == True 865 866 for each Excl(segid) state 867 map_segments_lookup maps to a sane Segment(seg) 868 for each ShM/ShR(tsetid,lsetid) state 869 each lk in lset is a valid Lock 870 each thr in tset is a valid thread, which is non-dead 871 872 } 873 */ 874 875 876 /* Return True iff 'thr' holds 'lk' in some mode. */ 877 static Bool thread_is_a_holder_of_Lock ( Thread* thr, Lock* lk ) 878 { 879 if (lk->heldBy) 880 return VG_(elemBag)( lk->heldBy, (UWord)thr ) > 0; 881 else 882 return False; 883 } 884 885 /* Sanity check Threads, as far as possible */ 886 __attribute__((noinline)) 887 static void threads__sanity_check ( const HChar* who ) 888 { 889 #define BAD(_str) do { how = (_str); goto bad; } while (0) 890 const HChar* how = "no error"; 891 Thread* thr; 892 WordSetID wsA, wsW; 893 UWord* ls_words; 894 UWord ls_size, i; 895 Lock* lk; 896 for (thr = admin_threads; thr; thr = thr->admin) { 897 if (!HG_(is_sane_Thread)(thr)) BAD("1"); 898 wsA = thr->locksetA; 899 wsW = thr->locksetW; 900 // locks held in W mode are a subset of all locks held 901 if (!HG_(isSubsetOf)( univ_lsets, wsW, wsA )) BAD("7"); 902 HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, wsA ); 903 for (i = 0; i < ls_size; i++) { 904 lk = (Lock*)ls_words[i]; 905 // Thread.lockset: each element is really a valid Lock 906 if (!HG_(is_sane_LockN)(lk)) BAD("2"); 907 // Thread.lockset: each Lock in set is actually held by that 908 // thread 909 if (!thread_is_a_holder_of_Lock(thr,lk)) BAD("3"); 910 } 911 } 912 return; 913 bad: 914 VG_(printf)("threads__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how); 915 tl_assert(0); 916 #undef BAD 917 } 918 919 920 /* Sanity check Locks, as far as possible */ 921 __attribute__((noinline)) 922 static void locks__sanity_check ( const HChar* who ) 923 { 924 #define BAD(_str) do { how = (_str); goto bad; } while (0) 925 const HChar* how = "no error"; 926 Addr gla; 927 Lock* lk; 928 Int i; 929 // # entries in admin_locks == # entries in map_locks 930 for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin_next) 931 ; 932 if (i != VG_(sizeFM)(map_locks)) BAD("1"); 933 // for each entry (gla, lk) in map_locks 934 // gla == lk->guest_addr 935 VG_(initIterFM)( map_locks ); 936 while (VG_(nextIterFM)( map_locks, 937 (UWord*)&gla, (UWord*)&lk )) { 938 if (lk->guestaddr != gla) BAD("2"); 939 } 940 VG_(doneIterFM)( map_locks ); 941 // scan through admin_locks ... 942 for (lk = admin_locks; lk; lk = lk->admin_next) { 943 // lock is sane. Quite comprehensive, also checks that 944 // referenced (holder) threads are sane. 945 if (!HG_(is_sane_LockN)(lk)) BAD("3"); 946 // map_locks binds guest address back to this lock 947 if (lk != map_locks_maybe_lookup(lk->guestaddr)) BAD("4"); 948 // look at all threads mentioned as holders of this lock. Ensure 949 // this lock is mentioned in their locksets. 950 if (lk->heldBy) { 951 Thread* thr; 952 UWord count; 953 VG_(initIterBag)( lk->heldBy ); 954 while (VG_(nextIterBag)( lk->heldBy, 955 (UWord*)&thr, &count )) { 956 // HG_(is_sane_LockN) above ensures these 957 tl_assert(count >= 1); 958 tl_assert(HG_(is_sane_Thread)(thr)); 959 if (!HG_(elemWS)(univ_lsets, thr->locksetA, (UWord)lk)) 960 BAD("6"); 961 // also check the w-only lockset 962 if (lk->heldW 963 && !HG_(elemWS)(univ_lsets, thr->locksetW, (UWord)lk)) 964 BAD("7"); 965 if ((!lk->heldW) 966 && HG_(elemWS)(univ_lsets, thr->locksetW, (UWord)lk)) 967 BAD("8"); 968 } 969 VG_(doneIterBag)( lk->heldBy ); 970 } else { 971 /* lock not held by anybody */ 972 if (lk->heldW) BAD("9"); /* should be False if !heldBy */ 973 // since lk is unheld, then (no lockset contains lk) 974 // hmm, this is really too expensive to check. Hmm. 975 } 976 } 977 978 return; 979 bad: 980 VG_(printf)("locks__sanity_check: who=\"%s\", bad=\"%s\"\n", who, how); 981 tl_assert(0); 982 #undef BAD 983 } 984 985 986 static void all_except_Locks__sanity_check ( const HChar* who ) { 987 stats__sanity_checks++; 988 if (0) VG_(printf)("all_except_Locks__sanity_check(%s)\n", who); 989 threads__sanity_check(who); 990 if (HG_(clo_track_lockorders)) 991 laog__sanity_check(who); 992 } 993 static void all__sanity_check ( const HChar* who ) { 994 all_except_Locks__sanity_check(who); 995 locks__sanity_check(who); 996 } 997 998 999 /*----------------------------------------------------------------*/ 1000 /*--- Shadow value and address range handlers ---*/ 1001 /*----------------------------------------------------------------*/ 1002 1003 static void laog__pre_thread_acquires_lock ( Thread*, Lock* ); /* fwds */ 1004 //static void laog__handle_lock_deletions ( WordSetID ); /* fwds */ 1005 static inline Thread* get_current_Thread ( void ); /* fwds */ 1006 __attribute__((noinline)) 1007 static void laog__handle_one_lock_deletion ( Lock* lk ); /* fwds */ 1008 1009 1010 /* Block-copy states (needed for implementing realloc()). */ 1011 /* FIXME this copies shadow memory; it doesn't apply the MSM to it. 1012 Is that a problem? (hence 'scopy' rather than 'ccopy') */ 1013 static void shadow_mem_scopy_range ( Thread* thr, 1014 Addr src, Addr dst, SizeT len ) 1015 { 1016 Thr* hbthr = thr->hbthr; 1017 tl_assert(hbthr); 1018 libhb_copy_shadow_state( hbthr, src, dst, len ); 1019 } 1020 1021 static void shadow_mem_cread_range ( Thread* thr, Addr a, SizeT len ) 1022 { 1023 Thr* hbthr = thr->hbthr; 1024 tl_assert(hbthr); 1025 LIBHB_CREAD_N(hbthr, a, len); 1026 } 1027 1028 static void shadow_mem_cwrite_range ( Thread* thr, Addr a, SizeT len ) { 1029 Thr* hbthr = thr->hbthr; 1030 tl_assert(hbthr); 1031 LIBHB_CWRITE_N(hbthr, a, len); 1032 } 1033 1034 static void shadow_mem_make_New ( Thread* thr, Addr a, SizeT len ) 1035 { 1036 libhb_srange_new( thr->hbthr, a, len ); 1037 } 1038 1039 static void shadow_mem_make_NoAccess_NoFX ( Thread* thr, Addr aIN, SizeT len ) 1040 { 1041 if (0 && len > 500) 1042 VG_(printf)("make NoAccess_NoFX ( %#lx, %lu )\n", aIN, len ); 1043 // has no effect (NoFX) 1044 libhb_srange_noaccess_NoFX( thr->hbthr, aIN, len ); 1045 } 1046 1047 static void shadow_mem_make_NoAccess_AHAE ( Thread* thr, Addr aIN, SizeT len ) 1048 { 1049 if (0 && len > 500) 1050 VG_(printf)("make NoAccess_AHAE ( %#lx, %lu )\n", aIN, len ); 1051 // Actually Has An Effect (AHAE) 1052 libhb_srange_noaccess_AHAE( thr->hbthr, aIN, len ); 1053 } 1054 1055 static void shadow_mem_make_Untracked ( Thread* thr, Addr aIN, SizeT len ) 1056 { 1057 if (0 && len > 500) 1058 VG_(printf)("make Untracked ( %#lx, %lu )\n", aIN, len ); 1059 libhb_srange_untrack( thr->hbthr, aIN, len ); 1060 } 1061 1062 1063 /*----------------------------------------------------------------*/ 1064 /*--- Event handlers (evh__* functions) ---*/ 1065 /*--- plus helpers (evhH__* functions) ---*/ 1066 /*----------------------------------------------------------------*/ 1067 1068 /*--------- Event handler helpers (evhH__* functions) ---------*/ 1069 1070 /* Create a new segment for 'thr', making it depend (.prev) on its 1071 existing segment, bind together the SegmentID and Segment, and 1072 return both of them. Also update 'thr' so it references the new 1073 Segment. */ 1074 //zz static 1075 //zz void evhH__start_new_segment_for_thread ( /*OUT*/SegmentID* new_segidP, 1076 //zz /*OUT*/Segment** new_segP, 1077 //zz Thread* thr ) 1078 //zz { 1079 //zz Segment* cur_seg; 1080 //zz tl_assert(new_segP); 1081 //zz tl_assert(new_segidP); 1082 //zz tl_assert(HG_(is_sane_Thread)(thr)); 1083 //zz cur_seg = map_segments_lookup( thr->csegid ); 1084 //zz tl_assert(cur_seg); 1085 //zz tl_assert(cur_seg->thr == thr); /* all sane segs should point back 1086 //zz at their owner thread. */ 1087 //zz *new_segP = mk_Segment( thr, cur_seg, NULL/*other*/ ); 1088 //zz *new_segidP = alloc_SegmentID(); 1089 //zz map_segments_add( *new_segidP, *new_segP ); 1090 //zz thr->csegid = *new_segidP; 1091 //zz } 1092 1093 1094 /* The lock at 'lock_ga' has acquired a writer. Make all necessary 1095 updates, and also do all possible error checks. */ 1096 static 1097 void evhH__post_thread_w_acquires_lock ( Thread* thr, 1098 LockKind lkk, Addr lock_ga ) 1099 { 1100 Lock* lk; 1101 1102 /* Basically what we need to do is call lockN_acquire_writer. 1103 However, that will barf if any 'invalid' lock states would 1104 result. Therefore check before calling. Side effect is that 1105 'HG_(is_sane_LockN)(lk)' is both a pre- and post-condition of this 1106 routine. 1107 1108 Because this routine is only called after successful lock 1109 acquisition, we should not be asked to move the lock into any 1110 invalid states. Requests to do so are bugs in libpthread, since 1111 that should have rejected any such requests. */ 1112 1113 tl_assert(HG_(is_sane_Thread)(thr)); 1114 /* Try to find the lock. If we can't, then create a new one with 1115 kind 'lkk'. */ 1116 lk = map_locks_lookup_or_create( 1117 lkk, lock_ga, map_threads_reverse_lookup_SLOW(thr) ); 1118 tl_assert( HG_(is_sane_LockN)(lk) ); 1119 1120 /* check libhb level entities exist */ 1121 tl_assert(thr->hbthr); 1122 tl_assert(lk->hbso); 1123 1124 if (lk->heldBy == NULL) { 1125 /* the lock isn't held. Simple. */ 1126 tl_assert(!lk->heldW); 1127 lockN_acquire_writer( lk, thr ); 1128 /* acquire a dependency from the lock's VCs */ 1129 libhb_so_recv( thr->hbthr, lk->hbso, True/*strong_recv*/ ); 1130 goto noerror; 1131 } 1132 1133 /* So the lock is already held. If held as a r-lock then 1134 libpthread must be buggy. */ 1135 tl_assert(lk->heldBy); 1136 if (!lk->heldW) { 1137 HG_(record_error_Misc)( 1138 thr, "Bug in libpthread: write lock " 1139 "granted on rwlock which is currently rd-held"); 1140 goto error; 1141 } 1142 1143 /* So the lock is held in w-mode. If it's held by some other 1144 thread, then libpthread must be buggy. */ 1145 tl_assert(VG_(sizeUniqueBag)(lk->heldBy) == 1); /* from precondition */ 1146 1147 if (thr != (Thread*)VG_(anyElementOfBag)(lk->heldBy)) { 1148 HG_(record_error_Misc)( 1149 thr, "Bug in libpthread: write lock " 1150 "granted on mutex/rwlock which is currently " 1151 "wr-held by a different thread"); 1152 goto error; 1153 } 1154 1155 /* So the lock is already held in w-mode by 'thr'. That means this 1156 is an attempt to lock it recursively, which is only allowable 1157 for LK_mbRec kinded locks. Since this routine is called only 1158 once the lock has been acquired, this must also be a libpthread 1159 bug. */ 1160 if (lk->kind != LK_mbRec) { 1161 HG_(record_error_Misc)( 1162 thr, "Bug in libpthread: recursive write lock " 1163 "granted on mutex/wrlock which does not " 1164 "support recursion"); 1165 goto error; 1166 } 1167 1168 /* So we are recursively re-locking a lock we already w-hold. */ 1169 lockN_acquire_writer( lk, thr ); 1170 /* acquire a dependency from the lock's VC. Probably pointless, 1171 but also harmless. */ 1172 libhb_so_recv( thr->hbthr, lk->hbso, True/*strong_recv*/ ); 1173 goto noerror; 1174 1175 noerror: 1176 if (HG_(clo_track_lockorders)) { 1177 /* check lock order acquisition graph, and update. This has to 1178 happen before the lock is added to the thread's locksetA/W. */ 1179 laog__pre_thread_acquires_lock( thr, lk ); 1180 } 1181 /* update the thread's held-locks set */ 1182 thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (UWord)lk ); 1183 thr->locksetW = HG_(addToWS)( univ_lsets, thr->locksetW, (UWord)lk ); 1184 /* fall through */ 1185 1186 error: 1187 tl_assert(HG_(is_sane_LockN)(lk)); 1188 } 1189 1190 1191 /* The lock at 'lock_ga' has acquired a reader. Make all necessary 1192 updates, and also do all possible error checks. */ 1193 static 1194 void evhH__post_thread_r_acquires_lock ( Thread* thr, 1195 LockKind lkk, Addr lock_ga ) 1196 { 1197 Lock* lk; 1198 1199 /* Basically what we need to do is call lockN_acquire_reader. 1200 However, that will barf if any 'invalid' lock states would 1201 result. Therefore check before calling. Side effect is that 1202 'HG_(is_sane_LockN)(lk)' is both a pre- and post-condition of this 1203 routine. 1204 1205 Because this routine is only called after successful lock 1206 acquisition, we should not be asked to move the lock into any 1207 invalid states. Requests to do so are bugs in libpthread, since 1208 that should have rejected any such requests. */ 1209 1210 tl_assert(HG_(is_sane_Thread)(thr)); 1211 /* Try to find the lock. If we can't, then create a new one with 1212 kind 'lkk'. Only a reader-writer lock can be read-locked, 1213 hence the first assertion. */ 1214 tl_assert(lkk == LK_rdwr); 1215 lk = map_locks_lookup_or_create( 1216 lkk, lock_ga, map_threads_reverse_lookup_SLOW(thr) ); 1217 tl_assert( HG_(is_sane_LockN)(lk) ); 1218 1219 /* check libhb level entities exist */ 1220 tl_assert(thr->hbthr); 1221 tl_assert(lk->hbso); 1222 1223 if (lk->heldBy == NULL) { 1224 /* the lock isn't held. Simple. */ 1225 tl_assert(!lk->heldW); 1226 lockN_acquire_reader( lk, thr ); 1227 /* acquire a dependency from the lock's VC */ 1228 libhb_so_recv( thr->hbthr, lk->hbso, False/*!strong_recv*/ ); 1229 goto noerror; 1230 } 1231 1232 /* So the lock is already held. If held as a w-lock then 1233 libpthread must be buggy. */ 1234 tl_assert(lk->heldBy); 1235 if (lk->heldW) { 1236 HG_(record_error_Misc)( thr, "Bug in libpthread: read lock " 1237 "granted on rwlock which is " 1238 "currently wr-held"); 1239 goto error; 1240 } 1241 1242 /* Easy enough. In short anybody can get a read-lock on a rwlock 1243 provided it is either unlocked or already in rd-held. */ 1244 lockN_acquire_reader( lk, thr ); 1245 /* acquire a dependency from the lock's VC. Probably pointless, 1246 but also harmless. */ 1247 libhb_so_recv( thr->hbthr, lk->hbso, False/*!strong_recv*/ ); 1248 goto noerror; 1249 1250 noerror: 1251 if (HG_(clo_track_lockorders)) { 1252 /* check lock order acquisition graph, and update. This has to 1253 happen before the lock is added to the thread's locksetA/W. */ 1254 laog__pre_thread_acquires_lock( thr, lk ); 1255 } 1256 /* update the thread's held-locks set */ 1257 thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (UWord)lk ); 1258 /* but don't update thr->locksetW, since lk is only rd-held */ 1259 /* fall through */ 1260 1261 error: 1262 tl_assert(HG_(is_sane_LockN)(lk)); 1263 } 1264 1265 1266 /* The lock at 'lock_ga' is just about to be unlocked. Make all 1267 necessary updates, and also do all possible error checks. */ 1268 static 1269 void evhH__pre_thread_releases_lock ( Thread* thr, 1270 Addr lock_ga, Bool isRDWR ) 1271 { 1272 Lock* lock; 1273 Word n; 1274 Bool was_heldW; 1275 1276 /* This routine is called prior to a lock release, before 1277 libpthread has had a chance to validate the call. Hence we need 1278 to detect and reject any attempts to move the lock into an 1279 invalid state. Such attempts are bugs in the client. 1280 1281 isRDWR is True if we know from the wrapper context that lock_ga 1282 should refer to a reader-writer lock, and is False if [ditto] 1283 lock_ga should refer to a standard mutex. */ 1284 1285 tl_assert(HG_(is_sane_Thread)(thr)); 1286 lock = map_locks_maybe_lookup( lock_ga ); 1287 1288 if (!lock) { 1289 /* We know nothing about a lock at 'lock_ga'. Nevertheless 1290 the client is trying to unlock it. So complain, then ignore 1291 the attempt. */ 1292 HG_(record_error_UnlockBogus)( thr, lock_ga ); 1293 return; 1294 } 1295 1296 tl_assert(lock->guestaddr == lock_ga); 1297 tl_assert(HG_(is_sane_LockN)(lock)); 1298 1299 if (isRDWR && lock->kind != LK_rdwr) { 1300 HG_(record_error_Misc)( thr, "pthread_rwlock_unlock with a " 1301 "pthread_mutex_t* argument " ); 1302 } 1303 if ((!isRDWR) && lock->kind == LK_rdwr) { 1304 HG_(record_error_Misc)( thr, "pthread_mutex_unlock with a " 1305 "pthread_rwlock_t* argument " ); 1306 } 1307 1308 if (!lock->heldBy) { 1309 /* The lock is not held. This indicates a serious bug in the 1310 client. */ 1311 tl_assert(!lock->heldW); 1312 HG_(record_error_UnlockUnlocked)( thr, lock ); 1313 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetA, (UWord)lock )); 1314 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (UWord)lock )); 1315 goto error; 1316 } 1317 1318 /* test just above dominates */ 1319 tl_assert(lock->heldBy); 1320 was_heldW = lock->heldW; 1321 1322 /* The lock is held. Is this thread one of the holders? If not, 1323 report a bug in the client. */ 1324 n = VG_(elemBag)( lock->heldBy, (UWord)thr ); 1325 tl_assert(n >= 0); 1326 if (n == 0) { 1327 /* We are not a current holder of the lock. This is a bug in 1328 the guest, and (per POSIX pthread rules) the unlock 1329 attempt will fail. So just complain and do nothing 1330 else. */ 1331 Thread* realOwner = (Thread*)VG_(anyElementOfBag)( lock->heldBy ); 1332 tl_assert(HG_(is_sane_Thread)(realOwner)); 1333 tl_assert(realOwner != thr); 1334 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetA, (UWord)lock )); 1335 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (UWord)lock )); 1336 HG_(record_error_UnlockForeign)( thr, realOwner, lock ); 1337 goto error; 1338 } 1339 1340 /* Ok, we hold the lock 'n' times. */ 1341 tl_assert(n >= 1); 1342 1343 lockN_release( lock, thr ); 1344 1345 n--; 1346 tl_assert(n >= 0); 1347 1348 if (n > 0) { 1349 tl_assert(lock->heldBy); 1350 tl_assert(n == VG_(elemBag)( lock->heldBy, (UWord)thr )); 1351 /* We still hold the lock. So either it's a recursive lock 1352 or a rwlock which is currently r-held. */ 1353 tl_assert(lock->kind == LK_mbRec 1354 || (lock->kind == LK_rdwr && !lock->heldW)); 1355 tl_assert(HG_(elemWS)( univ_lsets, thr->locksetA, (UWord)lock )); 1356 if (lock->heldW) 1357 tl_assert(HG_(elemWS)( univ_lsets, thr->locksetW, (UWord)lock )); 1358 else 1359 tl_assert(!HG_(elemWS)( univ_lsets, thr->locksetW, (UWord)lock )); 1360 } else { 1361 /* n is zero. This means we don't hold the lock any more. But 1362 if it's a rwlock held in r-mode, someone else could still 1363 hold it. Just do whatever sanity checks we can. */ 1364 if (lock->kind == LK_rdwr && lock->heldBy) { 1365 /* It's a rwlock. We no longer hold it but we used to; 1366 nevertheless it still appears to be held by someone else. 1367 The implication is that, prior to this release, it must 1368 have been shared by us and and whoever else is holding it; 1369 which in turn implies it must be r-held, since a lock 1370 can't be w-held by more than one thread. */ 1371 /* The lock is now R-held by somebody else: */ 1372 tl_assert(lock->heldW == False); 1373 } else { 1374 /* Normal case. It's either not a rwlock, or it's a rwlock 1375 that we used to hold in w-mode (which is pretty much the 1376 same thing as a non-rwlock.) Since this transaction is 1377 atomic (V does not allow multiple threads to run 1378 simultaneously), it must mean the lock is now not held by 1379 anybody. Hence assert for it. */ 1380 /* The lock is now not held by anybody: */ 1381 tl_assert(!lock->heldBy); 1382 tl_assert(lock->heldW == False); 1383 } 1384 //if (lock->heldBy) { 1385 // tl_assert(0 == VG_(elemBag)( lock->heldBy, (UWord)thr )); 1386 //} 1387 /* update this thread's lockset accordingly. */ 1388 thr->locksetA 1389 = HG_(delFromWS)( univ_lsets, thr->locksetA, (UWord)lock ); 1390 thr->locksetW 1391 = HG_(delFromWS)( univ_lsets, thr->locksetW, (UWord)lock ); 1392 /* push our VC into the lock */ 1393 tl_assert(thr->hbthr); 1394 tl_assert(lock->hbso); 1395 /* If the lock was previously W-held, then we want to do a 1396 strong send, and if previously R-held, then a weak send. */ 1397 libhb_so_send( thr->hbthr, lock->hbso, was_heldW ); 1398 } 1399 /* fall through */ 1400 1401 error: 1402 tl_assert(HG_(is_sane_LockN)(lock)); 1403 } 1404 1405 1406 /* ---------------------------------------------------------- */ 1407 /* -------- Event handlers proper (evh__* functions) -------- */ 1408 /* ---------------------------------------------------------- */ 1409 1410 /* What is the Thread* for the currently running thread? This is 1411 absolutely performance critical. We receive notifications from the 1412 core for client code starts/stops, and cache the looked-up result 1413 in 'current_Thread'. Hence, for the vast majority of requests, 1414 finding the current thread reduces to a read of a global variable, 1415 provided get_current_Thread_in_C_C is inlined. 1416 1417 Outside of client code, current_Thread is NULL, and presumably 1418 any uses of it will cause a segfault. Hence: 1419 1420 - for uses definitely within client code, use 1421 get_current_Thread_in_C_C. 1422 1423 - for all other uses, use get_current_Thread. 1424 */ 1425 1426 static Thread *current_Thread = NULL, 1427 *current_Thread_prev = NULL; 1428 1429 static void evh__start_client_code ( ThreadId tid, ULong nDisp ) { 1430 if (0) VG_(printf)("start %d %llu\n", (Int)tid, nDisp); 1431 tl_assert(current_Thread == NULL); 1432 current_Thread = map_threads_lookup( tid ); 1433 tl_assert(current_Thread != NULL); 1434 if (current_Thread != current_Thread_prev) { 1435 libhb_Thr_resumes( current_Thread->hbthr ); 1436 current_Thread_prev = current_Thread; 1437 } 1438 } 1439 static void evh__stop_client_code ( ThreadId tid, ULong nDisp ) { 1440 if (0) VG_(printf)(" stop %d %llu\n", (Int)tid, nDisp); 1441 tl_assert(current_Thread != NULL); 1442 current_Thread = NULL; 1443 libhb_maybe_GC(); 1444 } 1445 static inline Thread* get_current_Thread_in_C_C ( void ) { 1446 return current_Thread; 1447 } 1448 static inline Thread* get_current_Thread ( void ) { 1449 ThreadId coretid; 1450 Thread* thr; 1451 thr = get_current_Thread_in_C_C(); 1452 if (LIKELY(thr)) 1453 return thr; 1454 /* evidently not in client code. Do it the slow way. */ 1455 coretid = VG_(get_running_tid)(); 1456 /* FIXME: get rid of the following kludge. It exists because 1457 evh__new_mem is called during initialisation (as notification 1458 of initial memory layout) and VG_(get_running_tid)() returns 1459 VG_INVALID_THREADID at that point. */ 1460 if (coretid == VG_INVALID_THREADID) 1461 coretid = 1; /* KLUDGE */ 1462 thr = map_threads_lookup( coretid ); 1463 return thr; 1464 } 1465 1466 static 1467 void evh__new_mem ( Addr a, SizeT len ) { 1468 Thread *thr = get_current_Thread(); 1469 if (SHOW_EVENTS >= 2) 1470 VG_(printf)("evh__new_mem(%p, %lu)\n", (void*)a, len ); 1471 shadow_mem_make_New( thr, a, len ); 1472 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1473 all__sanity_check("evh__new_mem-post"); 1474 if (UNLIKELY(thr->pthread_create_nesting_level > 0)) 1475 shadow_mem_make_Untracked( thr, a, len ); 1476 } 1477 1478 static 1479 void evh__new_mem_stack ( Addr a, SizeT len ) { 1480 Thread *thr = get_current_Thread(); 1481 if (SHOW_EVENTS >= 2) 1482 VG_(printf)("evh__new_mem_stack(%p, %lu)\n", (void*)a, len ); 1483 shadow_mem_make_New( thr, -VG_STACK_REDZONE_SZB + a, len ); 1484 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1485 all__sanity_check("evh__new_mem_stack-post"); 1486 if (UNLIKELY(thr->pthread_create_nesting_level > 0)) 1487 shadow_mem_make_Untracked( thr, a, len ); 1488 } 1489 1490 static 1491 void evh__new_mem_w_tid ( Addr a, SizeT len, ThreadId tid ) { 1492 Thread *thr = get_current_Thread(); 1493 if (SHOW_EVENTS >= 2) 1494 VG_(printf)("evh__new_mem_w_tid(%p, %lu)\n", (void*)a, len ); 1495 shadow_mem_make_New( thr, a, len ); 1496 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1497 all__sanity_check("evh__new_mem_w_tid-post"); 1498 if (UNLIKELY(thr->pthread_create_nesting_level > 0)) 1499 shadow_mem_make_Untracked( thr, a, len ); 1500 } 1501 1502 static 1503 void evh__new_mem_w_perms ( Addr a, SizeT len, 1504 Bool rr, Bool ww, Bool xx, ULong di_handle ) { 1505 Thread *thr = get_current_Thread(); 1506 if (SHOW_EVENTS >= 1) 1507 VG_(printf)("evh__new_mem_w_perms(%p, %lu, %d,%d,%d)\n", 1508 (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); 1509 if (rr || ww || xx) { 1510 shadow_mem_make_New( thr, a, len ); 1511 if (UNLIKELY(thr->pthread_create_nesting_level > 0)) 1512 shadow_mem_make_Untracked( thr, a, len ); 1513 } 1514 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1515 all__sanity_check("evh__new_mem_w_perms-post"); 1516 } 1517 1518 static 1519 void evh__set_perms ( Addr a, SizeT len, 1520 Bool rr, Bool ww, Bool xx ) { 1521 // This handles mprotect requests. If the memory is being put 1522 // into no-R no-W state, paint it as NoAccess, for the reasons 1523 // documented at evh__die_mem_munmap(). 1524 if (SHOW_EVENTS >= 1) 1525 VG_(printf)("evh__set_perms(%p, %lu, r=%d w=%d x=%d)\n", 1526 (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); 1527 /* Hmm. What should we do here, that actually makes any sense? 1528 Let's say: if neither readable nor writable, then declare it 1529 NoAccess, else leave it alone. */ 1530 if (!(rr || ww)) 1531 shadow_mem_make_NoAccess_AHAE( get_current_Thread(), a, len ); 1532 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1533 all__sanity_check("evh__set_perms-post"); 1534 } 1535 1536 static 1537 void evh__die_mem ( Addr a, SizeT len ) { 1538 // Urr, libhb ignores this. 1539 if (SHOW_EVENTS >= 2) 1540 VG_(printf)("evh__die_mem(%p, %lu)\n", (void*)a, len ); 1541 shadow_mem_make_NoAccess_NoFX( get_current_Thread(), a, len ); 1542 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1543 all__sanity_check("evh__die_mem-post"); 1544 } 1545 1546 static 1547 void evh__die_mem_munmap ( Addr a, SizeT len ) { 1548 // It's important that libhb doesn't ignore this. If, as is likely, 1549 // the client is subject to address space layout randomization, 1550 // then unmapped areas may never get remapped over, even in long 1551 // runs. If we just ignore them we wind up with large resource 1552 // (VTS) leaks in libhb. So force them to NoAccess, so that all 1553 // VTS references in the affected area are dropped. Marking memory 1554 // as NoAccess is expensive, but we assume that munmap is sufficiently 1555 // rare that the space gains of doing this are worth the costs. 1556 if (SHOW_EVENTS >= 2) 1557 VG_(printf)("evh__die_mem_munmap(%p, %lu)\n", (void*)a, len ); 1558 shadow_mem_make_NoAccess_AHAE( get_current_Thread(), a, len ); 1559 } 1560 1561 static 1562 void evh__untrack_mem ( Addr a, SizeT len ) { 1563 // Libhb doesn't ignore this. 1564 if (SHOW_EVENTS >= 2) 1565 VG_(printf)("evh__untrack_mem(%p, %lu)\n", (void*)a, len ); 1566 shadow_mem_make_Untracked( get_current_Thread(), a, len ); 1567 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1568 all__sanity_check("evh__untrack_mem-post"); 1569 } 1570 1571 static 1572 void evh__copy_mem ( Addr src, Addr dst, SizeT len ) { 1573 if (SHOW_EVENTS >= 2) 1574 VG_(printf)("evh__copy_mem(%p, %p, %lu)\n", (void*)src, (void*)dst, len ); 1575 Thread *thr = get_current_Thread(); 1576 if (LIKELY(thr->synchr_nesting == 0)) 1577 shadow_mem_scopy_range( thr , src, dst, len ); 1578 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1579 all__sanity_check("evh__copy_mem-post"); 1580 } 1581 1582 static 1583 void evh__pre_thread_ll_create ( ThreadId parent, ThreadId child ) 1584 { 1585 if (SHOW_EVENTS >= 1) 1586 VG_(printf)("evh__pre_thread_ll_create(p=%d, c=%d)\n", 1587 (Int)parent, (Int)child ); 1588 1589 if (parent != VG_INVALID_THREADID) { 1590 Thread* thr_p; 1591 Thread* thr_c; 1592 Thr* hbthr_p; 1593 Thr* hbthr_c; 1594 1595 tl_assert(HG_(is_sane_ThreadId)(parent)); 1596 tl_assert(HG_(is_sane_ThreadId)(child)); 1597 tl_assert(parent != child); 1598 1599 thr_p = map_threads_maybe_lookup( parent ); 1600 thr_c = map_threads_maybe_lookup( child ); 1601 1602 tl_assert(thr_p != NULL); 1603 tl_assert(thr_c == NULL); 1604 1605 hbthr_p = thr_p->hbthr; 1606 tl_assert(hbthr_p != NULL); 1607 tl_assert( libhb_get_Thr_hgthread(hbthr_p) == thr_p ); 1608 1609 hbthr_c = libhb_create ( hbthr_p ); 1610 1611 /* Create a new thread record for the child. */ 1612 /* a Thread for the new thread ... */ 1613 thr_c = mk_Thread( hbthr_c ); 1614 tl_assert( libhb_get_Thr_hgthread(hbthr_c) == NULL ); 1615 libhb_set_Thr_hgthread(hbthr_c, thr_c); 1616 1617 /* and bind it in the thread-map table */ 1618 map_threads[child] = thr_c; 1619 tl_assert(thr_c->coretid == VG_INVALID_THREADID); 1620 thr_c->coretid = child; 1621 1622 /* Record where the parent is so we can later refer to this in 1623 error messages. 1624 1625 On x86/amd64-linux, this entails a nasty glibc specific hack. 1626 The stack snapshot is taken immediately after the parent has 1627 returned from its sys_clone call. Unfortunately there is no 1628 unwind info for the insn following "syscall" - reading the 1629 glibc sources confirms this. So we ask for a snapshot to be 1630 taken as if RIP was 3 bytes earlier, in a place where there 1631 is unwind info. Sigh. 1632 */ 1633 { Word first_ip_delta = 0; 1634 # if defined(VGP_amd64_linux) || defined(VGP_x86_linux) 1635 first_ip_delta = -3; 1636 # elif defined(VGP_arm64_linux) || defined(VGP_arm_linux) 1637 first_ip_delta = -1; 1638 # endif 1639 thr_c->created_at = VG_(record_ExeContext)(parent, first_ip_delta); 1640 } 1641 1642 if (HG_(clo_ignore_thread_creation)) { 1643 HG_(thread_enter_pthread_create)(thr_c); 1644 tl_assert(thr_c->synchr_nesting == 0); 1645 HG_(thread_enter_synchr)(thr_c); 1646 /* Counterpart in _VG_USERREQ__HG_SET_MY_PTHREAD_T. */ 1647 } 1648 } 1649 1650 if (HG_(clo_sanity_flags) & SCE_THREADS) 1651 all__sanity_check("evh__pre_thread_create-post"); 1652 } 1653 1654 static 1655 void evh__pre_thread_ll_exit ( ThreadId quit_tid ) 1656 { 1657 Int nHeld; 1658 Thread* thr_q; 1659 if (SHOW_EVENTS >= 1) 1660 VG_(printf)("evh__pre_thread_ll_exit(thr=%d)\n", 1661 (Int)quit_tid ); 1662 1663 /* quit_tid has disappeared without joining to any other thread. 1664 Therefore there is no synchronisation event associated with its 1665 exit and so we have to pretty much treat it as if it was still 1666 alive but mysteriously making no progress. That is because, if 1667 we don't know when it really exited, then we can never say there 1668 is a point in time when we're sure the thread really has 1669 finished, and so we need to consider the possibility that it 1670 lingers indefinitely and continues to interact with other 1671 threads. */ 1672 /* However, it might have rendezvous'd with a thread that called 1673 pthread_join with this one as arg, prior to this point (that's 1674 how NPTL works). In which case there has already been a prior 1675 sync event. So in any case, just let the thread exit. On NPTL, 1676 all thread exits go through here. */ 1677 tl_assert(HG_(is_sane_ThreadId)(quit_tid)); 1678 thr_q = map_threads_maybe_lookup( quit_tid ); 1679 tl_assert(thr_q != NULL); 1680 1681 /* Complain if this thread holds any locks. */ 1682 nHeld = HG_(cardinalityWS)( univ_lsets, thr_q->locksetA ); 1683 tl_assert(nHeld >= 0); 1684 if (nHeld > 0) { 1685 HChar buf[80]; 1686 VG_(sprintf)(buf, "Exiting thread still holds %d lock%s", 1687 nHeld, nHeld > 1 ? "s" : ""); 1688 HG_(record_error_Misc)( thr_q, buf ); 1689 } 1690 1691 /* Not much to do here: 1692 - tell libhb the thread is gone 1693 - clear the map_threads entry, in order that the Valgrind core 1694 can re-use it. */ 1695 /* Cleanup actions (next 5 lines) copied in evh__atfork_child; keep 1696 in sync. */ 1697 tl_assert(thr_q->hbthr); 1698 libhb_async_exit(thr_q->hbthr); 1699 tl_assert(thr_q->coretid == quit_tid); 1700 thr_q->coretid = VG_INVALID_THREADID; 1701 map_threads_delete( quit_tid ); 1702 1703 if (HG_(clo_sanity_flags) & SCE_THREADS) 1704 all__sanity_check("evh__pre_thread_ll_exit-post"); 1705 } 1706 1707 /* This is called immediately after fork, for the child only. 'tid' 1708 is the only surviving thread (as per POSIX rules on fork() in 1709 threaded programs), so we have to clean up map_threads to remove 1710 entries for any other threads. */ 1711 static 1712 void evh__atfork_child ( ThreadId tid ) 1713 { 1714 UInt i; 1715 Thread* thr; 1716 /* Slot 0 should never be used. */ 1717 thr = map_threads_maybe_lookup( 0/*INVALID*/ ); 1718 tl_assert(!thr); 1719 /* Clean up all other slots except 'tid'. */ 1720 for (i = 1; i < VG_N_THREADS; i++) { 1721 if (i == tid) 1722 continue; 1723 thr = map_threads_maybe_lookup(i); 1724 if (!thr) 1725 continue; 1726 /* Cleanup actions (next 5 lines) copied from end of 1727 evh__pre_thread_ll_exit; keep in sync. */ 1728 tl_assert(thr->hbthr); 1729 libhb_async_exit(thr->hbthr); 1730 tl_assert(thr->coretid == i); 1731 thr->coretid = VG_INVALID_THREADID; 1732 map_threads_delete(i); 1733 } 1734 } 1735 1736 /* generate a dependence from the hbthr_q quitter to the hbthr_s stayer. */ 1737 static 1738 void generate_quitter_stayer_dependence (Thr* hbthr_q, Thr* hbthr_s) 1739 { 1740 SO* so; 1741 /* Allocate a temporary synchronisation object and use it to send 1742 an imaginary message from the quitter to the stayer, the purpose 1743 being to generate a dependence from the quitter to the 1744 stayer. */ 1745 so = libhb_so_alloc(); 1746 tl_assert(so); 1747 /* Send last arg of _so_send as False, since the sending thread 1748 doesn't actually exist any more, so we don't want _so_send to 1749 try taking stack snapshots of it. */ 1750 libhb_so_send(hbthr_q, so, True/*strong_send*//*?!? wrt comment above*/); 1751 libhb_so_recv(hbthr_s, so, True/*strong_recv*/); 1752 libhb_so_dealloc(so); 1753 1754 /* Tell libhb that the quitter has been reaped. Note that we might 1755 have to be cleverer about this, to exclude 2nd and subsequent 1756 notifications for the same hbthr_q, in the case where the app is 1757 buggy (calls pthread_join twice or more on the same thread) AND 1758 where libpthread is also buggy and doesn't return ESRCH on 1759 subsequent calls. (If libpthread isn't thusly buggy, then the 1760 wrapper for pthread_join in hg_intercepts.c will stop us getting 1761 notified here multiple times for the same joinee.) See also 1762 comments in helgrind/tests/jointwice.c. */ 1763 libhb_joinedwith_done(hbthr_q); 1764 } 1765 1766 1767 static 1768 void evh__HG_PTHREAD_JOIN_POST ( ThreadId stay_tid, Thread* quit_thr ) 1769 { 1770 Thread* thr_s; 1771 Thread* thr_q; 1772 Thr* hbthr_s; 1773 Thr* hbthr_q; 1774 1775 if (SHOW_EVENTS >= 1) 1776 VG_(printf)("evh__post_thread_join(stayer=%d, quitter=%p)\n", 1777 (Int)stay_tid, quit_thr ); 1778 1779 tl_assert(HG_(is_sane_ThreadId)(stay_tid)); 1780 1781 thr_s = map_threads_maybe_lookup( stay_tid ); 1782 thr_q = quit_thr; 1783 tl_assert(thr_s != NULL); 1784 tl_assert(thr_q != NULL); 1785 tl_assert(thr_s != thr_q); 1786 1787 hbthr_s = thr_s->hbthr; 1788 hbthr_q = thr_q->hbthr; 1789 tl_assert(hbthr_s != hbthr_q); 1790 tl_assert( libhb_get_Thr_hgthread(hbthr_s) == thr_s ); 1791 tl_assert( libhb_get_Thr_hgthread(hbthr_q) == thr_q ); 1792 1793 generate_quitter_stayer_dependence (hbthr_q, hbthr_s); 1794 1795 /* evh__pre_thread_ll_exit issues an error message if the exiting 1796 thread holds any locks. No need to check here. */ 1797 1798 /* This holds because, at least when using NPTL as the thread 1799 library, we should be notified the low level thread exit before 1800 we hear of any join event on it. The low level exit 1801 notification feeds through into evh__pre_thread_ll_exit, 1802 which should clear the map_threads entry for it. Hence we 1803 expect there to be no map_threads entry at this point. */ 1804 tl_assert( map_threads_maybe_reverse_lookup_SLOW(thr_q) 1805 == VG_INVALID_THREADID); 1806 1807 if (HG_(clo_sanity_flags) & SCE_THREADS) 1808 all__sanity_check("evh__post_thread_join-post"); 1809 } 1810 1811 static 1812 void evh__pre_mem_read ( CorePart part, ThreadId tid, const HChar* s, 1813 Addr a, SizeT size) { 1814 if (SHOW_EVENTS >= 2 1815 || (SHOW_EVENTS >= 1 && size != 1)) 1816 VG_(printf)("evh__pre_mem_read(ctid=%d, \"%s\", %p, %lu)\n", 1817 (Int)tid, s, (void*)a, size ); 1818 Thread *thr = map_threads_lookup(tid); 1819 if (LIKELY(thr->synchr_nesting == 0)) 1820 shadow_mem_cread_range(thr, a, size); 1821 if (size >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1822 all__sanity_check("evh__pre_mem_read-post"); 1823 } 1824 1825 static 1826 void evh__pre_mem_read_asciiz ( CorePart part, ThreadId tid, 1827 const HChar* s, Addr a ) { 1828 Int len; 1829 if (SHOW_EVENTS >= 1) 1830 VG_(printf)("evh__pre_mem_asciiz(ctid=%d, \"%s\", %p)\n", 1831 (Int)tid, s, (void*)a ); 1832 // Don't segfault if the string starts in an obviously stupid 1833 // place. Actually we should check the whole string, not just 1834 // the start address, but that's too much trouble. At least 1835 // checking the first byte is better than nothing. See #255009. 1836 if (!VG_(am_is_valid_for_client) (a, 1, VKI_PROT_READ)) 1837 return; 1838 Thread *thr = map_threads_lookup(tid); 1839 len = VG_(strlen)( (HChar*) a ); 1840 if (LIKELY(thr->synchr_nesting == 0)) 1841 shadow_mem_cread_range( thr, a, len+1 ); 1842 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1843 all__sanity_check("evh__pre_mem_read_asciiz-post"); 1844 } 1845 1846 static 1847 void evh__pre_mem_write ( CorePart part, ThreadId tid, const HChar* s, 1848 Addr a, SizeT size ) { 1849 if (SHOW_EVENTS >= 1) 1850 VG_(printf)("evh__pre_mem_write(ctid=%d, \"%s\", %p, %lu)\n", 1851 (Int)tid, s, (void*)a, size ); 1852 Thread *thr = map_threads_lookup(tid); 1853 if (LIKELY(thr->synchr_nesting == 0)) 1854 shadow_mem_cwrite_range(thr, a, size); 1855 if (size >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1856 all__sanity_check("evh__pre_mem_write-post"); 1857 } 1858 1859 static 1860 void evh__new_mem_heap ( Addr a, SizeT len, Bool is_inited ) { 1861 if (SHOW_EVENTS >= 1) 1862 VG_(printf)("evh__new_mem_heap(%p, %lu, inited=%d)\n", 1863 (void*)a, len, (Int)is_inited ); 1864 // We ignore the initialisation state (is_inited); that's ok. 1865 shadow_mem_make_New(get_current_Thread(), a, len); 1866 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1867 all__sanity_check("evh__pre_mem_read-post"); 1868 } 1869 1870 static 1871 void evh__die_mem_heap ( Addr a, SizeT len ) { 1872 Thread* thr; 1873 if (SHOW_EVENTS >= 1) 1874 VG_(printf)("evh__die_mem_heap(%p, %lu)\n", (void*)a, len ); 1875 thr = get_current_Thread(); 1876 tl_assert(thr); 1877 if (HG_(clo_free_is_write)) { 1878 /* Treat frees as if the memory was written immediately prior to 1879 the free. This shakes out more races, specifically, cases 1880 where memory is referenced by one thread, and freed by 1881 another, and there's no observable synchronisation event to 1882 guarantee that the reference happens before the free. */ 1883 if (LIKELY(thr->synchr_nesting == 0)) 1884 shadow_mem_cwrite_range(thr, a, len); 1885 } 1886 shadow_mem_make_NoAccess_AHAE( thr, a, len ); 1887 /* We used to call instead 1888 shadow_mem_make_NoAccess_NoFX( thr, a, len ); 1889 A non-buggy application will not access anymore 1890 the freed memory, and so marking no access is in theory useless. 1891 Not marking freed memory would avoid the overhead for applications 1892 doing mostly malloc/free, as the freed memory should then be recycled 1893 very quickly after marking. 1894 We rather mark it noaccess for the following reasons: 1895 * accessibility bits then always correctly represents the memory 1896 status (e.g. for the client request VALGRIND_HG_GET_ABITS). 1897 * the overhead is reasonable (about 5 seconds per Gb in 1000 bytes 1898 blocks, on a ppc64le, for a unrealistic workload of an application 1899 doing only malloc/free). 1900 * marking no access allows to GC the SecMap, which might improve 1901 performance and/or memory usage. 1902 * we might detect more applications bugs when memory is marked 1903 noaccess. 1904 If needed, we could support here an option --free-is-noaccess=yes|no 1905 to avoid marking freed memory as no access if some applications 1906 would need to avoid the marking noaccess overhead. */ 1907 1908 if (len >= SCE_BIGRANGE_T && (HG_(clo_sanity_flags) & SCE_BIGRANGE)) 1909 all__sanity_check("evh__pre_mem_read-post"); 1910 } 1911 1912 /* --- Event handlers called from generated code --- */ 1913 1914 static VG_REGPARM(1) 1915 void evh__mem_help_cread_1(Addr a) { 1916 Thread* thr = get_current_Thread_in_C_C(); 1917 Thr* hbthr = thr->hbthr; 1918 if (LIKELY(thr->synchr_nesting == 0)) 1919 LIBHB_CREAD_1(hbthr, a); 1920 } 1921 1922 static VG_REGPARM(1) 1923 void evh__mem_help_cread_2(Addr a) { 1924 Thread* thr = get_current_Thread_in_C_C(); 1925 Thr* hbthr = thr->hbthr; 1926 if (LIKELY(thr->synchr_nesting == 0)) 1927 LIBHB_CREAD_2(hbthr, a); 1928 } 1929 1930 static VG_REGPARM(1) 1931 void evh__mem_help_cread_4(Addr a) { 1932 Thread* thr = get_current_Thread_in_C_C(); 1933 Thr* hbthr = thr->hbthr; 1934 if (LIKELY(thr->synchr_nesting == 0)) 1935 LIBHB_CREAD_4(hbthr, a); 1936 } 1937 1938 static VG_REGPARM(1) 1939 void evh__mem_help_cread_8(Addr a) { 1940 Thread* thr = get_current_Thread_in_C_C(); 1941 Thr* hbthr = thr->hbthr; 1942 if (LIKELY(thr->synchr_nesting == 0)) 1943 LIBHB_CREAD_8(hbthr, a); 1944 } 1945 1946 static VG_REGPARM(2) 1947 void evh__mem_help_cread_N(Addr a, SizeT size) { 1948 Thread* thr = get_current_Thread_in_C_C(); 1949 Thr* hbthr = thr->hbthr; 1950 if (LIKELY(thr->synchr_nesting == 0)) 1951 LIBHB_CREAD_N(hbthr, a, size); 1952 } 1953 1954 static VG_REGPARM(1) 1955 void evh__mem_help_cwrite_1(Addr a) { 1956 Thread* thr = get_current_Thread_in_C_C(); 1957 Thr* hbthr = thr->hbthr; 1958 if (LIKELY(thr->synchr_nesting == 0)) 1959 LIBHB_CWRITE_1(hbthr, a); 1960 } 1961 1962 static VG_REGPARM(1) 1963 void evh__mem_help_cwrite_2(Addr a) { 1964 Thread* thr = get_current_Thread_in_C_C(); 1965 Thr* hbthr = thr->hbthr; 1966 if (LIKELY(thr->synchr_nesting == 0)) 1967 LIBHB_CWRITE_2(hbthr, a); 1968 } 1969 1970 static VG_REGPARM(1) 1971 void evh__mem_help_cwrite_4(Addr a) { 1972 Thread* thr = get_current_Thread_in_C_C(); 1973 Thr* hbthr = thr->hbthr; 1974 if (LIKELY(thr->synchr_nesting == 0)) 1975 LIBHB_CWRITE_4(hbthr, a); 1976 } 1977 1978 static VG_REGPARM(1) 1979 void evh__mem_help_cwrite_8(Addr a) { 1980 Thread* thr = get_current_Thread_in_C_C(); 1981 Thr* hbthr = thr->hbthr; 1982 if (LIKELY(thr->synchr_nesting == 0)) 1983 LIBHB_CWRITE_8(hbthr, a); 1984 } 1985 1986 static VG_REGPARM(2) 1987 void evh__mem_help_cwrite_N(Addr a, SizeT size) { 1988 Thread* thr = get_current_Thread_in_C_C(); 1989 Thr* hbthr = thr->hbthr; 1990 if (LIKELY(thr->synchr_nesting == 0)) 1991 LIBHB_CWRITE_N(hbthr, a, size); 1992 } 1993 1994 1995 /* ------------------------------------------------------- */ 1996 /* -------------- events to do with mutexes -------------- */ 1997 /* ------------------------------------------------------- */ 1998 1999 /* EXPOSITION only: by intercepting lock init events we can show the 2000 user where the lock was initialised, rather than only being able to 2001 show where it was first locked. Intercepting lock initialisations 2002 is not necessary for the basic operation of the race checker. */ 2003 static 2004 void evh__HG_PTHREAD_MUTEX_INIT_POST( ThreadId tid, 2005 void* mutex, Word mbRec ) 2006 { 2007 if (SHOW_EVENTS >= 1) 2008 VG_(printf)("evh__hg_PTHREAD_MUTEX_INIT_POST(ctid=%d, mbRec=%ld, %p)\n", 2009 (Int)tid, mbRec, (void*)mutex ); 2010 tl_assert(mbRec == 0 || mbRec == 1); 2011 map_locks_lookup_or_create( mbRec ? LK_mbRec : LK_nonRec, 2012 (Addr)mutex, tid ); 2013 if (HG_(clo_sanity_flags) & SCE_LOCKS) 2014 all__sanity_check("evh__hg_PTHREAD_MUTEX_INIT_POST"); 2015 } 2016 2017 static 2018 void evh__HG_PTHREAD_MUTEX_DESTROY_PRE( ThreadId tid, void* mutex, 2019 Bool mutex_is_init ) 2020 { 2021 Thread* thr; 2022 Lock* lk; 2023 if (SHOW_EVENTS >= 1) 2024 VG_(printf)("evh__hg_PTHREAD_MUTEX_DESTROY_PRE" 2025 "(ctid=%d, %p, isInit=%d)\n", 2026 (Int)tid, (void*)mutex, (Int)mutex_is_init ); 2027 2028 thr = map_threads_maybe_lookup( tid ); 2029 /* cannot fail - Thread* must already exist */ 2030 tl_assert( HG_(is_sane_Thread)(thr) ); 2031 2032 lk = map_locks_maybe_lookup( (Addr)mutex ); 2033 2034 if (lk == NULL && mutex_is_init) { 2035 /* We're destroying a mutex which we don't have any record of, 2036 and which appears to have the value PTHREAD_MUTEX_INITIALIZER. 2037 Assume it never got used, and so we don't need to do anything 2038 more. */ 2039 goto out; 2040 } 2041 2042 if (lk == NULL || (lk->kind != LK_nonRec && lk->kind != LK_mbRec)) { 2043 HG_(record_error_Misc)( 2044 thr, "pthread_mutex_destroy with invalid argument" ); 2045 } 2046 2047 if (lk) { 2048 tl_assert( HG_(is_sane_LockN)(lk) ); 2049 tl_assert( lk->guestaddr == (Addr)mutex ); 2050 if (lk->heldBy) { 2051 /* Basically act like we unlocked the lock */ 2052 HG_(record_error_Misc)( 2053 thr, "pthread_mutex_destroy of a locked mutex" ); 2054 /* remove lock from locksets of all owning threads */ 2055 remove_Lock_from_locksets_of_all_owning_Threads( lk ); 2056 VG_(deleteBag)( lk->heldBy ); 2057 lk->heldBy = NULL; 2058 lk->heldW = False; 2059 lk->acquired_at = NULL; 2060 } 2061 tl_assert( !lk->heldBy ); 2062 tl_assert( HG_(is_sane_LockN)(lk) ); 2063 2064 if (HG_(clo_track_lockorders)) 2065 laog__handle_one_lock_deletion(lk); 2066 map_locks_delete( lk->guestaddr ); 2067 del_LockN( lk ); 2068 } 2069 2070 out: 2071 if (HG_(clo_sanity_flags) & SCE_LOCKS) 2072 all__sanity_check("evh__hg_PTHREAD_MUTEX_DESTROY_PRE"); 2073 } 2074 2075 static void evh__HG_PTHREAD_MUTEX_LOCK_PRE ( ThreadId tid, 2076 void* mutex, Word isTryLock ) 2077 { 2078 /* Just check the mutex is sane; nothing else to do. */ 2079 // 'mutex' may be invalid - not checked by wrapper 2080 Thread* thr; 2081 Lock* lk; 2082 if (SHOW_EVENTS >= 1) 2083 VG_(printf)("evh__hg_PTHREAD_MUTEX_LOCK_PRE(ctid=%d, mutex=%p)\n", 2084 (Int)tid, (void*)mutex ); 2085 2086 tl_assert(isTryLock == 0 || isTryLock == 1); 2087 thr = map_threads_maybe_lookup( tid ); 2088 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2089 2090 lk = map_locks_maybe_lookup( (Addr)mutex ); 2091 2092 if (lk && (lk->kind == LK_rdwr)) { 2093 HG_(record_error_Misc)( thr, "pthread_mutex_lock with a " 2094 "pthread_rwlock_t* argument " ); 2095 } 2096 2097 if ( lk 2098 && isTryLock == 0 2099 && (lk->kind == LK_nonRec || lk->kind == LK_rdwr) 2100 && lk->heldBy 2101 && lk->heldW 2102 && VG_(elemBag)( lk->heldBy, (UWord)thr ) > 0 ) { 2103 /* uh, it's a non-recursive lock and we already w-hold it, and 2104 this is a real lock operation (not a speculative "tryLock" 2105 kind of thing). Duh. Deadlock coming up; but at least 2106 produce an error message. */ 2107 const HChar* errstr = "Attempt to re-lock a " 2108 "non-recursive lock I already hold"; 2109 const HChar* auxstr = "Lock was previously acquired"; 2110 if (lk->acquired_at) { 2111 HG_(record_error_Misc_w_aux)( thr, errstr, auxstr, lk->acquired_at ); 2112 } else { 2113 HG_(record_error_Misc)( thr, errstr ); 2114 } 2115 } 2116 } 2117 2118 static void evh__HG_PTHREAD_MUTEX_LOCK_POST ( ThreadId tid, void* mutex ) 2119 { 2120 // only called if the real library call succeeded - so mutex is sane 2121 Thread* thr; 2122 if (SHOW_EVENTS >= 1) 2123 VG_(printf)("evh__HG_PTHREAD_MUTEX_LOCK_POST(ctid=%d, mutex=%p)\n", 2124 (Int)tid, (void*)mutex ); 2125 2126 thr = map_threads_maybe_lookup( tid ); 2127 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2128 2129 evhH__post_thread_w_acquires_lock( 2130 thr, 2131 LK_mbRec, /* if not known, create new lock with this LockKind */ 2132 (Addr)mutex 2133 ); 2134 } 2135 2136 static void evh__HG_PTHREAD_MUTEX_UNLOCK_PRE ( ThreadId tid, void* mutex ) 2137 { 2138 // 'mutex' may be invalid - not checked by wrapper 2139 Thread* thr; 2140 if (SHOW_EVENTS >= 1) 2141 VG_(printf)("evh__HG_PTHREAD_MUTEX_UNLOCK_PRE(ctid=%d, mutex=%p)\n", 2142 (Int)tid, (void*)mutex ); 2143 2144 thr = map_threads_maybe_lookup( tid ); 2145 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2146 2147 evhH__pre_thread_releases_lock( thr, (Addr)mutex, False/*!isRDWR*/ ); 2148 } 2149 2150 static void evh__HG_PTHREAD_MUTEX_UNLOCK_POST ( ThreadId tid, void* mutex ) 2151 { 2152 // only called if the real library call succeeded - so mutex is sane 2153 Thread* thr; 2154 if (SHOW_EVENTS >= 1) 2155 VG_(printf)("evh__hg_PTHREAD_MUTEX_UNLOCK_POST(ctid=%d, mutex=%p)\n", 2156 (Int)tid, (void*)mutex ); 2157 thr = map_threads_maybe_lookup( tid ); 2158 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2159 2160 // anything we should do here? 2161 } 2162 2163 2164 /* ------------------------------------------------------- */ 2165 /* -------------- events to do with spinlocks ------------ */ 2166 /* ------------------------------------------------------- */ 2167 2168 /* All a bit of a kludge. Pretend we're really dealing with ordinary 2169 pthread_mutex_t's instead, for the most part. */ 2170 2171 static void evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( ThreadId tid, 2172 void* slock ) 2173 { 2174 Thread* thr; 2175 Lock* lk; 2176 /* In glibc's kludgey world, we're either initialising or unlocking 2177 it. Since this is the pre-routine, if it is locked, unlock it 2178 and take a dependence edge. Otherwise, do nothing. */ 2179 2180 if (SHOW_EVENTS >= 1) 2181 VG_(printf)("evh__hg_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE" 2182 "(ctid=%d, slock=%p)\n", 2183 (Int)tid, (void*)slock ); 2184 2185 thr = map_threads_maybe_lookup( tid ); 2186 /* cannot fail - Thread* must already exist */; 2187 tl_assert( HG_(is_sane_Thread)(thr) ); 2188 2189 lk = map_locks_maybe_lookup( (Addr)slock ); 2190 if (lk && lk->heldBy) { 2191 /* it's held. So do the normal pre-unlock actions, as copied 2192 from evh__HG_PTHREAD_MUTEX_UNLOCK_PRE. This stupidly 2193 duplicates the map_locks_maybe_lookup. */ 2194 evhH__pre_thread_releases_lock( thr, (Addr)slock, 2195 False/*!isRDWR*/ ); 2196 } 2197 } 2198 2199 static void evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( ThreadId tid, 2200 void* slock ) 2201 { 2202 Lock* lk; 2203 /* More kludgery. If the lock has never been seen before, do 2204 actions as per evh__HG_PTHREAD_MUTEX_INIT_POST. Else do 2205 nothing. */ 2206 2207 if (SHOW_EVENTS >= 1) 2208 VG_(printf)("evh__hg_PTHREAD_SPIN_INIT_OR_UNLOCK_POST" 2209 "(ctid=%d, slock=%p)\n", 2210 (Int)tid, (void*)slock ); 2211 2212 lk = map_locks_maybe_lookup( (Addr)slock ); 2213 if (!lk) { 2214 map_locks_lookup_or_create( LK_nonRec, (Addr)slock, tid ); 2215 } 2216 } 2217 2218 static void evh__HG_PTHREAD_SPIN_LOCK_PRE( ThreadId tid, 2219 void* slock, Word isTryLock ) 2220 { 2221 evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, slock, isTryLock ); 2222 } 2223 2224 static void evh__HG_PTHREAD_SPIN_LOCK_POST( ThreadId tid, 2225 void* slock ) 2226 { 2227 evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, slock ); 2228 } 2229 2230 static void evh__HG_PTHREAD_SPIN_DESTROY_PRE( ThreadId tid, 2231 void* slock ) 2232 { 2233 evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, slock, 0/*!isInit*/ ); 2234 } 2235 2236 2237 /* ----------------------------------------------------- */ 2238 /* --------------- events to do with CVs --------------- */ 2239 /* ----------------------------------------------------- */ 2240 2241 /* A mapping from CV to (the SO associated with it, plus some 2242 auxiliary data for error checking). When the CV is 2243 signalled/broadcasted upon, we do a 'send' into the SO, and when a 2244 wait on it completes, we do a 'recv' from the SO. This is believed 2245 to give the correct happens-before events arising from CV 2246 signallings/broadcasts. 2247 */ 2248 2249 /* .so is the SO for this CV. 2250 .mx_ga is the associated mutex, when .nWaiters > 0 2251 2252 POSIX says effectively that the first pthread_cond_{timed}wait call 2253 causes a dynamic binding between the CV and the mutex, and that 2254 lasts until such time as the waiter count falls to zero. Hence 2255 need to keep track of the number of waiters in order to do 2256 consistency tracking. */ 2257 typedef 2258 struct { 2259 SO* so; /* libhb-allocated SO */ 2260 void* mx_ga; /* addr of associated mutex, if any */ 2261 UWord nWaiters; /* # threads waiting on the CV */ 2262 } 2263 CVInfo; 2264 2265 2266 /* pthread_cond_t* -> CVInfo* */ 2267 static WordFM* map_cond_to_CVInfo = NULL; 2268 2269 static void map_cond_to_CVInfo_INIT ( void ) { 2270 if (UNLIKELY(map_cond_to_CVInfo == NULL)) { 2271 map_cond_to_CVInfo = VG_(newFM)( HG_(zalloc), 2272 "hg.mctCI.1", HG_(free), NULL ); 2273 } 2274 } 2275 2276 static CVInfo* map_cond_to_CVInfo_lookup_or_alloc ( void* cond ) { 2277 UWord key, val; 2278 map_cond_to_CVInfo_INIT(); 2279 if (VG_(lookupFM)( map_cond_to_CVInfo, &key, &val, (UWord)cond )) { 2280 tl_assert(key == (UWord)cond); 2281 return (CVInfo*)val; 2282 } else { 2283 SO* so = libhb_so_alloc(); 2284 CVInfo* cvi = HG_(zalloc)("hg.mctCloa.1", sizeof(CVInfo)); 2285 cvi->so = so; 2286 cvi->mx_ga = 0; 2287 VG_(addToFM)( map_cond_to_CVInfo, (UWord)cond, (UWord)cvi ); 2288 return cvi; 2289 } 2290 } 2291 2292 static CVInfo* map_cond_to_CVInfo_lookup_NO_alloc ( void* cond ) { 2293 UWord key, val; 2294 map_cond_to_CVInfo_INIT(); 2295 if (VG_(lookupFM)( map_cond_to_CVInfo, &key, &val, (UWord)cond )) { 2296 tl_assert(key == (UWord)cond); 2297 return (CVInfo*)val; 2298 } else { 2299 return NULL; 2300 } 2301 } 2302 2303 static void map_cond_to_CVInfo_delete ( ThreadId tid, 2304 void* cond, Bool cond_is_init ) { 2305 Thread* thr; 2306 UWord keyW, valW; 2307 2308 thr = map_threads_maybe_lookup( tid ); 2309 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2310 2311 map_cond_to_CVInfo_INIT(); 2312 if (VG_(lookupFM)( map_cond_to_CVInfo, &keyW, &valW, (UWord)cond )) { 2313 CVInfo* cvi = (CVInfo*)valW; 2314 tl_assert(keyW == (UWord)cond); 2315 tl_assert(cvi); 2316 tl_assert(cvi->so); 2317 if (cvi->nWaiters > 0) { 2318 HG_(record_error_Misc)( 2319 thr, "pthread_cond_destroy:" 2320 " destruction of condition variable being waited upon"); 2321 /* Destroying a cond var being waited upon outcome is EBUSY and 2322 variable is not destroyed. */ 2323 return; 2324 } 2325 if (!VG_(delFromFM)( map_cond_to_CVInfo, &keyW, &valW, (UWord)cond )) 2326 tl_assert(0); // cond var found above, and not here ??? 2327 libhb_so_dealloc(cvi->so); 2328 cvi->mx_ga = 0; 2329 HG_(free)(cvi); 2330 } else { 2331 /* We have no record of this CV. So complain about it 2332 .. except, don't bother to complain if it has exactly the 2333 value PTHREAD_COND_INITIALIZER, since it might be that the CV 2334 was initialised like that but never used. */ 2335 if (!cond_is_init) { 2336 HG_(record_error_Misc)( 2337 thr, "pthread_cond_destroy: destruction of unknown cond var"); 2338 } 2339 } 2340 } 2341 2342 static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond ) 2343 { 2344 /* 'tid' has signalled on 'cond'. As per the comment above, bind 2345 cond to a SO if it is not already so bound, and 'send' on the 2346 SO. This is later used by other thread(s) which successfully 2347 exit from a pthread_cond_wait on the same cv; then they 'recv' 2348 from the SO, thereby acquiring a dependency on this signalling 2349 event. */ 2350 Thread* thr; 2351 CVInfo* cvi; 2352 //Lock* lk; 2353 2354 if (SHOW_EVENTS >= 1) 2355 VG_(printf)("evh__HG_PTHREAD_COND_SIGNAL_PRE(ctid=%d, cond=%p)\n", 2356 (Int)tid, (void*)cond ); 2357 2358 thr = map_threads_maybe_lookup( tid ); 2359 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2360 2361 cvi = map_cond_to_CVInfo_lookup_or_alloc( cond ); 2362 tl_assert(cvi); 2363 tl_assert(cvi->so); 2364 2365 // error-if: mutex is bogus 2366 // error-if: mutex is not locked 2367 // Hmm. POSIX doesn't actually say that it's an error to call 2368 // pthread_cond_signal with the associated mutex being unlocked. 2369 // Although it does say that it should be "if consistent scheduling 2370 // is desired." For that reason, print "dubious" if the lock isn't 2371 // held by any thread. Skip the "dubious" if it is held by some 2372 // other thread; that sounds straight-out wrong. 2373 // 2374 // Anybody who writes code that signals on a CV without holding 2375 // the associated MX needs to be shipped off to a lunatic asylum 2376 // ASAP, even though POSIX doesn't actually declare such behaviour 2377 // illegal -- it makes code extremely difficult to understand/ 2378 // reason about. In particular it puts the signalling thread in 2379 // a situation where it is racing against the released waiter 2380 // as soon as the signalling is done, and so there needs to be 2381 // some auxiliary synchronisation mechanism in the program that 2382 // makes this safe -- or the race(s) need to be harmless, or 2383 // probably nonexistent. 2384 // 2385 if (1) { 2386 Lock* lk = NULL; 2387 if (cvi->mx_ga != 0) { 2388 lk = map_locks_maybe_lookup( (Addr)cvi->mx_ga ); 2389 } 2390 /* note: lk could be NULL. Be careful. */ 2391 if (lk) { 2392 if (lk->kind == LK_rdwr) { 2393 HG_(record_error_Misc)(thr, 2394 "pthread_cond_{signal,broadcast}: associated lock is a rwlock"); 2395 } 2396 if (lk->heldBy == NULL) { 2397 HG_(record_error_Misc)(thr, 2398 "pthread_cond_{signal,broadcast}: dubious: " 2399 "associated lock is not held by any thread"); 2400 } 2401 if (lk->heldBy != NULL && 0 == VG_(elemBag)(lk->heldBy, (UWord)thr)) { 2402 HG_(record_error_Misc)(thr, 2403 "pthread_cond_{signal,broadcast}: " 2404 "associated lock is not held by calling thread"); 2405 } 2406 } else { 2407 /* Couldn't even find the damn thing. */ 2408 // But actually .. that's not necessarily an error. We don't 2409 // know the (CV,MX) binding until a pthread_cond_wait or bcast 2410 // shows us what it is, and if that may not have happened yet. 2411 // So just keep quiet in this circumstance. 2412 //HG_(record_error_Misc)( thr, 2413 // "pthread_cond_{signal,broadcast}: " 2414 // "no or invalid mutex associated with cond"); 2415 } 2416 } 2417 2418 libhb_so_send( thr->hbthr, cvi->so, True/*strong_send*/ ); 2419 } 2420 2421 /* returns True if it reckons 'mutex' is valid and held by this 2422 thread, else False */ 2423 static Bool evh__HG_PTHREAD_COND_WAIT_PRE ( ThreadId tid, 2424 void* cond, void* mutex ) 2425 { 2426 Thread* thr; 2427 Lock* lk; 2428 Bool lk_valid = True; 2429 CVInfo* cvi; 2430 2431 if (SHOW_EVENTS >= 1) 2432 VG_(printf)("evh__hg_PTHREAD_COND_WAIT_PRE" 2433 "(ctid=%d, cond=%p, mutex=%p)\n", 2434 (Int)tid, (void*)cond, (void*)mutex ); 2435 2436 thr = map_threads_maybe_lookup( tid ); 2437 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2438 2439 lk = map_locks_maybe_lookup( (Addr)mutex ); 2440 2441 /* Check for stupid mutex arguments. There are various ways to be 2442 a bozo. Only complain once, though, even if more than one thing 2443 is wrong. */ 2444 if (lk == NULL) { 2445 lk_valid = False; 2446 HG_(record_error_Misc)( 2447 thr, 2448 "pthread_cond_{timed}wait called with invalid mutex" ); 2449 } else { 2450 tl_assert( HG_(is_sane_LockN)(lk) ); 2451 if (lk->kind == LK_rdwr) { 2452 lk_valid = False; 2453 HG_(record_error_Misc)( 2454 thr, "pthread_cond_{timed}wait called with mutex " 2455 "of type pthread_rwlock_t*" ); 2456 } else 2457 if (lk->heldBy == NULL) { 2458 lk_valid = False; 2459 HG_(record_error_Misc)( 2460 thr, "pthread_cond_{timed}wait called with un-held mutex"); 2461 } else 2462 if (lk->heldBy != NULL 2463 && VG_(elemBag)( lk->heldBy, (UWord)thr ) == 0) { 2464 lk_valid = False; 2465 HG_(record_error_Misc)( 2466 thr, "pthread_cond_{timed}wait called with mutex " 2467 "held by a different thread" ); 2468 } 2469 } 2470 2471 // error-if: cond is also associated with a different mutex 2472 cvi = map_cond_to_CVInfo_lookup_or_alloc(cond); 2473 tl_assert(cvi); 2474 tl_assert(cvi->so); 2475 if (cvi->nWaiters == 0) { 2476 /* form initial (CV,MX) binding */ 2477 cvi->mx_ga = mutex; 2478 } 2479 else /* check existing (CV,MX) binding */ 2480 if (cvi->mx_ga != mutex) { 2481 HG_(record_error_Misc)( 2482 thr, "pthread_cond_{timed}wait: cond is associated " 2483 "with a different mutex"); 2484 } 2485 cvi->nWaiters++; 2486 2487 return lk_valid; 2488 } 2489 2490 static void evh__HG_PTHREAD_COND_WAIT_POST ( ThreadId tid, 2491 void* cond, void* mutex, 2492 Bool timeout) 2493 { 2494 /* A pthread_cond_wait(cond, mutex) completed successfully. Find 2495 the SO for this cond, and 'recv' from it so as to acquire a 2496 dependency edge back to the signaller/broadcaster. */ 2497 Thread* thr; 2498 CVInfo* cvi; 2499 2500 if (SHOW_EVENTS >= 1) 2501 VG_(printf)("evh__HG_PTHREAD_COND_WAIT_POST" 2502 "(ctid=%d, cond=%p, mutex=%p)\n, timeout=%d", 2503 (Int)tid, (void*)cond, (void*)mutex, (Int)timeout ); 2504 2505 thr = map_threads_maybe_lookup( tid ); 2506 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2507 2508 // error-if: cond is also associated with a different mutex 2509 2510 cvi = map_cond_to_CVInfo_lookup_NO_alloc( cond ); 2511 if (!cvi) { 2512 /* This could be either a bug in helgrind or the guest application 2513 that did an error (e.g. cond var was destroyed by another thread. 2514 Let's assume helgrind is perfect ... 2515 Note that this is similar to drd behaviour. */ 2516 HG_(record_error_Misc)(thr, "condition variable has been destroyed while" 2517 " being waited upon"); 2518 return; 2519 } 2520 2521 tl_assert(cvi); 2522 tl_assert(cvi->so); 2523 tl_assert(cvi->nWaiters > 0); 2524 2525 if (!timeout && !libhb_so_everSent(cvi->so)) { 2526 /* Hmm. How can a wait on 'cond' succeed if nobody signalled 2527 it? If this happened it would surely be a bug in the threads 2528 library. Or one of those fabled "spurious wakeups". */ 2529 HG_(record_error_Misc)( thr, "Bug in libpthread: pthread_cond_wait " 2530 "succeeded" 2531 " without prior pthread_cond_post"); 2532 } 2533 2534 /* anyway, acquire a dependency on it. */ 2535 libhb_so_recv( thr->hbthr, cvi->so, True/*strong_recv*/ ); 2536 2537 cvi->nWaiters--; 2538 } 2539 2540 static void evh__HG_PTHREAD_COND_INIT_POST ( ThreadId tid, 2541 void* cond, void* cond_attr ) 2542 { 2543 CVInfo* cvi; 2544 2545 if (SHOW_EVENTS >= 1) 2546 VG_(printf)("evh__HG_PTHREAD_COND_INIT_POST" 2547 "(ctid=%d, cond=%p, cond_attr=%p)\n", 2548 (Int)tid, (void*)cond, (void*) cond_attr ); 2549 2550 cvi = map_cond_to_CVInfo_lookup_or_alloc( cond ); 2551 tl_assert (cvi); 2552 tl_assert (cvi->so); 2553 } 2554 2555 2556 static void evh__HG_PTHREAD_COND_DESTROY_PRE ( ThreadId tid, 2557 void* cond, Bool cond_is_init ) 2558 { 2559 /* Deal with destroy events. The only purpose is to free storage 2560 associated with the CV, so as to avoid any possible resource 2561 leaks. */ 2562 if (SHOW_EVENTS >= 1) 2563 VG_(printf)("evh__HG_PTHREAD_COND_DESTROY_PRE" 2564 "(ctid=%d, cond=%p, cond_is_init=%d)\n", 2565 (Int)tid, (void*)cond, (Int)cond_is_init ); 2566 2567 map_cond_to_CVInfo_delete( tid, cond, cond_is_init ); 2568 } 2569 2570 2571 /* ------------------------------------------------------- */ 2572 /* -------------- events to do with rwlocks -------------- */ 2573 /* ------------------------------------------------------- */ 2574 2575 /* EXPOSITION only */ 2576 static 2577 void evh__HG_PTHREAD_RWLOCK_INIT_POST( ThreadId tid, void* rwl ) 2578 { 2579 if (SHOW_EVENTS >= 1) 2580 VG_(printf)("evh__hg_PTHREAD_RWLOCK_INIT_POST(ctid=%d, %p)\n", 2581 (Int)tid, (void*)rwl ); 2582 map_locks_lookup_or_create( LK_rdwr, (Addr)rwl, tid ); 2583 if (HG_(clo_sanity_flags) & SCE_LOCKS) 2584 all__sanity_check("evh__hg_PTHREAD_RWLOCK_INIT_POST"); 2585 } 2586 2587 static 2588 void evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( ThreadId tid, void* rwl ) 2589 { 2590 Thread* thr; 2591 Lock* lk; 2592 if (SHOW_EVENTS >= 1) 2593 VG_(printf)("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE(ctid=%d, %p)\n", 2594 (Int)tid, (void*)rwl ); 2595 2596 thr = map_threads_maybe_lookup( tid ); 2597 /* cannot fail - Thread* must already exist */ 2598 tl_assert( HG_(is_sane_Thread)(thr) ); 2599 2600 lk = map_locks_maybe_lookup( (Addr)rwl ); 2601 2602 if (lk == NULL || lk->kind != LK_rdwr) { 2603 HG_(record_error_Misc)( 2604 thr, "pthread_rwlock_destroy with invalid argument" ); 2605 } 2606 2607 if (lk) { 2608 tl_assert( HG_(is_sane_LockN)(lk) ); 2609 tl_assert( lk->guestaddr == (Addr)rwl ); 2610 if (lk->heldBy) { 2611 /* Basically act like we unlocked the lock */ 2612 HG_(record_error_Misc)( 2613 thr, "pthread_rwlock_destroy of a locked mutex" ); 2614 /* remove lock from locksets of all owning threads */ 2615 remove_Lock_from_locksets_of_all_owning_Threads( lk ); 2616 VG_(deleteBag)( lk->heldBy ); 2617 lk->heldBy = NULL; 2618 lk->heldW = False; 2619 lk->acquired_at = NULL; 2620 } 2621 tl_assert( !lk->heldBy ); 2622 tl_assert( HG_(is_sane_LockN)(lk) ); 2623 2624 if (HG_(clo_track_lockorders)) 2625 laog__handle_one_lock_deletion(lk); 2626 map_locks_delete( lk->guestaddr ); 2627 del_LockN( lk ); 2628 } 2629 2630 if (HG_(clo_sanity_flags) & SCE_LOCKS) 2631 all__sanity_check("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE"); 2632 } 2633 2634 static 2635 void evh__HG_PTHREAD_RWLOCK_LOCK_PRE ( ThreadId tid, 2636 void* rwl, 2637 Word isW, Word isTryLock ) 2638 { 2639 /* Just check the rwl is sane; nothing else to do. */ 2640 // 'rwl' may be invalid - not checked by wrapper 2641 Thread* thr; 2642 Lock* lk; 2643 if (SHOW_EVENTS >= 1) 2644 VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_PRE(ctid=%d, isW=%d, %p)\n", 2645 (Int)tid, (Int)isW, (void*)rwl ); 2646 2647 tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */ 2648 tl_assert(isTryLock == 0 || isTryLock == 1); /* assured us by wrapper */ 2649 thr = map_threads_maybe_lookup( tid ); 2650 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2651 2652 lk = map_locks_maybe_lookup( (Addr)rwl ); 2653 if ( lk 2654 && (lk->kind == LK_nonRec || lk->kind == LK_mbRec) ) { 2655 /* Wrong kind of lock. Duh. */ 2656 HG_(record_error_Misc)( 2657 thr, "pthread_rwlock_{rd,rw}lock with a " 2658 "pthread_mutex_t* argument " ); 2659 } 2660 } 2661 2662 static 2663 void evh__HG_PTHREAD_RWLOCK_LOCK_POST ( ThreadId tid, void* rwl, Word isW ) 2664 { 2665 // only called if the real library call succeeded - so mutex is sane 2666 Thread* thr; 2667 if (SHOW_EVENTS >= 1) 2668 VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_POST(ctid=%d, isW=%d, %p)\n", 2669 (Int)tid, (Int)isW, (void*)rwl ); 2670 2671 tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */ 2672 thr = map_threads_maybe_lookup( tid ); 2673 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2674 2675 (isW ? evhH__post_thread_w_acquires_lock 2676 : evhH__post_thread_r_acquires_lock)( 2677 thr, 2678 LK_rdwr, /* if not known, create new lock with this LockKind */ 2679 (Addr)rwl 2680 ); 2681 } 2682 2683 static void evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE ( ThreadId tid, void* rwl ) 2684 { 2685 // 'rwl' may be invalid - not checked by wrapper 2686 Thread* thr; 2687 if (SHOW_EVENTS >= 1) 2688 VG_(printf)("evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ctid=%d, rwl=%p)\n", 2689 (Int)tid, (void*)rwl ); 2690 2691 thr = map_threads_maybe_lookup( tid ); 2692 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2693 2694 evhH__pre_thread_releases_lock( thr, (Addr)rwl, True/*isRDWR*/ ); 2695 } 2696 2697 static void evh__HG_PTHREAD_RWLOCK_UNLOCK_POST ( ThreadId tid, void* rwl ) 2698 { 2699 // only called if the real library call succeeded - so mutex is sane 2700 Thread* thr; 2701 if (SHOW_EVENTS >= 1) 2702 VG_(printf)("evh__hg_PTHREAD_RWLOCK_UNLOCK_POST(ctid=%d, rwl=%p)\n", 2703 (Int)tid, (void*)rwl ); 2704 thr = map_threads_maybe_lookup( tid ); 2705 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2706 2707 // anything we should do here? 2708 } 2709 2710 2711 /* ---------------------------------------------------------- */ 2712 /* -------------- events to do with semaphores -------------- */ 2713 /* ---------------------------------------------------------- */ 2714 2715 /* This is similar to but not identical to the handling for condition 2716 variables. */ 2717 2718 /* For each semaphore, we maintain a stack of SOs. When a 'post' 2719 operation is done on a semaphore (unlocking, essentially), a new SO 2720 is created for the posting thread, the posting thread does a strong 2721 send to it (which merely installs the posting thread's VC in the 2722 SO), and the SO is pushed on the semaphore's stack. 2723 2724 Later, when a (probably different) thread completes 'wait' on the 2725 semaphore, we pop a SO off the semaphore's stack (which should be 2726 nonempty), and do a strong recv from it. This mechanism creates 2727 dependencies between posters and waiters of the semaphore. 2728 2729 It may not be necessary to use a stack - perhaps a bag of SOs would 2730 do. But we do need to keep track of how many unused-up posts have 2731 happened for the semaphore. 2732 2733 Imagine T1 and T2 both post once on a semaphore S, and T3 waits 2734 twice on S. T3 cannot complete its waits without both T1 and T2 2735 posting. The above mechanism will ensure that T3 acquires 2736 dependencies on both T1 and T2. 2737 2738 When a semaphore is initialised with value N, we do as if we'd 2739 posted N times on the semaphore: basically create N SOs and do a 2740 strong send to all of then. This allows up to N waits on the 2741 semaphore to acquire a dependency on the initialisation point, 2742 which AFAICS is the correct behaviour. 2743 2744 We don't emit an error for DESTROY_PRE on a semaphore we don't know 2745 about. We should. 2746 */ 2747 2748 /* sem_t* -> XArray* SO* */ 2749 static WordFM* map_sem_to_SO_stack = NULL; 2750 2751 static void map_sem_to_SO_stack_INIT ( void ) { 2752 if (map_sem_to_SO_stack == NULL) { 2753 map_sem_to_SO_stack = VG_(newFM)( HG_(zalloc), "hg.mstSs.1", 2754 HG_(free), NULL ); 2755 } 2756 } 2757 2758 static void push_SO_for_sem ( void* sem, SO* so ) { 2759 UWord keyW; 2760 XArray* xa; 2761 tl_assert(so); 2762 map_sem_to_SO_stack_INIT(); 2763 if (VG_(lookupFM)( map_sem_to_SO_stack, 2764 &keyW, (UWord*)&xa, (UWord)sem )) { 2765 tl_assert(keyW == (UWord)sem); 2766 tl_assert(xa); 2767 VG_(addToXA)( xa, &so ); 2768 } else { 2769 xa = VG_(newXA)( HG_(zalloc), "hg.pSfs.1", HG_(free), sizeof(SO*) ); 2770 VG_(addToXA)( xa, &so ); 2771 VG_(addToFM)( map_sem_to_SO_stack, (UWord)sem, (UWord)xa ); 2772 } 2773 } 2774 2775 static SO* mb_pop_SO_for_sem ( void* sem ) { 2776 UWord keyW; 2777 XArray* xa; 2778 SO* so; 2779 map_sem_to_SO_stack_INIT(); 2780 if (VG_(lookupFM)( map_sem_to_SO_stack, 2781 &keyW, (UWord*)&xa, (UWord)sem )) { 2782 /* xa is the stack for this semaphore. */ 2783 Word sz; 2784 tl_assert(keyW == (UWord)sem); 2785 sz = VG_(sizeXA)( xa ); 2786 tl_assert(sz >= 0); 2787 if (sz == 0) 2788 return NULL; /* odd, the stack is empty */ 2789 so = *(SO**)VG_(indexXA)( xa, sz-1 ); 2790 tl_assert(so); 2791 VG_(dropTailXA)( xa, 1 ); 2792 return so; 2793 } else { 2794 /* hmm, that's odd. No stack for this semaphore. */ 2795 return NULL; 2796 } 2797 } 2798 2799 static void evh__HG_POSIX_SEM_DESTROY_PRE ( ThreadId tid, void* sem ) 2800 { 2801 UWord keyW, valW; 2802 SO* so; 2803 2804 if (SHOW_EVENTS >= 1) 2805 VG_(printf)("evh__HG_POSIX_SEM_DESTROY_PRE(ctid=%d, sem=%p)\n", 2806 (Int)tid, (void*)sem ); 2807 2808 map_sem_to_SO_stack_INIT(); 2809 2810 /* Empty out the semaphore's SO stack. This way of doing it is 2811 stupid, but at least it's easy. */ 2812 while (1) { 2813 so = mb_pop_SO_for_sem( sem ); 2814 if (!so) break; 2815 libhb_so_dealloc(so); 2816 } 2817 2818 if (VG_(delFromFM)( map_sem_to_SO_stack, &keyW, &valW, (UWord)sem )) { 2819 XArray* xa = (XArray*)valW; 2820 tl_assert(keyW == (UWord)sem); 2821 tl_assert(xa); 2822 tl_assert(VG_(sizeXA)(xa) == 0); /* preceding loop just emptied it */ 2823 VG_(deleteXA)(xa); 2824 } 2825 } 2826 2827 static 2828 void evh__HG_POSIX_SEM_INIT_POST ( ThreadId tid, void* sem, UWord value ) 2829 { 2830 SO* so; 2831 Thread* thr; 2832 2833 if (SHOW_EVENTS >= 1) 2834 VG_(printf)("evh__HG_POSIX_SEM_INIT_POST(ctid=%d, sem=%p, value=%lu)\n", 2835 (Int)tid, (void*)sem, value ); 2836 2837 thr = map_threads_maybe_lookup( tid ); 2838 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2839 2840 /* Empty out the semaphore's SO stack. This way of doing it is 2841 stupid, but at least it's easy. */ 2842 while (1) { 2843 so = mb_pop_SO_for_sem( sem ); 2844 if (!so) break; 2845 libhb_so_dealloc(so); 2846 } 2847 2848 /* If we don't do this check, the following while loop runs us out 2849 of memory for stupid initial values of 'value'. */ 2850 if (value > 10000) { 2851 HG_(record_error_Misc)( 2852 thr, "sem_init: initial value exceeds 10000; using 10000" ); 2853 value = 10000; 2854 } 2855 2856 /* Now create 'valid' new SOs for the thread, do a strong send to 2857 each of them, and push them all on the stack. */ 2858 for (; value > 0; value--) { 2859 Thr* hbthr = thr->hbthr; 2860 tl_assert(hbthr); 2861 2862 so = libhb_so_alloc(); 2863 libhb_so_send( hbthr, so, True/*strong send*/ ); 2864 push_SO_for_sem( sem, so ); 2865 } 2866 } 2867 2868 static void evh__HG_POSIX_SEM_POST_PRE ( ThreadId tid, void* sem ) 2869 { 2870 /* 'tid' has posted on 'sem'. Create a new SO, do a strong send to 2871 it (iow, write our VC into it, then tick ours), and push the SO 2872 on on a stack of SOs associated with 'sem'. This is later used 2873 by other thread(s) which successfully exit from a sem_wait on 2874 the same sem; by doing a strong recv from SOs popped of the 2875 stack, they acquire dependencies on the posting thread 2876 segment(s). */ 2877 2878 Thread* thr; 2879 SO* so; 2880 Thr* hbthr; 2881 2882 if (SHOW_EVENTS >= 1) 2883 VG_(printf)("evh__HG_POSIX_SEM_POST_PRE(ctid=%d, sem=%p)\n", 2884 (Int)tid, (void*)sem ); 2885 2886 thr = map_threads_maybe_lookup( tid ); 2887 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2888 2889 // error-if: sem is bogus 2890 2891 hbthr = thr->hbthr; 2892 tl_assert(hbthr); 2893 2894 so = libhb_so_alloc(); 2895 libhb_so_send( hbthr, so, True/*strong send*/ ); 2896 push_SO_for_sem( sem, so ); 2897 } 2898 2899 static void evh__HG_POSIX_SEM_WAIT_POST ( ThreadId tid, void* sem ) 2900 { 2901 /* A sem_wait(sem) completed successfully. Pop the posting-SO for 2902 the 'sem' from this semaphore's SO-stack, and do a strong recv 2903 from it. This creates a dependency back to one of the post-ers 2904 for the semaphore. */ 2905 2906 Thread* thr; 2907 SO* so; 2908 Thr* hbthr; 2909 2910 if (SHOW_EVENTS >= 1) 2911 VG_(printf)("evh__HG_POSIX_SEM_WAIT_POST(ctid=%d, sem=%p)\n", 2912 (Int)tid, (void*)sem ); 2913 2914 thr = map_threads_maybe_lookup( tid ); 2915 tl_assert(thr); /* cannot fail - Thread* must already exist */ 2916 2917 // error-if: sem is bogus 2918 2919 so = mb_pop_SO_for_sem( sem ); 2920 2921 if (so) { 2922 hbthr = thr->hbthr; 2923 tl_assert(hbthr); 2924 2925 libhb_so_recv( hbthr, so, True/*strong recv*/ ); 2926 libhb_so_dealloc(so); 2927 } else { 2928 /* Hmm. How can a wait on 'sem' succeed if nobody posted to it? 2929 If this happened it would surely be a bug in the threads 2930 library. */ 2931 HG_(record_error_Misc)( 2932 thr, "Bug in libpthread: sem_wait succeeded on" 2933 " semaphore without prior sem_post"); 2934 } 2935 } 2936 2937 2938 /* -------------------------------------------------------- */ 2939 /* -------------- events to do with barriers -------------- */ 2940 /* -------------------------------------------------------- */ 2941 2942 typedef 2943 struct { 2944 Bool initted; /* has it yet been initted by guest? */ 2945 Bool resizable; /* is resizing allowed? */ 2946 UWord size; /* declared size */ 2947 XArray* waiting; /* XA of Thread*. # present is 0 .. .size */ 2948 } 2949 Bar; 2950 2951 static Bar* new_Bar ( void ) { 2952 Bar* bar = HG_(zalloc)( "hg.nB.1 (new_Bar)", sizeof(Bar) ); 2953 /* all fields are zero */ 2954 tl_assert(bar->initted == False); 2955 return bar; 2956 } 2957 2958 static void delete_Bar ( Bar* bar ) { 2959 tl_assert(bar); 2960 if (bar->waiting) 2961 VG_(deleteXA)(bar->waiting); 2962 HG_(free)(bar); 2963 } 2964 2965 /* A mapping which stores auxiliary data for barriers. */ 2966 2967 /* pthread_barrier_t* -> Bar* */ 2968 static WordFM* map_barrier_to_Bar = NULL; 2969 2970 static void map_barrier_to_Bar_INIT ( void ) { 2971 if (UNLIKELY(map_barrier_to_Bar == NULL)) { 2972 map_barrier_to_Bar = VG_(newFM)( HG_(zalloc), 2973 "hg.mbtBI.1", HG_(free), NULL ); 2974 } 2975 } 2976 2977 static Bar* map_barrier_to_Bar_lookup_or_alloc ( void* barrier ) { 2978 UWord key, val; 2979 map_barrier_to_Bar_INIT(); 2980 if (VG_(lookupFM)( map_barrier_to_Bar, &key, &val, (UWord)barrier )) { 2981 tl_assert(key == (UWord)barrier); 2982 return (Bar*)val; 2983 } else { 2984 Bar* bar = new_Bar(); 2985 VG_(addToFM)( map_barrier_to_Bar, (UWord)barrier, (UWord)bar ); 2986 return bar; 2987 } 2988 } 2989 2990 static void map_barrier_to_Bar_delete ( void* barrier ) { 2991 UWord keyW, valW; 2992 map_barrier_to_Bar_INIT(); 2993 if (VG_(delFromFM)( map_barrier_to_Bar, &keyW, &valW, (UWord)barrier )) { 2994 Bar* bar = (Bar*)valW; 2995 tl_assert(keyW == (UWord)barrier); 2996 delete_Bar(bar); 2997 } 2998 } 2999 3000 3001 static void evh__HG_PTHREAD_BARRIER_INIT_PRE ( ThreadId tid, 3002 void* barrier, 3003 UWord count, 3004 UWord resizable ) 3005 { 3006 Thread* thr; 3007 Bar* bar; 3008 3009 if (SHOW_EVENTS >= 1) 3010 VG_(printf)("evh__HG_PTHREAD_BARRIER_INIT_PRE" 3011 "(tid=%d, barrier=%p, count=%lu, resizable=%lu)\n", 3012 (Int)tid, (void*)barrier, count, resizable ); 3013 3014 thr = map_threads_maybe_lookup( tid ); 3015 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3016 3017 if (count == 0) { 3018 HG_(record_error_Misc)( 3019 thr, "pthread_barrier_init: 'count' argument is zero" 3020 ); 3021 } 3022 3023 if (resizable != 0 && resizable != 1) { 3024 HG_(record_error_Misc)( 3025 thr, "pthread_barrier_init: invalid 'resizable' argument" 3026 ); 3027 } 3028 3029 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 3030 tl_assert(bar); 3031 3032 if (bar->initted) { 3033 HG_(record_error_Misc)( 3034 thr, "pthread_barrier_init: barrier is already initialised" 3035 ); 3036 } 3037 3038 if (bar->waiting && VG_(sizeXA)(bar->waiting) > 0) { 3039 tl_assert(bar->initted); 3040 HG_(record_error_Misc)( 3041 thr, "pthread_barrier_init: threads are waiting at barrier" 3042 ); 3043 VG_(dropTailXA)(bar->waiting, VG_(sizeXA)(bar->waiting)); 3044 } 3045 if (!bar->waiting) { 3046 bar->waiting = VG_(newXA)( HG_(zalloc), "hg.eHPBIP.1", HG_(free), 3047 sizeof(Thread*) ); 3048 } 3049 3050 tl_assert(VG_(sizeXA)(bar->waiting) == 0); 3051 bar->initted = True; 3052 bar->resizable = resizable == 1 ? True : False; 3053 bar->size = count; 3054 } 3055 3056 3057 static void evh__HG_PTHREAD_BARRIER_DESTROY_PRE ( ThreadId tid, 3058 void* barrier ) 3059 { 3060 Thread* thr; 3061 Bar* bar; 3062 3063 /* Deal with destroy events. The only purpose is to free storage 3064 associated with the barrier, so as to avoid any possible 3065 resource leaks. */ 3066 if (SHOW_EVENTS >= 1) 3067 VG_(printf)("evh__HG_PTHREAD_BARRIER_DESTROY_PRE" 3068 "(tid=%d, barrier=%p)\n", 3069 (Int)tid, (void*)barrier ); 3070 3071 thr = map_threads_maybe_lookup( tid ); 3072 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3073 3074 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 3075 tl_assert(bar); 3076 3077 if (!bar->initted) { 3078 HG_(record_error_Misc)( 3079 thr, "pthread_barrier_destroy: barrier was never initialised" 3080 ); 3081 } 3082 3083 if (bar->initted && bar->waiting && VG_(sizeXA)(bar->waiting) > 0) { 3084 HG_(record_error_Misc)( 3085 thr, "pthread_barrier_destroy: threads are waiting at barrier" 3086 ); 3087 } 3088 3089 /* Maybe we shouldn't do this; just let it persist, so that when it 3090 is reinitialised we don't need to do any dynamic memory 3091 allocation? The downside is a potentially unlimited space leak, 3092 if the client creates (in turn) a large number of barriers all 3093 at different locations. Note that if we do later move to the 3094 don't-delete-it scheme, we need to mark the barrier as 3095 uninitialised again since otherwise a later _init call will 3096 elicit a duplicate-init error. */ 3097 map_barrier_to_Bar_delete( barrier ); 3098 } 3099 3100 3101 /* All the threads have arrived. Now do the Interesting Bit. Get a 3102 new synchronisation object and do a weak send to it from all the 3103 participating threads. This makes its vector clocks be the join of 3104 all the individual threads' vector clocks. Then do a strong 3105 receive from it back to all threads, so that their VCs are a copy 3106 of it (hence are all equal to the join of their original VCs.) */ 3107 static void do_barrier_cross_sync_and_empty ( Bar* bar ) 3108 { 3109 /* XXX check bar->waiting has no duplicates */ 3110 UWord i; 3111 SO* so = libhb_so_alloc(); 3112 3113 tl_assert(bar->waiting); 3114 tl_assert(VG_(sizeXA)(bar->waiting) == bar->size); 3115 3116 /* compute the join ... */ 3117 for (i = 0; i < bar->size; i++) { 3118 Thread* t = *(Thread**)VG_(indexXA)(bar->waiting, i); 3119 Thr* hbthr = t->hbthr; 3120 libhb_so_send( hbthr, so, False/*weak send*/ ); 3121 } 3122 /* ... and distribute to all threads */ 3123 for (i = 0; i < bar->size; i++) { 3124 Thread* t = *(Thread**)VG_(indexXA)(bar->waiting, i); 3125 Thr* hbthr = t->hbthr; 3126 libhb_so_recv( hbthr, so, True/*strong recv*/ ); 3127 } 3128 3129 /* finally, we must empty out the waiting vector */ 3130 VG_(dropTailXA)(bar->waiting, VG_(sizeXA)(bar->waiting)); 3131 3132 /* and we don't need this any more. Perhaps a stack-allocated 3133 SO would be better? */ 3134 libhb_so_dealloc(so); 3135 } 3136 3137 3138 static void evh__HG_PTHREAD_BARRIER_WAIT_PRE ( ThreadId tid, 3139 void* barrier ) 3140 { 3141 /* This function gets called after a client thread calls 3142 pthread_barrier_wait but before it arrives at the real 3143 pthread_barrier_wait. 3144 3145 Why is the following correct? It's a bit subtle. 3146 3147 If this is not the last thread arriving at the barrier, we simply 3148 note its presence and return. Because valgrind (at least as of 3149 Nov 08) is single threaded, we are guaranteed safe from any race 3150 conditions when in this function -- no other client threads are 3151 running. 3152 3153 If this is the last thread, then we are again the only running 3154 thread. All the other threads will have either arrived at the 3155 real pthread_barrier_wait or are on their way to it, but in any 3156 case are guaranteed not to be able to move past it, because this 3157 thread is currently in this function and so has not yet arrived 3158 at the real pthread_barrier_wait. That means that: 3159 3160 1. While we are in this function, none of the other threads 3161 waiting at the barrier can move past it. 3162 3163 2. When this function returns (and simulated execution resumes), 3164 this thread and all other waiting threads will be able to move 3165 past the real barrier. 3166 3167 Because of this, it is now safe to update the vector clocks of 3168 all threads, to represent the fact that they all arrived at the 3169 barrier and have all moved on. There is no danger of any 3170 complications to do with some threads leaving the barrier and 3171 racing back round to the front, whilst others are still leaving 3172 (which is the primary source of complication in correct handling/ 3173 implementation of barriers). That can't happen because we update 3174 here our data structures so as to indicate that the threads have 3175 passed the barrier, even though, as per (2) above, they are 3176 guaranteed not to pass the barrier until we return. 3177 3178 This relies crucially on Valgrind being single threaded. If that 3179 changes, this will need to be reconsidered. 3180 */ 3181 Thread* thr; 3182 Bar* bar; 3183 UWord present; 3184 3185 if (SHOW_EVENTS >= 1) 3186 VG_(printf)("evh__HG_PTHREAD_BARRIER_WAIT_PRE" 3187 "(tid=%d, barrier=%p)\n", 3188 (Int)tid, (void*)barrier ); 3189 3190 thr = map_threads_maybe_lookup( tid ); 3191 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3192 3193 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 3194 tl_assert(bar); 3195 3196 if (!bar->initted) { 3197 HG_(record_error_Misc)( 3198 thr, "pthread_barrier_wait: barrier is uninitialised" 3199 ); 3200 return; /* client is broken .. avoid assertions below */ 3201 } 3202 3203 /* guaranteed by _INIT_PRE above */ 3204 tl_assert(bar->size > 0); 3205 tl_assert(bar->waiting); 3206 3207 VG_(addToXA)( bar->waiting, &thr ); 3208 3209 /* guaranteed by this function */ 3210 present = VG_(sizeXA)(bar->waiting); 3211 tl_assert(present > 0 && present <= bar->size); 3212 3213 if (present < bar->size) 3214 return; 3215 3216 do_barrier_cross_sync_and_empty(bar); 3217 } 3218 3219 3220 static void evh__HG_PTHREAD_BARRIER_RESIZE_PRE ( ThreadId tid, 3221 void* barrier, 3222 UWord newcount ) 3223 { 3224 Thread* thr; 3225 Bar* bar; 3226 UWord present; 3227 3228 if (SHOW_EVENTS >= 1) 3229 VG_(printf)("evh__HG_PTHREAD_BARRIER_RESIZE_PRE" 3230 "(tid=%d, barrier=%p, newcount=%lu)\n", 3231 (Int)tid, (void*)barrier, newcount ); 3232 3233 thr = map_threads_maybe_lookup( tid ); 3234 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3235 3236 bar = map_barrier_to_Bar_lookup_or_alloc(barrier); 3237 tl_assert(bar); 3238 3239 if (!bar->initted) { 3240 HG_(record_error_Misc)( 3241 thr, "pthread_barrier_resize: barrier is uninitialised" 3242 ); 3243 return; /* client is broken .. avoid assertions below */ 3244 } 3245 3246 if (!bar->resizable) { 3247 HG_(record_error_Misc)( 3248 thr, "pthread_barrier_resize: barrier is may not be resized" 3249 ); 3250 return; /* client is broken .. avoid assertions below */ 3251 } 3252 3253 if (newcount == 0) { 3254 HG_(record_error_Misc)( 3255 thr, "pthread_barrier_resize: 'newcount' argument is zero" 3256 ); 3257 return; /* client is broken .. avoid assertions below */ 3258 } 3259 3260 /* guaranteed by _INIT_PRE above */ 3261 tl_assert(bar->size > 0); 3262 tl_assert(bar->waiting); 3263 /* Guaranteed by this fn */ 3264 tl_assert(newcount > 0); 3265 3266 if (newcount >= bar->size) { 3267 /* Increasing the capacity. There's no possibility of threads 3268 moving on from the barrier in this situation, so just note 3269 the fact and do nothing more. */ 3270 bar->size = newcount; 3271 } else { 3272 /* Decreasing the capacity. If we decrease it to be equal or 3273 below the number of waiting threads, they will now move past 3274 the barrier, so need to mess with dep edges in the same way 3275 as if the barrier had filled up normally. */ 3276 present = VG_(sizeXA)(bar->waiting); 3277 tl_assert(present >= 0 && present <= bar->size); 3278 if (newcount <= present) { 3279 bar->size = present; /* keep the cross_sync call happy */ 3280 do_barrier_cross_sync_and_empty(bar); 3281 } 3282 bar->size = newcount; 3283 } 3284 } 3285 3286 3287 /* ----------------------------------------------------- */ 3288 /* ----- events to do with user-specified HB edges ----- */ 3289 /* ----------------------------------------------------- */ 3290 3291 /* A mapping from arbitrary UWord tag to the SO associated with it. 3292 The UWord tags are meaningless to us, interpreted only by the 3293 user. */ 3294 3295 3296 3297 /* UWord -> SO* */ 3298 static WordFM* map_usertag_to_SO = NULL; 3299 3300 static void map_usertag_to_SO_INIT ( void ) { 3301 if (UNLIKELY(map_usertag_to_SO == NULL)) { 3302 map_usertag_to_SO = VG_(newFM)( HG_(zalloc), 3303 "hg.mutS.1", HG_(free), NULL ); 3304 } 3305 } 3306 3307 static SO* map_usertag_to_SO_lookup_or_alloc ( UWord usertag ) { 3308 UWord key, val; 3309 map_usertag_to_SO_INIT(); 3310 if (VG_(lookupFM)( map_usertag_to_SO, &key, &val, usertag )) { 3311 tl_assert(key == (UWord)usertag); 3312 return (SO*)val; 3313 } else { 3314 SO* so = libhb_so_alloc(); 3315 VG_(addToFM)( map_usertag_to_SO, usertag, (UWord)so ); 3316 return so; 3317 } 3318 } 3319 3320 static void map_usertag_to_SO_delete ( UWord usertag ) { 3321 UWord keyW, valW; 3322 map_usertag_to_SO_INIT(); 3323 if (VG_(delFromFM)( map_usertag_to_SO, &keyW, &valW, usertag )) { 3324 SO* so = (SO*)valW; 3325 tl_assert(keyW == usertag); 3326 tl_assert(so); 3327 libhb_so_dealloc(so); 3328 } 3329 } 3330 3331 3332 static 3333 void evh__HG_USERSO_SEND_PRE ( ThreadId tid, UWord usertag ) 3334 { 3335 /* TID is just about to notionally sent a message on a notional 3336 abstract synchronisation object whose identity is given by 3337 USERTAG. Bind USERTAG to a real SO if it is not already so 3338 bound, and do a 'weak send' on the SO. This joins the vector 3339 clocks from this thread into any vector clocks already present 3340 in the SO. The resulting SO vector clocks are later used by 3341 other thread(s) which successfully 'receive' from the SO, 3342 thereby acquiring a dependency on all the events that have 3343 previously signalled on this SO. */ 3344 Thread* thr; 3345 SO* so; 3346 3347 if (SHOW_EVENTS >= 1) 3348 VG_(printf)("evh__HG_USERSO_SEND_PRE(ctid=%d, usertag=%#lx)\n", 3349 (Int)tid, usertag ); 3350 3351 thr = map_threads_maybe_lookup( tid ); 3352 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3353 3354 so = map_usertag_to_SO_lookup_or_alloc( usertag ); 3355 tl_assert(so); 3356 3357 libhb_so_send( thr->hbthr, so, False/*!strong_send*/ ); 3358 } 3359 3360 static 3361 void evh__HG_USERSO_RECV_POST ( ThreadId tid, UWord usertag ) 3362 { 3363 /* TID has just notionally received a message from a notional 3364 abstract synchronisation object whose identity is given by 3365 USERTAG. Bind USERTAG to a real SO if it is not already so 3366 bound. If the SO has at some point in the past been 'sent' on, 3367 to a 'strong receive' on it, thereby acquiring a dependency on 3368 the sender. */ 3369 Thread* thr; 3370 SO* so; 3371 3372 if (SHOW_EVENTS >= 1) 3373 VG_(printf)("evh__HG_USERSO_RECV_POST(ctid=%d, usertag=%#lx)\n", 3374 (Int)tid, usertag ); 3375 3376 thr = map_threads_maybe_lookup( tid ); 3377 tl_assert(thr); /* cannot fail - Thread* must already exist */ 3378 3379 so = map_usertag_to_SO_lookup_or_alloc( usertag ); 3380 tl_assert(so); 3381 3382 /* Acquire a dependency on it. If the SO has never so far been 3383 sent on, then libhb_so_recv will do nothing. So we're safe 3384 regardless of SO's history. */ 3385 libhb_so_recv( thr->hbthr, so, True/*strong_recv*/ ); 3386 } 3387 3388 static 3389 void evh__HG_USERSO_FORGET_ALL ( ThreadId tid, UWord usertag ) 3390 { 3391 /* TID declares that any happens-before edges notionally stored in 3392 USERTAG can be deleted. If (as would normally be the case) a 3393 SO is associated with USERTAG, then the association is removed 3394 and all resources associated with SO are freed. Importantly, 3395 that frees up any VTSs stored in SO. */ 3396 if (SHOW_EVENTS >= 1) 3397 VG_(printf)("evh__HG_USERSO_FORGET_ALL(ctid=%d, usertag=%#lx)\n", 3398 (Int)tid, usertag ); 3399 3400 map_usertag_to_SO_delete( usertag ); 3401 } 3402 3403 3404 #if defined(VGO_solaris) 3405 /* ----------------------------------------------------- */ 3406 /* --- events to do with bind guard/clear intercepts --- */ 3407 /* ----------------------------------------------------- */ 3408 3409 static 3410 void evh__HG_RTLD_BIND_GUARD(ThreadId tid, Int flags) 3411 { 3412 if (SHOW_EVENTS >= 1) 3413 VG_(printf)("evh__HG_RTLD_BIND_GUARD" 3414 "(tid=%d, flags=%d)\n", 3415 (Int)tid, flags); 3416 3417 Thread *thr = map_threads_maybe_lookup(tid); 3418 tl_assert(thr != NULL); 3419 3420 Int bindflag = (flags & VKI_THR_FLG_RTLD); 3421 if ((bindflag & thr->bind_guard_flag) == 0) { 3422 thr->bind_guard_flag |= bindflag; 3423 HG_(thread_enter_synchr)(thr); 3424 /* Misuse pthread_create_nesting_level for ignoring mutex activity. */ 3425 HG_(thread_enter_pthread_create)(thr); 3426 } 3427 } 3428 3429 static 3430 void evh__HG_RTLD_BIND_CLEAR(ThreadId tid, Int flags) 3431 { 3432 if (SHOW_EVENTS >= 1) 3433 VG_(printf)("evh__HG_RTLD_BIND_CLEAR" 3434 "(tid=%d, flags=%d)\n", 3435 (Int)tid, flags); 3436 3437 Thread *thr = map_threads_maybe_lookup(tid); 3438 tl_assert(thr != NULL); 3439 3440 Int bindflag = (flags & VKI_THR_FLG_RTLD); 3441 if ((thr->bind_guard_flag & bindflag) != 0) { 3442 thr->bind_guard_flag &= ~bindflag; 3443 HG_(thread_leave_synchr)(thr); 3444 HG_(thread_leave_pthread_create)(thr); 3445 } 3446 } 3447 #endif /* VGO_solaris */ 3448 3449 3450 /*--------------------------------------------------------------*/ 3451 /*--- Lock acquisition order monitoring ---*/ 3452 /*--------------------------------------------------------------*/ 3453 3454 /* FIXME: here are some optimisations still to do in 3455 laog__pre_thread_acquires_lock. 3456 3457 The graph is structured so that if L1 --*--> L2 then L1 must be 3458 acquired before L2. 3459 3460 The common case is that some thread T holds (eg) L1 L2 and L3 and 3461 is repeatedly acquiring and releasing Ln, and there is no ordering 3462 error in what it is doing. Hence it repeatedly: 3463 3464 (1) searches laog to see if Ln --*--> {L1,L2,L3}, which always 3465 produces the answer No (because there is no error). 3466 3467 (2) adds edges {L1,L2,L3} --> Ln to laog, which are already present 3468 (because they already got added the first time T acquired Ln). 3469 3470 Hence cache these two events: 3471 3472 (1) Cache result of the query from last time. Invalidate the cache 3473 any time any edges are added to or deleted from laog. 3474 3475 (2) Cache these add-edge requests and ignore them if said edges 3476 have already been added to laog. Invalidate the cache any time 3477 any edges are deleted from laog. 3478 */ 3479 3480 typedef 3481 struct { 3482 WordSetID inns; /* in univ_laog */ 3483 WordSetID outs; /* in univ_laog */ 3484 } 3485 LAOGLinks; 3486 3487 /* lock order acquisition graph */ 3488 static WordFM* laog = NULL; /* WordFM Lock* LAOGLinks* */ 3489 3490 /* EXPOSITION ONLY: for each edge in 'laog', record the two places 3491 where that edge was created, so that we can show the user later if 3492 we need to. */ 3493 typedef 3494 struct { 3495 Addr src_ga; /* Lock guest addresses for */ 3496 Addr dst_ga; /* src/dst of the edge */ 3497 ExeContext* src_ec; /* And corresponding places where that */ 3498 ExeContext* dst_ec; /* ordering was established */ 3499 } 3500 LAOGLinkExposition; 3501 3502 static Word cmp_LAOGLinkExposition ( UWord llx1W, UWord llx2W ) { 3503 /* Compare LAOGLinkExposition*s by (src_ga,dst_ga) field pair. */ 3504 LAOGLinkExposition* llx1 = (LAOGLinkExposition*)llx1W; 3505 LAOGLinkExposition* llx2 = (LAOGLinkExposition*)llx2W; 3506 if (llx1->src_ga < llx2->src_ga) return -1; 3507 if (llx1->src_ga > llx2->src_ga) return 1; 3508 if (llx1->dst_ga < llx2->dst_ga) return -1; 3509 if (llx1->dst_ga > llx2->dst_ga) return 1; 3510 return 0; 3511 } 3512 3513 static WordFM* laog_exposition = NULL; /* WordFM LAOGLinkExposition* NULL */ 3514 /* end EXPOSITION ONLY */ 3515 3516 3517 __attribute__((noinline)) 3518 static void laog__init ( void ) 3519 { 3520 tl_assert(!laog); 3521 tl_assert(!laog_exposition); 3522 tl_assert(HG_(clo_track_lockorders)); 3523 3524 laog = VG_(newFM)( HG_(zalloc), "hg.laog__init.1", 3525 HG_(free), NULL/*unboxedcmp*/ ); 3526 3527 laog_exposition = VG_(newFM)( HG_(zalloc), "hg.laog__init.2", HG_(free), 3528 cmp_LAOGLinkExposition ); 3529 } 3530 3531 static void laog__show ( const HChar* who ) { 3532 UWord i, ws_size; 3533 UWord* ws_words; 3534 Lock* me; 3535 LAOGLinks* links; 3536 VG_(printf)("laog (requested by %s) {\n", who); 3537 VG_(initIterFM)( laog ); 3538 me = NULL; 3539 links = NULL; 3540 while (VG_(nextIterFM)( laog, (UWord*)&me, 3541 (UWord*)&links )) { 3542 tl_assert(me); 3543 tl_assert(links); 3544 VG_(printf)(" node %p:\n", me); 3545 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns ); 3546 for (i = 0; i < ws_size; i++) 3547 VG_(printf)(" inn %#lx\n", ws_words[i] ); 3548 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs ); 3549 for (i = 0; i < ws_size; i++) 3550 VG_(printf)(" out %#lx\n", ws_words[i] ); 3551 me = NULL; 3552 links = NULL; 3553 } 3554 VG_(doneIterFM)( laog ); 3555 VG_(printf)("}\n"); 3556 } 3557 3558 static void univ_laog_do_GC ( void ) { 3559 Word i; 3560 LAOGLinks* links; 3561 Word seen = 0; 3562 Int prev_next_gc_univ_laog = next_gc_univ_laog; 3563 const UWord univ_laog_cardinality = HG_(cardinalityWSU)( univ_laog); 3564 3565 Bool *univ_laog_seen = HG_(zalloc) ( "hg.gc_univ_laog.1", 3566 (Int) univ_laog_cardinality 3567 * sizeof(Bool) ); 3568 // univ_laog_seen[*] set to 0 (False) by zalloc. 3569 3570 VG_(initIterFM)( laog ); 3571 links = NULL; 3572 while (VG_(nextIterFM)( laog, NULL, (UWord*)&links )) { 3573 tl_assert(links); 3574 tl_assert(links->inns >= 0 && links->inns < univ_laog_cardinality); 3575 univ_laog_seen[links->inns] = True; 3576 tl_assert(links->outs >= 0 && links->outs < univ_laog_cardinality); 3577 univ_laog_seen[links->outs] = True; 3578 links = NULL; 3579 } 3580 VG_(doneIterFM)( laog ); 3581 3582 for (i = 0; i < (Int)univ_laog_cardinality; i++) { 3583 if (univ_laog_seen[i]) 3584 seen++; 3585 else 3586 HG_(dieWS) ( univ_laog, (WordSet)i ); 3587 } 3588 3589 HG_(free) (univ_laog_seen); 3590 3591 // We need to decide the value of the next_gc. 3592 // 3 solutions were looked at: 3593 // Sol 1: garbage collect at seen * 2 3594 // This solution was a lot slower, probably because we both do a lot of 3595 // garbage collection and do not keep long enough laog WV that will become 3596 // useful again very soon. 3597 // Sol 2: garbage collect at a percentage increase of the current cardinality 3598 // (with a min increase of 1) 3599 // Trials on a small test program with 1%, 5% and 10% increase was done. 3600 // 1% is slightly faster than 5%, which is slightly slower than 10%. 3601 // However, on a big application, this caused the memory to be exhausted, 3602 // as even a 1% increase of size at each gc becomes a lot, when many gc 3603 // are done. 3604 // Sol 3: always garbage collect at current cardinality + 1. 3605 // This solution was the fastest of the 3 solutions, and caused no memory 3606 // exhaustion in the big application. 3607 // 3608 // With regards to cost introduced by gc: on the t2t perf test (doing only 3609 // lock/unlock operations), t2t 50 10 2 was about 25% faster than the 3610 // version with garbage collection. With t2t 50 20 2, my machine started 3611 // to page out, and so the garbage collected version was much faster. 3612 // On smaller lock sets (e.g. t2t 20 5 2, giving about 100 locks), the 3613 // difference performance is insignificant (~ 0.1 s). 3614 // Of course, it might be that real life programs are not well represented 3615 // by t2t. 3616 3617 // If ever we want to have a more sophisticated control 3618 // (e.g. clo options to control the percentage increase or fixed increased), 3619 // we should do it here, eg. 3620 // next_gc_univ_laog = prev_next_gc_univ_laog + VG_(clo_laog_gc_fixed); 3621 // Currently, we just hard-code the solution 3 above. 3622 next_gc_univ_laog = prev_next_gc_univ_laog + 1; 3623 3624 if (VG_(clo_stats)) 3625 VG_(message) 3626 (Vg_DebugMsg, 3627 "univ_laog_do_GC cardinality entered %d exit %d next gc at %d\n", 3628 (Int)univ_laog_cardinality, (Int)seen, next_gc_univ_laog); 3629 } 3630 3631 3632 __attribute__((noinline)) 3633 static void laog__add_edge ( Lock* src, Lock* dst ) { 3634 UWord keyW; 3635 LAOGLinks* links; 3636 Bool presentF, presentR; 3637 if (0) VG_(printf)("laog__add_edge %p %p\n", src, dst); 3638 3639 /* Take the opportunity to sanity check the graph. Record in 3640 presentF if there is already a src->dst mapping in this node's 3641 forwards links, and presentR if there is already a src->dst 3642 mapping in this node's backwards links. They should agree! 3643 Also, we need to know whether the edge was already present so as 3644 to decide whether or not to update the link details mapping. We 3645 can compute presentF and presentR essentially for free, so may 3646 as well do this always. */ 3647 presentF = presentR = False; 3648 3649 /* Update the out edges for src */ 3650 keyW = 0; 3651 links = NULL; 3652 if (VG_(lookupFM)( laog, &keyW, (UWord*)&links, (UWord)src )) { 3653 WordSetID outs_new; 3654 tl_assert(links); 3655 tl_assert(keyW == (UWord)src); 3656 outs_new = HG_(addToWS)( univ_laog, links->outs, (UWord)dst ); 3657 presentF = outs_new == links->outs; 3658 links->outs = outs_new; 3659 } else { 3660 links = HG_(zalloc)("hg.lae.1", sizeof(LAOGLinks)); 3661 links->inns = HG_(emptyWS)( univ_laog ); 3662 links->outs = HG_(singletonWS)( univ_laog, (UWord)dst ); 3663 VG_(addToFM)( laog, (UWord)src, (UWord)links ); 3664 } 3665 /* Update the in edges for dst */ 3666 keyW = 0; 3667 links = NULL; 3668 if (VG_(lookupFM)( laog, &keyW, (UWord*)&links, (UWord)dst )) { 3669 WordSetID inns_new; 3670 tl_assert(links); 3671 tl_assert(keyW == (UWord)dst); 3672 inns_new = HG_(addToWS)( univ_laog, links->inns, (UWord)src ); 3673 presentR = inns_new == links->inns; 3674 links->inns = inns_new; 3675 } else { 3676 links = HG_(zalloc)("hg.lae.2", sizeof(LAOGLinks)); 3677 links->inns = HG_(singletonWS)( univ_laog, (UWord)src ); 3678 links->outs = HG_(emptyWS)( univ_laog ); 3679 VG_(addToFM)( laog, (UWord)dst, (UWord)links ); 3680 } 3681 3682 tl_assert( (presentF && presentR) || (!presentF && !presentR) ); 3683 3684 if (!presentF && src->acquired_at && dst->acquired_at) { 3685 LAOGLinkExposition expo; 3686 /* If this edge is entering the graph, and we have acquired_at 3687 information for both src and dst, record those acquisition 3688 points. Hence, if there is later a violation of this 3689 ordering, we can show the user the two places in which the 3690 required src-dst ordering was previously established. */ 3691 if (0) VG_(printf)("acquire edge %#lx %#lx\n", 3692 src->guestaddr, dst->guestaddr); 3693 expo.src_ga = src->guestaddr; 3694 expo.dst_ga = dst->guestaddr; 3695 expo.src_ec = NULL; 3696 expo.dst_ec = NULL; 3697 tl_assert(laog_exposition); 3698 if (VG_(lookupFM)( laog_exposition, NULL, NULL, (UWord)&expo )) { 3699 /* we already have it; do nothing */ 3700 } else { 3701 LAOGLinkExposition* expo2 = HG_(zalloc)("hg.lae.3", 3702 sizeof(LAOGLinkExposition)); 3703 expo2->src_ga = src->guestaddr; 3704 expo2->dst_ga = dst->guestaddr; 3705 expo2->src_ec = src->acquired_at; 3706 expo2->dst_ec = dst->acquired_at; 3707 VG_(addToFM)( laog_exposition, (UWord)expo2, (UWord)NULL ); 3708 } 3709 } 3710 3711 if (HG_(cardinalityWSU) (univ_laog) >= next_gc_univ_laog) 3712 univ_laog_do_GC(); 3713 } 3714 3715 __attribute__((noinline)) 3716 static void laog__del_edge ( Lock* src, Lock* dst ) { 3717 UWord keyW; 3718 LAOGLinks* links; 3719 if (0) VG_(printf)("laog__del_edge enter %p %p\n", src, dst); 3720 /* Update the out edges for src */ 3721 keyW = 0; 3722 links = NULL; 3723 if (VG_(lookupFM)( laog, &keyW, (UWord*)&links, (UWord)src )) { 3724 tl_assert(links); 3725 tl_assert(keyW == (UWord)src); 3726 links->outs = HG_(delFromWS)( univ_laog, links->outs, (UWord)dst ); 3727 } 3728 /* Update the in edges for dst */ 3729 keyW = 0; 3730 links = NULL; 3731 if (VG_(lookupFM)( laog, &keyW, (UWord*)&links, (UWord)dst )) { 3732 tl_assert(links); 3733 tl_assert(keyW == (UWord)dst); 3734 links->inns = HG_(delFromWS)( univ_laog, links->inns, (UWord)src ); 3735 } 3736 3737 /* Remove the exposition of src,dst (if present) */ 3738 { 3739 LAOGLinkExposition *fm_expo; 3740 3741 LAOGLinkExposition expo; 3742 expo.src_ga = src->guestaddr; 3743 expo.dst_ga = dst->guestaddr; 3744 expo.src_ec = NULL; 3745 expo.dst_ec = NULL; 3746 3747 if (VG_(delFromFM) (laog_exposition, 3748 (UWord*)&fm_expo, NULL, (UWord)&expo )) { 3749 HG_(free) (fm_expo); 3750 } 3751 } 3752 3753 /* deleting edges can increase nr of of WS so check for gc. */ 3754 if (HG_(cardinalityWSU) (univ_laog) >= next_gc_univ_laog) 3755 univ_laog_do_GC(); 3756 if (0) VG_(printf)("laog__del_edge exit\n"); 3757 } 3758 3759 __attribute__((noinline)) 3760 static WordSetID /* in univ_laog */ laog__succs ( Lock* lk ) { 3761 UWord keyW; 3762 LAOGLinks* links; 3763 keyW = 0; 3764 links = NULL; 3765 if (VG_(lookupFM)( laog, &keyW, (UWord*)&links, (UWord)lk )) { 3766 tl_assert(links); 3767 tl_assert(keyW == (UWord)lk); 3768 return links->outs; 3769 } else { 3770 return HG_(emptyWS)( univ_laog ); 3771 } 3772 } 3773 3774 __attribute__((noinline)) 3775 static WordSetID /* in univ_laog */ laog__preds ( Lock* lk ) { 3776 UWord keyW; 3777 LAOGLinks* links; 3778 keyW = 0; 3779 links = NULL; 3780 if (VG_(lookupFM)( laog, &keyW, (UWord*)&links, (UWord)lk )) { 3781 tl_assert(links); 3782 tl_assert(keyW == (UWord)lk); 3783 return links->inns; 3784 } else { 3785 return HG_(emptyWS)( univ_laog ); 3786 } 3787 } 3788 3789 __attribute__((noinline)) 3790 static void laog__sanity_check ( const HChar* who ) { 3791 UWord i, ws_size; 3792 UWord* ws_words; 3793 Lock* me; 3794 LAOGLinks* links; 3795 VG_(initIterFM)( laog ); 3796 me = NULL; 3797 links = NULL; 3798 if (0) VG_(printf)("laog sanity check\n"); 3799 while (VG_(nextIterFM)( laog, (UWord*)&me, 3800 (UWord*)&links )) { 3801 tl_assert(me); 3802 tl_assert(links); 3803 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns ); 3804 for (i = 0; i < ws_size; i++) { 3805 if ( ! HG_(elemWS)( univ_laog, 3806 laog__succs( (Lock*)ws_words[i] ), 3807 (UWord)me )) 3808 goto bad; 3809 } 3810 HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs ); 3811 for (i = 0; i < ws_size; i++) { 3812 if ( ! HG_(elemWS)( univ_laog, 3813 laog__preds( (Lock*)ws_words[i] ), 3814 (UWord)me )) 3815 goto bad; 3816 } 3817 me = NULL; 3818 links = NULL; 3819 } 3820 VG_(doneIterFM)( laog ); 3821 return; 3822 3823 bad: 3824 VG_(printf)("laog__sanity_check(%s) FAILED\n", who); 3825 laog__show(who); 3826 tl_assert(0); 3827 } 3828 3829 /* If there is a path in laog from 'src' to any of the elements in 3830 'dst', return an arbitrarily chosen element of 'dst' reachable from 3831 'src'. If no path exist from 'src' to any element in 'dst', return 3832 NULL. */ 3833 __attribute__((noinline)) 3834 static 3835 Lock* laog__do_dfs_from_to ( Lock* src, WordSetID dsts /* univ_lsets */ ) 3836 { 3837 Lock* ret; 3838 Word ssz; 3839 XArray* stack; /* of Lock* */ 3840 WordFM* visited; /* Lock* -> void, iow, Set(Lock*) */ 3841 Lock* here; 3842 WordSetID succs; 3843 UWord succs_size, i; 3844 UWord* succs_words; 3845 //laog__sanity_check(); 3846 3847 /* If the destination set is empty, we can never get there from 3848 'src' :-), so don't bother to try */ 3849 if (HG_(isEmptyWS)( univ_lsets, dsts )) 3850 return NULL; 3851 3852 ret = NULL; 3853 stack = VG_(newXA)( HG_(zalloc), "hg.lddft.1", HG_(free), sizeof(Lock*) ); 3854 visited = VG_(newFM)( HG_(zalloc), "hg.lddft.2", HG_(free), NULL/*unboxedcmp*/ ); 3855 3856 (void) VG_(addToXA)( stack, &src ); 3857 3858 while (True) { 3859 3860 ssz = VG_(sizeXA)( stack ); 3861 3862 if (ssz == 0) { ret = NULL; break; } 3863 3864 here = *(Lock**) VG_(indexXA)( stack, ssz-1 ); 3865 VG_(dropTailXA)( stack, 1 ); 3866 3867 if (HG_(elemWS)( univ_lsets, dsts, (UWord)here )) { ret = here; break; } 3868 3869 if (VG_(lookupFM)( visited, NULL, NULL, (UWord)here )) 3870 continue; 3871 3872 VG_(addToFM)( visited, (UWord)here, 0 ); 3873 3874 succs = laog__succs( here ); 3875 HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs ); 3876 for (i = 0; i < succs_size; i++) 3877 (void) VG_(addToXA)( stack, &succs_words[i] ); 3878 } 3879 3880 VG_(deleteFM)( visited, NULL, NULL ); 3881 VG_(deleteXA)( stack ); 3882 return ret; 3883 } 3884 3885 3886 /* Thread 'thr' is acquiring 'lk'. Check for inconsistent ordering 3887 between 'lk' and the locks already held by 'thr' and issue a 3888 complaint if so. Also, update the ordering graph appropriately. 3889 */ 3890 __attribute__((noinline)) 3891 static void laog__pre_thread_acquires_lock ( 3892 Thread* thr, /* NB: BEFORE lock is added */ 3893 Lock* lk 3894 ) 3895 { 3896 UWord* ls_words; 3897 UWord ls_size, i; 3898 Lock* other; 3899 3900 /* It may be that 'thr' already holds 'lk' and is recursively 3901 relocking in. In this case we just ignore the call. */ 3902 /* NB: univ_lsets really is correct here */ 3903 if (HG_(elemWS)( univ_lsets, thr->locksetA, (UWord)lk )) 3904 return; 3905 3906 /* First, the check. Complain if there is any path in laog from lk 3907 to any of the locks already held by thr, since if any such path 3908 existed, it would mean that previously lk was acquired before 3909 (rather than after, as we are doing here) at least one of those 3910 locks. 3911 */ 3912 other = laog__do_dfs_from_to(lk, thr->locksetA); 3913 if (other) { 3914 LAOGLinkExposition key, *found; 3915 /* So we managed to find a path lk --*--> other in the graph, 3916 which implies that 'lk' should have been acquired before 3917 'other' but is in fact being acquired afterwards. We present 3918 the lk/other arguments to record_error_LockOrder in the order 3919 in which they should have been acquired. */ 3920 /* Go look in the laog_exposition mapping, to find the allocation 3921 points for this edge, so we can show the user. */ 3922 key.src_ga = lk->guestaddr; 3923 key.dst_ga = other->guestaddr; 3924 key.src_ec = NULL; 3925 key.dst_ec = NULL; 3926 found = NULL; 3927 if (VG_(lookupFM)( laog_exposition, 3928 (UWord*)&found, NULL, (UWord)&key )) { 3929 tl_assert(found != &key); 3930 tl_assert(found->src_ga == key.src_ga); 3931 tl_assert(found->dst_ga == key.dst_ga); 3932 tl_assert(found->src_ec); 3933 tl_assert(found->dst_ec); 3934 HG_(record_error_LockOrder)( 3935 thr, lk, other, 3936 found->src_ec, found->dst_ec, other->acquired_at ); 3937 } else { 3938 /* Hmm. This can't happen (can it?) */ 3939 /* Yes, it can happen: see tests/tc14_laog_dinphils. 3940 Imagine we have 3 philosophers A B C, and the forks 3941 between them: 3942 3943 C 3944 3945 fCA fBC 3946 3947 A fAB B 3948 3949 Let's have the following actions: 3950 A takes fCA,fAB 3951 A releases fCA,fAB 3952 B takes fAB,fBC 3953 B releases fAB,fBC 3954 C takes fBC,fCA 3955 C releases fBC,fCA 3956 3957 Helgrind will report a lock order error when C takes fCA. 3958 Effectively, we have a deadlock if the following 3959 sequence is done: 3960 A takes fCA 3961 B takes fAB 3962 C takes fBC 3963 3964 The error reported is: 3965 Observed (incorrect) order fBC followed by fCA 3966 but the stack traces that have established the required order 3967 are not given. 3968 3969 This is because there is no pair (fCA, fBC) in laog exposition : 3970 the laog_exposition records all pairs of locks between a new lock 3971 taken by a thread and all the already taken locks. 3972 So, there is no laog_exposition (fCA, fBC) as no thread ever 3973 first locked fCA followed by fBC. 3974 3975 In other words, when the deadlock cycle involves more than 3976 two locks, then helgrind does not report the sequence of 3977 operations that created the cycle. 3978 3979 However, we can report the current stack trace (where 3980 lk is being taken), and the stack trace where other was acquired: 3981 Effectively, the variable 'other' contains a lock currently 3982 held by this thread, with its 'acquired_at'. */ 3983 3984 HG_(record_error_LockOrder)( 3985 thr, lk, other, 3986 NULL, NULL, other->acquired_at ); 3987 } 3988 } 3989 3990 /* Second, add to laog the pairs 3991 (old, lk) | old <- locks already held by thr 3992 Since both old and lk are currently held by thr, their acquired_at 3993 fields must be non-NULL. 3994 */ 3995 tl_assert(lk->acquired_at); 3996 HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, thr->locksetA ); 3997 for (i = 0; i < ls_size; i++) { 3998 Lock* old = (Lock*)ls_words[i]; 3999 tl_assert(old->acquired_at); 4000 laog__add_edge( old, lk ); 4001 } 4002 4003 /* Why "except_Locks" ? We're here because a lock is being 4004 acquired by a thread, and we're in an inconsistent state here. 4005 See the call points in evhH__post_thread_{r,w}_acquires_lock. 4006 When called in this inconsistent state, locks__sanity_check duly 4007 barfs. */ 4008 if (HG_(clo_sanity_flags) & SCE_LAOG) 4009 all_except_Locks__sanity_check("laog__pre_thread_acquires_lock-post"); 4010 } 4011 4012 /* Allocates a duplicate of words. Caller must HG_(free) the result. */ 4013 static UWord* UWordV_dup(UWord* words, Word words_size) 4014 { 4015 UInt i; 4016 4017 if (words_size == 0) 4018 return NULL; 4019 4020 UWord *dup = HG_(zalloc) ("hg.dup.1", (SizeT) words_size * sizeof(UWord)); 4021 4022 for (i = 0; i < words_size; i++) 4023 dup[i] = words[i]; 4024 4025 return dup; 4026 } 4027 4028 /* Delete from 'laog' any pair mentioning a lock in locksToDelete */ 4029 4030 __attribute__((noinline)) 4031 static void laog__handle_one_lock_deletion ( Lock* lk ) 4032 { 4033 WordSetID preds, succs; 4034 UWord preds_size, succs_size, i, j; 4035 UWord *preds_words, *succs_words; 4036 4037 preds = laog__preds( lk ); 4038 succs = laog__succs( lk ); 4039 4040 // We need to duplicate the payload, as these can be garbage collected 4041 // during the del/add operations below. 4042 HG_(getPayloadWS)( &preds_words, &preds_size, univ_laog, preds ); 4043 preds_words = UWordV_dup(preds_words, preds_size); 4044 4045 HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs ); 4046 succs_words = UWordV_dup(succs_words, succs_size); 4047 4048 for (i = 0; i < preds_size; i++) 4049 laog__del_edge( (Lock*)preds_words[i], lk ); 4050 4051 for (j = 0; j < succs_size; j++) 4052 laog__del_edge( lk, (Lock*)succs_words[j] ); 4053 4054 for (i = 0; i < preds_size; i++) { 4055 for (j = 0; j < succs_size; j++) { 4056 if (preds_words[i] != succs_words[j]) { 4057 /* This can pass unlocked locks to laog__add_edge, since 4058 we're deleting stuff. So their acquired_at fields may 4059 be NULL. */ 4060 laog__add_edge( (Lock*)preds_words[i], (Lock*)succs_words[j] ); 4061 } 4062 } 4063 } 4064 4065 if (preds_words) 4066 HG_(free) (preds_words); 4067 if (succs_words) 4068 HG_(free) (succs_words); 4069 4070 // Remove lk information from laog links FM 4071 { 4072 LAOGLinks *links; 4073 Lock* linked_lk; 4074 4075 if (VG_(delFromFM) (laog, 4076 (UWord*)&linked_lk, (UWord*)&links, (UWord)lk)) { 4077 tl_assert (linked_lk == lk); 4078 HG_(free) (links); 4079 } 4080 } 4081 /* FIXME ??? What about removing lock lk data from EXPOSITION ??? */ 4082 } 4083 4084 //__attribute__((noinline)) 4085 //static void laog__handle_lock_deletions ( 4086 // WordSetID /* in univ_laog */ locksToDelete 4087 // ) 4088 //{ 4089 // Word i, ws_size; 4090 // UWord* ws_words; 4091 // 4092 // 4093 // HG_(getPayloadWS)( &ws_words, &ws_size, univ_lsets, locksToDelete ); 4094 // UWordV_dup call needed here ... 4095 // for (i = 0; i < ws_size; i++) 4096 // laog__handle_one_lock_deletion( (Lock*)ws_words[i] ); 4097 // 4098 // if (HG_(clo_sanity_flags) & SCE_LAOG) 4099 // all__sanity_check("laog__handle_lock_deletions-post"); 4100 //} 4101 4102 4103 /*--------------------------------------------------------------*/ 4104 /*--- Malloc/free replacements ---*/ 4105 /*--------------------------------------------------------------*/ 4106 4107 typedef 4108 struct { 4109 void* next; /* required by m_hashtable */ 4110 Addr payload; /* ptr to actual block */ 4111 SizeT szB; /* size requested */ 4112 ExeContext* where; /* where it was allocated */ 4113 Thread* thr; /* allocating thread */ 4114 } 4115 MallocMeta; 4116 4117 /* A hash table of MallocMetas, used to track malloc'd blocks 4118 (obviously). */ 4119 static VgHashTable *hg_mallocmeta_table = NULL; 4120 4121 /* MallocMeta are small elements. We use a pool to avoid 4122 the overhead of malloc for each MallocMeta. */ 4123 static PoolAlloc *MallocMeta_poolalloc = NULL; 4124 4125 static MallocMeta* new_MallocMeta ( void ) { 4126 MallocMeta* md = VG_(allocEltPA) (MallocMeta_poolalloc); 4127 VG_(memset)(md, 0, sizeof(MallocMeta)); 4128 return md; 4129 } 4130 static void delete_MallocMeta ( MallocMeta* md ) { 4131 VG_(freeEltPA)(MallocMeta_poolalloc, md); 4132 } 4133 4134 4135 /* Allocate a client block and set up the metadata for it. */ 4136 4137 static 4138 void* handle_alloc ( ThreadId tid, 4139 SizeT szB, SizeT alignB, Bool is_zeroed ) 4140 { 4141 Addr p; 4142 MallocMeta* md; 4143 4144 tl_assert( ((SSizeT)szB) >= 0 ); 4145 p = (Addr)VG_(cli_malloc)(alignB, szB); 4146 if (!p) { 4147 return NULL; 4148 } 4149 if (is_zeroed) 4150 VG_(memset)((void*)p, 0, szB); 4151 4152 /* Note that map_threads_lookup must succeed (cannot assert), since 4153 memory can only be allocated by currently alive threads, hence 4154 they must have an entry in map_threads. */ 4155 md = new_MallocMeta(); 4156 md->payload = p; 4157 md->szB = szB; 4158 md->where = VG_(record_ExeContext)( tid, 0 ); 4159 md->thr = map_threads_lookup( tid ); 4160 4161 VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md ); 4162 if (UNLIKELY(VG_(clo_xtree_memory) == Vg_XTMemory_Full)) 4163 VG_(XTMemory_Full_alloc)(md->szB, md->where); 4164 4165 /* Tell the lower level memory wranglers. */ 4166 evh__new_mem_heap( p, szB, is_zeroed ); 4167 4168 return (void*)p; 4169 } 4170 4171 /* Re the checks for less-than-zero (also in hg_cli__realloc below): 4172 Cast to a signed type to catch any unexpectedly negative args. 4173 We're assuming here that the size asked for is not greater than 4174 2^31 bytes (for 32-bit platforms) or 2^63 bytes (for 64-bit 4175 platforms). */ 4176 static void* hg_cli__malloc ( ThreadId tid, SizeT n ) { 4177 if (((SSizeT)n) < 0) return NULL; 4178 return handle_alloc ( tid, n, VG_(clo_alignment), 4179 /*is_zeroed*/False ); 4180 } 4181 static void* hg_cli____builtin_new ( ThreadId tid, SizeT n ) { 4182 if (((SSizeT)n) < 0) return NULL; 4183 return handle_alloc ( tid, n, VG_(clo_alignment), 4184 /*is_zeroed*/False ); 4185 } 4186 static void* hg_cli____builtin_vec_new ( ThreadId tid, SizeT n ) { 4187 if (((SSizeT)n) < 0) return NULL; 4188 return handle_alloc ( tid, n, VG_(clo_alignment), 4189 /*is_zeroed*/False ); 4190 } 4191 static void* hg_cli__memalign ( ThreadId tid, SizeT align, SizeT n ) { 4192 if (((SSizeT)n) < 0) return NULL; 4193 return handle_alloc ( tid, n, align, 4194 /*is_zeroed*/False ); 4195 } 4196 static void* hg_cli__calloc ( ThreadId tid, SizeT nmemb, SizeT size1 ) { 4197 if ( ((SSizeT)nmemb) < 0 || ((SSizeT)size1) < 0 ) return NULL; 4198 return handle_alloc ( tid, nmemb*size1, VG_(clo_alignment), 4199 /*is_zeroed*/True ); 4200 } 4201 4202 4203 /* Free a client block, including getting rid of the relevant 4204 metadata. */ 4205 4206 static void handle_free ( ThreadId tid, void* p ) 4207 { 4208 MallocMeta *md, *old_md; 4209 SizeT szB; 4210 4211 /* First see if we can find the metadata for 'p'. */ 4212 md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p ); 4213 if (!md) 4214 return; /* apparently freeing a bogus address. Oh well. */ 4215 4216 tl_assert(md->payload == (Addr)p); 4217 szB = md->szB; 4218 if (UNLIKELY(VG_(clo_xtree_memory) == Vg_XTMemory_Full)) { 4219 ExeContext* ec_free = VG_(record_ExeContext)( tid, 0 ); 4220 VG_(XTMemory_Full_free)(md->szB, md->where, ec_free); 4221 } 4222 4223 /* Nuke the metadata block */ 4224 old_md = (MallocMeta*) 4225 VG_(HT_remove)( hg_mallocmeta_table, (UWord)p ); 4226 tl_assert(old_md); /* it must be present - we just found it */ 4227 tl_assert(old_md == md); 4228 tl_assert(old_md->payload == (Addr)p); 4229 4230 VG_(cli_free)((void*)old_md->payload); 4231 delete_MallocMeta(old_md); 4232 4233 /* Tell the lower level memory wranglers. */ 4234 evh__die_mem_heap( (Addr)p, szB ); 4235 } 4236 4237 static void hg_cli__free ( ThreadId tid, void* p ) { 4238 handle_free(tid, p); 4239 } 4240 static void hg_cli____builtin_delete ( ThreadId tid, void* p ) { 4241 handle_free(tid, p); 4242 } 4243 static void hg_cli____builtin_vec_delete ( ThreadId tid, void* p ) { 4244 handle_free(tid, p); 4245 } 4246 4247 4248 static void* hg_cli__realloc ( ThreadId tid, void* payloadV, SizeT new_size ) 4249 { 4250 MallocMeta *md, *md_new, *md_tmp; 4251 SizeT i; 4252 4253 Addr payload = (Addr)payloadV; 4254 4255 if (((SSizeT)new_size) < 0) return NULL; 4256 4257 md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)payload ); 4258 if (!md) 4259 return NULL; /* apparently realloc-ing a bogus address. Oh well. */ 4260 4261 tl_assert(md->payload == payload); 4262 4263 if (md->szB == new_size) { 4264 /* size unchanged */ 4265 md->where = VG_(record_ExeContext)(tid, 0); 4266 return payloadV; 4267 } 4268 4269 if (md->szB > new_size) { 4270 /* new size is smaller */ 4271 md->szB = new_size; 4272 md->where = VG_(record_ExeContext)(tid, 0); 4273 evh__die_mem_heap( md->payload + new_size, md->szB - new_size ); 4274 return payloadV; 4275 } 4276 4277 /* else */ { 4278 /* new size is bigger */ 4279 Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size); 4280 4281 /* First half kept and copied, second half new */ 4282 // FIXME: shouldn't we use a copier which implements the 4283 // memory state machine? 4284 evh__copy_mem( payload, p_new, md->szB ); 4285 evh__new_mem_heap ( p_new + md->szB, new_size - md->szB, 4286 /*inited*/False ); 4287 /* FIXME: can anything funny happen here? specifically, if the 4288 old range contained a lock, then die_mem_heap will complain. 4289 Is that the correct behaviour? Not sure. */ 4290 evh__die_mem_heap( payload, md->szB ); 4291 4292 /* Copy from old to new */ 4293 for (i = 0; i < md->szB; i++) 4294 ((UChar*)p_new)[i] = ((UChar*)payload)[i]; 4295 4296 /* Because the metadata hash table is index by payload address, 4297 we have to get rid of the old hash table entry and make a new 4298 one. We can't just modify the existing metadata in place, 4299 because then it would (almost certainly) be in the wrong hash 4300 chain. */ 4301 md_new = new_MallocMeta(); 4302 *md_new = *md; 4303 4304 md_tmp = VG_(HT_remove)( hg_mallocmeta_table, payload ); 4305 tl_assert(md_tmp); 4306 tl_assert(md_tmp == md); 4307 4308 VG_(cli_free)((void*)md->payload); 4309 delete_MallocMeta(md); 4310 4311 /* Update fields */ 4312 md_new->where = VG_(record_ExeContext)( tid, 0 ); 4313 md_new->szB = new_size; 4314 md_new->payload = p_new; 4315 md_new->thr = map_threads_lookup( tid ); 4316 4317 /* and add */ 4318 VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md_new ); 4319 4320 return (void*)p_new; 4321 } 4322 } 4323 4324 static SizeT hg_cli_malloc_usable_size ( ThreadId tid, void* p ) 4325 { 4326 MallocMeta *md = VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p ); 4327 4328 // There may be slop, but pretend there isn't because only the asked-for 4329 // area will have been shadowed properly. 4330 return ( md ? md->szB : 0 ); 4331 } 4332 4333 4334 /* For error creation: map 'data_addr' to a malloc'd chunk, if any. 4335 Slow linear search. With a bit of hash table help if 'data_addr' 4336 is either the start of a block or up to 15 word-sized steps along 4337 from the start of a block. */ 4338 4339 static inline Bool addr_is_in_MM_Chunk( MallocMeta* mm, Addr a ) 4340 { 4341 /* Accept 'a' as within 'mm' if 'mm's size is zero and 'a' points 4342 right at it. */ 4343 if (UNLIKELY(mm->szB == 0 && a == mm->payload)) 4344 return True; 4345 /* else normal interval rules apply */ 4346 if (LIKELY(a < mm->payload)) return False; 4347 if (LIKELY(a >= mm->payload + mm->szB)) return False; 4348 return True; 4349 } 4350 4351 Bool HG_(mm_find_containing_block)( /*OUT*/ExeContext** where, 4352 /*OUT*/UInt* tnr, 4353 /*OUT*/Addr* payload, 4354 /*OUT*/SizeT* szB, 4355 Addr data_addr ) 4356 { 4357 MallocMeta* mm; 4358 Int i; 4359 const Int n_fast_check_words = 16; 4360 4361 /* First, do a few fast searches on the basis that data_addr might 4362 be exactly the start of a block or up to 15 words inside. This 4363 can happen commonly via the creq 4364 _VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK. */ 4365 for (i = 0; i < n_fast_check_words; i++) { 4366 mm = VG_(HT_lookup)( hg_mallocmeta_table, 4367 data_addr - (UWord)(UInt)i * sizeof(UWord) ); 4368 if (UNLIKELY(mm && addr_is_in_MM_Chunk(mm, data_addr))) 4369 goto found; 4370 } 4371 4372 /* Well, this totally sucks. But without using an interval tree or 4373 some such, it's hard to see how to do better. We have to check 4374 every block in the entire table. */ 4375 VG_(HT_ResetIter)(hg_mallocmeta_table); 4376 while ( (mm = VG_(HT_Next)(hg_mallocmeta_table)) ) { 4377 if (UNLIKELY(addr_is_in_MM_Chunk(mm, data_addr))) 4378 goto found; 4379 } 4380 4381 /* Not found. Bah. */ 4382 return False; 4383 /*NOTREACHED*/ 4384 4385 found: 4386 tl_assert(mm); 4387 tl_assert(addr_is_in_MM_Chunk(mm, data_addr)); 4388 if (where) *where = mm->where; 4389 if (tnr) *tnr = mm->thr->errmsg_index; 4390 if (payload) *payload = mm->payload; 4391 if (szB) *szB = mm->szB; 4392 return True; 4393 } 4394 4395 4396 /*--------------------------------------------------------------*/ 4397 /*--- Instrumentation ---*/ 4398 /*--------------------------------------------------------------*/ 4399 4400 #define unop(_op, _arg1) IRExpr_Unop((_op),(_arg1)) 4401 #define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2)) 4402 #define mkexpr(_tmp) IRExpr_RdTmp((_tmp)) 4403 #define mkU32(_n) IRExpr_Const(IRConst_U32(_n)) 4404 #define mkU64(_n) IRExpr_Const(IRConst_U64(_n)) 4405 #define assign(_t, _e) IRStmt_WrTmp((_t), (_e)) 4406 4407 /* This takes and returns atoms, of course. Not full IRExprs. */ 4408 static IRExpr* mk_And1 ( IRSB* sbOut, IRExpr* arg1, IRExpr* arg2 ) 4409 { 4410 tl_assert(arg1 && arg2); 4411 tl_assert(isIRAtom(arg1)); 4412 tl_assert(isIRAtom(arg2)); 4413 /* Generate 32to1(And32(1Uto32(arg1), 1Uto32(arg2))). Appalling 4414 code, I know. */ 4415 IRTemp wide1 = newIRTemp(sbOut->tyenv, Ity_I32); 4416 IRTemp wide2 = newIRTemp(sbOut->tyenv, Ity_I32); 4417 IRTemp anded = newIRTemp(sbOut->tyenv, Ity_I32); 4418 IRTemp res = newIRTemp(sbOut->tyenv, Ity_I1); 4419 addStmtToIRSB(sbOut, assign(wide1, unop(Iop_1Uto32, arg1))); 4420 addStmtToIRSB(sbOut, assign(wide2, unop(Iop_1Uto32, arg2))); 4421 addStmtToIRSB(sbOut, assign(anded, binop(Iop_And32, mkexpr(wide1), 4422 mkexpr(wide2)))); 4423 addStmtToIRSB(sbOut, assign(res, unop(Iop_32to1, mkexpr(anded)))); 4424 return mkexpr(res); 4425 } 4426 4427 static void instrument_mem_access ( IRSB* sbOut, 4428 IRExpr* addr, 4429 Int szB, 4430 Bool isStore, 4431 Int hWordTy_szB, 4432 Int goff_sp, 4433 IRExpr* guard ) /* NULL => True */ 4434 { 4435 IRType tyAddr = Ity_INVALID; 4436 const HChar* hName = NULL; 4437 void* hAddr = NULL; 4438 Int regparms = 0; 4439 IRExpr** argv = NULL; 4440 IRDirty* di = NULL; 4441 4442 // THRESH is the size of the window above SP (well, 4443 // mostly above) that we assume implies a stack reference. 4444 const Int THRESH = 4096 * 4; // somewhat arbitrary 4445 const Int rz_szB = VG_STACK_REDZONE_SZB; 4446 4447 tl_assert(isIRAtom(addr)); 4448 tl_assert(hWordTy_szB == 4 || hWordTy_szB == 8); 4449 4450 tyAddr = typeOfIRExpr( sbOut->tyenv, addr ); 4451 tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64); 4452 4453 /* So the effective address is in 'addr' now. */ 4454 regparms = 1; // unless stated otherwise 4455 if (isStore) { 4456 switch (szB) { 4457 case 1: 4458 hName = "evh__mem_help_cwrite_1"; 4459 hAddr = &evh__mem_help_cwrite_1; 4460 argv = mkIRExprVec_1( addr ); 4461 break; 4462 case 2: 4463 hName = "evh__mem_help_cwrite_2"; 4464 hAddr = &evh__mem_help_cwrite_2; 4465 argv = mkIRExprVec_1( addr ); 4466 break; 4467 case 4: 4468 hName = "evh__mem_help_cwrite_4"; 4469 hAddr = &evh__mem_help_cwrite_4; 4470 argv = mkIRExprVec_1( addr ); 4471 break; 4472 case 8: 4473 hName = "evh__mem_help_cwrite_8"; 4474 hAddr = &evh__mem_help_cwrite_8; 4475 argv = mkIRExprVec_1( addr ); 4476 break; 4477 default: 4478 tl_assert(szB > 8 && szB <= 512); /* stay sane */ 4479 regparms = 2; 4480 hName = "evh__mem_help_cwrite_N"; 4481 hAddr = &evh__mem_help_cwrite_N; 4482 argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB )); 4483 break; 4484 } 4485 } else { 4486 switch (szB) { 4487 case 1: 4488 hName = "evh__mem_help_cread_1"; 4489 hAddr = &evh__mem_help_cread_1; 4490 argv = mkIRExprVec_1( addr ); 4491 break; 4492 case 2: 4493 hName = "evh__mem_help_cread_2"; 4494 hAddr = &evh__mem_help_cread_2; 4495 argv = mkIRExprVec_1( addr ); 4496 break; 4497 case 4: 4498 hName = "evh__mem_help_cread_4"; 4499 hAddr = &evh__mem_help_cread_4; 4500 argv = mkIRExprVec_1( addr ); 4501 break; 4502 case 8: 4503 hName = "evh__mem_help_cread_8"; 4504 hAddr = &evh__mem_help_cread_8; 4505 argv = mkIRExprVec_1( addr ); 4506 break; 4507 default: 4508 tl_assert(szB > 8 && szB <= 512); /* stay sane */ 4509 regparms = 2; 4510 hName = "evh__mem_help_cread_N"; 4511 hAddr = &evh__mem_help_cread_N; 4512 argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB )); 4513 break; 4514 } 4515 } 4516 4517 /* Create the helper. */ 4518 tl_assert(hName); 4519 tl_assert(hAddr); 4520 tl_assert(argv); 4521 di = unsafeIRDirty_0_N( regparms, 4522 hName, VG_(fnptr_to_fnentry)( hAddr ), 4523 argv ); 4524 4525 if (! HG_(clo_check_stack_refs)) { 4526 /* We're ignoring memory references which are (obviously) to the 4527 stack. In fact just skip stack refs that are within 4 pages 4528 of SP (SP - the redzone, really), as that's simple, easy, and 4529 filters out most stack references. */ 4530 /* Generate the guard condition: "(addr - (SP - RZ)) >u N", for 4531 some arbitrary N. If that is true then addr is outside the 4532 range (SP - RZ .. SP + N - RZ). If N is smallish (a few 4533 pages) then we can say addr is within a few pages of SP and 4534 so can't possibly be a heap access, and so can be skipped. 4535 4536 Note that the condition simplifies to 4537 (addr - SP + RZ) >u N 4538 which generates better code in x86/amd64 backends, but it does 4539 not unfortunately simplify to 4540 (addr - SP) >u (N - RZ) 4541 (would be beneficial because N - RZ is a constant) because 4542 wraparound arithmetic messes up the comparison. eg. 4543 20 >u 10 == True, 4544 but (20 - 15) >u (10 - 15) == 5 >u (MAXINT-5) == False. 4545 */ 4546 IRTemp sp = newIRTemp(sbOut->tyenv, tyAddr); 4547 addStmtToIRSB( sbOut, assign(sp, IRExpr_Get(goff_sp, tyAddr))); 4548 4549 /* "addr - SP" */ 4550 IRTemp addr_minus_sp = newIRTemp(sbOut->tyenv, tyAddr); 4551 addStmtToIRSB( 4552 sbOut, 4553 assign(addr_minus_sp, 4554 tyAddr == Ity_I32 4555 ? binop(Iop_Sub32, addr, mkexpr(sp)) 4556 : binop(Iop_Sub64, addr, mkexpr(sp))) 4557 ); 4558 4559 /* "addr - SP + RZ" */ 4560 IRTemp diff = newIRTemp(sbOut->tyenv, tyAddr); 4561 addStmtToIRSB( 4562 sbOut, 4563 assign(diff, 4564 tyAddr == Ity_I32 4565 ? binop(Iop_Add32, mkexpr(addr_minus_sp), mkU32(rz_szB)) 4566 : binop(Iop_Add64, mkexpr(addr_minus_sp), mkU64(rz_szB))) 4567 ); 4568 4569 /* guardA == "guard on the address" */ 4570 IRTemp guardA = newIRTemp(sbOut->tyenv, Ity_I1); 4571 addStmtToIRSB( 4572 sbOut, 4573 assign(guardA, 4574 tyAddr == Ity_I32 4575 ? binop(Iop_CmpLT32U, mkU32(THRESH), mkexpr(diff)) 4576 : binop(Iop_CmpLT64U, mkU64(THRESH), mkexpr(diff))) 4577 ); 4578 di->guard = mkexpr(guardA); 4579 } 4580 4581 /* If there's a guard on the access itself (as supplied by the 4582 caller of this routine), we need to AND that in to any guard we 4583 might already have. */ 4584 if (guard) { 4585 di->guard = mk_And1(sbOut, di->guard, guard); 4586 } 4587 4588 /* Add the helper. */ 4589 addStmtToIRSB( sbOut, IRStmt_Dirty(di) ); 4590 } 4591 4592 4593 /* Figure out if GA is a guest code address in the dynamic linker, and 4594 if so return True. Otherwise (and in case of any doubt) return 4595 False. (sidedly safe w/ False as the safe value) */ 4596 static Bool is_in_dynamic_linker_shared_object( Addr ga ) 4597 { 4598 DebugInfo* dinfo; 4599 const HChar* soname; 4600 4601 dinfo = VG_(find_DebugInfo)( ga ); 4602 if (!dinfo) return False; 4603 4604 soname = VG_(DebugInfo_get_soname)(dinfo); 4605 tl_assert(soname); 4606 if (0) VG_(printf)("%s\n", soname); 4607 4608 return VG_(is_soname_ld_so)(soname); 4609 } 4610 4611 static 4612 IRSB* hg_instrument ( VgCallbackClosure* closure, 4613 IRSB* bbIn, 4614 const VexGuestLayout* layout, 4615 const VexGuestExtents* vge, 4616 const VexArchInfo* archinfo_host, 4617 IRType gWordTy, IRType hWordTy ) 4618 { 4619 Int i; 4620 IRSB* bbOut; 4621 Addr cia; /* address of current insn */ 4622 IRStmt* st; 4623 Bool inLDSO = False; 4624 Addr inLDSOmask4K = 1; /* mismatches on first check */ 4625 4626 const Int goff_sp = layout->offset_SP; 4627 4628 if (gWordTy != hWordTy) { 4629 /* We don't currently support this case. */ 4630 VG_(tool_panic)("host/guest word size mismatch"); 4631 } 4632 4633 if (VKI_PAGE_SIZE < 4096 || VG_(log2)(VKI_PAGE_SIZE) == -1) { 4634 VG_(tool_panic)("implausible or too-small VKI_PAGE_SIZE"); 4635 } 4636 4637 /* Set up BB */ 4638 bbOut = emptyIRSB(); 4639 bbOut->tyenv = deepCopyIRTypeEnv(bbIn->tyenv); 4640 bbOut->next = deepCopyIRExpr(bbIn->next); 4641 bbOut->jumpkind = bbIn->jumpkind; 4642 bbOut->offsIP = bbIn->offsIP; 4643 4644 // Copy verbatim any IR preamble preceding the first IMark 4645 i = 0; 4646 while (i < bbIn->stmts_used && bbIn->stmts[i]->tag != Ist_IMark) { 4647 addStmtToIRSB( bbOut, bbIn->stmts[i] ); 4648 i++; 4649 } 4650 4651 // Get the first statement, and initial cia from it 4652 tl_assert(bbIn->stmts_used > 0); 4653 tl_assert(i < bbIn->stmts_used); 4654 st = bbIn->stmts[i]; 4655 tl_assert(Ist_IMark == st->tag); 4656 cia = st->Ist.IMark.addr; 4657 st = NULL; 4658 4659 for (/*use current i*/; i < bbIn->stmts_used; i++) { 4660 st = bbIn->stmts[i]; 4661 tl_assert(st); 4662 tl_assert(isFlatIRStmt(st)); 4663 switch (st->tag) { 4664 case Ist_NoOp: 4665 case Ist_AbiHint: 4666 case Ist_Put: 4667 case Ist_PutI: 4668 case Ist_Exit: 4669 /* None of these can contain any memory references. */ 4670 break; 4671 4672 case Ist_IMark: 4673 /* no mem refs, but note the insn address. */ 4674 cia = st->Ist.IMark.addr; 4675 /* Don't instrument the dynamic linker. It generates a 4676 lot of races which we just expensively suppress, so 4677 it's pointless. 4678 4679 Avoid flooding is_in_dynamic_linker_shared_object with 4680 requests by only checking at transitions between 4K 4681 pages. */ 4682 if ((cia & ~(Addr)0xFFF) != inLDSOmask4K) { 4683 if (0) VG_(printf)("NEW %#lx\n", cia); 4684 inLDSOmask4K = cia & ~(Addr)0xFFF; 4685 inLDSO = is_in_dynamic_linker_shared_object(cia); 4686 } else { 4687 if (0) VG_(printf)("old %#lx\n", cia); 4688 } 4689 break; 4690 4691 case Ist_MBE: 4692 switch (st->Ist.MBE.event) { 4693 case Imbe_Fence: 4694 case Imbe_CancelReservation: 4695 break; /* not interesting */ 4696 default: 4697 goto unhandled; 4698 } 4699 break; 4700 4701 case Ist_CAS: { 4702 /* Atomic read-modify-write cycle. Just pretend it's a 4703 read. */ 4704 IRCAS* cas = st->Ist.CAS.details; 4705 Bool isDCAS = cas->oldHi != IRTemp_INVALID; 4706 if (isDCAS) { 4707 tl_assert(cas->expdHi); 4708 tl_assert(cas->dataHi); 4709 } else { 4710 tl_assert(!cas->expdHi); 4711 tl_assert(!cas->dataHi); 4712 } 4713 /* Just be boring about it. */ 4714 if (!inLDSO) { 4715 instrument_mem_access( 4716 bbOut, 4717 cas->addr, 4718 (isDCAS ? 2 : 1) 4719 * sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)), 4720 False/*!isStore*/, 4721 sizeofIRType(hWordTy), goff_sp, 4722 NULL/*no-guard*/ 4723 ); 4724 } 4725 break; 4726 } 4727 4728 case Ist_LLSC: { 4729 /* We pretend store-conditionals don't exist, viz, ignore 4730 them. Whereas load-linked's are treated the same as 4731 normal loads. */ 4732 IRType dataTy; 4733 if (st->Ist.LLSC.storedata == NULL) { 4734 /* LL */ 4735 dataTy = typeOfIRTemp(bbIn->tyenv, st->Ist.LLSC.result); 4736 if (!inLDSO) { 4737 instrument_mem_access( 4738 bbOut, 4739 st->Ist.LLSC.addr, 4740 sizeofIRType(dataTy), 4741 False/*!isStore*/, 4742 sizeofIRType(hWordTy), goff_sp, 4743 NULL/*no-guard*/ 4744 ); 4745 } 4746 } else { 4747 /* SC */ 4748 /*ignore */ 4749 } 4750 break; 4751 } 4752 4753 case Ist_Store: 4754 if (!inLDSO) { 4755 instrument_mem_access( 4756 bbOut, 4757 st->Ist.Store.addr, 4758 sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)), 4759 True/*isStore*/, 4760 sizeofIRType(hWordTy), goff_sp, 4761 NULL/*no-guard*/ 4762 ); 4763 } 4764 break; 4765 4766 case Ist_StoreG: { 4767 IRStoreG* sg = st->Ist.StoreG.details; 4768 IRExpr* data = sg->data; 4769 IRExpr* addr = sg->addr; 4770 IRType type = typeOfIRExpr(bbIn->tyenv, data); 4771 tl_assert(type != Ity_INVALID); 4772 instrument_mem_access( bbOut, addr, sizeofIRType(type), 4773 True/*isStore*/, 4774 sizeofIRType(hWordTy), 4775 goff_sp, sg->guard ); 4776 break; 4777 } 4778 4779 case Ist_LoadG: { 4780 IRLoadG* lg = st->Ist.LoadG.details; 4781 IRType type = Ity_INVALID; /* loaded type */ 4782 IRType typeWide = Ity_INVALID; /* after implicit widening */ 4783 IRExpr* addr = lg->addr; 4784 typeOfIRLoadGOp(lg->cvt, &typeWide, &type); 4785 tl_assert(type != Ity_INVALID); 4786 instrument_mem_access( bbOut, addr, sizeofIRType(type), 4787 False/*!isStore*/, 4788 sizeofIRType(hWordTy), 4789 goff_sp, lg->guard ); 4790 break; 4791 } 4792 4793 case Ist_WrTmp: { 4794 IRExpr* data = st->Ist.WrTmp.data; 4795 if (data->tag == Iex_Load) { 4796 if (!inLDSO) { 4797 instrument_mem_access( 4798 bbOut, 4799 data->Iex.Load.addr, 4800 sizeofIRType(data->Iex.Load.ty), 4801 False/*!isStore*/, 4802 sizeofIRType(hWordTy), goff_sp, 4803 NULL/*no-guard*/ 4804 ); 4805 } 4806 } 4807 break; 4808 } 4809 4810 case Ist_Dirty: { 4811 Int dataSize; 4812 IRDirty* d = st->Ist.Dirty.details; 4813 if (d->mFx != Ifx_None) { 4814 /* This dirty helper accesses memory. Collect the 4815 details. */ 4816 tl_assert(d->mAddr != NULL); 4817 tl_assert(d->mSize != 0); 4818 dataSize = d->mSize; 4819 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) { 4820 if (!inLDSO) { 4821 instrument_mem_access( 4822 bbOut, d->mAddr, dataSize, False/*!isStore*/, 4823 sizeofIRType(hWordTy), goff_sp, NULL/*no-guard*/ 4824 ); 4825 } 4826 } 4827 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) { 4828 if (!inLDSO) { 4829 instrument_mem_access( 4830 bbOut, d->mAddr, dataSize, True/*isStore*/, 4831 sizeofIRType(hWordTy), goff_sp, NULL/*no-guard*/ 4832 ); 4833 } 4834 } 4835 } else { 4836 tl_assert(d->mAddr == NULL); 4837 tl_assert(d->mSize == 0); 4838 } 4839 break; 4840 } 4841 4842 default: 4843 unhandled: 4844 ppIRStmt(st); 4845 tl_assert(0); 4846 4847 } /* switch (st->tag) */ 4848 4849 addStmtToIRSB( bbOut, st ); 4850 } /* iterate over bbIn->stmts */ 4851 4852 return bbOut; 4853 } 4854 4855 #undef binop 4856 #undef mkexpr 4857 #undef mkU32 4858 #undef mkU64 4859 #undef assign 4860 4861 4862 /*----------------------------------------------------------------*/ 4863 /*--- Client requests ---*/ 4864 /*----------------------------------------------------------------*/ 4865 4866 /* Sheesh. Yet another goddam finite map. */ 4867 static WordFM* map_pthread_t_to_Thread = NULL; /* pthread_t -> Thread* */ 4868 4869 static void map_pthread_t_to_Thread_INIT ( void ) { 4870 if (UNLIKELY(map_pthread_t_to_Thread == NULL)) { 4871 map_pthread_t_to_Thread = VG_(newFM)( HG_(zalloc), "hg.mpttT.1", 4872 HG_(free), NULL ); 4873 } 4874 } 4875 4876 /* A list of Ada dependent tasks and their masters. Used for implementing 4877 the Ada task termination semantic as implemented by the 4878 gcc gnat Ada runtime. */ 4879 typedef 4880 struct { 4881 void* dependent; // Ada Task Control Block of the Dependent 4882 void* master; // ATCB of the master 4883 Word master_level; // level of dependency between master and dependent 4884 Thread* hg_dependent; // helgrind Thread* for dependent task. 4885 } 4886 GNAT_dmml; // (d)ependent (m)aster (m)aster_(l)evel. 4887 static XArray* gnat_dmmls; /* of GNAT_dmml */ 4888 static void gnat_dmmls_INIT (void) 4889 { 4890 if (UNLIKELY(gnat_dmmls == NULL)) { 4891 gnat_dmmls = VG_(newXA) (HG_(zalloc), "hg.gnat_md.1", 4892 HG_(free), 4893 sizeof(GNAT_dmml) ); 4894 } 4895 } 4896 4897 static void xtmemory_report_next_block(XT_Allocs* xta, ExeContext** ec_alloc) 4898 { 4899 const MallocMeta* md = VG_(HT_Next)(hg_mallocmeta_table); 4900 if (md) { 4901 xta->nbytes = md->szB; 4902 xta->nblocks = 1; 4903 *ec_alloc = md->where; 4904 } else 4905 xta->nblocks = 0; 4906 } 4907 static void HG_(xtmemory_report) ( const HChar* filename, Bool fini ) 4908 { 4909 // Make xtmemory_report_next_block ready to be called. 4910 VG_(HT_ResetIter)(hg_mallocmeta_table); 4911 VG_(XTMemory_report)(filename, fini, xtmemory_report_next_block, 4912 VG_(XT_filter_1top_and_maybe_below_main)); 4913 } 4914 4915 static void print_monitor_help ( void ) 4916 { 4917 VG_(gdb_printf) 4918 ( 4919 "\n" 4920 "helgrind monitor commands:\n" 4921 " info locks [lock_addr] : show status of lock at addr lock_addr\n" 4922 " with no lock_addr, show status of all locks\n" 4923 " accesshistory <addr> [<len>] : show access history recorded\n" 4924 " for <len> (or 1) bytes at <addr>\n" 4925 " xtmemory [<filename>]\n" 4926 " dump xtree memory profile in <filename> (default xtmemory.kcg)\n" 4927 "\n"); 4928 } 4929 4930 /* return True if request recognised, False otherwise */ 4931 static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) 4932 { 4933 HChar* wcmd; 4934 HChar s[VG_(strlen)(req)]; /* copy for strtok_r */ 4935 HChar *ssaveptr; 4936 Int kwdid; 4937 4938 VG_(strcpy) (s, req); 4939 4940 wcmd = VG_(strtok_r) (s, " ", &ssaveptr); 4941 /* NB: if possible, avoid introducing a new command below which 4942 starts with the same first letter(s) as an already existing 4943 command. This ensures a shorter abbreviation for the user. */ 4944 switch (VG_(keyword_id) 4945 ("help info accesshistory xtmemory", 4946 wcmd, kwd_report_duplicated_matches)) { 4947 case -2: /* multiple matches */ 4948 return True; 4949 case -1: /* not found */ 4950 return False; 4951 case 0: /* help */ 4952 print_monitor_help(); 4953 return True; 4954 case 1: /* info */ 4955 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr); 4956 switch (kwdid = VG_(keyword_id) 4957 ("locks", 4958 wcmd, kwd_report_all)) { 4959 case -2: 4960 case -1: 4961 break; 4962 case 0: // locks 4963 { 4964 const HChar* wa; 4965 Addr lk_addr = 0; 4966 Bool lk_shown = False; 4967 Bool all_locks = True; 4968 Int i; 4969 Lock* lk; 4970 4971 wa = VG_(strtok_r) (NULL, " ", &ssaveptr); 4972 if (wa != NULL) { 4973 if (VG_(parse_Addr) (&wa, &lk_addr) ) 4974 all_locks = False; 4975 else { 4976 VG_(gdb_printf) ("missing or malformed address\n"); 4977 } 4978 } 4979 for (i = 0, lk = admin_locks; lk; i++, lk = lk->admin_next) { 4980 if (all_locks || lk_addr == lk->guestaddr) { 4981 pp_Lock(0, lk, 4982 True /* show_lock_addrdescr */, 4983 False /* show_internal_data */); 4984 lk_shown = True; 4985 } 4986 } 4987 if (i == 0) 4988 VG_(gdb_printf) ("no locks\n"); 4989 if (!all_locks && !lk_shown) 4990 VG_(gdb_printf) ("lock with address %p not found\n", 4991 (void*)lk_addr); 4992 } 4993 break; 4994 default: 4995 tl_assert(0); 4996 } 4997 return True; 4998 4999 case 2: /* accesshistory */ 5000 { 5001 Addr address; 5002 SizeT szB = 1; 5003 if (HG_(clo_history_level) < 2) { 5004 VG_(gdb_printf) 5005 ("helgrind must be started with --history-level=full" 5006 " to use accesshistory\n"); 5007 return True; 5008 } 5009 if (VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr)) { 5010 if (szB >= 1) 5011 libhb_event_map_access_history (address, szB, HG_(print_access)); 5012 else 5013 VG_(gdb_printf) ("len must be >=1\n"); 5014 } 5015 return True; 5016 } 5017 5018 case 3: { /* xtmemory */ 5019 HChar* filename; 5020 filename = VG_(strtok_r) (NULL, " ", &ssaveptr); 5021 HG_(xtmemory_report)(filename, False); 5022 return True; 5023 } 5024 5025 default: 5026 tl_assert(0); 5027 return False; 5028 } 5029 } 5030 5031 static 5032 Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret) 5033 { 5034 if (!VG_IS_TOOL_USERREQ('H','G',args[0]) 5035 && VG_USERREQ__GDB_MONITOR_COMMAND != args[0]) 5036 return False; 5037 5038 /* Anything that gets past the above check is one of ours, so we 5039 should be able to handle it. */ 5040 5041 /* default, meaningless return value, unless otherwise set */ 5042 *ret = 0; 5043 5044 switch (args[0]) { 5045 5046 /* --- --- User-visible client requests --- --- */ 5047 5048 case VG_USERREQ__HG_CLEAN_MEMORY: 5049 if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY(%#lx,%lu)\n", 5050 args[1], args[2]); 5051 /* Call die_mem to (expensively) tidy up properly, if there 5052 are any held locks etc in the area. Calling evh__die_mem 5053 and then evh__new_mem is a bit inefficient; probably just 5054 the latter would do. */ 5055 if (args[2] > 0) { /* length */ 5056 evh__die_mem(args[1], args[2]); 5057 /* and then set it to New */ 5058 evh__new_mem(args[1], args[2]); 5059 } 5060 break; 5061 5062 case _VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK: { 5063 Addr payload = 0; 5064 SizeT pszB = 0; 5065 if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK(%#lx)\n", 5066 args[1]); 5067 if (HG_(mm_find_containing_block)(NULL, NULL, 5068 &payload, &pszB, args[1])) { 5069 if (pszB > 0) { 5070 evh__die_mem(payload, pszB); 5071 evh__new_mem(payload, pszB); 5072 } 5073 *ret = pszB; 5074 } else { 5075 *ret = (UWord)-1; 5076 } 5077 break; 5078 } 5079 5080 case _VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED: 5081 if (0) VG_(printf)("HG_ARANGE_MAKE_UNTRACKED(%#lx,%lu)\n", 5082 args[1], args[2]); 5083 if (args[2] > 0) { /* length */ 5084 evh__untrack_mem(args[1], args[2]); 5085 } 5086 break; 5087 5088 case _VG_USERREQ__HG_ARANGE_MAKE_TRACKED: 5089 if (0) VG_(printf)("HG_ARANGE_MAKE_TRACKED(%#lx,%lu)\n", 5090 args[1], args[2]); 5091 if (args[2] > 0) { /* length */ 5092 evh__new_mem(args[1], args[2]); 5093 } 5094 break; 5095 5096 case _VG_USERREQ__HG_GET_ABITS: 5097 if (0) VG_(printf)("HG_GET_ABITS(%#lx,%#lx,%lu)\n", 5098 args[1], args[2], args[3]); 5099 UChar *zzabit = (UChar *) args[2]; 5100 if (zzabit == NULL 5101 || VG_(am_is_valid_for_client)((Addr)zzabit, (SizeT)args[3], 5102 VKI_PROT_READ|VKI_PROT_WRITE)) 5103 *ret = (UWord) libhb_srange_get_abits ((Addr) args[1], 5104 (UChar*) args[2], 5105 (SizeT) args[3]); 5106 else 5107 *ret = -1; 5108 break; 5109 5110 /* This thread (tid) (a master) is informing us that it has 5111 seen the termination of a dependent task, and that this should 5112 be considered as a join between master and dependent. */ 5113 case _VG_USERREQ__HG_GNAT_DEPENDENT_MASTER_JOIN: { 5114 Word n; 5115 const Thread *stayer = map_threads_maybe_lookup( tid ); 5116 const void *dependent = (void*)args[1]; 5117 const void *master = (void*)args[2]; 5118 5119 if (0) 5120 VG_(printf)("HG_GNAT_DEPENDENT_MASTER_JOIN (tid %d): " 5121 "self_id = %p Thread* = %p dependent %p\n", 5122 (Int)tid, master, stayer, dependent); 5123 5124 gnat_dmmls_INIT(); 5125 /* Similar loop as for master completed hook below, but stops at 5126 the first matching occurence, only comparing master and 5127 dependent. */ 5128 for (n = VG_(sizeXA) (gnat_dmmls) - 1; n >= 0; n--) { 5129 GNAT_dmml *dmml = (GNAT_dmml*) VG_(indexXA)(gnat_dmmls, n); 5130 if (dmml->master == master 5131 && dmml->dependent == dependent) { 5132 if (0) 5133 VG_(printf)("quitter %p dependency to stayer %p (join)\n", 5134 dmml->hg_dependent->hbthr, stayer->hbthr); 5135 tl_assert(dmml->hg_dependent->hbthr != stayer->hbthr); 5136 generate_quitter_stayer_dependence (dmml->hg_dependent->hbthr, 5137 stayer->hbthr); 5138 VG_(removeIndexXA) (gnat_dmmls, n); 5139 break; 5140 } 5141 } 5142 break; 5143 } 5144 5145 /* --- --- Client requests for Helgrind's use only --- --- */ 5146 5147 /* Some thread is telling us its pthread_t value. Record the 5148 binding between that and the associated Thread*, so we can 5149 later find the Thread* again when notified of a join by the 5150 thread. */ 5151 case _VG_USERREQ__HG_SET_MY_PTHREAD_T: { 5152 Thread* my_thr = NULL; 5153 if (0) 5154 VG_(printf)("SET_MY_PTHREAD_T (tid %d): pthread_t = %p\n", (Int)tid, 5155 (void*)args[1]); 5156 map_pthread_t_to_Thread_INIT(); 5157 my_thr = map_threads_maybe_lookup( tid ); 5158 /* This assertion should hold because the map_threads (tid to 5159 Thread*) binding should have been made at the point of 5160 low-level creation of this thread, which should have 5161 happened prior to us getting this client request for it. 5162 That's because this client request is sent from 5163 client-world from the 'thread_wrapper' function, which 5164 only runs once the thread has been low-level created. */ 5165 tl_assert(my_thr != NULL); 5166 /* So now we know that (pthread_t)args[1] is associated with 5167 (Thread*)my_thr. Note that down. */ 5168 if (0) 5169 VG_(printf)("XXXX: bind pthread_t %p to Thread* %p\n", 5170 (void*)args[1], (void*)my_thr ); 5171 VG_(addToFM)( map_pthread_t_to_Thread, (UWord)args[1], (UWord)my_thr ); 5172 5173 if (my_thr->coretid != 1) { 5174 /* FIXME: hardwires assumption about identity of the root thread. */ 5175 if (HG_(clo_ignore_thread_creation)) { 5176 HG_(thread_leave_pthread_create)(my_thr); 5177 HG_(thread_leave_synchr)(my_thr); 5178 tl_assert(my_thr->synchr_nesting == 0); 5179 } 5180 } 5181 break; 5182 } 5183 5184 case _VG_USERREQ__HG_PTH_API_ERROR: { 5185 Thread* my_thr = NULL; 5186 map_pthread_t_to_Thread_INIT(); 5187 my_thr = map_threads_maybe_lookup( tid ); 5188 tl_assert(my_thr); /* See justification above in SET_MY_PTHREAD_T */ 5189 HG_(record_error_PthAPIerror)( 5190 my_thr, (HChar*)args[1], (UWord)args[2], (HChar*)args[3] ); 5191 break; 5192 } 5193 5194 /* This thread (tid) has completed a join with the quitting 5195 thread whose pthread_t is in args[1]. */ 5196 case _VG_USERREQ__HG_PTHREAD_JOIN_POST: { 5197 Thread* thr_q = NULL; /* quitter Thread* */ 5198 Bool found = False; 5199 if (0) 5200 VG_(printf)("NOTIFY_JOIN_COMPLETE (tid %d): quitter = %p\n", (Int)tid, 5201 (void*)args[1]); 5202 map_pthread_t_to_Thread_INIT(); 5203 found = VG_(lookupFM)( map_pthread_t_to_Thread, 5204 NULL, (UWord*)&thr_q, (UWord)args[1] ); 5205 /* Can this fail? It would mean that our pthread_join 5206 wrapper observed a successful join on args[1] yet that 5207 thread never existed (or at least, it never lodged an 5208 entry in the mapping (via SET_MY_PTHREAD_T)). Which 5209 sounds like a bug in the threads library. */ 5210 // FIXME: get rid of this assertion; handle properly 5211 tl_assert(found); 5212 if (found) { 5213 if (0) 5214 VG_(printf)(".................... quitter Thread* = %p\n", 5215 thr_q); 5216 evh__HG_PTHREAD_JOIN_POST( tid, thr_q ); 5217 } 5218 break; 5219 } 5220 5221 /* This thread (tid) is informing us of its master. */ 5222 case _VG_USERREQ__HG_GNAT_MASTER_HOOK: { 5223 GNAT_dmml dmml; 5224 dmml.dependent = (void*)args[1]; 5225 dmml.master = (void*)args[2]; 5226 dmml.master_level = (Word)args[3]; 5227 dmml.hg_dependent = map_threads_maybe_lookup( tid ); 5228 tl_assert(dmml.hg_dependent); 5229 5230 if (0) 5231 VG_(printf)("HG_GNAT_MASTER_HOOK (tid %d): " 5232 "dependent = %p master = %p master_level = %ld" 5233 " dependent Thread* = %p\n", 5234 (Int)tid, dmml.dependent, dmml.master, dmml.master_level, 5235 dmml.hg_dependent); 5236 gnat_dmmls_INIT(); 5237 VG_(addToXA) (gnat_dmmls, &dmml); 5238 break; 5239 } 5240 5241 /* This thread (tid) is informing us that it has completed a 5242 master. */ 5243 case _VG_USERREQ__HG_GNAT_MASTER_COMPLETED_HOOK: { 5244 Word n; 5245 const Thread *stayer = map_threads_maybe_lookup( tid ); 5246 const void *master = (void*)args[1]; 5247 const Word master_level = (Word) args[2]; 5248 tl_assert(stayer); 5249 5250 if (0) 5251 VG_(printf)("HG_GNAT_MASTER_COMPLETED_HOOK (tid %d): " 5252 "self_id = %p master_level = %ld Thread* = %p\n", 5253 (Int)tid, master, master_level, stayer); 5254 5255 gnat_dmmls_INIT(); 5256 /* Reverse loop on the array, simulating a pthread_join for 5257 the Dependent tasks of the completed master, and removing 5258 them from the array. */ 5259 for (n = VG_(sizeXA) (gnat_dmmls) - 1; n >= 0; n--) { 5260 GNAT_dmml *dmml = (GNAT_dmml*) VG_(indexXA)(gnat_dmmls, n); 5261 if (dmml->master == master 5262 && dmml->master_level == master_level) { 5263 if (0) 5264 VG_(printf)("quitter %p dependency to stayer %p\n", 5265 dmml->hg_dependent->hbthr, stayer->hbthr); 5266 tl_assert(dmml->hg_dependent->hbthr != stayer->hbthr); 5267 generate_quitter_stayer_dependence (dmml->hg_dependent->hbthr, 5268 stayer->hbthr); 5269 VG_(removeIndexXA) (gnat_dmmls, n); 5270 } 5271 } 5272 break; 5273 } 5274 5275 /* EXPOSITION only: by intercepting lock init events we can show 5276 the user where the lock was initialised, rather than only 5277 being able to show where it was first locked. Intercepting 5278 lock initialisations is not necessary for the basic operation 5279 of the race checker. */ 5280 case _VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST: 5281 evh__HG_PTHREAD_MUTEX_INIT_POST( tid, (void*)args[1], args[2] ); 5282 break; 5283 5284 /* mutex=arg[1], mutex_is_init=arg[2] */ 5285 case _VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE: 5286 evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, (void*)args[1], args[2] != 0 ); 5287 break; 5288 5289 case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE: // pth_mx_t* 5290 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5291 if (HG_(get_pthread_create_nesting_level)(tid) == 0) 5292 evh__HG_PTHREAD_MUTEX_UNLOCK_PRE( tid, (void*)args[1] ); 5293 break; 5294 5295 case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST: // pth_mx_t* 5296 if (HG_(get_pthread_create_nesting_level)(tid) == 0) 5297 evh__HG_PTHREAD_MUTEX_UNLOCK_POST( tid, (void*)args[1] ); 5298 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5299 break; 5300 5301 case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE: // pth_mx_t* 5302 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5303 if (HG_(get_pthread_create_nesting_level)(tid) == 0) 5304 evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, (void*)args[1], args[2] ); 5305 break; 5306 5307 case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST: // pth_mx_t*, long 5308 if ((args[2] == True) // lock actually taken 5309 && (HG_(get_pthread_create_nesting_level)(tid) == 0)) 5310 evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, (void*)args[1] ); 5311 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5312 break; 5313 5314 /* This thread is about to do pthread_cond_signal on the 5315 pthread_cond_t* in arg[1]. Ditto pthread_cond_broadcast. */ 5316 case _VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE: 5317 case _VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE: 5318 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5319 evh__HG_PTHREAD_COND_SIGNAL_PRE( tid, (void*)args[1] ); 5320 break; 5321 5322 case _VG_USERREQ__HG_PTHREAD_COND_SIGNAL_POST: 5323 case _VG_USERREQ__HG_PTHREAD_COND_BROADCAST_POST: 5324 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5325 break; 5326 5327 /* Entry into pthread_cond_wait, cond=arg[1], mutex=arg[2]. 5328 Returns a flag indicating whether or not the mutex is believed to be 5329 valid for this operation. */ 5330 case _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE: { 5331 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5332 Bool mutex_is_valid 5333 = evh__HG_PTHREAD_COND_WAIT_PRE( tid, (void*)args[1], 5334 (void*)args[2] ); 5335 *ret = mutex_is_valid ? 1 : 0; 5336 break; 5337 } 5338 5339 /* Thread successfully completed pthread_cond_init: 5340 cond=arg[1], cond_attr=arg[2] */ 5341 case _VG_USERREQ__HG_PTHREAD_COND_INIT_POST: 5342 evh__HG_PTHREAD_COND_INIT_POST( tid, 5343 (void*)args[1], (void*)args[2] ); 5344 break; 5345 5346 /* cond=arg[1], cond_is_init=arg[2] */ 5347 case _VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE: 5348 evh__HG_PTHREAD_COND_DESTROY_PRE( tid, (void*)args[1], args[2] != 0 ); 5349 break; 5350 5351 /* Thread completed pthread_cond_wait, cond=arg[1], 5352 mutex=arg[2], timeout=arg[3], successful=arg[4] */ 5353 case _VG_USERREQ__HG_PTHREAD_COND_WAIT_POST: 5354 if (args[4] == True) 5355 evh__HG_PTHREAD_COND_WAIT_POST( tid, 5356 (void*)args[1], (void*)args[2], 5357 (Bool)args[3] ); 5358 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5359 break; 5360 5361 case _VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST: 5362 evh__HG_PTHREAD_RWLOCK_INIT_POST( tid, (void*)args[1] ); 5363 break; 5364 5365 case _VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE: 5366 evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( tid, (void*)args[1] ); 5367 break; 5368 5369 /* rwlock=arg[1], isW=arg[2], isTryLock=arg[3] */ 5370 case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE: 5371 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5372 if (HG_(get_pthread_create_nesting_level)(tid) == 0) 5373 evh__HG_PTHREAD_RWLOCK_LOCK_PRE( tid, (void*)args[1], 5374 args[2], args[3] ); 5375 break; 5376 5377 /* rwlock=arg[1], isW=arg[2], tookLock=arg[3] */ 5378 case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST: 5379 if ((args[3] == True) 5380 && (HG_(get_pthread_create_nesting_level)(tid) == 0)) 5381 evh__HG_PTHREAD_RWLOCK_LOCK_POST( tid, (void*)args[1], args[2] ); 5382 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5383 break; 5384 5385 case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE: 5386 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5387 if (HG_(get_pthread_create_nesting_level)(tid) == 0) 5388 evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE( tid, (void*)args[1] ); 5389 break; 5390 5391 case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST: 5392 if (HG_(get_pthread_create_nesting_level)(tid) == 0) 5393 evh__HG_PTHREAD_RWLOCK_UNLOCK_POST( tid, (void*)args[1] ); 5394 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5395 break; 5396 5397 case _VG_USERREQ__HG_POSIX_SEM_INIT_POST: /* sem_t*, unsigned long */ 5398 evh__HG_POSIX_SEM_INIT_POST( tid, (void*)args[1], args[2] ); 5399 break; 5400 5401 case _VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE: /* sem_t* */ 5402 evh__HG_POSIX_SEM_DESTROY_PRE( tid, (void*)args[1] ); 5403 break; 5404 5405 case _VG_USERREQ__HG_POSIX_SEM_POST_PRE: /* sem_t* */ 5406 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5407 evh__HG_POSIX_SEM_POST_PRE( tid, (void*)args[1] ); 5408 break; 5409 5410 case _VG_USERREQ__HG_POSIX_SEM_POST_POST: /* sem_t* */ 5411 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5412 break; 5413 5414 case _VG_USERREQ__HG_POSIX_SEM_WAIT_PRE: /* sem_t* */ 5415 HG_(thread_enter_synchr)(map_threads_maybe_lookup(tid)); 5416 break; 5417 5418 case _VG_USERREQ__HG_POSIX_SEM_WAIT_POST: /* sem_t*, long tookLock */ 5419 if (args[2] == True) 5420 evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] ); 5421 HG_(thread_leave_synchr)(map_threads_maybe_lookup(tid)); 5422 break; 5423 5424 case _VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE: 5425 /* pth_bar_t*, ulong count, ulong resizable */ 5426 evh__HG_PTHREAD_BARRIER_INIT_PRE( tid, (void*)args[1], 5427 args[2], args[3] ); 5428 break; 5429 5430 case _VG_USERREQ__HG_PTHREAD_BARRIER_RESIZE_PRE: 5431 /* pth_bar_t*, ulong newcount */ 5432 evh__HG_PTHREAD_BARRIER_RESIZE_PRE ( tid, (void*)args[1], 5433 args[2] ); 5434 break; 5435 5436 case _VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE: 5437 /* pth_bar_t* */ 5438 evh__HG_PTHREAD_BARRIER_WAIT_PRE( tid, (void*)args[1] ); 5439 break; 5440 5441 case _VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE: 5442 /* pth_bar_t* */ 5443 evh__HG_PTHREAD_BARRIER_DESTROY_PRE( tid, (void*)args[1] ); 5444 break; 5445 5446 case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE: 5447 /* pth_spinlock_t* */ 5448 evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( tid, (void*)args[1] ); 5449 break; 5450 5451 case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST: 5452 /* pth_spinlock_t* */ 5453 evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( tid, (void*)args[1] ); 5454 break; 5455 5456 case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE: 5457 /* pth_spinlock_t*, Word */ 5458 evh__HG_PTHREAD_SPIN_LOCK_PRE( tid, (void*)args[1], args[2] ); 5459 break; 5460 5461 case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST: 5462 /* pth_spinlock_t* */ 5463 evh__HG_PTHREAD_SPIN_LOCK_POST( tid, (void*)args[1] ); 5464 break; 5465 5466 case _VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE: 5467 /* pth_spinlock_t* */ 5468 evh__HG_PTHREAD_SPIN_DESTROY_PRE( tid, (void*)args[1] ); 5469 break; 5470 5471 case _VG_USERREQ__HG_CLIENTREQ_UNIMP: { 5472 /* HChar* who */ 5473 HChar* who = (HChar*)args[1]; 5474 HChar buf[50 + 50]; 5475 Thread* thr = map_threads_maybe_lookup( tid ); 5476 tl_assert( thr ); /* I must be mapped */ 5477 tl_assert( who ); 5478 tl_assert( VG_(strlen)(who) <= 50 ); 5479 VG_(sprintf)(buf, "Unimplemented client request macro \"%s\"", who ); 5480 /* record_error_Misc strdup's buf, so this is safe: */ 5481 HG_(record_error_Misc)( thr, buf ); 5482 break; 5483 } 5484 5485 case _VG_USERREQ__HG_USERSO_SEND_PRE: 5486 /* UWord arbitrary-SO-tag */ 5487 evh__HG_USERSO_SEND_PRE( tid, args[1] ); 5488 break; 5489 5490 case _VG_USERREQ__HG_USERSO_RECV_POST: 5491 /* UWord arbitrary-SO-tag */ 5492 evh__HG_USERSO_RECV_POST( tid, args[1] ); 5493 break; 5494 5495 case _VG_USERREQ__HG_USERSO_FORGET_ALL: 5496 /* UWord arbitrary-SO-tag */ 5497 evh__HG_USERSO_FORGET_ALL( tid, args[1] ); 5498 break; 5499 5500 case VG_USERREQ__GDB_MONITOR_COMMAND: { 5501 Bool handled = handle_gdb_monitor_command (tid, (HChar*)args[1]); 5502 if (handled) 5503 *ret = 1; 5504 else 5505 *ret = 0; 5506 return handled; 5507 } 5508 5509 case _VG_USERREQ__HG_PTHREAD_CREATE_BEGIN: { 5510 Thread *thr = map_threads_maybe_lookup(tid); 5511 if (HG_(clo_ignore_thread_creation)) { 5512 HG_(thread_enter_pthread_create)(thr); 5513 HG_(thread_enter_synchr)(thr); 5514 } 5515 break; 5516 } 5517 5518 case _VG_USERREQ__HG_PTHREAD_CREATE_END: { 5519 Thread *thr = map_threads_maybe_lookup(tid); 5520 if (HG_(clo_ignore_thread_creation)) { 5521 HG_(thread_leave_pthread_create)(thr); 5522 HG_(thread_leave_synchr)(thr); 5523 } 5524 break; 5525 } 5526 5527 case _VG_USERREQ__HG_PTHREAD_MUTEX_ACQUIRE_PRE: // pth_mx_t*, long tryLock 5528 evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, (void*)args[1], args[2] ); 5529 break; 5530 5531 case _VG_USERREQ__HG_PTHREAD_MUTEX_ACQUIRE_POST: // pth_mx_t* 5532 evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, (void*)args[1] ); 5533 break; 5534 5535 case _VG_USERREQ__HG_PTHREAD_RWLOCK_ACQUIRED: // void*, long isW 5536 evh__HG_PTHREAD_RWLOCK_LOCK_POST( tid, (void*)args[1], args[2] ); 5537 break; 5538 5539 case _VG_USERREQ__HG_PTHREAD_RWLOCK_RELEASED: // void* 5540 evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE( tid, (void*)args[1] ); 5541 break; 5542 5543 case _VG_USERREQ__HG_POSIX_SEM_RELEASED: /* sem_t* */ 5544 evh__HG_POSIX_SEM_POST_PRE( tid, (void*)args[1] ); 5545 break; 5546 5547 case _VG_USERREQ__HG_POSIX_SEM_ACQUIRED: /* sem_t* */ 5548 evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] ); 5549 break; 5550 5551 #if defined(VGO_solaris) 5552 case _VG_USERREQ__HG_RTLD_BIND_GUARD: 5553 evh__HG_RTLD_BIND_GUARD(tid, args[1]); 5554 break; 5555 5556 case _VG_USERREQ__HG_RTLD_BIND_CLEAR: 5557 evh__HG_RTLD_BIND_CLEAR(tid, args[1]); 5558 break; 5559 #endif /* VGO_solaris */ 5560 5561 default: 5562 /* Unhandled Helgrind client request! */ 5563 tl_assert2(0, "unhandled Helgrind client request 0x%lx", 5564 args[0]); 5565 } 5566 5567 return True; 5568 } 5569 5570 5571 /*----------------------------------------------------------------*/ 5572 /*--- Setup ---*/ 5573 /*----------------------------------------------------------------*/ 5574 5575 static Bool hg_process_cmd_line_option ( const HChar* arg ) 5576 { 5577 const HChar* tmp_str; 5578 5579 if VG_BOOL_CLO(arg, "--track-lockorders", 5580 HG_(clo_track_lockorders)) {} 5581 else if VG_BOOL_CLO(arg, "--cmp-race-err-addrs", 5582 HG_(clo_cmp_race_err_addrs)) {} 5583 5584 else if VG_XACT_CLO(arg, "--history-level=none", 5585 HG_(clo_history_level), 0); 5586 else if VG_XACT_CLO(arg, "--history-level=approx", 5587 HG_(clo_history_level), 1); 5588 else if VG_XACT_CLO(arg, "--history-level=full", 5589 HG_(clo_history_level), 2); 5590 5591 else if VG_BINT_CLO(arg, "--conflict-cache-size", 5592 HG_(clo_conflict_cache_size), 10*1000, 150*1000*1000) {} 5593 5594 /* "stuvwx" --> stuvwx (binary) */ 5595 else if VG_STR_CLO(arg, "--hg-sanity-flags", tmp_str) { 5596 Int j; 5597 5598 if (6 != VG_(strlen)(tmp_str)) { 5599 VG_(message)(Vg_UserMsg, 5600 "--hg-sanity-flags argument must have 6 digits\n"); 5601 return False; 5602 } 5603 for (j = 0; j < 6; j++) { 5604 if ('0' == tmp_str[j]) { /* do nothing */ } 5605 else if ('1' == tmp_str[j]) HG_(clo_sanity_flags) |= (1 << (6-1-j)); 5606 else { 5607 VG_(message)(Vg_UserMsg, "--hg-sanity-flags argument can " 5608 "only contain 0s and 1s\n"); 5609 return False; 5610 } 5611 } 5612 if (0) VG_(printf)("XXX sanity flags: 0x%lx\n", HG_(clo_sanity_flags)); 5613 } 5614 5615 else if VG_BOOL_CLO(arg, "--free-is-write", 5616 HG_(clo_free_is_write)) {} 5617 5618 else if VG_XACT_CLO(arg, "--vts-pruning=never", 5619 HG_(clo_vts_pruning), 0); 5620 else if VG_XACT_CLO(arg, "--vts-pruning=auto", 5621 HG_(clo_vts_pruning), 1); 5622 else if VG_XACT_CLO(arg, "--vts-pruning=always", 5623 HG_(clo_vts_pruning), 2); 5624 5625 else if VG_BOOL_CLO(arg, "--check-stack-refs", 5626 HG_(clo_check_stack_refs)) {} 5627 else if VG_BOOL_CLO(arg, "--ignore-thread-creation", 5628 HG_(clo_ignore_thread_creation)) {} 5629 5630 else 5631 return VG_(replacement_malloc_process_cmd_line_option)(arg); 5632 5633 return True; 5634 } 5635 5636 static void hg_print_usage ( void ) 5637 { 5638 VG_(printf)( 5639 " --free-is-write=no|yes treat heap frees as writes [no]\n" 5640 " --track-lockorders=no|yes show lock ordering errors? [yes]\n" 5641 " --history-level=none|approx|full [full]\n" 5642 " full: show both stack traces for a data race (can be very slow)\n" 5643 " approx: full trace for one thread, approx for the other (faster)\n" 5644 " none: only show trace for one thread in a race (fastest)\n" 5645 " --conflict-cache-size=N size of 'full' history cache [2000000]\n" 5646 " --check-stack-refs=no|yes race-check reads and writes on the\n" 5647 " main stack and thread stacks? [yes]\n" 5648 " --ignore-thread-creation=yes|no Ignore activities during thread\n" 5649 " creation [%s]\n", 5650 HG_(clo_ignore_thread_creation) ? "yes" : "no" 5651 ); 5652 } 5653 5654 static void hg_print_debug_usage ( void ) 5655 { 5656 VG_(printf)(" --cmp-race-err-addrs=no|yes are data addresses in " 5657 "race errors significant? [no]\n"); 5658 VG_(printf)(" --hg-sanity-flags=<XXXXXX> sanity check " 5659 " at events (X = 0|1) [000000]\n"); 5660 VG_(printf)(" --hg-sanity-flags values:\n"); 5661 VG_(printf)(" 010000 after changes to " 5662 "lock-order-acquisition-graph\n"); 5663 VG_(printf)(" 001000 at memory accesses (NB: not currently used)\n"); 5664 VG_(printf)(" 000100 at mem permission setting for " 5665 "ranges >= %d bytes\n", SCE_BIGRANGE_T); 5666 VG_(printf)(" 000010 at lock/unlock events\n"); 5667 VG_(printf)(" 000001 at thread create/join events\n"); 5668 VG_(printf)( 5669 " --vts-pruning=never|auto|always [auto]\n" 5670 " never: is never done (may cause big space leaks in Helgrind)\n" 5671 " auto: done just often enough to keep space usage under control\n" 5672 " always: done after every VTS GC (mostly just a big time waster)\n" 5673 ); 5674 } 5675 5676 static void hg_print_stats (void) 5677 { 5678 5679 if (1) { 5680 VG_(printf)("\n"); 5681 HG_(ppWSUstats)( univ_lsets, "univ_lsets" ); 5682 if (HG_(clo_track_lockorders)) { 5683 VG_(printf)("\n"); 5684 HG_(ppWSUstats)( univ_laog, "univ_laog" ); 5685 } 5686 } 5687 5688 //zz VG_(printf)("\n"); 5689 //zz VG_(printf)(" hbefore: %'10lu queries\n", stats__hbefore_queries); 5690 //zz VG_(printf)(" hbefore: %'10lu cache 0 hits\n", stats__hbefore_cache0s); 5691 //zz VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs); 5692 //zz VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches); 5693 //zz VG_(printf)(" hbefore: %'10lu of which slow\n", 5694 //zz stats__hbefore_gsearches - stats__hbefore_gsearchFs); 5695 //zz VG_(printf)(" hbefore: %'10lu stack high water mark\n", 5696 //zz stats__hbefore_stk_hwm); 5697 //zz VG_(printf)(" hbefore: %'10lu cache invals\n", stats__hbefore_invals); 5698 //zz VG_(printf)(" hbefore: %'10lu probes\n", stats__hbefore_probes); 5699 5700 VG_(printf)("\n"); 5701 VG_(printf)(" locksets: %'8d unique lock sets\n", 5702 (Int)HG_(cardinalityWSU)( univ_lsets )); 5703 if (HG_(clo_track_lockorders)) { 5704 VG_(printf)(" univ_laog: %'8d unique lock sets\n", 5705 (Int)HG_(cardinalityWSU)( univ_laog )); 5706 } 5707 5708 //VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n", 5709 // stats__ga_LL_adds, 5710 // (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) ); 5711 5712 VG_(printf)(" LockN-to-P map: %'8llu queries (%llu map size)\n", 5713 HG_(stats__LockN_to_P_queries), 5714 HG_(stats__LockN_to_P_get_map_size)() ); 5715 5716 VG_(printf)("client malloc-ed blocks: %'8u\n", 5717 VG_(HT_count_nodes)(hg_mallocmeta_table)); 5718 5719 VG_(printf)("string table map: %'8llu queries (%llu map size)\n", 5720 HG_(stats__string_table_queries), 5721 HG_(stats__string_table_get_map_size)() ); 5722 if (HG_(clo_track_lockorders)) { 5723 VG_(printf)(" LAOG: %'8d map size\n", 5724 (Int)(laog ? VG_(sizeFM)( laog ) : 0)); 5725 VG_(printf)(" LAOG exposition: %'8d map size\n", 5726 (Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0)); 5727 } 5728 5729 VG_(printf)(" locks: %'8lu acquires, " 5730 "%'lu releases\n", 5731 stats__lockN_acquires, 5732 stats__lockN_releases 5733 ); 5734 VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks); 5735 5736 VG_(printf)("\n"); 5737 libhb_shutdown(True); // This in fact only print stats. 5738 } 5739 5740 static void hg_fini ( Int exitcode ) 5741 { 5742 HG_(xtmemory_report) (VG_(clo_xtree_memory_file), True); 5743 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) { 5744 VG_(message)(Vg_UserMsg, 5745 "For counts of detected and suppressed errors, " 5746 "rerun with: -v\n"); 5747 } 5748 5749 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml) 5750 && HG_(clo_history_level) >= 2) { 5751 VG_(umsg)( 5752 "Use --history-level=approx or =none to gain increased speed, at\n" ); 5753 VG_(umsg)( 5754 "the cost of reduced accuracy of conflicting-access information\n"); 5755 } 5756 5757 if (SHOW_DATA_STRUCTURES) 5758 pp_everything( PP_ALL, "SK_(fini)" ); 5759 if (HG_(clo_sanity_flags)) 5760 all__sanity_check("SK_(fini)"); 5761 5762 if (VG_(clo_stats)) 5763 hg_print_stats(); 5764 } 5765 5766 /* FIXME: move these somewhere sane */ 5767 5768 static 5769 void for_libhb__get_stacktrace ( Thr* hbt, Addr* frames, UWord nRequest ) 5770 { 5771 Thread* thr; 5772 ThreadId tid; 5773 UWord nActual; 5774 tl_assert(hbt); 5775 thr = libhb_get_Thr_hgthread( hbt ); 5776 tl_assert(thr); 5777 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 5778 nActual = (UWord)VG_(get_StackTrace)( tid, frames, (UInt)nRequest, 5779 NULL, NULL, 0 ); 5780 tl_assert(nActual <= nRequest); 5781 for (; nActual < nRequest; nActual++) 5782 frames[nActual] = 0; 5783 } 5784 5785 static 5786 ExeContext* for_libhb__get_EC ( Thr* hbt ) 5787 { 5788 Thread* thr; 5789 ThreadId tid; 5790 ExeContext* ec; 5791 tl_assert(hbt); 5792 thr = libhb_get_Thr_hgthread( hbt ); 5793 tl_assert(thr); 5794 tid = map_threads_maybe_reverse_lookup_SLOW(thr); 5795 /* this will assert if tid is invalid */ 5796 ec = VG_(record_ExeContext)( tid, 0 ); 5797 return ec; 5798 } 5799 5800 5801 static void hg_post_clo_init ( void ) 5802 { 5803 Thr* hbthr_root; 5804 5805 ///////////////////////////////////////////// 5806 hbthr_root = libhb_init( for_libhb__get_stacktrace, 5807 for_libhb__get_EC ); 5808 ///////////////////////////////////////////// 5809 5810 5811 if (HG_(clo_track_lockorders)) 5812 laog__init(); 5813 5814 initialise_data_structures(hbthr_root); 5815 if (VG_(clo_xtree_memory) == Vg_XTMemory_Full) 5816 // Activate full xtree memory profiling. 5817 VG_(XTMemory_Full_init)(VG_(XT_filter_1top_and_maybe_below_main)); 5818 } 5819 5820 static void hg_info_location (Addr a) 5821 { 5822 (void) HG_(get_and_pp_addrdescr) (a); 5823 } 5824 5825 static void hg_pre_clo_init ( void ) 5826 { 5827 VG_(details_name) ("Helgrind"); 5828 VG_(details_version) (NULL); 5829 VG_(details_description) ("a thread error detector"); 5830 VG_(details_copyright_author)( 5831 "Copyright (C) 2007-2017, and GNU GPL'd, by OpenWorks LLP et al."); 5832 VG_(details_bug_reports_to) (VG_BUGS_TO); 5833 VG_(details_avg_translation_sizeB) ( 320 ); 5834 5835 VG_(basic_tool_funcs) (hg_post_clo_init, 5836 hg_instrument, 5837 hg_fini); 5838 5839 VG_(needs_core_errors) (); 5840 VG_(needs_tool_errors) (HG_(eq_Error), 5841 HG_(before_pp_Error), 5842 HG_(pp_Error), 5843 False,/*show TIDs for errors*/ 5844 HG_(update_extra), 5845 HG_(recognised_suppression), 5846 HG_(read_extra_suppression_info), 5847 HG_(error_matches_suppression), 5848 HG_(get_error_name), 5849 HG_(get_extra_suppression_info), 5850 HG_(print_extra_suppression_use), 5851 HG_(update_extra_suppression_use)); 5852 5853 VG_(needs_xml_output) (); 5854 5855 VG_(needs_command_line_options)(hg_process_cmd_line_option, 5856 hg_print_usage, 5857 hg_print_debug_usage); 5858 VG_(needs_client_requests) (hg_handle_client_request); 5859 5860 // FIXME? 5861 //VG_(needs_sanity_checks) (hg_cheap_sanity_check, 5862 // hg_expensive_sanity_check); 5863 5864 VG_(needs_print_stats) (hg_print_stats); 5865 VG_(needs_info_location) (hg_info_location); 5866 5867 VG_(needs_malloc_replacement) (hg_cli__malloc, 5868 hg_cli____builtin_new, 5869 hg_cli____builtin_vec_new, 5870 hg_cli__memalign, 5871 hg_cli__calloc, 5872 hg_cli__free, 5873 hg_cli____builtin_delete, 5874 hg_cli____builtin_vec_delete, 5875 hg_cli__realloc, 5876 hg_cli_malloc_usable_size, 5877 HG_CLI__DEFAULT_MALLOC_REDZONE_SZB ); 5878 5879 /* 21 Dec 08: disabled this; it mostly causes H to start more 5880 slowly and use significantly more memory, without very often 5881 providing useful results. The user can request to load this 5882 information manually with --read-var-info=yes. */ 5883 if (0) VG_(needs_var_info)(); /* optional */ 5884 5885 VG_(track_new_mem_startup) ( evh__new_mem_w_perms ); 5886 VG_(track_new_mem_stack_signal)( evh__new_mem_w_tid ); 5887 VG_(track_new_mem_brk) ( evh__new_mem_w_tid ); 5888 VG_(track_new_mem_mmap) ( evh__new_mem_w_perms ); 5889 VG_(track_new_mem_stack) ( evh__new_mem_stack ); 5890 5891 // FIXME: surely this isn't thread-aware 5892 VG_(track_copy_mem_remap) ( evh__copy_mem ); 5893 5894 VG_(track_change_mem_mprotect) ( evh__set_perms ); 5895 5896 VG_(track_die_mem_stack_signal)( evh__die_mem ); 5897 VG_(track_die_mem_brk) ( evh__die_mem_munmap ); 5898 VG_(track_die_mem_munmap) ( evh__die_mem_munmap ); 5899 5900 /* evh__die_mem calls at the end libhb_srange_noaccess_NoFX 5901 which has no effect. We do not use VG_(track_die_mem_stack), 5902 as this would be an expensive way to do nothing. */ 5903 // VG_(track_die_mem_stack) ( evh__die_mem ); 5904 5905 // FIXME: what is this for? 5906 VG_(track_ban_mem_stack) (NULL); 5907 5908 VG_(track_pre_mem_read) ( evh__pre_mem_read ); 5909 VG_(track_pre_mem_read_asciiz) ( evh__pre_mem_read_asciiz ); 5910 VG_(track_pre_mem_write) ( evh__pre_mem_write ); 5911 VG_(track_post_mem_write) (NULL); 5912 5913 ///////////////// 5914 5915 VG_(track_pre_thread_ll_create)( evh__pre_thread_ll_create ); 5916 VG_(track_pre_thread_ll_exit) ( evh__pre_thread_ll_exit ); 5917 5918 VG_(track_start_client_code)( evh__start_client_code ); 5919 VG_(track_stop_client_code)( evh__stop_client_code ); 5920 5921 /* Ensure that requirements for "dodgy C-as-C++ style inheritance" 5922 as described in comments at the top of pub_tool_hashtable.h, are 5923 met. Blargh. */ 5924 tl_assert( sizeof(void*) == sizeof(struct _MallocMeta*) ); 5925 tl_assert( sizeof(UWord) == sizeof(Addr) ); 5926 hg_mallocmeta_table 5927 = VG_(HT_construct)( "hg_malloc_metadata_table" ); 5928 5929 MallocMeta_poolalloc = VG_(newPA) ( sizeof(MallocMeta), 5930 1000, 5931 HG_(zalloc), 5932 "hg_malloc_metadata_pool", 5933 HG_(free)); 5934 5935 // add a callback to clean up on (threaded) fork. 5936 VG_(atfork)(NULL/*pre*/, NULL/*parent*/, evh__atfork_child/*child*/); 5937 } 5938 5939 VG_DETERMINE_INTERFACE_VERSION(hg_pre_clo_init) 5940 5941 /*--------------------------------------------------------------------*/ 5942 /*--- end hg_main.c ---*/ 5943 /*--------------------------------------------------------------------*/ 5944