blob: 2b6d6f50266219d513374e3b0f35e497701d07ab [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
bart09dc13f2009-02-14 15:13:31 +00002/*
bart86562bd2009-02-16 19:43:56 +00003 This file is part of drd, a thread error detector.
bart09dc13f2009-02-14 15:13:31 +00004
sewardj9eecbbb2010-05-03 21:37:12 +00005 Copyright (C) 2006-2010 Bart Van Assche <bart.vanassche@gmail.com>.
bart09dc13f2009-02-14 15:13:31 +00006
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
26#include "drd_bitmap.h"
27#include "drd_thread_bitmap.h"
bart41b226c2009-02-14 16:55:19 +000028#include "drd_vc.h" /* DRD_(vc_snprint)() */
bart09dc13f2009-02-14 15:13:31 +000029
30/* Include several source files here in order to allow the compiler to */
31/* do more inlining. */
32#include "drd_bitmap.c"
33#include "drd_load_store.h"
34#include "drd_segment.c"
35#include "drd_thread.c"
36#include "drd_vc.c"
37#include "libvex_guest_offsets.h"
38
39
40/* STACK_POINTER_OFFSET: VEX register offset for the stack pointer register. */
41#if defined(VGA_x86)
42#define STACK_POINTER_OFFSET OFFSET_x86_ESP
43#elif defined(VGA_amd64)
44#define STACK_POINTER_OFFSET OFFSET_amd64_RSP
45#elif defined(VGA_ppc32)
sewardj4cb6bf72010-01-01 18:31:41 +000046#define STACK_POINTER_OFFSET OFFSET_ppc32_GPR1
bart09dc13f2009-02-14 15:13:31 +000047#elif defined(VGA_ppc64)
sewardj4cb6bf72010-01-01 18:31:41 +000048#define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
49#elif defined(VGA_arm)
50#define STACK_POINTER_OFFSET OFFSET_arm_R13
bart09dc13f2009-02-14 15:13:31 +000051#else
52#error Unknown architecture.
53#endif
54
55
56/* Local variables. */
57
bartf98a5692009-05-03 17:17:37 +000058static Bool s_check_stack_accesses = False;
59static Bool s_first_race_only = False;
bart09dc13f2009-02-14 15:13:31 +000060
61
62/* Function definitions. */
63
64Bool DRD_(get_check_stack_accesses)()
65{
bartf98a5692009-05-03 17:17:37 +000066 return s_check_stack_accesses;
bart09dc13f2009-02-14 15:13:31 +000067}
68
69void DRD_(set_check_stack_accesses)(const Bool c)
70{
bartbedfd232009-03-26 19:07:15 +000071 tl_assert(c == False || c == True);
bartf98a5692009-05-03 17:17:37 +000072 s_check_stack_accesses = c;
73}
74
75Bool DRD_(get_first_race_only)()
76{
77 return s_first_race_only;
78}
79
80void DRD_(set_first_race_only)(const Bool fro)
81{
82 tl_assert(fro == False || fro == True);
83 s_first_race_only = fro;
bart09dc13f2009-02-14 15:13:31 +000084}
85
bart1335ecc2009-02-14 16:10:53 +000086void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bartbedfd232009-03-26 19:07:15 +000087 const BmAccessTypeT access_type)
bart09dc13f2009-02-14 15:13:31 +000088{
bartbedfd232009-03-26 19:07:15 +000089 if (DRD_(is_any_traced)(addr, addr + size))
90 {
bart8f822af2009-06-08 18:20:42 +000091 char* vc;
92
93 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bartbedfd232009-03-26 19:07:15 +000094 VG_(message)(Vg_UserMsg,
bart63c92ea2009-07-19 17:53:56 +000095 "%s 0x%lx size %ld (thread %d / vc %s)\n",
bartbedfd232009-03-26 19:07:15 +000096 access_type == eLoad
97 ? "load "
98 : access_type == eStore
99 ? "store"
100 : access_type == eStart
101 ? "start"
102 : access_type == eEnd
103 ? "end "
104 : "????",
105 addr,
106 size,
bartbedfd232009-03-26 19:07:15 +0000107 DRD_(thread_get_running_tid)(),
108 vc);
bart8f822af2009-06-08 18:20:42 +0000109 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000110 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
111 VG_(clo_backtrace_size));
112 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
113 == VG_(get_running_tid)());
114 }
bart09dc13f2009-02-14 15:13:31 +0000115}
116
bart07595032010-08-29 09:51:06 +0000117static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000118{
bartbedfd232009-03-26 19:07:15 +0000119 return DRD_(trace_mem_access)(addr, size, eLoad);
bart09dc13f2009-02-14 15:13:31 +0000120}
121
bart07595032010-08-29 09:51:06 +0000122static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000123{
bartbedfd232009-03-26 19:07:15 +0000124 return DRD_(trace_mem_access)(addr, size, eStore);
bart09dc13f2009-02-14 15:13:31 +0000125}
126
127static void drd_report_race(const Addr addr, const SizeT size,
128 const BmAccessTypeT access_type)
129{
bartbedfd232009-03-26 19:07:15 +0000130 DataRaceErrInfo drei;
bart09dc13f2009-02-14 15:13:31 +0000131
bartbedfd232009-03-26 19:07:15 +0000132 drei.tid = DRD_(thread_get_running_tid)();
133 drei.addr = addr;
134 drei.size = size;
135 drei.access_type = access_type;
136 VG_(maybe_record_error)(VG_(get_running_tid)(),
137 DataRaceErr,
138 VG_(get_IP)(VG_(get_running_tid)()),
139 "Conflicting accesses",
140 &drei);
bartf98a5692009-05-03 17:17:37 +0000141
142 if (s_first_race_only)
143 {
144 DRD_(start_suppression)(addr, addr + size, "first race only");
145 }
bart09dc13f2009-02-14 15:13:31 +0000146}
147
bart99edb292009-02-15 15:59:20 +0000148VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000149{
150#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000151 /* The assert below has been commented out because of performance reasons.*/
152 tl_assert(thread_get_running_tid()
153 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000154#endif
155
bartd45d9952009-05-31 18:53:54 +0000156 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000157 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000158 || ! DRD_(thread_address_on_stack)(addr))
159 && bm_access_load_triggers_conflict(addr, addr + size)
160 && ! DRD_(is_suppressed)(addr, addr + size))
161 {
162 drd_report_race(addr, size, eLoad);
163 }
bart09dc13f2009-02-14 15:13:31 +0000164}
165
166static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
167{
bartd45d9952009-05-31 18:53:54 +0000168 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000169 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000170 || ! DRD_(thread_address_on_stack)(addr))
171 && bm_access_load_1_triggers_conflict(addr)
172 && ! DRD_(is_suppressed)(addr, addr + 1))
173 {
174 drd_report_race(addr, 1, eLoad);
175 }
bart09dc13f2009-02-14 15:13:31 +0000176}
177
178static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
179{
bartd45d9952009-05-31 18:53:54 +0000180 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000181 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000182 || ! DRD_(thread_address_on_stack)(addr))
183 && bm_access_load_2_triggers_conflict(addr)
184 && ! DRD_(is_suppressed)(addr, addr + 2))
185 {
186 drd_report_race(addr, 2, eLoad);
187 }
bart09dc13f2009-02-14 15:13:31 +0000188}
189
190static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
191{
bartd45d9952009-05-31 18:53:54 +0000192 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000193 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000194 || ! DRD_(thread_address_on_stack)(addr))
195 && bm_access_load_4_triggers_conflict(addr)
196 && ! DRD_(is_suppressed)(addr, addr + 4))
197 {
198 drd_report_race(addr, 4, eLoad);
199 }
bart09dc13f2009-02-14 15:13:31 +0000200}
201
202static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
203{
bartd45d9952009-05-31 18:53:54 +0000204 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000205 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000206 || ! DRD_(thread_address_on_stack)(addr))
207 && bm_access_load_8_triggers_conflict(addr)
208 && ! DRD_(is_suppressed)(addr, addr + 8))
209 {
210 drd_report_race(addr, 8, eLoad);
211 }
bart09dc13f2009-02-14 15:13:31 +0000212}
213
bart99edb292009-02-15 15:59:20 +0000214VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000215{
216#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000217 /* The assert below has been commented out because of performance reasons.*/
218 tl_assert(thread_get_running_tid()
219 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000220#endif
221
bartd45d9952009-05-31 18:53:54 +0000222 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000223 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000224 || ! DRD_(thread_address_on_stack)(addr))
225 && bm_access_store_triggers_conflict(addr, addr + size)
226 && ! DRD_(is_suppressed)(addr, addr + size))
227 {
228 drd_report_race(addr, size, eStore);
229 }
bart09dc13f2009-02-14 15:13:31 +0000230}
231
232static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
233{
bartd45d9952009-05-31 18:53:54 +0000234 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000235 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000236 || ! DRD_(thread_address_on_stack)(addr))
237 && bm_access_store_1_triggers_conflict(addr)
238 && ! DRD_(is_suppressed)(addr, addr + 1))
239 {
240 drd_report_race(addr, 1, eStore);
241 }
bart09dc13f2009-02-14 15:13:31 +0000242}
243
244static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
245{
bartd45d9952009-05-31 18:53:54 +0000246 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000247 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000248 || ! DRD_(thread_address_on_stack)(addr))
249 && bm_access_store_2_triggers_conflict(addr)
250 && ! DRD_(is_suppressed)(addr, addr + 2))
251 {
252 drd_report_race(addr, 2, eStore);
253 }
bart09dc13f2009-02-14 15:13:31 +0000254}
255
256static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
257{
bartd45d9952009-05-31 18:53:54 +0000258 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000259 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000260 || ! DRD_(thread_address_on_stack)(addr))
261 && bm_access_store_4_triggers_conflict(addr)
262 && ! DRD_(is_suppressed)(addr, addr + 4))
263 {
264 drd_report_race(addr, 4, eStore);
265 }
bart09dc13f2009-02-14 15:13:31 +0000266}
267
268static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
269{
bartd45d9952009-05-31 18:53:54 +0000270 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000271 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000272 || ! DRD_(thread_address_on_stack)(addr))
273 && bm_access_store_8_triggers_conflict(addr)
274 && ! DRD_(is_suppressed)(addr, addr + 8))
275 {
276 drd_report_race(addr, 8, eStore);
277 }
bart09dc13f2009-02-14 15:13:31 +0000278}
279
280/**
281 * Return true if and only if addr_expr matches the pattern (SP) or
282 * <offset>(SP).
283 */
284static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
285{
bartbedfd232009-03-26 19:07:15 +0000286 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000287
bartbedfd232009-03-26 19:07:15 +0000288 if (addr_expr->tag == Iex_RdTmp)
289 {
290 int i;
291 for (i = 0; i < bb->stmts_size; i++)
bart09dc13f2009-02-14 15:13:31 +0000292 {
bartbedfd232009-03-26 19:07:15 +0000293 if (bb->stmts[i]
294 && bb->stmts[i]->tag == Ist_WrTmp
295 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
296 {
297 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
298 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
299 {
300 result = True;
301 }
bart09dc13f2009-02-14 15:13:31 +0000302
bartbedfd232009-03-26 19:07:15 +0000303 //ppIRExpr(e);
304 //VG_(printf)(" (%s)\n", result ? "True" : "False");
305 break;
306 }
bart09dc13f2009-02-14 15:13:31 +0000307 }
bartbedfd232009-03-26 19:07:15 +0000308 }
309 return result;
bart09dc13f2009-02-14 15:13:31 +0000310}
311
312static void instrument_load(IRSB* const bb,
313 IRExpr* const addr_expr,
314 const HWord size)
315{
bartbedfd232009-03-26 19:07:15 +0000316 IRExpr* size_expr;
317 IRExpr** argv;
318 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000319
bartbedfd232009-03-26 19:07:15 +0000320 if (UNLIKELY(DRD_(any_address_is_traced)()))
321 {
322 addStmtToIRSB(bb,
323 IRStmt_Dirty(
324 unsafeIRDirty_0_N(/*regparms*/2,
325 "drd_trace_load",
326 VG_(fnptr_to_fnentry)
bart07595032010-08-29 09:51:06 +0000327 (drd_trace_mem_load),
bartbedfd232009-03-26 19:07:15 +0000328 mkIRExprVec_2(addr_expr,
329 mkIRExpr_HWord(size)))));
330 }
bart09dc13f2009-02-14 15:13:31 +0000331
bartf98a5692009-05-03 17:17:37 +0000332 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000333 return;
bart09dc13f2009-02-14 15:13:31 +0000334
bartbedfd232009-03-26 19:07:15 +0000335 switch (size)
336 {
337 case 1:
338 argv = mkIRExprVec_1(addr_expr);
339 di = unsafeIRDirty_0_N(/*regparms*/1,
340 "drd_trace_load_1",
341 VG_(fnptr_to_fnentry)(drd_trace_load_1),
342 argv);
343 break;
344 case 2:
345 argv = mkIRExprVec_1(addr_expr);
346 di = unsafeIRDirty_0_N(/*regparms*/1,
347 "drd_trace_load_2",
348 VG_(fnptr_to_fnentry)(drd_trace_load_2),
349 argv);
350 break;
351 case 4:
352 argv = mkIRExprVec_1(addr_expr);
353 di = unsafeIRDirty_0_N(/*regparms*/1,
354 "drd_trace_load_4",
355 VG_(fnptr_to_fnentry)(drd_trace_load_4),
356 argv);
357 break;
358 case 8:
359 argv = mkIRExprVec_1(addr_expr);
360 di = unsafeIRDirty_0_N(/*regparms*/1,
361 "drd_trace_load_8",
362 VG_(fnptr_to_fnentry)(drd_trace_load_8),
363 argv);
364 break;
365 default:
366 size_expr = mkIRExpr_HWord(size);
367 argv = mkIRExprVec_2(addr_expr, size_expr);
368 di = unsafeIRDirty_0_N(/*regparms*/2,
369 "drd_trace_load",
370 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
371 argv);
372 break;
373 }
374 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000375}
376
377static void instrument_store(IRSB* const bb,
378 IRExpr* const addr_expr,
379 const HWord size)
380{
bartbedfd232009-03-26 19:07:15 +0000381 IRExpr* size_expr;
382 IRExpr** argv;
383 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000384
bartbedfd232009-03-26 19:07:15 +0000385 if (UNLIKELY(DRD_(any_address_is_traced)()))
386 {
387 addStmtToIRSB(bb,
388 IRStmt_Dirty(
389 unsafeIRDirty_0_N(/*regparms*/2,
390 "drd_trace_store",
391 VG_(fnptr_to_fnentry)
bart07595032010-08-29 09:51:06 +0000392 (drd_trace_mem_store),
bartbedfd232009-03-26 19:07:15 +0000393 mkIRExprVec_2(addr_expr,
394 mkIRExpr_HWord(size)))));
395 }
bart09dc13f2009-02-14 15:13:31 +0000396
bartf98a5692009-05-03 17:17:37 +0000397 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000398 return;
bart09dc13f2009-02-14 15:13:31 +0000399
bartbedfd232009-03-26 19:07:15 +0000400 switch (size)
401 {
402 case 1:
403 argv = mkIRExprVec_1(addr_expr);
404 di = unsafeIRDirty_0_N(/*regparms*/1,
405 "drd_trace_store_1",
406 VG_(fnptr_to_fnentry)(drd_trace_store_1),
407 argv);
408 break;
409 case 2:
410 argv = mkIRExprVec_1(addr_expr);
411 di = unsafeIRDirty_0_N(/*regparms*/1,
412 "drd_trace_store_2",
413 VG_(fnptr_to_fnentry)(drd_trace_store_2),
414 argv);
415 break;
416 case 4:
417 argv = mkIRExprVec_1(addr_expr);
418 di = unsafeIRDirty_0_N(/*regparms*/1,
419 "drd_trace_store_4",
420 VG_(fnptr_to_fnentry)(drd_trace_store_4),
421 argv);
422 break;
423 case 8:
424 argv = mkIRExprVec_1(addr_expr);
425 di = unsafeIRDirty_0_N(/*regparms*/1,
426 "drd_trace_store_8",
427 VG_(fnptr_to_fnentry)(drd_trace_store_8),
428 argv);
429 break;
430 default:
431 size_expr = mkIRExpr_HWord(size);
432 argv = mkIRExprVec_2(addr_expr, size_expr);
433 di = unsafeIRDirty_0_N(/*regparms*/2,
434 "drd_trace_store",
435 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
436 argv);
437 break;
438 }
439 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000440}
441
bart1335ecc2009-02-14 16:10:53 +0000442IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000443 IRSB* const bb_in,
444 VexGuestLayout* const layout,
bart31b983d2010-02-21 14:52:59 +0000445 VexGuestExtents* const vge,
bartbedfd232009-03-26 19:07:15 +0000446 IRType const gWordTy,
447 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000448{
bartbedfd232009-03-26 19:07:15 +0000449 IRDirty* di;
450 Int i;
451 IRSB* bb;
452 IRExpr** argv;
453 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000454
bartbedfd232009-03-26 19:07:15 +0000455 /* Set up BB */
456 bb = emptyIRSB();
457 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
458 bb->next = deepCopyIRExpr(bb_in->next);
459 bb->jumpkind = bb_in->jumpkind;
bart09dc13f2009-02-14 15:13:31 +0000460
bartbedfd232009-03-26 19:07:15 +0000461 for (i = 0; i < bb_in->stmts_used; i++)
462 {
463 IRStmt* const st = bb_in->stmts[i];
464 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000465 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000466
bartbedfd232009-03-26 19:07:15 +0000467 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000468 {
bartbedfd232009-03-26 19:07:15 +0000469 /* Note: the code for not instrumenting the code in .plt */
470 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
471 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
472 /* This is because on this platform dynamic library symbols are */
473 /* relocated in another way than by later binutils versions. The */
474 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
475 case Ist_IMark:
sewardje3f1e592009-07-31 09:41:29 +0000476 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000477 != Vg_SectPLT;
478 addStmtToIRSB(bb, st);
479 break;
480
481 case Ist_MBE:
482 switch (st->Ist.MBE.event)
483 {
484 case Imbe_Fence:
485 break; /* not interesting */
bartbedfd232009-03-26 19:07:15 +0000486 default:
487 tl_assert(0);
488 }
489 addStmtToIRSB(bb, st);
490 break;
491
492 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000493 if (instrument)
bartbedfd232009-03-26 19:07:15 +0000494 {
495 instrument_store(bb,
496 st->Ist.Store.addr,
497 sizeofIRType(typeOfIRExpr(bb->tyenv,
498 st->Ist.Store.data)));
499 }
500 addStmtToIRSB(bb, st);
501 break;
502
503 case Ist_WrTmp:
504 if (instrument)
505 {
506 const IRExpr* const data = st->Ist.WrTmp.data;
507 if (data->tag == Iex_Load)
508 {
509 instrument_load(bb,
510 data->Iex.Load.addr,
511 sizeofIRType(data->Iex.Load.ty));
512 }
513 }
514 addStmtToIRSB(bb, st);
515 break;
516
517 case Ist_Dirty:
518 if (instrument)
519 {
520 IRDirty* d = st->Ist.Dirty.details;
521 IREffect const mFx = d->mFx;
522 switch (mFx) {
523 case Ifx_None:
524 break;
525 case Ifx_Read:
526 case Ifx_Write:
527 case Ifx_Modify:
528 tl_assert(d->mAddr);
529 tl_assert(d->mSize > 0);
530 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
531 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
532 di = unsafeIRDirty_0_N(
533 /*regparms*/2,
534 "drd_trace_load",
535 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
536 argv);
537 addStmtToIRSB(bb, IRStmt_Dirty(di));
538 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000539 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000540 {
541 di = unsafeIRDirty_0_N(
542 /*regparms*/2,
543 "drd_trace_store",
544 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
545 argv);
546 addStmtToIRSB(bb, IRStmt_Dirty(di));
547 }
548 break;
549 default:
550 tl_assert(0);
551 }
552 }
553 addStmtToIRSB(bb, st);
554 break;
555
sewardj1c0ce7a2009-07-01 08:10:49 +0000556 case Ist_CAS:
557 if (instrument)
558 {
barta14e3282009-07-11 14:35:59 +0000559 /*
560 * Treat compare-and-swap as a read. By handling atomic
561 * instructions as read instructions no data races are reported
562 * between conflicting atomic operations nor between atomic
563 * operations and non-atomic reads. Conflicts between atomic
564 * operations and non-atomic write operations are still reported
565 * however.
566 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000567 Int dataSize;
568 IRCAS* cas = st->Ist.CAS.details;
569 tl_assert(cas->addr != NULL);
570 tl_assert(cas->dataLo != NULL);
571 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
572 if (cas->dataHi != NULL)
573 dataSize *= 2; /* since it's a doubleword-CAS */
574 instrument_load(bb, cas->addr, dataSize);
575 }
576 addStmtToIRSB(bb, st);
577 break;
578
sewardjdb5907d2009-11-26 17:20:21 +0000579 case Ist_LLSC: {
580 /* Ignore store-conditionals, and handle load-linked's
581 exactly like normal loads. */
582 IRType dataTy;
583 if (st->Ist.LLSC.storedata == NULL)
584 {
585 /* LL */
586 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
587 if (instrument) {
588 instrument_load(bb,
589 st->Ist.LLSC.addr,
590 sizeofIRType(dataTy));
591 }
592 }
593 else
594 {
595 /* SC */
596 /*ignore */
597 }
bartbedfd232009-03-26 19:07:15 +0000598 addStmtToIRSB(bb, st);
599 break;
bart09dc13f2009-02-14 15:13:31 +0000600 }
sewardjdb5907d2009-11-26 17:20:21 +0000601
602 case Ist_NoOp:
603 case Ist_AbiHint:
604 case Ist_Put:
605 case Ist_PutI:
606 case Ist_Exit:
607 /* None of these can contain any memory references. */
608 addStmtToIRSB(bb, st);
609 break;
610
611 default:
612 ppIRStmt(st);
613 tl_assert(0);
614 }
bartbedfd232009-03-26 19:07:15 +0000615 }
bart09dc13f2009-02-14 15:13:31 +0000616
bartbedfd232009-03-26 19:07:15 +0000617 return bb;
bart09dc13f2009-02-14 15:13:31 +0000618}
619