1 /* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */
3 This file is part of drd, a thread error detector.
5 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 The GNU General Public License is contained in the file COPYING.
26 #include "drd_bitmap.h"
27 #include "drd_thread_bitmap.h"
28 #include "drd_vc.h" /* DRD_(vc_snprint)() */
30 /* Include several source files here in order to allow the compiler to */
31 /* do more inlining. */
32 #include "drd_bitmap.c"
33 #include "drd_load_store.h"
34 #include "drd_segment.c"
35 #include "drd_thread.c"
37 #include "libvex_guest_offsets.h"
40 /* STACK_POINTER_OFFSET: VEX register offset for the stack pointer register. */
42 #define STACK_POINTER_OFFSET OFFSET_x86_ESP
43 #elif defined(VGA_amd64)
44 #define STACK_POINTER_OFFSET OFFSET_amd64_RSP
45 #elif defined(VGA_ppc32)
46 #define STACK_POINTER_OFFSET OFFSET_ppc32_GPR1
47 #elif defined(VGA_ppc64)
48 #define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
49 #elif defined(VGA_arm)
50 #define STACK_POINTER_OFFSET OFFSET_arm_R13
51 #elif defined(VGA_s390x)
52 #define STACK_POINTER_OFFSET OFFSET_s390x_r15
54 #error Unknown architecture.
58 /* Local variables. */
60 static Bool s_check_stack_accesses = False;
61 static Bool s_first_race_only = False;
64 /* Function definitions. */
66 Bool DRD_(get_check_stack_accesses)()
68 return s_check_stack_accesses;
71 void DRD_(set_check_stack_accesses)(const Bool c)
73 tl_assert(c == False || c == True);
74 s_check_stack_accesses = c;
77 Bool DRD_(get_first_race_only)()
79 return s_first_race_only;
82 void DRD_(set_first_race_only)(const Bool fro)
84 tl_assert(fro == False || fro == True);
85 s_first_race_only = fro;
88 void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
89 const BmAccessTypeT access_type)
91 if (DRD_(is_any_traced)(addr, addr + size))
95 vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
96 VG_(message)(Vg_UserMsg,
97 "%s 0x%lx size %ld (thread %d / vc %s)\n",
100 : access_type == eStore
102 : access_type == eStart
104 : access_type == eEnd
109 DRD_(thread_get_running_tid)(),
112 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
113 VG_(clo_backtrace_size));
114 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
115 == VG_(get_running_tid)());
119 static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
121 return DRD_(trace_mem_access)(addr, size, eLoad);
124 static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
126 return DRD_(trace_mem_access)(addr, size, eStore);
129 static void drd_report_race(const Addr addr, const SizeT size,
130 const BmAccessTypeT access_type)
132 DataRaceErrInfo drei;
134 drei.tid = DRD_(thread_get_running_tid)();
137 drei.access_type = access_type;
138 VG_(maybe_record_error)(VG_(get_running_tid)(),
140 VG_(get_IP)(VG_(get_running_tid)()),
141 "Conflicting accesses",
144 if (s_first_race_only)
146 DRD_(start_suppression)(addr, addr + size, "first race only");
150 VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
152 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
153 /* The assert below has been commented out because of performance reasons.*/
154 tl_assert(DRD_(thread_get_running_tid)()
155 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
158 if (DRD_(running_thread_is_recording_loads)()
159 && (s_check_stack_accesses
160 || ! DRD_(thread_address_on_stack)(addr))
161 && bm_access_load_triggers_conflict(addr, addr + size)
162 && ! DRD_(is_suppressed)(addr, addr + size))
164 drd_report_race(addr, size, eLoad);
168 static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
170 if (DRD_(running_thread_is_recording_loads)()
171 && (s_check_stack_accesses
172 || ! DRD_(thread_address_on_stack)(addr))
173 && bm_access_load_1_triggers_conflict(addr)
174 && ! DRD_(is_suppressed)(addr, addr + 1))
176 drd_report_race(addr, 1, eLoad);
180 static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
182 if (DRD_(running_thread_is_recording_loads)()
183 && (s_check_stack_accesses
184 || ! DRD_(thread_address_on_stack)(addr))
185 && bm_access_load_2_triggers_conflict(addr)
186 && ! DRD_(is_suppressed)(addr, addr + 2))
188 drd_report_race(addr, 2, eLoad);
192 static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
194 if (DRD_(running_thread_is_recording_loads)()
195 && (s_check_stack_accesses
196 || ! DRD_(thread_address_on_stack)(addr))
197 && bm_access_load_4_triggers_conflict(addr)
198 && ! DRD_(is_suppressed)(addr, addr + 4))
200 drd_report_race(addr, 4, eLoad);
204 static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
206 if (DRD_(running_thread_is_recording_loads)()
207 && (s_check_stack_accesses
208 || ! DRD_(thread_address_on_stack)(addr))
209 && bm_access_load_8_triggers_conflict(addr)
210 && ! DRD_(is_suppressed)(addr, addr + 8))
212 drd_report_race(addr, 8, eLoad);
216 VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
218 #ifdef ENABLE_DRD_CONSISTENCY_CHECKS
219 /* The assert below has been commented out because of performance reasons.*/
220 tl_assert(DRD_(thread_get_running_tid)()
221 == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
224 if (DRD_(running_thread_is_recording_stores)()
225 && (s_check_stack_accesses
226 || ! DRD_(thread_address_on_stack)(addr))
227 && bm_access_store_triggers_conflict(addr, addr + size)
228 && ! DRD_(is_suppressed)(addr, addr + size))
230 drd_report_race(addr, size, eStore);
234 static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
236 if (DRD_(running_thread_is_recording_stores)()
237 && (s_check_stack_accesses
238 || ! DRD_(thread_address_on_stack)(addr))
239 && bm_access_store_1_triggers_conflict(addr)
240 && ! DRD_(is_suppressed)(addr, addr + 1))
242 drd_report_race(addr, 1, eStore);
246 static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
248 if (DRD_(running_thread_is_recording_stores)()
249 && (s_check_stack_accesses
250 || ! DRD_(thread_address_on_stack)(addr))
251 && bm_access_store_2_triggers_conflict(addr)
252 && ! DRD_(is_suppressed)(addr, addr + 2))
254 drd_report_race(addr, 2, eStore);
258 static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
260 if (DRD_(running_thread_is_recording_stores)()
261 && (s_check_stack_accesses
262 || ! DRD_(thread_address_on_stack)(addr))
263 && bm_access_store_4_triggers_conflict(addr)
264 && ! DRD_(is_suppressed)(addr, addr + 4))
266 drd_report_race(addr, 4, eStore);
270 static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
272 if (DRD_(running_thread_is_recording_stores)()
273 && (s_check_stack_accesses
274 || ! DRD_(thread_address_on_stack)(addr))
275 && bm_access_store_8_triggers_conflict(addr)
276 && ! DRD_(is_suppressed)(addr, addr + 8))
278 drd_report_race(addr, 8, eStore);
283 * Return true if and only if addr_expr matches the pattern (SP) or
286 static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
290 if (addr_expr->tag == Iex_RdTmp)
293 for (i = 0; i < bb->stmts_size; i++)
296 && bb->stmts[i]->tag == Ist_WrTmp
297 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
299 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
300 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
306 //VG_(printf)(" (%s)\n", result ? "True" : "False");
314 static void instrument_load(IRSB* const bb,
315 IRExpr* const addr_expr,
322 if (UNLIKELY(DRD_(any_address_is_traced)()))
326 unsafeIRDirty_0_N(/*regparms*/2,
328 VG_(fnptr_to_fnentry)
329 (drd_trace_mem_load),
330 mkIRExprVec_2(addr_expr,
331 mkIRExpr_HWord(size)))));
334 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
340 argv = mkIRExprVec_1(addr_expr);
341 di = unsafeIRDirty_0_N(/*regparms*/1,
343 VG_(fnptr_to_fnentry)(drd_trace_load_1),
347 argv = mkIRExprVec_1(addr_expr);
348 di = unsafeIRDirty_0_N(/*regparms*/1,
350 VG_(fnptr_to_fnentry)(drd_trace_load_2),
354 argv = mkIRExprVec_1(addr_expr);
355 di = unsafeIRDirty_0_N(/*regparms*/1,
357 VG_(fnptr_to_fnentry)(drd_trace_load_4),
361 argv = mkIRExprVec_1(addr_expr);
362 di = unsafeIRDirty_0_N(/*regparms*/1,
364 VG_(fnptr_to_fnentry)(drd_trace_load_8),
368 size_expr = mkIRExpr_HWord(size);
369 argv = mkIRExprVec_2(addr_expr, size_expr);
370 di = unsafeIRDirty_0_N(/*regparms*/2,
372 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
376 addStmtToIRSB(bb, IRStmt_Dirty(di));
379 static void instrument_store(IRSB* const bb,
380 IRExpr* const addr_expr,
387 if (UNLIKELY(DRD_(any_address_is_traced)()))
391 unsafeIRDirty_0_N(/*regparms*/2,
393 VG_(fnptr_to_fnentry)
394 (drd_trace_mem_store),
395 mkIRExprVec_2(addr_expr,
396 mkIRExpr_HWord(size)))));
399 if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
405 argv = mkIRExprVec_1(addr_expr);
406 di = unsafeIRDirty_0_N(/*regparms*/1,
408 VG_(fnptr_to_fnentry)(drd_trace_store_1),
412 argv = mkIRExprVec_1(addr_expr);
413 di = unsafeIRDirty_0_N(/*regparms*/1,
415 VG_(fnptr_to_fnentry)(drd_trace_store_2),
419 argv = mkIRExprVec_1(addr_expr);
420 di = unsafeIRDirty_0_N(/*regparms*/1,
422 VG_(fnptr_to_fnentry)(drd_trace_store_4),
426 argv = mkIRExprVec_1(addr_expr);
427 di = unsafeIRDirty_0_N(/*regparms*/1,
429 VG_(fnptr_to_fnentry)(drd_trace_store_8),
433 size_expr = mkIRExpr_HWord(size);
434 argv = mkIRExprVec_2(addr_expr, size_expr);
435 di = unsafeIRDirty_0_N(/*regparms*/2,
437 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
441 addStmtToIRSB(bb, IRStmt_Dirty(di));
444 IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
446 VexGuestLayout* const layout,
447 VexGuestExtents* const vge,
448 IRType const gWordTy,
449 IRType const hWordTy)
455 Bool instrument = True;
459 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
460 bb->next = deepCopyIRExpr(bb_in->next);
461 bb->jumpkind = bb_in->jumpkind;
463 for (i = 0; i < bb_in->stmts_used; i++)
465 IRStmt* const st = bb_in->stmts[i];
467 tl_assert(isFlatIRStmt(st));
471 /* Note: the code for not instrumenting the code in .plt */
472 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
473 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
474 /* This is because on this platform dynamic library symbols are */
475 /* relocated in another way than by later binutils versions. The */
476 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
478 instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
480 addStmtToIRSB(bb, st);
484 switch (st->Ist.MBE.event)
487 break; /* not interesting */
491 addStmtToIRSB(bb, st);
499 sizeofIRType(typeOfIRExpr(bb->tyenv,
500 st->Ist.Store.data)));
502 addStmtToIRSB(bb, st);
508 const IRExpr* const data = st->Ist.WrTmp.data;
509 if (data->tag == Iex_Load)
513 sizeofIRType(data->Iex.Load.ty));
516 addStmtToIRSB(bb, st);
522 IRDirty* d = st->Ist.Dirty.details;
523 IREffect const mFx = d->mFx;
531 tl_assert(d->mSize > 0);
532 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
533 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
534 di = unsafeIRDirty_0_N(
537 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
539 addStmtToIRSB(bb, IRStmt_Dirty(di));
541 if (mFx == Ifx_Write || mFx == Ifx_Modify)
543 di = unsafeIRDirty_0_N(
546 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
548 addStmtToIRSB(bb, IRStmt_Dirty(di));
555 addStmtToIRSB(bb, st);
562 * Treat compare-and-swap as a read. By handling atomic
563 * instructions as read instructions no data races are reported
564 * between conflicting atomic operations nor between atomic
565 * operations and non-atomic reads. Conflicts between atomic
566 * operations and non-atomic write operations are still reported
570 IRCAS* cas = st->Ist.CAS.details;
571 tl_assert(cas->addr != NULL);
572 tl_assert(cas->dataLo != NULL);
573 dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
574 if (cas->dataHi != NULL)
575 dataSize *= 2; /* since it's a doubleword-CAS */
576 instrument_load(bb, cas->addr, dataSize);
578 addStmtToIRSB(bb, st);
582 /* Ignore store-conditionals, and handle load-linked's
583 exactly like normal loads. */
585 if (st->Ist.LLSC.storedata == NULL)
588 dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
592 sizeofIRType(dataTy));
600 addStmtToIRSB(bb, st);
609 /* None of these can contain any memory references. */
610 addStmtToIRSB(bb, st);