blob: 9820da0c7e1f0797933c89b0f787feba06768e5d [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
bart876cafd2010-10-10 18:07:31 +00005 Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
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
sewardjb5b87402011-03-07 16:05:35 +000051#elif defined(VGA_s390x)
52#define STACK_POINTER_OFFSET OFFSET_s390x_r15
bart09dc13f2009-02-14 15:13:31 +000053#else
54#error Unknown architecture.
55#endif
56
57
58/* Local variables. */
59
bartf98a5692009-05-03 17:17:37 +000060static Bool s_check_stack_accesses = False;
61static Bool s_first_race_only = False;
bart09dc13f2009-02-14 15:13:31 +000062
63
64/* Function definitions. */
65
66Bool DRD_(get_check_stack_accesses)()
67{
bartf98a5692009-05-03 17:17:37 +000068 return s_check_stack_accesses;
bart09dc13f2009-02-14 15:13:31 +000069}
70
71void DRD_(set_check_stack_accesses)(const Bool c)
72{
bartbedfd232009-03-26 19:07:15 +000073 tl_assert(c == False || c == True);
bartf98a5692009-05-03 17:17:37 +000074 s_check_stack_accesses = c;
75}
76
77Bool DRD_(get_first_race_only)()
78{
79 return s_first_race_only;
80}
81
82void DRD_(set_first_race_only)(const Bool fro)
83{
84 tl_assert(fro == False || fro == True);
85 s_first_race_only = fro;
bart09dc13f2009-02-14 15:13:31 +000086}
87
bart1335ecc2009-02-14 16:10:53 +000088void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bartbedfd232009-03-26 19:07:15 +000089 const BmAccessTypeT access_type)
bart09dc13f2009-02-14 15:13:31 +000090{
bartbedfd232009-03-26 19:07:15 +000091 if (DRD_(is_any_traced)(addr, addr + size))
92 {
bart8f822af2009-06-08 18:20:42 +000093 char* vc;
94
95 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bartbedfd232009-03-26 19:07:15 +000096 VG_(message)(Vg_UserMsg,
bart63c92ea2009-07-19 17:53:56 +000097 "%s 0x%lx size %ld (thread %d / vc %s)\n",
bartbedfd232009-03-26 19:07:15 +000098 access_type == eLoad
99 ? "load "
100 : access_type == eStore
101 ? "store"
102 : access_type == eStart
103 ? "start"
104 : access_type == eEnd
105 ? "end "
106 : "????",
107 addr,
108 size,
bartbedfd232009-03-26 19:07:15 +0000109 DRD_(thread_get_running_tid)(),
110 vc);
bart8f822af2009-06-08 18:20:42 +0000111 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000112 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
113 VG_(clo_backtrace_size));
114 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
115 == VG_(get_running_tid)());
116 }
bart09dc13f2009-02-14 15:13:31 +0000117}
118
bart07595032010-08-29 09:51:06 +0000119static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000120{
bartbedfd232009-03-26 19:07:15 +0000121 return DRD_(trace_mem_access)(addr, size, eLoad);
bart09dc13f2009-02-14 15:13:31 +0000122}
123
bart07595032010-08-29 09:51:06 +0000124static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000125{
bartbedfd232009-03-26 19:07:15 +0000126 return DRD_(trace_mem_access)(addr, size, eStore);
bart09dc13f2009-02-14 15:13:31 +0000127}
128
129static void drd_report_race(const Addr addr, const SizeT size,
130 const BmAccessTypeT access_type)
131{
bartbedfd232009-03-26 19:07:15 +0000132 DataRaceErrInfo drei;
bart09dc13f2009-02-14 15:13:31 +0000133
bartbedfd232009-03-26 19:07:15 +0000134 drei.tid = DRD_(thread_get_running_tid)();
135 drei.addr = addr;
136 drei.size = size;
137 drei.access_type = access_type;
138 VG_(maybe_record_error)(VG_(get_running_tid)(),
139 DataRaceErr,
140 VG_(get_IP)(VG_(get_running_tid)()),
141 "Conflicting accesses",
142 &drei);
bartf98a5692009-05-03 17:17:37 +0000143
144 if (s_first_race_only)
145 {
146 DRD_(start_suppression)(addr, addr + size, "first race only");
147 }
bart09dc13f2009-02-14 15:13:31 +0000148}
149
bart99edb292009-02-15 15:59:20 +0000150VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000151{
152#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000153 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000154 tl_assert(DRD_(thread_get_running_tid)()
155 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000156#endif
157
bartd45d9952009-05-31 18:53:54 +0000158 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000159 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000160 || ! DRD_(thread_address_on_stack)(addr))
161 && bm_access_load_triggers_conflict(addr, addr + size)
162 && ! DRD_(is_suppressed)(addr, addr + size))
163 {
164 drd_report_race(addr, size, eLoad);
165 }
bart09dc13f2009-02-14 15:13:31 +0000166}
167
168static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
169{
bartd45d9952009-05-31 18:53:54 +0000170 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000171 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000172 || ! DRD_(thread_address_on_stack)(addr))
173 && bm_access_load_1_triggers_conflict(addr)
174 && ! DRD_(is_suppressed)(addr, addr + 1))
175 {
176 drd_report_race(addr, 1, eLoad);
177 }
bart09dc13f2009-02-14 15:13:31 +0000178}
179
180static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
181{
bartd45d9952009-05-31 18:53:54 +0000182 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000183 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000184 || ! DRD_(thread_address_on_stack)(addr))
185 && bm_access_load_2_triggers_conflict(addr)
186 && ! DRD_(is_suppressed)(addr, addr + 2))
187 {
188 drd_report_race(addr, 2, eLoad);
189 }
bart09dc13f2009-02-14 15:13:31 +0000190}
191
192static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
193{
bartd45d9952009-05-31 18:53:54 +0000194 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000195 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000196 || ! DRD_(thread_address_on_stack)(addr))
197 && bm_access_load_4_triggers_conflict(addr)
198 && ! DRD_(is_suppressed)(addr, addr + 4))
199 {
200 drd_report_race(addr, 4, eLoad);
201 }
bart09dc13f2009-02-14 15:13:31 +0000202}
203
204static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
205{
bartd45d9952009-05-31 18:53:54 +0000206 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000207 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000208 || ! DRD_(thread_address_on_stack)(addr))
209 && bm_access_load_8_triggers_conflict(addr)
210 && ! DRD_(is_suppressed)(addr, addr + 8))
211 {
212 drd_report_race(addr, 8, eLoad);
213 }
bart09dc13f2009-02-14 15:13:31 +0000214}
215
bart99edb292009-02-15 15:59:20 +0000216VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000217{
218#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000219 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000220 tl_assert(DRD_(thread_get_running_tid)()
221 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000222#endif
223
bartd45d9952009-05-31 18:53:54 +0000224 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000225 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000226 || ! DRD_(thread_address_on_stack)(addr))
227 && bm_access_store_triggers_conflict(addr, addr + size)
228 && ! DRD_(is_suppressed)(addr, addr + size))
229 {
230 drd_report_race(addr, size, eStore);
231 }
bart09dc13f2009-02-14 15:13:31 +0000232}
233
234static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
235{
bartd45d9952009-05-31 18:53:54 +0000236 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000237 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000238 || ! DRD_(thread_address_on_stack)(addr))
239 && bm_access_store_1_triggers_conflict(addr)
240 && ! DRD_(is_suppressed)(addr, addr + 1))
241 {
242 drd_report_race(addr, 1, eStore);
243 }
bart09dc13f2009-02-14 15:13:31 +0000244}
245
246static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
247{
bartd45d9952009-05-31 18:53:54 +0000248 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000249 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000250 || ! DRD_(thread_address_on_stack)(addr))
251 && bm_access_store_2_triggers_conflict(addr)
252 && ! DRD_(is_suppressed)(addr, addr + 2))
253 {
254 drd_report_race(addr, 2, eStore);
255 }
bart09dc13f2009-02-14 15:13:31 +0000256}
257
258static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
259{
bartd45d9952009-05-31 18:53:54 +0000260 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000261 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000262 || ! DRD_(thread_address_on_stack)(addr))
263 && bm_access_store_4_triggers_conflict(addr)
264 && ! DRD_(is_suppressed)(addr, addr + 4))
265 {
266 drd_report_race(addr, 4, eStore);
267 }
bart09dc13f2009-02-14 15:13:31 +0000268}
269
270static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
271{
bartd45d9952009-05-31 18:53:54 +0000272 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000273 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000274 || ! DRD_(thread_address_on_stack)(addr))
275 && bm_access_store_8_triggers_conflict(addr)
276 && ! DRD_(is_suppressed)(addr, addr + 8))
277 {
278 drd_report_race(addr, 8, eStore);
279 }
bart09dc13f2009-02-14 15:13:31 +0000280}
281
282/**
283 * Return true if and only if addr_expr matches the pattern (SP) or
284 * <offset>(SP).
285 */
286static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
287{
bartbedfd232009-03-26 19:07:15 +0000288 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000289
bartbedfd232009-03-26 19:07:15 +0000290 if (addr_expr->tag == Iex_RdTmp)
291 {
292 int i;
293 for (i = 0; i < bb->stmts_size; i++)
bart09dc13f2009-02-14 15:13:31 +0000294 {
bartbedfd232009-03-26 19:07:15 +0000295 if (bb->stmts[i]
296 && bb->stmts[i]->tag == Ist_WrTmp
297 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
298 {
299 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
300 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
301 {
302 result = True;
303 }
bart09dc13f2009-02-14 15:13:31 +0000304
bartbedfd232009-03-26 19:07:15 +0000305 //ppIRExpr(e);
306 //VG_(printf)(" (%s)\n", result ? "True" : "False");
307 break;
308 }
bart09dc13f2009-02-14 15:13:31 +0000309 }
bartbedfd232009-03-26 19:07:15 +0000310 }
311 return result;
bart09dc13f2009-02-14 15:13:31 +0000312}
313
314static void instrument_load(IRSB* const bb,
315 IRExpr* const addr_expr,
316 const HWord size)
317{
bartbedfd232009-03-26 19:07:15 +0000318 IRExpr* size_expr;
319 IRExpr** argv;
320 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000321
bartbedfd232009-03-26 19:07:15 +0000322 if (UNLIKELY(DRD_(any_address_is_traced)()))
323 {
324 addStmtToIRSB(bb,
325 IRStmt_Dirty(
326 unsafeIRDirty_0_N(/*regparms*/2,
327 "drd_trace_load",
328 VG_(fnptr_to_fnentry)
bart07595032010-08-29 09:51:06 +0000329 (drd_trace_mem_load),
bartbedfd232009-03-26 19:07:15 +0000330 mkIRExprVec_2(addr_expr,
331 mkIRExpr_HWord(size)))));
332 }
bart09dc13f2009-02-14 15:13:31 +0000333
bartf98a5692009-05-03 17:17:37 +0000334 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000335 return;
bart09dc13f2009-02-14 15:13:31 +0000336
bartbedfd232009-03-26 19:07:15 +0000337 switch (size)
338 {
339 case 1:
340 argv = mkIRExprVec_1(addr_expr);
341 di = unsafeIRDirty_0_N(/*regparms*/1,
342 "drd_trace_load_1",
343 VG_(fnptr_to_fnentry)(drd_trace_load_1),
344 argv);
345 break;
346 case 2:
347 argv = mkIRExprVec_1(addr_expr);
348 di = unsafeIRDirty_0_N(/*regparms*/1,
349 "drd_trace_load_2",
350 VG_(fnptr_to_fnentry)(drd_trace_load_2),
351 argv);
352 break;
353 case 4:
354 argv = mkIRExprVec_1(addr_expr);
355 di = unsafeIRDirty_0_N(/*regparms*/1,
356 "drd_trace_load_4",
357 VG_(fnptr_to_fnentry)(drd_trace_load_4),
358 argv);
359 break;
360 case 8:
361 argv = mkIRExprVec_1(addr_expr);
362 di = unsafeIRDirty_0_N(/*regparms*/1,
363 "drd_trace_load_8",
364 VG_(fnptr_to_fnentry)(drd_trace_load_8),
365 argv);
366 break;
367 default:
368 size_expr = mkIRExpr_HWord(size);
369 argv = mkIRExprVec_2(addr_expr, size_expr);
370 di = unsafeIRDirty_0_N(/*regparms*/2,
371 "drd_trace_load",
372 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
373 argv);
374 break;
375 }
376 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000377}
378
379static void instrument_store(IRSB* const bb,
380 IRExpr* const addr_expr,
381 const HWord size)
382{
bartbedfd232009-03-26 19:07:15 +0000383 IRExpr* size_expr;
384 IRExpr** argv;
385 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000386
bartbedfd232009-03-26 19:07:15 +0000387 if (UNLIKELY(DRD_(any_address_is_traced)()))
388 {
389 addStmtToIRSB(bb,
390 IRStmt_Dirty(
391 unsafeIRDirty_0_N(/*regparms*/2,
392 "drd_trace_store",
393 VG_(fnptr_to_fnentry)
bart07595032010-08-29 09:51:06 +0000394 (drd_trace_mem_store),
bartbedfd232009-03-26 19:07:15 +0000395 mkIRExprVec_2(addr_expr,
396 mkIRExpr_HWord(size)))));
397 }
bart09dc13f2009-02-14 15:13:31 +0000398
bartf98a5692009-05-03 17:17:37 +0000399 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000400 return;
bart09dc13f2009-02-14 15:13:31 +0000401
bartbedfd232009-03-26 19:07:15 +0000402 switch (size)
403 {
404 case 1:
405 argv = mkIRExprVec_1(addr_expr);
406 di = unsafeIRDirty_0_N(/*regparms*/1,
407 "drd_trace_store_1",
408 VG_(fnptr_to_fnentry)(drd_trace_store_1),
409 argv);
410 break;
411 case 2:
412 argv = mkIRExprVec_1(addr_expr);
413 di = unsafeIRDirty_0_N(/*regparms*/1,
414 "drd_trace_store_2",
415 VG_(fnptr_to_fnentry)(drd_trace_store_2),
416 argv);
417 break;
418 case 4:
419 argv = mkIRExprVec_1(addr_expr);
420 di = unsafeIRDirty_0_N(/*regparms*/1,
421 "drd_trace_store_4",
422 VG_(fnptr_to_fnentry)(drd_trace_store_4),
423 argv);
424 break;
425 case 8:
426 argv = mkIRExprVec_1(addr_expr);
427 di = unsafeIRDirty_0_N(/*regparms*/1,
428 "drd_trace_store_8",
429 VG_(fnptr_to_fnentry)(drd_trace_store_8),
430 argv);
431 break;
432 default:
433 size_expr = mkIRExpr_HWord(size);
434 argv = mkIRExprVec_2(addr_expr, size_expr);
435 di = unsafeIRDirty_0_N(/*regparms*/2,
436 "drd_trace_store",
437 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
438 argv);
439 break;
440 }
441 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000442}
443
bart1335ecc2009-02-14 16:10:53 +0000444IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000445 IRSB* const bb_in,
446 VexGuestLayout* const layout,
bart31b983d2010-02-21 14:52:59 +0000447 VexGuestExtents* const vge,
bartbedfd232009-03-26 19:07:15 +0000448 IRType const gWordTy,
449 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000450{
bartbedfd232009-03-26 19:07:15 +0000451 IRDirty* di;
452 Int i;
453 IRSB* bb;
454 IRExpr** argv;
455 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000456
bartbedfd232009-03-26 19:07:15 +0000457 /* Set up BB */
458 bb = emptyIRSB();
459 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
460 bb->next = deepCopyIRExpr(bb_in->next);
461 bb->jumpkind = bb_in->jumpkind;
bart09dc13f2009-02-14 15:13:31 +0000462
bartbedfd232009-03-26 19:07:15 +0000463 for (i = 0; i < bb_in->stmts_used; i++)
464 {
465 IRStmt* const st = bb_in->stmts[i];
466 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000467 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000468
bartbedfd232009-03-26 19:07:15 +0000469 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000470 {
bartbedfd232009-03-26 19:07:15 +0000471 /* Note: the code for not instrumenting the code in .plt */
472 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
473 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
474 /* This is because on this platform dynamic library symbols are */
475 /* relocated in another way than by later binutils versions. The */
476 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
477 case Ist_IMark:
sewardje3f1e592009-07-31 09:41:29 +0000478 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000479 != Vg_SectPLT;
480 addStmtToIRSB(bb, st);
481 break;
482
483 case Ist_MBE:
484 switch (st->Ist.MBE.event)
485 {
486 case Imbe_Fence:
487 break; /* not interesting */
bartbedfd232009-03-26 19:07:15 +0000488 default:
489 tl_assert(0);
490 }
491 addStmtToIRSB(bb, st);
492 break;
493
494 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000495 if (instrument)
bartbedfd232009-03-26 19:07:15 +0000496 {
497 instrument_store(bb,
498 st->Ist.Store.addr,
499 sizeofIRType(typeOfIRExpr(bb->tyenv,
500 st->Ist.Store.data)));
501 }
502 addStmtToIRSB(bb, st);
503 break;
504
505 case Ist_WrTmp:
506 if (instrument)
507 {
508 const IRExpr* const data = st->Ist.WrTmp.data;
509 if (data->tag == Iex_Load)
510 {
511 instrument_load(bb,
512 data->Iex.Load.addr,
513 sizeofIRType(data->Iex.Load.ty));
514 }
515 }
516 addStmtToIRSB(bb, st);
517 break;
518
519 case Ist_Dirty:
520 if (instrument)
521 {
522 IRDirty* d = st->Ist.Dirty.details;
523 IREffect const mFx = d->mFx;
524 switch (mFx) {
525 case Ifx_None:
526 break;
527 case Ifx_Read:
528 case Ifx_Write:
529 case Ifx_Modify:
530 tl_assert(d->mAddr);
531 tl_assert(d->mSize > 0);
532 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
533 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
534 di = unsafeIRDirty_0_N(
535 /*regparms*/2,
536 "drd_trace_load",
537 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
538 argv);
539 addStmtToIRSB(bb, IRStmt_Dirty(di));
540 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000541 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000542 {
543 di = unsafeIRDirty_0_N(
544 /*regparms*/2,
545 "drd_trace_store",
546 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
547 argv);
548 addStmtToIRSB(bb, IRStmt_Dirty(di));
549 }
550 break;
551 default:
552 tl_assert(0);
553 }
554 }
555 addStmtToIRSB(bb, st);
556 break;
557
sewardj1c0ce7a2009-07-01 08:10:49 +0000558 case Ist_CAS:
559 if (instrument)
560 {
barta14e3282009-07-11 14:35:59 +0000561 /*
562 * Treat compare-and-swap as a read. By handling atomic
563 * instructions as read instructions no data races are reported
564 * between conflicting atomic operations nor between atomic
565 * operations and non-atomic reads. Conflicts between atomic
566 * operations and non-atomic write operations are still reported
567 * however.
568 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000569 Int dataSize;
570 IRCAS* cas = st->Ist.CAS.details;
571 tl_assert(cas->addr != NULL);
572 tl_assert(cas->dataLo != NULL);
573 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
574 if (cas->dataHi != NULL)
575 dataSize *= 2; /* since it's a doubleword-CAS */
576 instrument_load(bb, cas->addr, dataSize);
577 }
578 addStmtToIRSB(bb, st);
579 break;
580
sewardjdb5907d2009-11-26 17:20:21 +0000581 case Ist_LLSC: {
582 /* Ignore store-conditionals, and handle load-linked's
583 exactly like normal loads. */
584 IRType dataTy;
585 if (st->Ist.LLSC.storedata == NULL)
586 {
587 /* LL */
588 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
589 if (instrument) {
590 instrument_load(bb,
591 st->Ist.LLSC.addr,
592 sizeofIRType(dataTy));
593 }
594 }
595 else
596 {
597 /* SC */
598 /*ignore */
599 }
bartbedfd232009-03-26 19:07:15 +0000600 addStmtToIRSB(bb, st);
601 break;
bart09dc13f2009-02-14 15:13:31 +0000602 }
sewardjdb5907d2009-11-26 17:20:21 +0000603
604 case Ist_NoOp:
605 case Ist_AbiHint:
606 case Ist_Put:
607 case Ist_PutI:
608 case Ist_Exit:
609 /* None of these can contain any memory references. */
610 addStmtToIRSB(bb, st);
611 break;
612
613 default:
614 ppIRStmt(st);
615 tl_assert(0);
616 }
bartbedfd232009-03-26 19:07:15 +0000617 }
bart09dc13f2009-02-14 15:13:31 +0000618
bartbedfd232009-03-26 19:07:15 +0000619 return bb;
bart09dc13f2009-02-14 15:13:31 +0000620}
621