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