blob: 996ee611736b9ac8f63b595d2d93b18a21f1de01 [file] [log] [blame]
bart09dc13f2009-02-14 15:13:31 +00001/*
bart86562bd2009-02-16 19:43:56 +00002 This file is part of drd, a thread error detector.
bart09dc13f2009-02-14 15:13:31 +00003
bart922304f2011-03-13 12:02:44 +00004 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
bart09dc13f2009-02-14 15:13:31 +00005
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307, USA.
20
21 The GNU General Public License is contained in the file COPYING.
22*/
23
24
25#include "drd_bitmap.h"
26#include "drd_thread_bitmap.h"
bart41b226c2009-02-14 16:55:19 +000027#include "drd_vc.h" /* DRD_(vc_snprint)() */
bart09dc13f2009-02-14 15:13:31 +000028
29/* Include several source files here in order to allow the compiler to */
30/* do more inlining. */
31#include "drd_bitmap.c"
32#include "drd_load_store.h"
33#include "drd_segment.c"
34#include "drd_thread.c"
35#include "drd_vc.c"
36#include "libvex_guest_offsets.h"
37
38
39/* STACK_POINTER_OFFSET: VEX register offset for the stack pointer register. */
40#if defined(VGA_x86)
41#define STACK_POINTER_OFFSET OFFSET_x86_ESP
42#elif defined(VGA_amd64)
43#define STACK_POINTER_OFFSET OFFSET_amd64_RSP
44#elif defined(VGA_ppc32)
sewardj4cb6bf72010-01-01 18:31:41 +000045#define STACK_POINTER_OFFSET OFFSET_ppc32_GPR1
bart09dc13f2009-02-14 15:13:31 +000046#elif defined(VGA_ppc64)
sewardj4cb6bf72010-01-01 18:31:41 +000047#define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
48#elif defined(VGA_arm)
49#define STACK_POINTER_OFFSET OFFSET_arm_R13
sewardjb5b87402011-03-07 16:05:35 +000050#elif defined(VGA_s390x)
51#define STACK_POINTER_OFFSET OFFSET_s390x_r15
bart09dc13f2009-02-14 15:13:31 +000052#else
53#error Unknown architecture.
54#endif
55
56
57/* Local variables. */
58
bartf98a5692009-05-03 17:17:37 +000059static Bool s_check_stack_accesses = False;
60static Bool s_first_race_only = False;
bart09dc13f2009-02-14 15:13:31 +000061
62
63/* Function definitions. */
64
65Bool DRD_(get_check_stack_accesses)()
66{
bartf98a5692009-05-03 17:17:37 +000067 return s_check_stack_accesses;
bart09dc13f2009-02-14 15:13:31 +000068}
69
70void DRD_(set_check_stack_accesses)(const Bool c)
71{
bartbedfd232009-03-26 19:07:15 +000072 tl_assert(c == False || c == True);
bartf98a5692009-05-03 17:17:37 +000073 s_check_stack_accesses = c;
74}
75
76Bool DRD_(get_first_race_only)()
77{
78 return s_first_race_only;
79}
80
81void DRD_(set_first_race_only)(const Bool fro)
82{
83 tl_assert(fro == False || fro == True);
84 s_first_race_only = fro;
bart09dc13f2009-02-14 15:13:31 +000085}
86
bart1335ecc2009-02-14 16:10:53 +000087void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bart7826acb2011-12-11 18:49:39 +000088 const BmAccessTypeT access_type,
bart42f32632011-12-13 11:12:05 +000089 const HWord stored_value_hi,
90 const HWord stored_value_lo)
bart09dc13f2009-02-14 15:13:31 +000091{
bartbedfd232009-03-26 19:07:15 +000092 if (DRD_(is_any_traced)(addr, addr + size))
93 {
bart8f822af2009-06-08 18:20:42 +000094 char* vc;
95
96 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bart7826acb2011-12-11 18:49:39 +000097 if (access_type == eStore && size <= sizeof(HWord)) {
bart5cda1b52011-12-12 19:37:10 +000098 DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %ld/0x%lx (thread %d /"
bart42f32632011-12-13 11:12:05 +000099 " vc %s)", addr, size, stored_value_lo,
100 stored_value_lo, DRD_(thread_get_running_tid)(),
101 vc);
102 } else if (access_type == eStore && size > sizeof(HWord)) {
103 ULong sv;
104
105 tl_assert(sizeof(HWord) == 4);
106 sv = ((ULong)stored_value_hi << 32) | stored_value_lo;
107 DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %lld/0x%llx (thread %d"
108 " / vc %s)", addr, size, sv, sv,
bart7826acb2011-12-11 18:49:39 +0000109 DRD_(thread_get_running_tid)(), vc);
110 } else {
111 DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
112 access_type == eLoad ? "load "
113 : access_type == eStore ? "store"
114 : access_type == eStart ? "start"
115 : access_type == eEnd ? "end " : "????",
116 addr, size, DRD_(thread_get_running_tid)(), vc);
117 }
bart8f822af2009-06-08 18:20:42 +0000118 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000119 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
120 == VG_(get_running_tid)());
121 }
bart09dc13f2009-02-14 15:13:31 +0000122}
123
bart07595032010-08-29 09:51:06 +0000124static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000125{
bart42f32632011-12-13 11:12:05 +0000126 return DRD_(trace_mem_access)(addr, size, eLoad, 0, 0);
bart09dc13f2009-02-14 15:13:31 +0000127}
128
bart7826acb2011-12-11 18:49:39 +0000129static VG_REGPARM(3) void drd_trace_mem_store(const Addr addr,const SizeT size,
bart42f32632011-12-13 11:12:05 +0000130 const HWord stored_value_hi,
131 const HWord stored_value_lo)
bart09dc13f2009-02-14 15:13:31 +0000132{
bart42f32632011-12-13 11:12:05 +0000133 return DRD_(trace_mem_access)(addr, size, eStore, stored_value_hi,
134 stored_value_lo);
bart09dc13f2009-02-14 15:13:31 +0000135}
136
137static void drd_report_race(const Addr addr, const SizeT size,
138 const BmAccessTypeT access_type)
139{
bart7a9db0f2012-04-01 14:40:16 +0000140 ThreadId vg_tid;
bart09dc13f2009-02-14 15:13:31 +0000141
bart7a9db0f2012-04-01 14:40:16 +0000142 vg_tid = VG_(get_running_tid)();
bart7886dd32012-04-01 15:06:57 +0000143 if (!DRD_(get_check_stack_accesses)()
144 && DRD_(thread_address_on_any_stack)(addr)) {
bart7a9db0f2012-04-01 14:40:16 +0000145#if 0
146 GenericErrInfo GEI = {
147 .tid = DRD_(thread_get_running_tid)(),
148 .addr = addr,
149 };
150 VG_(maybe_record_error)(vg_tid, GenericErr, VG_(get_IP)(vg_tid),
151 "--check-stack-var=no skips checking stack"
152 " variables shared over threads",
153 &GEI);
154#endif
155 } else {
156 DataRaceErrInfo drei = {
157 .tid = DRD_(thread_get_running_tid)(),
158 .addr = addr,
159 .size = size,
160 .access_type = access_type,
161 };
162 VG_(maybe_record_error)(vg_tid, DataRaceErr, VG_(get_IP)(vg_tid),
163 "Conflicting access", &drei);
bartf98a5692009-05-03 17:17:37 +0000164
bart7a9db0f2012-04-01 14:40:16 +0000165 if (s_first_race_only)
166 DRD_(start_suppression)(addr, addr + size, "first race only");
bartf98a5692009-05-03 17:17:37 +0000167 }
bart09dc13f2009-02-14 15:13:31 +0000168}
169
bart99edb292009-02-15 15:59:20 +0000170VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000171{
172#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000173 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000174 tl_assert(DRD_(thread_get_running_tid)()
175 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000176#endif
177
bartd45d9952009-05-31 18:53:54 +0000178 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000179 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000180 || ! DRD_(thread_address_on_stack)(addr))
181 && bm_access_load_triggers_conflict(addr, addr + size)
182 && ! DRD_(is_suppressed)(addr, addr + size))
183 {
184 drd_report_race(addr, size, eLoad);
185 }
bart09dc13f2009-02-14 15:13:31 +0000186}
187
188static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
189{
bartd45d9952009-05-31 18:53:54 +0000190 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000191 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000192 || ! DRD_(thread_address_on_stack)(addr))
193 && bm_access_load_1_triggers_conflict(addr)
194 && ! DRD_(is_suppressed)(addr, addr + 1))
195 {
196 drd_report_race(addr, 1, eLoad);
197 }
bart09dc13f2009-02-14 15:13:31 +0000198}
199
200static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
201{
bartd45d9952009-05-31 18:53:54 +0000202 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000203 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000204 || ! DRD_(thread_address_on_stack)(addr))
205 && bm_access_load_2_triggers_conflict(addr)
206 && ! DRD_(is_suppressed)(addr, addr + 2))
207 {
208 drd_report_race(addr, 2, eLoad);
209 }
bart09dc13f2009-02-14 15:13:31 +0000210}
211
212static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
213{
bartd45d9952009-05-31 18:53:54 +0000214 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000215 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000216 || ! DRD_(thread_address_on_stack)(addr))
217 && bm_access_load_4_triggers_conflict(addr)
218 && ! DRD_(is_suppressed)(addr, addr + 4))
219 {
220 drd_report_race(addr, 4, eLoad);
221 }
bart09dc13f2009-02-14 15:13:31 +0000222}
223
224static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
225{
bartd45d9952009-05-31 18:53:54 +0000226 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000227 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000228 || ! DRD_(thread_address_on_stack)(addr))
229 && bm_access_load_8_triggers_conflict(addr)
230 && ! DRD_(is_suppressed)(addr, addr + 8))
231 {
232 drd_report_race(addr, 8, eLoad);
233 }
bart09dc13f2009-02-14 15:13:31 +0000234}
235
bart99edb292009-02-15 15:59:20 +0000236VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000237{
238#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000239 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000240 tl_assert(DRD_(thread_get_running_tid)()
241 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000242#endif
243
bartd45d9952009-05-31 18:53:54 +0000244 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000245 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000246 || ! DRD_(thread_address_on_stack)(addr))
247 && bm_access_store_triggers_conflict(addr, addr + size)
248 && ! DRD_(is_suppressed)(addr, addr + size))
249 {
250 drd_report_race(addr, size, eStore);
251 }
bart09dc13f2009-02-14 15:13:31 +0000252}
253
254static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
255{
bartd45d9952009-05-31 18:53:54 +0000256 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000257 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000258 || ! DRD_(thread_address_on_stack)(addr))
259 && bm_access_store_1_triggers_conflict(addr)
260 && ! DRD_(is_suppressed)(addr, addr + 1))
261 {
262 drd_report_race(addr, 1, eStore);
263 }
bart09dc13f2009-02-14 15:13:31 +0000264}
265
266static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
267{
bartd45d9952009-05-31 18:53:54 +0000268 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000269 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000270 || ! DRD_(thread_address_on_stack)(addr))
271 && bm_access_store_2_triggers_conflict(addr)
272 && ! DRD_(is_suppressed)(addr, addr + 2))
273 {
274 drd_report_race(addr, 2, eStore);
275 }
bart09dc13f2009-02-14 15:13:31 +0000276}
277
278static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
279{
bartd45d9952009-05-31 18:53:54 +0000280 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000281 && (s_check_stack_accesses
bart71ce1322011-12-11 17:54:17 +0000282 || !DRD_(thread_address_on_stack)(addr))
bartbedfd232009-03-26 19:07:15 +0000283 && bm_access_store_4_triggers_conflict(addr)
bart71ce1322011-12-11 17:54:17 +0000284 && !DRD_(is_suppressed)(addr, addr + 4))
bartbedfd232009-03-26 19:07:15 +0000285 {
286 drd_report_race(addr, 4, eStore);
287 }
bart09dc13f2009-02-14 15:13:31 +0000288}
289
290static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
291{
bartd45d9952009-05-31 18:53:54 +0000292 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000293 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000294 || ! DRD_(thread_address_on_stack)(addr))
295 && bm_access_store_8_triggers_conflict(addr)
296 && ! DRD_(is_suppressed)(addr, addr + 8))
297 {
298 drd_report_race(addr, 8, eStore);
299 }
bart09dc13f2009-02-14 15:13:31 +0000300}
301
302/**
303 * Return true if and only if addr_expr matches the pattern (SP) or
304 * <offset>(SP).
305 */
306static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
307{
bartbedfd232009-03-26 19:07:15 +0000308 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000309
bartbedfd232009-03-26 19:07:15 +0000310 if (addr_expr->tag == Iex_RdTmp)
311 {
312 int i;
313 for (i = 0; i < bb->stmts_size; i++)
bart09dc13f2009-02-14 15:13:31 +0000314 {
bartbedfd232009-03-26 19:07:15 +0000315 if (bb->stmts[i]
316 && bb->stmts[i]->tag == Ist_WrTmp
317 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
318 {
319 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
320 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
321 {
322 result = True;
323 }
bart09dc13f2009-02-14 15:13:31 +0000324
bartbedfd232009-03-26 19:07:15 +0000325 //ppIRExpr(e);
326 //VG_(printf)(" (%s)\n", result ? "True" : "False");
327 break;
328 }
bart09dc13f2009-02-14 15:13:31 +0000329 }
bartbedfd232009-03-26 19:07:15 +0000330 }
331 return result;
bart09dc13f2009-02-14 15:13:31 +0000332}
333
bartea692152011-12-11 20:17:57 +0000334static const IROp u_widen_irop[5][9] = {
bart9ad8d802011-12-12 19:54:32 +0000335 [Ity_I1 - Ity_I1] = { [4] = Iop_1Uto32, [8] = Iop_1Uto64 },
336 [Ity_I8 - Ity_I1] = { [4] = Iop_8Uto32, [8] = Iop_8Uto64 },
337 [Ity_I16 - Ity_I1] = { [4] = Iop_16Uto32, [8] = Iop_16Uto64 },
338 [Ity_I32 - Ity_I1] = { [8] = Iop_32Uto64 },
bartea692152011-12-11 20:17:57 +0000339};
340
bartb63dc782011-12-12 19:18:26 +0000341/**
342 * Instrument the client code to trace a memory load (--trace-addr).
343 */
bart25026ef2011-12-17 12:59:45 +0000344static IRExpr* instr_trace_mem_load(IRSB* const bb, IRExpr* addr_expr,
345 const HWord size)
bartea692152011-12-11 20:17:57 +0000346{
bart25026ef2011-12-17 12:59:45 +0000347 IRTemp tmp;
348
349 tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
350 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
351 addr_expr = IRExpr_RdTmp(tmp);
352
bartb63dc782011-12-12 19:18:26 +0000353 addStmtToIRSB(bb,
354 IRStmt_Dirty(
355 unsafeIRDirty_0_N(/*regparms*/2,
356 "drd_trace_mem_load",
357 VG_(fnptr_to_fnentry)
358 (drd_trace_mem_load),
359 mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)))));
bart25026ef2011-12-17 12:59:45 +0000360
361 return addr_expr;
bartb63dc782011-12-12 19:18:26 +0000362}
363
364/**
365 * Instrument the client code to trace a memory store (--trace-addr).
366 */
367static void instr_trace_mem_store(IRSB* const bb, IRExpr* const addr_expr,
bart42f32632011-12-13 11:12:05 +0000368 IRExpr* data_expr_hi, IRExpr* data_expr_lo)
bartb63dc782011-12-12 19:18:26 +0000369{
370 IRType ty_data_expr;
bartea692152011-12-11 20:17:57 +0000371 HWord size;
372
bartb63dc782011-12-12 19:18:26 +0000373 tl_assert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
bart42f32632011-12-13 11:12:05 +0000374 tl_assert(!data_expr_hi || typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I32);
bartea692152011-12-11 20:17:57 +0000375
bart42f32632011-12-13 11:12:05 +0000376 ty_data_expr = typeOfIRExpr(bb->tyenv, data_expr_lo);
bartb63dc782011-12-12 19:18:26 +0000377 size = sizeofIRType(ty_data_expr);
378
bart7ca75ed2011-12-13 08:53:23 +0000379#if 0
380 // Test code
381 if (ty_data_expr == Ity_I32) {
382 IRTemp tmp = newIRTemp(bb->tyenv, Ity_F32);
bart42f32632011-12-13 11:12:05 +0000383 data_expr_lo = IRExpr_Unop(Iop_ReinterpI32asF32, data_expr_lo);
384 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
385 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000386 ty_data_expr = Ity_F32;
387 } else if (ty_data_expr == Ity_I64) {
388 IRTemp tmp = newIRTemp(bb->tyenv, Ity_F64);
bart42f32632011-12-13 11:12:05 +0000389 data_expr_lo = IRExpr_Unop(Iop_ReinterpI64asF64, data_expr_lo);
390 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
391 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000392 ty_data_expr = Ity_F64;
393 }
394#endif
395
396 if (ty_data_expr == Ity_F32) {
397 IRTemp tmp = newIRTemp(bb->tyenv, Ity_I32);
398 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF32asI32,
bart42f32632011-12-13 11:12:05 +0000399 data_expr_lo)));
400 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000401 ty_data_expr = Ity_I32;
402 } else if (ty_data_expr == Ity_F64) {
403 IRTemp tmp = newIRTemp(bb->tyenv, Ity_I64);
404 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF64asI64,
bart42f32632011-12-13 11:12:05 +0000405 data_expr_lo)));
406 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000407 ty_data_expr = Ity_I64;
408 }
409
bartb63dc782011-12-12 19:18:26 +0000410 if (size == sizeof(HWord)
411 && (ty_data_expr == Ity_I32 || ty_data_expr == Ity_I64))
412 {
413 /* No conversion necessary */
bartea692152011-12-11 20:17:57 +0000414 } else {
415 IROp widen_op;
416
bartb63dc782011-12-12 19:18:26 +0000417 if (Ity_I1 <= ty_data_expr
418 && ty_data_expr
419 < Ity_I1 + sizeof(u_widen_irop)/sizeof(u_widen_irop[0]))
420 {
421 widen_op = u_widen_irop[ty_data_expr - Ity_I1][sizeof(HWord)];
bartea692152011-12-11 20:17:57 +0000422 if (!widen_op)
423 widen_op = Iop_INVALID;
424 } else {
425 widen_op = Iop_INVALID;
426 }
427 if (widen_op != Iop_INVALID) {
428 IRTemp tmp;
429
bartb63dc782011-12-12 19:18:26 +0000430 /* Widen the integer expression to a HWord */
bartea692152011-12-11 20:17:57 +0000431 tmp = newIRTemp(bb->tyenv, sizeof(HWord) == 4 ? Ity_I32 : Ity_I64);
432 addStmtToIRSB(bb,
bart42f32632011-12-13 11:12:05 +0000433 IRStmt_WrTmp(tmp, IRExpr_Unop(widen_op, data_expr_lo)));
434 data_expr_lo = IRExpr_RdTmp(tmp);
435 } else if (size > sizeof(HWord) && !data_expr_hi
436 && ty_data_expr == Ity_I64) {
437 IRTemp tmp;
438
439 tl_assert(sizeof(HWord) == 4);
440 tl_assert(size == 8);
441 tmp = newIRTemp(bb->tyenv, Ity_I32);
442 addStmtToIRSB(bb,
443 IRStmt_WrTmp(tmp,
444 IRExpr_Unop(Iop_64HIto32, data_expr_lo)));
445 data_expr_hi = IRExpr_RdTmp(tmp);
446 tmp = newIRTemp(bb->tyenv, Ity_I32);
447 addStmtToIRSB(bb, IRStmt_WrTmp(tmp,
448 IRExpr_Unop(Iop_64to32, data_expr_lo)));
449 data_expr_lo = IRExpr_RdTmp(tmp);
bartea692152011-12-11 20:17:57 +0000450 } else {
bart42f32632011-12-13 11:12:05 +0000451 data_expr_lo = mkIRExpr_HWord(0);
bartea692152011-12-11 20:17:57 +0000452 }
453 }
454 addStmtToIRSB(bb,
455 IRStmt_Dirty(
456 unsafeIRDirty_0_N(/*regparms*/3,
457 "drd_trace_mem_store",
bart42f32632011-12-13 11:12:05 +0000458 VG_(fnptr_to_fnentry)(drd_trace_mem_store),
459 mkIRExprVec_4(addr_expr, mkIRExpr_HWord(size),
460 data_expr_hi ? data_expr_hi
461 : mkIRExpr_HWord(0), data_expr_lo))));
bartea692152011-12-11 20:17:57 +0000462}
463
464static void instrument_load(IRSB* const bb, IRExpr* const addr_expr,
bartb63dc782011-12-12 19:18:26 +0000465 const HWord size)
bart09dc13f2009-02-14 15:13:31 +0000466{
bartbedfd232009-03-26 19:07:15 +0000467 IRExpr* size_expr;
468 IRExpr** argv;
469 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000470
bartea692152011-12-11 20:17:57 +0000471 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000472 return;
bart09dc13f2009-02-14 15:13:31 +0000473
bartbedfd232009-03-26 19:07:15 +0000474 switch (size)
475 {
476 case 1:
477 argv = mkIRExprVec_1(addr_expr);
478 di = unsafeIRDirty_0_N(/*regparms*/1,
479 "drd_trace_load_1",
480 VG_(fnptr_to_fnentry)(drd_trace_load_1),
481 argv);
482 break;
483 case 2:
484 argv = mkIRExprVec_1(addr_expr);
485 di = unsafeIRDirty_0_N(/*regparms*/1,
486 "drd_trace_load_2",
487 VG_(fnptr_to_fnentry)(drd_trace_load_2),
488 argv);
489 break;
490 case 4:
491 argv = mkIRExprVec_1(addr_expr);
492 di = unsafeIRDirty_0_N(/*regparms*/1,
493 "drd_trace_load_4",
494 VG_(fnptr_to_fnentry)(drd_trace_load_4),
495 argv);
496 break;
497 case 8:
498 argv = mkIRExprVec_1(addr_expr);
499 di = unsafeIRDirty_0_N(/*regparms*/1,
500 "drd_trace_load_8",
501 VG_(fnptr_to_fnentry)(drd_trace_load_8),
502 argv);
503 break;
504 default:
505 size_expr = mkIRExpr_HWord(size);
506 argv = mkIRExprVec_2(addr_expr, size_expr);
507 di = unsafeIRDirty_0_N(/*regparms*/2,
508 "drd_trace_load",
509 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
510 argv);
511 break;
512 }
513 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000514}
515
bart25026ef2011-12-17 12:59:45 +0000516static void instrument_store(IRSB* const bb, IRExpr* addr_expr,
bart7826acb2011-12-11 18:49:39 +0000517 IRExpr* const data_expr)
bart09dc13f2009-02-14 15:13:31 +0000518{
bartbedfd232009-03-26 19:07:15 +0000519 IRExpr* size_expr;
520 IRExpr** argv;
521 IRDirty* di;
bart7826acb2011-12-11 18:49:39 +0000522 HWord size;
523
524 size = sizeofIRType(typeOfIRExpr(bb->tyenv, data_expr));
bart09dc13f2009-02-14 15:13:31 +0000525
bart25026ef2011-12-17 12:59:45 +0000526 if (UNLIKELY(DRD_(any_address_is_traced)())) {
527 IRTemp tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
528 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
529 addr_expr = IRExpr_RdTmp(tmp);
bart42f32632011-12-13 11:12:05 +0000530 instr_trace_mem_store(bb, addr_expr, NULL, data_expr);
bart25026ef2011-12-17 12:59:45 +0000531 }
bart09dc13f2009-02-14 15:13:31 +0000532
bart71ce1322011-12-11 17:54:17 +0000533 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000534 return;
bart09dc13f2009-02-14 15:13:31 +0000535
bartbedfd232009-03-26 19:07:15 +0000536 switch (size)
537 {
538 case 1:
539 argv = mkIRExprVec_1(addr_expr);
540 di = unsafeIRDirty_0_N(/*regparms*/1,
541 "drd_trace_store_1",
542 VG_(fnptr_to_fnentry)(drd_trace_store_1),
543 argv);
544 break;
545 case 2:
546 argv = mkIRExprVec_1(addr_expr);
547 di = unsafeIRDirty_0_N(/*regparms*/1,
548 "drd_trace_store_2",
549 VG_(fnptr_to_fnentry)(drd_trace_store_2),
550 argv);
551 break;
552 case 4:
553 argv = mkIRExprVec_1(addr_expr);
554 di = unsafeIRDirty_0_N(/*regparms*/1,
555 "drd_trace_store_4",
556 VG_(fnptr_to_fnentry)(drd_trace_store_4),
557 argv);
558 break;
559 case 8:
560 argv = mkIRExprVec_1(addr_expr);
561 di = unsafeIRDirty_0_N(/*regparms*/1,
562 "drd_trace_store_8",
563 VG_(fnptr_to_fnentry)(drd_trace_store_8),
564 argv);
565 break;
566 default:
567 size_expr = mkIRExpr_HWord(size);
568 argv = mkIRExprVec_2(addr_expr, size_expr);
569 di = unsafeIRDirty_0_N(/*regparms*/2,
570 "drd_trace_store",
571 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
572 argv);
573 break;
574 }
575 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000576}
577
bart1335ecc2009-02-14 16:10:53 +0000578IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000579 IRSB* const bb_in,
580 VexGuestLayout* const layout,
bart31b983d2010-02-21 14:52:59 +0000581 VexGuestExtents* const vge,
bartbedfd232009-03-26 19:07:15 +0000582 IRType const gWordTy,
583 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000584{
bartbedfd232009-03-26 19:07:15 +0000585 IRDirty* di;
586 Int i;
587 IRSB* bb;
588 IRExpr** argv;
589 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000590
bartbedfd232009-03-26 19:07:15 +0000591 /* Set up BB */
592 bb = emptyIRSB();
593 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
594 bb->next = deepCopyIRExpr(bb_in->next);
595 bb->jumpkind = bb_in->jumpkind;
bart09dc13f2009-02-14 15:13:31 +0000596
bartbedfd232009-03-26 19:07:15 +0000597 for (i = 0; i < bb_in->stmts_used; i++)
598 {
599 IRStmt* const st = bb_in->stmts[i];
600 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000601 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000602
bartbedfd232009-03-26 19:07:15 +0000603 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000604 {
bartbedfd232009-03-26 19:07:15 +0000605 /* Note: the code for not instrumenting the code in .plt */
606 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
607 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
608 /* This is because on this platform dynamic library symbols are */
609 /* relocated in another way than by later binutils versions. The */
610 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
611 case Ist_IMark:
sewardje3f1e592009-07-31 09:41:29 +0000612 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000613 != Vg_SectPLT;
614 addStmtToIRSB(bb, st);
615 break;
616
617 case Ist_MBE:
618 switch (st->Ist.MBE.event)
619 {
620 case Imbe_Fence:
621 break; /* not interesting */
bartbedfd232009-03-26 19:07:15 +0000622 default:
623 tl_assert(0);
624 }
625 addStmtToIRSB(bb, st);
626 break;
627
628 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000629 if (instrument)
bart7826acb2011-12-11 18:49:39 +0000630 instrument_store(bb, st->Ist.Store.addr, st->Ist.Store.data);
bartbedfd232009-03-26 19:07:15 +0000631 addStmtToIRSB(bb, st);
632 break;
633
634 case Ist_WrTmp:
bartea692152011-12-11 20:17:57 +0000635 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000636 const IRExpr* const data = st->Ist.WrTmp.data;
bart25026ef2011-12-17 12:59:45 +0000637 IRExpr* addr_expr = data->Iex.Load.addr;
bartb63dc782011-12-12 19:18:26 +0000638 if (data->tag == Iex_Load) {
bart25026ef2011-12-17 12:59:45 +0000639 if (UNLIKELY(DRD_(any_address_is_traced)())) {
640 addr_expr = instr_trace_mem_load(bb, addr_expr,
bartb63dc782011-12-12 19:18:26 +0000641 sizeofIRType(data->Iex.Load.ty));
bart25026ef2011-12-17 12:59:45 +0000642 }
bartea692152011-12-11 20:17:57 +0000643 instrument_load(bb, data->Iex.Load.addr,
bartb63dc782011-12-12 19:18:26 +0000644 sizeofIRType(data->Iex.Load.ty));
645 }
bartbedfd232009-03-26 19:07:15 +0000646 }
647 addStmtToIRSB(bb, st);
648 break;
649
650 case Ist_Dirty:
bartb63dc782011-12-12 19:18:26 +0000651 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000652 IRDirty* d = st->Ist.Dirty.details;
653 IREffect const mFx = d->mFx;
654 switch (mFx) {
655 case Ifx_None:
656 break;
657 case Ifx_Read:
658 case Ifx_Write:
659 case Ifx_Modify:
660 tl_assert(d->mAddr);
661 tl_assert(d->mSize > 0);
662 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
663 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
664 di = unsafeIRDirty_0_N(
665 /*regparms*/2,
666 "drd_trace_load",
667 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
668 argv);
669 addStmtToIRSB(bb, IRStmt_Dirty(di));
670 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000671 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000672 {
673 di = unsafeIRDirty_0_N(
674 /*regparms*/2,
675 "drd_trace_store",
676 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
677 argv);
678 addStmtToIRSB(bb, IRStmt_Dirty(di));
679 }
680 break;
681 default:
682 tl_assert(0);
683 }
684 }
685 addStmtToIRSB(bb, st);
686 break;
687
sewardj1c0ce7a2009-07-01 08:10:49 +0000688 case Ist_CAS:
bartb63dc782011-12-12 19:18:26 +0000689 if (instrument) {
barta14e3282009-07-11 14:35:59 +0000690 /*
691 * Treat compare-and-swap as a read. By handling atomic
692 * instructions as read instructions no data races are reported
693 * between conflicting atomic operations nor between atomic
694 * operations and non-atomic reads. Conflicts between atomic
695 * operations and non-atomic write operations are still reported
696 * however.
697 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000698 Int dataSize;
699 IRCAS* cas = st->Ist.CAS.details;
bartb63dc782011-12-12 19:18:26 +0000700
sewardj1c0ce7a2009-07-01 08:10:49 +0000701 tl_assert(cas->addr != NULL);
702 tl_assert(cas->dataLo != NULL);
703 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
704 if (cas->dataHi != NULL)
705 dataSize *= 2; /* since it's a doubleword-CAS */
bartb63dc782011-12-12 19:18:26 +0000706
bart42f32632011-12-13 11:12:05 +0000707 if (UNLIKELY(DRD_(any_address_is_traced)()))
708 instr_trace_mem_store(bb, cas->addr, cas->dataHi, cas->dataLo);
bartb63dc782011-12-12 19:18:26 +0000709
710 instrument_load(bb, cas->addr, dataSize);
sewardj1c0ce7a2009-07-01 08:10:49 +0000711 }
712 addStmtToIRSB(bb, st);
713 break;
714
sewardjdb5907d2009-11-26 17:20:21 +0000715 case Ist_LLSC: {
bartea692152011-12-11 20:17:57 +0000716 /*
717 * Ignore store-conditionals (except for tracing), and handle
718 * load-linked's exactly like normal loads.
719 */
sewardjdb5907d2009-11-26 17:20:21 +0000720 IRType dataTy;
bartb63dc782011-12-12 19:18:26 +0000721
bartea692152011-12-11 20:17:57 +0000722 if (st->Ist.LLSC.storedata == NULL) {
sewardjdb5907d2009-11-26 17:20:21 +0000723 /* LL */
724 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
bartb63dc782011-12-12 19:18:26 +0000725 if (instrument) {
bart25026ef2011-12-17 12:59:45 +0000726 IRExpr* addr_expr = st->Ist.LLSC.addr;
bartb63dc782011-12-12 19:18:26 +0000727 if (UNLIKELY(DRD_(any_address_is_traced)()))
bart25026ef2011-12-17 12:59:45 +0000728 addr_expr = instr_trace_mem_load(bb, addr_expr,
729 sizeofIRType(dataTy));
bartb63dc782011-12-12 19:18:26 +0000730
bart25026ef2011-12-17 12:59:45 +0000731 instrument_load(bb, addr_expr, sizeofIRType(dataTy));
bartb63dc782011-12-12 19:18:26 +0000732 }
bartea692152011-12-11 20:17:57 +0000733 } else {
sewardjdb5907d2009-11-26 17:20:21 +0000734 /* SC */
bart42f32632011-12-13 11:12:05 +0000735 instr_trace_mem_store(bb, st->Ist.LLSC.addr, NULL,
bartb63dc782011-12-12 19:18:26 +0000736 st->Ist.LLSC.storedata);
sewardjdb5907d2009-11-26 17:20:21 +0000737 }
bartbedfd232009-03-26 19:07:15 +0000738 addStmtToIRSB(bb, st);
739 break;
bart09dc13f2009-02-14 15:13:31 +0000740 }
sewardjdb5907d2009-11-26 17:20:21 +0000741
742 case Ist_NoOp:
743 case Ist_AbiHint:
744 case Ist_Put:
745 case Ist_PutI:
746 case Ist_Exit:
747 /* None of these can contain any memory references. */
748 addStmtToIRSB(bb, st);
749 break;
750
751 default:
752 ppIRStmt(st);
753 tl_assert(0);
754 }
bartbedfd232009-03-26 19:07:15 +0000755 }
bart09dc13f2009-02-14 15:13:31 +0000756
bartbedfd232009-03-26 19:07:15 +0000757 return bb;
bart09dc13f2009-02-14 15:13:31 +0000758}
759