1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of drd, a thread error detector.
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>.
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_bitmap.h"
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_thread_bitmap.h"
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_vc.h"            /* DRD_(vc_snprint)() */
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Include several source files here in order to allow the compiler to */
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* do more inlining.                                                   */
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_bitmap.c"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_load_store.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_segment.c"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_thread.c"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_vc.c"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_offsets.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* STACK_POINTER_OFFSET: VEX register offset for the stack pointer register. */
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGA_x86)
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STACK_POINTER_OFFSET OFFSET_x86_ESP
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_amd64)
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STACK_POINTER_OFFSET OFFSET_amd64_RSP
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_ppc32)
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STACK_POINTER_OFFSET OFFSET_ppc32_GPR1
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_ppc64)
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_arm)
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STACK_POINTER_OFFSET OFFSET_arm_R13
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_arm64)
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define STACK_POINTER_OFFSET OFFSET_arm64_XSP
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGA_s390x)
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define STACK_POINTER_OFFSET OFFSET_s390x_r15
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGA_mips32)
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define STACK_POINTER_OFFSET OFFSET_mips32_r29
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_mips64)
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define STACK_POINTER_OFFSET OFFSET_mips64_r29
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error Unknown architecture.
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local variables. */
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool s_check_stack_accesses = False;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool s_first_race_only      = False;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function definitions. */
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(get_check_stack_accesses)()
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_check_stack_accesses;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(set_check_stack_accesses)(const Bool c)
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(c == False || c == True);
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_check_stack_accesses = c;
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(get_first_race_only)()
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_first_race_only;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(set_first_race_only)(const Bool fro)
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(fro == False || fro == True);
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_first_race_only = fro;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(trace_mem_access)(const Addr addr, const SizeT size,
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            const BmAccessTypeT access_type,
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            const HWord stored_value_hi,
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            const HWord stored_value_lo)
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(is_any_traced)(addr, addr + size))
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* vc;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (access_type == eStore && size <= sizeof(HWord)) {
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %ld/0x%lx (thread %d /"
105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              " vc %s)", addr, size, stored_value_lo,
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              stored_value_lo, DRD_(thread_get_running_tid)(),
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              vc);
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else if (access_type == eStore && size > sizeof(HWord)) {
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ULong sv;
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tl_assert(sizeof(HWord) == 4);
112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sv = ((ULong)stored_value_hi << 32) | stored_value_lo;
113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %lld/0x%llx (thread %d"
114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              " / vc %s)", addr, size, sv, sv,
115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              DRD_(thread_get_running_tid)(), vc);
116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              access_type == eLoad ? "load "
119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              : access_type == eStore ? "store"
120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              : access_type == eStart ? "start"
121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              : access_type == eEnd ? "end  " : "????",
122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              addr, size, DRD_(thread_get_running_tid)(), vc);
123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(vc);
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                == VG_(get_running_tid)());
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return DRD_(trace_mem_access)(addr, size, eLoad, 0, 0);
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic VG_REGPARM(3) void drd_trace_mem_store(const Addr addr,const SizeT size,
136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              const HWord stored_value_hi,
137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              const HWord stored_value_lo)
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return DRD_(trace_mem_access)(addr, size, eStore, stored_value_hi,
140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 stored_value_lo);
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_report_race(const Addr addr, const SizeT size,
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            const BmAccessTypeT access_type)
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ThreadId vg_tid;
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vg_tid = VG_(get_running_tid)();
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!DRD_(get_check_stack_accesses)()
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && DRD_(thread_address_on_any_stack)(addr)) {
151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if 0
152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      GenericErrInfo GEI = {
153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .tid = DRD_(thread_get_running_tid)(),
154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .addr = addr,
155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      };
156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(maybe_record_error)(vg_tid, GenericErr, VG_(get_IP)(vg_tid),
157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              "--check-stack-var=no skips checking stack"
158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              " variables shared over threads",
159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              &GEI);
160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  } else {
162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DataRaceErrInfo drei = {
163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .tid  = DRD_(thread_get_running_tid)(),
164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .addr = addr,
165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .size = size,
166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .access_type = access_type,
167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      };
168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(maybe_record_error)(vg_tid, DataRaceErr, VG_(get_IP)(vg_tid),
169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              "Conflicting access", &drei);
170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (s_first_race_only)
172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DRD_(start_suppression)(addr, addr + size, "first race only");
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The assert below has been commented out because of performance reasons.*/
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(thread_get_running_tid)()
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_loads)()
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_load_triggers_conflict(addr, addr + size)
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + size))
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, size, eLoad);
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_load_1(Addr addr)
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_loads)()
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_load_1_triggers_conflict(addr)
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 1))
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 1, eLoad);
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_load_2(Addr addr)
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_loads)()
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_load_2_triggers_conflict(addr)
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 2))
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 2, eLoad);
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_load_4(Addr addr)
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_loads)()
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_load_4_triggers_conflict(addr)
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 4))
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 4, eLoad);
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_load_8(Addr addr)
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_loads)()
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_load_8_triggers_conflict(addr)
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 8))
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 8, eLoad);
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The assert below has been commented out because of performance reasons.*/
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(DRD_(thread_get_running_tid)()
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_stores)()
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_store_triggers_conflict(addr, addr + size)
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + size))
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, size, eStore);
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_store_1(Addr addr)
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_stores)()
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_store_1_triggers_conflict(addr)
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 1))
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 1, eStore);
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_store_2(Addr addr)
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_stores)()
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_store_2_triggers_conflict(addr)
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 2))
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 2, eStore);
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_store_4(Addr addr)
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_stores)()
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || !DRD_(thread_address_on_stack)(addr))
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_store_4_triggers_conflict(addr)
290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && !DRD_(is_suppressed)(addr, addr + 4))
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 4, eStore);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1) void drd_trace_store_8(Addr addr)
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(running_thread_is_recording_stores)()
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (s_check_stack_accesses
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ! DRD_(thread_address_on_stack)(addr))
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && bm_access_store_8_triggers_conflict(addr)
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ! DRD_(is_suppressed)(addr, addr + 8))
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_report_race(addr, 8, eStore);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return true if and only if addr_expr matches the pattern (SP) or
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * <offset>(SP).
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool result = False;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (addr_expr->tag == Iex_RdTmp)
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int i;
319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      for (i = 0; i < bb->stmts_used; i++)
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bb->stmts[i]
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && bb->stmts[i]->tag == Ist_WrTmp
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               result = True;
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //ppIRExpr(e);
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //VG_(printf)(" (%s)\n", result ? "True" : "False");
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return result;
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic const IROp u_widen_irop[5][9] = {
341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   [Ity_I1  - Ity_I1] = { [4] = Iop_1Uto32,  [8] = Iop_1Uto64 },
342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   [Ity_I8  - Ity_I1] = { [4] = Iop_8Uto32,  [8] = Iop_8Uto64 },
343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   [Ity_I16 - Ity_I1] = { [4] = Iop_16Uto32, [8] = Iop_16Uto64 },
344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   [Ity_I32 - Ity_I1] = {                    [8] = Iop_32Uto64 },
345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/**
348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Instrument the client code to trace a memory load (--trace-addr).
349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */
350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRExpr* instr_trace_mem_load(IRSB* const bb, IRExpr* addr_expr,
351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    const HWord size,
352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    IRExpr* const guard/* NULL => True */)
353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp tmp;
355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addr_expr = IRExpr_RdTmp(tmp);
359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRDirty* di
360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     = unsafeIRDirty_0_N(/*regparms*/2,
361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         "drd_trace_mem_load",
362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         VG_(fnptr_to_fnentry)
363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         (drd_trace_mem_load),
364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)));
365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard) di->guard = guard;
366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addStmtToIRSB(bb, IRStmt_Dirty(di));
367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return addr_expr;
369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/**
372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Instrument the client code to trace a memory store (--trace-addr).
373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */
374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void instr_trace_mem_store(IRSB* const bb, IRExpr* const addr_expr,
375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  IRExpr* data_expr_hi, IRExpr* data_expr_lo,
376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  IRExpr* const guard/* NULL => True */)
377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty_data_expr;
379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HWord size;
380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(!data_expr_hi || typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I32);
383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ty_data_expr = typeOfIRExpr(bb->tyenv, data_expr_lo);
385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   size = sizeofIRType(ty_data_expr);
386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if 0
388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Test code
389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ty_data_expr == Ity_I32) {
390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp tmp = newIRTemp(bb->tyenv, Ity_F32);
391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      data_expr_lo = IRExpr_Unop(Iop_ReinterpI32asF32, data_expr_lo);
392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      data_expr_lo = IRExpr_RdTmp(tmp);
394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty_data_expr = Ity_F32;
395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else if (ty_data_expr == Ity_I64) {
396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp tmp = newIRTemp(bb->tyenv, Ity_F64);
397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      data_expr_lo = IRExpr_Unop(Iop_ReinterpI64asF64, data_expr_lo);
398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      data_expr_lo = IRExpr_RdTmp(tmp);
400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty_data_expr = Ity_F64;
401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ty_data_expr == Ity_F32) {
405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp tmp = newIRTemp(bb->tyenv, Ity_I32);
406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF32asI32,
407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                      data_expr_lo)));
408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      data_expr_lo = IRExpr_RdTmp(tmp);
409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty_data_expr = Ity_I32;
410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else if (ty_data_expr == Ity_F64) {
411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp tmp = newIRTemp(bb->tyenv, Ity_I64);
412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF64asI64,
413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                      data_expr_lo)));
414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      data_expr_lo = IRExpr_RdTmp(tmp);
415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ty_data_expr = Ity_I64;
416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (size == sizeof(HWord)
419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && (ty_data_expr == Ity_I32 || ty_data_expr == Ity_I64))
420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* No conversion necessary */
422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp widen_op;
424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (Ity_I1 <= ty_data_expr
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && ty_data_expr
427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             < Ity_I1 + sizeof(u_widen_irop)/sizeof(u_widen_irop[0]))
428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         widen_op = u_widen_irop[ty_data_expr - Ity_I1][sizeof(HWord)];
430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!widen_op)
431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            widen_op = Iop_INVALID;
432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         widen_op = Iop_INVALID;
434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (widen_op != Iop_INVALID) {
436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tmp;
437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Widen the integer expression to a HWord */
439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = newIRTemp(bb->tyenv, sizeof(HWord) == 4 ? Ity_I32 : Ity_I64);
440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addStmtToIRSB(bb,
441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       IRStmt_WrTmp(tmp, IRExpr_Unop(widen_op, data_expr_lo)));
442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         data_expr_lo = IRExpr_RdTmp(tmp);
443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else if (size > sizeof(HWord) && !data_expr_hi
444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 && ty_data_expr == Ity_I64) {
445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tmp;
446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tl_assert(sizeof(HWord) == 4);
448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tl_assert(size == 8);
449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = newIRTemp(bb->tyenv, Ity_I32);
450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addStmtToIRSB(bb,
451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       IRStmt_WrTmp(tmp,
452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    IRExpr_Unop(Iop_64HIto32, data_expr_lo)));
453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         data_expr_hi = IRExpr_RdTmp(tmp);
454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmp = newIRTemp(bb->tyenv, Ity_I32);
455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addStmtToIRSB(bb, IRStmt_WrTmp(tmp,
456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        IRExpr_Unop(Iop_64to32, data_expr_lo)));
457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         data_expr_lo = IRExpr_RdTmp(tmp);
458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         data_expr_lo = mkIRExpr_HWord(0);
460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRDirty* di
463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     = unsafeIRDirty_0_N(/*regparms*/3,
464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         "drd_trace_mem_store",
465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         VG_(fnptr_to_fnentry)(drd_trace_mem_store),
466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         mkIRExprVec_4(addr_expr, mkIRExpr_HWord(size),
467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       data_expr_hi ? data_expr_hi
468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       : mkIRExpr_HWord(0), data_expr_lo));
469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard) di->guard = guard;
470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addStmtToIRSB(bb, IRStmt_Dirty(di) );
471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void instrument_load(IRSB* const bb, IRExpr* const addr_expr,
474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            const HWord size,
475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            IRExpr* const guard/* NULL => True */)
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* size_expr;
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** argv;
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size)
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1:
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_load_1",
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_load_1),
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 2:
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_load_2",
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_load_2),
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 4:
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_load_4",
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_load_4),
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 8:
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_load_8",
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_load_8),
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size_expr = mkIRExpr_HWord(size);
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_2(addr_expr, size_expr);
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/2,
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_load",
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(DRD_(trace_load)),
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard) di->guard = guard;
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB(bb, IRStmt_Dirty(di));
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void instrument_store(IRSB* const bb, IRExpr* addr_expr,
528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             IRExpr* const data_expr,
529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             IRExpr* const guard_expr/* NULL => True */)
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* size_expr;
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** argv;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HWord size;
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   size = sizeofIRType(typeOfIRExpr(bb->tyenv, data_expr));
537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (UNLIKELY(DRD_(any_address_is_traced)())) {
539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTemp tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addr_expr = IRExpr_RdTmp(tmp);
542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      instr_trace_mem_store(bb, addr_expr, NULL, data_expr, guard_expr);
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size)
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1:
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_store_1",
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_store_1),
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 2:
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_store_2",
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_store_2),
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 4:
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_store_4",
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_store_4),
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 8:
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_1(addr_expr);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/1,
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_store_8",
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(drd_trace_store_8),
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size_expr = mkIRExpr_HWord(size);
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = mkIRExprVec_2(addr_expr, size_expr);
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N(/*regparms*/2,
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             "drd_trace_store",
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             VG_(fnptr_to_fnentry)(DRD_(trace_store)),
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             argv);
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard_expr) di->guard = guard_expr;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB(bb, IRStmt_Dirty(di));
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* DRD_(instrument)(VgCallbackClosure* const closure,
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRSB* const bb_in,
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VexGuestLayout* const layout,
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VexGuestExtents* const vge,
595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       VexArchInfo* archinfo_host,
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRType const gWordTy,
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRType const hWordTy)
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*    bb;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** argv;
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     instrument = True;
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up BB */
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb           = emptyIRSB();
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->next     = deepCopyIRExpr(bb_in->next);
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bb->jumpkind = bb_in->jumpkind;
610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   bb->offsIP   = bb_in->offsIP;
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb_in->stmts_used; i++)
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRStmt* const st = bb_in->stmts[i];
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isFlatIRStmt(st));
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag)
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: the code for not instrumenting the code in .plt          */
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is because on this platform dynamic library symbols are   */
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* relocated in another way than by later binutils versions. The  */
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            != Vg_SectPLT;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (st->Ist.MBE.event)
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Imbe_Fence:
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break; /* not interesting */
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(0);
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (instrument)
645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            instrument_store(bb, st->Ist.Store.addr, st->Ist.Store.data,
646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             NULL/* no guard */);
647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addStmtToIRSB(bb, st);
648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg   = st->Ist.StoreG.details;
652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr*   data = sg->data;
653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr*   addr = sg->addr;
654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (instrument)
655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            instrument_store(bb, addr, data, sg->guard);
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg        = st->Ist.LoadG.details;
662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRType   type      = Ity_INVALID; /* loaded type */
663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRType   typeWide  = Ity_INVALID; /* after implicit widening */
664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr*  addr_expr = lg->addr;
665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tl_assert(type != Ity_INVALID);
667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (UNLIKELY(DRD_(any_address_is_traced)())) {
668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addr_expr = instr_trace_mem_load(bb, addr_expr,
669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             sizeofIRType(type), lg->guard);
670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         instrument_load(bb, lg->addr,
672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         sizeofIRType(type), lg->guard);
673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addStmtToIRSB(bb, st);
674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (instrument) {
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const IRExpr* const data = st->Ist.WrTmp.data;
680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRExpr* addr_expr = data->Iex.Load.addr;
681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (data->tag == Iex_Load) {
682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (UNLIKELY(DRD_(any_address_is_traced)())) {
683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  addr_expr = instr_trace_mem_load(bb, addr_expr,
684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       sizeofIRType(data->Iex.Load.ty),
685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       NULL/* no guard */);
686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               }
687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               instrument_load(bb, addr_expr, sizeofIRType(data->Iex.Load.ty),
688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                               NULL/* no guard */);
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (instrument) {
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRDirty* d = st->Ist.Dirty.details;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IREffect const mFx = d->mFx;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (mFx) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ifx_None:
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ifx_Read:
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ifx_Write:
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ifx_Modify:
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(d->mAddr);
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(d->mSize > 0);
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (mFx == Ifx_Read || mFx == Ifx_Modify) {
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di = unsafeIRDirty_0_N(
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          /*regparms*/2,
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "drd_trace_load",
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(fnptr_to_fnentry)(DRD_(trace_load)),
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          argv);
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  addStmtToIRSB(bb, IRStmt_Dirty(di));
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (mFx == Ifx_Write || mFx == Ifx_Modify)
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               {
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  di = unsafeIRDirty_0_N(
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          /*regparms*/2,
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "drd_trace_store",
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(fnptr_to_fnentry)(DRD_(trace_store)),
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          argv);
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  addStmtToIRSB(bb, IRStmt_Dirty(di));
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(0);
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (instrument) {
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * Treat compare-and-swap as a read. By handling atomic
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * instructions as read instructions no data races are reported
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * between conflicting atomic operations nor between atomic
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * operations and non-atomic reads. Conflicts between atomic
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * operations and non-atomic write operations are still reported
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * however.
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             */
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int    dataSize;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRCAS* cas = st->Ist.CAS.details;
744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(cas->addr != NULL);
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(cas->dataLo != NULL);
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (cas->dataHi != NULL)
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataSize *= 2; /* since it's a doubleword-CAS */
750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (UNLIKELY(DRD_(any_address_is_traced)()))
752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               instr_trace_mem_store(bb, cas->addr, cas->dataHi, cas->dataLo,
753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     NULL/* no guard */);
754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            instrument_load(bb, cas->addr, dataSize, NULL/*no guard*/);
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC: {
761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*
762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          * Ignore store-conditionals (except for tracing), and handle
763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          * load-linked's exactly like normal loads.
764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          */
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType dataTy;
766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (st->Ist.LLSC.storedata == NULL) {
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* LL */
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (instrument) {
771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRExpr* addr_expr = st->Ist.LLSC.addr;
772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (UNLIKELY(DRD_(any_address_is_traced)()))
773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  addr_expr = instr_trace_mem_load(bb, addr_expr,
774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                   sizeofIRType(dataTy),
775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                   NULL /* no guard */);
776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               instrument_load(bb, addr_expr, sizeofIRType(dataTy),
778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                               NULL/*no guard*/);
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* SC */
782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            instr_trace_mem_store(bb, st->Ist.LLSC.addr, NULL,
783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  st->Ist.LLSC.storedata,
784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  NULL/* no guard */);
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* None of these can contain any memory references. */
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addStmtToIRSB(bb, st);
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bb;
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
808