• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2008-2010, Google Inc.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Neither the name of Google Inc. nor the names of its
11  * contributors may be used to endorse or promote products derived from
12  * this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 // This file is part of ThreadSanitizer, a dynamic data race detector.
28 // Author: Konstantin Serebryany.
29 // Author: Timur Iskhodzhanov.
30 
31 #define __STDC_LIMIT_MACROS
32 #include "pin.H"
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <map>
38 #include <assert.h>
39 
40 #include "thread_sanitizer.h"
41 #include "ts_lock.h"
42 #include "ts_trace_info.h"
43 #include "ts_race_verifier.h"
44 #include "common_util.h"
45 
46 
47 #if defined(__GNUC__)
48 # include <cxxabi.h>  // __cxa_demangle
49 # define ATOMIC_READ(a) __sync_add_and_fetch(a, 0)
50 
51 #elif defined(_MSC_VER)
52 namespace WINDOWS
53 {
54 // This is the way of including winows.h recommended by PIN docs.
55 #include<Windows.h>
56 }
57 
58 #include <intrin.h>
59 # define popen(x,y) (NULL)
60 # define ATOMIC_READ(a)         _InterlockedCompareExchange(a, 0, 0)
61 # define usleep(x) WINDOWS::Sleep((x)/1000)
62 # define UINTPTR_MAX ((uintptr_t)-1)
63 #endif
64 
65 #ifdef NDEBUG
66 # error "Please don't define NDEBUG"
67 #endif
68 
69 static void DumpEvent(CONTEXT *ctx, EventType type, int32_t tid, uintptr_t pc,
70                       uintptr_t a, uintptr_t info);
71 //------ Global PIN lock ------- {{{1
72 class ScopedReentrantClientLock {
73  public:
ScopedReentrantClientLock(int line)74   ScopedReentrantClientLock(int line)
75     : line_(line) {
76     // if (line && G_flags->debug_level >= 5)  Printf("??Try  at line %d\n", line);
77     PIN_LockClient();
78     if (line && G_flags->debug_level >= 5)  Printf("++Lock at line %d\n", line);
79   }
~ScopedReentrantClientLock()80   ~ScopedReentrantClientLock() {
81     if (line_ && G_flags->debug_level >= 5) Printf("--Unlock at line %d\n", line_);
82     PIN_UnlockClient();
83   }
84  private:
85   int line_;
86 };
87 
88 //--------------- Globals ----------------- {{{1
89 extern FILE *G_out;
90 
91 // Number of threads created by pthread_create (i.e. not counting main thread).
92 static int n_created_threads = 0;
93 // Number of started threads, i.e. the number of CallbackForThreadStart calls.
94 static int n_started_threads = 0;
95 
96 const uint32_t kMaxThreads = PIN_MAX_THREADS;
97 
98 // Serializes the ThreadSanitizer callbacks if TS_SERIALIZED==1
99 static TSLock g_main_ts_lock;
100 
101 // Serializes calls to pthread_create and CreateThread.
102 static TSLock g_thread_create_lock;
103 // Under g_thread_create_lock.
104 static THREADID g_tid_of_thread_which_called_create_thread = -1;
105 
106 #ifdef _MSC_VER
107 // On Windows, we need to create a h-b arc between
108 // RtlQueueWorkItem(callback, x, y) and the call to callback.
109 // Same for RegisterWaitForSingleObject.
110 static unordered_set<uintptr_t> *g_windows_thread_pool_calback_set;
111 // Similarly, we need h-b arcs between the returns from callbacks and
112 // thre related UnregisterWaitEx. Damn, what a stupid interface!
113 static unordered_map<uintptr_t, uintptr_t> *g_windows_thread_pool_wait_object_map;
114 #endif
115 
116 //--------------- StackFrame ----------------- {{{1
117 struct StackFrame {
118   uintptr_t pc;
119   uintptr_t sp;
StackFrameStackFrame120   StackFrame(uintptr_t p, uintptr_t s) : pc(p), sp(s) { }
121 };
122 //--------------- InstrumentedCallFrame ----- {{{1
123 // Machinery to implement the fast interceptors in PIN
124 // (i.e. the ones that don't use PIN_CallApplicationFunction).
125 // We instrument the entry of the interesting function (e.g. malloc)
126 // and all RET instructions in this function's module (e.g. libc).
127 // At entry, we push an InstrumentedCallFrame object onto InstrumentedCallStack.
128 // At every RET instruction we check if the stack is not empty (fast path)
129 // and if the top contains the current SP. If yes -- this is the function return
130 // and we pop the stack.
131 struct InstrumentedCallFrame {
132   typedef void (*callback_t)(THREADID tid, InstrumentedCallFrame &frame,
133                              ADDRINT ret);
134   callback_t callback;
135   uintptr_t pc;
136   uintptr_t sp;
137   uintptr_t arg[4];
138 };
139 
140 struct InstrumentedCallStack {
141  public:
InstrumentedCallStackInstrumentedCallStack142   InstrumentedCallStack() : size_(0) { }
143 
sizeInstrumentedCallStack144   size_t size() { return size_; }
145 
PushInstrumentedCallStack146   void Push(InstrumentedCallFrame::callback_t callback,
147             uintptr_t pc,
148             uintptr_t sp,
149             uintptr_t a0, uintptr_t a1) {
150     CHECK(size() < TS_ARRAY_SIZE(frames_));
151     size_++;
152     Top()->callback = callback;
153     Top()->pc = pc;
154     Top()->sp = sp;
155     Top()->arg[0] = a0;
156     Top()->arg[1] = a1;
157   }
158 
PopInstrumentedCallStack159   void Pop() {
160     CHECK(size() > 0);
161     size_--;
162   }
163 
TopInstrumentedCallStack164   InstrumentedCallFrame *Top() {
165     CHECK(size() > 0);
166     return &frames_[size_-1];
167   }
168 
PrintInstrumentedCallStack169   void Print() {
170     for (size_t i = 0; i < size(); i++) {
171       Printf( " %p\n", frames_[i].sp);
172       if (i > 0) CHECK(frames_[i].sp <= frames_[i-1].sp);
173     }
174   }
175 
176  private:
177   InstrumentedCallFrame frames_[20];
178   size_t size_;
179 };
180 
181 //--------------- PinThread ----------------- {{{1
182 const size_t kThreadLocalEventBufferSize = 2048 - 2;
183 // The number of mops should be at least 2 less than the size of TLEB
184 // so that we have space to put SBLOCK_ENTER token and the trace_info ptr.
185 const size_t kMaxMopsPerTrace = kThreadLocalEventBufferSize - 2;
186 
187 REG tls_reg;
188 
189 struct PinThread;
190 
191 struct ThreadLocalEventBuffer {
192   PinThread *t;
193   size_t size;
194   uintptr_t events[kThreadLocalEventBufferSize];
195 };
196 
197 struct PinThread {
198   ThreadLocalEventBuffer tleb;
199   int          uniq_tid;
200   uint32_t     literace_sampling;  // cache of a flag.
201   volatile long last_child_tid;
202   InstrumentedCallStack ic_stack;
203   THREADID     tid;
204   THREADID     parent_tid;
205   pthread_t    my_ptid;
206   size_t       thread_stack_size_if_known;
207   size_t       last_child_stack_size_if_known;
208   vector<StackFrame> shadow_stack;
209   TraceInfo    *trace_info;
210   int ignore_accesses;  // if > 0, ignore all memory accesses.
211   int ignore_accesses_depth;
212   int ignore_sync;      // if > 0, ignore all sync events.
213   int spin_lock_recursion_depth;
214   bool         thread_finished;
215   bool         thread_done;
216   bool         holding_lock;
217   int          n_consumed_events;
218 #ifdef _MSC_VER
219   enum StartupState {
220     STARTING,
221     CHILD_READY,
222     MAY_CONTINUE,
223   };
224   volatile long startup_state;  // used to handle the CREATE_SUSPENDED flag.
225 #endif
226   char         padding[64];  // avoid any chance of ping-pong.
227 };
228 
229 // Array of pin threads, indexed by pin's THREADID.
230 static PinThread *g_pin_threads;
231 
232 // If true, ignore all accesses in all threads.
233 extern bool global_ignore;
234 
235 #ifdef _MSC_VER
236 static unordered_set<pthread_t> *g_win_handles_which_are_threads;
237 #endif
238 
239 //-------------------- ts_replace ------------------- {{{1
ReportAccesRange(THREADID tid,uintptr_t pc,EventType type,uintptr_t x,size_t size)240 static void ReportAccesRange(THREADID tid, uintptr_t pc, EventType type, uintptr_t x, size_t size) {
241   if (size && !g_pin_threads[tid].ignore_accesses) {
242     uintptr_t end = x + size;
243     for(uintptr_t a = x; a < end; a += 8) {
244       size_t cur_size = min((uintptr_t)8, end - a);
245       DumpEvent(0, type, tid, pc, a, cur_size);
246     }
247   }
248 }
249 
250 #define REPORT_READ_RANGE(x, size) ReportAccesRange(tid, pc, READ, (uintptr_t)x, size)
251 #define REPORT_WRITE_RANGE(x, size) ReportAccesRange(tid, pc, WRITE, (uintptr_t)x, size)
252 
253 #define EXTRA_REPLACE_PARAMS THREADID tid, uintptr_t pc,
254 #define EXTRA_REPLACE_ARGS tid, pc,
255 #include "ts_replace.h"
256 
257 //------------- ThreadSanitizer exports ------------ {{{1
Demangle(const char * str)258 string Demangle(const char *str) {
259 #if defined(__GNUC__)
260   int status;
261   char *demangled = __cxxabiv1::__cxa_demangle(str, 0, 0, &status);
262   if (demangled) {
263     string res = demangled;
264     free(demangled);
265     return res;
266   }
267 #endif
268   return str;
269 }
270 
PcToStrings(uintptr_t pc,bool demangle,string * img_name,string * rtn_name,string * file_name,int * line_no)271 void PcToStrings(uintptr_t pc, bool demangle,
272                 string *img_name, string *rtn_name,
273                 string *file_name, int *line_no) {
274   if (G_flags->symbolize) {
275     RTN rtn;
276     ScopedReentrantClientLock lock(__LINE__);
277     // ClientLock must be held.
278     PIN_GetSourceLocation(pc, NULL, line_no, file_name);
279     *file_name = ConvertToPlatformIndependentPath(*file_name);
280     rtn = RTN_FindByAddress(pc);
281     string name;
282     if (RTN_Valid(rtn)) {
283       *rtn_name = demangle
284           ? Demangle(RTN_Name(rtn).c_str())
285           : RTN_Name(rtn);
286       *img_name = IMG_Name(SEC_Img(RTN_Sec(rtn)));
287     }
288   }
289 }
290 
PcToRtnName(uintptr_t pc,bool demangle)291 string PcToRtnName(uintptr_t pc, bool demangle) {
292   string res;
293   if (G_flags->symbolize) {
294     {
295       ScopedReentrantClientLock lock(__LINE__);
296       RTN rtn = RTN_FindByAddress(pc);
297       if (RTN_Valid(rtn)) {
298         res = demangle
299             ? Demangle(RTN_Name(rtn).c_str())
300             : RTN_Name(rtn);
301       }
302     }
303   }
304   return res;
305 }
306 
307 //--------------- ThreadLocalEventBuffer ----------------- {{{1
308 // thread local event buffer is an array of uintptr_t.
309 // The events are encoded like this:
310 // { RTN_CALL, call_pc, target_pc }
311 // { RTN_EXIT }
312 // { SBLOCK_ENTER, trace_info_of_size_n, addr1, addr2, ... addr_n}
313 
314 enum TLEBSpecificEvents {
315   TLEB_IGNORE_ALL_BEGIN = LAST_EVENT + 1,
316   TLEB_IGNORE_ALL_END,
317   TLEB_IGNORE_SYNC_BEGIN,
318   TLEB_IGNORE_SYNC_END,
319   TLEB_GLOBAL_IGNORE_ON,
320   TLEB_GLOBAL_IGNORE_OFF,
321 };
322 
DumpEventPlainText(EventType type,int32_t tid,uintptr_t pc,uintptr_t a,uintptr_t info)323 static bool DumpEventPlainText(EventType type, int32_t tid, uintptr_t pc,
324                         uintptr_t a, uintptr_t info) {
325 #if DEBUG == 0 || defined(_MSC_VER)
326   return false;
327 #else
328   if (G_flags->dump_events.empty()) return false;
329 
330   static unordered_set<uintptr_t> *pc_set;
331   if (pc_set == NULL) {
332     pc_set = new unordered_set<uintptr_t>;
333   }
334   static FILE *log_file = NULL;
335   if (log_file == NULL) {
336     log_file = popen(("gzip > " + G_flags->dump_events).c_str(), "w");
337   }
338   if (G_flags->symbolize && pc_set->insert(pc).second) {
339     string img_name, rtn_name, file_name;
340     int line = 0;
341     PcToStrings(pc, false, &img_name, &rtn_name, &file_name, &line);
342     if (file_name.empty()) file_name = "unknown";
343     if (img_name.empty()) img_name = "unknown";
344     if (rtn_name.empty()) rtn_name = "unknown";
345     if (line == 0) line = 1;
346     fprintf(log_file, "#PC %lx %s %s %s %d\n",
347             (long)pc, img_name.c_str(), rtn_name.c_str(),
348             file_name.c_str(), line);
349   }
350   fprintf(log_file, "%s %x %lx %lx %lx\n", kEventNames[type], tid,
351           (long)pc, (long)a, (long)info);
352   return true;
353 #endif
354 }
355 
DumpEventInternal(EventType type,int32_t uniq_tid,uintptr_t pc,uintptr_t a,uintptr_t info)356 static void DumpEventInternal(EventType type, int32_t uniq_tid, uintptr_t pc,
357                               uintptr_t a, uintptr_t info) {
358   if (DumpEventPlainText(type, uniq_tid, pc, a, info)) return;
359   // PIN wraps the tid (after 2048), but we need a uniq tid.
360   Event event(type, uniq_tid, pc, a, info);
361   ThreadSanitizerHandleOneEvent(&event);
362 }
363 
ComputeIgnoreAccesses(PinThread & t)364 void ComputeIgnoreAccesses(PinThread &t) {
365   t.ignore_accesses = (t.ignore_accesses_depth != 0) || (global_ignore != 0);
366 }
367 
HandleInnerEvent(PinThread & t,uintptr_t event)368 static void HandleInnerEvent(PinThread &t, uintptr_t event) {
369   DCHECK(event > LAST_EVENT);
370   if (event == TLEB_IGNORE_ALL_BEGIN){
371     t.ignore_accesses_depth++;
372     ComputeIgnoreAccesses(t);
373   } else if (event == TLEB_IGNORE_ALL_END){
374     t.ignore_accesses_depth--;
375     CHECK(t.ignore_accesses_depth >= 0);
376     ComputeIgnoreAccesses(t);
377   } else if (event == TLEB_IGNORE_SYNC_BEGIN){
378     t.ignore_sync++;
379   } else if (event == TLEB_IGNORE_SYNC_END){
380     t.ignore_sync--;
381     CHECK(t.ignore_sync >= 0);
382   } else if (event == TLEB_GLOBAL_IGNORE_ON){
383     Report("INFO: GLOBAL IGNORE ON\n");
384     global_ignore = true;
385     ComputeIgnoreAccesses(t);
386   } else if (event == TLEB_GLOBAL_IGNORE_OFF){
387     Report("INFO: GLOBAL IGNORE OFF\n");
388     global_ignore = false;
389     ComputeIgnoreAccesses(t);
390   } else {
391     Printf("Event: %ld (last: %ld)\n", event, LAST_EVENT);
392     CHECK(0);
393   }
394 }
395 
WantToIgnoreEvent(PinThread & t,uintptr_t event)396 static INLINE bool WantToIgnoreEvent(PinThread &t, uintptr_t event) {
397   if (t.ignore_sync &&
398       (event == WRITER_LOCK || event == READER_LOCK || event == UNLOCK ||
399        event == SIGNAL || event == WAIT)) {
400     // do nothing, we are ignoring locks.
401     return true;
402   } else if (t.ignore_accesses && (event == READ || event == WRITE)) {
403     // do nothing, we are ignoring mops.
404     return true;
405   }
406   return false;
407 }
408 
TLEBFlushUnlocked(ThreadLocalEventBuffer & tleb)409 static INLINE void TLEBFlushUnlocked(ThreadLocalEventBuffer &tleb) {
410   if (tleb.size == 0) return;
411   PinThread &t = *tleb.t;
412   // global_ignore should be always on with race verifier
413   DCHECK(!g_race_verifier_active || global_ignore);
414   DCHECK(tleb.size <= kThreadLocalEventBufferSize);
415   if (DEBUG_MODE && t.thread_done) {
416     Printf("ACHTUNG!!! an event from a dead thread T%d\n", t.tid);
417   }
418   DCHECK(!t.thread_done);
419 
420   if (TS_SERIALIZED == 1 || DEBUG_MODE) {
421     size_t max_idx = TS_ARRAY_SIZE(G_stats->tleb_flush);
422     size_t idx = min((size_t)u32_log2(tleb.size), max_idx - 1);
423     CHECK(idx < max_idx);
424     G_stats->tleb_flush[idx]++;
425   }
426 
427   if (TS_SERIALIZED == 1 && G_flags->offline) {
428     fwrite(tleb.events, sizeof(uintptr_t), tleb.size, G_out);
429     tleb.size = 0;
430     return;
431   }
432 
433   size_t i;
434   for (i = 0; i < tleb.size; ) {
435     uintptr_t event = tleb.events[i++];
436     DCHECK(!g_race_verifier_active ||
437         event == SBLOCK_ENTER || event == EXPECT_RACE || event == THR_START);
438     if (event == RTN_EXIT) {
439       if (DumpEventPlainText(RTN_EXIT, t.uniq_tid, 0, 0, 0)) continue;
440       ThreadSanitizerHandleRtnExit(t.uniq_tid);
441     } else if (event == RTN_CALL) {
442       uintptr_t call_pc = tleb.events[i++];
443       uintptr_t target_pc = tleb.events[i++];
444       IGNORE_BELOW_RTN ignore_below = (IGNORE_BELOW_RTN)tleb.events[i++];
445       if (DumpEventPlainText(RTN_CALL, t.uniq_tid, call_pc,
446                              target_pc, ignore_below)) continue;
447       ThreadSanitizerHandleRtnCall(t.uniq_tid, call_pc, target_pc,
448                                    ignore_below);
449     } else if (event == SBLOCK_ENTER){
450       TraceInfo *trace_info = (TraceInfo*) tleb.events[i++];
451       DCHECK(trace_info);
452       bool do_this_trace = true;
453       if (t.ignore_accesses) {
454         do_this_trace = false;
455       } else if (t.literace_sampling) {
456         do_this_trace = !trace_info->LiteRaceSkipTraceRealTid(
457             t.uniq_tid, t.literace_sampling);
458       }
459 
460       size_t n = trace_info->n_mops();
461       if (do_this_trace) {
462         if (DEBUG_MODE && !G_flags->dump_events.empty()) {
463           DumpEventPlainText(SBLOCK_ENTER, t.uniq_tid, trace_info->pc(), 0, 0);
464           for (size_t j = 0; j < n; j++) {
465             MopInfo *mop = trace_info->GetMop(j);
466             DCHECK(mop->size());
467             DCHECK(mop);
468             uintptr_t addr = tleb.events[i + j];
469             if (addr) {
470               DumpEventPlainText(mop->is_write() ? WRITE : READ, t.uniq_tid,
471                                      mop->pc(), addr, mop->size());
472             }
473           }
474         } else {
475           ThreadSanitizerHandleTrace(t.uniq_tid, trace_info, tleb.events+i);
476         }
477       }
478       i += n;
479     } else if (event == THR_START) {
480       uintptr_t parent = -1;
481       if (t.parent_tid != (THREADID)-1) {
482         parent = g_pin_threads[t.parent_tid].uniq_tid;
483       }
484       DumpEventInternal(THR_START, t.uniq_tid, 0, 0, parent);
485     } else if (event == THR_END) {
486       DumpEventInternal(THR_END, t.uniq_tid, 0, 0, 0);
487       DCHECK(t.thread_finished == true);
488       DCHECK(t.thread_done == false);
489       t.thread_done = true;
490       i += 3;  // consume the unneeded data.
491       DCHECK(i == tleb.size);  // should be last event in this tleb.
492     } else if (event > LAST_EVENT) {
493       HandleInnerEvent(t, event);
494     } else {
495       // all other events.
496       CHECK(event > NOOP && event < LAST_EVENT);
497       uintptr_t pc    = tleb.events[i++];
498       uintptr_t a     = tleb.events[i++];
499       uintptr_t info  = tleb.events[i++];
500       if (!WantToIgnoreEvent(t, event)) {
501         DumpEventInternal((EventType)event, t.uniq_tid, pc, a, info);
502       }
503     }
504   }
505   DCHECK(i == tleb.size);
506   tleb.size = 0;
507   if (DEBUG_MODE) { // for sanity checking.
508     memset(tleb.events, 0xf0, sizeof(tleb.events));
509   }
510 }
511 
TLEBFlushLocked(PinThread & t)512 static INLINE void TLEBFlushLocked(PinThread &t) {
513 #if TS_SERIALIZED==1
514   if (G_flags->dry_run) {
515     t.tleb.size = 0;
516     return;
517   }
518   CHECK(t.tleb.size <= kThreadLocalEventBufferSize);
519   G_stats->lock_sites[0]++;
520   ScopedLock lock(&g_main_ts_lock);
521   TLEBFlushUnlocked(t.tleb);
522 #else
523   TLEBFlushUnlocked(t.tleb);
524 #endif
525 }
526 
TLEBAddRtnCall(PinThread & t,uintptr_t call_pc,uintptr_t target_pc,IGNORE_BELOW_RTN ignore_below)527 static void TLEBAddRtnCall(PinThread &t, uintptr_t call_pc,
528                            uintptr_t target_pc, IGNORE_BELOW_RTN ignore_below) {
529   if (TS_SERIALIZED == 0) {
530     TLEBFlushLocked(t);
531     ThreadSanitizerHandleRtnCall(t.uniq_tid, call_pc, target_pc,
532                                  ignore_below);
533     return;
534   }
535   DCHECK(t.tleb.size <= kThreadLocalEventBufferSize);
536   if (t.tleb.size + 4 > kThreadLocalEventBufferSize) {
537     TLEBFlushLocked(t);
538     DCHECK(t.tleb.size == 0);
539   }
540   t.tleb.events[t.tleb.size++] = RTN_CALL;
541   t.tleb.events[t.tleb.size++] = call_pc;
542   t.tleb.events[t.tleb.size++] = target_pc;
543   t.tleb.events[t.tleb.size++] = ignore_below;
544   DCHECK(t.tleb.size <= kThreadLocalEventBufferSize);
545 }
546 
TLEBAddRtnExit(PinThread & t)547 static void TLEBAddRtnExit(PinThread &t) {
548   if (TS_SERIALIZED == 0) {
549     TLEBFlushLocked(t);
550     ThreadSanitizerHandleRtnExit(t.uniq_tid);
551     return;
552   }
553   if (t.tleb.size + 1 > kThreadLocalEventBufferSize) {
554     TLEBFlushLocked(t);
555   }
556   t.tleb.events[t.tleb.size++] = RTN_EXIT;
557   DCHECK(t.tleb.size <= kThreadLocalEventBufferSize);
558 }
559 
TLEBAddTrace(PinThread & t)560 static INLINE uintptr_t *TLEBAddTrace(PinThread &t) {
561   size_t n = t.trace_info->n_mops();
562   DCHECK(n > 0);
563   if (TS_SERIALIZED == 0) {
564     TLEBFlushLocked(t);
565   } else if (t.tleb.size + 2 + n > kThreadLocalEventBufferSize) {
566     TLEBFlushLocked(t);
567   }
568   if (TS_SERIALIZED == 1) {
569     t.tleb.events[t.tleb.size++] = SBLOCK_ENTER;
570     t.tleb.events[t.tleb.size++] = (uintptr_t)t.trace_info;
571   } else {
572     DCHECK(t.tleb.size == 0);
573     t.tleb.events[0] = SBLOCK_ENTER;
574     t.tleb.events[1] = (uintptr_t)t.trace_info;
575     t.tleb.size += 2;
576   }
577   uintptr_t *mop_addresses = &t.tleb.events[t.tleb.size];
578   // not every address will be written to. so they will stay 0.
579   for (size_t i = 0; i < n; i++) {
580     mop_addresses[i] = 0;
581   }
582   t.tleb.size += n;
583   DCHECK(t.tleb.size <= kThreadLocalEventBufferSize);
584   return mop_addresses;
585 }
586 
TLEBStartThread(PinThread & t)587 static void TLEBStartThread(PinThread &t) {
588   CHECK(t.tleb.size == 0);
589   t.tleb.events[t.tleb.size++] = THR_START;
590 }
591 
TLEBSimpleEvent(PinThread & t,uintptr_t event)592 static void TLEBSimpleEvent(PinThread &t, uintptr_t event) {
593   if (g_race_verifier_active)
594     return;
595   if (TS_SERIALIZED == 0) {
596     TLEBFlushLocked(t);
597     if (event < LAST_EVENT) {
598       Event e((EventType)event, t.uniq_tid, 0, 0, 0);
599       ThreadSanitizerHandleOneEvent(&e);
600     } else {
601       HandleInnerEvent(t, event);
602     }
603     return;
604   }
605   if (t.tleb.size + 1 > kThreadLocalEventBufferSize) {
606     TLEBFlushLocked(t);
607   }
608   t.tleb.events[t.tleb.size++] = event;
609   DCHECK(t.tleb.size <= kThreadLocalEventBufferSize);
610 }
611 
TLEBAddGenericEventAndFlush(PinThread & t,EventType type,uintptr_t pc,uintptr_t a,uintptr_t info)612 static void TLEBAddGenericEventAndFlush(PinThread &t,
613                                         EventType type, uintptr_t pc,
614                                         uintptr_t a, uintptr_t info) {
615   if (TS_SERIALIZED == 0) {
616     if (WantToIgnoreEvent(t, type)) return;
617     TLEBFlushLocked(t);
618     Event e(type, t.uniq_tid, pc, a, info);
619     ThreadSanitizerHandleOneEvent(&e);
620     return;
621   }
622   if (t.tleb.size + 4 > kThreadLocalEventBufferSize) {
623     TLEBFlushLocked(t);
624   }
625   DCHECK(type > NOOP && type < LAST_EVENT);
626   t.tleb.events[t.tleb.size++] = type;
627   t.tleb.events[t.tleb.size++] = pc;
628   t.tleb.events[t.tleb.size++] = a;
629   t.tleb.events[t.tleb.size++] = info;
630   TLEBFlushLocked(t);
631   DCHECK(t.tleb.size <= kThreadLocalEventBufferSize);
632 }
633 
634 static void UpdateCallStack(PinThread &t, ADDRINT sp);
635 
636 // Must be called from its thread (except for THR_END case)!
DumpEventWithSp(uintptr_t sp,EventType type,int32_t tid,uintptr_t pc,uintptr_t a,uintptr_t info)637 static void DumpEventWithSp(uintptr_t sp, EventType type, int32_t tid, uintptr_t pc,
638                             uintptr_t a, uintptr_t info) {
639   if (!g_race_verifier_active || type == EXPECT_RACE) {
640     PinThread &t = g_pin_threads[tid];
641     if (sp) {
642       UpdateCallStack(t, sp);
643     }
644     TLEBAddGenericEventAndFlush(t, type, pc, a, info);
645   }
646 }
DumpEvent(CONTEXT * ctx,EventType type,int32_t tid,uintptr_t pc,uintptr_t a,uintptr_t info)647 static void DumpEvent(CONTEXT *ctx, EventType type, int32_t tid, uintptr_t pc,
648                       uintptr_t a, uintptr_t info) {
649   DumpEventWithSp(ctx ? PIN_GetContextReg(ctx, REG_STACK_PTR) : 0,
650             type, tid, pc, a, info);
651 }
652 
653 //--------- Wraping and relacing --------------- {{{1
654 static set<string> g_wrapped_functions;
InformAboutFunctionWrap(RTN rtn,string name)655 static void InformAboutFunctionWrap(RTN rtn, string name) {
656   g_wrapped_functions.insert(name);
657   if (!debug_wrap) return;
658   Printf("Function wrapped: %s (%s %s)\n", name.c_str(),
659          RTN_Name(rtn).c_str(), IMG_Name(SEC_Img(RTN_Sec(rtn))).c_str());
660 }
661 
RtnMatchesName(const string & rtn_name,const string & name)662 static bool RtnMatchesName(const string &rtn_name, const string &name) {
663   CHECK(name.size() > 0);
664   size_t pos = rtn_name.find(name);
665   if (pos == string::npos) {
666     return false;
667   }
668   if (pos == 0 && name.size() == rtn_name.size()) {
669   //  Printf("Full match: %s %s\n", rtn_name.c_str(), name.c_str());
670     return true;
671   }
672   // match MyFuncName@123
673   if (pos == 0 && name.size() < rtn_name.size()
674       && rtn_name[name.size()] == '@') {
675   //  Printf("Versioned match: %s %s\n", rtn_name.c_str(), name.c_str());
676     return true;
677   }
678   // match _MyFuncName@123
679   if (pos == 1 && rtn_name[0] == '_' && name.size() < rtn_name.size()
680       && rtn_name[name.size() + 1] == '@') {
681     // Printf("Versioned match: %s %s\n", rtn_name.c_str(), name.c_str());
682     return true;
683   }
684 
685   return false;
686 }
687 
688 #define FAST_WRAP_PARAM0 THREADID tid, ADDRINT pc, ADDRINT sp
689 #define FAST_WRAP_PARAM1 FAST_WRAP_PARAM0, ADDRINT arg0
690 #define FAST_WRAP_PARAM2 FAST_WRAP_PARAM1, ADDRINT arg1
691 #define FAST_WRAP_PARAM3 FAST_WRAP_PARAM2, ADDRINT arg2
692 
693 #define FAST_WRAP_PARAM_AFTER \
694   THREADID tid, InstrumentedCallFrame &frame, ADDRINT ret
695 
696 
697 #define DEBUG_FAST_INTERCEPTORS 0
698 //#define DEBUG_FAST_INTERCEPTORS (tid == 1)
699 
700 #define PUSH_AFTER_CALLBACK1(callback, a0) \
701   g_pin_threads[tid].ic_stack.Push(callback, pc, sp, a0, 0); \
702   if (DEBUG_FAST_INTERCEPTORS) \
703     Printf("T%d %s pc=%p sp=%p *sp=(%p) arg0=%p stack_size=%ld\n",\
704          tid, __FUNCTION__, pc, sp,\
705          ((void**)sp)[0],\
706          arg0,\
707          g_pin_threads[tid].ic_stack.size()\
708          );\
709 
710 
711 #define WRAP_NAME(name) Wrap_##name
712 #define WRAP4(name) WrapFunc4(img, rtn, #name, (AFUNPTR)Wrap_##name)
713 #define WRAPSTD1(name) WrapStdCallFunc1(rtn, #name, (AFUNPTR)Wrap_##name)
714 #define WRAPSTD2(name) WrapStdCallFunc2(rtn, #name, (AFUNPTR)Wrap_##name)
715 #define WRAPSTD3(name) WrapStdCallFunc3(rtn, #name, (AFUNPTR)Wrap_##name)
716 #define WRAPSTD4(name) WrapStdCallFunc4(rtn, #name, (AFUNPTR)Wrap_##name)
717 #define WRAPSTD5(name) WrapStdCallFunc5(rtn, #name, (AFUNPTR)Wrap_##name)
718 #define WRAPSTD6(name) WrapStdCallFunc6(rtn, #name, (AFUNPTR)Wrap_##name)
719 #define WRAPSTD7(name) WrapStdCallFunc7(rtn, #name, (AFUNPTR)Wrap_##name)
720 #define WRAPSTD8(name) WrapStdCallFunc8(rtn, #name, (AFUNPTR)Wrap_##name)
721 #define WRAPSTD10(name) WrapStdCallFunc10(rtn, #name, (AFUNPTR)Wrap_##name)
722 #define WRAPSTD11(name) WrapStdCallFunc11(rtn, #name, (AFUNPTR)Wrap_##name)
723 #define WRAP_PARAM4  THREADID tid, ADDRINT pc, CONTEXT *ctx, \
724                                 AFUNPTR f,\
725                                 uintptr_t arg0, uintptr_t arg1, \
726                                 uintptr_t arg2, uintptr_t arg3
727 
728 #define WRAP_PARAM6 WRAP_PARAM4, uintptr_t arg4, uintptr_t arg5
729 #define WRAP_PARAM8 WRAP_PARAM6, uintptr_t arg6, uintptr_t arg7
730 #define WRAP_PARAM10 WRAP_PARAM8, uintptr_t arg8, uintptr_t arg9
731 #define WRAP_PARAM12 WRAP_PARAM10, uintptr_t arg10, uintptr_t arg11
732 
CallFun4(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)733 static uintptr_t CallFun4(CONTEXT *ctx, THREADID tid,
734                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
735                          uintptr_t arg2, uintptr_t arg3) {
736   uintptr_t ret = 0xdeadbee1;
737   PIN_CallApplicationFunction(ctx, tid,
738                               CALLINGSTD_DEFAULT, (AFUNPTR)(f),
739                               PIN_PARG(uintptr_t), &ret,
740                               PIN_PARG(uintptr_t), arg0,
741                               PIN_PARG(uintptr_t), arg1,
742                               PIN_PARG(uintptr_t), arg2,
743                               PIN_PARG(uintptr_t), arg3,
744                               PIN_PARG_END());
745   return ret;
746 }
747 
CallFun6(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5)748 static uintptr_t CallFun6(CONTEXT *ctx, THREADID tid,
749                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
750                          uintptr_t arg2, uintptr_t arg3,
751                          uintptr_t arg4, uintptr_t arg5) {
752   uintptr_t ret = 0xdeadbee1;
753   PIN_CallApplicationFunction(ctx, tid,
754                               CALLINGSTD_DEFAULT, (AFUNPTR)(f),
755                               PIN_PARG(uintptr_t), &ret,
756                               PIN_PARG(uintptr_t), arg0,
757                               PIN_PARG(uintptr_t), arg1,
758                               PIN_PARG(uintptr_t), arg2,
759                               PIN_PARG(uintptr_t), arg3,
760                               PIN_PARG(uintptr_t), arg4,
761                               PIN_PARG(uintptr_t), arg5,
762                               PIN_PARG_END());
763   return ret;
764 }
765 
766 #define CALL_ME_INSIDE_WRAPPER_4() CallFun4(ctx, tid, f, arg0, arg1, arg2, arg3)
767 #define CALL_ME_INSIDE_WRAPPER_6() CallFun6(ctx, tid, f, arg0, arg1, arg2, arg3, arg4, arg5)
768 
769 // Completely replace (i.e. not wrap) a function with 3 (or less) parameters.
770 // The original function will not be called.
ReplaceFunc3(IMG img,RTN rtn,const char * name,AFUNPTR replacement_func)771 void ReplaceFunc3(IMG img, RTN rtn, const char *name, AFUNPTR replacement_func) {
772   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
773     InformAboutFunctionWrap(rtn, name);
774     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
775                                  CALLINGSTD_DEFAULT,
776                                  "proto",
777                                  PIN_PARG(uintptr_t),
778                                  PIN_PARG(uintptr_t),
779                                  PIN_PARG(uintptr_t),
780                                  PIN_PARG_END());
781     RTN_ReplaceSignature(rtn,
782                          AFUNPTR(replacement_func),
783                          IARG_PROTOTYPE, proto,
784                          IARG_THREAD_ID,
785                          IARG_INST_PTR,
786                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
787                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
788                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
789                          IARG_END);
790     PROTO_Free(proto);
791   }
792 }
793 
794 // Wrap a function with up to 4 parameters.
WrapFunc4(IMG img,RTN rtn,const char * name,AFUNPTR replacement_func)795 void WrapFunc4(IMG img, RTN rtn, const char *name, AFUNPTR replacement_func) {
796   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
797     InformAboutFunctionWrap(rtn, name);
798     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
799                                  CALLINGSTD_DEFAULT,
800                                  "proto",
801                                  PIN_PARG(uintptr_t),
802                                  PIN_PARG(uintptr_t),
803                                  PIN_PARG(uintptr_t),
804                                  PIN_PARG(uintptr_t),
805                                  PIN_PARG_END());
806     RTN_ReplaceSignature(rtn,
807                          AFUNPTR(replacement_func),
808                          IARG_PROTOTYPE, proto,
809                          IARG_THREAD_ID,
810                          IARG_INST_PTR,
811                          IARG_CONTEXT,
812                          IARG_ORIG_FUNCPTR,
813                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
814                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
815                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
816                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
817                          IARG_END);
818     PROTO_Free(proto);
819   }
820 }
821 
822 // Wrap a function with up to 6 parameters.
WrapFunc6(IMG img,RTN rtn,const char * name,AFUNPTR replacement_func)823 void WrapFunc6(IMG img, RTN rtn, const char *name, AFUNPTR replacement_func) {
824   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
825     InformAboutFunctionWrap(rtn, name);
826     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
827                                  CALLINGSTD_DEFAULT,
828                                  "proto",
829                                  PIN_PARG(uintptr_t),
830                                  PIN_PARG(uintptr_t),
831                                  PIN_PARG(uintptr_t),
832                                  PIN_PARG(uintptr_t),
833                                  PIN_PARG(uintptr_t),
834                                  PIN_PARG(uintptr_t),
835                                  PIN_PARG_END());
836     RTN_ReplaceSignature(rtn,
837                          AFUNPTR(replacement_func),
838                          IARG_PROTOTYPE, proto,
839                          IARG_THREAD_ID,
840                          IARG_INST_PTR,
841                          IARG_CONTEXT,
842                          IARG_ORIG_FUNCPTR,
843                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
844                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
845                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
846                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
847                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
848                          IARG_FUNCARG_ENTRYPOINT_VALUE, 5,
849                          IARG_END);
850     PROTO_Free(proto);
851   }
852 }
853 
854 
855 //--------- Instrumentation callbacks --------------- {{{1
856 //---------- Debug -----------------------------------{{{2
857 #define DEB_PR (0)
858 
ShowPcAndSp(const char * where,THREADID tid,ADDRINT pc,ADDRINT sp)859 static void ShowPcAndSp(const char *where, THREADID tid,
860                         ADDRINT pc, ADDRINT sp) {
861     Printf("%s T%d sp=%ld pc=%p %s\n", where, tid, sp, pc,
862            PcToRtnName(pc, true).c_str());
863 }
864 
PrintShadowStack(PinThread & t)865 static void PrintShadowStack(PinThread &t) {
866   Printf("T%d Shadow stack (%d)\n", t.tid, (int)t.shadow_stack.size());
867   for (int i = t.shadow_stack.size() - 1; i >= 0; i--) {
868     uintptr_t pc = t.shadow_stack[i].pc;
869     uintptr_t sp = t.shadow_stack[i].sp;
870     Printf("  sp=%ld pc=%lx %s\n", sp, pc, PcToRtnName(pc, true).c_str());
871   }
872 }
873 
DebugOnlyShowPcAndSp(const char * where,THREADID tid,ADDRINT pc,ADDRINT sp)874 static void DebugOnlyShowPcAndSp(const char *where, THREADID tid,
875                                  ADDRINT pc, ADDRINT sp) {
876   if (DEB_PR) {
877     ShowPcAndSp(where, tid, pc, sp);
878   }
879 }
880 
WRAP_NAME(ThreadSanitizerQuery)881 static uintptr_t WRAP_NAME(ThreadSanitizerQuery)(WRAP_PARAM4) {
882   const char *query = (const char*)arg0;
883   return (uintptr_t)ThreadSanitizerQuery(query);
884 }
885 
886 //--------- Ignores -------------------------------- {{{2
IgnoreMopsBegin(THREADID tid)887 static void IgnoreMopsBegin(THREADID tid) {
888   // if (tid != 0) Printf("T%d IgnoreMops++\n", tid);
889   TLEBSimpleEvent(g_pin_threads[tid], TLEB_IGNORE_ALL_BEGIN);
890 }
IgnoreMopsEnd(THREADID tid)891 static void IgnoreMopsEnd(THREADID tid) {
892   // if (tid != 0) Printf("T%d IgnoreMops--\n", tid);
893   TLEBSimpleEvent(g_pin_threads[tid], TLEB_IGNORE_ALL_END);
894 }
895 
IgnoreSyncAndMopsBegin(THREADID tid)896 static void IgnoreSyncAndMopsBegin(THREADID tid) {
897   // if (tid != 0) Printf("T%d IgnoreSync++\n", tid);
898   IgnoreMopsBegin(tid);
899   TLEBSimpleEvent(g_pin_threads[tid], TLEB_IGNORE_SYNC_BEGIN);
900 }
IgnoreSyncAndMopsEnd(THREADID tid)901 static void IgnoreSyncAndMopsEnd(THREADID tid) {
902   // if (tid != 0) Printf("T%d IgnoreSync--\n", tid);
903   IgnoreMopsEnd(tid);
904   TLEBSimpleEvent(g_pin_threads[tid], TLEB_IGNORE_SYNC_END);
905 }
906 
907 //--------- __cxa_guard_* -------------------------- {{{2
908 // From gcc/cp/decl.c:
909 // --------------------------------------------------------------
910 //      Emit code to perform this initialization but once.  This code
911 //      looks like:
912 //
913 //      static <type> guard;
914 //      if (!guard.first_byte) {
915 //        if (__cxa_guard_acquire (&guard)) {
916 //          bool flag = false;
917 //          try {
918 //            // Do initialization.
919 //            flag = true; __cxa_guard_release (&guard);
920 //            // Register variable for destruction at end of program.
921 //           } catch {
922 //          if (!flag) __cxa_guard_abort (&guard);
923 //         }
924 //      }
925 // --------------------------------------------------------------
926 // So, when __cxa_guard_acquire returns true, we start ignoring all accesses
927 // and in __cxa_guard_release we stop ignoring them.
928 // We also need to ignore all accesses inside these two functions.
929 
Before_cxa_guard_acquire(THREADID tid,ADDRINT pc,ADDRINT guard)930 static void Before_cxa_guard_acquire(THREADID tid, ADDRINT pc, ADDRINT guard) {
931   IgnoreMopsBegin(tid);
932 }
933 
After_cxa_guard_acquire(THREADID tid,ADDRINT pc,ADDRINT ret)934 static void After_cxa_guard_acquire(THREADID tid, ADDRINT pc, ADDRINT ret) {
935   if (ret) {
936     // Continue ignoring, it will end in __cxa_guard_release.
937   } else {
938     // Stop ignoring, there will be no matching call to __cxa_guard_release.
939     IgnoreMopsEnd(tid);
940   }
941 }
942 
After_cxa_guard_release(THREADID tid,ADDRINT pc)943 static void After_cxa_guard_release(THREADID tid, ADDRINT pc) {
944   IgnoreMopsEnd(tid);
945 }
946 
WRAP_NAME(pthread_once)947 static uintptr_t WRAP_NAME(pthread_once)(WRAP_PARAM4) {
948   uintptr_t ret;
949   IgnoreMopsBegin(tid);
950   ret = CALL_ME_INSIDE_WRAPPER_4();
951   IgnoreMopsEnd(tid);
952   return ret;
953 }
954 
TmpCallback1(THREADID tid,ADDRINT pc)955 void TmpCallback1(THREADID tid, ADDRINT pc) {
956   Printf("%s T%d %lx\n", __FUNCTION__, tid, pc);
957 }
TmpCallback2(THREADID tid,ADDRINT pc)958 void TmpCallback2(THREADID tid, ADDRINT pc) {
959   Printf("%s T%d %lx\n", __FUNCTION__, tid, pc);
960 }
961 
962 //--------- Threads --------------------------------- {{{2
HandleThreadCreateBefore(THREADID tid,ADDRINT pc)963 static void HandleThreadCreateBefore(THREADID tid, ADDRINT pc) {
964   DumpEvent(0, THR_CREATE_BEFORE, tid, pc, 0, 0);
965   g_thread_create_lock.Lock();
966   IgnoreMopsBegin(tid);
967   CHECK(g_tid_of_thread_which_called_create_thread == (THREADID)-1);
968   g_tid_of_thread_which_called_create_thread = tid;
969   n_created_threads++;
970 }
971 
HandleThreadCreateAbort(THREADID tid)972 static void HandleThreadCreateAbort(THREADID tid) {
973   CHECK(g_tid_of_thread_which_called_create_thread == tid);
974   g_tid_of_thread_which_called_create_thread = (THREADID)-1;
975   n_created_threads--;
976   IgnoreMopsEnd(tid);
977   g_thread_create_lock.Unlock();
978 }
979 
HandleThreadCreateAfter(THREADID tid,pthread_t child_ptid,bool suspend_child)980 static THREADID HandleThreadCreateAfter(THREADID tid, pthread_t child_ptid,
981                                         bool suspend_child) {
982   // Spin, waiting for last_child_tid to appear (i.e. wait for the thread to
983   // actually start) so that we know the child's tid. No locks.
984   while (!ATOMIC_READ(&g_pin_threads[tid].last_child_tid)) {
985     YIELD();
986   }
987 
988   CHECK(g_tid_of_thread_which_called_create_thread == tid);
989   g_tid_of_thread_which_called_create_thread = -1;
990 
991   THREADID last_child_tid = g_pin_threads[tid].last_child_tid;
992   CHECK(last_child_tid);
993 
994   PinThread &child_t = g_pin_threads[last_child_tid];
995   child_t.my_ptid = child_ptid;
996 
997 #ifdef _MSC_VER
998   if (suspend_child) {
999     while (ATOMIC_READ(&child_t.startup_state) != PinThread::CHILD_READY) {
1000       YIELD();
1001     }
1002     // Strictly speaking, PIN forbids calling system functions like this.
1003     // This may violate application library isolation but
1004     // a) YIELD == WINDOWS::Sleep, so we violate it anyways
1005     // b) SuspendThread probably calls NtSuspendThread right away
1006     WINDOWS::DWORD old_count = WINDOWS::SuspendThread((WINDOWS::HANDLE)child_ptid);  // TODO handle?
1007     CHECK(old_count == 0);
1008   }
1009   child_t.startup_state = PinThread::MAY_CONTINUE;
1010 #else
1011   CHECK(!suspend_child);  // Not implemented - do we need to?
1012 #endif
1013 
1014   int uniq_tid_of_child = child_t.uniq_tid;
1015   g_pin_threads[tid].last_child_tid = 0;
1016 
1017   IgnoreMopsEnd(tid);
1018   g_thread_create_lock.Unlock();
1019 
1020   DumpEvent(0, THR_CREATE_AFTER, tid, 0, 0, uniq_tid_of_child);
1021   return last_child_tid;
1022 }
1023 
WRAP_NAME(pthread_create)1024 static uintptr_t WRAP_NAME(pthread_create)(WRAP_PARAM4) {
1025   HandleThreadCreateBefore(tid, pc);
1026 
1027   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
1028   if (ret != 0) {
1029     HandleThreadCreateAbort(tid);
1030     return ret;
1031   }
1032 
1033   pthread_t child_ptid = *(pthread_t*)arg0;
1034   HandleThreadCreateAfter(tid, child_ptid, false);
1035 
1036   return ret;
1037 }
1038 
CallbackForThreadStart(THREADID tid,CONTEXT * ctxt,INT32 flags,void * v)1039 void CallbackForThreadStart(THREADID tid, CONTEXT *ctxt,
1040                             INT32 flags, void *v) {
1041   // We can not rely on PIN_GetParentTid() since it is broken on Windows.
1042 
1043   if (g_pin_threads == NULL) {
1044     g_pin_threads = new PinThread[kMaxThreads];
1045   }
1046 
1047   bool has_parent = true;
1048   if (tid == 0) {
1049     // Main thread or we have attached to a running process.
1050     has_parent = false;
1051   } else {
1052     CHECK(tid > 0);
1053   }
1054 
1055   CHECK(tid < kMaxThreads);
1056   PinThread &t = g_pin_threads[tid];
1057   memset(&t, 0, sizeof(PinThread));
1058   t.uniq_tid = n_started_threads++;
1059   t.literace_sampling = G_flags->literace_sampling;
1060   t.tid = tid;
1061   t.tleb.t = &t;
1062 #if defined(_MSC_VER)
1063   t.startup_state = PinThread::STARTING;
1064 #endif
1065   ComputeIgnoreAccesses(t);
1066 
1067 
1068   PIN_SetContextReg(ctxt, tls_reg, (ADDRINT)&t.tleb.events[2]);
1069 
1070   t.parent_tid = -1;
1071   if (has_parent) {
1072     t.parent_tid = g_tid_of_thread_which_called_create_thread;
1073 #if !defined(_MSC_VER)  // On Windows, threads may appear out of thin air.
1074     CHECK(t.parent_tid != (THREADID)-1);
1075 #endif  // _MSC_VER
1076   }
1077 
1078   if (debug_thread) {
1079     Printf("T%d ThreadStart parent=%d child=%d\n", tid, t.parent_tid, tid);
1080   }
1081 
1082   if (has_parent && t.parent_tid != (THREADID)-1) {
1083     g_pin_threads[t.parent_tid].last_child_tid = tid;
1084     t.thread_stack_size_if_known =
1085         g_pin_threads[t.parent_tid].last_child_stack_size_if_known;
1086   } else {
1087 #if defined(_MSC_VER)
1088     t.startup_state = PinThread::MAY_CONTINUE;
1089 #endif
1090   }
1091 
1092   // This is a lock-free (thread local) operation.
1093   TLEBStartThread(t);
1094 /* TODO(timurrrr): investigate and un-comment
1095 #ifdef _MSC_VER
1096   // Ignore all mops & sync before the real thread code.
1097   // See the corresponding IgnoreSyncAndMopsEnd in Before_BaseThreadInitThunk.
1098   IgnoreSyncAndMopsBegin(tid);
1099 #endif
1100 */
1101 }
1102 
Before_start_thread(THREADID tid,ADDRINT pc,ADDRINT sp)1103 static void Before_start_thread(THREADID tid, ADDRINT pc, ADDRINT sp) {
1104   PinThread &t = g_pin_threads[tid];
1105   if (debug_thread) {
1106     Printf("T%d Before_start_thread: sp=%p my_ptid=%p diff=%p\n",
1107          tid, sp, t.my_ptid, t.my_ptid - sp);
1108   }
1109   // This is a rather scary hack, but I see no easy way to avoid it.
1110   // On linux NPTL, the pthread_t structure is the same block of memory
1111   // as the stack (and the tls?). Somewhere inside the pthread_t
1112   // object lives the address of stackblock followed by its size
1113   // (see nptl/descr.h).
1114   // At the current point we may not know the value of pthread_t (my_ptid),
1115   // but we do know the current sp, which is a bit less than my_ptid.
1116   //
1117   // address                        value
1118   // ------------------------------------------------
1119   // 0xffffffffffffffff:
1120   //
1121   // stackblock + stackblock_size:
1122   // my_ptid:
1123   //
1124   //                                stackblock_size
1125   //                                stackblock
1126   //
1127   // current_sp:
1128   //
1129   //
1130   // stackblock:
1131   //
1132   // 0x0000000000000000:
1133   // -------------------------------------------------
1134   //
1135   // So, we itrate from sp to the higher addresses (but just in case, not more
1136   // than a few pages) trying to find a pair of values which looks like
1137   // stackblock and stackblock_size. Oh well.
1138   // Note that in valgrind we are able to get this info from
1139   //  pthread_getattr_np (linux) or pthread_get_stackaddr_np (mac),
1140   // but in PIN we can't call those (can we?).
1141   uintptr_t prev = 0;
1142   for (uintptr_t sp1 = sp; sp1 - sp < 0x2000;
1143        sp1 += sizeof(uintptr_t)) {
1144     uintptr_t val = *(uintptr_t*)sp1;
1145     if (val == 0) continue;
1146     if (prev &&
1147         (prev & 0xfff) == 0 && // stack is page aligned
1148         prev < sp &&           // min stack is < sp
1149         prev + val > sp &&     // max stack is > sp
1150         val >= (1 << 15) &&    // stack size is >= 32k
1151         val <= 128 * (1 << 20) // stack size is hardly > 128M
1152         ) {
1153       if (debug_thread) {
1154         Printf("T%d found stack: %p size=%p\n", tid, prev, val);
1155       }
1156       DumpEvent(0, THR_STACK_TOP, tid, pc, prev + val, val);
1157       return;
1158     }
1159     prev = val;
1160   }
1161   // The hack above does not always works. (TODO(kcc)). Do something.
1162   Printf("WARNING: ThreadSanitizerPin is guessing stack size for T%d\n", tid);
1163   DumpEvent(0, THR_STACK_TOP, tid, pc, sp, t.thread_stack_size_if_known);
1164 }
1165 
1166 #ifdef _MSC_VER
WRAP_NAME(CreateThread)1167 static uintptr_t WRAP_NAME(CreateThread)(WRAP_PARAM6) {
1168   PinThread &t = g_pin_threads[tid];
1169   t.last_child_stack_size_if_known = arg1 ? arg1 : 1024 * 1024;
1170 
1171   HandleThreadCreateBefore(tid, pc);
1172 
1173   // We can't start the thread suspended because we want to get its
1174   // PIN thread ID before leaving CreateThread.
1175   // So, we reset the CREATE_SUSPENDED flag and SuspendThread before any client
1176   // code is executed in the HandleThreadCreateAfter if needed.
1177   bool should_be_suspended = arg4 & CREATE_SUSPENDED;
1178   arg4 &= ~CREATE_SUSPENDED;
1179 
1180   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_6();
1181   if (ret == NULL) {
1182     HandleThreadCreateAbort(tid);
1183     return ret;
1184   }
1185   pthread_t child_ptid = ret;
1186   THREADID child_tid = HandleThreadCreateAfter(tid, child_ptid,
1187                                                should_be_suspended);
1188   {
1189     ScopedReentrantClientLock lock(__LINE__);
1190     if (g_win_handles_which_are_threads == NULL) {
1191       g_win_handles_which_are_threads = new unordered_set<pthread_t>;
1192     }
1193     g_win_handles_which_are_threads->insert(child_ptid);
1194   }
1195   return ret;
1196 }
1197 
Before_BaseThreadInitThunk(THREADID tid,ADDRINT pc,ADDRINT sp)1198 static void Before_BaseThreadInitThunk(THREADID tid, ADDRINT pc, ADDRINT sp) {
1199   PinThread &t = g_pin_threads[tid];
1200   size_t stack_size = t.thread_stack_size_if_known;
1201   // Printf("T%d %s %p %p\n", tid, __FUNCTION__, sp, stack_size);
1202   /* TODO(timurrrr): investigate and uncomment
1203   if (tid != 0) {
1204     // Ignore all mops & sync before the real thread code.
1205     // See the corresponding IgnoreSyncAndMopsBegin in CallbackForThreadStart.
1206     IgnoreSyncAndMopsEnd(tid);
1207     TLEBFlushLocked(t);
1208     CHECK(t.ignore_sync == 0);
1209     CHECK(t.ignore_accesses == 0);
1210   }
1211   */
1212   DumpEvent(0, THR_STACK_TOP, tid, pc, sp, stack_size);
1213 
1214 #ifdef _MSC_VER
1215   if (t.startup_state != PinThread::MAY_CONTINUE) {
1216     CHECK(t.startup_state == PinThread::STARTING);
1217     t.startup_state = PinThread::CHILD_READY;
1218     while (ATOMIC_READ(&t.startup_state) != PinThread::MAY_CONTINUE) {
1219       YIELD();
1220     }
1221     // Corresponds to SIGNAL from ResumeThread if the thread was suspended on
1222     // start.
1223     DumpEvent(0, WAIT, tid, pc, t.my_ptid, 0);
1224   }
1225 #endif
1226 }
1227 
Before_RtlExitUserThread(THREADID tid,ADDRINT pc)1228 static void Before_RtlExitUserThread(THREADID tid, ADDRINT pc) {
1229   PinThread &t = g_pin_threads[tid];
1230   if (t.tid != 0) {
1231     // Once we started exiting the thread, ignore the locking events.
1232     // This way we will avoid h-b arcs between unrelated threads.
1233     // We also start ignoring all mops, otherwise we will get tons of race
1234     // reports from the windows guts.
1235     IgnoreSyncAndMopsBegin(tid);
1236   }
1237 }
1238 #endif  // _MSC_VER
1239 
CallbackForThreadFini(THREADID tid,const CONTEXT * ctxt,INT32 code,void * v)1240 void CallbackForThreadFini(THREADID tid, const CONTEXT *ctxt,
1241                           INT32 code, void *v) {
1242   PinThread &t = g_pin_threads[tid];
1243   t.thread_finished = true;
1244   // We can not DumpEvent here,
1245   // due to possible deadlock with PIN's internal lock.
1246   if (debug_thread) {
1247     Printf("T%d Thread finished (ptid=%d)\n", tid, t.my_ptid);
1248   }
1249 }
1250 
HandleThreadJoinAfter(THREADID tid,pthread_t joined_ptid)1251 static bool HandleThreadJoinAfter(THREADID tid, pthread_t joined_ptid) {
1252   THREADID joined_tid = kMaxThreads;
1253   int max_uniq_tid_found = -1;
1254 
1255   // TODO(timurrrr): walking through g_pin_threads may be slow.
1256   // Do we need to/Can we optimize it?
1257   for (THREADID j = 1; j < kMaxThreads; j++) {
1258     if (g_pin_threads[j].thread_finished == false)
1259       continue;
1260     if (g_pin_threads[j].my_ptid == joined_ptid) {
1261       // We search for the thread with the maximum uniq_tid to work around
1262       // thread HANDLE reuse issues.
1263       if (max_uniq_tid_found < g_pin_threads[j].uniq_tid) {
1264         max_uniq_tid_found = g_pin_threads[j].uniq_tid;
1265         joined_tid = j;
1266       }
1267     }
1268   }
1269   if (joined_tid == kMaxThreads) {
1270     // This may happen in the following case:
1271     //  - A non-joinable thread is created and a handle is assigned to it.
1272     //  - Since the thread is non-joinable, the handle is then reused
1273     //  for some other purpose, e.g. for a WaitableEvent.
1274     //  - We did not yet register the thread fini event.
1275     //  - We observe WaitForSingleObjectEx(ptid) and think that this is thread
1276     //  join event, while it is not.
1277     if (debug_thread)
1278       Printf("T%d JoinAfter returns false! ptid=%d\n", tid, joined_ptid);
1279     return false;
1280   }
1281   CHECK(joined_tid < kMaxThreads);
1282   CHECK(joined_tid > 0);
1283   g_pin_threads[joined_tid].my_ptid = 0;
1284   int joined_uniq_tid = g_pin_threads[joined_tid].uniq_tid;
1285 
1286   if (debug_thread) {
1287     Printf("T%d JoinAfter   parent=%d child=%d (uniq=%d)\n", tid, tid,
1288            joined_tid, joined_uniq_tid);
1289   }
1290 
1291   // Here we send an event for a different thread (joined_tid), which is already
1292   // dead.
1293   DumpEvent(0, THR_END, joined_tid, 0, 0, 0);
1294 
1295 
1296   DumpEvent(0, THR_JOIN_AFTER, tid, 0, joined_uniq_tid, 0);
1297   return true;
1298 }
1299 
WRAP_NAME(pthread_join)1300 static uintptr_t WRAP_NAME(pthread_join)(WRAP_PARAM4) {
1301   if (G_flags->debug_level >= 2)
1302     Printf("T%d in  pthread_join %p\n", tid, arg0);
1303   pthread_t joined_ptid = (pthread_t)arg0;
1304   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
1305   HandleThreadJoinAfter(tid, joined_ptid);
1306   if (G_flags->debug_level >= 2)
1307     Printf("T%d out pthread_join %p\n", tid, arg0);
1308   return ret;
1309 }
1310 
WRAP_NAME(fwrite)1311 static size_t WRAP_NAME(fwrite)(WRAP_PARAM4) {
1312   void* p = (void*)arg0;
1313   size_t size = (size_t)arg1 * (size_t)arg2;
1314   REPORT_READ_RANGE(p, size);
1315   IgnoreMopsBegin(tid);
1316   size_t ret = CALL_ME_INSIDE_WRAPPER_4();
1317   IgnoreMopsEnd(tid);
1318   return ret;
1319 }
1320 
1321 #ifdef _MSC_VER
1322 
1323 
CallStdCallFun1(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0)1324 uintptr_t CallStdCallFun1(CONTEXT *ctx, THREADID tid,
1325                          AFUNPTR f, uintptr_t arg0) {
1326   uintptr_t ret = 0xdeadbee1;
1327   PIN_CallApplicationFunction(ctx, tid,
1328                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1329                               PIN_PARG(uintptr_t), &ret,
1330                               PIN_PARG(uintptr_t), arg0,
1331                               PIN_PARG_END());
1332   return ret;
1333 }
1334 
CallStdCallFun2(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1)1335 uintptr_t CallStdCallFun2(CONTEXT *ctx, THREADID tid,
1336                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1) {
1337   uintptr_t ret = 0xdeadbee2;
1338   PIN_CallApplicationFunction(ctx, tid,
1339                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1340                               PIN_PARG(uintptr_t), &ret,
1341                               PIN_PARG(uintptr_t), arg0,
1342                               PIN_PARG(uintptr_t), arg1,
1343                               PIN_PARG_END());
1344   return ret;
1345 }
1346 
CallStdCallFun3(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2)1347 uintptr_t CallStdCallFun3(CONTEXT *ctx, THREADID tid,
1348                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
1349                          uintptr_t arg2) {
1350   uintptr_t ret = 0xdeadbee3;
1351   PIN_CallApplicationFunction(ctx, tid,
1352                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1353                               PIN_PARG(uintptr_t), &ret,
1354                               PIN_PARG(uintptr_t), arg0,
1355                               PIN_PARG(uintptr_t), arg1,
1356                               PIN_PARG(uintptr_t), arg2,
1357                               PIN_PARG_END());
1358   return ret;
1359 }
1360 
CallStdCallFun4(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3)1361 uintptr_t CallStdCallFun4(CONTEXT *ctx, THREADID tid,
1362                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
1363                          uintptr_t arg2, uintptr_t arg3) {
1364   uintptr_t ret = 0xdeadbee4;
1365   PIN_CallApplicationFunction(ctx, tid,
1366                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1367                               PIN_PARG(uintptr_t), &ret,
1368                               PIN_PARG(uintptr_t), arg0,
1369                               PIN_PARG(uintptr_t), arg1,
1370                               PIN_PARG(uintptr_t), arg2,
1371                               PIN_PARG(uintptr_t), arg3,
1372                               PIN_PARG_END());
1373   return ret;
1374 }
1375 
CallStdCallFun5(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4)1376 uintptr_t CallStdCallFun5(CONTEXT *ctx, THREADID tid,
1377                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
1378                          uintptr_t arg2, uintptr_t arg3,
1379                          uintptr_t arg4) {
1380   uintptr_t ret = 0xdeadbee5;
1381   PIN_CallApplicationFunction(ctx, tid,
1382                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1383                               PIN_PARG(uintptr_t), &ret,
1384                               PIN_PARG(uintptr_t), arg0,
1385                               PIN_PARG(uintptr_t), arg1,
1386                               PIN_PARG(uintptr_t), arg2,
1387                               PIN_PARG(uintptr_t), arg3,
1388                               PIN_PARG(uintptr_t), arg4,
1389                               PIN_PARG_END());
1390   return ret;
1391 }
1392 
CallStdCallFun6(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5)1393 uintptr_t CallStdCallFun6(CONTEXT *ctx, THREADID tid,
1394                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
1395                          uintptr_t arg2, uintptr_t arg3,
1396                          uintptr_t arg4, uintptr_t arg5) {
1397   uintptr_t ret = 0xdeadbee6;
1398   PIN_CallApplicationFunction(ctx, tid,
1399                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1400                               PIN_PARG(uintptr_t), &ret,
1401                               PIN_PARG(uintptr_t), arg0,
1402                               PIN_PARG(uintptr_t), arg1,
1403                               PIN_PARG(uintptr_t), arg2,
1404                               PIN_PARG(uintptr_t), arg3,
1405                               PIN_PARG(uintptr_t), arg4,
1406                               PIN_PARG(uintptr_t), arg5,
1407                               PIN_PARG_END());
1408   return ret;
1409 }
1410 
CallStdCallFun7(CONTEXT * ctx,THREADID tid,AFUNPTR f,uintptr_t arg0,uintptr_t arg1,uintptr_t arg2,uintptr_t arg3,uintptr_t arg4,uintptr_t arg5,uintptr_t arg6)1411 uintptr_t CallStdCallFun7(CONTEXT *ctx, THREADID tid,
1412                          AFUNPTR f, uintptr_t arg0, uintptr_t arg1,
1413                          uintptr_t arg2, uintptr_t arg3,
1414                          uintptr_t arg4, uintptr_t arg5,
1415                          uintptr_t arg6) {
1416   uintptr_t ret = 0xdeadbee7;
1417   PIN_CallApplicationFunction(ctx, tid,
1418                               CALLINGSTD_STDCALL, (AFUNPTR)(f),
1419                               PIN_PARG(uintptr_t), &ret,
1420                               PIN_PARG(uintptr_t), arg0,
1421                               PIN_PARG(uintptr_t), arg1,
1422                               PIN_PARG(uintptr_t), arg2,
1423                               PIN_PARG(uintptr_t), arg3,
1424                               PIN_PARG(uintptr_t), arg4,
1425                               PIN_PARG(uintptr_t), arg5,
1426                               PIN_PARG(uintptr_t), arg6,
1427                               PIN_PARG_END());
1428   return ret;
1429 }
1430 
WRAP_NAME(ResumeThread)1431 uintptr_t WRAP_NAME(ResumeThread)(WRAP_PARAM4) {
1432 //  Printf("T%d %s arg0=%p\n", tid, __FUNCTION__, arg0);
1433   DumpEvent(ctx, SIGNAL, tid, pc, arg0, 0);
1434   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1435   return ret;
1436 }
WRAP_NAME(RtlInitializeCriticalSection)1437 uintptr_t WRAP_NAME(RtlInitializeCriticalSection)(WRAP_PARAM4) {
1438 //  Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1439   DumpEvent(ctx, LOCK_CREATE, tid, pc, arg0, 0);
1440   IgnoreSyncAndMopsBegin(tid);
1441   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1442   IgnoreSyncAndMopsEnd(tid);
1443   return ret;
1444 }
WRAP_NAME(RtlInitializeCriticalSectionAndSpinCount)1445 uintptr_t WRAP_NAME(RtlInitializeCriticalSectionAndSpinCount)(WRAP_PARAM4) {
1446 //  Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1447   DumpEvent(ctx, LOCK_CREATE, tid, pc, arg0, 0);
1448   IgnoreSyncAndMopsBegin(tid);
1449   uintptr_t ret = CallStdCallFun2(ctx, tid, f, arg0, arg1);
1450   IgnoreSyncAndMopsEnd(tid);
1451   return ret;
1452 }
WRAP_NAME(RtlInitializeCriticalSectionEx)1453 uintptr_t WRAP_NAME(RtlInitializeCriticalSectionEx)(WRAP_PARAM4) {
1454 //  Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1455   DumpEvent(ctx, LOCK_CREATE, tid, pc, arg0, 0);
1456   IgnoreSyncAndMopsBegin(tid);
1457   uintptr_t ret = CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1458   IgnoreSyncAndMopsEnd(tid);
1459   return ret;
1460 }
WRAP_NAME(RtlDeleteCriticalSection)1461 uintptr_t WRAP_NAME(RtlDeleteCriticalSection)(WRAP_PARAM4) {
1462 //  Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1463   DumpEvent(ctx, LOCK_DESTROY, tid, pc, arg0, 0);
1464   IgnoreSyncAndMopsBegin(tid);
1465   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1466   IgnoreSyncAndMopsEnd(tid);
1467   return ret;
1468 }
WRAP_NAME(RtlEnterCriticalSection)1469 uintptr_t WRAP_NAME(RtlEnterCriticalSection)(WRAP_PARAM4) {
1470 //  Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1471   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1472   DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
1473   return ret;
1474 }
WRAP_NAME(RtlTryEnterCriticalSection)1475 uintptr_t WRAP_NAME(RtlTryEnterCriticalSection)(WRAP_PARAM4) {
1476   // Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+5, arg0);
1477   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1478   if (ret) {
1479     DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
1480   }
1481   return ret;
1482 }
WRAP_NAME(RtlLeaveCriticalSection)1483 uintptr_t WRAP_NAME(RtlLeaveCriticalSection)(WRAP_PARAM4) {
1484 //  Printf("T%d pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1485   DumpEvent(ctx, UNLOCK, tid, pc, arg0, 0);
1486   return CallStdCallFun1(ctx, tid, f, arg0);
1487 }
1488 
WRAP_NAME(DuplicateHandle)1489 uintptr_t WRAP_NAME(DuplicateHandle)(WRAP_PARAM8) {
1490   Printf("WARNING: DuplicateHandle called for handle 0x%X.\n", arg1);
1491   Printf("Future events on this handle may be processed incorrectly.\n");
1492   return CallStdCallFun7(ctx, tid, f, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
1493 }
1494 
WRAP_NAME(SetEvent)1495 uintptr_t WRAP_NAME(SetEvent)(WRAP_PARAM4) {
1496   //Printf("T%d before pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1497   DumpEvent(ctx, SIGNAL, tid, pc, arg0, 0);
1498   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1499   //Printf("T%d after pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0);
1500   return ret;
1501 }
1502 
InternalWrapCreateSemaphore(WRAP_PARAM4)1503 uintptr_t InternalWrapCreateSemaphore(WRAP_PARAM4) {
1504   if (arg3 != NULL) {
1505     Printf("WARNING: CreateSemaphore called with lpName='%s'.\n", arg3);
1506     Printf("Future events on this semaphore may be processed incorrectly "
1507            "if it is reused.\n");
1508   }
1509   return CallStdCallFun4(ctx, tid, f, arg0, arg1, arg2, arg3);
1510 }
1511 
WRAP_NAME(CreateSemaphoreA)1512 uintptr_t WRAP_NAME(CreateSemaphoreA)(WRAP_PARAM4) {
1513   return InternalWrapCreateSemaphore(tid, pc, ctx, f, arg0, arg1, arg2, arg3);
1514 }
1515 
WRAP_NAME(CreateSemaphoreW)1516 uintptr_t WRAP_NAME(CreateSemaphoreW)(WRAP_PARAM4) {
1517   return InternalWrapCreateSemaphore(tid, pc, ctx, f, arg0, arg1, arg2, arg3);
1518 }
1519 
WRAP_NAME(ReleaseSemaphore)1520 uintptr_t WRAP_NAME(ReleaseSemaphore)(WRAP_PARAM4) {
1521   DumpEvent(ctx, SIGNAL, tid, pc, arg0, 0);
1522   return CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1523 }
1524 
WRAP_NAME(RtlInterlockedPushEntrySList)1525 uintptr_t WRAP_NAME(RtlInterlockedPushEntrySList)(WRAP_PARAM4) {
1526   DumpEvent(ctx, SIGNAL, tid, pc, arg1, 0);
1527   uintptr_t ret = CallStdCallFun2(ctx, tid, f, arg0, arg1);
1528   // Printf("T%d %s list=%p item=%p\n", tid, __FUNCTION__, arg0, arg1);
1529   return ret;
1530 }
1531 
WRAP_NAME(RtlInterlockedPopEntrySList)1532 uintptr_t WRAP_NAME(RtlInterlockedPopEntrySList)(WRAP_PARAM4) {
1533   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1534   // Printf("T%d %s list=%p item=%p\n", tid, __FUNCTION__, arg0, ret);
1535   if (ret) {
1536     DumpEvent(ctx, WAIT, tid, pc, ret, 0);
1537   }
1538   return ret;
1539 }
1540 
WRAP_NAME(RtlAcquireSRWLockExclusive)1541 uintptr_t WRAP_NAME(RtlAcquireSRWLockExclusive)(WRAP_PARAM4) {
1542   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1543   DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
1544   return ret;
1545 }
WRAP_NAME(RtlAcquireSRWLockShared)1546 uintptr_t WRAP_NAME(RtlAcquireSRWLockShared)(WRAP_PARAM4) {
1547   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1548   DumpEvent(ctx, READER_LOCK, tid, pc, arg0, 0);
1549   return ret;
1550 }
WRAP_NAME(RtlTryAcquireSRWLockExclusive)1551 uintptr_t WRAP_NAME(RtlTryAcquireSRWLockExclusive)(WRAP_PARAM4) {
1552   // Printf("T%d %s %p\n", tid, __FUNCTION__, arg0);
1553   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1554   if (ret & 0xFF) {  // Looks like this syscall return value is just 1 byte.
1555     DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
1556   }
1557   return ret;
1558 }
WRAP_NAME(RtlTryAcquireSRWLockShared)1559 uintptr_t WRAP_NAME(RtlTryAcquireSRWLockShared)(WRAP_PARAM4) {
1560   // Printf("T%d %s %p\n", tid, __FUNCTION__, arg0);
1561   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1562   if (ret & 0xFF) {  // Looks like this syscall return value is just 1 byte.
1563     DumpEvent(ctx, READER_LOCK, tid, pc, arg0, 0);
1564   }
1565   return ret;
1566 }
WRAP_NAME(RtlReleaseSRWLockExclusive)1567 uintptr_t WRAP_NAME(RtlReleaseSRWLockExclusive)(WRAP_PARAM4) {
1568   // Printf("T%d %s %p\n", tid, __FUNCTION__, arg0);
1569   DumpEvent(ctx, UNLOCK, tid, pc, arg0, 0);
1570   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1571   return ret;
1572 }
WRAP_NAME(RtlReleaseSRWLockShared)1573 uintptr_t WRAP_NAME(RtlReleaseSRWLockShared)(WRAP_PARAM4) {
1574   // Printf("T%d %s %p\n", tid, __FUNCTION__, arg0);
1575   DumpEvent(ctx, UNLOCK, tid, pc, arg0, 0);
1576   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1577   return ret;
1578 }
WRAP_NAME(RtlInitializeSRWLock)1579 uintptr_t WRAP_NAME(RtlInitializeSRWLock)(WRAP_PARAM4) {
1580   // Printf("T%d %s %p\n", tid, __FUNCTION__, arg0);
1581   DumpEvent(ctx, LOCK_CREATE, tid, pc, arg0, 0);
1582   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1583   return ret;
1584 }
1585 
WRAP_NAME(RtlWakeConditionVariable)1586 uintptr_t WRAP_NAME(RtlWakeConditionVariable)(WRAP_PARAM4) {
1587   // Printf("T%d %s arg0=%p\n", tid, __FUNCTION__, arg0);
1588   DumpEvent(ctx, SIGNAL, tid, pc, arg0, 0);
1589   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1590   return ret;
1591 }
WRAP_NAME(RtlWakeAllConditionVariable)1592 uintptr_t WRAP_NAME(RtlWakeAllConditionVariable)(WRAP_PARAM4) {
1593   // Printf("T%d %s arg0=%p\n", tid, __FUNCTION__, arg0);
1594   DumpEvent(ctx, SIGNAL, tid, pc, arg0, 0);
1595   uintptr_t ret = CallStdCallFun1(ctx, tid, f, arg0);
1596   return ret;
1597 }
WRAP_NAME(RtlSleepConditionVariableSRW)1598 uintptr_t WRAP_NAME(RtlSleepConditionVariableSRW)(WRAP_PARAM4) {
1599   // No need to unlock/lock - looks like RtlSleepConditionVariableSRW performs
1600   // Rtl{Acquire,Release}SRW... calls itself!
1601   uintptr_t ret = CallStdCallFun4(ctx, tid, f, arg0, arg1, arg2, arg3);
1602   if ((ret & 0xFF) == 0)
1603     DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
1604   // Printf("T%d %s arg0=%p arg1=%p; ret=%d\n", tid, __FUNCTION__, arg0, arg1, ret);
1605   return ret;
1606 }
WRAP_NAME(RtlSleepConditionVariableCS)1607 uintptr_t WRAP_NAME(RtlSleepConditionVariableCS)(WRAP_PARAM4) {
1608   // TODO(timurrrr): do we need unlock/lock?
1609   uintptr_t ret = CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1610   if ((ret & 0xFF) == 0)
1611     DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
1612   // Printf("T%d %s arg0=%p arg1=%p; ret=%d\n", tid, __FUNCTION__, arg0, arg1, ret);
1613   return ret;
1614 }
1615 
WRAP_NAME(RtlQueueWorkItem)1616 uintptr_t WRAP_NAME(RtlQueueWorkItem)(WRAP_PARAM4) {
1617   // Printf("T%d %s arg0=%p arg1=%p; arg2=%d\n", tid, __FUNCTION__, arg0, arg1, arg2);
1618   g_windows_thread_pool_calback_set->insert(arg0);
1619   DumpEvent(ctx, SIGNAL, tid, pc, arg0, 0);
1620   uintptr_t ret = CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1621   return ret;
1622 }
1623 
WRAP_NAME(RegisterWaitForSingleObject)1624 uintptr_t WRAP_NAME(RegisterWaitForSingleObject)(WRAP_PARAM6) {
1625   // Printf("T%d %s arg0=%p arg2=%p\n", tid, __FUNCTION__, arg0, arg2);
1626   g_windows_thread_pool_calback_set->insert(arg2);
1627   DumpEvent(ctx, SIGNAL, tid, pc, arg2, 0);
1628   uintptr_t ret = CallStdCallFun6(ctx, tid, f, arg0, arg1, arg2, arg3, arg4, arg5);
1629   if (ret) {
1630     uintptr_t wait_object = *(uintptr_t*)arg0;
1631     (*g_windows_thread_pool_wait_object_map)[wait_object] = arg2;
1632     // Printf("T%d %s *arg0=%p\n", tid, __FUNCTION__, wait_object);
1633   }
1634   return ret;
1635 }
1636 
WRAP_NAME(UnregisterWaitEx)1637 uintptr_t WRAP_NAME(UnregisterWaitEx)(WRAP_PARAM4) {
1638   CHECK(g_windows_thread_pool_wait_object_map);
1639   uintptr_t obj = (*g_windows_thread_pool_wait_object_map)[arg0];
1640   // Printf("T%d %s arg0=%p obj=%p\n", tid, __FUNCTION__, arg0, obj);
1641   uintptr_t ret = CallStdCallFun2(ctx, tid, f, arg0, arg1);
1642   if (ret) {
1643     DumpEvent(ctx, WAIT, tid, pc, obj, 0);
1644   }
1645   return ret;
1646 }
1647 
WRAP_NAME(VirtualAlloc)1648 uintptr_t WRAP_NAME(VirtualAlloc)(WRAP_PARAM4) {
1649   // Printf("T%d VirtualAlloc: %p %p %p %p\n", tid, arg0, arg1, arg2, arg3);
1650   uintptr_t ret = CallStdCallFun4(ctx, tid, f, arg0, arg1, arg2, arg3);
1651   return ret;
1652 }
1653 
WRAP_NAME(GlobalAlloc)1654 uintptr_t WRAP_NAME(GlobalAlloc)(WRAP_PARAM4) {
1655   uintptr_t ret = CallStdCallFun2(ctx, tid, f, arg0, arg1);
1656   // Printf("T%d %s(%p %p)=%p\n", tid, __FUNCTION__, arg0, arg1, ret);
1657   if (ret != 0) {
1658     DumpEvent(ctx, MALLOC, tid, pc, ret, arg1);
1659   }
1660   return ret;
1661 }
1662 
WRAP_NAME(ZwAllocateVirtualMemory)1663 uintptr_t WRAP_NAME(ZwAllocateVirtualMemory)(WRAP_PARAM6) {
1664   // Printf("T%d >>%s(%p %p %p %p %p %p)\n", tid, __FUNCTION__, arg0, arg1, arg2, arg3, arg4, arg5);
1665   uintptr_t ret = CallStdCallFun6(ctx, tid, f, arg0, arg1, arg2, arg3, arg4, arg5);
1666   // Printf("T%d <<%s(%p %p) = %p\n", tid, __FUNCTION__, *(void**)arg1, *(void**)arg3, ret);
1667   if (ret == 0) {
1668     DumpEvent(ctx, MALLOC, tid, pc, *(uintptr_t*)arg1, *(uintptr_t*)arg3);
1669   }
1670   return ret;
1671 }
1672 
WRAP_NAME(AllocateHeap)1673 uintptr_t WRAP_NAME(AllocateHeap)(WRAP_PARAM4) {
1674   uintptr_t ret = CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1675   // Printf("T%d RtlAllocateHeap(%p %p %p)=%p\n", tid, arg0, arg1, arg2, ret);
1676   if (ret != 0) {
1677     DumpEvent(ctx, MALLOC, tid, pc, ret, arg3);
1678   }
1679   return ret;
1680 }
1681 
WRAP_NAME(HeapCreate)1682 uintptr_t WRAP_NAME(HeapCreate)(WRAP_PARAM4) {
1683   uintptr_t ret = CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1684   Printf("T%d %s(%p %p %p)=%p\n", tid, __FUNCTION__, arg0, arg1, arg2, ret);
1685   return ret;
1686 }
1687 
1688 // We don't use the definition of WAIT_OBJECT_0 from winbase.h because
1689 // it can't be compiled here for some reason.
1690 #define WAIT_OBJECT_0_ 0
1691 
WRAP_NAME(WaitForSingleObjectEx)1692 uintptr_t WRAP_NAME(WaitForSingleObjectEx)(WRAP_PARAM4) {
1693   if (G_flags->verbosity >= 1) {
1694     ShowPcAndSp(__FUNCTION__, tid, pc, 0);
1695     Printf("arg0=%lx arg1=%lx\n", arg0, arg1);
1696   }
1697 
1698   //Printf("T%d before pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0, arg1);
1699   uintptr_t ret = CallStdCallFun3(ctx, tid, f, arg0, arg1, arg2);
1700   //Printf("T%d after pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0, arg1);
1701 
1702   if (ret == WAIT_OBJECT_0_) {
1703     bool is_thread_handle = false;
1704     {
1705       ScopedReentrantClientLock lock(__LINE__);
1706       if (g_win_handles_which_are_threads) {
1707         is_thread_handle = g_win_handles_which_are_threads->count(arg0) > 0;
1708         g_win_handles_which_are_threads->erase(arg0);
1709       }
1710     }
1711     if (is_thread_handle)
1712       HandleThreadJoinAfter(tid, arg0);
1713     DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
1714   }
1715 
1716   return ret;
1717 }
1718 
WRAP_NAME(WaitForMultipleObjectsEx)1719 uintptr_t WRAP_NAME(WaitForMultipleObjectsEx)(WRAP_PARAM6) {
1720   if (G_flags->verbosity >= 1) {
1721     ShowPcAndSp(__FUNCTION__, tid, pc, 0);
1722     Printf("arg0=%lx arg1=%lx arg2=%lx arg3=%lx\n", arg0, arg1, arg2, arg3);
1723   }
1724 
1725   //Printf("T%d before pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0, arg1);
1726   uintptr_t ret = CallStdCallFun5(ctx, tid, f, arg0, arg1, arg2, arg3, arg4);
1727   //Printf("T%d after pc=%p %s: %p\n", tid, pc, __FUNCTION__+8, arg0, arg1);
1728 
1729   if (ret >= WAIT_OBJECT_0_ && ret < WAIT_OBJECT_0_ + arg0) {
1730     // TODO(timurrrr): add support for WAIT_ABANDONED_0
1731 
1732     int start_id, count;
1733     if (arg2 /* wait_for_all */ == 1) {
1734       start_id = 0;
1735       count = arg0;
1736     } else {
1737       start_id = ret - WAIT_OBJECT_0_;
1738       count = 1;
1739     }
1740 
1741     for (int i = start_id; i < start_id + count; i++) {
1742       uintptr_t handle = ((uintptr_t*)arg1)[i];
1743       bool is_thread_handle = false;
1744       {
1745         ScopedReentrantClientLock lock(__LINE__);
1746         if (g_win_handles_which_are_threads) {
1747           is_thread_handle = g_win_handles_which_are_threads->count(handle) > 0;
1748           g_win_handles_which_are_threads->erase(handle);
1749         }
1750       }
1751       if (is_thread_handle)
1752         HandleThreadJoinAfter(tid, handle);
1753       DumpEvent(ctx, WAIT, tid, pc, handle, 0);
1754     }
1755   }
1756 
1757   return ret;
1758 }
1759 
1760 #endif  // _MSC_VER
1761 
1762 //--------- memory allocation ---------------------- {{{2
WRAP_NAME(mmap)1763 uintptr_t WRAP_NAME(mmap)(WRAP_PARAM6) {
1764   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_6();
1765 
1766   if (ret != (ADDRINT)-1L) {
1767     DumpEvent(ctx, MMAP, tid, pc, ret, arg1);
1768   }
1769 
1770   return ret;
1771 }
1772 
WRAP_NAME(munmap)1773 uintptr_t WRAP_NAME(munmap)(WRAP_PARAM4) {
1774   PinThread &t = g_pin_threads[tid];
1775   TLEBFlushLocked(t);
1776   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
1777   if (ret != (uintptr_t)-1L) {
1778     DumpEvent(ctx, MUNMAP, tid, pc, arg0, arg1);
1779   }
1780   return ret;
1781 }
1782 
1783 
After_malloc(FAST_WRAP_PARAM_AFTER)1784 void After_malloc(FAST_WRAP_PARAM_AFTER) {
1785   size_t size = frame.arg[0];
1786   if (DEBUG_FAST_INTERCEPTORS)
1787     Printf("T%d %s %ld %p\n", tid, __FUNCTION__, size, ret);
1788   IgnoreSyncAndMopsEnd(tid);
1789   DumpEventWithSp(frame.sp, MALLOC, tid, frame.pc, ret, size);
1790 }
1791 
Before_malloc(FAST_WRAP_PARAM1)1792 void Before_malloc(FAST_WRAP_PARAM1) {
1793   IgnoreSyncAndMopsBegin(tid);
1794   PUSH_AFTER_CALLBACK1(After_malloc, arg0);
1795 }
1796 
After_free(FAST_WRAP_PARAM_AFTER)1797 void After_free(FAST_WRAP_PARAM_AFTER) {
1798   if (DEBUG_FAST_INTERCEPTORS)
1799     Printf("T%d %s %p\n", tid, __FUNCTION__, frame.arg[0]);
1800   IgnoreSyncAndMopsEnd(tid);
1801 }
1802 
Before_free(FAST_WRAP_PARAM1)1803 void Before_free(FAST_WRAP_PARAM1) {
1804   PinThread &t = g_pin_threads[tid];
1805   TLEBFlushLocked(t);
1806   DumpEvent(0, FREE, tid, pc, arg0, 0);
1807   IgnoreSyncAndMopsBegin(tid);
1808   PUSH_AFTER_CALLBACK1(After_free, arg0);
1809 }
1810 
Before_calloc(FAST_WRAP_PARAM2)1811 void Before_calloc(FAST_WRAP_PARAM2) {
1812   IgnoreSyncAndMopsBegin(tid);
1813   PUSH_AFTER_CALLBACK1(After_malloc, arg0 * arg1);
1814 }
1815 
Before_realloc(FAST_WRAP_PARAM2)1816 void Before_realloc(FAST_WRAP_PARAM2) {
1817   PinThread &t = g_pin_threads[tid];
1818   TLEBFlushLocked(t);
1819   IgnoreSyncAndMopsBegin(tid);
1820   // TODO: handle FREE? We don't do it in Valgrind right now.
1821   PUSH_AFTER_CALLBACK1(After_malloc, arg1);
1822 }
1823 
1824 // Fast path for INS_InsertIfCall.
Before_RET_IF(THREADID tid,ADDRINT pc,ADDRINT sp,ADDRINT ret)1825 ADDRINT Before_RET_IF(THREADID tid, ADDRINT pc, ADDRINT sp, ADDRINT ret) {
1826   PinThread &t = g_pin_threads[tid];
1827   return t.ic_stack.size();
1828 }
1829 
Before_RET_THEN(THREADID tid,ADDRINT pc,ADDRINT sp,ADDRINT ret)1830 void Before_RET_THEN(THREADID tid, ADDRINT pc, ADDRINT sp, ADDRINT ret) {
1831   PinThread &t = g_pin_threads[tid];
1832   if (t.ic_stack.size() == 0) return;
1833   DCHECK(t.ic_stack.size());
1834   InstrumentedCallFrame *frame = t.ic_stack.Top();
1835   if (DEBUG_FAST_INTERCEPTORS) {
1836     Printf("T%d RET  pc=%p sp=%p *sp=%p frame.sp=%p stack_size %ld\n",
1837            tid, pc, sp, *(uintptr_t*)sp, frame->sp, t.ic_stack.size());
1838     t.ic_stack.Print();
1839   }
1840   while (frame->sp <= sp) {
1841     if (DEBUG_FAST_INTERCEPTORS)
1842       Printf("pop\n");
1843     frame->callback(tid, *frame, ret);
1844     t.ic_stack.Pop();
1845     if (t.ic_stack.size()) {
1846       frame = t.ic_stack.Top();
1847     } else {
1848       break;
1849     }
1850   }
1851 }
1852 
1853 // These are no longer used in favor of "fast" wrappers (e.g. Before_malloc)
1854 // TODO(timurrrr): Check on the buildbot and remove.
WRAP_NAME(malloc)1855 uintptr_t WRAP_NAME(malloc)(WRAP_PARAM4) { CHECK(0); }
WRAP_NAME(realloc)1856 uintptr_t WRAP_NAME(realloc)(WRAP_PARAM4) { CHECK(0); }
WRAP_NAME(calloc)1857 uintptr_t WRAP_NAME(calloc)(WRAP_PARAM4) { CHECK(0); }
WRAP_NAME(free)1858 uintptr_t WRAP_NAME(free)(WRAP_PARAM4) { CHECK(0); }
1859 
1860 
1861 //-------- Routines and stack ---------------------- {{{2
UpdateCallStack(PinThread & t,ADDRINT sp)1862 static INLINE void UpdateCallStack(PinThread &t, ADDRINT sp) {
1863   while (t.shadow_stack.size() > 0 && sp >= t.shadow_stack.back().sp) {
1864     TLEBAddRtnExit(t);
1865     size_t size = t.shadow_stack.size();
1866     CHECK(size < 1000000);  // stay sane.
1867     uintptr_t popped_pc = t.shadow_stack.back().pc;
1868 #ifdef _MSC_VER
1869     // h-b edge from here to UnregisterWaitEx.
1870     CHECK(g_windows_thread_pool_calback_set);
1871     if (g_windows_thread_pool_calback_set->count(popped_pc)) {
1872       DumpEvent(0, SIGNAL, t.tid, 0, popped_pc, 0);
1873       // Printf("T%d ret %p\n", t.tid, popped_pc);
1874     }
1875 #endif
1876 
1877     if (debug_rtn) {
1878       ShowPcAndSp("RET : ", t.tid, popped_pc, sp);
1879     }
1880     t.shadow_stack.pop_back();
1881     CHECK(size - 1 == t.shadow_stack.size());
1882     if (DEB_PR) {
1883       Printf("POP SHADOW STACK\n");
1884       PrintShadowStack(t);
1885     }
1886   }
1887 }
1888 
InsertBeforeEvent_SysCall(THREADID tid,ADDRINT sp)1889 void InsertBeforeEvent_SysCall(THREADID tid, ADDRINT sp) {
1890   PinThread &t = g_pin_threads[tid];
1891   UpdateCallStack(t, sp);
1892   TLEBFlushLocked(t);
1893 }
1894 
InsertBeforeEvent_Call(THREADID tid,ADDRINT pc,ADDRINT target,ADDRINT sp,IGNORE_BELOW_RTN ignore_below)1895 void InsertBeforeEvent_Call(THREADID tid, ADDRINT pc, ADDRINT target,
1896                             ADDRINT sp, IGNORE_BELOW_RTN ignore_below) {
1897   PinThread &t = g_pin_threads[tid];
1898   DebugOnlyShowPcAndSp(__FUNCTION__, t.tid, pc, sp);
1899   UpdateCallStack(t, sp);
1900   TLEBAddRtnCall(t, pc, target, ignore_below);
1901   t.shadow_stack.push_back(StackFrame(target, sp));
1902   if (DEB_PR) {
1903     PrintShadowStack(t);
1904   }
1905   if (DEBUG_MODE && debug_rtn) {
1906     ShowPcAndSp("CALL: ", t.tid, target, sp);
1907   }
1908 
1909 #ifdef _MSC_VER
1910   // h-b edge from RtlQueueWorkItem to here.
1911   CHECK(g_windows_thread_pool_calback_set);
1912   if (g_windows_thread_pool_calback_set->count(target)) {
1913     DumpEvent(0, WAIT, tid, pc, target, 0);
1914   }
1915 #endif
1916 }
1917 
OnTraceSerial(THREADID tid,ADDRINT sp,TraceInfo * trace_info,uintptr_t ** tls_reg_p)1918 static void OnTraceSerial(THREADID tid, ADDRINT sp, TraceInfo *trace_info,
1919     uintptr_t **tls_reg_p) {
1920   PinThread &t = g_pin_threads[tid];
1921 
1922   DCHECK(trace_info);
1923   DCHECK(trace_info->n_mops() > 0);
1924   DebugOnlyShowPcAndSp(__FUNCTION__, t.tid, trace_info->pc(), sp);
1925 
1926   UpdateCallStack(t, sp);
1927 
1928   t.trace_info = trace_info;
1929   trace_info->counter()++;
1930   *tls_reg_p = TLEBAddTrace(t);
1931 }
1932 
OnTraceParallel(uintptr_t * tls_reg,ADDRINT sp,TraceInfo * trace_info)1933 static void OnTraceParallel(uintptr_t *tls_reg, ADDRINT sp, TraceInfo *trace_info) {
1934   // Get the thread handler directly from tls_reg.
1935   PinThread &t = *(PinThread*)(tls_reg - 4);
1936   t.trace_info = trace_info;
1937   if (t.ignore_accesses) return;
1938 
1939   DCHECK(trace_info);
1940   DCHECK(trace_info->n_mops() > 0);
1941   DebugOnlyShowPcAndSp(__FUNCTION__, t.tid, trace_info->pc(), sp);
1942 
1943   UpdateCallStack(t, sp);
1944 
1945 
1946   if (DEBUG_MODE && G_flags->show_stats)  // this stat may be racey; avoid ping-pong.
1947     trace_info->counter()++;
1948   TLEBAddTrace(t);
1949 }
1950 
1951 /* Verify all mop accesses in the last trace of the given thread by registering
1952    them with RaceVerifier and sleeping a bit. */
OnTraceVerifyInternal(PinThread & t,uintptr_t ** tls_reg_p)1953 static void OnTraceVerifyInternal(PinThread &t, uintptr_t **tls_reg_p) {
1954   DCHECK(g_race_verifier_active);
1955   if (t.trace_info) {
1956     int need_sleep = 0;
1957     for (unsigned i = 0; i < t.trace_info->n_mops(); ++i) {
1958       uintptr_t addr = (*tls_reg_p)[i];
1959       if (addr) {
1960         MopInfo *mop = t.trace_info->GetMop(i);
1961         need_sleep += RaceVerifierStartAccess(t.uniq_tid, addr, mop->pc(),
1962             mop->is_write());
1963       }
1964     }
1965 
1966     if (!need_sleep)
1967       return;
1968 
1969     usleep(G_flags->race_verifier_sleep_ms * 1000);
1970 
1971     for (unsigned i = 0; i < t.trace_info->n_mops(); ++i) {
1972       uintptr_t addr = (*tls_reg_p)[i];
1973       if (addr) {
1974         MopInfo *mop = t.trace_info->GetMop(i);
1975         RaceVerifierEndAccess(t.uniq_tid, addr, mop->pc(), mop->is_write());
1976       }
1977     }
1978   }
1979 }
1980 
OnTraceNoMopsVerify(THREADID tid,ADDRINT sp,uintptr_t ** tls_reg_p)1981 static void OnTraceNoMopsVerify(THREADID tid, ADDRINT sp,
1982     uintptr_t **tls_reg_p) {
1983   PinThread &t = g_pin_threads[tid];
1984   DCHECK(g_race_verifier_active);
1985   OnTraceVerifyInternal(t, tls_reg_p);
1986   t.trace_info = NULL;
1987 }
1988 
OnTraceVerify(THREADID tid,ADDRINT sp,TraceInfo * trace_info,uintptr_t ** tls_reg_p)1989 static void OnTraceVerify(THREADID tid, ADDRINT sp, TraceInfo *trace_info,
1990     uintptr_t **tls_reg_p) {
1991   DCHECK(g_race_verifier_active);
1992   PinThread &t = g_pin_threads[tid];
1993   OnTraceVerifyInternal(t, tls_reg_p);
1994 
1995   DCHECK(trace_info->n_mops() > 0);
1996 
1997   t.trace_info = trace_info;
1998   trace_info->counter()++;
1999   *tls_reg_p = TLEBAddTrace(t);
2000 }
2001 
2002 
2003 //---------- Memory accesses -------------------------- {{{2
2004 // 'addr' is the section of t.tleb.events which is set in OnTrace.
2005 // 'idx' is the number of this mop in its trace.
2006 // 'a' is the actuall address.
2007 // 'tid' is thread ID, used only in debug mode.
2008 //
2009 // In opt mode this is just one instruction! Something like this:
2010 // mov %rcx,(%rdi,%rdx,8)
OnMop(uintptr_t * addr,THREADID tid,ADDRINT idx,ADDRINT a)2011 static void OnMop(uintptr_t *addr, THREADID tid, ADDRINT idx, ADDRINT a) {
2012   if (DEBUG_MODE) {
2013     PinThread &t= g_pin_threads[tid];
2014     CHECK(idx < kMaxMopsPerTrace);
2015     CHECK(idx < t.trace_info->n_mops());
2016     uintptr_t *ptr = addr + idx;
2017     CHECK(ptr >= t.tleb.events);
2018     CHECK(ptr < t.tleb.events + kThreadLocalEventBufferSize);
2019     if (a == G_flags->trace_addr) {
2020       Printf("T%d %s %lx\n", t.tid, __FUNCTION__, a);
2021     }
2022   }
2023   addr[idx] = a;
2024 }
2025 
On_PredicatedMop(BOOL is_running,uintptr_t * addr,THREADID tid,ADDRINT idx,ADDRINT a)2026 static void On_PredicatedMop(BOOL is_running, uintptr_t *addr,
2027                              THREADID tid, ADDRINT idx, ADDRINT a) {
2028   if (is_running) {
2029     OnMop(addr, tid, idx, a);
2030   }
2031 }
2032 
OnMopCheckIdentStoreBefore(uintptr_t * addr,THREADID tid,ADDRINT idx,ADDRINT a)2033 static void OnMopCheckIdentStoreBefore(uintptr_t *addr, THREADID tid, ADDRINT idx, ADDRINT a) {
2034   // Write the value of *a to tleb.
2035   addr[idx] = *(uintptr_t*)a;
2036 }
OnMopCheckIdentStoreAfter(uintptr_t * addr,THREADID tid,ADDRINT idx,ADDRINT a)2037 static void OnMopCheckIdentStoreAfter(uintptr_t *addr, THREADID tid, ADDRINT idx, ADDRINT a) {
2038   // Check if the previous value of *a is equal to the new one.
2039   // If not, we have a regular memory access. If yes, we have an ident operation,
2040   // which we want to ignore.
2041   uintptr_t previous_value_of_a = addr[idx];
2042   uintptr_t new_value_of_a = *(uintptr_t*)a;
2043   // 111...111 if the values are different, 0 otherwise.
2044   uintptr_t ne_mask = -(uintptr_t)(new_value_of_a != previous_value_of_a);
2045   addr[idx] = ne_mask & a;
2046 }
2047 
2048 //---------- I/O; exit------------------------------- {{{2
2049 static const uintptr_t kIOMagic = 0x1234c678;
2050 
Before_SignallingIOCall(THREADID tid,ADDRINT pc)2051 static void Before_SignallingIOCall(THREADID tid, ADDRINT pc) {
2052   DumpEvent(0, SIGNAL, tid, pc, kIOMagic, 0);
2053 }
2054 
After_WaitingIOCall(THREADID tid,ADDRINT pc)2055 static void After_WaitingIOCall(THREADID tid, ADDRINT pc) {
2056   DumpEvent(0, WAIT, tid, pc, kIOMagic, 0);
2057 }
2058 
2059 static const uintptr_t kAtexitMagic = 0x9876f432;
2060 
On_atexit(THREADID tid,ADDRINT pc)2061 static void On_atexit(THREADID tid, ADDRINT pc) {
2062   DumpEvent(0, SIGNAL, tid, pc, kAtexitMagic, 0);
2063 }
2064 
On_exit(THREADID tid,ADDRINT pc)2065 static void On_exit(THREADID tid, ADDRINT pc) {
2066   DumpEvent(0, WAIT, tid, pc, kAtexitMagic, 0);
2067 }
2068 
2069 //---------- Synchronization -------------------------- {{{2
2070 // locks
Before_pthread_unlock(THREADID tid,ADDRINT pc,ADDRINT mu)2071 static void Before_pthread_unlock(THREADID tid, ADDRINT pc, ADDRINT mu) {
2072   DumpEvent(0, UNLOCK, tid, pc, mu, 0);
2073 }
2074 
After_pthread_mutex_lock(FAST_WRAP_PARAM_AFTER)2075 static void After_pthread_mutex_lock(FAST_WRAP_PARAM_AFTER) {
2076   DumpEventWithSp(frame.sp, WRITER_LOCK, tid, frame.pc, frame.arg[0], 0);
2077 }
2078 
Before_pthread_mutex_lock(FAST_WRAP_PARAM1)2079 static void Before_pthread_mutex_lock(FAST_WRAP_PARAM1) {
2080   PUSH_AFTER_CALLBACK1(After_pthread_mutex_lock, arg0);
2081 }
2082 
2083 // In some versions of libpthread, pthread_spin_lock is effectively
2084 // a recursive function. It jumps to its first insn:
2085 //    beb0:       f0 ff 0f                lock decl (%rdi)
2086 //    beb3:       75 0b                   jne    bec0 <pthread_spin_lock+0x10>
2087 //    beb5:       31 c0                   xor    %eax,%eax
2088 //    beb7:       c3                      retq
2089 //    beb8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
2090 //    bebf:       00
2091 //    bec0:       f3 90                   pause
2092 //    bec2:       83 3f 00                cmpl   $0x0,(%rdi)
2093 //    bec5:       7f e9  >>>>>>>>>>>>>    jg     beb0 <pthread_spin_lock>
2094 //    bec7:       eb f7                   jmp    bec0 <pthread_spin_lock+0x10>
2095 //
2096 // So, we need to act only when we return from the last (depth=0) invocation.
WRAP_NAME(pthread_spin_lock)2097 static uintptr_t WRAP_NAME(pthread_spin_lock)(WRAP_PARAM4) {
2098   PinThread &t= g_pin_threads[tid];
2099   t.spin_lock_recursion_depth++;
2100   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2101   t.spin_lock_recursion_depth--;
2102   if (t.spin_lock_recursion_depth == 0) {
2103     DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
2104   }
2105   return ret;
2106 }
2107 
WRAP_NAME(pthread_rwlock_wrlock)2108 static uintptr_t WRAP_NAME(pthread_rwlock_wrlock)(WRAP_PARAM4) {
2109   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2110   DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
2111   return ret;
2112 }
2113 
WRAP_NAME(pthread_rwlock_rdlock)2114 static uintptr_t WRAP_NAME(pthread_rwlock_rdlock)(WRAP_PARAM4) {
2115   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2116   DumpEvent(ctx, READER_LOCK, tid, pc, arg0, 0);
2117   return ret;
2118 }
2119 
WRAP_NAME(pthread_mutex_trylock)2120 static uintptr_t WRAP_NAME(pthread_mutex_trylock)(WRAP_PARAM4) {
2121   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2122   if (ret == 0)
2123     DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
2124   return ret;
2125 }
2126 
WRAP_NAME(pthread_spin_trylock)2127 static uintptr_t WRAP_NAME(pthread_spin_trylock)(WRAP_PARAM4) {
2128   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2129   if (ret == 0)
2130     DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
2131   return ret;
2132 }
2133 
WRAP_NAME(pthread_spin_init)2134 static uintptr_t WRAP_NAME(pthread_spin_init)(WRAP_PARAM4) {
2135   DumpEvent(ctx, UNLOCK_OR_INIT, tid, pc, arg0, 0);
2136   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2137   return ret;
2138 }
WRAP_NAME(pthread_spin_destroy)2139 static uintptr_t WRAP_NAME(pthread_spin_destroy)(WRAP_PARAM4) {
2140   DumpEvent(ctx, LOCK_DESTROY, tid, pc, arg0, 0);
2141   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2142   return ret;
2143 }
WRAP_NAME(pthread_spin_unlock)2144 static uintptr_t WRAP_NAME(pthread_spin_unlock)(WRAP_PARAM4) {
2145   DumpEvent(ctx, UNLOCK_OR_INIT, tid, pc, arg0, 0);
2146   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2147   return ret;
2148 }
2149 
WRAP_NAME(pthread_rwlock_trywrlock)2150 static uintptr_t WRAP_NAME(pthread_rwlock_trywrlock)(WRAP_PARAM4) {
2151   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2152   if (ret == 0)
2153     DumpEvent(ctx, WRITER_LOCK, tid, pc, arg0, 0);
2154   return ret;
2155 }
2156 
WRAP_NAME(pthread_rwlock_tryrdlock)2157 static uintptr_t WRAP_NAME(pthread_rwlock_tryrdlock)(WRAP_PARAM4) {
2158   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2159   if (ret == 0)
2160     DumpEvent(ctx, READER_LOCK, tid, pc, arg0, 0);
2161   return ret;
2162 }
2163 
2164 
Before_pthread_mutex_init(THREADID tid,ADDRINT pc,ADDRINT mu)2165 static void Before_pthread_mutex_init(THREADID tid, ADDRINT pc, ADDRINT mu) {
2166   DumpEvent(0, LOCK_CREATE, tid, pc, mu, 0);
2167 }
Before_pthread_rwlock_init(THREADID tid,ADDRINT pc,ADDRINT mu)2168 static void Before_pthread_rwlock_init(THREADID tid, ADDRINT pc, ADDRINT mu) {
2169   DumpEvent(0, LOCK_CREATE, tid, pc, mu, 0);
2170 }
2171 
Before_pthread_mutex_destroy(THREADID tid,ADDRINT pc,ADDRINT mu)2172 static void Before_pthread_mutex_destroy(THREADID tid, ADDRINT pc, ADDRINT mu) {
2173   DumpEvent(0, LOCK_DESTROY, tid, pc, mu, 0);
2174 }
Before_pthread_rwlock_destroy(THREADID tid,ADDRINT pc,ADDRINT mu)2175 static void Before_pthread_rwlock_destroy(THREADID tid, ADDRINT pc, ADDRINT mu) {
2176   DumpEvent(0, LOCK_DESTROY, tid, pc, mu, 0);
2177 }
2178 
2179 // barrier
WRAP_NAME(pthread_barrier_init)2180 static uintptr_t WRAP_NAME(pthread_barrier_init)(WRAP_PARAM4) {
2181   DumpEvent(ctx, CYCLIC_BARRIER_INIT, tid, pc, arg0, arg2);
2182   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2183   return ret;
2184 }
WRAP_NAME(pthread_barrier_wait)2185 static uintptr_t WRAP_NAME(pthread_barrier_wait)(WRAP_PARAM4) {
2186   DumpEvent(ctx, CYCLIC_BARRIER_WAIT_BEFORE, tid, pc, arg0, 0);
2187   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2188   DumpEvent(ctx, CYCLIC_BARRIER_WAIT_AFTER, tid, pc, arg0, 0);
2189   return ret;
2190 }
2191 
2192 
2193 // condvar
Before_pthread_cond_signal(THREADID tid,ADDRINT pc,ADDRINT cv)2194 static void Before_pthread_cond_signal(THREADID tid, ADDRINT pc, ADDRINT cv) {
2195   DumpEvent(0, SIGNAL, tid, pc, cv, 0);
2196 }
2197 
WRAP_NAME(pthread_cond_wait)2198 static uintptr_t WRAP_NAME(pthread_cond_wait)(WRAP_PARAM4) {
2199   DumpEvent(ctx, UNLOCK, tid, pc, arg1, 0);
2200   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2201   DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
2202   DumpEvent(ctx, WRITER_LOCK, tid, pc, arg1, 0);
2203   return ret;
2204 }
WRAP_NAME(pthread_cond_timedwait)2205 static uintptr_t WRAP_NAME(pthread_cond_timedwait)(WRAP_PARAM4) {
2206   DumpEvent(ctx, UNLOCK, tid, pc, arg1, 0);
2207   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2208   if (ret == 0) {
2209     DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
2210   }
2211   DumpEvent(ctx, WRITER_LOCK, tid, pc, arg1, 0);
2212   return ret;
2213 }
2214 
2215 // epoll
2216 static const uintptr_t kSocketMagic = 0xDEADFBAD;
2217 
Before_epoll_ctl(THREADID tid,ADDRINT pc)2218 static void Before_epoll_ctl(THREADID tid, ADDRINT pc) {
2219   DumpEvent(0, SIGNAL, tid, pc, kSocketMagic, 0);
2220 }
2221 
After_epoll_wait(THREADID tid,ADDRINT pc)2222 static void After_epoll_wait(THREADID tid, ADDRINT pc) {
2223   DumpEvent(0, WAIT, tid, pc, kSocketMagic, 0);
2224 }
2225 
2226 // sem
After_sem_open(THREADID tid,ADDRINT pc,ADDRINT ret)2227 static void After_sem_open(THREADID tid, ADDRINT pc, ADDRINT ret) {
2228   // TODO(kcc): need to handle it more precise?
2229   DumpEvent(0, SIGNAL, tid, pc, ret, 0);
2230 }
Before_sem_post(THREADID tid,ADDRINT pc,ADDRINT sem)2231 static void Before_sem_post(THREADID tid, ADDRINT pc, ADDRINT sem) {
2232   DumpEvent(0, SIGNAL, tid, pc, sem, 0);
2233 }
2234 
WRAP_NAME(sem_wait)2235 static uintptr_t WRAP_NAME(sem_wait)(WRAP_PARAM4) {
2236   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2237   DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
2238   return ret;
2239 }
WRAP_NAME(sem_trywait)2240 static uintptr_t WRAP_NAME(sem_trywait)(WRAP_PARAM4) {
2241   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2242   if (ret == 0) {
2243     DumpEvent(ctx, WAIT, tid, pc, arg0, 0);
2244   }
2245   return ret;
2246 }
2247 
2248 // etc
2249 #if defined(__GNUC__)
WRAP_NAME(lockf)2250 uintptr_t WRAP_NAME(lockf)(WRAP_PARAM4) {
2251   if (arg1 == F_ULOCK) {
2252     DumpEvent(0, SIGNAL, tid, pc, kSocketMagic, 0);
2253   }
2254 
2255   uintptr_t ret = CALL_ME_INSIDE_WRAPPER_4();
2256 
2257   if (arg1 == F_LOCK && ret == 0) {
2258     DumpEvent(0, WAIT, tid, pc, kSocketMagic, 0);
2259   }
2260 
2261   return ret;
2262 }
2263 #endif
2264 
2265 //--------- Annotations -------------------------- {{{2
On_AnnotateBenignRace(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a,ADDRINT descr)2266 static void On_AnnotateBenignRace(THREADID tid, ADDRINT pc,
2267                                   ADDRINT file, ADDRINT line,
2268                                   ADDRINT a, ADDRINT descr) {
2269   DumpEvent(0, BENIGN_RACE, tid, descr, a, 1);
2270 }
2271 
On_AnnotateBenignRaceSized(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a,ADDRINT size,ADDRINT descr)2272 static void On_AnnotateBenignRaceSized(THREADID tid, ADDRINT pc,
2273                                        ADDRINT file, ADDRINT line,
2274                                        ADDRINT a, ADDRINT size, ADDRINT descr) {
2275   DumpEvent(0, BENIGN_RACE, tid, descr, a, size);
2276 }
2277 
On_AnnotateExpectRace(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a,ADDRINT descr)2278 static void On_AnnotateExpectRace(THREADID tid, ADDRINT pc,
2279                                   ADDRINT file, ADDRINT line,
2280                                   ADDRINT a, ADDRINT descr) {
2281   DumpEvent(0, EXPECT_RACE, tid, descr, a, 0);
2282 }
2283 
On_AnnotateFlushExpectedRaces(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line)2284 static void On_AnnotateFlushExpectedRaces(THREADID tid, ADDRINT pc,
2285                                   ADDRINT file, ADDRINT line) {
2286   DumpEvent(0, FLUSH_EXPECTED_RACES, 0, 0, 0, 0);
2287 }
2288 
2289 
On_AnnotateTraceMemory(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a)2290 static void On_AnnotateTraceMemory(THREADID tid, ADDRINT pc,
2291                                    ADDRINT file, ADDRINT line,
2292                                    ADDRINT a) {
2293   DumpEvent(0, TRACE_MEM, tid, pc, a, 0);
2294 }
2295 
On_AnnotateNewMemory(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a,ADDRINT size)2296 static void On_AnnotateNewMemory(THREADID tid, ADDRINT pc,
2297                                    ADDRINT file, ADDRINT line,
2298                                    ADDRINT a, ADDRINT size) {
2299   DumpEvent(0, MALLOC, tid, pc, a, size);
2300 }
2301 
On_AnnotateNoOp(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a)2302 static void On_AnnotateNoOp(THREADID tid, ADDRINT pc,
2303                             ADDRINT file, ADDRINT line, ADDRINT a) {
2304   Printf("%s T%d: %s:%d %p\n", __FUNCTION__, tid, (char*)file, (int)line, a);
2305   //DumpEvent(0, STACK_TRACE, tid, pc, 0, 0);
2306 //  PrintShadowStack(tid);
2307 }
2308 
On_AnnotateFlushState(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line)2309 static void On_AnnotateFlushState(THREADID tid, ADDRINT pc,
2310                                   ADDRINT file, ADDRINT line) {
2311   DumpEvent(0, FLUSH_STATE, tid, pc, 0, 0);
2312 }
2313 
On_AnnotateCondVarSignal(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT obj)2314 static void On_AnnotateCondVarSignal(THREADID tid, ADDRINT pc,
2315                                      ADDRINT file, ADDRINT line, ADDRINT obj) {
2316   DumpEvent(0, SIGNAL, tid, pc, obj, 0);
2317 }
2318 
On_AnnotateCondVarWait(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT obj)2319 static void On_AnnotateCondVarWait(THREADID tid, ADDRINT pc,
2320                                    ADDRINT file, ADDRINT line, ADDRINT obj) {
2321   DumpEvent(0, WAIT, tid, pc, obj, 0);
2322 }
2323 
On_AnnotateHappensBefore(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT obj)2324 static void On_AnnotateHappensBefore(THREADID tid, ADDRINT pc,
2325                                      ADDRINT file, ADDRINT line, ADDRINT obj) {
2326   DumpEvent(0, SIGNAL, tid, pc, obj, 0);
2327 }
2328 
On_AnnotateHappensAfter(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT obj)2329 static void On_AnnotateHappensAfter(THREADID tid, ADDRINT pc,
2330                                     ADDRINT file, ADDRINT line, ADDRINT obj) {
2331   DumpEvent(0, WAIT, tid, pc, obj, 0);
2332 }
2333 
On_AnnotateEnableRaceDetection(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT enable)2334 static void On_AnnotateEnableRaceDetection(THREADID tid, ADDRINT pc,
2335                                         ADDRINT file, ADDRINT line,
2336                                         ADDRINT enable) {
2337   if (!g_race_verifier_active)
2338     TLEBSimpleEvent(g_pin_threads[tid],
2339         enable ? TLEB_GLOBAL_IGNORE_OFF : TLEB_GLOBAL_IGNORE_ON);
2340 }
2341 
On_AnnotateIgnoreReadsBegin(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line)2342 static void On_AnnotateIgnoreReadsBegin(THREADID tid, ADDRINT pc,
2343                                         ADDRINT file, ADDRINT line) {
2344   DumpEvent(0, IGNORE_READS_BEG, tid, pc, 0, 0);
2345 }
On_AnnotateIgnoreReadsEnd(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line)2346 static void On_AnnotateIgnoreReadsEnd(THREADID tid, ADDRINT pc,
2347                                       ADDRINT file, ADDRINT line) {
2348   DumpEvent(0, IGNORE_READS_END, tid, pc, 0, 0);
2349 }
On_AnnotateIgnoreWritesBegin(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line)2350 static void On_AnnotateIgnoreWritesBegin(THREADID tid, ADDRINT pc,
2351                                          ADDRINT file, ADDRINT line) {
2352   DumpEvent(0, IGNORE_WRITES_BEG, tid, pc, 0, 0);
2353 }
On_AnnotateIgnoreWritesEnd(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line)2354 static void On_AnnotateIgnoreWritesEnd(THREADID tid, ADDRINT pc,
2355                                        ADDRINT file, ADDRINT line) {
2356   DumpEvent(0, IGNORE_WRITES_END, tid, pc, 0, 0);
2357 }
On_AnnotateThreadName(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT name)2358 static void On_AnnotateThreadName(THREADID tid, ADDRINT pc,
2359                                   ADDRINT file, ADDRINT line,
2360                                   ADDRINT name) {
2361   DumpEvent(0, SET_THREAD_NAME, tid, pc, name, 0);
2362 }
On_AnnotatePublishMemoryRange(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a,ADDRINT size)2363 static void On_AnnotatePublishMemoryRange(THREADID tid, ADDRINT pc,
2364                                           ADDRINT file, ADDRINT line,
2365                                           ADDRINT a, ADDRINT size) {
2366   DumpEvent(0, PUBLISH_RANGE, tid, pc, a, size);
2367 }
2368 
On_AnnotateUnpublishMemoryRange(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT a,ADDRINT size)2369 static void On_AnnotateUnpublishMemoryRange(THREADID tid, ADDRINT pc,
2370                                           ADDRINT file, ADDRINT line,
2371                                           ADDRINT a, ADDRINT size) {
2372 //  Printf("T%d %s %lx %lx\n", tid, __FUNCTION__, a, size);
2373   DumpEvent(0, UNPUBLISH_RANGE, tid, pc, a, size);
2374 }
2375 
2376 
On_AnnotateMutexIsUsedAsCondVar(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT mu)2377 static void On_AnnotateMutexIsUsedAsCondVar(THREADID tid, ADDRINT pc,
2378                                             ADDRINT file, ADDRINT line,
2379                                             ADDRINT mu) {
2380   DumpEvent(0, HB_LOCK, tid, pc, mu, 0);
2381 }
2382 
On_AnnotateMutexIsNotPhb(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT mu)2383 static void On_AnnotateMutexIsNotPhb(THREADID tid, ADDRINT pc,
2384                                      ADDRINT file, ADDRINT line,
2385                                      ADDRINT mu) {
2386   DumpEvent(0, NON_HB_LOCK, tid, pc, mu, 0);
2387 }
2388 
On_AnnotatePCQCreate(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT pcq)2389 static void On_AnnotatePCQCreate(THREADID tid, ADDRINT pc,
2390                                  ADDRINT file, ADDRINT line,
2391                                  ADDRINT pcq) {
2392   DumpEvent(0, PCQ_CREATE, tid, pc, pcq, 0);
2393 }
2394 
On_AnnotatePCQDestroy(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT pcq)2395 static void On_AnnotatePCQDestroy(THREADID tid, ADDRINT pc,
2396                                   ADDRINT file, ADDRINT line,
2397                                   ADDRINT pcq) {
2398   DumpEvent(0, PCQ_DESTROY, tid, pc, pcq, 0);
2399 }
2400 
On_AnnotatePCQPut(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT pcq)2401 static void On_AnnotatePCQPut(THREADID tid, ADDRINT pc,
2402                               ADDRINT file, ADDRINT line,
2403                               ADDRINT pcq) {
2404   DumpEvent(0, PCQ_PUT, tid, pc, pcq, 0);
2405 }
2406 
On_AnnotatePCQGet(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT pcq)2407 static void On_AnnotatePCQGet(THREADID tid, ADDRINT pc,
2408                               ADDRINT file, ADDRINT line,
2409                               ADDRINT pcq) {
2410   DumpEvent(0, PCQ_GET, tid, pc, pcq, 0);
2411 }
2412 
On_AnnotateRWLockCreate(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT lock)2413 static void On_AnnotateRWLockCreate(THREADID tid, ADDRINT pc,
2414                                     ADDRINT file, ADDRINT line,
2415                                     ADDRINT lock) {
2416   DumpEvent(0, LOCK_CREATE, tid, pc, lock, 0);
2417 }
2418 
On_AnnotateRWLockDestroy(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT lock)2419 static void On_AnnotateRWLockDestroy(THREADID tid, ADDRINT pc,
2420                                     ADDRINT file, ADDRINT line,
2421                                     ADDRINT lock) {
2422   DumpEvent(0, LOCK_DESTROY, tid, pc, lock, 0);
2423 }
2424 
On_AnnotateRWLockAcquired(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT lock,ADDRINT is_w)2425 static void On_AnnotateRWLockAcquired(THREADID tid, ADDRINT pc,
2426                                      ADDRINT file, ADDRINT line,
2427                                      ADDRINT lock, ADDRINT is_w) {
2428   DumpEvent(0, is_w ? WRITER_LOCK : READER_LOCK, tid, pc, lock, 0);
2429 }
2430 
On_AnnotateRWLockReleased(THREADID tid,ADDRINT pc,ADDRINT file,ADDRINT line,ADDRINT lock,ADDRINT is_w)2431 static void On_AnnotateRWLockReleased(THREADID tid, ADDRINT pc,
2432                                      ADDRINT file, ADDRINT line,
2433                                      ADDRINT lock, ADDRINT is_w) {
2434   DumpEvent(0, UNLOCK, tid, pc, lock, 0);
2435 }
2436 
2437 
WRAP_NAME(RunningOnValgrind)2438 int WRAP_NAME(RunningOnValgrind)(WRAP_PARAM4) {
2439   return 1;
2440 }
2441 
2442 //--------- Instrumentation ----------------------- {{{1
IgnoreImage(IMG img)2443 static bool IgnoreImage(IMG img) {
2444   string name = IMG_Name(img);
2445   if (name.find("/ld-") != string::npos)
2446     return true;
2447   return false;
2448 }
2449 
IgnoreRtn(RTN rtn)2450 static bool IgnoreRtn(RTN rtn) {
2451   CHECK(rtn != RTN_Invalid());
2452   ADDRINT rtn_address = RTN_Address(rtn);
2453   if (ThreadSanitizerWantToInstrumentSblock(rtn_address) == false)
2454     return true;
2455   return false;
2456 }
2457 
InstrumentCall(INS ins)2458 static bool InstrumentCall(INS ins) {
2459   // Call.
2460   if (INS_IsProcedureCall(ins) && !INS_IsSyscall(ins)) {
2461     IGNORE_BELOW_RTN ignore_below = IGNORE_BELOW_RTN_UNKNOWN;
2462     if (INS_IsDirectBranchOrCall(ins)) {
2463       ADDRINT target = INS_DirectBranchOrCallTargetAddress(ins);
2464       bool ignore = ThreadSanitizerIgnoreAccessesBelowFunction(target);
2465       ignore_below = ignore ? IGNORE_BELOW_RTN_YES : IGNORE_BELOW_RTN_NO;
2466     }
2467     INS_InsertCall(ins, IPOINT_BEFORE,
2468                    (AFUNPTR)InsertBeforeEvent_Call,
2469                    IARG_THREAD_ID,
2470                    IARG_INST_PTR,
2471                    IARG_BRANCH_TARGET_ADDR,
2472                    IARG_REG_VALUE, REG_STACK_PTR,
2473                    IARG_ADDRINT, ignore_below,
2474                    IARG_END);
2475     return true;
2476   }
2477   if (INS_IsSyscall(ins)) {
2478     INS_InsertCall(ins, IPOINT_BEFORE,
2479                    (AFUNPTR)InsertBeforeEvent_SysCall,
2480                    IARG_THREAD_ID,
2481                    IARG_REG_VALUE, REG_STACK_PTR,
2482                    IARG_END);
2483   }
2484   return false;
2485 }
2486 
2487 
2488 // return the number of inserted instrumentations.
InstrumentMopsInBBl(BBL bbl,RTN rtn,TraceInfo * trace_info,uintptr_t instrument_pc,size_t * mop_idx)2489 static void InstrumentMopsInBBl(BBL bbl, RTN rtn, TraceInfo *trace_info, uintptr_t instrument_pc, size_t *mop_idx) {
2490   // compute 'dtor_head', see
2491   // http://code.google.com/p/data-race-test/wiki/PopularDataRaces#Data_race_on_vptr
2492   // On x86_64 only the first BB of DTOR is treated as dtor_head.
2493   // On x86, we have to treat more BBs as dtor_head due to -fPIC.
2494   // See http://code.google.com/p/chromium/issues/detail?id=61199
2495   bool dtor_head = false;
2496 #ifdef TARGET_IA32
2497   size_t max_offset_for_dtor_head = 32;
2498 #else
2499   size_t max_offset_for_dtor_head = 0;
2500 #endif
2501 
2502   if (BBL_Address(bbl) - RTN_Address(rtn) <= max_offset_for_dtor_head) {
2503     string demangled_rtn_name = Demangle(RTN_Name(rtn).c_str());
2504     if (demangled_rtn_name.find("::~") != string::npos)
2505       dtor_head = true;
2506   }
2507 
2508   INS tail = BBL_InsTail(bbl);
2509   // All memory reads/writes
2510   for( INS ins = BBL_InsHead(bbl);
2511        INS_Valid(ins);
2512        ins = INS_Next(ins) ) {
2513     if (ins != tail) {
2514       CHECK(!INS_IsRet(ins));
2515       CHECK(!INS_IsProcedureCall(ins));
2516     }
2517     // bool is_stack = INS_IsStackRead(ins) || INS_IsStackWrite(ins);
2518     if (INS_IsAtomicUpdate(ins)) continue;
2519 
2520     int n_mops = INS_MemoryOperandCount(ins);
2521     if (n_mops == 0) continue;
2522 
2523     string opcode_str = OPCODE_StringShort(INS_Opcode(ins));
2524     if (trace_info && debug_ins) {
2525       Printf("  INS: opcode=%s n_mops=%d dis=\"%s\"\n",
2526              opcode_str.c_str(),  n_mops,
2527              INS_Disassemble(ins).c_str());
2528     }
2529 
2530     bool ins_ignore_writes = false;
2531     bool ins_ignore_reads = false;
2532 
2533     // CALL writes to stack and (if the call is indirect) reads the target
2534     // address. We don't want to handle the stack write.
2535     if (INS_IsCall(ins)) {
2536       CHECK(n_mops == 1 || n_mops == 2);
2537       ins_ignore_writes = true;
2538     }
2539 
2540     // PUSH: we ignore the write to stack but we don't ignore the read (if any).
2541     if (opcode_str == "PUSH") {
2542       CHECK(n_mops == 1 || n_mops == 2);
2543       ins_ignore_writes = true;
2544     }
2545 
2546     // POP: we are reading from stack, Ignore it.
2547     if (opcode_str == "POP") {
2548       CHECK(n_mops == 1 || n_mops == 2);
2549       ins_ignore_reads = true;
2550       continue;
2551     }
2552 
2553     // RET/LEAVE -- ignore it, it just reads the return address and stack.
2554     if (INS_IsRet(ins) || opcode_str == "LEAVE") {
2555       CHECK(n_mops == 1);
2556       continue;
2557     }
2558 
2559     bool is_predicated = INS_IsPredicated(ins);
2560     for (int i = 0; i < n_mops; i++) {
2561       if (*mop_idx >= kMaxMopsPerTrace) {
2562         Report("INFO: too many mops in trace: %d %s\n",
2563             INS_Address(ins), PcToRtnName(INS_Address(ins), true).c_str());
2564         return;
2565       }
2566       size_t size = INS_MemoryOperandSize(ins, i);
2567       CHECK(size);
2568       bool is_write = INS_MemoryOperandIsWritten(ins, i);
2569 
2570       if (ins_ignore_writes && is_write) continue;
2571       if (ins_ignore_reads && !is_write) continue;
2572       if (instrument_pc && instrument_pc != INS_Address(ins)) continue;
2573 
2574       bool check_ident_store = false;
2575       if (dtor_head && is_write && INS_IsMov(ins) && size == sizeof(void*)) {
2576         // This is a special case for '*addr = value', where we want to ignore the
2577         // access if *addr == value before the store.
2578         CHECK(!is_predicated);
2579         check_ident_store = true;
2580       }
2581 
2582       if (trace_info) {
2583         if (debug_ins) {
2584           Printf("    size=%ld is_w=%d\n", size, (int)is_write);
2585         }
2586         IPOINT point = IPOINT_BEFORE;
2587         AFUNPTR on_mop_callback = (AFUNPTR)OnMop;
2588         if (check_ident_store) {
2589           INS_InsertCall(ins, IPOINT_BEFORE,
2590             (AFUNPTR)OnMopCheckIdentStoreBefore,
2591             IARG_REG_VALUE, tls_reg,
2592             IARG_THREAD_ID,
2593             IARG_ADDRINT, *mop_idx,
2594             IARG_MEMORYOP_EA, i,
2595             IARG_END);
2596           // This is just a MOV, so we can insert the instrumentation code
2597           // after the insn.
2598           point = IPOINT_AFTER;
2599           on_mop_callback = (AFUNPTR)OnMopCheckIdentStoreAfter;
2600         }
2601 
2602         MopInfo *mop = trace_info->GetMop(*mop_idx);
2603         new (mop) MopInfo(INS_Address(ins), size, is_write, false);
2604         if (is_predicated) {
2605           INS_InsertPredicatedCall(ins, point,
2606               (AFUNPTR)On_PredicatedMop,
2607               IARG_EXECUTING,
2608               IARG_REG_VALUE, tls_reg,
2609               IARG_THREAD_ID,
2610               IARG_ADDRINT, *mop_idx,
2611               IARG_MEMORYOP_EA, i,
2612               IARG_END);
2613         } else {
2614           INS_InsertCall(ins, point,
2615               on_mop_callback,
2616               IARG_REG_VALUE, tls_reg,
2617               IARG_THREAD_ID,
2618               IARG_ADDRINT, *mop_idx,
2619               IARG_MEMORYOP_EA, i,
2620               IARG_END);
2621         }
2622       }
2623       (*mop_idx)++;
2624     }
2625   }
2626 }
2627 
CallbackForTRACE(TRACE trace,void * v)2628 void CallbackForTRACE(TRACE trace, void *v) {
2629   CHECK(n_started_threads > 0);
2630 
2631   RTN rtn = TRACE_Rtn(trace);
2632   bool ignore_memory = false;
2633   string img_name = "<>";
2634   string rtn_name = "<>";
2635   if (RTN_Valid(rtn)) {
2636     SEC sec = RTN_Sec(rtn);
2637     IMG img = SEC_Img(sec);
2638     rtn_name = RTN_Name(rtn);
2639     img_name = IMG_Name(img);
2640 
2641     if (IgnoreImage(img)) {
2642       // Printf("Ignoring memory accesses in %s\n", IMG_Name(img).c_str());
2643       ignore_memory = true;
2644     } else if (IgnoreRtn(rtn)) {
2645       ignore_memory = true;
2646     }
2647   }
2648 
2649   uintptr_t instrument_pc = 0;
2650   if (g_race_verifier_active) {
2651     // Check if this trace looks like part of a possible race report.
2652     uintptr_t min_pc = UINTPTR_MAX;
2653     uintptr_t max_pc = 0;
2654     for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
2655       min_pc = MIN(min_pc, INS_Address(BBL_InsHead(bbl)));
2656       max_pc = MAX(max_pc, INS_Address(BBL_InsTail(bbl)));
2657     }
2658 
2659     bool verify_trace = RaceVerifierGetAddresses(min_pc, max_pc, &instrument_pc);
2660     if (!verify_trace)
2661       ignore_memory = true;
2662   }
2663 
2664   size_t n_mops = 0;
2665   // count the mops.
2666   for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
2667     if (!ignore_memory) {
2668       InstrumentMopsInBBl(bbl, rtn, NULL, instrument_pc, &n_mops);
2669     }
2670     INS tail = BBL_InsTail(bbl);
2671     if (INS_IsRet(tail)) {
2672 #if 0
2673       INS_InsertIfCall(tail, IPOINT_BEFORE,
2674                        (AFUNPTR)Before_RET_IF,
2675                        IARG_THREAD_ID,
2676                        IARG_END);
2677 
2678       INS_InsertThenCall(
2679 #else
2680         INS_InsertCall(
2681 #endif
2682           tail, IPOINT_BEFORE,
2683           (AFUNPTR)Before_RET_THEN,
2684           IARG_THREAD_ID,
2685           IARG_INST_PTR,
2686           IARG_REG_VALUE, REG_STACK_PTR,
2687           IARG_FUNCRET_EXITPOINT_VALUE,
2688           IARG_END);
2689     }
2690   }
2691 
2692   // Handle the head of the trace
2693   INS head = BBL_InsHead(TRACE_BblHead(trace));
2694   CHECK(n_mops <= kMaxMopsPerTrace);
2695 
2696   TraceInfo *trace_info = NULL;
2697   if (n_mops) {
2698     trace_info = TraceInfo::NewTraceInfo(n_mops, INS_Address(head));
2699     if (TS_SERIALIZED == 0) {
2700       // TODO(kcc): implement race verifier here.
2701       INS_InsertCall(head, IPOINT_BEFORE,
2702                      (AFUNPTR)OnTraceParallel,
2703                      IARG_REG_VALUE, tls_reg,
2704                      IARG_REG_VALUE, REG_STACK_PTR,
2705                      IARG_PTR, trace_info,
2706                      IARG_END);
2707     } else {
2708       AFUNPTR handler = (AFUNPTR)(g_race_verifier_active ?
2709                                   OnTraceVerify : OnTraceSerial);
2710       INS_InsertCall(head, IPOINT_BEFORE,
2711                      handler,
2712                      IARG_THREAD_ID,
2713                      IARG_REG_VALUE, REG_STACK_PTR,
2714                      IARG_PTR, trace_info,
2715                      IARG_REG_REFERENCE, tls_reg,
2716                      IARG_END);
2717     }
2718   } else {
2719     if (g_race_verifier_active) {
2720       INS_InsertCall(head, IPOINT_BEFORE,
2721                      (AFUNPTR)OnTraceNoMopsVerify,
2722                      IARG_THREAD_ID,
2723                      IARG_REG_VALUE, REG_STACK_PTR,
2724                      IARG_REG_REFERENCE, tls_reg,
2725                      IARG_END);
2726     }
2727   }
2728 
2729   // instrument the mops. We want to do it after we instrumented the head
2730   // to maintain the right order of instrumentation callbacks (head first, then
2731   // mops).
2732   size_t i = 0;
2733   if (n_mops) {
2734     if (debug_ins) {
2735       Printf("TRACE %p (%p); n_mops=%ld %s\n", trace_info,
2736              TRACE_Address(trace),
2737              trace_info->n_mops(),
2738              PcToRtnName(trace_info->pc(), false).c_str());
2739     }
2740     for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
2741       InstrumentMopsInBBl(bbl, rtn, trace_info, instrument_pc, &i);
2742     }
2743   }
2744 
2745   // instrument the calls, do it after all other instrumentation.
2746   if (!g_race_verifier_active) {
2747     for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
2748       InstrumentCall(BBL_InsTail(bbl));
2749     }
2750   }
2751 
2752   CHECK(n_mops == i);
2753 }
2754 
2755 
2756 #define INSERT_FN_HELPER(point, name, rtn, to_insert, ...) \
2757     RTN_Open(rtn); \
2758     if (G_flags->verbosity >= 2) Printf("RTN: Inserting %-50s (%s) %s (%s) img: %s\n", \
2759     #to_insert, #point, RTN_Name(rtn).c_str(), name, IMG_Name(img).c_str());\
2760     RTN_InsertCall(rtn, point, (AFUNPTR)to_insert, IARG_THREAD_ID, \
2761                    IARG_INST_PTR, __VA_ARGS__, IARG_END);\
2762     RTN_Close(rtn); \
2763 
2764 #define INSERT_FN(point, name, to_insert, ...) \
2765   while (RtnMatchesName(rtn_name, name)) {\
2766     INSERT_FN_HELPER(point, name, rtn, to_insert, __VA_ARGS__); \
2767     break;\
2768   }\
2769 
2770 
2771 #define INSERT_BEFORE_FN(name, to_insert, ...) \
2772     INSERT_FN(IPOINT_BEFORE, name, to_insert, __VA_ARGS__)
2773 
2774 #define INSERT_BEFORE_1_SP(name, to_insert) \
2775     INSERT_BEFORE_FN(name, to_insert, \
2776                      IARG_REG_VALUE, REG_STACK_PTR, \
2777                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0)
2778 
2779 #define INSERT_BEFORE_2_SP(name, to_insert) \
2780     INSERT_BEFORE_FN(name, to_insert, \
2781                      IARG_REG_VALUE, REG_STACK_PTR, \
2782                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0, \
2783                      IARG_FUNCARG_ENTRYPOINT_VALUE, 1)
2784 
2785 #define INSERT_BEFORE_0(name, to_insert) \
2786     INSERT_BEFORE_FN(name, to_insert, IARG_END);
2787 
2788 #define INSERT_BEFORE_1(name, to_insert) \
2789     INSERT_BEFORE_FN(name, to_insert, \
2790                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0)
2791 
2792 #define INSERT_BEFORE_2(name, to_insert) \
2793     INSERT_BEFORE_FN(name, to_insert, \
2794                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0, \
2795                      IARG_FUNCARG_ENTRYPOINT_VALUE, 1)
2796 
2797 #define INSERT_BEFORE_3(name, to_insert) \
2798     INSERT_BEFORE_FN(name, to_insert, \
2799                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0, \
2800                      IARG_FUNCARG_ENTRYPOINT_VALUE, 1, \
2801                      IARG_FUNCARG_ENTRYPOINT_VALUE, 2)
2802 
2803 #define INSERT_BEFORE_4(name, to_insert) \
2804     INSERT_BEFORE_FN(name, to_insert, \
2805                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0, \
2806                      IARG_FUNCARG_ENTRYPOINT_VALUE, 1, \
2807                      IARG_FUNCARG_ENTRYPOINT_VALUE, 2, \
2808                      IARG_FUNCARG_ENTRYPOINT_VALUE, 3)
2809 
2810 #define INSERT_BEFORE_5(name, to_insert) \
2811     INSERT_BEFORE_FN(name, to_insert, \
2812                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0, \
2813                      IARG_FUNCARG_ENTRYPOINT_VALUE, 1, \
2814                      IARG_FUNCARG_ENTRYPOINT_VALUE, 2, \
2815                      IARG_FUNCARG_ENTRYPOINT_VALUE, 3, \
2816                      IARG_FUNCARG_ENTRYPOINT_VALUE, 4)
2817 
2818 #define INSERT_BEFORE_6(name, to_insert) \
2819     INSERT_BEFORE_FN(name, to_insert, \
2820                      IARG_FUNCARG_ENTRYPOINT_VALUE, 0, \
2821                      IARG_FUNCARG_ENTRYPOINT_VALUE, 1, \
2822                      IARG_FUNCARG_ENTRYPOINT_VALUE, 2, \
2823                      IARG_FUNCARG_ENTRYPOINT_VALUE, 3, \
2824                      IARG_FUNCARG_ENTRYPOINT_VALUE, 4, \
2825                      IARG_FUNCARG_ENTRYPOINT_VALUE, 5)
2826 
2827 #define INSERT_AFTER_FN(name, to_insert, ...) \
2828     INSERT_FN(IPOINT_AFTER, name, to_insert, __VA_ARGS__)
2829 
2830 #define INSERT_AFTER_0(name, to_insert) \
2831     INSERT_AFTER_FN(name, to_insert, IARG_END)
2832 
2833 #define INSERT_AFTER_1(name, to_insert) \
2834     INSERT_AFTER_FN(name, to_insert, IARG_FUNCRET_EXITPOINT_VALUE)
2835 
2836 
2837 #ifdef _MSC_VER
WrapStdCallFunc1(RTN rtn,char * name,AFUNPTR replacement_func)2838 void WrapStdCallFunc1(RTN rtn, char *name, AFUNPTR replacement_func) {
2839   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2840     InformAboutFunctionWrap(rtn, name);
2841     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2842                                  CALLINGSTD_STDCALL,
2843                                  "proto",
2844                                  PIN_PARG(uintptr_t),
2845                                  PIN_PARG_END());
2846     RTN_ReplaceSignature(rtn,
2847                          AFUNPTR(replacement_func),
2848                          IARG_PROTOTYPE, proto,
2849                          IARG_THREAD_ID,
2850                          IARG_INST_PTR,
2851                          IARG_CONTEXT,
2852                          IARG_ORIG_FUNCPTR,
2853                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
2854                          IARG_END);
2855     PROTO_Free(proto);
2856   }
2857 }
2858 
WrapStdCallFunc2(RTN rtn,char * name,AFUNPTR replacement_func)2859 void WrapStdCallFunc2(RTN rtn, char *name, AFUNPTR replacement_func) {
2860   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2861     InformAboutFunctionWrap(rtn, name);
2862     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2863                                  CALLINGSTD_STDCALL,
2864                                  "proto",
2865                                  PIN_PARG(uintptr_t),
2866                                  PIN_PARG(uintptr_t),
2867                                  PIN_PARG_END());
2868     RTN_ReplaceSignature(rtn,
2869                          AFUNPTR(replacement_func),
2870                          IARG_PROTOTYPE, proto,
2871                          IARG_THREAD_ID,
2872                          IARG_INST_PTR,
2873                          IARG_CONTEXT,
2874                          IARG_ORIG_FUNCPTR,
2875                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
2876                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
2877                          IARG_END);
2878     PROTO_Free(proto);
2879   }
2880 }
2881 
WrapStdCallFunc3(RTN rtn,char * name,AFUNPTR replacement_func)2882 void WrapStdCallFunc3(RTN rtn, char *name, AFUNPTR replacement_func) {
2883   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2884     InformAboutFunctionWrap(rtn, name);
2885     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2886                                  CALLINGSTD_STDCALL,
2887                                  "proto",
2888                                  PIN_PARG(uintptr_t),
2889                                  PIN_PARG(uintptr_t),
2890                                  PIN_PARG(uintptr_t),
2891                                  PIN_PARG_END());
2892     RTN_ReplaceSignature(rtn,
2893                          AFUNPTR(replacement_func),
2894                          IARG_PROTOTYPE, proto,
2895                          IARG_THREAD_ID,
2896                          IARG_INST_PTR,
2897                          IARG_CONTEXT,
2898                          IARG_ORIG_FUNCPTR,
2899                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
2900                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
2901                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
2902                          IARG_END);
2903     PROTO_Free(proto);
2904   }
2905 }
2906 
WrapStdCallFunc4(RTN rtn,char * name,AFUNPTR replacement_func)2907 void WrapStdCallFunc4(RTN rtn, char *name, AFUNPTR replacement_func) {
2908   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2909     InformAboutFunctionWrap(rtn, name);
2910     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2911                                  CALLINGSTD_STDCALL,
2912                                  "proto",
2913                                  PIN_PARG(uintptr_t),
2914                                  PIN_PARG(uintptr_t),
2915                                  PIN_PARG(uintptr_t),
2916                                  PIN_PARG(uintptr_t),
2917                                  PIN_PARG_END());
2918     RTN_ReplaceSignature(rtn,
2919                          AFUNPTR(replacement_func),
2920                          IARG_PROTOTYPE, proto,
2921                          IARG_THREAD_ID,
2922                          IARG_INST_PTR,
2923                          IARG_CONTEXT,
2924                          IARG_ORIG_FUNCPTR,
2925                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
2926                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
2927                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
2928                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
2929                          IARG_END);
2930     PROTO_Free(proto);
2931   }
2932 }
2933 
WrapStdCallFunc5(RTN rtn,char * name,AFUNPTR replacement_func)2934 void WrapStdCallFunc5(RTN rtn, char *name, AFUNPTR replacement_func) {
2935   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2936     InformAboutFunctionWrap(rtn, name);
2937     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2938                                  CALLINGSTD_STDCALL,
2939                                  "proto",
2940                                  PIN_PARG(uintptr_t),
2941                                  PIN_PARG(uintptr_t),
2942                                  PIN_PARG(uintptr_t),
2943                                  PIN_PARG(uintptr_t),
2944                                  PIN_PARG(uintptr_t),
2945                                  PIN_PARG_END());
2946     RTN_ReplaceSignature(rtn,
2947                          AFUNPTR(replacement_func),
2948                          IARG_PROTOTYPE, proto,
2949                          IARG_THREAD_ID,
2950                          IARG_INST_PTR,
2951                          IARG_CONTEXT,
2952                          IARG_ORIG_FUNCPTR,
2953                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
2954                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
2955                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
2956                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
2957                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
2958                          IARG_END);
2959     PROTO_Free(proto);
2960   }
2961 }
2962 
WrapStdCallFunc6(RTN rtn,char * name,AFUNPTR replacement_func)2963 void WrapStdCallFunc6(RTN rtn, char *name, AFUNPTR replacement_func) {
2964   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2965     InformAboutFunctionWrap(rtn, name);
2966     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2967                                  CALLINGSTD_STDCALL,
2968                                  "proto",
2969                                  PIN_PARG(uintptr_t),
2970                                  PIN_PARG(uintptr_t),
2971                                  PIN_PARG(uintptr_t),
2972                                  PIN_PARG(uintptr_t),
2973                                  PIN_PARG(uintptr_t),
2974                                  PIN_PARG(uintptr_t),
2975                                  PIN_PARG_END());
2976     RTN_ReplaceSignature(rtn,
2977                          AFUNPTR(replacement_func),
2978                          IARG_PROTOTYPE, proto,
2979                          IARG_THREAD_ID,
2980                          IARG_INST_PTR,
2981                          IARG_CONTEXT,
2982                          IARG_ORIG_FUNCPTR,
2983                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
2984                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
2985                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
2986                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
2987                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
2988                          IARG_FUNCARG_ENTRYPOINT_VALUE, 5,
2989                          IARG_END);
2990     PROTO_Free(proto);
2991   }
2992 }
2993 
WrapStdCallFunc7(RTN rtn,char * name,AFUNPTR replacement_func)2994 void WrapStdCallFunc7(RTN rtn, char *name, AFUNPTR replacement_func) {
2995   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
2996     InformAboutFunctionWrap(rtn, name);
2997     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
2998                                  CALLINGSTD_STDCALL,
2999                                  "proto",
3000                                  PIN_PARG(uintptr_t),
3001                                  PIN_PARG(uintptr_t),
3002                                  PIN_PARG(uintptr_t),
3003                                  PIN_PARG(uintptr_t),
3004                                  PIN_PARG(uintptr_t),
3005                                  PIN_PARG(uintptr_t),
3006                                  PIN_PARG(uintptr_t),
3007                                  PIN_PARG_END());
3008     RTN_ReplaceSignature(rtn,
3009                          AFUNPTR(replacement_func),
3010                          IARG_PROTOTYPE, proto,
3011                          IARG_THREAD_ID,
3012                          IARG_INST_PTR,
3013                          IARG_CONTEXT,
3014                          IARG_ORIG_FUNCPTR,
3015                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
3016                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
3017                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
3018                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
3019                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
3020                          IARG_FUNCARG_ENTRYPOINT_VALUE, 5,
3021                          IARG_FUNCARG_ENTRYPOINT_VALUE, 6,
3022                          IARG_END);
3023     PROTO_Free(proto);
3024   }
3025 }
3026 
WrapStdCallFunc8(RTN rtn,char * name,AFUNPTR replacement_func)3027 void WrapStdCallFunc8(RTN rtn, char *name, AFUNPTR replacement_func) {
3028   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
3029     InformAboutFunctionWrap(rtn, name);
3030     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
3031                                  CALLINGSTD_STDCALL,
3032                                  "proto",
3033                                  PIN_PARG(uintptr_t),
3034                                  PIN_PARG(uintptr_t),
3035                                  PIN_PARG(uintptr_t),
3036                                  PIN_PARG(uintptr_t),
3037                                  PIN_PARG(uintptr_t),
3038                                  PIN_PARG(uintptr_t),
3039                                  PIN_PARG(uintptr_t),
3040                                  PIN_PARG(uintptr_t),
3041                                  PIN_PARG_END());
3042     RTN_ReplaceSignature(rtn,
3043                          AFUNPTR(replacement_func),
3044                          IARG_PROTOTYPE, proto,
3045                          IARG_THREAD_ID,
3046                          IARG_INST_PTR,
3047                          IARG_CONTEXT,
3048                          IARG_ORIG_FUNCPTR,
3049                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
3050                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
3051                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
3052                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
3053                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
3054                          IARG_FUNCARG_ENTRYPOINT_VALUE, 5,
3055                          IARG_FUNCARG_ENTRYPOINT_VALUE, 6,
3056                          IARG_FUNCARG_ENTRYPOINT_VALUE, 7,
3057                          IARG_END);
3058     PROTO_Free(proto);
3059   }
3060 }
3061 
WrapStdCallFunc10(RTN rtn,char * name,AFUNPTR replacement_func)3062 void WrapStdCallFunc10(RTN rtn, char *name, AFUNPTR replacement_func) {
3063   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
3064     InformAboutFunctionWrap(rtn, name);
3065     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
3066                                  CALLINGSTD_STDCALL,
3067                                  "proto",
3068                                  PIN_PARG(uintptr_t),
3069                                  PIN_PARG(uintptr_t),
3070                                  PIN_PARG(uintptr_t),
3071                                  PIN_PARG(uintptr_t),
3072                                  PIN_PARG(uintptr_t),
3073                                  PIN_PARG(uintptr_t),
3074                                  PIN_PARG(uintptr_t),
3075                                  PIN_PARG(uintptr_t),
3076                                  PIN_PARG(uintptr_t),
3077                                  PIN_PARG(uintptr_t),
3078                                  PIN_PARG_END());
3079     RTN_ReplaceSignature(rtn,
3080                          AFUNPTR(replacement_func),
3081                          IARG_PROTOTYPE, proto,
3082                          IARG_THREAD_ID,
3083                          IARG_INST_PTR,
3084                          IARG_CONTEXT,
3085                          IARG_ORIG_FUNCPTR,
3086                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
3087                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
3088                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
3089                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
3090                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
3091                          IARG_FUNCARG_ENTRYPOINT_VALUE, 5,
3092                          IARG_FUNCARG_ENTRYPOINT_VALUE, 6,
3093                          IARG_FUNCARG_ENTRYPOINT_VALUE, 7,
3094                          IARG_FUNCARG_ENTRYPOINT_VALUE, 8,
3095                          IARG_FUNCARG_ENTRYPOINT_VALUE, 9,
3096                          IARG_END);
3097     PROTO_Free(proto);
3098   }
3099 }
3100 
WrapStdCallFunc11(RTN rtn,char * name,AFUNPTR replacement_func)3101 void WrapStdCallFunc11(RTN rtn, char *name, AFUNPTR replacement_func) {
3102   if (RTN_Valid(rtn) && RtnMatchesName(RTN_Name(rtn), name)) {
3103     InformAboutFunctionWrap(rtn, name);
3104     PROTO proto = PROTO_Allocate(PIN_PARG(uintptr_t),
3105                                  CALLINGSTD_STDCALL,
3106                                  "proto",
3107                                  PIN_PARG(uintptr_t),
3108                                  PIN_PARG(uintptr_t),
3109                                  PIN_PARG(uintptr_t),
3110                                  PIN_PARG(uintptr_t),
3111                                  PIN_PARG(uintptr_t),
3112                                  PIN_PARG(uintptr_t),
3113                                  PIN_PARG(uintptr_t),
3114                                  PIN_PARG(uintptr_t),
3115                                  PIN_PARG(uintptr_t),
3116                                  PIN_PARG(uintptr_t),
3117                                  PIN_PARG(uintptr_t),
3118                                  PIN_PARG_END());
3119     RTN_ReplaceSignature(rtn,
3120                          AFUNPTR(replacement_func),
3121                          IARG_PROTOTYPE, proto,
3122                          IARG_THREAD_ID,
3123                          IARG_INST_PTR,
3124                          IARG_CONTEXT,
3125                          IARG_ORIG_FUNCPTR,
3126                          IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
3127                          IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
3128                          IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
3129                          IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
3130                          IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
3131                          IARG_FUNCARG_ENTRYPOINT_VALUE, 5,
3132                          IARG_FUNCARG_ENTRYPOINT_VALUE, 6,
3133                          IARG_FUNCARG_ENTRYPOINT_VALUE, 7,
3134                          IARG_FUNCARG_ENTRYPOINT_VALUE, 8,
3135                          IARG_FUNCARG_ENTRYPOINT_VALUE, 9,
3136                          IARG_FUNCARG_ENTRYPOINT_VALUE, 10,
3137                          IARG_END);
3138     PROTO_Free(proto);
3139   }
3140 }
3141 
3142 #endif
3143 
MaybeInstrumentOneRoutine(IMG img,RTN rtn)3144 static void MaybeInstrumentOneRoutine(IMG img, RTN rtn) {
3145   if (IgnoreImage(img)) {
3146     return;
3147   }
3148   string rtn_name = RTN_Name(rtn);
3149   string img_name = IMG_Name(img);
3150   if (debug_wrap) {
3151     Printf("%s: %s %s pc=%p\n", __FUNCTION__, rtn_name.c_str(),
3152            img_name.c_str(), RTN_Address(rtn));
3153   }
3154 
3155   // malloc/free/etc
3156   const char *malloc_names[] = {
3157     "malloc",
3158 #if defined(__GNUC__)
3159     "_Znwm",
3160     "_Znam",
3161     "_Znwj",
3162     "_Znaj",
3163     "_ZnwmRKSt9nothrow_t",
3164     "_ZnamRKSt9nothrow_t",
3165     "_ZnwjRKSt9nothrow_t",
3166     "_ZnajRKSt9nothrow_t",
3167 #endif
3168 #if defined(_MSC_VER)
3169     "operator new",
3170     "operator new[]",
3171 #endif  // _MSC_VER
3172   };
3173 
3174   const char *free_names[] = {
3175     "free",
3176 #if defined(__GNUC__)
3177     "_ZdaPv",
3178     "_ZdlPv",
3179     "_ZdlPvRKSt9nothrow_t",
3180     "_ZdaPvRKSt9nothrow_t",
3181 #endif  // __GNUC__
3182 #if defined(_MSC_VER)
3183     "operator delete",
3184     "operator delete[]",
3185 #endif  // _MSC_VER
3186   };
3187 
3188   for (size_t i = 0; i < TS_ARRAY_SIZE(malloc_names); i++) {
3189     const char *name = malloc_names[i];
3190     INSERT_BEFORE_1_SP(name, Before_malloc);
3191   }
3192 
3193   for (size_t i = 0; i < TS_ARRAY_SIZE(free_names); i++) {
3194     const char *name = free_names[i];
3195     INSERT_BEFORE_1_SP(name, Before_free);
3196   }
3197 
3198   INSERT_BEFORE_2_SP("calloc", Before_calloc);
3199   INSERT_BEFORE_2_SP("realloc", Before_realloc);
3200 
3201 #if defined(__GNUC__)
3202   WrapFunc6(img, rtn, "mmap", (AFUNPTR)WRAP_NAME(mmap));
3203   WrapFunc4(img, rtn, "munmap", (AFUNPTR)WRAP_NAME(munmap));
3204 
3205   WrapFunc4(img, rtn, "lockf", (AFUNPTR)WRAP_NAME(lockf));
3206   // pthread create/join
3207   WrapFunc4(img, rtn, "pthread_create", (AFUNPTR)WRAP_NAME(pthread_create));
3208   WrapFunc4(img, rtn, "pthread_join", (AFUNPTR)WRAP_NAME(pthread_join));
3209   WrapFunc4(img, rtn, "fwrite", (AFUNPTR)WRAP_NAME(fwrite));
3210 
3211   INSERT_FN(IPOINT_BEFORE, "start_thread",
3212             Before_start_thread,
3213             IARG_REG_VALUE, REG_STACK_PTR, IARG_END);
3214 
3215    // pthread_cond_*
3216   INSERT_BEFORE_1("pthread_cond_signal", Before_pthread_cond_signal);
3217   WRAP4(pthread_cond_wait);
3218   WRAP4(pthread_cond_timedwait);
3219 
3220   // pthread_mutex_*
3221   INSERT_BEFORE_1("pthread_mutex_init", Before_pthread_mutex_init);
3222   INSERT_BEFORE_1("pthread_mutex_destroy", Before_pthread_mutex_destroy);
3223   INSERT_BEFORE_1("pthread_mutex_unlock", Before_pthread_unlock);
3224 
3225 
3226   INSERT_BEFORE_1_SP("pthread_mutex_lock", Before_pthread_mutex_lock);
3227   WRAP4(pthread_mutex_trylock);
3228   WRAP4(pthread_spin_lock);
3229   WRAP4(pthread_spin_trylock);
3230   WRAP4(pthread_spin_init);
3231   WRAP4(pthread_spin_destroy);
3232   WRAP4(pthread_spin_unlock);
3233   WRAP4(pthread_rwlock_wrlock);
3234   WRAP4(pthread_rwlock_rdlock);
3235   WRAP4(pthread_rwlock_trywrlock);
3236   WRAP4(pthread_rwlock_tryrdlock);
3237 
3238   // pthread_rwlock_*
3239   INSERT_BEFORE_1("pthread_rwlock_init", Before_pthread_rwlock_init);
3240   INSERT_BEFORE_1("pthread_rwlock_destroy", Before_pthread_rwlock_destroy);
3241   INSERT_BEFORE_1("pthread_rwlock_unlock", Before_pthread_unlock);
3242 
3243   // pthread_barrier_*
3244   WrapFunc4(img, rtn, "pthread_barrier_init",
3245             (AFUNPTR)WRAP_NAME(pthread_barrier_init));
3246   WrapFunc4(img, rtn, "pthread_barrier_wait",
3247             (AFUNPTR)WRAP_NAME(pthread_barrier_wait));
3248 
3249   // pthread_once
3250   WrapFunc4(img, rtn, "pthread_once", (AFUNPTR)WRAP_NAME(pthread_once));
3251 
3252   // sem_*
3253   INSERT_AFTER_1("sem_open", After_sem_open);
3254   INSERT_BEFORE_1("sem_post", Before_sem_post);
3255   WRAP4(sem_wait);
3256   WRAP4(sem_trywait);
3257 
3258   INSERT_BEFORE_0("epoll_ctl", Before_epoll_ctl);
3259   INSERT_AFTER_0("epoll_wait", After_epoll_wait);
3260 #endif  // __GNUC__
3261 
3262 #ifdef _MSC_VER
3263   WrapStdCallFunc6(rtn, "CreateThread", (AFUNPTR)WRAP_NAME(CreateThread));
3264   WRAPSTD1(ResumeThread);
3265 
3266   INSERT_FN(IPOINT_BEFORE, "BaseThreadInitThunk",
3267             Before_BaseThreadInitThunk,
3268             IARG_REG_VALUE, REG_STACK_PTR, IARG_END);
3269 
3270   INSERT_BEFORE_0("RtlExitUserThread", Before_RtlExitUserThread);
3271   INSERT_BEFORE_0("ExitThread", Before_RtlExitUserThread);
3272 
3273   WRAPSTD1(RtlInitializeCriticalSection);
3274   WRAPSTD2(RtlInitializeCriticalSectionAndSpinCount);
3275   WRAPSTD3(RtlInitializeCriticalSectionEx);
3276   WRAPSTD1(RtlDeleteCriticalSection);
3277   WRAPSTD1(RtlEnterCriticalSection);
3278   WRAPSTD1(RtlTryEnterCriticalSection);
3279   WRAPSTD1(RtlLeaveCriticalSection);
3280   WRAPSTD7(DuplicateHandle);
3281   WRAPSTD1(SetEvent);
3282   WRAPSTD4(CreateSemaphoreA);
3283   WRAPSTD4(CreateSemaphoreW);
3284   WRAPSTD3(ReleaseSemaphore);
3285 
3286   WRAPSTD1(RtlInterlockedPopEntrySList);
3287   WRAPSTD2(RtlInterlockedPushEntrySList);
3288 
3289 #if 1
3290   WRAPSTD1(RtlAcquireSRWLockExclusive);
3291   WRAPSTD1(RtlAcquireSRWLockShared);
3292   WRAPSTD1(RtlTryAcquireSRWLockExclusive);
3293   WRAPSTD1(RtlTryAcquireSRWLockShared);
3294   WRAPSTD1(RtlReleaseSRWLockExclusive);
3295   WRAPSTD1(RtlReleaseSRWLockShared);
3296   WRAPSTD1(RtlInitializeSRWLock);
3297   // For some reason, RtlInitializeSRWLock is aliased to RtlInitializeSRWLock..
3298   WrapStdCallFunc1(rtn, "RtlRunOnceInitialize",
3299                    (AFUNPTR)Wrap_RtlInitializeSRWLock);
3300 
3301   /* We haven't seen these syscalls used in the wild yet.
3302   WRAPSTD2(RtlUpdateClonedSRWLock);
3303   WRAPSTD1(RtlAcquireReleaseSRWLockExclusive);
3304   WRAPSTD1(RtlUpdateClonedCriticalSection);
3305   */
3306 
3307   WRAPSTD1(RtlWakeConditionVariable);
3308   WRAPSTD1(RtlWakeAllConditionVariable);
3309   WRAPSTD4(RtlSleepConditionVariableSRW);
3310   WRAPSTD3(RtlSleepConditionVariableCS);
3311 #endif  // if 1
3312 
3313   WRAPSTD3(RtlQueueWorkItem);
3314   WRAPSTD6(RegisterWaitForSingleObject);
3315   WRAPSTD2(UnregisterWaitEx);
3316 
3317   WRAPSTD3(WaitForSingleObjectEx);
3318   WRAPSTD5(WaitForMultipleObjectsEx);
3319 
3320   WrapStdCallFunc4(rtn, "VirtualAlloc", (AFUNPTR)(WRAP_NAME(VirtualAlloc)));
3321   WrapStdCallFunc6(rtn, "ZwAllocateVirtualMemory", (AFUNPTR)(WRAP_NAME(ZwAllocateVirtualMemory)));
3322   WrapStdCallFunc2(rtn, "GlobalAlloc", (AFUNPTR)WRAP_NAME(GlobalAlloc));
3323 //  WrapStdCallFunc3(rtn, "RtlAllocateHeap", (AFUNPTR) WRAP_NAME(AllocateHeap));
3324 //  WrapStdCallFunc3(rtn, "HeapCreate", (AFUNPTR) WRAP_NAME(HeapCreate));
3325 #endif  // _MSC_VER
3326 
3327   // Annotations.
3328   INSERT_BEFORE_4("AnnotateBenignRace", On_AnnotateBenignRace);
3329   INSERT_BEFORE_5("AnnotateBenignRaceSized", On_AnnotateBenignRaceSized);
3330   INSERT_BEFORE_5("WTFAnnotateBenignRaceSized", On_AnnotateBenignRaceSized);
3331   INSERT_BEFORE_4("AnnotateExpectRace", On_AnnotateExpectRace);
3332   INSERT_BEFORE_2("AnnotateFlushExpectedRaces", On_AnnotateFlushExpectedRaces);
3333   INSERT_BEFORE_3("AnnotateTraceMemory", On_AnnotateTraceMemory);
3334   INSERT_BEFORE_4("AnnotateNewMemory", On_AnnotateNewMemory);
3335   INSERT_BEFORE_3("AnnotateNoOp", On_AnnotateNoOp);
3336   INSERT_BEFORE_2("AnnotateFlushState", On_AnnotateFlushState);
3337 
3338   INSERT_BEFORE_3("AnnotateCondVarWait", On_AnnotateCondVarWait);
3339   INSERT_BEFORE_3("AnnotateCondVarSignal", On_AnnotateCondVarSignal);
3340   INSERT_BEFORE_3("AnnotateCondVarSignalAll", On_AnnotateCondVarSignal);
3341   INSERT_BEFORE_3("AnnotateHappensBefore", On_AnnotateHappensBefore);
3342   INSERT_BEFORE_3("WTFAnnotateHappensBefore", On_AnnotateHappensBefore);
3343   INSERT_BEFORE_3("AnnotateHappensAfter", On_AnnotateHappensAfter);
3344   INSERT_BEFORE_3("WTFAnnotateHappensAfter", On_AnnotateHappensAfter);
3345 
3346   INSERT_BEFORE_3("AnnotateEnableRaceDetection", On_AnnotateEnableRaceDetection);
3347   INSERT_BEFORE_0("AnnotateIgnoreReadsBegin", On_AnnotateIgnoreReadsBegin);
3348   INSERT_BEFORE_0("AnnotateIgnoreReadsEnd", On_AnnotateIgnoreReadsEnd);
3349   INSERT_BEFORE_0("AnnotateIgnoreWritesBegin", On_AnnotateIgnoreWritesBegin);
3350   INSERT_BEFORE_0("AnnotateIgnoreWritesEnd", On_AnnotateIgnoreWritesEnd);
3351   INSERT_BEFORE_3("AnnotateThreadName", On_AnnotateThreadName);
3352   INSERT_BEFORE_4("AnnotatePublishMemoryRange", On_AnnotatePublishMemoryRange);
3353   INSERT_BEFORE_4("AnnotateUnpublishMemoryRange", On_AnnotateUnpublishMemoryRange);
3354   INSERT_BEFORE_3("AnnotateMutexIsUsedAsCondVar", On_AnnotateMutexIsUsedAsCondVar);
3355   INSERT_BEFORE_3("AnnotateMutexIsNotPHB", On_AnnotateMutexIsNotPhb);
3356 
3357   INSERT_BEFORE_3("AnnotatePCQCreate", On_AnnotatePCQCreate);
3358   INSERT_BEFORE_3("AnnotatePCQDestroy", On_AnnotatePCQDestroy);
3359   INSERT_BEFORE_3("AnnotatePCQPut", On_AnnotatePCQPut);
3360   INSERT_BEFORE_3("AnnotatePCQGet", On_AnnotatePCQGet);
3361 
3362   INSERT_BEFORE_3("AnnotateRWLockCreate", On_AnnotateRWLockCreate);
3363   INSERT_BEFORE_3("AnnotateRWLockDestroy", On_AnnotateRWLockDestroy);
3364   INSERT_BEFORE_4("AnnotateRWLockAcquired", On_AnnotateRWLockAcquired);
3365   INSERT_BEFORE_4("AnnotateRWLockReleased", On_AnnotateRWLockReleased);
3366 
3367   // ThreadSanitizerQuery
3368   WrapFunc4(img, rtn, "ThreadSanitizerQuery",
3369             (AFUNPTR)WRAP_NAME(ThreadSanitizerQuery));
3370   WrapFunc4(img, rtn, "RunningOnValgrind",
3371             (AFUNPTR)WRAP_NAME(RunningOnValgrind));
3372 
3373   // I/O
3374   INSERT_BEFORE_0("write", Before_SignallingIOCall);
3375   INSERT_BEFORE_0("unlink", Before_SignallingIOCall);
3376   INSERT_BEFORE_0("rmdir", Before_SignallingIOCall);
3377 //  INSERT_BEFORE_0("send", Before_SignallingIOCall);
3378   INSERT_AFTER_0("__read_nocancel", After_WaitingIOCall);
3379   INSERT_AFTER_0("fopen", After_WaitingIOCall);
3380   INSERT_AFTER_0("__fopen_internal", After_WaitingIOCall);
3381   INSERT_AFTER_0("open", After_WaitingIOCall);
3382   INSERT_AFTER_0("opendir", After_WaitingIOCall);
3383 //  INSERT_AFTER_0("recv", After_WaitingIOCall);
3384 
3385   // strlen and friends.
3386   // These wrappers will generate memory access events.
3387   // So, if we don't want to get those events (e.g. memcpy inside
3388   // ld.so or ntdll.dll) we don't wrap them and the regular
3389   // ignore machinery will make sure we don't get the events.
3390   if (ThreadSanitizerWantToInstrumentSblock(RTN_Address(rtn))) {
3391     ReplaceFunc3(img, rtn, "memchr", (AFUNPTR)Replace_memchr);
3392     ReplaceFunc3(img, rtn, "strchr", (AFUNPTR)Replace_strchr);
3393     ReplaceFunc3(img, rtn, "index", (AFUNPTR)Replace_strchr);
3394     ReplaceFunc3(img, rtn, "strchrnul", (AFUNPTR)Replace_strchrnul);
3395     ReplaceFunc3(img, rtn, "strrchr", (AFUNPTR)Replace_strrchr);
3396     ReplaceFunc3(img, rtn, "rindex", (AFUNPTR)Replace_strrchr);
3397     ReplaceFunc3(img, rtn, "strlen", (AFUNPTR)Replace_strlen);
3398     ReplaceFunc3(img, rtn, "strcmp", (AFUNPTR)Replace_strcmp);
3399     ReplaceFunc3(img, rtn, "strncmp", (AFUNPTR)Replace_strncmp);
3400     ReplaceFunc3(img, rtn, "memcpy", (AFUNPTR)Replace_memcpy);
3401     ReplaceFunc3(img, rtn, "memcmp", (AFUNPTR)Replace_memcmp);
3402     ReplaceFunc3(img, rtn, "memmove", (AFUNPTR)Replace_memmove);
3403     ReplaceFunc3(img, rtn, "strcpy", (AFUNPTR)Replace_strcpy);
3404     ReplaceFunc3(img, rtn, "strncpy", (AFUNPTR)Replace_strncpy);
3405     ReplaceFunc3(img, rtn, "strcat", (AFUNPTR)Replace_strcat);
3406     ReplaceFunc3(img, rtn, "stpcpy", (AFUNPTR)Replace_stpcpy);
3407   }
3408 
3409   // __cxa_guard_acquire / __cxa_guard_release
3410   INSERT_BEFORE_1("__cxa_guard_acquire", Before_cxa_guard_acquire);
3411   INSERT_AFTER_1("__cxa_guard_acquire", After_cxa_guard_acquire);
3412   INSERT_AFTER_0("__cxa_guard_release", After_cxa_guard_release);
3413 
3414   INSERT_BEFORE_0("atexit", On_atexit);
3415   INSERT_BEFORE_0("exit", On_exit);
3416 }
3417 
3418 // Pin calls this function every time a new img is loaded.
CallbackForIMG(IMG img,void * v)3419 static void CallbackForIMG(IMG img, void *v) {
3420   if (debug_wrap) {
3421     Printf("Started CallbackForIMG %s\n", IMG_Name(img).c_str());
3422   }
3423 
3424   string img_name = IMG_Name(img);
3425   for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) {
3426     for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) {
3427       MaybeInstrumentOneRoutine(img, rtn);
3428     }
3429   }
3430   // In DEBUG_MODE check that we have the debug symbols in the Windows guts.
3431   // We should work w/o them too.
3432   // TODO(timurrrr): I doubt the problem is the missing symbols.
3433   // I have a strong gut feeling that this syscall was added
3434   // in Vista but only used since Windows 7. We had its wrapper wrong
3435   // (found on W7) but the Vista build was fine for months.
3436   // Also, we wrap RtlReleaseSRWLock*, so our TSan assertions would have been
3437   // broken if RtlTryAcquireSRWLock* wasn't wrapped - and we haven't see this.
3438   if (DEBUG_MODE && img_name.find("ntdll.dll") != string::npos) {
3439     if (g_wrapped_functions.count("RtlTryAcquireSRWLockExclusive") == 0) {
3440       Printf("WARNING: Debug symbols for ntdll.dll not found.\n");
3441     }
3442   }
3443 }
3444 
3445 // Returns:
3446 // TRUE
3447 // If user is interested to inject Pin (and tool) into child/exec-ed process
3448 // FALSE
3449 // If user is not interested to inject Pin (and tool) into child/exec-ed process
CallbackForExec(CHILD_PROCESS childProcess,VOID * val)3450 static BOOL CallbackForExec(CHILD_PROCESS childProcess, VOID *val) {
3451   int argc = 0;
3452   const CHAR *const * argv = NULL;
3453   CHILD_PROCESS_GetCommandLine(childProcess, &argc, &argv);
3454   CHECK(argc > 0);
3455   CHECK(argv);
3456   bool follow = G_flags->trace_children;
3457   if (DEBUG_MODE) {
3458     Printf("CallbackForExec: follow=%d: ", follow);
3459     for (int i = 0; i < argc; i++) {
3460       Printf("%s ", argv[i]);
3461     }
3462   }
3463   Printf("\n");
3464   return follow;
3465 }
3466 
3467 //--------- Fini ---------- {{{1
CallbackForFini(INT32 code,void * v)3468 static void CallbackForFini(INT32 code, void *v) {
3469   DumpEvent(0, THR_END, 0, 0, 0, 0);
3470   ThreadSanitizerFini();
3471   if (g_race_verifier_active) {
3472     RaceVerifierFini();
3473   }
3474   if (G_flags->show_stats) {
3475     TraceInfo::PrintTraceProfile();
3476   }
3477   if (G_flags->error_exitcode && GetNumberOfFoundErrors() > 0) {
3478     exit(G_flags->error_exitcode);
3479   }
3480 }
3481 
3482 //--------- Call Coverage ----------------- {{{1
3483 // A simplistic call coverage tool.
3484 // Outputs all pairs <call_site,call_target>.
3485 
3486 typedef set<pair<uintptr_t, uintptr_t> > CallCoverageSet;
3487 static CallCoverageSet *call_coverage_set;
3488 
3489 static map<uintptr_t, string> *function_names_map;
3490 static uintptr_t symbolized_functions_cache[1023];
3491 static pair<uintptr_t, uintptr_t> registered_pairs_cache[1023];
3492 
symbolize_pc(uintptr_t pc)3493 static void symbolize_pc(uintptr_t pc) {
3494   // Check a simple cache if we already symbolized this pc (racey).
3495   size_t idx = pc % TS_ARRAY_SIZE(symbolized_functions_cache);
3496   if (symbolized_functions_cache[idx] == pc) return;
3497 
3498   ScopedReentrantClientLock lock(__LINE__);
3499   CHECK(function_names_map);
3500   if (function_names_map->count(pc) == 0) {
3501     (*function_names_map)[pc] = PcToRtnName(pc, false);
3502   }
3503   symbolized_functions_cache[idx] = pc;
3504 }
3505 
CallCoverageRegisterCall(uintptr_t from,uintptr_t to)3506 static void CallCoverageRegisterCall(uintptr_t from, uintptr_t to) {
3507   symbolize_pc(from);
3508   symbolize_pc(to);
3509 
3510   // Check if we already registered this pair (racey).
3511   size_t idx = (from ^ to) % TS_ARRAY_SIZE(registered_pairs_cache);
3512   if (registered_pairs_cache[idx] == make_pair(from,to)) return;
3513 
3514   ScopedReentrantClientLock lock(__LINE__);
3515   call_coverage_set->insert(make_pair(from, to));
3516   registered_pairs_cache[idx] = make_pair(from,to);
3517 }
3518 
CallCoverageCallbackForTRACE(TRACE trace,void * v)3519 static void CallCoverageCallbackForTRACE(TRACE trace, void *v) {
3520   RTN rtn = TRACE_Rtn(trace);
3521   if (RTN_Valid(rtn)) {
3522     SEC sec = RTN_Sec(rtn);
3523     IMG img = SEC_Img(sec);
3524     string img_name = IMG_Name(img);
3525     // Don't instrument system libraries.
3526     if (img_name.find("/usr/") == 0) return;
3527   }
3528 
3529   if (call_coverage_set == NULL) {
3530     call_coverage_set = new CallCoverageSet;
3531     function_names_map = new map<uintptr_t, string>;
3532   }
3533   for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
3534     INS ins = BBL_InsTail(bbl);
3535     if (!INS_IsProcedureCall(ins) || INS_IsSyscall(ins)) continue;
3536     if (INS_IsDirectBranchOrCall(ins)) {
3537       // If <from, to> is know at instrumentation time, don't instrument.
3538       ADDRINT to = INS_DirectBranchOrCallTargetAddress(ins);
3539       ADDRINT from = INS_Address(ins);
3540       CallCoverageRegisterCall(from, to);
3541     } else {
3542       // target is dynamic. Need to instrument.
3543       INS_InsertCall(ins, IPOINT_BEFORE,
3544                      (AFUNPTR)CallCoverageRegisterCall,
3545                      IARG_INST_PTR,
3546                      IARG_BRANCH_TARGET_ADDR,
3547                      IARG_END);
3548     }
3549   }
3550 }
3551 
3552 // Output all <from,to> pairs.
CallCoverageCallbackForFini(INT32 code,void * v)3553 static void CallCoverageCallbackForFini(INT32 code, void *v) {
3554   CHECK(call_coverage_set);
3555   CHECK(function_names_map);
3556   for (CallCoverageSet::iterator it = call_coverage_set->begin();
3557        it != call_coverage_set->end(); ++it) {
3558     string from_name = (*function_names_map)[it->first];
3559     string to_name   = (*function_names_map)[it->second];
3560     if (to_name == ".plt" || to_name == "") continue;
3561     Printf("CallCoverage: %s => %s\n", from_name.c_str(), to_name.c_str());
3562   }
3563 }
3564 
3565 //--------- Main -------------------------- {{{1
main(INT32 argc,CHAR ** argv)3566 int main(INT32 argc, CHAR **argv) {
3567   PIN_Init(argc, argv);
3568   PIN_InitSymbols();
3569   G_out = stderr;
3570 
3571   // Init ThreadSanitizer.
3572   int first_param = 1;
3573   // skip until '-t something.so'.
3574   for (; first_param < argc && argv[first_param] != string("-t");
3575        first_param++) {
3576   }
3577   first_param += 2;
3578   vector<string> args;
3579   for (; first_param < argc; first_param++) {
3580     string param = argv[first_param];
3581     if (param == "--") break;
3582     if (param == "-short_name") continue;
3583     if (param == "-slow_asserts") continue;
3584     if (param == "1") continue;
3585     args.push_back(param);
3586   }
3587 
3588   G_flags = new FLAGS;
3589   ThreadSanitizerParseFlags(&args);
3590 
3591   if (G_flags->dry_run >= 2) {
3592     PIN_StartProgram();
3593     return 0;
3594   }
3595 
3596   FILE *socket_output = OpenSocketForWriting(G_flags->log_file);
3597   if (socket_output) {
3598     G_out = socket_output;
3599   } else if (!G_flags->log_file.empty()) {
3600     // Replace %p with tool PID
3601     string fname = G_flags->log_file;
3602     char pid_str[100] = "";
3603     sprintf(pid_str, "%u", getpid());
3604     while (fname.find("%p") != fname.npos)
3605       fname.replace(fname.find("%p"), 2, pid_str);
3606 
3607     G_out = fopen(fname.c_str(), "w");
3608     CHECK(G_out);
3609   }
3610 
3611   ThreadSanitizerInit();
3612 
3613   if (G_flags->call_coverage) {
3614     PIN_AddFiniFunction(CallCoverageCallbackForFini, 0);
3615     TRACE_AddInstrumentFunction(CallCoverageCallbackForTRACE, 0);
3616     PIN_StartProgram();
3617     return 0;
3618   }
3619 
3620   tls_reg = PIN_ClaimToolRegister();
3621   CHECK(REG_valid(tls_reg));
3622 #if _MSC_VER
3623   g_windows_thread_pool_calback_set = new unordered_set<uintptr_t>;
3624   g_windows_thread_pool_wait_object_map = new unordered_map<uintptr_t, uintptr_t>;
3625 #endif
3626 
3627   // Set up PIN callbacks.
3628   PIN_AddThreadStartFunction(CallbackForThreadStart, 0);
3629   PIN_AddThreadFiniFunction(CallbackForThreadFini, 0);
3630   PIN_AddFiniFunction(CallbackForFini, 0);
3631   IMG_AddInstrumentFunction(CallbackForIMG, 0);
3632   TRACE_AddInstrumentFunction(CallbackForTRACE, 0);
3633   PIN_AddFollowChildProcessFunction(CallbackForExec, NULL);
3634 
3635   Report("ThreadSanitizerPin r%s pin %d: %s\n",
3636          TS_VERSION, PIN_BUILD_NUMBER,
3637          G_flags->pure_happens_before ? "hybrid=no" : "hybrid=yes");
3638   if (DEBUG_MODE) {
3639     Report("INFO: Debug build\n");
3640   }
3641 
3642   if (g_race_verifier_active) {
3643     RaceVerifierInit(G_flags->race_verifier, G_flags->race_verifier_extra);
3644     global_ignore = true;
3645   }
3646 
3647   // Fire!
3648   PIN_StartProgram();
3649   return 0;
3650 }
3651 
3652 //--------- Questions about PIN -------------------------- {{{1
3653 /* Questions about PIN:
3654 
3655   - Names (e.g. pthread_create@... __pthread_mutex_unlock)
3656   - How to get name of a global var by it's address?
3657   - How to get stack pointer at thread creation?
3658   - How to get a stack trace (other than intercepting calls, entries, exits)
3659   - assert with full stack trace?
3660   */
3661 // end. {{{1
3662 // vim:shiftwidth=2:softtabstop=2:expandtab
3663