blob: d5cf75dc5114352b16494f1d2bff855318900a86 [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
5 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
6
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)
46#define STACK_POINTER_OFFSET ((OFFSET_ppc32_GPR0 + OFFSET_ppc32_GPR2) / 2)
47#elif defined(VGA_ppc64)
48#define STACK_POINTER_OFFSET ((OFFSET_ppc64_GPR0 + OFFSET_ppc64_GPR2) / 2)
49#else
50#error Unknown architecture.
51#endif
52
53
54/* Local variables. */
55
bartf98a5692009-05-03 17:17:37 +000056static Bool s_check_stack_accesses = False;
57static Bool s_first_race_only = False;
bart09dc13f2009-02-14 15:13:31 +000058
59
60/* Function definitions. */
61
62Bool DRD_(get_check_stack_accesses)()
63{
bartf98a5692009-05-03 17:17:37 +000064 return s_check_stack_accesses;
bart09dc13f2009-02-14 15:13:31 +000065}
66
67void DRD_(set_check_stack_accesses)(const Bool c)
68{
bartbedfd232009-03-26 19:07:15 +000069 tl_assert(c == False || c == True);
bartf98a5692009-05-03 17:17:37 +000070 s_check_stack_accesses = c;
71}
72
73Bool DRD_(get_first_race_only)()
74{
75 return s_first_race_only;
76}
77
78void DRD_(set_first_race_only)(const Bool fro)
79{
80 tl_assert(fro == False || fro == True);
81 s_first_race_only = fro;
bart09dc13f2009-02-14 15:13:31 +000082}
83
bart1335ecc2009-02-14 16:10:53 +000084void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bartbedfd232009-03-26 19:07:15 +000085 const BmAccessTypeT access_type)
bart09dc13f2009-02-14 15:13:31 +000086{
bartbedfd232009-03-26 19:07:15 +000087 if (DRD_(is_any_traced)(addr, addr + size))
88 {
bart8f822af2009-06-08 18:20:42 +000089 char* vc;
90
91 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bartbedfd232009-03-26 19:07:15 +000092 VG_(message)(Vg_UserMsg,
bart63c92ea2009-07-19 17:53:56 +000093 "%s 0x%lx size %ld (thread %d / vc %s)\n",
bartbedfd232009-03-26 19:07:15 +000094 access_type == eLoad
95 ? "load "
96 : access_type == eStore
97 ? "store"
98 : access_type == eStart
99 ? "start"
100 : access_type == eEnd
101 ? "end "
102 : "????",
103 addr,
104 size,
bartbedfd232009-03-26 19:07:15 +0000105 DRD_(thread_get_running_tid)(),
106 vc);
bart8f822af2009-06-08 18:20:42 +0000107 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000108 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
109 VG_(clo_backtrace_size));
110 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
111 == VG_(get_running_tid)());
112 }
bart09dc13f2009-02-14 15:13:31 +0000113}
114
115static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
116{
bartbedfd232009-03-26 19:07:15 +0000117 return DRD_(trace_mem_access)(addr, size, eLoad);
bart09dc13f2009-02-14 15:13:31 +0000118}
119
120static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
121{
bartbedfd232009-03-26 19:07:15 +0000122 return DRD_(trace_mem_access)(addr, size, eStore);
bart09dc13f2009-02-14 15:13:31 +0000123}
124
125static void drd_report_race(const Addr addr, const SizeT size,
126 const BmAccessTypeT access_type)
127{
bartbedfd232009-03-26 19:07:15 +0000128 DataRaceErrInfo drei;
bart09dc13f2009-02-14 15:13:31 +0000129
bartbedfd232009-03-26 19:07:15 +0000130 drei.tid = DRD_(thread_get_running_tid)();
131 drei.addr = addr;
132 drei.size = size;
133 drei.access_type = access_type;
134 VG_(maybe_record_error)(VG_(get_running_tid)(),
135 DataRaceErr,
136 VG_(get_IP)(VG_(get_running_tid)()),
137 "Conflicting accesses",
138 &drei);
bartf98a5692009-05-03 17:17:37 +0000139
140 if (s_first_race_only)
141 {
142 DRD_(start_suppression)(addr, addr + size, "first race only");
143 }
bart09dc13f2009-02-14 15:13:31 +0000144}
145
bart99edb292009-02-15 15:59:20 +0000146VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000147{
148#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000149 /* The assert below has been commented out because of performance reasons.*/
150 tl_assert(thread_get_running_tid()
151 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000152#endif
153
bartd45d9952009-05-31 18:53:54 +0000154 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000155 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000156 || ! DRD_(thread_address_on_stack)(addr))
157 && bm_access_load_triggers_conflict(addr, addr + size)
158 && ! DRD_(is_suppressed)(addr, addr + size))
159 {
160 drd_report_race(addr, size, eLoad);
161 }
bart09dc13f2009-02-14 15:13:31 +0000162}
163
164static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
165{
bartd45d9952009-05-31 18:53:54 +0000166 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000167 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000168 || ! DRD_(thread_address_on_stack)(addr))
169 && bm_access_load_1_triggers_conflict(addr)
170 && ! DRD_(is_suppressed)(addr, addr + 1))
171 {
172 drd_report_race(addr, 1, eLoad);
173 }
bart09dc13f2009-02-14 15:13:31 +0000174}
175
176static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
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_2_triggers_conflict(addr)
182 && ! DRD_(is_suppressed)(addr, addr + 2))
183 {
184 drd_report_race(addr, 2, eLoad);
185 }
bart09dc13f2009-02-14 15:13:31 +0000186}
187
188static VG_REGPARM(1) void drd_trace_load_4(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_4_triggers_conflict(addr)
194 && ! DRD_(is_suppressed)(addr, addr + 4))
195 {
196 drd_report_race(addr, 4, eLoad);
197 }
bart09dc13f2009-02-14 15:13:31 +0000198}
199
200static VG_REGPARM(1) void drd_trace_load_8(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_8_triggers_conflict(addr)
206 && ! DRD_(is_suppressed)(addr, addr + 8))
207 {
208 drd_report_race(addr, 8, eLoad);
209 }
bart09dc13f2009-02-14 15:13:31 +0000210}
211
bart99edb292009-02-15 15:59:20 +0000212VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000213{
214#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000215 /* The assert below has been commented out because of performance reasons.*/
216 tl_assert(thread_get_running_tid()
217 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000218#endif
219
bartd45d9952009-05-31 18:53:54 +0000220 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000221 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000222 || ! DRD_(thread_address_on_stack)(addr))
223 && bm_access_store_triggers_conflict(addr, addr + size)
224 && ! DRD_(is_suppressed)(addr, addr + size))
225 {
226 drd_report_race(addr, size, eStore);
227 }
bart09dc13f2009-02-14 15:13:31 +0000228}
229
230static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
231{
bartd45d9952009-05-31 18:53:54 +0000232 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000233 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000234 || ! DRD_(thread_address_on_stack)(addr))
235 && bm_access_store_1_triggers_conflict(addr)
236 && ! DRD_(is_suppressed)(addr, addr + 1))
237 {
238 drd_report_race(addr, 1, eStore);
239 }
bart09dc13f2009-02-14 15:13:31 +0000240}
241
242static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
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_2_triggers_conflict(addr)
248 && ! DRD_(is_suppressed)(addr, addr + 2))
249 {
250 drd_report_race(addr, 2, eStore);
251 }
bart09dc13f2009-02-14 15:13:31 +0000252}
253
254static VG_REGPARM(1) void drd_trace_store_4(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_4_triggers_conflict(addr)
260 && ! DRD_(is_suppressed)(addr, addr + 4))
261 {
262 drd_report_race(addr, 4, eStore);
263 }
bart09dc13f2009-02-14 15:13:31 +0000264}
265
266static VG_REGPARM(1) void drd_trace_store_8(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_8_triggers_conflict(addr)
272 && ! DRD_(is_suppressed)(addr, addr + 8))
273 {
274 drd_report_race(addr, 8, eStore);
275 }
bart09dc13f2009-02-14 15:13:31 +0000276}
277
278/**
279 * Return true if and only if addr_expr matches the pattern (SP) or
280 * <offset>(SP).
281 */
282static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
283{
bartbedfd232009-03-26 19:07:15 +0000284 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000285
bartbedfd232009-03-26 19:07:15 +0000286 if (addr_expr->tag == Iex_RdTmp)
287 {
288 int i;
289 for (i = 0; i < bb->stmts_size; i++)
bart09dc13f2009-02-14 15:13:31 +0000290 {
bartbedfd232009-03-26 19:07:15 +0000291 if (bb->stmts[i]
292 && bb->stmts[i]->tag == Ist_WrTmp
293 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
294 {
295 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
296 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
297 {
298 result = True;
299 }
bart09dc13f2009-02-14 15:13:31 +0000300
bartbedfd232009-03-26 19:07:15 +0000301 //ppIRExpr(e);
302 //VG_(printf)(" (%s)\n", result ? "True" : "False");
303 break;
304 }
bart09dc13f2009-02-14 15:13:31 +0000305 }
bartbedfd232009-03-26 19:07:15 +0000306 }
307 return result;
bart09dc13f2009-02-14 15:13:31 +0000308}
309
310static void instrument_load(IRSB* const bb,
311 IRExpr* const addr_expr,
312 const HWord size)
313{
bartbedfd232009-03-26 19:07:15 +0000314 IRExpr* size_expr;
315 IRExpr** argv;
316 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000317
bartbedfd232009-03-26 19:07:15 +0000318 if (UNLIKELY(DRD_(any_address_is_traced)()))
319 {
320 addStmtToIRSB(bb,
321 IRStmt_Dirty(
322 unsafeIRDirty_0_N(/*regparms*/2,
323 "drd_trace_load",
324 VG_(fnptr_to_fnentry)
325 (drd_trace_mem_load),
326 mkIRExprVec_2(addr_expr,
327 mkIRExpr_HWord(size)))));
328 }
bart09dc13f2009-02-14 15:13:31 +0000329
bartf98a5692009-05-03 17:17:37 +0000330 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000331 return;
bart09dc13f2009-02-14 15:13:31 +0000332
bartbedfd232009-03-26 19:07:15 +0000333 switch (size)
334 {
335 case 1:
336 argv = mkIRExprVec_1(addr_expr);
337 di = unsafeIRDirty_0_N(/*regparms*/1,
338 "drd_trace_load_1",
339 VG_(fnptr_to_fnentry)(drd_trace_load_1),
340 argv);
341 break;
342 case 2:
343 argv = mkIRExprVec_1(addr_expr);
344 di = unsafeIRDirty_0_N(/*regparms*/1,
345 "drd_trace_load_2",
346 VG_(fnptr_to_fnentry)(drd_trace_load_2),
347 argv);
348 break;
349 case 4:
350 argv = mkIRExprVec_1(addr_expr);
351 di = unsafeIRDirty_0_N(/*regparms*/1,
352 "drd_trace_load_4",
353 VG_(fnptr_to_fnentry)(drd_trace_load_4),
354 argv);
355 break;
356 case 8:
357 argv = mkIRExprVec_1(addr_expr);
358 di = unsafeIRDirty_0_N(/*regparms*/1,
359 "drd_trace_load_8",
360 VG_(fnptr_to_fnentry)(drd_trace_load_8),
361 argv);
362 break;
363 default:
364 size_expr = mkIRExpr_HWord(size);
365 argv = mkIRExprVec_2(addr_expr, size_expr);
366 di = unsafeIRDirty_0_N(/*regparms*/2,
367 "drd_trace_load",
368 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
369 argv);
370 break;
371 }
372 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000373}
374
375static void instrument_store(IRSB* const bb,
376 IRExpr* const addr_expr,
377 const HWord size)
378{
bartbedfd232009-03-26 19:07:15 +0000379 IRExpr* size_expr;
380 IRExpr** argv;
381 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000382
bartbedfd232009-03-26 19:07:15 +0000383 if (UNLIKELY(DRD_(any_address_is_traced)()))
384 {
385 addStmtToIRSB(bb,
386 IRStmt_Dirty(
387 unsafeIRDirty_0_N(/*regparms*/2,
388 "drd_trace_store",
389 VG_(fnptr_to_fnentry)
390 (drd_trace_mem_store),
391 mkIRExprVec_2(addr_expr,
392 mkIRExpr_HWord(size)))));
393 }
bart09dc13f2009-02-14 15:13:31 +0000394
bartf98a5692009-05-03 17:17:37 +0000395 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000396 return;
bart09dc13f2009-02-14 15:13:31 +0000397
bartbedfd232009-03-26 19:07:15 +0000398 switch (size)
399 {
400 case 1:
401 argv = mkIRExprVec_1(addr_expr);
402 di = unsafeIRDirty_0_N(/*regparms*/1,
403 "drd_trace_store_1",
404 VG_(fnptr_to_fnentry)(drd_trace_store_1),
405 argv);
406 break;
407 case 2:
408 argv = mkIRExprVec_1(addr_expr);
409 di = unsafeIRDirty_0_N(/*regparms*/1,
410 "drd_trace_store_2",
411 VG_(fnptr_to_fnentry)(drd_trace_store_2),
412 argv);
413 break;
414 case 4:
415 argv = mkIRExprVec_1(addr_expr);
416 di = unsafeIRDirty_0_N(/*regparms*/1,
417 "drd_trace_store_4",
418 VG_(fnptr_to_fnentry)(drd_trace_store_4),
419 argv);
420 break;
421 case 8:
422 argv = mkIRExprVec_1(addr_expr);
423 di = unsafeIRDirty_0_N(/*regparms*/1,
424 "drd_trace_store_8",
425 VG_(fnptr_to_fnentry)(drd_trace_store_8),
426 argv);
427 break;
428 default:
429 size_expr = mkIRExpr_HWord(size);
430 argv = mkIRExprVec_2(addr_expr, size_expr);
431 di = unsafeIRDirty_0_N(/*regparms*/2,
432 "drd_trace_store",
433 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
434 argv);
435 break;
436 }
437 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000438}
439
bart1335ecc2009-02-14 16:10:53 +0000440IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000441 IRSB* const bb_in,
442 VexGuestLayout* const layout,
443 VexGuestExtents* const vge,
444 IRType const gWordTy,
445 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000446{
bartbedfd232009-03-26 19:07:15 +0000447 IRDirty* di;
448 Int i;
449 IRSB* bb;
450 IRExpr** argv;
451 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000452
bartbedfd232009-03-26 19:07:15 +0000453 /* Set up BB */
454 bb = emptyIRSB();
455 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
456 bb->next = deepCopyIRExpr(bb_in->next);
457 bb->jumpkind = bb_in->jumpkind;
bart09dc13f2009-02-14 15:13:31 +0000458
bartbedfd232009-03-26 19:07:15 +0000459 for (i = 0; i < bb_in->stmts_used; i++)
460 {
461 IRStmt* const st = bb_in->stmts[i];
462 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000463 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000464
bartbedfd232009-03-26 19:07:15 +0000465 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000466 {
bartbedfd232009-03-26 19:07:15 +0000467 /* Note: the code for not instrumenting the code in .plt */
468 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
469 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
470 /* This is because on this platform dynamic library symbols are */
471 /* relocated in another way than by later binutils versions. The */
472 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
473 case Ist_IMark:
sewardje3f1e592009-07-31 09:41:29 +0000474 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000475 != Vg_SectPLT;
476 addStmtToIRSB(bb, st);
477 break;
478
479 case Ist_MBE:
480 switch (st->Ist.MBE.event)
481 {
482 case Imbe_Fence:
483 break; /* not interesting */
bartbedfd232009-03-26 19:07:15 +0000484 default:
485 tl_assert(0);
486 }
487 addStmtToIRSB(bb, st);
488 break;
489
490 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000491 if (instrument)
bartbedfd232009-03-26 19:07:15 +0000492 {
493 instrument_store(bb,
494 st->Ist.Store.addr,
495 sizeofIRType(typeOfIRExpr(bb->tyenv,
496 st->Ist.Store.data)));
497 }
498 addStmtToIRSB(bb, st);
499 break;
500
501 case Ist_WrTmp:
502 if (instrument)
503 {
504 const IRExpr* const data = st->Ist.WrTmp.data;
505 if (data->tag == Iex_Load)
506 {
507 instrument_load(bb,
508 data->Iex.Load.addr,
509 sizeofIRType(data->Iex.Load.ty));
510 }
511 }
512 addStmtToIRSB(bb, st);
513 break;
514
515 case Ist_Dirty:
516 if (instrument)
517 {
518 IRDirty* d = st->Ist.Dirty.details;
519 IREffect const mFx = d->mFx;
520 switch (mFx) {
521 case Ifx_None:
522 break;
523 case Ifx_Read:
524 case Ifx_Write:
525 case Ifx_Modify:
526 tl_assert(d->mAddr);
527 tl_assert(d->mSize > 0);
528 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
529 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
530 di = unsafeIRDirty_0_N(
531 /*regparms*/2,
532 "drd_trace_load",
533 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
534 argv);
535 addStmtToIRSB(bb, IRStmt_Dirty(di));
536 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000537 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000538 {
539 di = unsafeIRDirty_0_N(
540 /*regparms*/2,
541 "drd_trace_store",
542 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
543 argv);
544 addStmtToIRSB(bb, IRStmt_Dirty(di));
545 }
546 break;
547 default:
548 tl_assert(0);
549 }
550 }
551 addStmtToIRSB(bb, st);
552 break;
553
sewardj1c0ce7a2009-07-01 08:10:49 +0000554 case Ist_CAS:
555 if (instrument)
556 {
barta14e3282009-07-11 14:35:59 +0000557 /*
558 * Treat compare-and-swap as a read. By handling atomic
559 * instructions as read instructions no data races are reported
560 * between conflicting atomic operations nor between atomic
561 * operations and non-atomic reads. Conflicts between atomic
562 * operations and non-atomic write operations are still reported
563 * however.
564 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000565 Int dataSize;
566 IRCAS* cas = st->Ist.CAS.details;
567 tl_assert(cas->addr != NULL);
568 tl_assert(cas->dataLo != NULL);
569 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
570 if (cas->dataHi != NULL)
571 dataSize *= 2; /* since it's a doubleword-CAS */
572 instrument_load(bb, cas->addr, dataSize);
573 }
574 addStmtToIRSB(bb, st);
575 break;
576
sewardjdb5907d2009-11-26 17:20:21 +0000577 case Ist_LLSC: {
578 /* Ignore store-conditionals, and handle load-linked's
579 exactly like normal loads. */
580 IRType dataTy;
581 if (st->Ist.LLSC.storedata == NULL)
582 {
583 /* LL */
584 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
585 if (instrument) {
586 instrument_load(bb,
587 st->Ist.LLSC.addr,
588 sizeofIRType(dataTy));
589 }
590 }
591 else
592 {
593 /* SC */
594 /*ignore */
595 }
bartbedfd232009-03-26 19:07:15 +0000596 addStmtToIRSB(bb, st);
597 break;
bart09dc13f2009-02-14 15:13:31 +0000598 }
sewardjdb5907d2009-11-26 17:20:21 +0000599
600 case Ist_NoOp:
601 case Ist_AbiHint:
602 case Ist_Put:
603 case Ist_PutI:
604 case Ist_Exit:
605 /* None of these can contain any memory references. */
606 addStmtToIRSB(bb, st);
607 break;
608
609 default:
610 ppIRStmt(st);
611 tl_assert(0);
612 }
bartbedfd232009-03-26 19:07:15 +0000613 }
bart09dc13f2009-02-14 15:13:31 +0000614
bartbedfd232009-03-26 19:07:15 +0000615 return bb;
bart09dc13f2009-02-14 15:13:31 +0000616}
617