• 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-2011 OpenWorks LLP
12       info@open-works.co.uk
13 
14    Copyright (C) 2007-2011 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__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_delete(void * cond)2142 static void map_cond_to_CVInfo_delete ( void* cond ) {
2143    UWord keyW, valW;
2144    map_cond_to_CVInfo_INIT();
2145    if (VG_(delFromFM)( map_cond_to_CVInfo, &keyW, &valW, (UWord)cond )) {
2146       CVInfo* cvi = (CVInfo*)valW;
2147       tl_assert(keyW == (UWord)cond);
2148       tl_assert(cvi);
2149       tl_assert(cvi->so);
2150       libhb_so_dealloc(cvi->so);
2151       cvi->mx_ga = 0;
2152       HG_(free)(cvi);
2153    }
2154 }
2155 
evh__HG_PTHREAD_COND_SIGNAL_PRE(ThreadId tid,void * cond)2156 static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond )
2157 {
2158    /* 'tid' has signalled on 'cond'.  As per the comment above, bind
2159       cond to a SO if it is not already so bound, and 'send' on the
2160       SO.  This is later used by other thread(s) which successfully
2161       exit from a pthread_cond_wait on the same cv; then they 'recv'
2162       from the SO, thereby acquiring a dependency on this signalling
2163       event. */
2164    Thread*   thr;
2165    CVInfo*   cvi;
2166    //Lock*     lk;
2167 
2168    if (SHOW_EVENTS >= 1)
2169       VG_(printf)("evh__HG_PTHREAD_COND_SIGNAL_PRE(ctid=%d, cond=%p)\n",
2170                   (Int)tid, (void*)cond );
2171 
2172    thr = map_threads_maybe_lookup( tid );
2173    tl_assert(thr); /* cannot fail - Thread* must already exist */
2174 
2175    cvi = map_cond_to_CVInfo_lookup_or_alloc( cond );
2176    tl_assert(cvi);
2177    tl_assert(cvi->so);
2178 
2179    // error-if: mutex is bogus
2180    // error-if: mutex is not locked
2181    // Hmm.  POSIX doesn't actually say that it's an error to call
2182    // pthread_cond_signal with the associated mutex being unlocked.
2183    // Although it does say that it should be "if consistent scheduling
2184    // is desired."  For that reason, print "dubious" if the lock isn't
2185    // held by any thread.  Skip the "dubious" if it is held by some
2186    // other thread; that sounds straight-out wrong.
2187    //
2188    // Anybody who writes code that signals on a CV without holding
2189    // the associated MX needs to be shipped off to a lunatic asylum
2190    // ASAP, even though POSIX doesn't actually declare such behaviour
2191    // illegal -- it makes code extremely difficult to understand/
2192    // reason about.  In particular it puts the signalling thread in
2193    // a situation where it is racing against the released waiter
2194    // as soon as the signalling is done, and so there needs to be
2195    // some auxiliary synchronisation mechanism in the program that
2196    // makes this safe -- or the race(s) need to be harmless, or
2197    // probably nonexistent.
2198    //
2199    if (1) {
2200       Lock* lk = NULL;
2201       if (cvi->mx_ga != 0) {
2202          lk = map_locks_maybe_lookup( (Addr)cvi->mx_ga );
2203       }
2204       /* note: lk could be NULL.  Be careful. */
2205       if (lk) {
2206          if (lk->kind == LK_rdwr) {
2207             HG_(record_error_Misc)(thr,
2208                "pthread_cond_{signal,broadcast}: associated lock is a rwlock");
2209          }
2210          if (lk->heldBy == NULL) {
2211             HG_(record_error_Misc)(thr,
2212                "pthread_cond_{signal,broadcast}: dubious: "
2213                "associated lock is not held by any thread");
2214          }
2215          if (lk->heldBy != NULL && 0 == VG_(elemBag)(lk->heldBy, (Word)thr)) {
2216             HG_(record_error_Misc)(thr,
2217                "pthread_cond_{signal,broadcast}: "
2218                "associated lock is not held by calling thread");
2219          }
2220       } else {
2221          /* Couldn't even find the damn thing. */
2222          // But actually .. that's not necessarily an error.  We don't
2223          // know the (CV,MX) binding until a pthread_cond_wait or bcast
2224          // shows us what it is, and if that may not have happened yet.
2225          // So just keep quiet in this circumstance.
2226          //HG_(record_error_Misc)( thr,
2227          //   "pthread_cond_{signal,broadcast}: "
2228          //   "no or invalid mutex associated with cond");
2229       }
2230    }
2231 
2232    libhb_so_send( thr->hbthr, cvi->so, True/*strong_send*/ );
2233 }
2234 
2235 /* returns True if it reckons 'mutex' is valid and held by this
2236    thread, else False */
evh__HG_PTHREAD_COND_WAIT_PRE(ThreadId tid,void * cond,void * mutex)2237 static Bool evh__HG_PTHREAD_COND_WAIT_PRE ( ThreadId tid,
2238                                             void* cond, void* mutex )
2239 {
2240    Thread* thr;
2241    Lock*   lk;
2242    Bool    lk_valid = True;
2243    CVInfo* cvi;
2244 
2245    if (SHOW_EVENTS >= 1)
2246       VG_(printf)("evh__hg_PTHREAD_COND_WAIT_PRE"
2247                   "(ctid=%d, cond=%p, mutex=%p)\n",
2248                   (Int)tid, (void*)cond, (void*)mutex );
2249 
2250    thr = map_threads_maybe_lookup( tid );
2251    tl_assert(thr); /* cannot fail - Thread* must already exist */
2252 
2253    lk = map_locks_maybe_lookup( (Addr)mutex );
2254 
2255    /* Check for stupid mutex arguments.  There are various ways to be
2256       a bozo.  Only complain once, though, even if more than one thing
2257       is wrong. */
2258    if (lk == NULL) {
2259       lk_valid = False;
2260       HG_(record_error_Misc)(
2261          thr,
2262          "pthread_cond_{timed}wait called with invalid mutex" );
2263    } else {
2264       tl_assert( HG_(is_sane_LockN)(lk) );
2265       if (lk->kind == LK_rdwr) {
2266          lk_valid = False;
2267          HG_(record_error_Misc)(
2268             thr, "pthread_cond_{timed}wait called with mutex "
2269                  "of type pthread_rwlock_t*" );
2270       } else
2271          if (lk->heldBy == NULL) {
2272          lk_valid = False;
2273          HG_(record_error_Misc)(
2274             thr, "pthread_cond_{timed}wait called with un-held mutex");
2275       } else
2276       if (lk->heldBy != NULL
2277           && VG_(elemBag)( lk->heldBy, (Word)thr ) == 0) {
2278          lk_valid = False;
2279          HG_(record_error_Misc)(
2280             thr, "pthread_cond_{timed}wait called with mutex "
2281                  "held by a different thread" );
2282       }
2283    }
2284 
2285    // error-if: cond is also associated with a different mutex
2286    cvi = map_cond_to_CVInfo_lookup_or_alloc(cond);
2287    tl_assert(cvi);
2288    tl_assert(cvi->so);
2289    if (cvi->nWaiters == 0) {
2290       /* form initial (CV,MX) binding */
2291       cvi->mx_ga = mutex;
2292    }
2293    else /* check existing (CV,MX) binding */
2294    if (cvi->mx_ga != mutex) {
2295       HG_(record_error_Misc)(
2296          thr, "pthread_cond_{timed}wait: cond is associated "
2297               "with a different mutex");
2298    }
2299    cvi->nWaiters++;
2300 
2301    return lk_valid;
2302 }
2303 
evh__HG_PTHREAD_COND_WAIT_POST(ThreadId tid,void * cond,void * mutex)2304 static void evh__HG_PTHREAD_COND_WAIT_POST ( ThreadId tid,
2305                                              void* cond, void* mutex )
2306 {
2307    /* A pthread_cond_wait(cond, mutex) completed successfully.  Find
2308       the SO for this cond, and 'recv' from it so as to acquire a
2309       dependency edge back to the signaller/broadcaster. */
2310    Thread* thr;
2311    CVInfo* cvi;
2312 
2313    if (SHOW_EVENTS >= 1)
2314       VG_(printf)("evh__HG_PTHREAD_COND_WAIT_POST"
2315                   "(ctid=%d, cond=%p, mutex=%p)\n",
2316                   (Int)tid, (void*)cond, (void*)mutex );
2317 
2318    thr = map_threads_maybe_lookup( tid );
2319    tl_assert(thr); /* cannot fail - Thread* must already exist */
2320 
2321    // error-if: cond is also associated with a different mutex
2322 
2323    cvi = map_cond_to_CVInfo_lookup_or_alloc( cond );
2324    tl_assert(cvi);
2325    tl_assert(cvi->so);
2326    tl_assert(cvi->nWaiters > 0);
2327 
2328    if (!libhb_so_everSent(cvi->so)) {
2329       /* Hmm.  How can a wait on 'cond' succeed if nobody signalled
2330          it?  If this happened it would surely be a bug in the threads
2331          library.  Or one of those fabled "spurious wakeups". */
2332       HG_(record_error_Misc)( thr, "Bug in libpthread: pthread_cond_wait "
2333                                    "succeeded"
2334                                    " without prior pthread_cond_post");
2335    }
2336 
2337    /* anyway, acquire a dependency on it. */
2338    libhb_so_recv( thr->hbthr, cvi->so, True/*strong_recv*/ );
2339 
2340    cvi->nWaiters--;
2341 }
2342 
evh__HG_PTHREAD_COND_DESTROY_PRE(ThreadId tid,void * cond)2343 static void evh__HG_PTHREAD_COND_DESTROY_PRE ( ThreadId tid,
2344                                                void* cond )
2345 {
2346    /* Deal with destroy events.  The only purpose is to free storage
2347       associated with the CV, so as to avoid any possible resource
2348       leaks. */
2349    if (SHOW_EVENTS >= 1)
2350       VG_(printf)("evh__HG_PTHREAD_COND_DESTROY_PRE"
2351                   "(ctid=%d, cond=%p)\n",
2352                   (Int)tid, (void*)cond );
2353 
2354    map_cond_to_CVInfo_delete( cond );
2355 }
2356 
2357 
2358 /* ------------------------------------------------------- */
2359 /* -------------- events to do with rwlocks -------------- */
2360 /* ------------------------------------------------------- */
2361 
2362 /* EXPOSITION only */
2363 static
evh__HG_PTHREAD_RWLOCK_INIT_POST(ThreadId tid,void * rwl)2364 void evh__HG_PTHREAD_RWLOCK_INIT_POST( ThreadId tid, void* rwl )
2365 {
2366    if (SHOW_EVENTS >= 1)
2367       VG_(printf)("evh__hg_PTHREAD_RWLOCK_INIT_POST(ctid=%d, %p)\n",
2368                   (Int)tid, (void*)rwl );
2369    map_locks_lookup_or_create( LK_rdwr, (Addr)rwl, tid );
2370    if (HG_(clo_sanity_flags) & SCE_LOCKS)
2371       all__sanity_check("evh__hg_PTHREAD_RWLOCK_INIT_POST");
2372 }
2373 
2374 static
evh__HG_PTHREAD_RWLOCK_DESTROY_PRE(ThreadId tid,void * rwl)2375 void evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( ThreadId tid, void* rwl )
2376 {
2377    Thread* thr;
2378    Lock*   lk;
2379    if (SHOW_EVENTS >= 1)
2380       VG_(printf)("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE(ctid=%d, %p)\n",
2381                   (Int)tid, (void*)rwl );
2382 
2383    thr = map_threads_maybe_lookup( tid );
2384    /* cannot fail - Thread* must already exist */
2385    tl_assert( HG_(is_sane_Thread)(thr) );
2386 
2387    lk = map_locks_maybe_lookup( (Addr)rwl );
2388 
2389    if (lk == NULL || lk->kind != LK_rdwr) {
2390       HG_(record_error_Misc)(
2391          thr, "pthread_rwlock_destroy with invalid argument" );
2392    }
2393 
2394    if (lk) {
2395       tl_assert( HG_(is_sane_LockN)(lk) );
2396       tl_assert( lk->guestaddr == (Addr)rwl );
2397       if (lk->heldBy) {
2398          /* Basically act like we unlocked the lock */
2399          HG_(record_error_Misc)(
2400             thr, "pthread_rwlock_destroy of a locked mutex" );
2401          /* remove lock from locksets of all owning threads */
2402          remove_Lock_from_locksets_of_all_owning_Threads( lk );
2403          VG_(deleteBag)( lk->heldBy );
2404          lk->heldBy = NULL;
2405          lk->heldW = False;
2406          lk->acquired_at = NULL;
2407       }
2408       tl_assert( !lk->heldBy );
2409       tl_assert( HG_(is_sane_LockN)(lk) );
2410 
2411       if (HG_(clo_track_lockorders))
2412          laog__handle_one_lock_deletion(lk);
2413       map_locks_delete( lk->guestaddr );
2414       del_LockN( lk );
2415    }
2416 
2417    if (HG_(clo_sanity_flags) & SCE_LOCKS)
2418       all__sanity_check("evh__hg_PTHREAD_RWLOCK_DESTROY_PRE");
2419 }
2420 
2421 static
evh__HG_PTHREAD_RWLOCK_LOCK_PRE(ThreadId tid,void * rwl,Word isW,Word isTryLock)2422 void evh__HG_PTHREAD_RWLOCK_LOCK_PRE ( ThreadId tid,
2423                                        void* rwl,
2424                                        Word isW, Word isTryLock )
2425 {
2426    /* Just check the rwl is sane; nothing else to do. */
2427    // 'rwl' may be invalid - not checked by wrapper
2428    Thread* thr;
2429    Lock*   lk;
2430    if (SHOW_EVENTS >= 1)
2431       VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_PRE(ctid=%d, isW=%d, %p)\n",
2432                   (Int)tid, (Int)isW, (void*)rwl );
2433 
2434    tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */
2435    tl_assert(isTryLock == 0 || isTryLock == 1); /* assured us by wrapper */
2436    thr = map_threads_maybe_lookup( tid );
2437    tl_assert(thr); /* cannot fail - Thread* must already exist */
2438 
2439    lk = map_locks_maybe_lookup( (Addr)rwl );
2440    if ( lk
2441         && (lk->kind == LK_nonRec || lk->kind == LK_mbRec) ) {
2442       /* Wrong kind of lock.  Duh.  */
2443       HG_(record_error_Misc)(
2444          thr, "pthread_rwlock_{rd,rw}lock with a "
2445               "pthread_mutex_t* argument " );
2446    }
2447 }
2448 
2449 static
evh__HG_PTHREAD_RWLOCK_LOCK_POST(ThreadId tid,void * rwl,Word isW)2450 void evh__HG_PTHREAD_RWLOCK_LOCK_POST ( ThreadId tid, void* rwl, Word isW )
2451 {
2452    // only called if the real library call succeeded - so mutex is sane
2453    Thread* thr;
2454    if (SHOW_EVENTS >= 1)
2455       VG_(printf)("evh__hg_PTHREAD_RWLOCK_LOCK_POST(ctid=%d, isW=%d, %p)\n",
2456                   (Int)tid, (Int)isW, (void*)rwl );
2457 
2458    tl_assert(isW == 0 || isW == 1); /* assured us by wrapper */
2459    thr = map_threads_maybe_lookup( tid );
2460    tl_assert(thr); /* cannot fail - Thread* must already exist */
2461 
2462    (isW ? evhH__post_thread_w_acquires_lock
2463         : evhH__post_thread_r_acquires_lock)(
2464       thr,
2465       LK_rdwr, /* if not known, create new lock with this LockKind */
2466       (Addr)rwl
2467    );
2468 }
2469 
evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ThreadId tid,void * rwl)2470 static void evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE ( ThreadId tid, void* rwl )
2471 {
2472    // 'rwl' may be invalid - not checked by wrapper
2473    Thread* thr;
2474    if (SHOW_EVENTS >= 1)
2475       VG_(printf)("evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE(ctid=%d, rwl=%p)\n",
2476                   (Int)tid, (void*)rwl );
2477 
2478    thr = map_threads_maybe_lookup( tid );
2479    tl_assert(thr); /* cannot fail - Thread* must already exist */
2480 
2481    evhH__pre_thread_releases_lock( thr, (Addr)rwl, True/*isRDWR*/ );
2482 }
2483 
evh__HG_PTHREAD_RWLOCK_UNLOCK_POST(ThreadId tid,void * rwl)2484 static void evh__HG_PTHREAD_RWLOCK_UNLOCK_POST ( ThreadId tid, void* rwl )
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_UNLOCK_POST(ctid=%d, rwl=%p)\n",
2490                   (Int)tid, (void*)rwl );
2491    thr = map_threads_maybe_lookup( tid );
2492    tl_assert(thr); /* cannot fail - Thread* must already exist */
2493 
2494    // anything we should do here?
2495 }
2496 
2497 
2498 /* ---------------------------------------------------------- */
2499 /* -------------- events to do with semaphores -------------- */
2500 /* ---------------------------------------------------------- */
2501 
2502 /* This is similar to but not identical to the handling for condition
2503    variables. */
2504 
2505 /* For each semaphore, we maintain a stack of SOs.  When a 'post'
2506    operation is done on a semaphore (unlocking, essentially), a new SO
2507    is created for the posting thread, the posting thread does a strong
2508    send to it (which merely installs the posting thread's VC in the
2509    SO), and the SO is pushed on the semaphore's stack.
2510 
2511    Later, when a (probably different) thread completes 'wait' on the
2512    semaphore, we pop a SO off the semaphore's stack (which should be
2513    nonempty), and do a strong recv from it.  This mechanism creates
2514    dependencies between posters and waiters of the semaphore.
2515 
2516    It may not be necessary to use a stack - perhaps a bag of SOs would
2517    do.  But we do need to keep track of how many unused-up posts have
2518    happened for the semaphore.
2519 
2520    Imagine T1 and T2 both post once on a semaphore S, and T3 waits
2521    twice on S.  T3 cannot complete its waits without both T1 and T2
2522    posting.  The above mechanism will ensure that T3 acquires
2523    dependencies on both T1 and T2.
2524 
2525    When a semaphore is initialised with value N, we do as if we'd
2526    posted N times on the semaphore: basically create N SOs and do a
2527    strong send to all of then.  This allows up to N waits on the
2528    semaphore to acquire a dependency on the initialisation point,
2529    which AFAICS is the correct behaviour.
2530 
2531    We don't emit an error for DESTROY_PRE on a semaphore we don't know
2532    about.  We should.
2533 */
2534 
2535 /* sem_t* -> XArray* SO* */
2536 static WordFM* map_sem_to_SO_stack = NULL;
2537 
map_sem_to_SO_stack_INIT(void)2538 static void map_sem_to_SO_stack_INIT ( void ) {
2539    if (map_sem_to_SO_stack == NULL) {
2540       map_sem_to_SO_stack = VG_(newFM)( HG_(zalloc), "hg.mstSs.1",
2541                                         HG_(free), NULL );
2542       tl_assert(map_sem_to_SO_stack != NULL);
2543    }
2544 }
2545 
push_SO_for_sem(void * sem,SO * so)2546 static void push_SO_for_sem ( void* sem, SO* so ) {
2547    UWord   keyW;
2548    XArray* xa;
2549    tl_assert(so);
2550    map_sem_to_SO_stack_INIT();
2551    if (VG_(lookupFM)( map_sem_to_SO_stack,
2552                       &keyW, (UWord*)&xa, (UWord)sem )) {
2553       tl_assert(keyW == (UWord)sem);
2554       tl_assert(xa);
2555       VG_(addToXA)( xa, &so );
2556    } else {
2557      xa = VG_(newXA)( HG_(zalloc), "hg.pSfs.1", HG_(free), sizeof(SO*) );
2558       VG_(addToXA)( xa, &so );
2559       VG_(addToFM)( map_sem_to_SO_stack, (Word)sem, (Word)xa );
2560    }
2561 }
2562 
mb_pop_SO_for_sem(void * sem)2563 static SO* mb_pop_SO_for_sem ( void* sem ) {
2564    UWord    keyW;
2565    XArray*  xa;
2566    SO* so;
2567    map_sem_to_SO_stack_INIT();
2568    if (VG_(lookupFM)( map_sem_to_SO_stack,
2569                       &keyW, (UWord*)&xa, (UWord)sem )) {
2570       /* xa is the stack for this semaphore. */
2571       Word sz;
2572       tl_assert(keyW == (UWord)sem);
2573       sz = VG_(sizeXA)( xa );
2574       tl_assert(sz >= 0);
2575       if (sz == 0)
2576          return NULL; /* odd, the stack is empty */
2577       so = *(SO**)VG_(indexXA)( xa, sz-1 );
2578       tl_assert(so);
2579       VG_(dropTailXA)( xa, 1 );
2580       return so;
2581    } else {
2582       /* hmm, that's odd.  No stack for this semaphore. */
2583       return NULL;
2584    }
2585 }
2586 
evh__HG_POSIX_SEM_DESTROY_PRE(ThreadId tid,void * sem)2587 static void evh__HG_POSIX_SEM_DESTROY_PRE ( ThreadId tid, void* sem )
2588 {
2589    UWord keyW, valW;
2590    SO*   so;
2591 
2592    if (SHOW_EVENTS >= 1)
2593       VG_(printf)("evh__HG_POSIX_SEM_DESTROY_PRE(ctid=%d, sem=%p)\n",
2594                   (Int)tid, (void*)sem );
2595 
2596    map_sem_to_SO_stack_INIT();
2597 
2598    /* Empty out the semaphore's SO stack.  This way of doing it is
2599       stupid, but at least it's easy. */
2600    while (1) {
2601       so = mb_pop_SO_for_sem( sem );
2602       if (!so) break;
2603       libhb_so_dealloc(so);
2604    }
2605 
2606    if (VG_(delFromFM)( map_sem_to_SO_stack, &keyW, &valW, (UWord)sem )) {
2607       XArray* xa = (XArray*)valW;
2608       tl_assert(keyW == (UWord)sem);
2609       tl_assert(xa);
2610       tl_assert(VG_(sizeXA)(xa) == 0); /* preceding loop just emptied it */
2611       VG_(deleteXA)(xa);
2612    }
2613 }
2614 
2615 static
evh__HG_POSIX_SEM_INIT_POST(ThreadId tid,void * sem,UWord value)2616 void evh__HG_POSIX_SEM_INIT_POST ( ThreadId tid, void* sem, UWord value )
2617 {
2618    SO*     so;
2619    Thread* thr;
2620 
2621    if (SHOW_EVENTS >= 1)
2622       VG_(printf)("evh__HG_POSIX_SEM_INIT_POST(ctid=%d, sem=%p, value=%lu)\n",
2623                   (Int)tid, (void*)sem, value );
2624 
2625    thr = map_threads_maybe_lookup( tid );
2626    tl_assert(thr); /* cannot fail - Thread* must already exist */
2627 
2628    /* Empty out the semaphore's SO stack.  This way of doing it is
2629       stupid, but at least it's easy. */
2630    while (1) {
2631       so = mb_pop_SO_for_sem( sem );
2632       if (!so) break;
2633       libhb_so_dealloc(so);
2634    }
2635 
2636    /* If we don't do this check, the following while loop runs us out
2637       of memory for stupid initial values of 'value'. */
2638    if (value > 10000) {
2639       HG_(record_error_Misc)(
2640          thr, "sem_init: initial value exceeds 10000; using 10000" );
2641       value = 10000;
2642    }
2643 
2644    /* Now create 'valid' new SOs for the thread, do a strong send to
2645       each of them, and push them all on the stack. */
2646    for (; value > 0; value--) {
2647       Thr* hbthr = thr->hbthr;
2648       tl_assert(hbthr);
2649 
2650       so = libhb_so_alloc();
2651       libhb_so_send( hbthr, so, True/*strong send*/ );
2652       push_SO_for_sem( sem, so );
2653    }
2654 }
2655 
evh__HG_POSIX_SEM_POST_PRE(ThreadId tid,void * sem)2656 static void evh__HG_POSIX_SEM_POST_PRE ( ThreadId tid, void* sem )
2657 {
2658    /* 'tid' has posted on 'sem'.  Create a new SO, do a strong send to
2659       it (iow, write our VC into it, then tick ours), and push the SO
2660       on on a stack of SOs associated with 'sem'.  This is later used
2661       by other thread(s) which successfully exit from a sem_wait on
2662       the same sem; by doing a strong recv from SOs popped of the
2663       stack, they acquire dependencies on the posting thread
2664       segment(s). */
2665 
2666    Thread* thr;
2667    SO*     so;
2668    Thr*    hbthr;
2669 
2670    if (SHOW_EVENTS >= 1)
2671       VG_(printf)("evh__HG_POSIX_SEM_POST_PRE(ctid=%d, sem=%p)\n",
2672                   (Int)tid, (void*)sem );
2673 
2674    thr = map_threads_maybe_lookup( tid );
2675    tl_assert(thr); /* cannot fail - Thread* must already exist */
2676 
2677    // error-if: sem is bogus
2678 
2679    hbthr = thr->hbthr;
2680    tl_assert(hbthr);
2681 
2682    so = libhb_so_alloc();
2683    libhb_so_send( hbthr, so, True/*strong send*/ );
2684    push_SO_for_sem( sem, so );
2685 }
2686 
evh__HG_POSIX_SEM_WAIT_POST(ThreadId tid,void * sem)2687 static void evh__HG_POSIX_SEM_WAIT_POST ( ThreadId tid, void* sem )
2688 {
2689    /* A sem_wait(sem) completed successfully.  Pop the posting-SO for
2690       the 'sem' from this semaphore's SO-stack, and do a strong recv
2691       from it.  This creates a dependency back to one of the post-ers
2692       for the semaphore. */
2693 
2694    Thread* thr;
2695    SO*     so;
2696    Thr*    hbthr;
2697 
2698    if (SHOW_EVENTS >= 1)
2699       VG_(printf)("evh__HG_POSIX_SEM_WAIT_POST(ctid=%d, sem=%p)\n",
2700                   (Int)tid, (void*)sem );
2701 
2702    thr = map_threads_maybe_lookup( tid );
2703    tl_assert(thr); /* cannot fail - Thread* must already exist */
2704 
2705    // error-if: sem is bogus
2706 
2707    so = mb_pop_SO_for_sem( sem );
2708 
2709    if (so) {
2710       hbthr = thr->hbthr;
2711       tl_assert(hbthr);
2712 
2713       libhb_so_recv( hbthr, so, True/*strong recv*/ );
2714       libhb_so_dealloc(so);
2715    } else {
2716       /* Hmm.  How can a wait on 'sem' succeed if nobody posted to it?
2717          If this happened it would surely be a bug in the threads
2718          library. */
2719       HG_(record_error_Misc)(
2720          thr, "Bug in libpthread: sem_wait succeeded on"
2721               " semaphore without prior sem_post");
2722    }
2723 }
2724 
2725 
2726 /* -------------------------------------------------------- */
2727 /* -------------- events to do with barriers -------------- */
2728 /* -------------------------------------------------------- */
2729 
2730 typedef
2731    struct {
2732       Bool    initted; /* has it yet been initted by guest? */
2733       Bool    resizable; /* is resizing allowed? */
2734       UWord   size;    /* declared size */
2735       XArray* waiting; /* XA of Thread*.  # present is 0 .. .size */
2736    }
2737    Bar;
2738 
new_Bar(void)2739 static Bar* new_Bar ( void ) {
2740    Bar* bar = HG_(zalloc)( "hg.nB.1 (new_Bar)", sizeof(Bar) );
2741    tl_assert(bar);
2742    /* all fields are zero */
2743    tl_assert(bar->initted == False);
2744    return bar;
2745 }
2746 
delete_Bar(Bar * bar)2747 static void delete_Bar ( Bar* bar ) {
2748    tl_assert(bar);
2749    if (bar->waiting)
2750       VG_(deleteXA)(bar->waiting);
2751    HG_(free)(bar);
2752 }
2753 
2754 /* A mapping which stores auxiliary data for barriers. */
2755 
2756 /* pthread_barrier_t* -> Bar* */
2757 static WordFM* map_barrier_to_Bar = NULL;
2758 
map_barrier_to_Bar_INIT(void)2759 static void map_barrier_to_Bar_INIT ( void ) {
2760    if (UNLIKELY(map_barrier_to_Bar == NULL)) {
2761       map_barrier_to_Bar = VG_(newFM)( HG_(zalloc),
2762                                        "hg.mbtBI.1", HG_(free), NULL );
2763       tl_assert(map_barrier_to_Bar != NULL);
2764    }
2765 }
2766 
map_barrier_to_Bar_lookup_or_alloc(void * barrier)2767 static Bar* map_barrier_to_Bar_lookup_or_alloc ( void* barrier ) {
2768    UWord key, val;
2769    map_barrier_to_Bar_INIT();
2770    if (VG_(lookupFM)( map_barrier_to_Bar, &key, &val, (UWord)barrier )) {
2771       tl_assert(key == (UWord)barrier);
2772       return (Bar*)val;
2773    } else {
2774       Bar* bar = new_Bar();
2775       VG_(addToFM)( map_barrier_to_Bar, (UWord)barrier, (UWord)bar );
2776       return bar;
2777    }
2778 }
2779 
map_barrier_to_Bar_delete(void * barrier)2780 static void map_barrier_to_Bar_delete ( void* barrier ) {
2781    UWord keyW, valW;
2782    map_barrier_to_Bar_INIT();
2783    if (VG_(delFromFM)( map_barrier_to_Bar, &keyW, &valW, (UWord)barrier )) {
2784       Bar* bar = (Bar*)valW;
2785       tl_assert(keyW == (UWord)barrier);
2786       delete_Bar(bar);
2787    }
2788 }
2789 
2790 
evh__HG_PTHREAD_BARRIER_INIT_PRE(ThreadId tid,void * barrier,UWord count,UWord resizable)2791 static void evh__HG_PTHREAD_BARRIER_INIT_PRE ( ThreadId tid,
2792                                                void* barrier,
2793                                                UWord count,
2794                                                UWord resizable )
2795 {
2796    Thread* thr;
2797    Bar*    bar;
2798 
2799    if (SHOW_EVENTS >= 1)
2800       VG_(printf)("evh__HG_PTHREAD_BARRIER_INIT_PRE"
2801                   "(tid=%d, barrier=%p, count=%lu, resizable=%lu)\n",
2802                   (Int)tid, (void*)barrier, count, resizable );
2803 
2804    thr = map_threads_maybe_lookup( tid );
2805    tl_assert(thr); /* cannot fail - Thread* must already exist */
2806 
2807    if (count == 0) {
2808       HG_(record_error_Misc)(
2809          thr, "pthread_barrier_init: 'count' argument is zero"
2810       );
2811    }
2812 
2813    if (resizable != 0 && resizable != 1) {
2814       HG_(record_error_Misc)(
2815          thr, "pthread_barrier_init: invalid 'resizable' argument"
2816       );
2817    }
2818 
2819    bar = map_barrier_to_Bar_lookup_or_alloc(barrier);
2820    tl_assert(bar);
2821 
2822    if (bar->initted) {
2823       HG_(record_error_Misc)(
2824          thr, "pthread_barrier_init: barrier is already initialised"
2825       );
2826    }
2827 
2828    if (bar->waiting && VG_(sizeXA)(bar->waiting) > 0) {
2829       tl_assert(bar->initted);
2830       HG_(record_error_Misc)(
2831          thr, "pthread_barrier_init: threads are waiting at barrier"
2832       );
2833       VG_(dropTailXA)(bar->waiting, VG_(sizeXA)(bar->waiting));
2834    }
2835    if (!bar->waiting) {
2836       bar->waiting = VG_(newXA)( HG_(zalloc), "hg.eHPBIP.1", HG_(free),
2837                                  sizeof(Thread*) );
2838    }
2839 
2840    tl_assert(bar->waiting);
2841    tl_assert(VG_(sizeXA)(bar->waiting) == 0);
2842    bar->initted   = True;
2843    bar->resizable = resizable == 1 ? True : False;
2844    bar->size      = count;
2845 }
2846 
2847 
evh__HG_PTHREAD_BARRIER_DESTROY_PRE(ThreadId tid,void * barrier)2848 static void evh__HG_PTHREAD_BARRIER_DESTROY_PRE ( ThreadId tid,
2849                                                   void* barrier )
2850 {
2851    Thread* thr;
2852    Bar*    bar;
2853 
2854    /* Deal with destroy events.  The only purpose is to free storage
2855       associated with the barrier, so as to avoid any possible
2856       resource leaks. */
2857    if (SHOW_EVENTS >= 1)
2858       VG_(printf)("evh__HG_PTHREAD_BARRIER_DESTROY_PRE"
2859                   "(tid=%d, barrier=%p)\n",
2860                   (Int)tid, (void*)barrier );
2861 
2862    thr = map_threads_maybe_lookup( tid );
2863    tl_assert(thr); /* cannot fail - Thread* must already exist */
2864 
2865    bar = map_barrier_to_Bar_lookup_or_alloc(barrier);
2866    tl_assert(bar);
2867 
2868    if (!bar->initted) {
2869       HG_(record_error_Misc)(
2870          thr, "pthread_barrier_destroy: barrier was never initialised"
2871       );
2872    }
2873 
2874    if (bar->initted && bar->waiting && VG_(sizeXA)(bar->waiting) > 0) {
2875       HG_(record_error_Misc)(
2876          thr, "pthread_barrier_destroy: threads are waiting at barrier"
2877       );
2878    }
2879 
2880    /* Maybe we shouldn't do this; just let it persist, so that when it
2881       is reinitialised we don't need to do any dynamic memory
2882       allocation?  The downside is a potentially unlimited space leak,
2883       if the client creates (in turn) a large number of barriers all
2884       at different locations.  Note that if we do later move to the
2885       don't-delete-it scheme, we need to mark the barrier as
2886       uninitialised again since otherwise a later _init call will
2887       elicit a duplicate-init error.  */
2888    map_barrier_to_Bar_delete( barrier );
2889 }
2890 
2891 
2892 /* All the threads have arrived.  Now do the Interesting Bit.  Get a
2893    new synchronisation object and do a weak send to it from all the
2894    participating threads.  This makes its vector clocks be the join of
2895    all the individual threads' vector clocks.  Then do a strong
2896    receive from it back to all threads, so that their VCs are a copy
2897    of it (hence are all equal to the join of their original VCs.) */
do_barrier_cross_sync_and_empty(Bar * bar)2898 static void do_barrier_cross_sync_and_empty ( Bar* bar )
2899 {
2900    /* XXX check bar->waiting has no duplicates */
2901    UWord i;
2902    SO*   so = libhb_so_alloc();
2903 
2904    tl_assert(bar->waiting);
2905    tl_assert(VG_(sizeXA)(bar->waiting) == bar->size);
2906 
2907    /* compute the join ... */
2908    for (i = 0; i < bar->size; i++) {
2909       Thread* t = *(Thread**)VG_(indexXA)(bar->waiting, i);
2910       Thr* hbthr = t->hbthr;
2911       libhb_so_send( hbthr, so, False/*weak send*/ );
2912    }
2913    /* ... and distribute to all threads */
2914    for (i = 0; i < bar->size; i++) {
2915       Thread* t = *(Thread**)VG_(indexXA)(bar->waiting, i);
2916       Thr* hbthr = t->hbthr;
2917       libhb_so_recv( hbthr, so, True/*strong recv*/ );
2918    }
2919 
2920    /* finally, we must empty out the waiting vector */
2921    VG_(dropTailXA)(bar->waiting, VG_(sizeXA)(bar->waiting));
2922 
2923    /* and we don't need this any more.  Perhaps a stack-allocated
2924       SO would be better? */
2925    libhb_so_dealloc(so);
2926 }
2927 
2928 
evh__HG_PTHREAD_BARRIER_WAIT_PRE(ThreadId tid,void * barrier)2929 static void evh__HG_PTHREAD_BARRIER_WAIT_PRE ( ThreadId tid,
2930                                                void* barrier )
2931 {
2932   /* This function gets called after a client thread calls
2933      pthread_barrier_wait but before it arrives at the real
2934      pthread_barrier_wait.
2935 
2936      Why is the following correct?  It's a bit subtle.
2937 
2938      If this is not the last thread arriving at the barrier, we simply
2939      note its presence and return.  Because valgrind (at least as of
2940      Nov 08) is single threaded, we are guaranteed safe from any race
2941      conditions when in this function -- no other client threads are
2942      running.
2943 
2944      If this is the last thread, then we are again the only running
2945      thread.  All the other threads will have either arrived at the
2946      real pthread_barrier_wait or are on their way to it, but in any
2947      case are guaranteed not to be able to move past it, because this
2948      thread is currently in this function and so has not yet arrived
2949      at the real pthread_barrier_wait.  That means that:
2950 
2951      1. While we are in this function, none of the other threads
2952         waiting at the barrier can move past it.
2953 
2954      2. When this function returns (and simulated execution resumes),
2955         this thread and all other waiting threads will be able to move
2956         past the real barrier.
2957 
2958      Because of this, it is now safe to update the vector clocks of
2959      all threads, to represent the fact that they all arrived at the
2960      barrier and have all moved on.  There is no danger of any
2961      complications to do with some threads leaving the barrier and
2962      racing back round to the front, whilst others are still leaving
2963      (which is the primary source of complication in correct handling/
2964      implementation of barriers).  That can't happen because we update
2965      here our data structures so as to indicate that the threads have
2966      passed the barrier, even though, as per (2) above, they are
2967      guaranteed not to pass the barrier until we return.
2968 
2969      This relies crucially on Valgrind being single threaded.  If that
2970      changes, this will need to be reconsidered.
2971    */
2972    Thread* thr;
2973    Bar*    bar;
2974    UWord   present;
2975 
2976    if (SHOW_EVENTS >= 1)
2977       VG_(printf)("evh__HG_PTHREAD_BARRIER_WAIT_PRE"
2978                   "(tid=%d, barrier=%p)\n",
2979                   (Int)tid, (void*)barrier );
2980 
2981    thr = map_threads_maybe_lookup( tid );
2982    tl_assert(thr); /* cannot fail - Thread* must already exist */
2983 
2984    bar = map_barrier_to_Bar_lookup_or_alloc(barrier);
2985    tl_assert(bar);
2986 
2987    if (!bar->initted) {
2988       HG_(record_error_Misc)(
2989          thr, "pthread_barrier_wait: barrier is uninitialised"
2990       );
2991       return; /* client is broken .. avoid assertions below */
2992    }
2993 
2994    /* guaranteed by _INIT_PRE above */
2995    tl_assert(bar->size > 0);
2996    tl_assert(bar->waiting);
2997 
2998    VG_(addToXA)( bar->waiting, &thr );
2999 
3000    /* guaranteed by this function */
3001    present = VG_(sizeXA)(bar->waiting);
3002    tl_assert(present > 0 && present <= bar->size);
3003 
3004    if (present < bar->size)
3005       return;
3006 
3007    do_barrier_cross_sync_and_empty(bar);
3008 }
3009 
3010 
evh__HG_PTHREAD_BARRIER_RESIZE_PRE(ThreadId tid,void * barrier,UWord newcount)3011 static void evh__HG_PTHREAD_BARRIER_RESIZE_PRE ( ThreadId tid,
3012                                                  void* barrier,
3013                                                  UWord newcount )
3014 {
3015    Thread* thr;
3016    Bar*    bar;
3017    UWord   present;
3018 
3019    if (SHOW_EVENTS >= 1)
3020       VG_(printf)("evh__HG_PTHREAD_BARRIER_RESIZE_PRE"
3021                   "(tid=%d, barrier=%p, newcount=%lu)\n",
3022                   (Int)tid, (void*)barrier, newcount );
3023 
3024    thr = map_threads_maybe_lookup( tid );
3025    tl_assert(thr); /* cannot fail - Thread* must already exist */
3026 
3027    bar = map_barrier_to_Bar_lookup_or_alloc(barrier);
3028    tl_assert(bar);
3029 
3030    if (!bar->initted) {
3031       HG_(record_error_Misc)(
3032          thr, "pthread_barrier_resize: barrier is uninitialised"
3033       );
3034       return; /* client is broken .. avoid assertions below */
3035    }
3036 
3037    if (!bar->resizable) {
3038       HG_(record_error_Misc)(
3039          thr, "pthread_barrier_resize: barrier is may not be resized"
3040       );
3041       return; /* client is broken .. avoid assertions below */
3042    }
3043 
3044    if (newcount == 0) {
3045       HG_(record_error_Misc)(
3046          thr, "pthread_barrier_resize: 'newcount' argument is zero"
3047       );
3048       return; /* client is broken .. avoid assertions below */
3049    }
3050 
3051    /* guaranteed by _INIT_PRE above */
3052    tl_assert(bar->size > 0);
3053    tl_assert(bar->waiting);
3054    /* Guaranteed by this fn */
3055    tl_assert(newcount > 0);
3056 
3057    if (newcount >= bar->size) {
3058       /* Increasing the capacity.  There's no possibility of threads
3059          moving on from the barrier in this situation, so just note
3060          the fact and do nothing more. */
3061       bar->size = newcount;
3062    } else {
3063       /* Decreasing the capacity.  If we decrease it to be equal or
3064          below the number of waiting threads, they will now move past
3065          the barrier, so need to mess with dep edges in the same way
3066          as if the barrier had filled up normally. */
3067       present = VG_(sizeXA)(bar->waiting);
3068       tl_assert(present >= 0 && present <= bar->size);
3069       if (newcount <= present) {
3070          bar->size = present; /* keep the cross_sync call happy */
3071          do_barrier_cross_sync_and_empty(bar);
3072       }
3073       bar->size = newcount;
3074    }
3075 }
3076 
3077 
3078 /* ----------------------------------------------------- */
3079 /* ----- events to do with user-specified HB edges ----- */
3080 /* ----------------------------------------------------- */
3081 
3082 /* A mapping from arbitrary UWord tag to the SO associated with it.
3083    The UWord tags are meaningless to us, interpreted only by the
3084    user. */
3085 
3086 
3087 
3088 /* UWord -> SO* */
3089 static WordFM* map_usertag_to_SO = NULL;
3090 
map_usertag_to_SO_INIT(void)3091 static void map_usertag_to_SO_INIT ( void ) {
3092    if (UNLIKELY(map_usertag_to_SO == NULL)) {
3093       map_usertag_to_SO = VG_(newFM)( HG_(zalloc),
3094                                       "hg.mutS.1", HG_(free), NULL );
3095       tl_assert(map_usertag_to_SO != NULL);
3096    }
3097 }
3098 
map_usertag_to_SO_lookup_or_alloc(UWord usertag)3099 static SO* map_usertag_to_SO_lookup_or_alloc ( UWord usertag ) {
3100    UWord key, val;
3101    map_usertag_to_SO_INIT();
3102    if (VG_(lookupFM)( map_usertag_to_SO, &key, &val, usertag )) {
3103       tl_assert(key == (UWord)usertag);
3104       return (SO*)val;
3105    } else {
3106       SO* so = libhb_so_alloc();
3107       VG_(addToFM)( map_usertag_to_SO, usertag, (UWord)so );
3108       return so;
3109    }
3110 }
3111 
map_usertag_to_SO_delete(UWord usertag)3112 static void map_usertag_to_SO_delete ( UWord usertag ) {
3113    UWord keyW, valW;
3114    map_usertag_to_SO_INIT();
3115    if (VG_(delFromFM)( map_usertag_to_SO, &keyW, &valW, usertag )) {
3116       SO* so = (SO*)valW;
3117       tl_assert(keyW == usertag);
3118       tl_assert(so);
3119       libhb_so_dealloc(so);
3120    }
3121 }
3122 
3123 
3124 static
evh__HG_USERSO_SEND_PRE(ThreadId tid,UWord usertag)3125 void evh__HG_USERSO_SEND_PRE ( ThreadId tid, UWord usertag )
3126 {
3127    /* TID is just about to notionally sent a message on a notional
3128       abstract synchronisation object whose identity is given by
3129       USERTAG.  Bind USERTAG to a real SO if it is not already so
3130       bound, and do a 'weak send' on the SO.  This joins the vector
3131       clocks from this thread into any vector clocks already present
3132       in the SO.  The resulting SO vector clocks are later used by
3133       other thread(s) which successfully 'receive' from the SO,
3134       thereby acquiring a dependency on all the events that have
3135       previously signalled on this SO. */
3136    Thread* thr;
3137    SO*     so;
3138 
3139    if (SHOW_EVENTS >= 1)
3140       VG_(printf)("evh__HG_USERSO_SEND_PRE(ctid=%d, usertag=%#lx)\n",
3141                   (Int)tid, usertag );
3142 
3143    thr = map_threads_maybe_lookup( tid );
3144    tl_assert(thr); /* cannot fail - Thread* must already exist */
3145 
3146    so = map_usertag_to_SO_lookup_or_alloc( usertag );
3147    tl_assert(so);
3148 
3149    libhb_so_send( thr->hbthr, so, False/*!strong_send*/ );
3150 }
3151 
3152 static
evh__HG_USERSO_RECV_POST(ThreadId tid,UWord usertag)3153 void evh__HG_USERSO_RECV_POST ( ThreadId tid, UWord usertag )
3154 {
3155    /* TID has just notionally received a message from a notional
3156       abstract synchronisation object whose identity is given by
3157       USERTAG.  Bind USERTAG to a real SO if it is not already so
3158       bound.  If the SO has at some point in the past been 'sent' on,
3159       to a 'strong receive' on it, thereby acquiring a dependency on
3160       the sender. */
3161    Thread* thr;
3162    SO*     so;
3163 
3164    if (SHOW_EVENTS >= 1)
3165       VG_(printf)("evh__HG_USERSO_RECV_POST(ctid=%d, usertag=%#lx)\n",
3166                   (Int)tid, usertag );
3167 
3168    thr = map_threads_maybe_lookup( tid );
3169    tl_assert(thr); /* cannot fail - Thread* must already exist */
3170 
3171    so = map_usertag_to_SO_lookup_or_alloc( usertag );
3172    tl_assert(so);
3173 
3174    /* Acquire a dependency on it.  If the SO has never so far been
3175       sent on, then libhb_so_recv will do nothing.  So we're safe
3176       regardless of SO's history. */
3177    libhb_so_recv( thr->hbthr, so, True/*strong_recv*/ );
3178 }
3179 
3180 static
evh__HG_USERSO_FORGET_ALL(ThreadId tid,UWord usertag)3181 void evh__HG_USERSO_FORGET_ALL ( ThreadId tid, UWord usertag )
3182 {
3183    /* TID declares that any happens-before edges notionally stored in
3184       USERTAG can be deleted.  If (as would normally be the case) a
3185       SO is associated with USERTAG, then the assocation is removed
3186       and all resources associated with SO are freed.  Importantly,
3187       that frees up any VTSs stored in SO. */
3188    if (SHOW_EVENTS >= 1)
3189       VG_(printf)("evh__HG_USERSO_FORGET_ALL(ctid=%d, usertag=%#lx)\n",
3190                   (Int)tid, usertag );
3191 
3192    map_usertag_to_SO_delete( usertag );
3193 }
3194 
3195 
3196 /*--------------------------------------------------------------*/
3197 /*--- Lock acquisition order monitoring                      ---*/
3198 /*--------------------------------------------------------------*/
3199 
3200 /* FIXME: here are some optimisations still to do in
3201           laog__pre_thread_acquires_lock.
3202 
3203    The graph is structured so that if L1 --*--> L2 then L1 must be
3204    acquired before L2.
3205 
3206    The common case is that some thread T holds (eg) L1 L2 and L3 and
3207    is repeatedly acquiring and releasing Ln, and there is no ordering
3208    error in what it is doing.  Hence it repeatly:
3209 
3210    (1) searches laog to see if Ln --*--> {L1,L2,L3}, which always
3211        produces the answer No (because there is no error).
3212 
3213    (2) adds edges {L1,L2,L3} --> Ln to laog, which are already present
3214        (because they already got added the first time T acquired Ln).
3215 
3216    Hence cache these two events:
3217 
3218    (1) Cache result of the query from last time.  Invalidate the cache
3219        any time any edges are added to or deleted from laog.
3220 
3221    (2) Cache these add-edge requests and ignore them if said edges
3222        have already been added to laog.  Invalidate the cache any time
3223        any edges are deleted from laog.
3224 */
3225 
3226 typedef
3227    struct {
3228       WordSetID inns; /* in univ_laog */
3229       WordSetID outs; /* in univ_laog */
3230    }
3231    LAOGLinks;
3232 
3233 /* lock order acquisition graph */
3234 static WordFM* laog = NULL; /* WordFM Lock* LAOGLinks* */
3235 
3236 /* EXPOSITION ONLY: for each edge in 'laog', record the two places
3237    where that edge was created, so that we can show the user later if
3238    we need to. */
3239 typedef
3240    struct {
3241       Addr        src_ga; /* Lock guest addresses for */
3242       Addr        dst_ga; /* src/dst of the edge */
3243       ExeContext* src_ec; /* And corresponding places where that */
3244       ExeContext* dst_ec; /* ordering was established */
3245    }
3246    LAOGLinkExposition;
3247 
cmp_LAOGLinkExposition(UWord llx1W,UWord llx2W)3248 static Word cmp_LAOGLinkExposition ( UWord llx1W, UWord llx2W ) {
3249    /* Compare LAOGLinkExposition*s by (src_ga,dst_ga) field pair. */
3250    LAOGLinkExposition* llx1 = (LAOGLinkExposition*)llx1W;
3251    LAOGLinkExposition* llx2 = (LAOGLinkExposition*)llx2W;
3252    if (llx1->src_ga < llx2->src_ga) return -1;
3253    if (llx1->src_ga > llx2->src_ga) return  1;
3254    if (llx1->dst_ga < llx2->dst_ga) return -1;
3255    if (llx1->dst_ga > llx2->dst_ga) return  1;
3256    return 0;
3257 }
3258 
3259 static WordFM* laog_exposition = NULL; /* WordFM LAOGLinkExposition* NULL */
3260 /* end EXPOSITION ONLY */
3261 
3262 
3263 __attribute__((noinline))
laog__init(void)3264 static void laog__init ( void )
3265 {
3266    tl_assert(!laog);
3267    tl_assert(!laog_exposition);
3268    tl_assert(HG_(clo_track_lockorders));
3269 
3270    laog = VG_(newFM)( HG_(zalloc), "hg.laog__init.1",
3271                       HG_(free), NULL/*unboxedcmp*/ );
3272 
3273    laog_exposition = VG_(newFM)( HG_(zalloc), "hg.laog__init.2", HG_(free),
3274                                  cmp_LAOGLinkExposition );
3275    tl_assert(laog);
3276    tl_assert(laog_exposition);
3277 }
3278 
laog__show(Char * who)3279 static void laog__show ( Char* who ) {
3280    Word i, ws_size;
3281    UWord* ws_words;
3282    Lock* me;
3283    LAOGLinks* links;
3284    VG_(printf)("laog (requested by %s) {\n", who);
3285    VG_(initIterFM)( laog );
3286    me = NULL;
3287    links = NULL;
3288    while (VG_(nextIterFM)( laog, (Word*)&me,
3289                                  (Word*)&links )) {
3290       tl_assert(me);
3291       tl_assert(links);
3292       VG_(printf)("   node %p:\n", me);
3293       HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns );
3294       for (i = 0; i < ws_size; i++)
3295          VG_(printf)("      inn %#lx\n", ws_words[i] );
3296       HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs );
3297       for (i = 0; i < ws_size; i++)
3298          VG_(printf)("      out %#lx\n", ws_words[i] );
3299       me = NULL;
3300       links = NULL;
3301    }
3302    VG_(doneIterFM)( laog );
3303    VG_(printf)("}\n");
3304 }
3305 
univ_laog_do_GC(void)3306 static void univ_laog_do_GC ( void ) {
3307    Word i;
3308    LAOGLinks* links;
3309    Word seen = 0;
3310    Int prev_next_gc_univ_laog = next_gc_univ_laog;
3311    const UWord univ_laog_cardinality = HG_(cardinalityWSU)( univ_laog);
3312 
3313    Bool *univ_laog_seen = HG_(zalloc) ( "hg.gc_univ_laog.1",
3314                                         (Int) univ_laog_cardinality
3315                                         * sizeof(Bool) );
3316    // univ_laog_seen[*] set to 0 (False) by zalloc.
3317 
3318    if (VG_(clo_stats))
3319       VG_(message)(Vg_DebugMsg,
3320                    "univ_laog_do_GC enter cardinality %'10d\n",
3321                    (Int)univ_laog_cardinality);
3322 
3323    VG_(initIterFM)( laog );
3324    links = NULL;
3325    while (VG_(nextIterFM)( laog, NULL, (UWord*)&links )) {
3326       tl_assert(links);
3327       tl_assert(links->inns >= 0 && links->inns < univ_laog_cardinality);
3328       univ_laog_seen[links->inns] = True;
3329       tl_assert(links->outs >= 0 && links->outs < univ_laog_cardinality);
3330       univ_laog_seen[links->outs] = True;
3331       links = NULL;
3332    }
3333    VG_(doneIterFM)( laog );
3334 
3335    for (i = 0; i < (Int)univ_laog_cardinality; i++) {
3336       if (univ_laog_seen[i])
3337          seen++;
3338       else
3339          HG_(dieWS) ( univ_laog, (WordSet)i );
3340    }
3341 
3342    HG_(free) (univ_laog_seen);
3343 
3344    // We need to decide the value of the next_gc.
3345    // 3 solutions were looked at:
3346    // Sol 1: garbage collect at seen * 2
3347    //   This solution was a lot slower, probably because we both do a lot of
3348    //   garbage collection and do not keep long enough laog WV that will become
3349    //   useful  again very soon.
3350    // Sol 2: garbage collect at a percentage increase of the current cardinality
3351    //         (with a min increase of 1)
3352    //   Trials on a small test program with 1%, 5% and 10% increase was done.
3353    //   1% is slightly faster than 5%, which is slightly slower than 10%.
3354    //   However, on a big application, this caused the memory to be exhausted,
3355    //   as even a 1% increase of size at each gc becomes a lot, when many gc
3356    //   are done.
3357    // Sol 3: always garbage collect at current cardinality + 1.
3358    //   This solution was the fastest of the 3 solutions, and caused no memory
3359    //   exhaustion in the big application.
3360    //
3361    // With regards to cost introduced by gc: on the t2t perf test (doing only
3362    // lock/unlock operations), t2t 50 10 2 was about 25% faster than the
3363    // version with garbage collection. With t2t 50 20 2, my machine started
3364    // to page out, and so the garbage collected version was much faster.
3365    // On smaller lock sets (e.g. t2t 20 5 2, giving about 100 locks), the
3366    // difference performance is insignificant (~ 0.1 s).
3367    // Of course, it might be that real life programs are not well represented
3368    // by t2t.
3369 
3370    // If ever we want to have a more sophisticated control
3371    // (e.g. clo options to control the percentage increase or fixed increased),
3372    // we should do it here, eg.
3373    //     next_gc_univ_laog = prev_next_gc_univ_laog + VG_(clo_laog_gc_fixed);
3374    // Currently, we just hard-code the solution 3 above.
3375    next_gc_univ_laog = prev_next_gc_univ_laog + 1;
3376 
3377    if (VG_(clo_stats))
3378       VG_(message)
3379          (Vg_DebugMsg,
3380           "univ_laog_do_GC exit seen %'8d next gc at cardinality %'10d\n",
3381           (Int)seen, next_gc_univ_laog);
3382 }
3383 
3384 
3385 __attribute__((noinline))
laog__add_edge(Lock * src,Lock * dst)3386 static void laog__add_edge ( Lock* src, Lock* dst ) {
3387    Word       keyW;
3388    LAOGLinks* links;
3389    Bool       presentF, presentR;
3390    if (0) VG_(printf)("laog__add_edge %p %p\n", src, dst);
3391 
3392    /* Take the opportunity to sanity check the graph.  Record in
3393       presentF if there is already a src->dst mapping in this node's
3394       forwards links, and presentR if there is already a src->dst
3395       mapping in this node's backwards links.  They should agree!
3396       Also, we need to know whether the edge was already present so as
3397       to decide whether or not to update the link details mapping.  We
3398       can compute presentF and presentR essentially for free, so may
3399       as well do this always. */
3400    presentF = presentR = False;
3401 
3402    /* Update the out edges for src */
3403    keyW  = 0;
3404    links = NULL;
3405    if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) {
3406       WordSetID outs_new;
3407       tl_assert(links);
3408       tl_assert(keyW == (Word)src);
3409       outs_new = HG_(addToWS)( univ_laog, links->outs, (Word)dst );
3410       presentF = outs_new == links->outs;
3411       links->outs = outs_new;
3412    } else {
3413       links = HG_(zalloc)("hg.lae.1", sizeof(LAOGLinks));
3414       links->inns = HG_(emptyWS)( univ_laog );
3415       links->outs = HG_(singletonWS)( univ_laog, (Word)dst );
3416       VG_(addToFM)( laog, (Word)src, (Word)links );
3417    }
3418    /* Update the in edges for dst */
3419    keyW  = 0;
3420    links = NULL;
3421    if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) {
3422       WordSetID inns_new;
3423       tl_assert(links);
3424       tl_assert(keyW == (Word)dst);
3425       inns_new = HG_(addToWS)( univ_laog, links->inns, (Word)src );
3426       presentR = inns_new == links->inns;
3427       links->inns = inns_new;
3428    } else {
3429       links = HG_(zalloc)("hg.lae.2", sizeof(LAOGLinks));
3430       links->inns = HG_(singletonWS)( univ_laog, (Word)src );
3431       links->outs = HG_(emptyWS)( univ_laog );
3432       VG_(addToFM)( laog, (Word)dst, (Word)links );
3433    }
3434 
3435    tl_assert( (presentF && presentR) || (!presentF && !presentR) );
3436 
3437    if (!presentF && src->acquired_at && dst->acquired_at) {
3438       LAOGLinkExposition expo;
3439       /* If this edge is entering the graph, and we have acquired_at
3440          information for both src and dst, record those acquisition
3441          points.  Hence, if there is later a violation of this
3442          ordering, we can show the user the two places in which the
3443          required src-dst ordering was previously established. */
3444       if (0) VG_(printf)("acquire edge %#lx %#lx\n",
3445                          src->guestaddr, dst->guestaddr);
3446       expo.src_ga = src->guestaddr;
3447       expo.dst_ga = dst->guestaddr;
3448       expo.src_ec = NULL;
3449       expo.dst_ec = NULL;
3450       tl_assert(laog_exposition);
3451       if (VG_(lookupFM)( laog_exposition, NULL, NULL, (Word)&expo )) {
3452          /* we already have it; do nothing */
3453       } else {
3454          LAOGLinkExposition* expo2 = HG_(zalloc)("hg.lae.3",
3455                                                sizeof(LAOGLinkExposition));
3456          expo2->src_ga = src->guestaddr;
3457          expo2->dst_ga = dst->guestaddr;
3458          expo2->src_ec = src->acquired_at;
3459          expo2->dst_ec = dst->acquired_at;
3460          VG_(addToFM)( laog_exposition, (Word)expo2, (Word)NULL );
3461       }
3462    }
3463 
3464    if (HG_(cardinalityWSU) (univ_laog) >= next_gc_univ_laog)
3465       univ_laog_do_GC();
3466 }
3467 
3468 __attribute__((noinline))
laog__del_edge(Lock * src,Lock * dst)3469 static void laog__del_edge ( Lock* src, Lock* dst ) {
3470    Word       keyW;
3471    LAOGLinks* links;
3472    if (0) VG_(printf)("laog__del_edge enter %p %p\n", src, dst);
3473    /* Update the out edges for src */
3474    keyW  = 0;
3475    links = NULL;
3476    if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) {
3477       tl_assert(links);
3478       tl_assert(keyW == (Word)src);
3479       links->outs = HG_(delFromWS)( univ_laog, links->outs, (Word)dst );
3480    }
3481    /* Update the in edges for dst */
3482    keyW  = 0;
3483    links = NULL;
3484    if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) {
3485       tl_assert(links);
3486       tl_assert(keyW == (Word)dst);
3487       links->inns = HG_(delFromWS)( univ_laog, links->inns, (Word)src );
3488    }
3489 
3490    /* Remove the exposition of src,dst (if present) */
3491    {
3492       LAOGLinkExposition *fm_expo;
3493 
3494       LAOGLinkExposition expo;
3495       expo.src_ga = src->guestaddr;
3496       expo.dst_ga = dst->guestaddr;
3497       expo.src_ec = NULL;
3498       expo.dst_ec = NULL;
3499 
3500       if (VG_(delFromFM) (laog_exposition,
3501                           (UWord*)&fm_expo, NULL, (UWord)&expo )) {
3502          HG_(free) (fm_expo);
3503       }
3504    }
3505 
3506    /* deleting edges can increase nr of of WS so check for gc. */
3507    if (HG_(cardinalityWSU) (univ_laog) >= next_gc_univ_laog)
3508       univ_laog_do_GC();
3509    if (0) VG_(printf)("laog__del_edge exit\n");
3510 }
3511 
3512 __attribute__((noinline))
laog__succs(Lock * lk)3513 static WordSetID /* in univ_laog */ laog__succs ( Lock* lk ) {
3514    Word       keyW;
3515    LAOGLinks* links;
3516    keyW  = 0;
3517    links = NULL;
3518    if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) {
3519       tl_assert(links);
3520       tl_assert(keyW == (Word)lk);
3521       return links->outs;
3522    } else {
3523       return HG_(emptyWS)( univ_laog );
3524    }
3525 }
3526 
3527 __attribute__((noinline))
laog__preds(Lock * lk)3528 static WordSetID /* in univ_laog */ laog__preds ( Lock* lk ) {
3529    Word       keyW;
3530    LAOGLinks* links;
3531    keyW  = 0;
3532    links = NULL;
3533    if (VG_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) {
3534       tl_assert(links);
3535       tl_assert(keyW == (Word)lk);
3536       return links->inns;
3537    } else {
3538       return HG_(emptyWS)( univ_laog );
3539    }
3540 }
3541 
3542 __attribute__((noinline))
laog__sanity_check(Char * who)3543 static void laog__sanity_check ( Char* who ) {
3544    Word i, ws_size;
3545    UWord* ws_words;
3546    Lock* me;
3547    LAOGLinks* links;
3548    VG_(initIterFM)( laog );
3549    me = NULL;
3550    links = NULL;
3551    if (0) VG_(printf)("laog sanity check\n");
3552    while (VG_(nextIterFM)( laog, (Word*)&me,
3553                                  (Word*)&links )) {
3554       tl_assert(me);
3555       tl_assert(links);
3556       HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns );
3557       for (i = 0; i < ws_size; i++) {
3558          if ( ! HG_(elemWS)( univ_laog,
3559                              laog__succs( (Lock*)ws_words[i] ),
3560                              (Word)me ))
3561             goto bad;
3562       }
3563       HG_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs );
3564       for (i = 0; i < ws_size; i++) {
3565          if ( ! HG_(elemWS)( univ_laog,
3566                              laog__preds( (Lock*)ws_words[i] ),
3567                              (Word)me ))
3568             goto bad;
3569       }
3570       me = NULL;
3571       links = NULL;
3572    }
3573    VG_(doneIterFM)( laog );
3574    return;
3575 
3576   bad:
3577    VG_(printf)("laog__sanity_check(%s) FAILED\n", who);
3578    laog__show(who);
3579    tl_assert(0);
3580 }
3581 
3582 /* If there is a path in laog from 'src' to any of the elements in
3583    'dst', return an arbitrarily chosen element of 'dst' reachable from
3584    'src'.  If no path exist from 'src' to any element in 'dst', return
3585    NULL. */
3586 __attribute__((noinline))
3587 static
laog__do_dfs_from_to(Lock * src,WordSetID dsts)3588 Lock* laog__do_dfs_from_to ( Lock* src, WordSetID dsts /* univ_lsets */ )
3589 {
3590    Lock*     ret;
3591    Word      i, ssz;
3592    XArray*   stack;   /* of Lock* */
3593    WordFM*   visited; /* Lock* -> void, iow, Set(Lock*) */
3594    Lock*     here;
3595    WordSetID succs;
3596    Word      succs_size;
3597    UWord*    succs_words;
3598    //laog__sanity_check();
3599 
3600    /* If the destination set is empty, we can never get there from
3601       'src' :-), so don't bother to try */
3602    if (HG_(isEmptyWS)( univ_lsets, dsts ))
3603       return NULL;
3604 
3605    ret     = NULL;
3606    stack   = VG_(newXA)( HG_(zalloc), "hg.lddft.1", HG_(free), sizeof(Lock*) );
3607    visited = VG_(newFM)( HG_(zalloc), "hg.lddft.2", HG_(free), NULL/*unboxedcmp*/ );
3608 
3609    (void) VG_(addToXA)( stack, &src );
3610 
3611    while (True) {
3612 
3613       ssz = VG_(sizeXA)( stack );
3614 
3615       if (ssz == 0) { ret = NULL; break; }
3616 
3617       here = *(Lock**) VG_(indexXA)( stack, ssz-1 );
3618       VG_(dropTailXA)( stack, 1 );
3619 
3620       if (HG_(elemWS)( univ_lsets, dsts, (Word)here )) { ret = here; break; }
3621 
3622       if (VG_(lookupFM)( visited, NULL, NULL, (Word)here ))
3623          continue;
3624 
3625       VG_(addToFM)( visited, (Word)here, 0 );
3626 
3627       succs = laog__succs( here );
3628       HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs );
3629       for (i = 0; i < succs_size; i++)
3630          (void) VG_(addToXA)( stack, &succs_words[i] );
3631    }
3632 
3633    VG_(deleteFM)( visited, NULL, NULL );
3634    VG_(deleteXA)( stack );
3635    return ret;
3636 }
3637 
3638 
3639 /* Thread 'thr' is acquiring 'lk'.  Check for inconsistent ordering
3640    between 'lk' and the locks already held by 'thr' and issue a
3641    complaint if so.  Also, update the ordering graph appropriately.
3642 */
3643 __attribute__((noinline))
laog__pre_thread_acquires_lock(Thread * thr,Lock * lk)3644 static void laog__pre_thread_acquires_lock (
3645                Thread* thr, /* NB: BEFORE lock is added */
3646                Lock*   lk
3647             )
3648 {
3649    UWord*   ls_words;
3650    Word     ls_size, i;
3651    Lock*    other;
3652 
3653    /* It may be that 'thr' already holds 'lk' and is recursively
3654       relocking in.  In this case we just ignore the call. */
3655    /* NB: univ_lsets really is correct here */
3656    if (HG_(elemWS)( univ_lsets, thr->locksetA, (Word)lk ))
3657       return;
3658 
3659    /* First, the check.  Complain if there is any path in laog from lk
3660       to any of the locks already held by thr, since if any such path
3661       existed, it would mean that previously lk was acquired before
3662       (rather than after, as we are doing here) at least one of those
3663       locks.
3664    */
3665    other = laog__do_dfs_from_to(lk, thr->locksetA);
3666    if (other) {
3667       LAOGLinkExposition key, *found;
3668       /* So we managed to find a path lk --*--> other in the graph,
3669          which implies that 'lk' should have been acquired before
3670          'other' but is in fact being acquired afterwards.  We present
3671          the lk/other arguments to record_error_LockOrder in the order
3672          in which they should have been acquired. */
3673       /* Go look in the laog_exposition mapping, to find the allocation
3674          points for this edge, so we can show the user. */
3675       key.src_ga = lk->guestaddr;
3676       key.dst_ga = other->guestaddr;
3677       key.src_ec = NULL;
3678       key.dst_ec = NULL;
3679       found = NULL;
3680       if (VG_(lookupFM)( laog_exposition,
3681                          (Word*)&found, NULL, (Word)&key )) {
3682          tl_assert(found != &key);
3683          tl_assert(found->src_ga == key.src_ga);
3684          tl_assert(found->dst_ga == key.dst_ga);
3685          tl_assert(found->src_ec);
3686          tl_assert(found->dst_ec);
3687          HG_(record_error_LockOrder)(
3688             thr, lk->guestaddr, other->guestaddr,
3689                  found->src_ec, found->dst_ec, other->acquired_at );
3690       } else {
3691          /* Hmm.  This can't happen (can it?) */
3692          HG_(record_error_LockOrder)(
3693             thr, lk->guestaddr, other->guestaddr,
3694                  NULL, NULL, NULL );
3695       }
3696    }
3697 
3698    /* Second, add to laog the pairs
3699         (old, lk)  |  old <- locks already held by thr
3700       Since both old and lk are currently held by thr, their acquired_at
3701       fields must be non-NULL.
3702    */
3703    tl_assert(lk->acquired_at);
3704    HG_(getPayloadWS)( &ls_words, &ls_size, univ_lsets, thr->locksetA );
3705    for (i = 0; i < ls_size; i++) {
3706       Lock* old = (Lock*)ls_words[i];
3707       tl_assert(old->acquired_at);
3708       laog__add_edge( old, lk );
3709    }
3710 
3711    /* Why "except_Locks" ?  We're here because a lock is being
3712       acquired by a thread, and we're in an inconsistent state here.
3713       See the call points in evhH__post_thread_{r,w}_acquires_lock.
3714       When called in this inconsistent state, locks__sanity_check duly
3715       barfs. */
3716    if (HG_(clo_sanity_flags) & SCE_LAOG)
3717       all_except_Locks__sanity_check("laog__pre_thread_acquires_lock-post");
3718 }
3719 
3720 /* Allocates a duplicate of words. Caller must HG_(free) the result. */
UWordV_dup(UWord * words,Word words_size)3721 static UWord* UWordV_dup(UWord* words, Word words_size)
3722 {
3723    UInt i;
3724 
3725    if (words_size == 0)
3726       return NULL;
3727 
3728    UWord *dup = HG_(zalloc) ("hg.dup.1", (SizeT) words_size * sizeof(UWord));
3729 
3730    for (i = 0; i < words_size; i++)
3731       dup[i] = words[i];
3732 
3733    return dup;
3734 }
3735 
3736 /* Delete from 'laog' any pair mentioning a lock in locksToDelete */
3737 
3738 __attribute__((noinline))
laog__handle_one_lock_deletion(Lock * lk)3739 static void laog__handle_one_lock_deletion ( Lock* lk )
3740 {
3741    WordSetID preds, succs;
3742    Word preds_size, succs_size, i, j;
3743    UWord *preds_words, *succs_words;
3744 
3745    preds = laog__preds( lk );
3746    succs = laog__succs( lk );
3747 
3748    // We need to duplicate the payload, as these can be garbage collected
3749    // during the del/add operations below.
3750    HG_(getPayloadWS)( &preds_words, &preds_size, univ_laog, preds );
3751    preds_words = UWordV_dup(preds_words, preds_size);
3752 
3753    HG_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs );
3754    succs_words = UWordV_dup(succs_words, succs_size);
3755 
3756    for (i = 0; i < preds_size; i++)
3757       laog__del_edge( (Lock*)preds_words[i], lk );
3758 
3759    for (j = 0; j < succs_size; j++)
3760       laog__del_edge( lk, (Lock*)succs_words[j] );
3761 
3762    for (i = 0; i < preds_size; i++) {
3763       for (j = 0; j < succs_size; j++) {
3764          if (preds_words[i] != succs_words[j]) {
3765             /* This can pass unlocked locks to laog__add_edge, since
3766                we're deleting stuff.  So their acquired_at fields may
3767                be NULL. */
3768             laog__add_edge( (Lock*)preds_words[i], (Lock*)succs_words[j] );
3769          }
3770       }
3771    }
3772 
3773    if (preds_words)
3774       HG_(free) (preds_words);
3775    if (succs_words)
3776       HG_(free) (succs_words);
3777 
3778    // Remove lk information from laog links FM
3779    {
3780       LAOGLinks *links;
3781       Lock* linked_lk;
3782 
3783       if (VG_(delFromFM) (laog,
3784                           (UWord*)&linked_lk, (UWord*)&links, (UWord)lk)) {
3785          tl_assert (linked_lk == lk);
3786          HG_(free) (links);
3787       }
3788    }
3789    /* FIXME ??? What about removing lock lk data from EXPOSITION ??? */
3790 }
3791 
3792 //__attribute__((noinline))
3793 //static void laog__handle_lock_deletions (
3794 //               WordSetID /* in univ_laog */ locksToDelete
3795 //            )
3796 //{
3797 //   Word   i, ws_size;
3798 //   UWord* ws_words;
3799 //
3800 //
3801 //   HG_(getPayloadWS)( &ws_words, &ws_size, univ_lsets, locksToDelete );
3802 //   UWordV_dup call needed here ...
3803 //   for (i = 0; i < ws_size; i++)
3804 //      laog__handle_one_lock_deletion( (Lock*)ws_words[i] );
3805 //
3806 //   if (HG_(clo_sanity_flags) & SCE_LAOG)
3807 //      all__sanity_check("laog__handle_lock_deletions-post");
3808 //}
3809 
3810 
3811 /*--------------------------------------------------------------*/
3812 /*--- Malloc/free replacements                               ---*/
3813 /*--------------------------------------------------------------*/
3814 
3815 typedef
3816    struct {
3817       void*       next;    /* required by m_hashtable */
3818       Addr        payload; /* ptr to actual block    */
3819       SizeT       szB;     /* size requested         */
3820       ExeContext* where;   /* where it was allocated */
3821       Thread*     thr;     /* allocating thread      */
3822    }
3823    MallocMeta;
3824 
3825 /* A hash table of MallocMetas, used to track malloc'd blocks
3826    (obviously). */
3827 static VgHashTable hg_mallocmeta_table = NULL;
3828 
3829 
new_MallocMeta(void)3830 static MallocMeta* new_MallocMeta ( void ) {
3831    MallocMeta* md = HG_(zalloc)( "hg.new_MallocMeta.1", sizeof(MallocMeta) );
3832    tl_assert(md);
3833    return md;
3834 }
delete_MallocMeta(MallocMeta * md)3835 static void delete_MallocMeta ( MallocMeta* md ) {
3836    HG_(free)(md);
3837 }
3838 
3839 
3840 /* Allocate a client block and set up the metadata for it. */
3841 
3842 static
handle_alloc(ThreadId tid,SizeT szB,SizeT alignB,Bool is_zeroed)3843 void* handle_alloc ( ThreadId tid,
3844                      SizeT szB, SizeT alignB, Bool is_zeroed )
3845 {
3846    Addr        p;
3847    MallocMeta* md;
3848 
3849    tl_assert( ((SSizeT)szB) >= 0 );
3850    p = (Addr)VG_(cli_malloc)(alignB, szB);
3851    if (!p) {
3852       return NULL;
3853    }
3854    if (is_zeroed)
3855       VG_(memset)((void*)p, 0, szB);
3856 
3857    /* Note that map_threads_lookup must succeed (cannot assert), since
3858       memory can only be allocated by currently alive threads, hence
3859       they must have an entry in map_threads. */
3860    md = new_MallocMeta();
3861    md->payload = p;
3862    md->szB     = szB;
3863    md->where   = VG_(record_ExeContext)( tid, 0 );
3864    md->thr     = map_threads_lookup( tid );
3865 
3866    VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md );
3867 
3868    /* Tell the lower level memory wranglers. */
3869    evh__new_mem_heap( p, szB, is_zeroed );
3870 
3871    return (void*)p;
3872 }
3873 
3874 /* Re the checks for less-than-zero (also in hg_cli__realloc below):
3875    Cast to a signed type to catch any unexpectedly negative args.
3876    We're assuming here that the size asked for is not greater than
3877    2^31 bytes (for 32-bit platforms) or 2^63 bytes (for 64-bit
3878    platforms). */
hg_cli__malloc(ThreadId tid,SizeT n)3879 static void* hg_cli__malloc ( ThreadId tid, SizeT n ) {
3880    if (((SSizeT)n) < 0) return NULL;
3881    return handle_alloc ( tid, n, VG_(clo_alignment),
3882                          /*is_zeroed*/False );
3883 }
hg_cli____builtin_new(ThreadId tid,SizeT n)3884 static void* hg_cli____builtin_new ( ThreadId tid, SizeT n ) {
3885    if (((SSizeT)n) < 0) return NULL;
3886    return handle_alloc ( tid, n, VG_(clo_alignment),
3887                          /*is_zeroed*/False );
3888 }
hg_cli____builtin_vec_new(ThreadId tid,SizeT n)3889 static void* hg_cli____builtin_vec_new ( ThreadId tid, SizeT n ) {
3890    if (((SSizeT)n) < 0) return NULL;
3891    return handle_alloc ( tid, n, VG_(clo_alignment),
3892                          /*is_zeroed*/False );
3893 }
hg_cli__memalign(ThreadId tid,SizeT align,SizeT n)3894 static void* hg_cli__memalign ( ThreadId tid, SizeT align, SizeT n ) {
3895    if (((SSizeT)n) < 0) return NULL;
3896    return handle_alloc ( tid, n, align,
3897                          /*is_zeroed*/False );
3898 }
hg_cli__calloc(ThreadId tid,SizeT nmemb,SizeT size1)3899 static void* hg_cli__calloc ( ThreadId tid, SizeT nmemb, SizeT size1 ) {
3900    if ( ((SSizeT)nmemb) < 0 || ((SSizeT)size1) < 0 ) return NULL;
3901    return handle_alloc ( tid, nmemb*size1, VG_(clo_alignment),
3902                          /*is_zeroed*/True );
3903 }
3904 
3905 
3906 /* Free a client block, including getting rid of the relevant
3907    metadata. */
3908 
handle_free(ThreadId tid,void * p)3909 static void handle_free ( ThreadId tid, void* p )
3910 {
3911    MallocMeta *md, *old_md;
3912    SizeT      szB;
3913 
3914    /* First see if we can find the metadata for 'p'. */
3915    md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p );
3916    if (!md)
3917       return; /* apparently freeing a bogus address.  Oh well. */
3918 
3919    tl_assert(md->payload == (Addr)p);
3920    szB = md->szB;
3921 
3922    /* Nuke the metadata block */
3923    old_md = (MallocMeta*)
3924             VG_(HT_remove)( hg_mallocmeta_table, (UWord)p );
3925    tl_assert(old_md); /* it must be present - we just found it */
3926    tl_assert(old_md == md);
3927    tl_assert(old_md->payload == (Addr)p);
3928 
3929    VG_(cli_free)((void*)old_md->payload);
3930    delete_MallocMeta(old_md);
3931 
3932    /* Tell the lower level memory wranglers. */
3933    evh__die_mem_heap( (Addr)p, szB );
3934 }
3935 
hg_cli__free(ThreadId tid,void * p)3936 static void hg_cli__free ( ThreadId tid, void* p ) {
3937    handle_free(tid, p);
3938 }
hg_cli____builtin_delete(ThreadId tid,void * p)3939 static void hg_cli____builtin_delete ( ThreadId tid, void* p ) {
3940    handle_free(tid, p);
3941 }
hg_cli____builtin_vec_delete(ThreadId tid,void * p)3942 static void hg_cli____builtin_vec_delete ( ThreadId tid, void* p ) {
3943    handle_free(tid, p);
3944 }
3945 
3946 
hg_cli__realloc(ThreadId tid,void * payloadV,SizeT new_size)3947 static void* hg_cli__realloc ( ThreadId tid, void* payloadV, SizeT new_size )
3948 {
3949    MallocMeta *md, *md_new, *md_tmp;
3950    SizeT      i;
3951 
3952    Addr payload = (Addr)payloadV;
3953 
3954    if (((SSizeT)new_size) < 0) return NULL;
3955 
3956    md = (MallocMeta*) VG_(HT_lookup)( hg_mallocmeta_table, (UWord)payload );
3957    if (!md)
3958       return NULL; /* apparently realloc-ing a bogus address.  Oh well. */
3959 
3960    tl_assert(md->payload == payload);
3961 
3962    if (md->szB == new_size) {
3963       /* size unchanged */
3964       md->where = VG_(record_ExeContext)(tid, 0);
3965       return payloadV;
3966    }
3967 
3968    if (md->szB > new_size) {
3969       /* new size is smaller */
3970       md->szB   = new_size;
3971       md->where = VG_(record_ExeContext)(tid, 0);
3972       evh__die_mem_heap( md->payload + new_size, md->szB - new_size );
3973       return payloadV;
3974    }
3975 
3976    /* else */ {
3977       /* new size is bigger */
3978       Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
3979 
3980       /* First half kept and copied, second half new */
3981       // FIXME: shouldn't we use a copier which implements the
3982       // memory state machine?
3983       evh__copy_mem( payload, p_new, md->szB );
3984       evh__new_mem_heap ( p_new + md->szB, new_size - md->szB,
3985                           /*inited*/False );
3986       /* FIXME: can anything funny happen here?  specifically, if the
3987          old range contained a lock, then die_mem_heap will complain.
3988          Is that the correct behaviour?  Not sure. */
3989       evh__die_mem_heap( payload, md->szB );
3990 
3991       /* Copy from old to new */
3992       for (i = 0; i < md->szB; i++)
3993          ((UChar*)p_new)[i] = ((UChar*)payload)[i];
3994 
3995       /* Because the metadata hash table is index by payload address,
3996          we have to get rid of the old hash table entry and make a new
3997          one.  We can't just modify the existing metadata in place,
3998          because then it would (almost certainly) be in the wrong hash
3999          chain. */
4000       md_new = new_MallocMeta();
4001       *md_new = *md;
4002 
4003       md_tmp = VG_(HT_remove)( hg_mallocmeta_table, payload );
4004       tl_assert(md_tmp);
4005       tl_assert(md_tmp == md);
4006 
4007       VG_(cli_free)((void*)md->payload);
4008       delete_MallocMeta(md);
4009 
4010       /* Update fields */
4011       md_new->where   = VG_(record_ExeContext)( tid, 0 );
4012       md_new->szB     = new_size;
4013       md_new->payload = p_new;
4014       md_new->thr     = map_threads_lookup( tid );
4015 
4016       /* and add */
4017       VG_(HT_add_node)( hg_mallocmeta_table, (VgHashNode*)md_new );
4018 
4019       return (void*)p_new;
4020    }
4021 }
4022 
hg_cli_malloc_usable_size(ThreadId tid,void * p)4023 static SizeT hg_cli_malloc_usable_size ( ThreadId tid, void* p )
4024 {
4025    MallocMeta *md = VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p );
4026 
4027    // There may be slop, but pretend there isn't because only the asked-for
4028    // area will have been shadowed properly.
4029    return ( md ? md->szB : 0 );
4030 }
4031 
4032 
4033 /* For error creation: map 'data_addr' to a malloc'd chunk, if any.
4034    Slow linear search.  With a bit of hash table help if 'data_addr'
4035    is either the start of a block or up to 15 word-sized steps along
4036    from the start of a block. */
4037 
addr_is_in_MM_Chunk(MallocMeta * mm,Addr a)4038 static inline Bool addr_is_in_MM_Chunk( MallocMeta* mm, Addr a )
4039 {
4040    /* Accept 'a' as within 'mm' if 'mm's size is zero and 'a' points
4041       right at it. */
4042   if (UNLIKELY(mm->szB == 0 && a == mm->payload))
4043      return True;
4044   /* else normal interval rules apply */
4045   if (LIKELY(a < mm->payload)) return False;
4046   if (LIKELY(a >= mm->payload + mm->szB)) return False;
4047   return True;
4048 }
4049 
HG_(mm_find_containing_block)4050 Bool HG_(mm_find_containing_block)( /*OUT*/ExeContext** where,
4051                                     /*OUT*/Addr*        payload,
4052                                     /*OUT*/SizeT*       szB,
4053                                     Addr                data_addr )
4054 {
4055    MallocMeta* mm;
4056    Int i;
4057    const Int n_fast_check_words = 16;
4058 
4059    /* First, do a few fast searches on the basis that data_addr might
4060       be exactly the start of a block or up to 15 words inside.  This
4061       can happen commonly via the creq
4062       _VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK. */
4063    for (i = 0; i < n_fast_check_words; i++) {
4064       mm = VG_(HT_lookup)( hg_mallocmeta_table,
4065                            data_addr - (UWord)(UInt)i * sizeof(UWord) );
4066       if (UNLIKELY(mm && addr_is_in_MM_Chunk(mm, data_addr)))
4067          goto found;
4068    }
4069 
4070    /* Well, this totally sucks.  But without using an interval tree or
4071       some such, it's hard to see how to do better.  We have to check
4072       every block in the entire table. */
4073    VG_(HT_ResetIter)(hg_mallocmeta_table);
4074    while ( (mm = VG_(HT_Next)(hg_mallocmeta_table)) ) {
4075       if (UNLIKELY(addr_is_in_MM_Chunk(mm, data_addr)))
4076          goto found;
4077    }
4078 
4079    /* Not found.  Bah. */
4080    return False;
4081    /*NOTREACHED*/
4082 
4083   found:
4084    tl_assert(mm);
4085    tl_assert(addr_is_in_MM_Chunk(mm, data_addr));
4086    if (where)   *where   = mm->where;
4087    if (payload) *payload = mm->payload;
4088    if (szB)     *szB     = mm->szB;
4089    return True;
4090 }
4091 
4092 
4093 /*--------------------------------------------------------------*/
4094 /*--- Instrumentation                                        ---*/
4095 /*--------------------------------------------------------------*/
4096 
4097 #define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
4098 #define mkexpr(_tmp)             IRExpr_RdTmp((_tmp))
4099 #define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
4100 #define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
4101 #define assign(_t, _e)           IRStmt_WrTmp((_t), (_e))
4102 
instrument_mem_access(IRSB * sbOut,IRExpr * addr,Int szB,Bool isStore,Int hWordTy_szB,Int goff_sp)4103 static void instrument_mem_access ( IRSB*   sbOut,
4104                                     IRExpr* addr,
4105                                     Int     szB,
4106                                     Bool    isStore,
4107                                     Int     hWordTy_szB,
4108                                     Int     goff_sp )
4109 {
4110    IRType   tyAddr   = Ity_INVALID;
4111    HChar*   hName    = NULL;
4112    void*    hAddr    = NULL;
4113    Int      regparms = 0;
4114    IRExpr** argv     = NULL;
4115    IRDirty* di       = NULL;
4116 
4117    // THRESH is the size of the window above SP (well,
4118    // mostly above) that we assume implies a stack reference.
4119    const Int THRESH = 4096 * 4; // somewhat arbitrary
4120    const Int rz_szB = VG_STACK_REDZONE_SZB;
4121 
4122    tl_assert(isIRAtom(addr));
4123    tl_assert(hWordTy_szB == 4 || hWordTy_szB == 8);
4124 
4125    tyAddr = typeOfIRExpr( sbOut->tyenv, addr );
4126    tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
4127 
4128    /* So the effective address is in 'addr' now. */
4129    regparms = 1; // unless stated otherwise
4130    if (isStore) {
4131       switch (szB) {
4132          case 1:
4133             hName = "evh__mem_help_cwrite_1";
4134             hAddr = &evh__mem_help_cwrite_1;
4135             argv = mkIRExprVec_1( addr );
4136             break;
4137          case 2:
4138             hName = "evh__mem_help_cwrite_2";
4139             hAddr = &evh__mem_help_cwrite_2;
4140             argv = mkIRExprVec_1( addr );
4141             break;
4142          case 4:
4143             hName = "evh__mem_help_cwrite_4";
4144             hAddr = &evh__mem_help_cwrite_4;
4145             argv = mkIRExprVec_1( addr );
4146             break;
4147          case 8:
4148             hName = "evh__mem_help_cwrite_8";
4149             hAddr = &evh__mem_help_cwrite_8;
4150             argv = mkIRExprVec_1( addr );
4151             break;
4152          default:
4153             tl_assert(szB > 8 && szB <= 512); /* stay sane */
4154             regparms = 2;
4155             hName = "evh__mem_help_cwrite_N";
4156             hAddr = &evh__mem_help_cwrite_N;
4157             argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB ));
4158             break;
4159       }
4160    } else {
4161       switch (szB) {
4162          case 1:
4163             hName = "evh__mem_help_cread_1";
4164             hAddr = &evh__mem_help_cread_1;
4165             argv = mkIRExprVec_1( addr );
4166             break;
4167          case 2:
4168             hName = "evh__mem_help_cread_2";
4169             hAddr = &evh__mem_help_cread_2;
4170             argv = mkIRExprVec_1( addr );
4171             break;
4172          case 4:
4173             hName = "evh__mem_help_cread_4";
4174             hAddr = &evh__mem_help_cread_4;
4175             argv = mkIRExprVec_1( addr );
4176             break;
4177          case 8:
4178             hName = "evh__mem_help_cread_8";
4179             hAddr = &evh__mem_help_cread_8;
4180             argv = mkIRExprVec_1( addr );
4181             break;
4182          default:
4183             tl_assert(szB > 8 && szB <= 512); /* stay sane */
4184             regparms = 2;
4185             hName = "evh__mem_help_cread_N";
4186             hAddr = &evh__mem_help_cread_N;
4187             argv = mkIRExprVec_2( addr, mkIRExpr_HWord( szB ));
4188             break;
4189       }
4190    }
4191 
4192    /* Create the helper. */
4193    tl_assert(hName);
4194    tl_assert(hAddr);
4195    tl_assert(argv);
4196    di = unsafeIRDirty_0_N( regparms,
4197                            hName, VG_(fnptr_to_fnentry)( hAddr ),
4198                            argv );
4199 
4200    if (! HG_(clo_check_stack_refs)) {
4201       /* We're ignoring memory references which are (obviously) to the
4202          stack.  In fact just skip stack refs that are within 4 pages
4203          of SP (SP - the redzone, really), as that's simple, easy, and
4204          filters out most stack references. */
4205       /* Generate the guard condition: "(addr - (SP - RZ)) >u N", for
4206          some arbitrary N.  If that is true then addr is outside the
4207          range (SP - RZ .. SP + N - RZ).  If N is smallish (a few
4208          pages) then we can say addr is within a few pages of SP and
4209          so can't possibly be a heap access, and so can be skipped.
4210 
4211          Note that the condition simplifies to
4212             (addr - SP + RZ) >u N
4213          which generates better code in x86/amd64 backends, but it does
4214          not unfortunately simplify to
4215             (addr - SP) >u (N - RZ)
4216          (would be beneficial because N - RZ is a constant) because
4217          wraparound arithmetic messes up the comparison.  eg.
4218          20 >u 10 == True,
4219          but (20 - 15) >u (10 - 15) == 5 >u (MAXINT-5) == False.
4220       */
4221       IRTemp sp = newIRTemp(sbOut->tyenv, tyAddr);
4222       addStmtToIRSB( sbOut, assign(sp, IRExpr_Get(goff_sp, tyAddr)));
4223 
4224       /* "addr - SP" */
4225       IRTemp addr_minus_sp = newIRTemp(sbOut->tyenv, tyAddr);
4226       addStmtToIRSB(
4227          sbOut,
4228          assign(addr_minus_sp,
4229                 tyAddr == Ity_I32
4230                    ? binop(Iop_Sub32, addr, mkexpr(sp))
4231                    : binop(Iop_Sub64, addr, mkexpr(sp)))
4232       );
4233 
4234       /* "addr - SP + RZ" */
4235       IRTemp diff = newIRTemp(sbOut->tyenv, tyAddr);
4236       addStmtToIRSB(
4237          sbOut,
4238          assign(diff,
4239                 tyAddr == Ity_I32
4240                    ? binop(Iop_Add32, mkexpr(addr_minus_sp), mkU32(rz_szB))
4241                    : binop(Iop_Add64, mkexpr(addr_minus_sp), mkU64(rz_szB)))
4242       );
4243 
4244       IRTemp guard = newIRTemp(sbOut->tyenv, Ity_I1);
4245       addStmtToIRSB(
4246          sbOut,
4247          assign(guard,
4248                 tyAddr == Ity_I32
4249                    ? binop(Iop_CmpLT32U, mkU32(THRESH), mkexpr(diff))
4250                    : binop(Iop_CmpLT64U, mkU64(THRESH), mkexpr(diff)))
4251       );
4252       di->guard = mkexpr(guard);
4253    }
4254 
4255    /* Add the helper. */
4256    addStmtToIRSB( sbOut, IRStmt_Dirty(di) );
4257 }
4258 
4259 
4260 /* Figure out if GA is a guest code address in the dynamic linker, and
4261    if so return True.  Otherwise (and in case of any doubt) return
4262    False.  (sidedly safe w/ False as the safe value) */
is_in_dynamic_linker_shared_object(Addr64 ga)4263 static Bool is_in_dynamic_linker_shared_object( Addr64 ga )
4264 {
4265    DebugInfo* dinfo;
4266    const UChar* soname;
4267    if (0) return False;
4268 
4269    dinfo = VG_(find_DebugInfo)( (Addr)ga );
4270    if (!dinfo) return False;
4271 
4272    soname = VG_(DebugInfo_get_soname)(dinfo);
4273    tl_assert(soname);
4274    if (0) VG_(printf)("%s\n", soname);
4275 
4276 #  if defined(VGO_linux)
4277    if (VG_STREQ(soname, VG_U_LD_LINUX_SO_3))        return True;
4278    if (VG_STREQ(soname, VG_U_LD_LINUX_SO_2))        return True;
4279    if (VG_STREQ(soname, VG_U_LD_LINUX_X86_64_SO_2)) return True;
4280    if (VG_STREQ(soname, VG_U_LD64_SO_1))            return True;
4281    if (VG_STREQ(soname, VG_U_LD_SO_1))              return True;
4282 #  elif defined(VGO_darwin)
4283    if (VG_STREQ(soname, VG_U_DYLD)) return True;
4284 #  else
4285 #    error "Unsupported OS"
4286 #  endif
4287    return False;
4288 }
4289 
4290 static
hg_instrument(VgCallbackClosure * closure,IRSB * bbIn,VexGuestLayout * layout,VexGuestExtents * vge,IRType gWordTy,IRType hWordTy)4291 IRSB* hg_instrument ( VgCallbackClosure* closure,
4292                       IRSB* bbIn,
4293                       VexGuestLayout* layout,
4294                       VexGuestExtents* vge,
4295                       IRType gWordTy, IRType hWordTy )
4296 {
4297    Int     i;
4298    IRSB*   bbOut;
4299    Addr64  cia; /* address of current insn */
4300    IRStmt* st;
4301    Bool    inLDSO = False;
4302    Addr64  inLDSOmask4K = 1; /* mismatches on first check */
4303 
4304    const Int goff_sp = layout->offset_SP;
4305 
4306    if (gWordTy != hWordTy) {
4307       /* We don't currently support this case. */
4308       VG_(tool_panic)("host/guest word size mismatch");
4309    }
4310 
4311    if (VKI_PAGE_SIZE < 4096 || VG_(log2)(VKI_PAGE_SIZE) == -1) {
4312       VG_(tool_panic)("implausible or too-small VKI_PAGE_SIZE");
4313    }
4314 
4315    /* Set up BB */
4316    bbOut           = emptyIRSB();
4317    bbOut->tyenv    = deepCopyIRTypeEnv(bbIn->tyenv);
4318    bbOut->next     = deepCopyIRExpr(bbIn->next);
4319    bbOut->jumpkind = bbIn->jumpkind;
4320 
4321    // Copy verbatim any IR preamble preceding the first IMark
4322    i = 0;
4323    while (i < bbIn->stmts_used && bbIn->stmts[i]->tag != Ist_IMark) {
4324       addStmtToIRSB( bbOut, bbIn->stmts[i] );
4325       i++;
4326    }
4327 
4328    // Get the first statement, and initial cia from it
4329    tl_assert(bbIn->stmts_used > 0);
4330    tl_assert(i < bbIn->stmts_used);
4331    st = bbIn->stmts[i];
4332    tl_assert(Ist_IMark == st->tag);
4333    cia = st->Ist.IMark.addr;
4334    st = NULL;
4335 
4336    for (/*use current i*/; i < bbIn->stmts_used; i++) {
4337       st = bbIn->stmts[i];
4338       tl_assert(st);
4339       tl_assert(isFlatIRStmt(st));
4340       switch (st->tag) {
4341          case Ist_NoOp:
4342          case Ist_AbiHint:
4343          case Ist_Put:
4344          case Ist_PutI:
4345          case Ist_Exit:
4346             /* None of these can contain any memory references. */
4347             break;
4348 
4349          case Ist_IMark:
4350             /* no mem refs, but note the insn address. */
4351             cia = st->Ist.IMark.addr;
4352             /* Don't instrument the dynamic linker.  It generates a
4353                lot of races which we just expensively suppress, so
4354                it's pointless.
4355 
4356                Avoid flooding is_in_dynamic_linker_shared_object with
4357                requests by only checking at transitions between 4K
4358                pages. */
4359             if ((cia & ~(Addr64)0xFFF) != inLDSOmask4K) {
4360                if (0) VG_(printf)("NEW %#lx\n", (Addr)cia);
4361                inLDSOmask4K = cia & ~(Addr64)0xFFF;
4362                inLDSO = is_in_dynamic_linker_shared_object(cia);
4363             } else {
4364                if (0) VG_(printf)("old %#lx\n", (Addr)cia);
4365             }
4366             break;
4367 
4368          case Ist_MBE:
4369             switch (st->Ist.MBE.event) {
4370                case Imbe_Fence:
4371                   break; /* not interesting */
4372                default:
4373                   goto unhandled;
4374             }
4375             break;
4376 
4377          case Ist_CAS: {
4378             /* Atomic read-modify-write cycle.  Just pretend it's a
4379                read. */
4380             IRCAS* cas    = st->Ist.CAS.details;
4381             Bool   isDCAS = cas->oldHi != IRTemp_INVALID;
4382             if (isDCAS) {
4383                tl_assert(cas->expdHi);
4384                tl_assert(cas->dataHi);
4385             } else {
4386                tl_assert(!cas->expdHi);
4387                tl_assert(!cas->dataHi);
4388             }
4389             /* Just be boring about it. */
4390             if (!inLDSO) {
4391                instrument_mem_access(
4392                   bbOut,
4393                   cas->addr,
4394                   (isDCAS ? 2 : 1)
4395                      * sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)),
4396                   False/*!isStore*/,
4397                   sizeofIRType(hWordTy), goff_sp
4398                );
4399             }
4400             break;
4401          }
4402 
4403          case Ist_LLSC: {
4404             /* We pretend store-conditionals don't exist, viz, ignore
4405                them.  Whereas load-linked's are treated the same as
4406                normal loads. */
4407             IRType dataTy;
4408             if (st->Ist.LLSC.storedata == NULL) {
4409                /* LL */
4410                dataTy = typeOfIRTemp(bbIn->tyenv, st->Ist.LLSC.result);
4411                if (!inLDSO) {
4412                   instrument_mem_access(
4413                      bbOut,
4414                      st->Ist.LLSC.addr,
4415                      sizeofIRType(dataTy),
4416                      False/*!isStore*/,
4417                      sizeofIRType(hWordTy), goff_sp
4418                   );
4419                }
4420             } else {
4421                /* SC */
4422                /*ignore */
4423             }
4424             break;
4425          }
4426 
4427          case Ist_Store:
4428             /* It seems we pretend that store-conditionals don't
4429                exist, viz, just ignore them ... */
4430             if (!inLDSO) {
4431                instrument_mem_access(
4432                   bbOut,
4433                   st->Ist.Store.addr,
4434                   sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)),
4435                   True/*isStore*/,
4436                   sizeofIRType(hWordTy), goff_sp
4437                );
4438             }
4439             break;
4440 
4441          case Ist_WrTmp: {
4442             /* ... whereas here we don't care whether a load is a
4443                vanilla one or a load-linked. */
4444             IRExpr* data = st->Ist.WrTmp.data;
4445             if (data->tag == Iex_Load) {
4446                if (!inLDSO) {
4447                   instrument_mem_access(
4448                      bbOut,
4449                      data->Iex.Load.addr,
4450                      sizeofIRType(data->Iex.Load.ty),
4451                      False/*!isStore*/,
4452                      sizeofIRType(hWordTy), goff_sp
4453                   );
4454                }
4455             }
4456             break;
4457          }
4458 
4459          case Ist_Dirty: {
4460             Int      dataSize;
4461             IRDirty* d = st->Ist.Dirty.details;
4462             if (d->mFx != Ifx_None) {
4463                /* This dirty helper accesses memory.  Collect the
4464                   details. */
4465                tl_assert(d->mAddr != NULL);
4466                tl_assert(d->mSize != 0);
4467                dataSize = d->mSize;
4468                if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
4469                   if (!inLDSO) {
4470                      instrument_mem_access(
4471                         bbOut, d->mAddr, dataSize, False/*!isStore*/,
4472                         sizeofIRType(hWordTy), goff_sp
4473                      );
4474                   }
4475                }
4476                if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
4477                   if (!inLDSO) {
4478                      instrument_mem_access(
4479                         bbOut, d->mAddr, dataSize, True/*isStore*/,
4480                         sizeofIRType(hWordTy), goff_sp
4481                      );
4482                   }
4483                }
4484             } else {
4485                tl_assert(d->mAddr == NULL);
4486                tl_assert(d->mSize == 0);
4487             }
4488             break;
4489          }
4490 
4491          default:
4492          unhandled:
4493             ppIRStmt(st);
4494             tl_assert(0);
4495 
4496       } /* switch (st->tag) */
4497 
4498       addStmtToIRSB( bbOut, st );
4499    } /* iterate over bbIn->stmts */
4500 
4501    return bbOut;
4502 }
4503 
4504 #undef binop
4505 #undef mkexpr
4506 #undef mkU32
4507 #undef mkU64
4508 #undef assign
4509 
4510 
4511 /*----------------------------------------------------------------*/
4512 /*--- Client requests                                          ---*/
4513 /*----------------------------------------------------------------*/
4514 
4515 /* Sheesh.  Yet another goddam finite map. */
4516 static WordFM* map_pthread_t_to_Thread = NULL; /* pthread_t -> Thread* */
4517 
map_pthread_t_to_Thread_INIT(void)4518 static void map_pthread_t_to_Thread_INIT ( void ) {
4519    if (UNLIKELY(map_pthread_t_to_Thread == NULL)) {
4520       map_pthread_t_to_Thread = VG_(newFM)( HG_(zalloc), "hg.mpttT.1",
4521                                             HG_(free), NULL );
4522       tl_assert(map_pthread_t_to_Thread != NULL);
4523    }
4524 }
4525 
4526 
4527 static
hg_handle_client_request(ThreadId tid,UWord * args,UWord * ret)4528 Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret)
4529 {
4530    if (!VG_IS_TOOL_USERREQ('H','G',args[0]))
4531       return False;
4532 
4533    /* Anything that gets past the above check is one of ours, so we
4534       should be able to handle it. */
4535 
4536    /* default, meaningless return value, unless otherwise set */
4537    *ret = 0;
4538 
4539    switch (args[0]) {
4540 
4541       /* --- --- User-visible client requests --- --- */
4542 
4543       case VG_USERREQ__HG_CLEAN_MEMORY:
4544          if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY(%#lx,%ld)\n",
4545                             args[1], args[2]);
4546          /* Call die_mem to (expensively) tidy up properly, if there
4547             are any held locks etc in the area.  Calling evh__die_mem
4548             and then evh__new_mem is a bit inefficient; probably just
4549             the latter would do. */
4550          if (args[2] > 0) { /* length */
4551             evh__die_mem(args[1], args[2]);
4552             /* and then set it to New */
4553             evh__new_mem(args[1], args[2]);
4554          }
4555          break;
4556 
4557       case _VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK: {
4558          Addr  payload = 0;
4559          SizeT pszB = 0;
4560          if (0) VG_(printf)("VG_USERREQ__HG_CLEAN_MEMORY_HEAPBLOCK(%#lx)\n",
4561                             args[1]);
4562          if (HG_(mm_find_containing_block)(NULL, &payload, &pszB, args[1])) {
4563             if (pszB > 0) {
4564                evh__die_mem(payload, pszB);
4565                evh__new_mem(payload, pszB);
4566             }
4567             *ret = pszB;
4568          } else {
4569             *ret = (UWord)-1;
4570          }
4571          break;
4572       }
4573 
4574       case _VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED:
4575          if (0) VG_(printf)("HG_ARANGE_MAKE_UNTRACKED(%#lx,%ld)\n",
4576                             args[1], args[2]);
4577          if (args[2] > 0) { /* length */
4578             evh__untrack_mem(args[1], args[2]);
4579          }
4580          break;
4581 
4582       case _VG_USERREQ__HG_ARANGE_MAKE_TRACKED:
4583          if (0) VG_(printf)("HG_ARANGE_MAKE_TRACKED(%#lx,%ld)\n",
4584                             args[1], args[2]);
4585          if (args[2] > 0) { /* length */
4586             evh__new_mem(args[1], args[2]);
4587          }
4588          break;
4589 
4590       /* --- --- Client requests for Helgrind's use only --- --- */
4591 
4592       /* Some thread is telling us its pthread_t value.  Record the
4593          binding between that and the associated Thread*, so we can
4594          later find the Thread* again when notified of a join by the
4595          thread. */
4596       case _VG_USERREQ__HG_SET_MY_PTHREAD_T: {
4597          Thread* my_thr = NULL;
4598          if (0)
4599          VG_(printf)("SET_MY_PTHREAD_T (tid %d): pthread_t = %p\n", (Int)tid,
4600                      (void*)args[1]);
4601          map_pthread_t_to_Thread_INIT();
4602          my_thr = map_threads_maybe_lookup( tid );
4603          /* This assertion should hold because the map_threads (tid to
4604             Thread*) binding should have been made at the point of
4605             low-level creation of this thread, which should have
4606             happened prior to us getting this client request for it.
4607             That's because this client request is sent from
4608             client-world from the 'thread_wrapper' function, which
4609             only runs once the thread has been low-level created. */
4610          tl_assert(my_thr != NULL);
4611          /* So now we know that (pthread_t)args[1] is associated with
4612             (Thread*)my_thr.  Note that down. */
4613          if (0)
4614          VG_(printf)("XXXX: bind pthread_t %p to Thread* %p\n",
4615                      (void*)args[1], (void*)my_thr );
4616          VG_(addToFM)( map_pthread_t_to_Thread, (Word)args[1], (Word)my_thr );
4617          break;
4618       }
4619 
4620       case _VG_USERREQ__HG_PTH_API_ERROR: {
4621          Thread* my_thr = NULL;
4622          map_pthread_t_to_Thread_INIT();
4623          my_thr = map_threads_maybe_lookup( tid );
4624          tl_assert(my_thr); /* See justification above in SET_MY_PTHREAD_T */
4625          HG_(record_error_PthAPIerror)(
4626             my_thr, (HChar*)args[1], (Word)args[2], (HChar*)args[3] );
4627          break;
4628       }
4629 
4630       /* This thread (tid) has completed a join with the quitting
4631          thread whose pthread_t is in args[1]. */
4632       case _VG_USERREQ__HG_PTHREAD_JOIN_POST: {
4633          Thread* thr_q = NULL; /* quitter Thread* */
4634          Bool    found = False;
4635          if (0)
4636          VG_(printf)("NOTIFY_JOIN_COMPLETE (tid %d): quitter = %p\n", (Int)tid,
4637                      (void*)args[1]);
4638          map_pthread_t_to_Thread_INIT();
4639          found = VG_(lookupFM)( map_pthread_t_to_Thread,
4640                                 NULL, (Word*)&thr_q, (Word)args[1] );
4641           /* Can this fail?  It would mean that our pthread_join
4642              wrapper observed a successful join on args[1] yet that
4643              thread never existed (or at least, it never lodged an
4644              entry in the mapping (via SET_MY_PTHREAD_T)).  Which
4645              sounds like a bug in the threads library. */
4646          // FIXME: get rid of this assertion; handle properly
4647          tl_assert(found);
4648          if (found) {
4649             if (0)
4650             VG_(printf)(".................... quitter Thread* = %p\n",
4651                         thr_q);
4652             evh__HG_PTHREAD_JOIN_POST( tid, thr_q );
4653          }
4654          break;
4655       }
4656 
4657       /* EXPOSITION only: by intercepting lock init events we can show
4658          the user where the lock was initialised, rather than only
4659          being able to show where it was first locked.  Intercepting
4660          lock initialisations is not necessary for the basic operation
4661          of the race checker. */
4662       case _VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST:
4663          evh__HG_PTHREAD_MUTEX_INIT_POST( tid, (void*)args[1], args[2] );
4664          break;
4665 
4666       case _VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE:
4667          evh__HG_PTHREAD_MUTEX_DESTROY_PRE( tid, (void*)args[1] );
4668          break;
4669 
4670       case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE:   // pth_mx_t*
4671          evh__HG_PTHREAD_MUTEX_UNLOCK_PRE( tid, (void*)args[1] );
4672          break;
4673 
4674       case _VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST:  // pth_mx_t*
4675          evh__HG_PTHREAD_MUTEX_UNLOCK_POST( tid, (void*)args[1] );
4676          break;
4677 
4678       case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE:     // pth_mx_t*, Word
4679          evh__HG_PTHREAD_MUTEX_LOCK_PRE( tid, (void*)args[1], args[2] );
4680          break;
4681 
4682       case _VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST:    // pth_mx_t*
4683          evh__HG_PTHREAD_MUTEX_LOCK_POST( tid, (void*)args[1] );
4684          break;
4685 
4686       /* This thread is about to do pthread_cond_signal on the
4687          pthread_cond_t* in arg[1].  Ditto pthread_cond_broadcast. */
4688       case _VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE:
4689       case _VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE:
4690          evh__HG_PTHREAD_COND_SIGNAL_PRE( tid, (void*)args[1] );
4691          break;
4692 
4693       /* Entry into pthread_cond_wait, cond=arg[1], mutex=arg[2].
4694          Returns a flag indicating whether or not the mutex is believed to be
4695          valid for this operation. */
4696       case _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE: {
4697          Bool mutex_is_valid
4698             = evh__HG_PTHREAD_COND_WAIT_PRE( tid, (void*)args[1],
4699                                                   (void*)args[2] );
4700          *ret = mutex_is_valid ? 1 : 0;
4701          break;
4702       }
4703 
4704       /* cond=arg[1] */
4705       case _VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE:
4706          evh__HG_PTHREAD_COND_DESTROY_PRE( tid, (void*)args[1] );
4707          break;
4708 
4709       /* Thread successfully completed pthread_cond_wait, cond=arg[1],
4710          mutex=arg[2] */
4711       case _VG_USERREQ__HG_PTHREAD_COND_WAIT_POST:
4712          evh__HG_PTHREAD_COND_WAIT_POST( tid,
4713                                          (void*)args[1], (void*)args[2] );
4714          break;
4715 
4716       case _VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST:
4717          evh__HG_PTHREAD_RWLOCK_INIT_POST( tid, (void*)args[1] );
4718          break;
4719 
4720       case _VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE:
4721          evh__HG_PTHREAD_RWLOCK_DESTROY_PRE( tid, (void*)args[1] );
4722          break;
4723 
4724       /* rwlock=arg[1], isW=arg[2], isTryLock=arg[3] */
4725       case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE:
4726          evh__HG_PTHREAD_RWLOCK_LOCK_PRE( tid, (void*)args[1],
4727                                                args[2], args[3] );
4728          break;
4729 
4730       /* rwlock=arg[1], isW=arg[2] */
4731       case _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST:
4732          evh__HG_PTHREAD_RWLOCK_LOCK_POST( tid, (void*)args[1], args[2] );
4733          break;
4734 
4735       case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE:
4736          evh__HG_PTHREAD_RWLOCK_UNLOCK_PRE( tid, (void*)args[1] );
4737          break;
4738 
4739       case _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST:
4740          evh__HG_PTHREAD_RWLOCK_UNLOCK_POST( tid, (void*)args[1] );
4741          break;
4742 
4743       case _VG_USERREQ__HG_POSIX_SEM_INIT_POST: /* sem_t*, unsigned long */
4744          evh__HG_POSIX_SEM_INIT_POST( tid, (void*)args[1], args[2] );
4745          break;
4746 
4747       case _VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE: /* sem_t* */
4748          evh__HG_POSIX_SEM_DESTROY_PRE( tid, (void*)args[1] );
4749          break;
4750 
4751       case _VG_USERREQ__HG_POSIX_SEM_POST_PRE: /* sem_t* */
4752          evh__HG_POSIX_SEM_POST_PRE( tid, (void*)args[1] );
4753          break;
4754 
4755       case _VG_USERREQ__HG_POSIX_SEM_WAIT_POST: /* sem_t* */
4756          evh__HG_POSIX_SEM_WAIT_POST( tid, (void*)args[1] );
4757          break;
4758 
4759       case _VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE:
4760          /* pth_bar_t*, ulong count, ulong resizable */
4761          evh__HG_PTHREAD_BARRIER_INIT_PRE( tid, (void*)args[1],
4762                                                 args[2], args[3] );
4763          break;
4764 
4765       case _VG_USERREQ__HG_PTHREAD_BARRIER_RESIZE_PRE:
4766          /* pth_bar_t*, ulong newcount */
4767          evh__HG_PTHREAD_BARRIER_RESIZE_PRE ( tid, (void*)args[1],
4768                                               args[2] );
4769          break;
4770 
4771       case _VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE:
4772          /* pth_bar_t* */
4773          evh__HG_PTHREAD_BARRIER_WAIT_PRE( tid, (void*)args[1] );
4774          break;
4775 
4776       case _VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE:
4777          /* pth_bar_t* */
4778          evh__HG_PTHREAD_BARRIER_DESTROY_PRE( tid, (void*)args[1] );
4779          break;
4780 
4781       case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE:
4782          /* pth_spinlock_t* */
4783          evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE( tid, (void*)args[1] );
4784          break;
4785 
4786       case _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST:
4787          /* pth_spinlock_t* */
4788          evh__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST( tid, (void*)args[1] );
4789          break;
4790 
4791       case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE:
4792          /* pth_spinlock_t*, Word */
4793          evh__HG_PTHREAD_SPIN_LOCK_PRE( tid, (void*)args[1], args[2] );
4794          break;
4795 
4796       case _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST:
4797          /* pth_spinlock_t* */
4798          evh__HG_PTHREAD_SPIN_LOCK_POST( tid, (void*)args[1] );
4799          break;
4800 
4801       case _VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE:
4802          /* pth_spinlock_t* */
4803          evh__HG_PTHREAD_SPIN_DESTROY_PRE( tid, (void*)args[1] );
4804          break;
4805 
4806       case _VG_USERREQ__HG_CLIENTREQ_UNIMP: {
4807          /* char* who */
4808          HChar*  who = (HChar*)args[1];
4809          HChar   buf[50 + 50];
4810          Thread* thr = map_threads_maybe_lookup( tid );
4811          tl_assert( thr ); /* I must be mapped */
4812          tl_assert( who );
4813          tl_assert( VG_(strlen)(who) <= 50 );
4814          VG_(sprintf)(buf, "Unimplemented client request macro \"%s\"", who );
4815          /* record_error_Misc strdup's buf, so this is safe: */
4816          HG_(record_error_Misc)( thr, buf );
4817          break;
4818       }
4819 
4820       case _VG_USERREQ__HG_USERSO_SEND_PRE:
4821          /* UWord arbitrary-SO-tag */
4822          evh__HG_USERSO_SEND_PRE( tid, args[1] );
4823          break;
4824 
4825       case _VG_USERREQ__HG_USERSO_RECV_POST:
4826          /* UWord arbitrary-SO-tag */
4827          evh__HG_USERSO_RECV_POST( tid, args[1] );
4828          break;
4829 
4830       case _VG_USERREQ__HG_USERSO_FORGET_ALL:
4831          /* UWord arbitrary-SO-tag */
4832          evh__HG_USERSO_FORGET_ALL( tid, args[1] );
4833          break;
4834 
4835       default:
4836          /* Unhandled Helgrind client request! */
4837          tl_assert2(0, "unhandled Helgrind client request 0x%lx",
4838                        args[0]);
4839    }
4840 
4841    return True;
4842 }
4843 
4844 
4845 /*----------------------------------------------------------------*/
4846 /*--- Setup                                                    ---*/
4847 /*----------------------------------------------------------------*/
4848 
hg_process_cmd_line_option(Char * arg)4849 static Bool hg_process_cmd_line_option ( Char* arg )
4850 {
4851    Char* tmp_str;
4852 
4853    if      VG_BOOL_CLO(arg, "--track-lockorders",
4854                             HG_(clo_track_lockorders)) {}
4855    else if VG_BOOL_CLO(arg, "--cmp-race-err-addrs",
4856                             HG_(clo_cmp_race_err_addrs)) {}
4857 
4858    else if VG_XACT_CLO(arg, "--history-level=none",
4859                             HG_(clo_history_level), 0);
4860    else if VG_XACT_CLO(arg, "--history-level=approx",
4861                             HG_(clo_history_level), 1);
4862    else if VG_XACT_CLO(arg, "--history-level=full",
4863                             HG_(clo_history_level), 2);
4864 
4865    /* If you change the 10k/30mill limits, remember to also change
4866       them in assertions at the top of event_map_maybe_GC. */
4867    else if VG_BINT_CLO(arg, "--conflict-cache-size",
4868                        HG_(clo_conflict_cache_size), 10*1000, 30*1000*1000) {}
4869 
4870    /* "stuvwx" --> stuvwx (binary) */
4871    else if VG_STR_CLO(arg, "--hg-sanity-flags", tmp_str) {
4872       Int j;
4873 
4874       if (6 != VG_(strlen)(tmp_str)) {
4875          VG_(message)(Vg_UserMsg,
4876                       "--hg-sanity-flags argument must have 6 digits\n");
4877          return False;
4878       }
4879       for (j = 0; j < 6; j++) {
4880          if      ('0' == tmp_str[j]) { /* do nothing */ }
4881          else if ('1' == tmp_str[j]) HG_(clo_sanity_flags) |= (1 << (6-1-j));
4882          else {
4883             VG_(message)(Vg_UserMsg, "--hg-sanity-flags argument can "
4884                                      "only contain 0s and 1s\n");
4885             return False;
4886          }
4887       }
4888       if (0) VG_(printf)("XXX sanity flags: 0x%lx\n", HG_(clo_sanity_flags));
4889    }
4890 
4891    else if VG_BOOL_CLO(arg, "--free-is-write",
4892                             HG_(clo_free_is_write)) {}
4893 
4894    else if VG_XACT_CLO(arg, "--vts-pruning=never",
4895                             HG_(clo_vts_pruning), 0);
4896    else if VG_XACT_CLO(arg, "--vts-pruning=auto",
4897                             HG_(clo_vts_pruning), 1);
4898    else if VG_XACT_CLO(arg, "--vts-pruning=always",
4899                             HG_(clo_vts_pruning), 2);
4900 
4901    else if VG_BOOL_CLO(arg, "--check-stack-refs",
4902                             HG_(clo_check_stack_refs)) {}
4903 
4904    else
4905       return VG_(replacement_malloc_process_cmd_line_option)(arg);
4906 
4907    return True;
4908 }
4909 
hg_print_usage(void)4910 static void hg_print_usage ( void )
4911 {
4912    VG_(printf)(
4913 "    --free-is-write=no|yes    treat heap frees as writes [no]\n"
4914 "    --track-lockorders=no|yes show lock ordering errors? [yes]\n"
4915 "    --history-level=none|approx|full [full]\n"
4916 "       full:   show both stack traces for a data race (can be very slow)\n"
4917 "       approx: full trace for one thread, approx for the other (faster)\n"
4918 "       none:   only show trace for one thread in a race (fastest)\n"
4919 "    --conflict-cache-size=N   size of 'full' history cache [1000000]\n"
4920 "    --check-stack-refs=no|yes race-check reads and writes on the\n"
4921 "                              main stack and thread stacks? [yes]\n"
4922    );
4923 }
4924 
hg_print_debug_usage(void)4925 static void hg_print_debug_usage ( void )
4926 {
4927    VG_(printf)("    --cmp-race-err-addrs=no|yes  are data addresses in "
4928                "race errors significant? [no]\n");
4929    VG_(printf)("    --hg-sanity-flags=<XXXXXX>   sanity check "
4930                "  at events (X = 0|1) [000000]\n");
4931    VG_(printf)("    --hg-sanity-flags values:\n");
4932    VG_(printf)("       010000   after changes to "
4933                "lock-order-acquisition-graph\n");
4934    VG_(printf)("       001000   at memory accesses (NB: not currently used)\n");
4935    VG_(printf)("       000100   at mem permission setting for "
4936                "ranges >= %d bytes\n", SCE_BIGRANGE_T);
4937    VG_(printf)("       000010   at lock/unlock events\n");
4938    VG_(printf)("       000001   at thread create/join events\n");
4939    VG_(printf)(
4940 "    --vts-pruning=never|auto|always [auto]\n"
4941 "       never:   is never done (may cause big space leaks in Helgrind)\n"
4942 "       auto:    done just often enough to keep space usage under control\n"
4943 "       always:  done after every VTS GC (mostly just a big time waster)\n"
4944     );
4945 }
4946 
hg_fini(Int exitcode)4947 static void hg_fini ( Int exitcode )
4948 {
4949    if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
4950       VG_(message)(Vg_UserMsg,
4951                    "For counts of detected and suppressed errors, "
4952                    "rerun with: -v\n");
4953    }
4954 
4955    if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)
4956        && HG_(clo_history_level) >= 2) {
4957       VG_(umsg)(
4958          "Use --history-level=approx or =none to gain increased speed, at\n" );
4959       VG_(umsg)(
4960          "the cost of reduced accuracy of conflicting-access information\n");
4961    }
4962 
4963    if (SHOW_DATA_STRUCTURES)
4964       pp_everything( PP_ALL, "SK_(fini)" );
4965    if (HG_(clo_sanity_flags))
4966       all__sanity_check("SK_(fini)");
4967 
4968    if (VG_(clo_stats)) {
4969 
4970       if (1) {
4971          VG_(printf)("\n");
4972          HG_(ppWSUstats)( univ_lsets, "univ_lsets" );
4973          if (HG_(clo_track_lockorders)) {
4974             VG_(printf)("\n");
4975             HG_(ppWSUstats)( univ_laog,  "univ_laog" );
4976          }
4977       }
4978 
4979       //zz       VG_(printf)("\n");
4980       //zz       VG_(printf)(" hbefore: %'10lu queries\n",        stats__hbefore_queries);
4981       //zz       VG_(printf)(" hbefore: %'10lu cache 0 hits\n",   stats__hbefore_cache0s);
4982       //zz       VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs);
4983       //zz       VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches);
4984       //zz       VG_(printf)(" hbefore: %'10lu   of which slow\n",
4985       //zz                   stats__hbefore_gsearches - stats__hbefore_gsearchFs);
4986       //zz       VG_(printf)(" hbefore: %'10lu stack high water mark\n",
4987       //zz                   stats__hbefore_stk_hwm);
4988       //zz       VG_(printf)(" hbefore: %'10lu cache invals\n",   stats__hbefore_invals);
4989       //zz       VG_(printf)(" hbefore: %'10lu probes\n",         stats__hbefore_probes);
4990 
4991       VG_(printf)("\n");
4992       VG_(printf)("        locksets: %'8d unique lock sets\n",
4993                   (Int)HG_(cardinalityWSU)( univ_lsets ));
4994       if (HG_(clo_track_lockorders)) {
4995          VG_(printf)("       univ_laog: %'8d unique lock sets\n",
4996                      (Int)HG_(cardinalityWSU)( univ_laog ));
4997       }
4998 
4999       //VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n",
5000       //            stats__ga_LL_adds,
5001       //            (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) );
5002 
5003       VG_(printf)("  LockN-to-P map: %'8llu queries (%llu map size)\n",
5004                   HG_(stats__LockN_to_P_queries),
5005                   HG_(stats__LockN_to_P_get_map_size)() );
5006 
5007       VG_(printf)("string table map: %'8llu queries (%llu map size)\n",
5008                   HG_(stats__string_table_queries),
5009                   HG_(stats__string_table_get_map_size)() );
5010       if (HG_(clo_track_lockorders)) {
5011          VG_(printf)("            LAOG: %'8d map size\n",
5012                      (Int)(laog ? VG_(sizeFM)( laog ) : 0));
5013          VG_(printf)(" LAOG exposition: %'8d map size\n",
5014                      (Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0));
5015       }
5016 
5017       VG_(printf)("           locks: %'8lu acquires, "
5018                   "%'lu releases\n",
5019                   stats__lockN_acquires,
5020                   stats__lockN_releases
5021                  );
5022       VG_(printf)("   sanity checks: %'8lu\n", stats__sanity_checks);
5023 
5024       VG_(printf)("\n");
5025       libhb_shutdown(True);
5026    }
5027 }
5028 
5029 /* FIXME: move these somewhere sane */
5030 
5031 static
for_libhb__get_stacktrace(Thr * hbt,Addr * frames,UWord nRequest)5032 void for_libhb__get_stacktrace ( Thr* hbt, Addr* frames, UWord nRequest )
5033 {
5034    Thread*     thr;
5035    ThreadId    tid;
5036    UWord       nActual;
5037    tl_assert(hbt);
5038    thr = libhb_get_Thr_hgthread( hbt );
5039    tl_assert(thr);
5040    tid = map_threads_maybe_reverse_lookup_SLOW(thr);
5041    nActual = (UWord)VG_(get_StackTrace)( tid, frames, (UInt)nRequest,
5042                                          NULL, NULL, 0 );
5043    tl_assert(nActual <= nRequest);
5044    for (; nActual < nRequest; nActual++)
5045       frames[nActual] = 0;
5046 }
5047 
5048 static
for_libhb__get_EC(Thr * hbt)5049 ExeContext* for_libhb__get_EC ( Thr* hbt )
5050 {
5051    Thread*     thr;
5052    ThreadId    tid;
5053    ExeContext* ec;
5054    tl_assert(hbt);
5055    thr = libhb_get_Thr_hgthread( hbt );
5056    tl_assert(thr);
5057    tid = map_threads_maybe_reverse_lookup_SLOW(thr);
5058    /* this will assert if tid is invalid */
5059    ec = VG_(record_ExeContext)( tid, 0 );
5060    return ec;
5061 }
5062 
5063 
hg_post_clo_init(void)5064 static void hg_post_clo_init ( void )
5065 {
5066    Thr* hbthr_root;
5067 
5068    /////////////////////////////////////////////
5069    hbthr_root = libhb_init( for_libhb__get_stacktrace,
5070                             for_libhb__get_EC );
5071    /////////////////////////////////////////////
5072 
5073 
5074    if (HG_(clo_track_lockorders))
5075       laog__init();
5076 
5077    initialise_data_structures(hbthr_root);
5078 }
5079 
hg_pre_clo_init(void)5080 static void hg_pre_clo_init ( void )
5081 {
5082    VG_(details_name)            ("Helgrind");
5083    VG_(details_version)         (NULL);
5084    VG_(details_description)     ("a thread error detector");
5085    VG_(details_copyright_author)(
5086       "Copyright (C) 2007-2011, and GNU GPL'd, by OpenWorks LLP et al.");
5087    VG_(details_bug_reports_to)  (VG_BUGS_TO);
5088    VG_(details_avg_translation_sizeB) ( 320 );
5089 
5090    VG_(basic_tool_funcs)          (hg_post_clo_init,
5091                                    hg_instrument,
5092                                    hg_fini);
5093 
5094    VG_(needs_core_errors)         ();
5095    VG_(needs_tool_errors)         (HG_(eq_Error),
5096                                    HG_(before_pp_Error),
5097                                    HG_(pp_Error),
5098                                    False,/*show TIDs for errors*/
5099                                    HG_(update_extra),
5100                                    HG_(recognised_suppression),
5101                                    HG_(read_extra_suppression_info),
5102                                    HG_(error_matches_suppression),
5103                                    HG_(get_error_name),
5104                                    HG_(get_extra_suppression_info));
5105 
5106    VG_(needs_xml_output)          ();
5107 
5108    VG_(needs_command_line_options)(hg_process_cmd_line_option,
5109                                    hg_print_usage,
5110                                    hg_print_debug_usage);
5111    VG_(needs_client_requests)     (hg_handle_client_request);
5112 
5113    // FIXME?
5114    //VG_(needs_sanity_checks)       (hg_cheap_sanity_check,
5115    //                                hg_expensive_sanity_check);
5116 
5117    VG_(needs_malloc_replacement)  (hg_cli__malloc,
5118                                    hg_cli____builtin_new,
5119                                    hg_cli____builtin_vec_new,
5120                                    hg_cli__memalign,
5121                                    hg_cli__calloc,
5122                                    hg_cli__free,
5123                                    hg_cli____builtin_delete,
5124                                    hg_cli____builtin_vec_delete,
5125                                    hg_cli__realloc,
5126                                    hg_cli_malloc_usable_size,
5127                                    HG_CLI__MALLOC_REDZONE_SZB );
5128 
5129    /* 21 Dec 08: disabled this; it mostly causes H to start more
5130       slowly and use significantly more memory, without very often
5131       providing useful results.  The user can request to load this
5132       information manually with --read-var-info=yes. */
5133    if (0) VG_(needs_var_info)(); /* optional */
5134 
5135    VG_(track_new_mem_startup)     ( evh__new_mem_w_perms );
5136    VG_(track_new_mem_stack_signal)( evh__new_mem_w_tid );
5137    VG_(track_new_mem_brk)         ( evh__new_mem_w_tid );
5138    VG_(track_new_mem_mmap)        ( evh__new_mem_w_perms );
5139    VG_(track_new_mem_stack)       ( evh__new_mem_stack );
5140 
5141    // FIXME: surely this isn't thread-aware
5142    VG_(track_copy_mem_remap)      ( evh__copy_mem );
5143 
5144    VG_(track_change_mem_mprotect) ( evh__set_perms );
5145 
5146    VG_(track_die_mem_stack_signal)( evh__die_mem );
5147    VG_(track_die_mem_brk)         ( evh__die_mem_munmap );
5148    VG_(track_die_mem_munmap)      ( evh__die_mem_munmap );
5149    VG_(track_die_mem_stack)       ( evh__die_mem );
5150 
5151    // FIXME: what is this for?
5152    VG_(track_ban_mem_stack)       (NULL);
5153 
5154    VG_(track_pre_mem_read)        ( evh__pre_mem_read );
5155    VG_(track_pre_mem_read_asciiz) ( evh__pre_mem_read_asciiz );
5156    VG_(track_pre_mem_write)       ( evh__pre_mem_write );
5157    VG_(track_post_mem_write)      (NULL);
5158 
5159    /////////////////
5160 
5161    VG_(track_pre_thread_ll_create)( evh__pre_thread_ll_create );
5162    VG_(track_pre_thread_ll_exit)  ( evh__pre_thread_ll_exit );
5163 
5164    VG_(track_start_client_code)( evh__start_client_code );
5165    VG_(track_stop_client_code)( evh__stop_client_code );
5166 
5167    /* Ensure that requirements for "dodgy C-as-C++ style inheritance"
5168       as described in comments at the top of pub_tool_hashtable.h, are
5169       met.  Blargh. */
5170    tl_assert( sizeof(void*) == sizeof(struct _MallocMeta*) );
5171    tl_assert( sizeof(UWord) == sizeof(Addr) );
5172    hg_mallocmeta_table
5173       = VG_(HT_construct)( "hg_malloc_metadata_table" );
5174 
5175    // add a callback to clean up on (threaded) fork.
5176    VG_(atfork)(NULL/*pre*/, NULL/*parent*/, evh__atfork_child/*child*/);
5177 }
5178 
5179 VG_DETERMINE_INTERFACE_VERSION(hg_pre_clo_init)
5180 
5181 /*--------------------------------------------------------------------*/
5182 /*--- end                                                hg_main.c ---*/
5183 /*--------------------------------------------------------------------*/
5184