blob: 032a989b6f3bd83a5044c850a77f588103706ac2 [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,
89 const HWord stored_value)
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)()));
bart7826acb2011-12-11 18:49:39 +000096 if (access_type == eStore && size <= sizeof(HWord)) {
bart5cda1b52011-12-12 19:37:10 +000097 DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %ld/0x%lx (thread %d /"
98 " vc %s)", addr, size, stored_value, stored_value,
bart7826acb2011-12-11 18:49:39 +000099 DRD_(thread_get_running_tid)(), vc);
100 } else {
101 DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
102 access_type == eLoad ? "load "
103 : access_type == eStore ? "store"
104 : access_type == eStart ? "start"
105 : access_type == eEnd ? "end " : "????",
106 addr, size, DRD_(thread_get_running_tid)(), vc);
107 }
bart8f822af2009-06-08 18:20:42 +0000108 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000109 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
110 == VG_(get_running_tid)());
111 }
bart09dc13f2009-02-14 15:13:31 +0000112}
113
bart07595032010-08-29 09:51:06 +0000114static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000115{
bart7826acb2011-12-11 18:49:39 +0000116 return DRD_(trace_mem_access)(addr, size, eLoad, 0);
bart09dc13f2009-02-14 15:13:31 +0000117}
118
bart7826acb2011-12-11 18:49:39 +0000119static VG_REGPARM(3) void drd_trace_mem_store(const Addr addr,const SizeT size,
120 const HWord stored_value)
bart09dc13f2009-02-14 15:13:31 +0000121{
bart7826acb2011-12-11 18:49:39 +0000122 return DRD_(trace_mem_access)(addr, size, eStore, stored_value);
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)()),
bart74b2d972011-10-08 08:54:57 +0000137 "Conflicting access",
bartbedfd232009-03-26 19:07:15 +0000138 &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.*/
bartd5bbc612010-09-02 14:44:17 +0000150 tl_assert(DRD_(thread_get_running_tid)()
151 == DRD_(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.*/
bartd5bbc612010-09-02 14:44:17 +0000216 tl_assert(DRD_(thread_get_running_tid)()
217 == DRD_(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
bart71ce1322011-12-11 17:54:17 +0000258 || !DRD_(thread_address_on_stack)(addr))
bartbedfd232009-03-26 19:07:15 +0000259 && bm_access_store_4_triggers_conflict(addr)
bart71ce1322011-12-11 17:54:17 +0000260 && !DRD_(is_suppressed)(addr, addr + 4))
bartbedfd232009-03-26 19:07:15 +0000261 {
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
bartea692152011-12-11 20:17:57 +0000310static const IROp u_widen_irop[5][9] = {
bart9ad8d802011-12-12 19:54:32 +0000311 [Ity_I1 - Ity_I1] = { [4] = Iop_1Uto32, [8] = Iop_1Uto64 },
312 [Ity_I8 - Ity_I1] = { [4] = Iop_8Uto32, [8] = Iop_8Uto64 },
313 [Ity_I16 - Ity_I1] = { [4] = Iop_16Uto32, [8] = Iop_16Uto64 },
314 [Ity_I32 - Ity_I1] = { [8] = Iop_32Uto64 },
bartea692152011-12-11 20:17:57 +0000315};
316
bartb63dc782011-12-12 19:18:26 +0000317/**
318 * Instrument the client code to trace a memory load (--trace-addr).
319 */
320static void instr_trace_mem_load(IRSB* const bb, IRExpr* const addr_expr,
321 const HWord size)
bartea692152011-12-11 20:17:57 +0000322{
bartb63dc782011-12-12 19:18:26 +0000323 addStmtToIRSB(bb,
324 IRStmt_Dirty(
325 unsafeIRDirty_0_N(/*regparms*/2,
326 "drd_trace_mem_load",
327 VG_(fnptr_to_fnentry)
328 (drd_trace_mem_load),
329 mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)))));
330}
331
332/**
333 * Instrument the client code to trace a memory store (--trace-addr).
334 */
335static void instr_trace_mem_store(IRSB* const bb, IRExpr* const addr_expr,
336 IRExpr* const data_expr)
337{
338 IRType ty_data_expr;
bartea692152011-12-11 20:17:57 +0000339 IRExpr *hword_data_expr;
340 HWord size;
341
bartb63dc782011-12-12 19:18:26 +0000342 tl_assert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
bartea692152011-12-11 20:17:57 +0000343
bartb63dc782011-12-12 19:18:26 +0000344 ty_data_expr = typeOfIRExpr(bb->tyenv, data_expr);
345 size = sizeofIRType(ty_data_expr);
346
347 if (size == sizeof(HWord)
348 && (ty_data_expr == Ity_I32 || ty_data_expr == Ity_I64))
349 {
350 /* No conversion necessary */
bartea692152011-12-11 20:17:57 +0000351 hword_data_expr = data_expr;
352 } else {
353 IROp widen_op;
354
bartb63dc782011-12-12 19:18:26 +0000355 if (Ity_I1 <= ty_data_expr
356 && ty_data_expr
357 < Ity_I1 + sizeof(u_widen_irop)/sizeof(u_widen_irop[0]))
358 {
359 widen_op = u_widen_irop[ty_data_expr - Ity_I1][sizeof(HWord)];
bartea692152011-12-11 20:17:57 +0000360 if (!widen_op)
361 widen_op = Iop_INVALID;
362 } else {
363 widen_op = Iop_INVALID;
364 }
365 if (widen_op != Iop_INVALID) {
366 IRTemp tmp;
367
bartb63dc782011-12-12 19:18:26 +0000368 /* Widen the integer expression to a HWord */
bartea692152011-12-11 20:17:57 +0000369 tmp = newIRTemp(bb->tyenv, sizeof(HWord) == 4 ? Ity_I32 : Ity_I64);
370 addStmtToIRSB(bb,
371 IRStmt_WrTmp(tmp, IRExpr_Unop(widen_op, data_expr)));
372 hword_data_expr = IRExpr_RdTmp(tmp);
373 } else {
bartb63dc782011-12-12 19:18:26 +0000374 /*
375 * Replace anything wider than a HWord and also Ity_F32, Ity_F64,
376 * Ity_F128 and Ity_V128 by zero.
377 */
bartea692152011-12-11 20:17:57 +0000378 hword_data_expr = mkIRExpr_HWord(0);
379 }
380 }
381 addStmtToIRSB(bb,
382 IRStmt_Dirty(
383 unsafeIRDirty_0_N(/*regparms*/3,
384 "drd_trace_mem_store",
385 VG_(fnptr_to_fnentry)
386 (drd_trace_mem_store),
387 mkIRExprVec_3(addr_expr, mkIRExpr_HWord(size),
388 hword_data_expr))));
389}
390
391static void instrument_load(IRSB* const bb, IRExpr* const addr_expr,
bartb63dc782011-12-12 19:18:26 +0000392 const HWord size)
bart09dc13f2009-02-14 15:13:31 +0000393{
bartbedfd232009-03-26 19:07:15 +0000394 IRExpr* size_expr;
395 IRExpr** argv;
396 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000397
bartea692152011-12-11 20:17:57 +0000398 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000399 return;
bart09dc13f2009-02-14 15:13:31 +0000400
bartbedfd232009-03-26 19:07:15 +0000401 switch (size)
402 {
403 case 1:
404 argv = mkIRExprVec_1(addr_expr);
405 di = unsafeIRDirty_0_N(/*regparms*/1,
406 "drd_trace_load_1",
407 VG_(fnptr_to_fnentry)(drd_trace_load_1),
408 argv);
409 break;
410 case 2:
411 argv = mkIRExprVec_1(addr_expr);
412 di = unsafeIRDirty_0_N(/*regparms*/1,
413 "drd_trace_load_2",
414 VG_(fnptr_to_fnentry)(drd_trace_load_2),
415 argv);
416 break;
417 case 4:
418 argv = mkIRExprVec_1(addr_expr);
419 di = unsafeIRDirty_0_N(/*regparms*/1,
420 "drd_trace_load_4",
421 VG_(fnptr_to_fnentry)(drd_trace_load_4),
422 argv);
423 break;
424 case 8:
425 argv = mkIRExprVec_1(addr_expr);
426 di = unsafeIRDirty_0_N(/*regparms*/1,
427 "drd_trace_load_8",
428 VG_(fnptr_to_fnentry)(drd_trace_load_8),
429 argv);
430 break;
431 default:
432 size_expr = mkIRExpr_HWord(size);
433 argv = mkIRExprVec_2(addr_expr, size_expr);
434 di = unsafeIRDirty_0_N(/*regparms*/2,
435 "drd_trace_load",
436 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
437 argv);
438 break;
439 }
440 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000441}
442
bart7826acb2011-12-11 18:49:39 +0000443static void instrument_store(IRSB* const bb, IRExpr* const addr_expr,
444 IRExpr* const data_expr)
bart09dc13f2009-02-14 15:13:31 +0000445{
bartbedfd232009-03-26 19:07:15 +0000446 IRExpr* size_expr;
447 IRExpr** argv;
448 IRDirty* di;
bart7826acb2011-12-11 18:49:39 +0000449 HWord size;
450
451 size = sizeofIRType(typeOfIRExpr(bb->tyenv, data_expr));
bart09dc13f2009-02-14 15:13:31 +0000452
bartbedfd232009-03-26 19:07:15 +0000453 if (UNLIKELY(DRD_(any_address_is_traced)()))
bartb63dc782011-12-12 19:18:26 +0000454 instr_trace_mem_store(bb, addr_expr, data_expr);
bart09dc13f2009-02-14 15:13:31 +0000455
bart71ce1322011-12-11 17:54:17 +0000456 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000457 return;
bart09dc13f2009-02-14 15:13:31 +0000458
bartbedfd232009-03-26 19:07:15 +0000459 switch (size)
460 {
461 case 1:
462 argv = mkIRExprVec_1(addr_expr);
463 di = unsafeIRDirty_0_N(/*regparms*/1,
464 "drd_trace_store_1",
465 VG_(fnptr_to_fnentry)(drd_trace_store_1),
466 argv);
467 break;
468 case 2:
469 argv = mkIRExprVec_1(addr_expr);
470 di = unsafeIRDirty_0_N(/*regparms*/1,
471 "drd_trace_store_2",
472 VG_(fnptr_to_fnentry)(drd_trace_store_2),
473 argv);
474 break;
475 case 4:
476 argv = mkIRExprVec_1(addr_expr);
477 di = unsafeIRDirty_0_N(/*regparms*/1,
478 "drd_trace_store_4",
479 VG_(fnptr_to_fnentry)(drd_trace_store_4),
480 argv);
481 break;
482 case 8:
483 argv = mkIRExprVec_1(addr_expr);
484 di = unsafeIRDirty_0_N(/*regparms*/1,
485 "drd_trace_store_8",
486 VG_(fnptr_to_fnentry)(drd_trace_store_8),
487 argv);
488 break;
489 default:
490 size_expr = mkIRExpr_HWord(size);
491 argv = mkIRExprVec_2(addr_expr, size_expr);
492 di = unsafeIRDirty_0_N(/*regparms*/2,
493 "drd_trace_store",
494 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
495 argv);
496 break;
497 }
498 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000499}
500
bart1335ecc2009-02-14 16:10:53 +0000501IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000502 IRSB* const bb_in,
503 VexGuestLayout* const layout,
bart31b983d2010-02-21 14:52:59 +0000504 VexGuestExtents* const vge,
bartbedfd232009-03-26 19:07:15 +0000505 IRType const gWordTy,
506 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000507{
bartbedfd232009-03-26 19:07:15 +0000508 IRDirty* di;
509 Int i;
510 IRSB* bb;
511 IRExpr** argv;
512 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000513
bartbedfd232009-03-26 19:07:15 +0000514 /* Set up BB */
515 bb = emptyIRSB();
516 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
517 bb->next = deepCopyIRExpr(bb_in->next);
518 bb->jumpkind = bb_in->jumpkind;
bart09dc13f2009-02-14 15:13:31 +0000519
bartbedfd232009-03-26 19:07:15 +0000520 for (i = 0; i < bb_in->stmts_used; i++)
521 {
522 IRStmt* const st = bb_in->stmts[i];
523 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000524 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000525
bartbedfd232009-03-26 19:07:15 +0000526 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000527 {
bartbedfd232009-03-26 19:07:15 +0000528 /* Note: the code for not instrumenting the code in .plt */
529 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
530 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
531 /* This is because on this platform dynamic library symbols are */
532 /* relocated in another way than by later binutils versions. The */
533 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
534 case Ist_IMark:
sewardje3f1e592009-07-31 09:41:29 +0000535 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000536 != Vg_SectPLT;
537 addStmtToIRSB(bb, st);
538 break;
539
540 case Ist_MBE:
541 switch (st->Ist.MBE.event)
542 {
543 case Imbe_Fence:
544 break; /* not interesting */
bartbedfd232009-03-26 19:07:15 +0000545 default:
546 tl_assert(0);
547 }
548 addStmtToIRSB(bb, st);
549 break;
550
551 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000552 if (instrument)
bart7826acb2011-12-11 18:49:39 +0000553 instrument_store(bb, st->Ist.Store.addr, st->Ist.Store.data);
bartbedfd232009-03-26 19:07:15 +0000554 addStmtToIRSB(bb, st);
555 break;
556
557 case Ist_WrTmp:
bartea692152011-12-11 20:17:57 +0000558 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000559 const IRExpr* const data = st->Ist.WrTmp.data;
bartb63dc782011-12-12 19:18:26 +0000560 if (data->tag == Iex_Load) {
561 if (UNLIKELY(DRD_(any_address_is_traced)()))
562 instr_trace_mem_load(bb, data->Iex.Load.addr,
563 sizeofIRType(data->Iex.Load.ty));
564
bartea692152011-12-11 20:17:57 +0000565 instrument_load(bb, data->Iex.Load.addr,
bartb63dc782011-12-12 19:18:26 +0000566 sizeofIRType(data->Iex.Load.ty));
567 }
bartbedfd232009-03-26 19:07:15 +0000568 }
569 addStmtToIRSB(bb, st);
570 break;
571
572 case Ist_Dirty:
bartb63dc782011-12-12 19:18:26 +0000573 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000574 IRDirty* d = st->Ist.Dirty.details;
575 IREffect const mFx = d->mFx;
576 switch (mFx) {
577 case Ifx_None:
578 break;
579 case Ifx_Read:
580 case Ifx_Write:
581 case Ifx_Modify:
582 tl_assert(d->mAddr);
583 tl_assert(d->mSize > 0);
584 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
585 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
586 di = unsafeIRDirty_0_N(
587 /*regparms*/2,
588 "drd_trace_load",
589 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
590 argv);
591 addStmtToIRSB(bb, IRStmt_Dirty(di));
592 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000593 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000594 {
595 di = unsafeIRDirty_0_N(
596 /*regparms*/2,
597 "drd_trace_store",
598 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
599 argv);
600 addStmtToIRSB(bb, IRStmt_Dirty(di));
601 }
602 break;
603 default:
604 tl_assert(0);
605 }
606 }
607 addStmtToIRSB(bb, st);
608 break;
609
sewardj1c0ce7a2009-07-01 08:10:49 +0000610 case Ist_CAS:
bartb63dc782011-12-12 19:18:26 +0000611 if (instrument) {
barta14e3282009-07-11 14:35:59 +0000612 /*
613 * Treat compare-and-swap as a read. By handling atomic
614 * instructions as read instructions no data races are reported
615 * between conflicting atomic operations nor between atomic
616 * operations and non-atomic reads. Conflicts between atomic
617 * operations and non-atomic write operations are still reported
618 * however.
619 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000620 Int dataSize;
621 IRCAS* cas = st->Ist.CAS.details;
bartb63dc782011-12-12 19:18:26 +0000622
sewardj1c0ce7a2009-07-01 08:10:49 +0000623 tl_assert(cas->addr != NULL);
624 tl_assert(cas->dataLo != NULL);
625 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
626 if (cas->dataHi != NULL)
627 dataSize *= 2; /* since it's a doubleword-CAS */
bartb63dc782011-12-12 19:18:26 +0000628
629 if (UNLIKELY(DRD_(any_address_is_traced)())) {
630 if (cas->dataHi) {
631 IRExpr* data_expr;
632
633 tl_assert(typeOfIRExpr(bb->tyenv, cas->dataLo) == Ity_I32);
634 data_expr
635 = IRExpr_Binop(
636 Iop_Or64,
637 IRExpr_Binop(
638 Iop_Shl64,
639 IRExpr_Unop(Iop_32Uto64, cas->dataHi),
640 mkIRExpr_HWord(32)),
641 IRExpr_Unop(Iop_32Uto64, cas->dataLo));
642 instr_trace_mem_store(bb, cas->addr, data_expr);
643 } else {
644 instr_trace_mem_store(bb, cas->addr, cas->dataLo);
645 }
646 }
647
648 instrument_load(bb, cas->addr, dataSize);
sewardj1c0ce7a2009-07-01 08:10:49 +0000649 }
650 addStmtToIRSB(bb, st);
651 break;
652
sewardjdb5907d2009-11-26 17:20:21 +0000653 case Ist_LLSC: {
bartea692152011-12-11 20:17:57 +0000654 /*
655 * Ignore store-conditionals (except for tracing), and handle
656 * load-linked's exactly like normal loads.
657 */
sewardjdb5907d2009-11-26 17:20:21 +0000658 IRType dataTy;
bartb63dc782011-12-12 19:18:26 +0000659
bartea692152011-12-11 20:17:57 +0000660 if (st->Ist.LLSC.storedata == NULL) {
sewardjdb5907d2009-11-26 17:20:21 +0000661 /* LL */
662 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
bartb63dc782011-12-12 19:18:26 +0000663 if (instrument) {
664 if (UNLIKELY(DRD_(any_address_is_traced)()))
665 instr_trace_mem_load(bb, st->Ist.LLSC.addr,
666 sizeofIRType(dataTy));
667
668 instrument_load(bb, st->Ist.LLSC.addr, sizeofIRType(dataTy));
669 }
bartea692152011-12-11 20:17:57 +0000670 } else {
sewardjdb5907d2009-11-26 17:20:21 +0000671 /* SC */
bartb63dc782011-12-12 19:18:26 +0000672 instr_trace_mem_store(bb, st->Ist.LLSC.addr,
673 st->Ist.LLSC.storedata);
sewardjdb5907d2009-11-26 17:20:21 +0000674 }
bartbedfd232009-03-26 19:07:15 +0000675 addStmtToIRSB(bb, st);
676 break;
bart09dc13f2009-02-14 15:13:31 +0000677 }
sewardjdb5907d2009-11-26 17:20:21 +0000678
679 case Ist_NoOp:
680 case Ist_AbiHint:
681 case Ist_Put:
682 case Ist_PutI:
683 case Ist_Exit:
684 /* None of these can contain any memory references. */
685 addStmtToIRSB(bb, st);
686 break;
687
688 default:
689 ppIRStmt(st);
690 tl_assert(0);
691 }
bartbedfd232009-03-26 19:07:15 +0000692 }
bart09dc13f2009-02-14 15:13:31 +0000693
bartbedfd232009-03-26 19:07:15 +0000694 return bb;
bart09dc13f2009-02-14 15:13:31 +0000695}
696