blob: 051f4f0673bab04ea90d4c2e4c63393c7ce2573b [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
Elliott Hughesed398002017-06-21 14:41:24 -07004 Copyright (C) 2006-2017 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
bart09dc13f2009-02-14 15:13:31 +000058#else
59#error Unknown architecture.
60#endif
61
62
63/* Local variables. */
64
bartf98a5692009-05-03 17:17:37 +000065static Bool s_check_stack_accesses = False;
66static Bool s_first_race_only = False;
bart09dc13f2009-02-14 15:13:31 +000067
68
69/* Function definitions. */
70
71Bool DRD_(get_check_stack_accesses)()
72{
bartf98a5692009-05-03 17:17:37 +000073 return s_check_stack_accesses;
bart09dc13f2009-02-14 15:13:31 +000074}
75
76void DRD_(set_check_stack_accesses)(const Bool c)
77{
bartbedfd232009-03-26 19:07:15 +000078 tl_assert(c == False || c == True);
bartf98a5692009-05-03 17:17:37 +000079 s_check_stack_accesses = c;
80}
81
82Bool DRD_(get_first_race_only)()
83{
84 return s_first_race_only;
85}
86
87void DRD_(set_first_race_only)(const Bool fro)
88{
89 tl_assert(fro == False || fro == True);
90 s_first_race_only = fro;
bart09dc13f2009-02-14 15:13:31 +000091}
92
bart1335ecc2009-02-14 16:10:53 +000093void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bart7826acb2011-12-11 18:49:39 +000094 const BmAccessTypeT access_type,
bart42f32632011-12-13 11:12:05 +000095 const HWord stored_value_hi,
96 const HWord stored_value_lo)
bart09dc13f2009-02-14 15:13:31 +000097{
bartbedfd232009-03-26 19:07:15 +000098 if (DRD_(is_any_traced)(addr, addr + size))
99 {
florian19f91bb2012-11-10 22:29:54 +0000100 HChar* vc;
bart8f822af2009-06-08 18:20:42 +0000101
102 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bart7826acb2011-12-11 18:49:39 +0000103 if (access_type == eStore && size <= sizeof(HWord)) {
florianea71ffb2015-08-05 14:38:57 +0000104 DRD_(trace_msg_w_bt)("store 0x%lx size %lu val %lu/0x%lx (thread %u /"
bart42f32632011-12-13 11:12:05 +0000105 " vc %s)", addr, size, stored_value_lo,
106 stored_value_lo, DRD_(thread_get_running_tid)(),
107 vc);
108 } else if (access_type == eStore && size > sizeof(HWord)) {
109 ULong sv;
110
111 tl_assert(sizeof(HWord) == 4);
112 sv = ((ULong)stored_value_hi << 32) | stored_value_lo;
florianea71ffb2015-08-05 14:38:57 +0000113 DRD_(trace_msg_w_bt)("store 0x%lx size %lu val %llu/0x%llx (thread %u"
bart42f32632011-12-13 11:12:05 +0000114 " / vc %s)", addr, size, sv, sv,
bart7826acb2011-12-11 18:49:39 +0000115 DRD_(thread_get_running_tid)(), vc);
116 } else {
florianea71ffb2015-08-05 14:38:57 +0000117 DRD_(trace_msg_w_bt)("%s 0x%lx size %lu (thread %u / vc %s)",
bart7826acb2011-12-11 18:49:39 +0000118 access_type == eLoad ? "load "
119 : access_type == eStore ? "store"
120 : access_type == eStart ? "start"
121 : access_type == eEnd ? "end " : "????",
122 addr, size, DRD_(thread_get_running_tid)(), vc);
123 }
bart8f822af2009-06-08 18:20:42 +0000124 VG_(free)(vc);
bartbedfd232009-03-26 19:07:15 +0000125 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
126 == VG_(get_running_tid)());
127 }
bart09dc13f2009-02-14 15:13:31 +0000128}
129
bart07595032010-08-29 09:51:06 +0000130static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000131{
bart42f32632011-12-13 11:12:05 +0000132 return DRD_(trace_mem_access)(addr, size, eLoad, 0, 0);
bart09dc13f2009-02-14 15:13:31 +0000133}
134
bart7826acb2011-12-11 18:49:39 +0000135static VG_REGPARM(3) void drd_trace_mem_store(const Addr addr,const SizeT size,
bart42f32632011-12-13 11:12:05 +0000136 const HWord stored_value_hi,
137 const HWord stored_value_lo)
bart09dc13f2009-02-14 15:13:31 +0000138{
bart42f32632011-12-13 11:12:05 +0000139 return DRD_(trace_mem_access)(addr, size, eStore, stored_value_hi,
140 stored_value_lo);
bart09dc13f2009-02-14 15:13:31 +0000141}
142
143static void drd_report_race(const Addr addr, const SizeT size,
144 const BmAccessTypeT access_type)
145{
bart7a9db0f2012-04-01 14:40:16 +0000146 ThreadId vg_tid;
bart09dc13f2009-02-14 15:13:31 +0000147
bart7a9db0f2012-04-01 14:40:16 +0000148 vg_tid = VG_(get_running_tid)();
bart7886dd32012-04-01 15:06:57 +0000149 if (!DRD_(get_check_stack_accesses)()
150 && DRD_(thread_address_on_any_stack)(addr)) {
bart7a9db0f2012-04-01 14:40:16 +0000151#if 0
152 GenericErrInfo GEI = {
153 .tid = DRD_(thread_get_running_tid)(),
154 .addr = addr,
155 };
156 VG_(maybe_record_error)(vg_tid, GenericErr, VG_(get_IP)(vg_tid),
157 "--check-stack-var=no skips checking stack"
158 " variables shared over threads",
159 &GEI);
160#endif
161 } else {
162 DataRaceErrInfo drei = {
163 .tid = DRD_(thread_get_running_tid)(),
164 .addr = addr,
165 .size = size,
166 .access_type = access_type,
167 };
168 VG_(maybe_record_error)(vg_tid, DataRaceErr, VG_(get_IP)(vg_tid),
169 "Conflicting access", &drei);
bartf98a5692009-05-03 17:17:37 +0000170
bart7a9db0f2012-04-01 14:40:16 +0000171 if (s_first_race_only)
172 DRD_(start_suppression)(addr, addr + size, "first race only");
bartf98a5692009-05-03 17:17:37 +0000173 }
bart09dc13f2009-02-14 15:13:31 +0000174}
175
bart99edb292009-02-15 15:59:20 +0000176VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000177{
178#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000179 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000180 tl_assert(DRD_(thread_get_running_tid)()
Elliott Hughesa0664b92017-04-18 17:46:52 -0700181 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid)()));
bart09dc13f2009-02-14 15:13:31 +0000182#endif
183
bartd45d9952009-05-31 18:53:54 +0000184 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000185 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000186 || ! DRD_(thread_address_on_stack)(addr))
187 && bm_access_load_triggers_conflict(addr, addr + size)
188 && ! DRD_(is_suppressed)(addr, addr + size))
189 {
190 drd_report_race(addr, size, eLoad);
191 }
bart09dc13f2009-02-14 15:13:31 +0000192}
193
194static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
195{
bartd45d9952009-05-31 18:53:54 +0000196 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000197 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000198 || ! DRD_(thread_address_on_stack)(addr))
199 && bm_access_load_1_triggers_conflict(addr)
200 && ! DRD_(is_suppressed)(addr, addr + 1))
201 {
202 drd_report_race(addr, 1, eLoad);
203 }
bart09dc13f2009-02-14 15:13:31 +0000204}
205
206static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
207{
bartd45d9952009-05-31 18:53:54 +0000208 if (DRD_(running_thread_is_recording_loads)()
bartf98a5692009-05-03 17:17:37 +0000209 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000210 || ! DRD_(thread_address_on_stack)(addr))
211 && bm_access_load_2_triggers_conflict(addr)
212 && ! DRD_(is_suppressed)(addr, addr + 2))
213 {
214 drd_report_race(addr, 2, eLoad);
215 }
bart09dc13f2009-02-14 15:13:31 +0000216}
217
218static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
219{
bartd45d9952009-05-31 18:53:54 +0000220 if (DRD_(running_thread_is_recording_loads)()
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_load_4_triggers_conflict(addr)
224 && ! DRD_(is_suppressed)(addr, addr + 4))
225 {
226 drd_report_race(addr, 4, eLoad);
227 }
bart09dc13f2009-02-14 15:13:31 +0000228}
229
230static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
231{
bartd45d9952009-05-31 18:53:54 +0000232 if (DRD_(running_thread_is_recording_loads)()
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_load_8_triggers_conflict(addr)
236 && ! DRD_(is_suppressed)(addr, addr + 8))
237 {
238 drd_report_race(addr, 8, eLoad);
239 }
bart09dc13f2009-02-14 15:13:31 +0000240}
241
bart99edb292009-02-15 15:59:20 +0000242VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000243{
244#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
bartbedfd232009-03-26 19:07:15 +0000245 /* The assert below has been commented out because of performance reasons.*/
bartd5bbc612010-09-02 14:44:17 +0000246 tl_assert(DRD_(thread_get_running_tid)()
Elliott Hughesa0664b92017-04-18 17:46:52 -0700247 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid)()));
bart09dc13f2009-02-14 15:13:31 +0000248#endif
249
bartd45d9952009-05-31 18:53:54 +0000250 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000251 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000252 || ! DRD_(thread_address_on_stack)(addr))
253 && bm_access_store_triggers_conflict(addr, addr + size)
254 && ! DRD_(is_suppressed)(addr, addr + size))
255 {
256 drd_report_race(addr, size, eStore);
257 }
bart09dc13f2009-02-14 15:13:31 +0000258}
259
260static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
261{
bartd45d9952009-05-31 18:53:54 +0000262 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000263 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000264 || ! DRD_(thread_address_on_stack)(addr))
265 && bm_access_store_1_triggers_conflict(addr)
266 && ! DRD_(is_suppressed)(addr, addr + 1))
267 {
268 drd_report_race(addr, 1, eStore);
269 }
bart09dc13f2009-02-14 15:13:31 +0000270}
271
272static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
273{
bartd45d9952009-05-31 18:53:54 +0000274 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000275 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000276 || ! DRD_(thread_address_on_stack)(addr))
277 && bm_access_store_2_triggers_conflict(addr)
278 && ! DRD_(is_suppressed)(addr, addr + 2))
279 {
280 drd_report_race(addr, 2, eStore);
281 }
bart09dc13f2009-02-14 15:13:31 +0000282}
283
284static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
285{
bartd45d9952009-05-31 18:53:54 +0000286 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000287 && (s_check_stack_accesses
bart71ce1322011-12-11 17:54:17 +0000288 || !DRD_(thread_address_on_stack)(addr))
bartbedfd232009-03-26 19:07:15 +0000289 && bm_access_store_4_triggers_conflict(addr)
bart71ce1322011-12-11 17:54:17 +0000290 && !DRD_(is_suppressed)(addr, addr + 4))
bartbedfd232009-03-26 19:07:15 +0000291 {
292 drd_report_race(addr, 4, eStore);
293 }
bart09dc13f2009-02-14 15:13:31 +0000294}
295
296static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
297{
bartd45d9952009-05-31 18:53:54 +0000298 if (DRD_(running_thread_is_recording_stores)()
bartf98a5692009-05-03 17:17:37 +0000299 && (s_check_stack_accesses
bartbedfd232009-03-26 19:07:15 +0000300 || ! DRD_(thread_address_on_stack)(addr))
301 && bm_access_store_8_triggers_conflict(addr)
302 && ! DRD_(is_suppressed)(addr, addr + 8))
303 {
304 drd_report_race(addr, 8, eStore);
305 }
bart09dc13f2009-02-14 15:13:31 +0000306}
307
308/**
309 * Return true if and only if addr_expr matches the pattern (SP) or
310 * <offset>(SP).
311 */
312static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
313{
bartbedfd232009-03-26 19:07:15 +0000314 Bool result = False;
bart09dc13f2009-02-14 15:13:31 +0000315
bartbedfd232009-03-26 19:07:15 +0000316 if (addr_expr->tag == Iex_RdTmp)
317 {
318 int i;
sewardj528b3502012-12-27 17:46:10 +0000319 for (i = 0; i < bb->stmts_used; i++)
bart09dc13f2009-02-14 15:13:31 +0000320 {
bartbedfd232009-03-26 19:07:15 +0000321 if (bb->stmts[i]
322 && bb->stmts[i]->tag == Ist_WrTmp
323 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
324 {
325 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
326 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
327 {
328 result = True;
329 }
bart09dc13f2009-02-14 15:13:31 +0000330
bartbedfd232009-03-26 19:07:15 +0000331 //ppIRExpr(e);
332 //VG_(printf)(" (%s)\n", result ? "True" : "False");
333 break;
334 }
bart09dc13f2009-02-14 15:13:31 +0000335 }
bartbedfd232009-03-26 19:07:15 +0000336 }
337 return result;
bart09dc13f2009-02-14 15:13:31 +0000338}
339
bartea692152011-12-11 20:17:57 +0000340static const IROp u_widen_irop[5][9] = {
bart9ad8d802011-12-12 19:54:32 +0000341 [Ity_I1 - Ity_I1] = { [4] = Iop_1Uto32, [8] = Iop_1Uto64 },
342 [Ity_I8 - Ity_I1] = { [4] = Iop_8Uto32, [8] = Iop_8Uto64 },
343 [Ity_I16 - Ity_I1] = { [4] = Iop_16Uto32, [8] = Iop_16Uto64 },
344 [Ity_I32 - Ity_I1] = { [8] = Iop_32Uto64 },
bartea692152011-12-11 20:17:57 +0000345};
346
bartb63dc782011-12-12 19:18:26 +0000347/**
348 * Instrument the client code to trace a memory load (--trace-addr).
349 */
bart25026ef2011-12-17 12:59:45 +0000350static IRExpr* instr_trace_mem_load(IRSB* const bb, IRExpr* addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000351 const HWord size,
352 IRExpr* const guard/* NULL => True */)
bartea692152011-12-11 20:17:57 +0000353{
bart25026ef2011-12-17 12:59:45 +0000354 IRTemp tmp;
355
356 tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
357 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
358 addr_expr = IRExpr_RdTmp(tmp);
sewardjcafe5052013-01-17 14:24:35 +0000359 IRDirty* di
360 = unsafeIRDirty_0_N(/*regparms*/2,
361 "drd_trace_mem_load",
362 VG_(fnptr_to_fnentry)
363 (drd_trace_mem_load),
364 mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)));
365 if (guard) di->guard = guard;
366 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart25026ef2011-12-17 12:59:45 +0000367
368 return addr_expr;
bartb63dc782011-12-12 19:18:26 +0000369}
370
371/**
372 * Instrument the client code to trace a memory store (--trace-addr).
373 */
374static void instr_trace_mem_store(IRSB* const bb, IRExpr* const addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000375 IRExpr* data_expr_hi, IRExpr* data_expr_lo,
376 IRExpr* const guard/* NULL => True */)
bartb63dc782011-12-12 19:18:26 +0000377{
378 IRType ty_data_expr;
bartea692152011-12-11 20:17:57 +0000379 HWord size;
380
bartb63dc782011-12-12 19:18:26 +0000381 tl_assert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
bart42f32632011-12-13 11:12:05 +0000382 tl_assert(!data_expr_hi || typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I32);
bartea692152011-12-11 20:17:57 +0000383
bart42f32632011-12-13 11:12:05 +0000384 ty_data_expr = typeOfIRExpr(bb->tyenv, data_expr_lo);
bartb63dc782011-12-12 19:18:26 +0000385 size = sizeofIRType(ty_data_expr);
386
bart7ca75ed2011-12-13 08:53:23 +0000387#if 0
388 // Test code
389 if (ty_data_expr == Ity_I32) {
390 IRTemp tmp = newIRTemp(bb->tyenv, Ity_F32);
bart42f32632011-12-13 11:12:05 +0000391 data_expr_lo = IRExpr_Unop(Iop_ReinterpI32asF32, data_expr_lo);
392 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
393 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000394 ty_data_expr = Ity_F32;
395 } else if (ty_data_expr == Ity_I64) {
396 IRTemp tmp = newIRTemp(bb->tyenv, Ity_F64);
bart42f32632011-12-13 11:12:05 +0000397 data_expr_lo = IRExpr_Unop(Iop_ReinterpI64asF64, data_expr_lo);
398 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, data_expr_lo));
399 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000400 ty_data_expr = Ity_F64;
401 }
402#endif
403
404 if (ty_data_expr == Ity_F32) {
405 IRTemp tmp = newIRTemp(bb->tyenv, Ity_I32);
406 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF32asI32,
bart42f32632011-12-13 11:12:05 +0000407 data_expr_lo)));
408 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000409 ty_data_expr = Ity_I32;
410 } else if (ty_data_expr == Ity_F64) {
411 IRTemp tmp = newIRTemp(bb->tyenv, Ity_I64);
412 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_ReinterpF64asI64,
bart42f32632011-12-13 11:12:05 +0000413 data_expr_lo)));
414 data_expr_lo = IRExpr_RdTmp(tmp);
bart7ca75ed2011-12-13 08:53:23 +0000415 ty_data_expr = Ity_I64;
416 }
417
bartb63dc782011-12-12 19:18:26 +0000418 if (size == sizeof(HWord)
419 && (ty_data_expr == Ity_I32 || ty_data_expr == Ity_I64))
420 {
421 /* No conversion necessary */
bartea692152011-12-11 20:17:57 +0000422 } else {
423 IROp widen_op;
424
bartb63dc782011-12-12 19:18:26 +0000425 if (Ity_I1 <= ty_data_expr
426 && ty_data_expr
427 < Ity_I1 + sizeof(u_widen_irop)/sizeof(u_widen_irop[0]))
428 {
429 widen_op = u_widen_irop[ty_data_expr - Ity_I1][sizeof(HWord)];
bartea692152011-12-11 20:17:57 +0000430 if (!widen_op)
431 widen_op = Iop_INVALID;
432 } else {
433 widen_op = Iop_INVALID;
434 }
435 if (widen_op != Iop_INVALID) {
436 IRTemp tmp;
437
bartb63dc782011-12-12 19:18:26 +0000438 /* Widen the integer expression to a HWord */
bartea692152011-12-11 20:17:57 +0000439 tmp = newIRTemp(bb->tyenv, sizeof(HWord) == 4 ? Ity_I32 : Ity_I64);
440 addStmtToIRSB(bb,
bart42f32632011-12-13 11:12:05 +0000441 IRStmt_WrTmp(tmp, IRExpr_Unop(widen_op, data_expr_lo)));
442 data_expr_lo = IRExpr_RdTmp(tmp);
443 } else if (size > sizeof(HWord) && !data_expr_hi
444 && ty_data_expr == Ity_I64) {
445 IRTemp tmp;
446
447 tl_assert(sizeof(HWord) == 4);
448 tl_assert(size == 8);
449 tmp = newIRTemp(bb->tyenv, Ity_I32);
450 addStmtToIRSB(bb,
451 IRStmt_WrTmp(tmp,
452 IRExpr_Unop(Iop_64HIto32, data_expr_lo)));
453 data_expr_hi = IRExpr_RdTmp(tmp);
454 tmp = newIRTemp(bb->tyenv, Ity_I32);
455 addStmtToIRSB(bb, IRStmt_WrTmp(tmp,
456 IRExpr_Unop(Iop_64to32, data_expr_lo)));
457 data_expr_lo = IRExpr_RdTmp(tmp);
bartea692152011-12-11 20:17:57 +0000458 } else {
bart42f32632011-12-13 11:12:05 +0000459 data_expr_lo = mkIRExpr_HWord(0);
bartea692152011-12-11 20:17:57 +0000460 }
461 }
sewardjcafe5052013-01-17 14:24:35 +0000462 IRDirty* di
463 = unsafeIRDirty_0_N(/*regparms*/3,
464 "drd_trace_mem_store",
465 VG_(fnptr_to_fnentry)(drd_trace_mem_store),
466 mkIRExprVec_4(addr_expr, mkIRExpr_HWord(size),
467 data_expr_hi ? data_expr_hi
468 : mkIRExpr_HWord(0), data_expr_lo));
469 if (guard) di->guard = guard;
470 addStmtToIRSB(bb, IRStmt_Dirty(di) );
bartea692152011-12-11 20:17:57 +0000471}
472
473static void instrument_load(IRSB* const bb, IRExpr* const addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000474 const HWord size,
475 IRExpr* const guard/* NULL => True */)
bart09dc13f2009-02-14 15:13:31 +0000476{
bartbedfd232009-03-26 19:07:15 +0000477 IRExpr* size_expr;
478 IRExpr** argv;
479 IRDirty* di;
bart09dc13f2009-02-14 15:13:31 +0000480
bartea692152011-12-11 20:17:57 +0000481 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000482 return;
bart09dc13f2009-02-14 15:13:31 +0000483
bartbedfd232009-03-26 19:07:15 +0000484 switch (size)
485 {
486 case 1:
487 argv = mkIRExprVec_1(addr_expr);
488 di = unsafeIRDirty_0_N(/*regparms*/1,
489 "drd_trace_load_1",
490 VG_(fnptr_to_fnentry)(drd_trace_load_1),
491 argv);
492 break;
493 case 2:
494 argv = mkIRExprVec_1(addr_expr);
495 di = unsafeIRDirty_0_N(/*regparms*/1,
496 "drd_trace_load_2",
497 VG_(fnptr_to_fnentry)(drd_trace_load_2),
498 argv);
499 break;
500 case 4:
501 argv = mkIRExprVec_1(addr_expr);
502 di = unsafeIRDirty_0_N(/*regparms*/1,
503 "drd_trace_load_4",
504 VG_(fnptr_to_fnentry)(drd_trace_load_4),
505 argv);
506 break;
507 case 8:
508 argv = mkIRExprVec_1(addr_expr);
509 di = unsafeIRDirty_0_N(/*regparms*/1,
510 "drd_trace_load_8",
511 VG_(fnptr_to_fnentry)(drd_trace_load_8),
512 argv);
513 break;
514 default:
515 size_expr = mkIRExpr_HWord(size);
516 argv = mkIRExprVec_2(addr_expr, size_expr);
517 di = unsafeIRDirty_0_N(/*regparms*/2,
518 "drd_trace_load",
519 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
520 argv);
521 break;
522 }
sewardjcafe5052013-01-17 14:24:35 +0000523 if (guard) di->guard = guard;
bartbedfd232009-03-26 19:07:15 +0000524 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000525}
526
bart25026ef2011-12-17 12:59:45 +0000527static void instrument_store(IRSB* const bb, IRExpr* addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000528 IRExpr* const data_expr,
529 IRExpr* const guard_expr/* NULL => True */)
bart09dc13f2009-02-14 15:13:31 +0000530{
bartbedfd232009-03-26 19:07:15 +0000531 IRExpr* size_expr;
532 IRExpr** argv;
533 IRDirty* di;
bart7826acb2011-12-11 18:49:39 +0000534 HWord size;
535
536 size = sizeofIRType(typeOfIRExpr(bb->tyenv, data_expr));
bart09dc13f2009-02-14 15:13:31 +0000537
bart25026ef2011-12-17 12:59:45 +0000538 if (UNLIKELY(DRD_(any_address_is_traced)())) {
539 IRTemp tmp = newIRTemp(bb->tyenv, typeOfIRExpr(bb->tyenv, addr_expr));
540 addStmtToIRSB(bb, IRStmt_WrTmp(tmp, addr_expr));
541 addr_expr = IRExpr_RdTmp(tmp);
sewardjcafe5052013-01-17 14:24:35 +0000542 instr_trace_mem_store(bb, addr_expr, NULL, data_expr, guard_expr);
bart25026ef2011-12-17 12:59:45 +0000543 }
bart09dc13f2009-02-14 15:13:31 +0000544
bart71ce1322011-12-11 17:54:17 +0000545 if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
bartbedfd232009-03-26 19:07:15 +0000546 return;
bart09dc13f2009-02-14 15:13:31 +0000547
bartbedfd232009-03-26 19:07:15 +0000548 switch (size)
549 {
550 case 1:
551 argv = mkIRExprVec_1(addr_expr);
552 di = unsafeIRDirty_0_N(/*regparms*/1,
553 "drd_trace_store_1",
554 VG_(fnptr_to_fnentry)(drd_trace_store_1),
555 argv);
556 break;
557 case 2:
558 argv = mkIRExprVec_1(addr_expr);
559 di = unsafeIRDirty_0_N(/*regparms*/1,
560 "drd_trace_store_2",
561 VG_(fnptr_to_fnentry)(drd_trace_store_2),
562 argv);
563 break;
564 case 4:
565 argv = mkIRExprVec_1(addr_expr);
566 di = unsafeIRDirty_0_N(/*regparms*/1,
567 "drd_trace_store_4",
568 VG_(fnptr_to_fnentry)(drd_trace_store_4),
569 argv);
570 break;
571 case 8:
572 argv = mkIRExprVec_1(addr_expr);
573 di = unsafeIRDirty_0_N(/*regparms*/1,
574 "drd_trace_store_8",
575 VG_(fnptr_to_fnentry)(drd_trace_store_8),
576 argv);
577 break;
578 default:
579 size_expr = mkIRExpr_HWord(size);
580 argv = mkIRExprVec_2(addr_expr, size_expr);
581 di = unsafeIRDirty_0_N(/*regparms*/2,
582 "drd_trace_store",
583 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
584 argv);
585 break;
586 }
sewardjcafe5052013-01-17 14:24:35 +0000587 if (guard_expr) di->guard = guard_expr;
bartbedfd232009-03-26 19:07:15 +0000588 addStmtToIRSB(bb, IRStmt_Dirty(di));
bart09dc13f2009-02-14 15:13:31 +0000589}
590
bart1335ecc2009-02-14 16:10:53 +0000591IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bartbedfd232009-03-26 19:07:15 +0000592 IRSB* const bb_in,
florian3c0c9472014-09-24 12:06:55 +0000593 const VexGuestLayout* const layout,
594 const VexGuestExtents* const vge,
595 const VexArchInfo* archinfo_host,
bartbedfd232009-03-26 19:07:15 +0000596 IRType const gWordTy,
597 IRType const hWordTy)
bart09dc13f2009-02-14 15:13:31 +0000598{
bartbedfd232009-03-26 19:07:15 +0000599 IRDirty* di;
600 Int i;
601 IRSB* bb;
602 IRExpr** argv;
603 Bool instrument = True;
bart09dc13f2009-02-14 15:13:31 +0000604
bartbedfd232009-03-26 19:07:15 +0000605 /* Set up BB */
606 bb = emptyIRSB();
607 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
608 bb->next = deepCopyIRExpr(bb_in->next);
609 bb->jumpkind = bb_in->jumpkind;
sewardj291849f2012-04-20 23:58:55 +0000610 bb->offsIP = bb_in->offsIP;
bart09dc13f2009-02-14 15:13:31 +0000611
bartbedfd232009-03-26 19:07:15 +0000612 for (i = 0; i < bb_in->stmts_used; i++)
613 {
614 IRStmt* const st = bb_in->stmts[i];
615 tl_assert(st);
sewardjdb5907d2009-11-26 17:20:21 +0000616 tl_assert(isFlatIRStmt(st));
bart09dc13f2009-02-14 15:13:31 +0000617
bartbedfd232009-03-26 19:07:15 +0000618 switch (st->tag)
bart09dc13f2009-02-14 15:13:31 +0000619 {
bartbedfd232009-03-26 19:07:15 +0000620 /* Note: the code for not instrumenting the code in .plt */
621 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
622 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
623 /* This is because on this platform dynamic library symbols are */
624 /* relocated in another way than by later binutils versions. The */
625 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
626 case Ist_IMark:
floriane08950b2014-11-13 21:41:28 +0000627 instrument = VG_(DebugInfo_sect_kind)(NULL, st->Ist.IMark.addr)
bartbedfd232009-03-26 19:07:15 +0000628 != Vg_SectPLT;
629 addStmtToIRSB(bb, st);
630 break;
631
632 case Ist_MBE:
633 switch (st->Ist.MBE.event)
634 {
635 case Imbe_Fence:
bartb68c9472014-09-18 07:11:24 +0000636 break; /* not interesting to DRD */
637 case Imbe_CancelReservation:
638 break; /* not interesting to DRD */
bartbedfd232009-03-26 19:07:15 +0000639 default:
640 tl_assert(0);
641 }
642 addStmtToIRSB(bb, st);
643 break;
644
645 case Ist_Store:
sewardjdb5907d2009-11-26 17:20:21 +0000646 if (instrument)
sewardjcafe5052013-01-17 14:24:35 +0000647 instrument_store(bb, st->Ist.Store.addr, st->Ist.Store.data,
648 NULL/* no guard */);
bartbedfd232009-03-26 19:07:15 +0000649 addStmtToIRSB(bb, st);
650 break;
651
sewardjcafe5052013-01-17 14:24:35 +0000652 case Ist_StoreG: {
653 IRStoreG* sg = st->Ist.StoreG.details;
654 IRExpr* data = sg->data;
655 IRExpr* addr = sg->addr;
656 if (instrument)
657 instrument_store(bb, addr, data, sg->guard);
658 addStmtToIRSB(bb, st);
659 break;
660 }
661
662 case Ist_LoadG: {
663 IRLoadG* lg = st->Ist.LoadG.details;
664 IRType type = Ity_INVALID; /* loaded type */
665 IRType typeWide = Ity_INVALID; /* after implicit widening */
666 IRExpr* addr_expr = lg->addr;
667 typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
668 tl_assert(type != Ity_INVALID);
669 if (UNLIKELY(DRD_(any_address_is_traced)())) {
670 addr_expr = instr_trace_mem_load(bb, addr_expr,
671 sizeofIRType(type), lg->guard);
672 }
673 instrument_load(bb, lg->addr,
674 sizeofIRType(type), lg->guard);
675 addStmtToIRSB(bb, st);
676 break;
677 }
678
bartbedfd232009-03-26 19:07:15 +0000679 case Ist_WrTmp:
bartea692152011-12-11 20:17:57 +0000680 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000681 const IRExpr* const data = st->Ist.WrTmp.data;
bart25026ef2011-12-17 12:59:45 +0000682 IRExpr* addr_expr = data->Iex.Load.addr;
bartb63dc782011-12-12 19:18:26 +0000683 if (data->tag == Iex_Load) {
bart25026ef2011-12-17 12:59:45 +0000684 if (UNLIKELY(DRD_(any_address_is_traced)())) {
685 addr_expr = instr_trace_mem_load(bb, addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000686 sizeofIRType(data->Iex.Load.ty),
687 NULL/* no guard */);
bart25026ef2011-12-17 12:59:45 +0000688 }
bart19fb8d72013-01-27 10:58:47 +0000689 instrument_load(bb, addr_expr, sizeofIRType(data->Iex.Load.ty),
sewardjcafe5052013-01-17 14:24:35 +0000690 NULL/* no guard */);
bartb63dc782011-12-12 19:18:26 +0000691 }
bartbedfd232009-03-26 19:07:15 +0000692 }
693 addStmtToIRSB(bb, st);
694 break;
695
696 case Ist_Dirty:
bartb63dc782011-12-12 19:18:26 +0000697 if (instrument) {
bartbedfd232009-03-26 19:07:15 +0000698 IRDirty* d = st->Ist.Dirty.details;
699 IREffect const mFx = d->mFx;
700 switch (mFx) {
701 case Ifx_None:
702 break;
703 case Ifx_Read:
704 case Ifx_Write:
705 case Ifx_Modify:
706 tl_assert(d->mAddr);
707 tl_assert(d->mSize > 0);
708 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
709 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
710 di = unsafeIRDirty_0_N(
711 /*regparms*/2,
712 "drd_trace_load",
713 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
714 argv);
715 addStmtToIRSB(bb, IRStmt_Dirty(di));
716 }
sewardj1c0ce7a2009-07-01 08:10:49 +0000717 if (mFx == Ifx_Write || mFx == Ifx_Modify)
bartbedfd232009-03-26 19:07:15 +0000718 {
719 di = unsafeIRDirty_0_N(
720 /*regparms*/2,
721 "drd_trace_store",
722 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
723 argv);
724 addStmtToIRSB(bb, IRStmt_Dirty(di));
725 }
726 break;
727 default:
728 tl_assert(0);
729 }
730 }
731 addStmtToIRSB(bb, st);
732 break;
733
sewardj1c0ce7a2009-07-01 08:10:49 +0000734 case Ist_CAS:
bartb63dc782011-12-12 19:18:26 +0000735 if (instrument) {
barta14e3282009-07-11 14:35:59 +0000736 /*
737 * Treat compare-and-swap as a read. By handling atomic
738 * instructions as read instructions no data races are reported
739 * between conflicting atomic operations nor between atomic
740 * operations and non-atomic reads. Conflicts between atomic
741 * operations and non-atomic write operations are still reported
742 * however.
743 */
sewardj1c0ce7a2009-07-01 08:10:49 +0000744 Int dataSize;
745 IRCAS* cas = st->Ist.CAS.details;
bartb63dc782011-12-12 19:18:26 +0000746
sewardj1c0ce7a2009-07-01 08:10:49 +0000747 tl_assert(cas->addr != NULL);
748 tl_assert(cas->dataLo != NULL);
749 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
750 if (cas->dataHi != NULL)
751 dataSize *= 2; /* since it's a doubleword-CAS */
bartb63dc782011-12-12 19:18:26 +0000752
bart42f32632011-12-13 11:12:05 +0000753 if (UNLIKELY(DRD_(any_address_is_traced)()))
sewardjcafe5052013-01-17 14:24:35 +0000754 instr_trace_mem_store(bb, cas->addr, cas->dataHi, cas->dataLo,
755 NULL/* no guard */);
bartb63dc782011-12-12 19:18:26 +0000756
sewardjcafe5052013-01-17 14:24:35 +0000757 instrument_load(bb, cas->addr, dataSize, NULL/*no guard*/);
sewardj1c0ce7a2009-07-01 08:10:49 +0000758 }
759 addStmtToIRSB(bb, st);
760 break;
761
sewardjdb5907d2009-11-26 17:20:21 +0000762 case Ist_LLSC: {
bartea692152011-12-11 20:17:57 +0000763 /*
764 * Ignore store-conditionals (except for tracing), and handle
765 * load-linked's exactly like normal loads.
766 */
sewardjdb5907d2009-11-26 17:20:21 +0000767 IRType dataTy;
bartb63dc782011-12-12 19:18:26 +0000768
bartea692152011-12-11 20:17:57 +0000769 if (st->Ist.LLSC.storedata == NULL) {
sewardjdb5907d2009-11-26 17:20:21 +0000770 /* LL */
771 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
bartb63dc782011-12-12 19:18:26 +0000772 if (instrument) {
bart25026ef2011-12-17 12:59:45 +0000773 IRExpr* addr_expr = st->Ist.LLSC.addr;
bartb63dc782011-12-12 19:18:26 +0000774 if (UNLIKELY(DRD_(any_address_is_traced)()))
bart25026ef2011-12-17 12:59:45 +0000775 addr_expr = instr_trace_mem_load(bb, addr_expr,
sewardjcafe5052013-01-17 14:24:35 +0000776 sizeofIRType(dataTy),
777 NULL /* no guard */);
bartb63dc782011-12-12 19:18:26 +0000778
sewardjcafe5052013-01-17 14:24:35 +0000779 instrument_load(bb, addr_expr, sizeofIRType(dataTy),
780 NULL/*no guard*/);
bartb63dc782011-12-12 19:18:26 +0000781 }
bartea692152011-12-11 20:17:57 +0000782 } else {
sewardjdb5907d2009-11-26 17:20:21 +0000783 /* SC */
bart42f32632011-12-13 11:12:05 +0000784 instr_trace_mem_store(bb, st->Ist.LLSC.addr, NULL,
sewardjcafe5052013-01-17 14:24:35 +0000785 st->Ist.LLSC.storedata,
786 NULL/* no guard */);
sewardjdb5907d2009-11-26 17:20:21 +0000787 }
bartbedfd232009-03-26 19:07:15 +0000788 addStmtToIRSB(bb, st);
789 break;
bart09dc13f2009-02-14 15:13:31 +0000790 }
sewardjdb5907d2009-11-26 17:20:21 +0000791
792 case Ist_NoOp:
793 case Ist_AbiHint:
794 case Ist_Put:
795 case Ist_PutI:
796 case Ist_Exit:
797 /* None of these can contain any memory references. */
798 addStmtToIRSB(bb, st);
799 break;
800
801 default:
802 ppIRStmt(st);
803 tl_assert(0);
804 }
bartbedfd232009-03-26 19:07:15 +0000805 }
bart09dc13f2009-02-14 15:13:31 +0000806
bartbedfd232009-03-26 19:07:15 +0000807 return bb;
bart09dc13f2009-02-14 15:13:31 +0000808}
809