blob: c7bfdedc7c9c0b4fd2debb981b861acc0bc950cb [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,
bartbedfd232009-03-26 19:07:15 +000088 const BmAccessTypeT access_type)
bart09dc13f2009-02-14 15:13:31 +000089{
bartbedfd232009-03-26 19:07:15 +000090 if (DRD_(is_any_traced)(addr, addr + size))
91 {
bart8f822af2009-06-08 18:20:42 +000092 char* vc;
93
94 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bartad994e82011-10-13 18:04:30 +000095 DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
96 access_type == eLoad ? "load "
97 : access_type == eStore ? "store"
98 : access_type == eStart ? "start"
99 : access_type == eEnd ? "end " : "????",
100 addr, size, DRD_(thread_get_running_tid)(), vc);
bart8f822af2009-06-08 18:20:42 +0000101 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000102 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
103 == VG_(get_running_tid)());
104 }
bart09dc13f2009-02-14 15:13:31 +0000105}
106
bart07595032010-08-29 09:51:06 +0000107static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000108{
bartbedfd232009-03-26 19:07:15 +0000109 return DRD_(trace_mem_access)(addr, size, eLoad);
bart09dc13f2009-02-14 15:13:31 +0000110}
111
bart07595032010-08-29 09:51:06 +0000112static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000113{
bartbedfd232009-03-26 19:07:15 +0000114 return DRD_(trace_mem_access)(addr, size, eStore);
bart09dc13f2009-02-14 15:13:31 +0000115}
116
117static void drd_report_race(const Addr addr, const SizeT size,
118 const BmAccessTypeT access_type)
119{
bartbedfd232009-03-26 19:07:15 +0000120 DataRaceErrInfo drei;
bart09dc13f2009-02-14 15:13:31 +0000121
bartbedfd232009-03-26 19:07:15 +0000122 drei.tid = DRD_(thread_get_running_tid)();
123 drei.addr = addr;
124 drei.size = size;
125 drei.access_type = access_type;
126 VG_(maybe_record_error)(VG_(get_running_tid)(),
127 DataRaceErr,
128 VG_(get_IP)(VG_(get_running_tid)()),
bart74b2d972011-10-08 08:54:57 +0000129 "Conflicting access",
bartbedfd232009-03-26 19:07:15 +0000130 &drei);
bartf98a5692009-05-03 17:17:37 +0000131
132 if (s_first_race_only)
133 {
134 DRD_(start_suppression)(addr, addr + size, "first race only");
135 }
bart09dc13f2009-02-14 15:13:31 +0000136}
137
bart99edb292009-02-15 15:59:20 +0000138VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000139{
140#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000141 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000142 tl_assert(DRD_(thread_get_running_tid)()
143 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000144#endif
145
bartd45d9952009-05-31 18:53:54 +0000146 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000147 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000148 || ! DRD_(thread_address_on_stack)(addr))
149 && bm_access_load_triggers_conflict(addr, addr + size)
150 && ! DRD_(is_suppressed)(addr, addr + size))
151 {
152 drd_report_race(addr, size, eLoad);
153 }
bart09dc13f2009-02-14 15:13:31 +0000154}
155
156static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
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_1_triggers_conflict(addr)
162 && ! DRD_(is_suppressed)(addr, addr + 1))
163 {
164 drd_report_race(addr, 1, eLoad);
165 }
bart09dc13f2009-02-14 15:13:31 +0000166}
167
168static VG_REGPARM(1) void drd_trace_load_2(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_2_triggers_conflict(addr)
174 && ! DRD_(is_suppressed)(addr, addr + 2))
175 {
176 drd_report_race(addr, 2, eLoad);
177 }
bart09dc13f2009-02-14 15:13:31 +0000178}
179
180static VG_REGPARM(1) void drd_trace_load_4(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_4_triggers_conflict(addr)
186 && ! DRD_(is_suppressed)(addr, addr + 4))
187 {
188 drd_report_race(addr, 4, eLoad);
189 }
bart09dc13f2009-02-14 15:13:31 +0000190}
191
192static VG_REGPARM(1) void drd_trace_load_8(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_8_triggers_conflict(addr)
198 && ! DRD_(is_suppressed)(addr, addr + 8))
199 {
200 drd_report_race(addr, 8, eLoad);
201 }
bart09dc13f2009-02-14 15:13:31 +0000202}
203
bart99edb292009-02-15 15:59:20 +0000204VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000205{
206#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000207 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000208 tl_assert(DRD_(thread_get_running_tid)()
209 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000210#endif
211
bartd45d9952009-05-31 18:53:54 +0000212 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000213 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000214 || ! DRD_(thread_address_on_stack)(addr))
215 && bm_access_store_triggers_conflict(addr, addr + size)
216 && ! DRD_(is_suppressed)(addr, addr + size))
217 {
218 drd_report_race(addr, size, eStore);
219 }
bart09dc13f2009-02-14 15:13:31 +0000220}
221
222static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
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_1_triggers_conflict(addr)
228 && ! DRD_(is_suppressed)(addr, addr + 1))
229 {
230 drd_report_race(addr, 1, eStore);
231 }
bart09dc13f2009-02-14 15:13:31 +0000232}
233
234static VG_REGPARM(1) void drd_trace_store_2(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_2_triggers_conflict(addr)
240 && ! DRD_(is_suppressed)(addr, addr + 2))
241 {
242 drd_report_race(addr, 2, eStore);
243 }
bart09dc13f2009-02-14 15:13:31 +0000244}
245
246static VG_REGPARM(1) void drd_trace_store_4(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
bart71ce1322011-12-11 17:54:17 +0000250 || !DRD_(thread_address_on_stack)(addr))
bartbedfd232009-03-26 19:07:15 +0000251 && bm_access_store_4_triggers_conflict(addr)
bart71ce1322011-12-11 17:54:17 +0000252 && !DRD_(is_suppressed)(addr, addr + 4))
bartbedfd232009-03-26 19:07:15 +0000253 {
254 drd_report_race(addr, 4, eStore);
255 }
bart09dc13f2009-02-14 15:13:31 +0000256}
257
258static VG_REGPARM(1) void drd_trace_store_8(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_8_triggers_conflict(addr)
264 && ! DRD_(is_suppressed)(addr, addr + 8))
265 {
266 drd_report_race(addr, 8, eStore);
267 }
bart09dc13f2009-02-14 15:13:31 +0000268}
269
270/**
271 * Return true if and only if addr_expr matches the pattern (SP) or
272 * <offset>(SP).
273 */
274static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
275{
bartbedfd232009-03-26 19:07:15 +0000276 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000277
bartbedfd232009-03-26 19:07:15 +0000278 if (addr_expr->tag == Iex_RdTmp)
279 {
280 int i;
281 for (i = 0; i < bb->stmts_size; i++)
bart09dc13f2009-02-14 15:13:31 +0000282 {
bartbedfd232009-03-26 19:07:15 +0000283 if (bb->stmts[i]
284 && bb->stmts[i]->tag == Ist_WrTmp
285 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
286 {
287 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
288 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
289 {
290 result = True;
291 }
bart09dc13f2009-02-14 15:13:31 +0000292
bartbedfd232009-03-26 19:07:15 +0000293 //ppIRExpr(e);
294 //VG_(printf)(" (%s)\n", result ? "True" : "False");
295 break;
296 }
bart09dc13f2009-02-14 15:13:31 +0000297 }
bartbedfd232009-03-26 19:07:15 +0000298 }
299 return result;
bart09dc13f2009-02-14 15:13:31 +0000300}
301
302static void instrument_load(IRSB* const bb,
303 IRExpr* const addr_expr,
304 const HWord size)
305{
bartbedfd232009-03-26 19:07:15 +0000306 IRExpr* size_expr;
307 IRExpr** argv;
308 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000309
bartbedfd232009-03-26 19:07:15 +0000310 if (UNLIKELY(DRD_(any_address_is_traced)()))
311 {
312 addStmtToIRSB(bb,
313 IRStmt_Dirty(
314 unsafeIRDirty_0_N(/*regparms*/2,
bart71ce1322011-12-11 17:54:17 +0000315 "drd_trace_mem_load",
bartbedfd232009-03-26 19:07:15 +0000316 VG_(fnptr_to_fnentry)
bart07595032010-08-29 09:51:06 +0000317 (drd_trace_mem_load),
bart71ce1322011-12-11 17:54:17 +0000318 mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)))));
bartbedfd232009-03-26 19:07:15 +0000319 }
bart09dc13f2009-02-14 15:13:31 +0000320
bartf98a5692009-05-03 17:17:37 +0000321 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000322 return;
bart09dc13f2009-02-14 15:13:31 +0000323
bartbedfd232009-03-26 19:07:15 +0000324 switch (size)
325 {
326 case 1:
327 argv = mkIRExprVec_1(addr_expr);
328 di = unsafeIRDirty_0_N(/*regparms*/1,
329 "drd_trace_load_1",
330 VG_(fnptr_to_fnentry)(drd_trace_load_1),
331 argv);
332 break;
333 case 2:
334 argv = mkIRExprVec_1(addr_expr);
335 di = unsafeIRDirty_0_N(/*regparms*/1,
336 "drd_trace_load_2",
337 VG_(fnptr_to_fnentry)(drd_trace_load_2),
338 argv);
339 break;
340 case 4:
341 argv = mkIRExprVec_1(addr_expr);
342 di = unsafeIRDirty_0_N(/*regparms*/1,
343 "drd_trace_load_4",
344 VG_(fnptr_to_fnentry)(drd_trace_load_4),
345 argv);
346 break;
347 case 8:
348 argv = mkIRExprVec_1(addr_expr);
349 di = unsafeIRDirty_0_N(/*regparms*/1,
350 "drd_trace_load_8",
351 VG_(fnptr_to_fnentry)(drd_trace_load_8),
352 argv);
353 break;
354 default:
355 size_expr = mkIRExpr_HWord(size);
356 argv = mkIRExprVec_2(addr_expr, size_expr);
357 di = unsafeIRDirty_0_N(/*regparms*/2,
358 "drd_trace_load",
359 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
360 argv);
361 break;
362 }
363 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000364}
365
366static void instrument_store(IRSB* const bb,
367 IRExpr* const addr_expr,
368 const HWord size)
369{
bartbedfd232009-03-26 19:07:15 +0000370 IRExpr* size_expr;
371 IRExpr** argv;
372 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000373
bartbedfd232009-03-26 19:07:15 +0000374 if (UNLIKELY(DRD_(any_address_is_traced)()))
375 {
376 addStmtToIRSB(bb,
bart71ce1322011-12-11 17:54:17 +0000377 IRStmt_Dirty(
378 unsafeIRDirty_0_N(/*regparms*/2,
379 "drd_trace_mem_store",
380 VG_(fnptr_to_fnentry)
381 (drd_trace_mem_store),
382 mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)))));
bartbedfd232009-03-26 19:07:15 +0000383 }
bart09dc13f2009-02-14 15:13:31 +0000384
bart71ce1322011-12-11 17:54:17 +0000385 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000386 return;
bart09dc13f2009-02-14 15:13:31 +0000387
bartbedfd232009-03-26 19:07:15 +0000388 switch (size)
389 {
390 case 1:
391 argv = mkIRExprVec_1(addr_expr);
392 di = unsafeIRDirty_0_N(/*regparms*/1,
393 "drd_trace_store_1",
394 VG_(fnptr_to_fnentry)(drd_trace_store_1),
395 argv);
396 break;
397 case 2:
398 argv = mkIRExprVec_1(addr_expr);
399 di = unsafeIRDirty_0_N(/*regparms*/1,
400 "drd_trace_store_2",
401 VG_(fnptr_to_fnentry)(drd_trace_store_2),
402 argv);
403 break;
404 case 4:
405 argv = mkIRExprVec_1(addr_expr);
406 di = unsafeIRDirty_0_N(/*regparms*/1,
407 "drd_trace_store_4",
408 VG_(fnptr_to_fnentry)(drd_trace_store_4),
409 argv);
410 break;
411 case 8:
412 argv = mkIRExprVec_1(addr_expr);
413 di = unsafeIRDirty_0_N(/*regparms*/1,
414 "drd_trace_store_8",
415 VG_(fnptr_to_fnentry)(drd_trace_store_8),
416 argv);
417 break;
418 default:
419 size_expr = mkIRExpr_HWord(size);
420 argv = mkIRExprVec_2(addr_expr, size_expr);
421 di = unsafeIRDirty_0_N(/*regparms*/2,
422 "drd_trace_store",
423 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
424 argv);
425 break;
426 }
427 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000428}
429
bart1335ecc2009-02-14 16:10:53 +0000430IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000431 IRSB* const bb_in,
432 VexGuestLayout* const layout,
bart31b983d2010-02-21 14:52:59 +0000433 VexGuestExtents* const vge,
bartbedfd232009-03-26 19:07:15 +0000434 IRType const gWordTy,
435 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000436{
bartbedfd232009-03-26 19:07:15 +0000437 IRDirty* di;
438 Int i;
439 IRSB* bb;
440 IRExpr** argv;
441 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000442
bartbedfd232009-03-26 19:07:15 +0000443 /* Set up BB */
444 bb = emptyIRSB();
445 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
446 bb->next = deepCopyIRExpr(bb_in->next);
447 bb->jumpkind = bb_in->jumpkind;
bart09dc13f2009-02-14 15:13:31 +0000448
bartbedfd232009-03-26 19:07:15 +0000449 for (i = 0; i < bb_in->stmts_used; i++)
450 {
451 IRStmt* const st = bb_in->stmts[i];
452 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000453 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000454
bartbedfd232009-03-26 19:07:15 +0000455 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000456 {
bartbedfd232009-03-26 19:07:15 +0000457 /* Note: the code for not instrumenting the code in .plt */
458 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
459 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
460 /* This is because on this platform dynamic library symbols are */
461 /* relocated in another way than by later binutils versions. The */
462 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
463 case Ist_IMark:
sewardje3f1e592009-07-31 09:41:29 +0000464 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000465 != Vg_SectPLT;
466 addStmtToIRSB(bb, st);
467 break;
468
469 case Ist_MBE:
470 switch (st->Ist.MBE.event)
471 {
472 case Imbe_Fence:
473 break; /* not interesting */
bartbedfd232009-03-26 19:07:15 +0000474 default:
475 tl_assert(0);
476 }
477 addStmtToIRSB(bb, st);
478 break;
479
480 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000481 if (instrument)
bartbedfd232009-03-26 19:07:15 +0000482 {
483 instrument_store(bb,
484 st->Ist.Store.addr,
485 sizeofIRType(typeOfIRExpr(bb->tyenv,
486 st->Ist.Store.data)));
487 }
488 addStmtToIRSB(bb, st);
489 break;
490
491 case Ist_WrTmp:
492 if (instrument)
493 {
494 const IRExpr* const data = st->Ist.WrTmp.data;
495 if (data->tag == Iex_Load)
496 {
497 instrument_load(bb,
498 data->Iex.Load.addr,
499 sizeofIRType(data->Iex.Load.ty));
500 }
501 }
502 addStmtToIRSB(bb, st);
503 break;
504
505 case Ist_Dirty:
506 if (instrument)
507 {
508 IRDirty* d = st->Ist.Dirty.details;
509 IREffect const mFx = d->mFx;
510 switch (mFx) {
511 case Ifx_None:
512 break;
513 case Ifx_Read:
514 case Ifx_Write:
515 case Ifx_Modify:
516 tl_assert(d->mAddr);
517 tl_assert(d->mSize > 0);
518 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
519 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
520 di = unsafeIRDirty_0_N(
521 /*regparms*/2,
522 "drd_trace_load",
523 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
524 argv);
525 addStmtToIRSB(bb, IRStmt_Dirty(di));
526 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000527 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000528 {
529 di = unsafeIRDirty_0_N(
530 /*regparms*/2,
531 "drd_trace_store",
532 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
533 argv);
534 addStmtToIRSB(bb, IRStmt_Dirty(di));
535 }
536 break;
537 default:
538 tl_assert(0);
539 }
540 }
541 addStmtToIRSB(bb, st);
542 break;
543
sewardj1c0ce7a2009-07-01 08:10:49 +0000544 case Ist_CAS:
545 if (instrument)
546 {
barta14e3282009-07-11 14:35:59 +0000547 /*
548 * Treat compare-and-swap as a read. By handling atomic
549 * instructions as read instructions no data races are reported
550 * between conflicting atomic operations nor between atomic
551 * operations and non-atomic reads. Conflicts between atomic
552 * operations and non-atomic write operations are still reported
553 * however.
554 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000555 Int dataSize;
556 IRCAS* cas = st->Ist.CAS.details;
557 tl_assert(cas->addr != NULL);
558 tl_assert(cas->dataLo != NULL);
559 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
560 if (cas->dataHi != NULL)
561 dataSize *= 2; /* since it's a doubleword-CAS */
562 instrument_load(bb, cas->addr, dataSize);
563 }
564 addStmtToIRSB(bb, st);
565 break;
566
sewardjdb5907d2009-11-26 17:20:21 +0000567 case Ist_LLSC: {
568 /* Ignore store-conditionals, and handle load-linked's
569 exactly like normal loads. */
570 IRType dataTy;
571 if (st->Ist.LLSC.storedata == NULL)
572 {
573 /* LL */
574 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
575 if (instrument) {
576 instrument_load(bb,
577 st->Ist.LLSC.addr,
578 sizeofIRType(dataTy));
579 }
580 }
581 else
582 {
583 /* SC */
584 /*ignore */
585 }
bartbedfd232009-03-26 19:07:15 +0000586 addStmtToIRSB(bb, st);
587 break;
bart09dc13f2009-02-14 15:13:31 +0000588 }
sewardjdb5907d2009-11-26 17:20:21 +0000589
590 case Ist_NoOp:
591 case Ist_AbiHint:
592 case Ist_Put:
593 case Ist_PutI:
594 case Ist_Exit:
595 /* None of these can contain any memory references. */
596 addStmtToIRSB(bb, st);
597 break;
598
599 default:
600 ppIRStmt(st);
601 tl_assert(0);
602 }
bartbedfd232009-03-26 19:07:15 +0000603 }
bart09dc13f2009-02-14 15:13:31 +0000604
bartbedfd232009-03-26 19:07:15 +0000605 return bb;
bart09dc13f2009-02-14 15:13:31 +0000606}
607