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