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