blob: 88e4d44e1f0ef277d4de7a610f42fb15cde8ccc6 [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
bartd4bab992013-10-04 05:55:30 +00004 Copyright (C) 2006-2013 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
carllcae0cc22014-08-07 23:17:29 +000046#elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
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
sewardjf0c12502014-01-12 12:54:00 +000050#elif defined(VGA_arm64)
sewardj03451882014-01-15 10:25:55 +000051#define STACK_POINTER_OFFSET OFFSET_arm64_XSP
sewardjb5b87402011-03-07 16:05:35 +000052#elif defined(VGA_s390x)
53#define STACK_POINTER_OFFSET OFFSET_s390x_r15
sewardj5db15402012-06-07 09:13:21 +000054#elif defined(VGA_mips32)
55#define STACK_POINTER_OFFSET OFFSET_mips32_r29
petarj4df0bfc2013-02-27 23:17:33 +000056#elif defined(VGA_mips64)
57#define STACK_POINTER_OFFSET OFFSET_mips64_r29
sewardj112711a2015-04-10 12:30:09 +000058#elif defined(VGA_tilegx)
59#define STACK_POINTER_OFFSET OFFSET_tilegx_r54
bart09dc13f2009-02-14 15:13:31 +000060#else
61#error Unknown architecture.
62#endif
63
64
65/* Local variables. */
66
bartf98a5692009-05-03 17:17:37 +000067static Bool s_check_stack_accesses = False;
68static Bool s_first_race_only = False;
bart09dc13f2009-02-14 15:13:31 +000069
70
71/* Function definitions. */
72
73Bool DRD_(get_check_stack_accesses)()
74{
bartf98a5692009-05-03 17:17:37 +000075 return s_check_stack_accesses;
bart09dc13f2009-02-14 15:13:31 +000076}
77
78void DRD_(set_check_stack_accesses)(const Bool c)
79{
bartbedfd232009-03-26 19:07:15 +000080 tl_assert(c == False || c == True);
bartf98a5692009-05-03 17:17:37 +000081 s_check_stack_accesses = c;
82}
83
84Bool DRD_(get_first_race_only)()
85{
86 return s_first_race_only;
87}
88
89void DRD_(set_first_race_only)(const Bool fro)
90{
91 tl_assert(fro == False || fro == True);
92 s_first_race_only = fro;
bart09dc13f2009-02-14 15:13:31 +000093}
94
bart1335ecc2009-02-14 16:10:53 +000095void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bart7826acb2011-12-11 18:49:39 +000096 const BmAccessTypeT access_type,
bart42f32632011-12-13 11:12:05 +000097 const HWord stored_value_hi,
98 const HWord stored_value_lo)
bart09dc13f2009-02-14 15:13:31 +000099{
bartbedfd232009-03-26 19:07:15 +0000100 if (DRD_(is_any_traced)(addr, addr + size))
101 {
florian19f91bb2012-11-10 22:29:54 +0000102 HChar* vc;
bart8f822af2009-06-08 18:20:42 +0000103
104 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bart7826acb2011-12-11 18:49:39 +0000105 if (access_type == eStore && size <= sizeof(HWord)) {
bart5cda1b52011-12-12 19:37:10 +0000106 DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %ld/0x%lx (thread %d /"
bart42f32632011-12-13 11:12:05 +0000107 " vc %s)", addr, size, stored_value_lo,
108 stored_value_lo, DRD_(thread_get_running_tid)(),
109 vc);
110 } else if (access_type == eStore && size > sizeof(HWord)) {
111 ULong sv;
112
113 tl_assert(sizeof(HWord) == 4);
114 sv = ((ULong)stored_value_hi << 32) | stored_value_lo;
115 DRD_(trace_msg_w_bt)("store 0x%lx size %ld val %lld/0x%llx (thread %d"
116 " / vc %s)", addr, size, sv, sv,
bart7826acb2011-12-11 18:49:39 +0000117 DRD_(thread_get_running_tid)(), vc);
118 } else {
119 DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
120 access_type == eLoad ? "load "
121 : access_type == eStore ? "store"
122 : access_type == eStart ? "start"
123 : access_type == eEnd ? "end " : "????",
124 addr, size, DRD_(thread_get_running_tid)(), vc);
125 }
bart8f822af2009-06-08 18:20:42 +0000126 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000127 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
128 == VG_(get_running_tid)());
129 }
bart09dc13f2009-02-14 15:13:31 +0000130}
131
bart07595032010-08-29 09:51:06 +0000132static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000133{
bart42f32632011-12-13 11:12:05 +0000134 return DRD_(trace_mem_access)(addr, size, eLoad, 0, 0);
bart09dc13f2009-02-14 15:13:31 +0000135}
136
bart7826acb2011-12-11 18:49:39 +0000137static VG_REGPARM(3) void drd_trace_mem_store(const Addr addr,const SizeT size,
bart42f32632011-12-13 11:12:05 +0000138 const HWord stored_value_hi,
139 const HWord stored_value_lo)
bart09dc13f2009-02-14 15:13:31 +0000140{
bart42f32632011-12-13 11:12:05 +0000141 return DRD_(trace_mem_access)(addr, size, eStore, stored_value_hi,
142 stored_value_lo);
bart09dc13f2009-02-14 15:13:31 +0000143}
144
145static void drd_report_race(const Addr addr, const SizeT size,
146 const BmAccessTypeT access_type)
147{
bart7a9db0f2012-04-01 14:40:16 +0000148 ThreadId vg_tid;
bart09dc13f2009-02-14 15:13:31 +0000149
bart7a9db0f2012-04-01 14:40:16 +0000150 vg_tid = VG_(get_running_tid)();
bart7886dd32012-04-01 15:06:57 +0000151 if (!DRD_(get_check_stack_accesses)()
152 && DRD_(thread_address_on_any_stack)(addr)) {
bart7a9db0f2012-04-01 14:40:16 +0000153#if 0
154 GenericErrInfo GEI = {
155 .tid = DRD_(thread_get_running_tid)(),
156 .addr = addr,
157 };
158 VG_(maybe_record_error)(vg_tid, GenericErr, VG_(get_IP)(vg_tid),
159 "--check-stack-var=no skips checking stack"
160 " variables shared over threads",
161 &GEI);
162#endif
163 } else {
164 DataRaceErrInfo drei = {
165 .tid = DRD_(thread_get_running_tid)(),
166 .addr = addr,
167 .size = size,
168 .access_type = access_type,
169 };
170 VG_(maybe_record_error)(vg_tid, DataRaceErr, VG_(get_IP)(vg_tid),
171 "Conflicting access", &drei);
bartf98a5692009-05-03 17:17:37 +0000172
bart7a9db0f2012-04-01 14:40:16 +0000173 if (s_first_race_only)
174 DRD_(start_suppression)(addr, addr + size, "first race only");
bartf98a5692009-05-03 17:17:37 +0000175 }
bart09dc13f2009-02-14 15:13:31 +0000176}
177
bart99edb292009-02-15 15:59:20 +0000178VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000179{
180#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000181 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000182 tl_assert(DRD_(thread_get_running_tid)()
183 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000184#endif
185
bartd45d9952009-05-31 18:53:54 +0000186 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000187 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000188 || ! DRD_(thread_address_on_stack)(addr))
189 && bm_access_load_triggers_conflict(addr, addr + size)
190 && ! DRD_(is_suppressed)(addr, addr + size))
191 {
192 drd_report_race(addr, size, eLoad);
193 }
bart09dc13f2009-02-14 15:13:31 +0000194}
195
196static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
197{
bartd45d9952009-05-31 18:53:54 +0000198 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000199 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000200 || ! DRD_(thread_address_on_stack)(addr))
201 && bm_access_load_1_triggers_conflict(addr)
202 && ! DRD_(is_suppressed)(addr, addr + 1))
203 {
204 drd_report_race(addr, 1, eLoad);
205 }
bart09dc13f2009-02-14 15:13:31 +0000206}
207
208static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
209{
bartd45d9952009-05-31 18:53:54 +0000210 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000211 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000212 || ! DRD_(thread_address_on_stack)(addr))
213 && bm_access_load_2_triggers_conflict(addr)
214 && ! DRD_(is_suppressed)(addr, addr + 2))
215 {
216 drd_report_race(addr, 2, eLoad);
217 }
bart09dc13f2009-02-14 15:13:31 +0000218}
219
220static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
221{
bartd45d9952009-05-31 18:53:54 +0000222 if (DRD_(running_thread_is_recording_loads)()
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_load_4_triggers_conflict(addr)
226 && ! DRD_(is_suppressed)(addr, addr + 4))
227 {
228 drd_report_race(addr, 4, eLoad);
229 }
bart09dc13f2009-02-14 15:13:31 +0000230}
231
232static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
233{
bartd45d9952009-05-31 18:53:54 +0000234 if (DRD_(running_thread_is_recording_loads)()
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_load_8_triggers_conflict(addr)
238 && ! DRD_(is_suppressed)(addr, addr + 8))
239 {
240 drd_report_race(addr, 8, eLoad);
241 }
bart09dc13f2009-02-14 15:13:31 +0000242}
243
bart99edb292009-02-15 15:59:20 +0000244VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000245{
246#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000247 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000248 tl_assert(DRD_(thread_get_running_tid)()
249 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
bart09dc13f2009-02-14 15:13:31 +0000250#endif
251
bartd45d9952009-05-31 18:53:54 +0000252 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000253 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000254 || ! DRD_(thread_address_on_stack)(addr))
255 && bm_access_store_triggers_conflict(addr, addr + size)
256 && ! DRD_(is_suppressed)(addr, addr + size))
257 {
258 drd_report_race(addr, size, eStore);
259 }
bart09dc13f2009-02-14 15:13:31 +0000260}
261
262static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
263{
bartd45d9952009-05-31 18:53:54 +0000264 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000265 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000266 || ! DRD_(thread_address_on_stack)(addr))
267 && bm_access_store_1_triggers_conflict(addr)
268 && ! DRD_(is_suppressed)(addr, addr + 1))
269 {
270 drd_report_race(addr, 1, eStore);
271 }
bart09dc13f2009-02-14 15:13:31 +0000272}
273
274static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
275{
bartd45d9952009-05-31 18:53:54 +0000276 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000277 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000278 || ! DRD_(thread_address_on_stack)(addr))
279 && bm_access_store_2_triggers_conflict(addr)
280 && ! DRD_(is_suppressed)(addr, addr + 2))
281 {
282 drd_report_race(addr, 2, eStore);
283 }
bart09dc13f2009-02-14 15:13:31 +0000284}
285
286static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
287{
bartd45d9952009-05-31 18:53:54 +0000288 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000289 && (s_check_stack_accesses
bart71ce1322011-12-11 17:54:17 +0000290 || !DRD_(thread_address_on_stack)(addr))
bartbedfd232009-03-26 19:07:15 +0000291 && bm_access_store_4_triggers_conflict(addr)
bart71ce1322011-12-11 17:54:17 +0000292 && !DRD_(is_suppressed)(addr, addr + 4))
bartbedfd232009-03-26 19:07:15 +0000293 {
294 drd_report_race(addr, 4, eStore);
295 }
bart09dc13f2009-02-14 15:13:31 +0000296}
297
298static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
299{
bartd45d9952009-05-31 18:53:54 +0000300 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000301 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000302 || ! DRD_(thread_address_on_stack)(addr))
303 && bm_access_store_8_triggers_conflict(addr)
304 && ! DRD_(is_suppressed)(addr, addr + 8))
305 {
306 drd_report_race(addr, 8, eStore);
307 }
bart09dc13f2009-02-14 15:13:31 +0000308}
309
310/**
311 * Return true if and only if addr_expr matches the pattern (SP) or
312 * <offset>(SP).
313 */
314static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
315{
bartbedfd232009-03-26 19:07:15 +0000316 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000317
bartbedfd232009-03-26 19:07:15 +0000318 if (addr_expr->tag == Iex_RdTmp)
319 {
320 int i;
sewardj528b3502012-12-27 17:46:10 +0000321 for (i = 0; i < bb->stmts_used; i++)
bart09dc13f2009-02-14 15:13:31 +0000322 {
bartbedfd232009-03-26 19:07:15 +0000323 if (bb->stmts[i]
324 && bb->stmts[i]->tag == Ist_WrTmp
325 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
326 {
327 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
328 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
329 {
330 result = True;
331 }
bart09dc13f2009-02-14 15:13:31 +0000332
bartbedfd232009-03-26 19:07:15 +0000333 //ppIRExpr(e);
334 //VG_(printf)(" (%s)\n", result ? "True" : "False");
335 break;
336 }
bart09dc13f2009-02-14 15:13:31 +0000337 }
bartbedfd232009-03-26 19:07:15 +0000338 }
339 return result;
bart09dc13f2009-02-14 15:13:31 +0000340}
341
bartea692152011-12-11 20:17:57 +0000342static const IROp u_widen_irop[5][9] = {
bart9ad8d802011-12-12 19:54:32 +0000343 [Ity_I1 - Ity_I1] = { [4] = Iop_1Uto32, [8] = Iop_1Uto64 },
344 [Ity_I8 - Ity_I1] = { [4] = Iop_8Uto32, [8] = Iop_8Uto64 },
345 [Ity_I16 - Ity_I1] = { [4] = Iop_16Uto32, [8] = Iop_16Uto64 },
346 [Ity_I32 - Ity_I1] = { [8] = Iop_32Uto64 },
bartea692152011-12-11 20:17:57 +0000347};
348
bartb63dc782011-12-12 19:18:26 +0000349/**
350 * Instrument the client code to trace a memory load (--trace-addr).
351 */
bart25026ef2011-12-17 12:59:45 +0000352static IRExpr* instr_trace_mem_load(IRSB* const bb, IRExpr* addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000353 const HWord size,
354 IRExpr* const guard/* NULL => True */)
bartea692152011-12-11 20:17:57 +0000355{
bart25026ef2011-12-17 12:59:45 +0000356 IRTemp tmp;
357
358 tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
359 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
360 addr_expr = IRExpr_RdTmp(tmp);
sewardjcafe5052013-01-17 14:24:35 +0000361 IRDirty* di
362 = unsafeIRDirty_0_N(/*regparms*/2,
363 "drd_trace_mem_load",
364 VG_(fnptr_to_fnentry)
365 (drd_trace_mem_load),
366 mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)));
367 if (guard) di->guard = guard;
368 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart25026ef2011-12-17 12:59:45 +0000369
370 return addr_expr;
bartb63dc782011-12-12 19:18:26 +0000371}
372
373/**
374 * Instrument the client code to trace a memory store (--trace-addr).
375 */
376static void instr_trace_mem_store(IRSB* const bb, IRExpr* const addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000377 IRExpr* data_expr_hi, IRExpr* data_expr_lo,
378 IRExpr* const guard/* NULL => True */)
bartb63dc782011-12-12 19:18:26 +0000379{
380 IRType ty_data_expr;
bartea692152011-12-11 20:17:57 +0000381 HWord size;
382
bartb63dc782011-12-12 19:18:26 +0000383 tl_assert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
bart42f32632011-12-13 11:12:05 +0000384 tl_assert(!data_expr_hi || typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I32);
bartea692152011-12-11 20:17:57 +0000385
bart42f32632011-12-13 11:12:05 +0000386 ty_data_expr = typeOfIRExpr(bb->tyenv, data_expr_lo);
bartb63dc782011-12-12 19:18:26 +0000387 size = sizeofIRType(ty_data_expr);
388
bart7ca75ed2011-12-13 08:53:23 +0000389#if 0
390 // Test code
391 if (ty_data_expr == Ity_I32) {
392 IRTemp tmp = newIRTemp(bb->tyenv, Ity_F32);
bart42f32632011-12-13 11:12:05 +0000393 data_expr_lo = IRExpr_Unop(Iop_ReinterpI32asF32, data_expr_lo);
394 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
395 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000396 ty_data_expr = Ity_F32;
397 } else if (ty_data_expr == Ity_I64) {
398 IRTemp tmp = newIRTemp(bb->tyenv, Ity_F64);
bart42f32632011-12-13 11:12:05 +0000399 data_expr_lo = IRExpr_Unop(Iop_ReinterpI64asF64, data_expr_lo);
400 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
401 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000402 ty_data_expr = Ity_F64;
403 }
404#endif
405
406 if (ty_data_expr == Ity_F32) {
407 IRTemp tmp = newIRTemp(bb->tyenv, Ity_I32);
408 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF32asI32,
bart42f32632011-12-13 11:12:05 +0000409 data_expr_lo)));
410 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000411 ty_data_expr = Ity_I32;
412 } else if (ty_data_expr == Ity_F64) {
413 IRTemp tmp = newIRTemp(bb->tyenv, Ity_I64);
414 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF64asI64,
bart42f32632011-12-13 11:12:05 +0000415 data_expr_lo)));
416 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000417 ty_data_expr = Ity_I64;
418 }
419
bartb63dc782011-12-12 19:18:26 +0000420 if (size == sizeof(HWord)
421 && (ty_data_expr == Ity_I32 || ty_data_expr == Ity_I64))
422 {
423 /* No conversion necessary */
bartea692152011-12-11 20:17:57 +0000424 } else {
425 IROp widen_op;
426
bartb63dc782011-12-12 19:18:26 +0000427 if (Ity_I1 <= ty_data_expr
428 && ty_data_expr
429 < Ity_I1 + sizeof(u_widen_irop)/sizeof(u_widen_irop[0]))
430 {
431 widen_op = u_widen_irop[ty_data_expr - Ity_I1][sizeof(HWord)];
bartea692152011-12-11 20:17:57 +0000432 if (!widen_op)
433 widen_op = Iop_INVALID;
434 } else {
435 widen_op = Iop_INVALID;
436 }
437 if (widen_op != Iop_INVALID) {
438 IRTemp tmp;
439
bartb63dc782011-12-12 19:18:26 +0000440 /* Widen the integer expression to a HWord */
bartea692152011-12-11 20:17:57 +0000441 tmp = newIRTemp(bb->tyenv, sizeof(HWord) == 4 ? Ity_I32 : Ity_I64);
442 addStmtToIRSB(bb,
bart42f32632011-12-13 11:12:05 +0000443 IRStmt_WrTmp(tmp, IRExpr_Unop(widen_op, data_expr_lo)));
444 data_expr_lo = IRExpr_RdTmp(tmp);
445 } else if (size > sizeof(HWord) && !data_expr_hi
446 && ty_data_expr == Ity_I64) {
447 IRTemp tmp;
448
449 tl_assert(sizeof(HWord) == 4);
450 tl_assert(size == 8);
451 tmp = newIRTemp(bb->tyenv, Ity_I32);
452 addStmtToIRSB(bb,
453 IRStmt_WrTmp(tmp,
454 IRExpr_Unop(Iop_64HIto32, data_expr_lo)));
455 data_expr_hi = IRExpr_RdTmp(tmp);
456 tmp = newIRTemp(bb->tyenv, Ity_I32);
457 addStmtToIRSB(bb, IRStmt_WrTmp(tmp,
458 IRExpr_Unop(Iop_64to32, data_expr_lo)));
459 data_expr_lo = IRExpr_RdTmp(tmp);
bartea692152011-12-11 20:17:57 +0000460 } else {
bart42f32632011-12-13 11:12:05 +0000461 data_expr_lo = mkIRExpr_HWord(0);
bartea692152011-12-11 20:17:57 +0000462 }
463 }
sewardjcafe5052013-01-17 14:24:35 +0000464 IRDirty* di
465 = unsafeIRDirty_0_N(/*regparms*/3,
466 "drd_trace_mem_store",
467 VG_(fnptr_to_fnentry)(drd_trace_mem_store),
468 mkIRExprVec_4(addr_expr, mkIRExpr_HWord(size),
469 data_expr_hi ? data_expr_hi
470 : mkIRExpr_HWord(0), data_expr_lo));
471 if (guard) di->guard = guard;
472 addStmtToIRSB(bb, IRStmt_Dirty(di) );
bartea692152011-12-11 20:17:57 +0000473}
474
475static void instrument_load(IRSB* const bb, IRExpr* const addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000476 const HWord size,
477 IRExpr* const guard/* NULL => True */)
bart09dc13f2009-02-14 15:13:31 +0000478{
bartbedfd232009-03-26 19:07:15 +0000479 IRExpr* size_expr;
480 IRExpr** argv;
481 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000482
bartea692152011-12-11 20:17:57 +0000483 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000484 return;
bart09dc13f2009-02-14 15:13:31 +0000485
bartbedfd232009-03-26 19:07:15 +0000486 switch (size)
487 {
488 case 1:
489 argv = mkIRExprVec_1(addr_expr);
490 di = unsafeIRDirty_0_N(/*regparms*/1,
491 "drd_trace_load_1",
492 VG_(fnptr_to_fnentry)(drd_trace_load_1),
493 argv);
494 break;
495 case 2:
496 argv = mkIRExprVec_1(addr_expr);
497 di = unsafeIRDirty_0_N(/*regparms*/1,
498 "drd_trace_load_2",
499 VG_(fnptr_to_fnentry)(drd_trace_load_2),
500 argv);
501 break;
502 case 4:
503 argv = mkIRExprVec_1(addr_expr);
504 di = unsafeIRDirty_0_N(/*regparms*/1,
505 "drd_trace_load_4",
506 VG_(fnptr_to_fnentry)(drd_trace_load_4),
507 argv);
508 break;
509 case 8:
510 argv = mkIRExprVec_1(addr_expr);
511 di = unsafeIRDirty_0_N(/*regparms*/1,
512 "drd_trace_load_8",
513 VG_(fnptr_to_fnentry)(drd_trace_load_8),
514 argv);
515 break;
516 default:
517 size_expr = mkIRExpr_HWord(size);
518 argv = mkIRExprVec_2(addr_expr, size_expr);
519 di = unsafeIRDirty_0_N(/*regparms*/2,
520 "drd_trace_load",
521 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
522 argv);
523 break;
524 }
sewardjcafe5052013-01-17 14:24:35 +0000525 if (guard) di->guard = guard;
bartbedfd232009-03-26 19:07:15 +0000526 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000527}
528
bart25026ef2011-12-17 12:59:45 +0000529static void instrument_store(IRSB* const bb, IRExpr* addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000530 IRExpr* const data_expr,
531 IRExpr* const guard_expr/* NULL => True */)
bart09dc13f2009-02-14 15:13:31 +0000532{
bartbedfd232009-03-26 19:07:15 +0000533 IRExpr* size_expr;
534 IRExpr** argv;
535 IRDirty* di;
bart7826acb2011-12-11 18:49:39 +0000536 HWord size;
537
538 size = sizeofIRType(typeOfIRExpr(bb->tyenv, data_expr));
bart09dc13f2009-02-14 15:13:31 +0000539
bart25026ef2011-12-17 12:59:45 +0000540 if (UNLIKELY(DRD_(any_address_is_traced)())) {
541 IRTemp tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
542 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
543 addr_expr = IRExpr_RdTmp(tmp);
sewardjcafe5052013-01-17 14:24:35 +0000544 instr_trace_mem_store(bb, addr_expr, NULL, data_expr, guard_expr);
bart25026ef2011-12-17 12:59:45 +0000545 }
bart09dc13f2009-02-14 15:13:31 +0000546
bart71ce1322011-12-11 17:54:17 +0000547 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000548 return;
bart09dc13f2009-02-14 15:13:31 +0000549
bartbedfd232009-03-26 19:07:15 +0000550 switch (size)
551 {
552 case 1:
553 argv = mkIRExprVec_1(addr_expr);
554 di = unsafeIRDirty_0_N(/*regparms*/1,
555 "drd_trace_store_1",
556 VG_(fnptr_to_fnentry)(drd_trace_store_1),
557 argv);
558 break;
559 case 2:
560 argv = mkIRExprVec_1(addr_expr);
561 di = unsafeIRDirty_0_N(/*regparms*/1,
562 "drd_trace_store_2",
563 VG_(fnptr_to_fnentry)(drd_trace_store_2),
564 argv);
565 break;
566 case 4:
567 argv = mkIRExprVec_1(addr_expr);
568 di = unsafeIRDirty_0_N(/*regparms*/1,
569 "drd_trace_store_4",
570 VG_(fnptr_to_fnentry)(drd_trace_store_4),
571 argv);
572 break;
573 case 8:
574 argv = mkIRExprVec_1(addr_expr);
575 di = unsafeIRDirty_0_N(/*regparms*/1,
576 "drd_trace_store_8",
577 VG_(fnptr_to_fnentry)(drd_trace_store_8),
578 argv);
579 break;
580 default:
581 size_expr = mkIRExpr_HWord(size);
582 argv = mkIRExprVec_2(addr_expr, size_expr);
583 di = unsafeIRDirty_0_N(/*regparms*/2,
584 "drd_trace_store",
585 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
586 argv);
587 break;
588 }
sewardjcafe5052013-01-17 14:24:35 +0000589 if (guard_expr) di->guard = guard_expr;
bartbedfd232009-03-26 19:07:15 +0000590 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000591}
592
bart1335ecc2009-02-14 16:10:53 +0000593IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000594 IRSB* const bb_in,
florian3c0c9472014-09-24 12:06:55 +0000595 const VexGuestLayout* const layout,
596 const VexGuestExtents* const vge,
597 const VexArchInfo* archinfo_host,
bartbedfd232009-03-26 19:07:15 +0000598 IRType const gWordTy,
599 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000600{
bartbedfd232009-03-26 19:07:15 +0000601 IRDirty* di;
602 Int i;
603 IRSB* bb;
604 IRExpr** argv;
605 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000606
bartbedfd232009-03-26 19:07:15 +0000607 /* Set up BB */
608 bb = emptyIRSB();
609 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
610 bb->next = deepCopyIRExpr(bb_in->next);
611 bb->jumpkind = bb_in->jumpkind;
sewardj291849f2012-04-20 23:58:55 +0000612 bb->offsIP = bb_in->offsIP;
bart09dc13f2009-02-14 15:13:31 +0000613
bartbedfd232009-03-26 19:07:15 +0000614 for (i = 0; i < bb_in->stmts_used; i++)
615 {
616 IRStmt* const st = bb_in->stmts[i];
617 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000618 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000619
bartbedfd232009-03-26 19:07:15 +0000620 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000621 {
bartbedfd232009-03-26 19:07:15 +0000622 /* Note: the code for not instrumenting the code in .plt */
623 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
624 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
625 /* This is because on this platform dynamic library symbols are */
626 /* relocated in another way than by later binutils versions. The */
627 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
628 case Ist_IMark:
floriane08950b2014-11-13 21:41:28 +0000629 instrument = VG_(DebugInfo_sect_kind)(NULL, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000630 != Vg_SectPLT;
631 addStmtToIRSB(bb, st);
632 break;
633
634 case Ist_MBE:
635 switch (st->Ist.MBE.event)
636 {
637 case Imbe_Fence:
bartb68c9472014-09-18 07:11:24 +0000638 break; /* not interesting to DRD */
639 case Imbe_CancelReservation:
640 break; /* not interesting to DRD */
bartbedfd232009-03-26 19:07:15 +0000641 default:
642 tl_assert(0);
643 }
644 addStmtToIRSB(bb, st);
645 break;
646
647 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000648 if (instrument)
sewardjcafe5052013-01-17 14:24:35 +0000649 instrument_store(bb, st->Ist.Store.addr, st->Ist.Store.data,
650 NULL/* no guard */);
bartbedfd232009-03-26 19:07:15 +0000651 addStmtToIRSB(bb, st);
652 break;
653
sewardjcafe5052013-01-17 14:24:35 +0000654 case Ist_StoreG: {
655 IRStoreG* sg = st->Ist.StoreG.details;
656 IRExpr* data = sg->data;
657 IRExpr* addr = sg->addr;
658 if (instrument)
659 instrument_store(bb, addr, data, sg->guard);
660 addStmtToIRSB(bb, st);
661 break;
662 }
663
664 case Ist_LoadG: {
665 IRLoadG* lg = st->Ist.LoadG.details;
666 IRType type = Ity_INVALID; /* loaded type */
667 IRType typeWide = Ity_INVALID; /* after implicit widening */
668 IRExpr* addr_expr = lg->addr;
669 typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
670 tl_assert(type != Ity_INVALID);
671 if (UNLIKELY(DRD_(any_address_is_traced)())) {
672 addr_expr = instr_trace_mem_load(bb, addr_expr,
673 sizeofIRType(type), lg->guard);
674 }
675 instrument_load(bb, lg->addr,
676 sizeofIRType(type), lg->guard);
677 addStmtToIRSB(bb, st);
678 break;
679 }
680
bartbedfd232009-03-26 19:07:15 +0000681 case Ist_WrTmp:
bartea692152011-12-11 20:17:57 +0000682 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000683 const IRExpr* const data = st->Ist.WrTmp.data;
bart25026ef2011-12-17 12:59:45 +0000684 IRExpr* addr_expr = data->Iex.Load.addr;
bartb63dc782011-12-12 19:18:26 +0000685 if (data->tag == Iex_Load) {
bart25026ef2011-12-17 12:59:45 +0000686 if (UNLIKELY(DRD_(any_address_is_traced)())) {
687 addr_expr = instr_trace_mem_load(bb, addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000688 sizeofIRType(data->Iex.Load.ty),
689 NULL/* no guard */);
bart25026ef2011-12-17 12:59:45 +0000690 }
bart19fb8d72013-01-27 10:58:47 +0000691 instrument_load(bb, addr_expr, sizeofIRType(data->Iex.Load.ty),
sewardjcafe5052013-01-17 14:24:35 +0000692 NULL/* no guard */);
bartb63dc782011-12-12 19:18:26 +0000693 }
bartbedfd232009-03-26 19:07:15 +0000694 }
695 addStmtToIRSB(bb, st);
696 break;
697
698 case Ist_Dirty:
bartb63dc782011-12-12 19:18:26 +0000699 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000700 IRDirty* d = st->Ist.Dirty.details;
701 IREffect const mFx = d->mFx;
702 switch (mFx) {
703 case Ifx_None:
704 break;
705 case Ifx_Read:
706 case Ifx_Write:
707 case Ifx_Modify:
708 tl_assert(d->mAddr);
709 tl_assert(d->mSize > 0);
710 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
711 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
712 di = unsafeIRDirty_0_N(
713 /*regparms*/2,
714 "drd_trace_load",
715 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
716 argv);
717 addStmtToIRSB(bb, IRStmt_Dirty(di));
718 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000719 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000720 {
721 di = unsafeIRDirty_0_N(
722 /*regparms*/2,
723 "drd_trace_store",
724 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
725 argv);
726 addStmtToIRSB(bb, IRStmt_Dirty(di));
727 }
728 break;
729 default:
730 tl_assert(0);
731 }
732 }
733 addStmtToIRSB(bb, st);
734 break;
735
sewardj1c0ce7a2009-07-01 08:10:49 +0000736 case Ist_CAS:
bartb63dc782011-12-12 19:18:26 +0000737 if (instrument) {
barta14e3282009-07-11 14:35:59 +0000738 /*
739 * Treat compare-and-swap as a read. By handling atomic
740 * instructions as read instructions no data races are reported
741 * between conflicting atomic operations nor between atomic
742 * operations and non-atomic reads. Conflicts between atomic
743 * operations and non-atomic write operations are still reported
744 * however.
745 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000746 Int dataSize;
747 IRCAS* cas = st->Ist.CAS.details;
bartb63dc782011-12-12 19:18:26 +0000748
sewardj1c0ce7a2009-07-01 08:10:49 +0000749 tl_assert(cas->addr != NULL);
750 tl_assert(cas->dataLo != NULL);
751 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
752 if (cas->dataHi != NULL)
753 dataSize *= 2; /* since it's a doubleword-CAS */
bartb63dc782011-12-12 19:18:26 +0000754
bart42f32632011-12-13 11:12:05 +0000755 if (UNLIKELY(DRD_(any_address_is_traced)()))
sewardjcafe5052013-01-17 14:24:35 +0000756 instr_trace_mem_store(bb, cas->addr, cas->dataHi, cas->dataLo,
757 NULL/* no guard */);
bartb63dc782011-12-12 19:18:26 +0000758
sewardjcafe5052013-01-17 14:24:35 +0000759 instrument_load(bb, cas->addr, dataSize, NULL/*no guard*/);
sewardj1c0ce7a2009-07-01 08:10:49 +0000760 }
761 addStmtToIRSB(bb, st);
762 break;
763
sewardjdb5907d2009-11-26 17:20:21 +0000764 case Ist_LLSC: {
bartea692152011-12-11 20:17:57 +0000765 /*
766 * Ignore store-conditionals (except for tracing), and handle
767 * load-linked's exactly like normal loads.
768 */
sewardjdb5907d2009-11-26 17:20:21 +0000769 IRType dataTy;
bartb63dc782011-12-12 19:18:26 +0000770
bartea692152011-12-11 20:17:57 +0000771 if (st->Ist.LLSC.storedata == NULL) {
sewardjdb5907d2009-11-26 17:20:21 +0000772 /* LL */
773 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
bartb63dc782011-12-12 19:18:26 +0000774 if (instrument) {
bart25026ef2011-12-17 12:59:45 +0000775 IRExpr* addr_expr = st->Ist.LLSC.addr;
bartb63dc782011-12-12 19:18:26 +0000776 if (UNLIKELY(DRD_(any_address_is_traced)()))
bart25026ef2011-12-17 12:59:45 +0000777 addr_expr = instr_trace_mem_load(bb, addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000778 sizeofIRType(dataTy),
779 NULL /* no guard */);
bartb63dc782011-12-12 19:18:26 +0000780
sewardjcafe5052013-01-17 14:24:35 +0000781 instrument_load(bb, addr_expr, sizeofIRType(dataTy),
782 NULL/*no guard*/);
bartb63dc782011-12-12 19:18:26 +0000783 }
bartea692152011-12-11 20:17:57 +0000784 } else {
sewardjdb5907d2009-11-26 17:20:21 +0000785 /* SC */
bart42f32632011-12-13 11:12:05 +0000786 instr_trace_mem_store(bb, st->Ist.LLSC.addr, NULL,
sewardjcafe5052013-01-17 14:24:35 +0000787 st->Ist.LLSC.storedata,
788 NULL/* no guard */);
sewardjdb5907d2009-11-26 17:20:21 +0000789 }
bartbedfd232009-03-26 19:07:15 +0000790 addStmtToIRSB(bb, st);
791 break;
bart09dc13f2009-02-14 15:13:31 +0000792 }
sewardjdb5907d2009-11-26 17:20:21 +0000793
794 case Ist_NoOp:
795 case Ist_AbiHint:
796 case Ist_Put:
797 case Ist_PutI:
798 case Ist_Exit:
799 /* None of these can contain any memory references. */
800 addStmtToIRSB(bb, st);
801 break;
802
803 default:
804 ppIRStmt(st);
805 tl_assert(0);
806 }
bartbedfd232009-03-26 19:07:15 +0000807 }
bart09dc13f2009-02-14 15:13:31 +0000808
bartbedfd232009-03-26 19:07:15 +0000809 return bb;
bart09dc13f2009-02-14 15:13:31 +0000810}
811