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