blob: 908c860a74d236888a0c8d407ee6234c39185455 [file] [log] [blame]
bart09dc13f2009-02-14 15:13:31 +00001/*
2 This file is part of drd, a data race detector.
3
4 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
5
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)
45#define STACK_POINTER_OFFSET ((OFFSET_ppc32_GPR0 + OFFSET_ppc32_GPR2) / 2)
46#elif defined(VGA_ppc64)
47#define STACK_POINTER_OFFSET ((OFFSET_ppc64_GPR0 + OFFSET_ppc64_GPR2) / 2)
48#else
49#error Unknown architecture.
50#endif
51
52
53/* Local variables. */
54
bart62a784c2009-02-15 13:11:14 +000055static Bool DRD_(s_check_stack_accesses) = False;
bart09dc13f2009-02-14 15:13:31 +000056
57
58/* Function definitions. */
59
60Bool DRD_(get_check_stack_accesses)()
61{
bart62a784c2009-02-15 13:11:14 +000062 return DRD_(s_check_stack_accesses);
bart09dc13f2009-02-14 15:13:31 +000063}
64
65void DRD_(set_check_stack_accesses)(const Bool c)
66{
67 tl_assert(c == False || c == True);
bart62a784c2009-02-15 13:11:14 +000068 DRD_(s_check_stack_accesses) = c;
bart09dc13f2009-02-14 15:13:31 +000069}
70
bart1335ecc2009-02-14 16:10:53 +000071void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
bart09dc13f2009-02-14 15:13:31 +000072 const BmAccessTypeT access_type)
73{
bart1335ecc2009-02-14 16:10:53 +000074 if (DRD_(is_any_traced)(addr, addr + size))
bart09dc13f2009-02-14 15:13:31 +000075 {
76 char vc[80];
bart62a784c2009-02-15 13:11:14 +000077 DRD_(vc_snprint)(vc, sizeof(vc),
78 DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
bart09dc13f2009-02-14 15:13:31 +000079 VG_(message)(Vg_UserMsg,
80 "%s 0x%lx size %ld (vg %d / drd %d / vc %s)",
81 access_type == eLoad
82 ? "load "
83 : access_type == eStore
84 ? "store"
85 : access_type == eStart
86 ? "start"
87 : access_type == eEnd
88 ? "end "
89 : "????",
90 addr,
91 size,
92 VG_(get_running_tid)(),
bart62a784c2009-02-15 13:11:14 +000093 DRD_(thread_get_running_tid)(),
bart09dc13f2009-02-14 15:13:31 +000094 vc);
95 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
96 VG_(clo_backtrace_size));
bart62a784c2009-02-15 13:11:14 +000097 tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
bart09dc13f2009-02-14 15:13:31 +000098 == VG_(get_running_tid)());
99 }
100}
101
102static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
103{
bart1335ecc2009-02-14 16:10:53 +0000104 return DRD_(trace_mem_access)(addr, size, eLoad);
bart09dc13f2009-02-14 15:13:31 +0000105}
106
107static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
108{
bart1335ecc2009-02-14 16:10:53 +0000109 return DRD_(trace_mem_access)(addr, size, eStore);
bart09dc13f2009-02-14 15:13:31 +0000110}
111
112static void drd_report_race(const Addr addr, const SizeT size,
113 const BmAccessTypeT access_type)
114{
115 DataRaceErrInfo drei;
116
bart62a784c2009-02-15 13:11:14 +0000117 drei.tid = DRD_(thread_get_running_tid)();
bart09dc13f2009-02-14 15:13:31 +0000118 drei.addr = addr;
119 drei.size = size;
120 drei.access_type = access_type;
121 VG_(maybe_record_error)(VG_(get_running_tid)(),
122 DataRaceErr,
123 VG_(get_IP)(VG_(get_running_tid)()),
124 "Conflicting accesses",
125 &drei);
126}
127
bart99edb292009-02-15 15:59:20 +0000128VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000129{
130#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
131 /* The assert below has been commented out because of performance reasons.*/
132 tl_assert(thread_get_running_tid()
133 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
134#endif
135
bart62a784c2009-02-15 13:11:14 +0000136 if (DRD_(running_thread_is_recording)()
137 && (DRD_(s_check_stack_accesses)
138 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000139 && bm_access_load_triggers_conflict(addr, addr + size)
bart1335ecc2009-02-14 16:10:53 +0000140 && ! DRD_(is_suppressed)(addr, addr + size))
bart09dc13f2009-02-14 15:13:31 +0000141 {
142 drd_report_race(addr, size, eLoad);
143 }
144}
145
146static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
147{
bart62a784c2009-02-15 13:11:14 +0000148 if (DRD_(running_thread_is_recording)()
149 && (DRD_(s_check_stack_accesses)
150 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000151 && bm_access_load_1_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000152 && ! DRD_(is_suppressed)(addr, addr + 1))
bart09dc13f2009-02-14 15:13:31 +0000153 {
154 drd_report_race(addr, 1, eLoad);
155 }
156}
157
158static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
159{
bart62a784c2009-02-15 13:11:14 +0000160 if (DRD_(running_thread_is_recording)()
161 && (DRD_(s_check_stack_accesses)
162 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000163 && bm_access_load_2_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000164 && ! DRD_(is_suppressed)(addr, addr + 2))
bart09dc13f2009-02-14 15:13:31 +0000165 {
166 drd_report_race(addr, 2, eLoad);
167 }
168}
169
170static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
171{
bart62a784c2009-02-15 13:11:14 +0000172 if (DRD_(running_thread_is_recording)()
173 && (DRD_(s_check_stack_accesses)
174 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000175 && bm_access_load_4_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000176 && ! DRD_(is_suppressed)(addr, addr + 4))
bart09dc13f2009-02-14 15:13:31 +0000177 {
178 drd_report_race(addr, 4, eLoad);
179 }
180}
181
182static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
183{
bart62a784c2009-02-15 13:11:14 +0000184 if (DRD_(running_thread_is_recording)()
185 && (DRD_(s_check_stack_accesses)
186 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000187 && bm_access_load_8_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000188 && ! DRD_(is_suppressed)(addr, addr + 8))
bart09dc13f2009-02-14 15:13:31 +0000189 {
190 drd_report_race(addr, 8, eLoad);
191 }
192}
193
bart99edb292009-02-15 15:59:20 +0000194VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
bart09dc13f2009-02-14 15:13:31 +0000195{
196#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
197 /* The assert below has been commented out because of performance reasons.*/
198 tl_assert(thread_get_running_tid()
199 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
200#endif
201
bart62a784c2009-02-15 13:11:14 +0000202 if (DRD_(running_thread_is_recording)()
203 && (DRD_(s_check_stack_accesses)
204 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000205 && bm_access_store_triggers_conflict(addr, addr + size)
bart1335ecc2009-02-14 16:10:53 +0000206 && ! DRD_(is_suppressed)(addr, addr + size))
bart09dc13f2009-02-14 15:13:31 +0000207 {
208 drd_report_race(addr, size, eStore);
209 }
210}
211
212static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
213{
bart62a784c2009-02-15 13:11:14 +0000214 if (DRD_(running_thread_is_recording)()
215 && (DRD_(s_check_stack_accesses)
216 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000217 && bm_access_store_1_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000218 && ! DRD_(is_suppressed)(addr, addr + 1))
bart09dc13f2009-02-14 15:13:31 +0000219 {
220 drd_report_race(addr, 1, eStore);
221 }
222}
223
224static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
225{
bart62a784c2009-02-15 13:11:14 +0000226 if (DRD_(running_thread_is_recording)()
227 && (DRD_(s_check_stack_accesses)
228 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000229 && bm_access_store_2_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000230 && ! DRD_(is_suppressed)(addr, addr + 2))
bart09dc13f2009-02-14 15:13:31 +0000231 {
232 drd_report_race(addr, 2, eStore);
233 }
234}
235
236static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
237{
bart62a784c2009-02-15 13:11:14 +0000238 if (DRD_(running_thread_is_recording)()
239 && (DRD_(s_check_stack_accesses)
240 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000241 && bm_access_store_4_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000242 && ! DRD_(is_suppressed)(addr, addr + 4))
bart09dc13f2009-02-14 15:13:31 +0000243 {
244 drd_report_race(addr, 4, eStore);
245 }
246}
247
248static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
249{
bart62a784c2009-02-15 13:11:14 +0000250 if (DRD_(running_thread_is_recording)()
251 && (DRD_(s_check_stack_accesses)
252 || ! DRD_(thread_address_on_stack)(addr))
bart09dc13f2009-02-14 15:13:31 +0000253 && bm_access_store_8_triggers_conflict(addr)
bart1335ecc2009-02-14 16:10:53 +0000254 && ! DRD_(is_suppressed)(addr, addr + 8))
bart09dc13f2009-02-14 15:13:31 +0000255 {
256 drd_report_race(addr, 8, eStore);
257 }
258}
259
260/**
261 * Return true if and only if addr_expr matches the pattern (SP) or
262 * <offset>(SP).
263 */
264static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
265{
266 Bool result = False;
267
268 if (addr_expr->tag == Iex_RdTmp)
269 {
270 int i;
271 for (i = 0; i < bb->stmts_size; i++)
272 {
273 if (bb->stmts[i]
274 && bb->stmts[i]->tag == Ist_WrTmp
275 && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
276 {
277 IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
278 if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
279 {
280 result = True;
281 }
282
283 //ppIRExpr(e);
284 //VG_(printf)(" (%s)\n", result ? "True" : "False");
285 break;
286 }
287 }
288 }
289 return result;
290}
291
292static void instrument_load(IRSB* const bb,
293 IRExpr* const addr_expr,
294 const HWord size)
295{
296 IRExpr* size_expr;
297 IRExpr** argv;
298 IRDirty* di;
299
bart1335ecc2009-02-14 16:10:53 +0000300 if (UNLIKELY(DRD_(any_address_is_traced)()))
bart09dc13f2009-02-14 15:13:31 +0000301 {
302 addStmtToIRSB(bb,
303 IRStmt_Dirty(
304 unsafeIRDirty_0_N(/*regparms*/2,
305 "drd_trace_load",
306 VG_(fnptr_to_fnentry)
307 (drd_trace_mem_load),
308 mkIRExprVec_2(addr_expr,
309 mkIRExpr_HWord(size)))));
310 }
311
bart62a784c2009-02-15 13:11:14 +0000312 if (! DRD_(s_check_stack_accesses) && is_stack_access(bb, addr_expr))
bart09dc13f2009-02-14 15:13:31 +0000313 return;
314
315 switch (size)
316 {
317 case 1:
318 argv = mkIRExprVec_1(addr_expr);
319 di = unsafeIRDirty_0_N(/*regparms*/1,
320 "drd_trace_load_1",
321 VG_(fnptr_to_fnentry)(drd_trace_load_1),
322 argv);
323 break;
324 case 2:
325 argv = mkIRExprVec_1(addr_expr);
326 di = unsafeIRDirty_0_N(/*regparms*/1,
327 "drd_trace_load_2",
328 VG_(fnptr_to_fnentry)(drd_trace_load_2),
329 argv);
330 break;
331 case 4:
332 argv = mkIRExprVec_1(addr_expr);
333 di = unsafeIRDirty_0_N(/*regparms*/1,
334 "drd_trace_load_4",
335 VG_(fnptr_to_fnentry)(drd_trace_load_4),
336 argv);
337 break;
338 case 8:
339 argv = mkIRExprVec_1(addr_expr);
340 di = unsafeIRDirty_0_N(/*regparms*/1,
341 "drd_trace_load_8",
342 VG_(fnptr_to_fnentry)(drd_trace_load_8),
343 argv);
344 break;
345 default:
346 size_expr = mkIRExpr_HWord(size);
347 argv = mkIRExprVec_2(addr_expr, size_expr);
348 di = unsafeIRDirty_0_N(/*regparms*/2,
349 "drd_trace_load",
bart99edb292009-02-15 15:59:20 +0000350 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
bart09dc13f2009-02-14 15:13:31 +0000351 argv);
352 break;
353 }
354 addStmtToIRSB(bb, IRStmt_Dirty(di));
355}
356
357static void instrument_store(IRSB* const bb,
358 IRExpr* const addr_expr,
359 const HWord size)
360{
361 IRExpr* size_expr;
362 IRExpr** argv;
363 IRDirty* di;
364
bart1335ecc2009-02-14 16:10:53 +0000365 if (UNLIKELY(DRD_(any_address_is_traced)()))
bart09dc13f2009-02-14 15:13:31 +0000366 {
367 addStmtToIRSB(bb,
368 IRStmt_Dirty(
369 unsafeIRDirty_0_N(/*regparms*/2,
370 "drd_trace_store",
371 VG_(fnptr_to_fnentry)
372 (drd_trace_mem_store),
373 mkIRExprVec_2(addr_expr,
374 mkIRExpr_HWord(size)))));
375 }
376
bart62a784c2009-02-15 13:11:14 +0000377 if (! DRD_(s_check_stack_accesses) && is_stack_access(bb, addr_expr))
bart09dc13f2009-02-14 15:13:31 +0000378 return;
379
380 switch (size)
381 {
382 case 1:
383 argv = mkIRExprVec_1(addr_expr);
384 di = unsafeIRDirty_0_N(/*regparms*/1,
385 "drd_trace_store_1",
386 VG_(fnptr_to_fnentry)(drd_trace_store_1),
387 argv);
388 break;
389 case 2:
390 argv = mkIRExprVec_1(addr_expr);
391 di = unsafeIRDirty_0_N(/*regparms*/1,
392 "drd_trace_store_2",
393 VG_(fnptr_to_fnentry)(drd_trace_store_2),
394 argv);
395 break;
396 case 4:
397 argv = mkIRExprVec_1(addr_expr);
398 di = unsafeIRDirty_0_N(/*regparms*/1,
399 "drd_trace_store_4",
400 VG_(fnptr_to_fnentry)(drd_trace_store_4),
401 argv);
402 break;
403 case 8:
404 argv = mkIRExprVec_1(addr_expr);
405 di = unsafeIRDirty_0_N(/*regparms*/1,
406 "drd_trace_store_8",
407 VG_(fnptr_to_fnentry)(drd_trace_store_8),
408 argv);
409 break;
410 default:
411 size_expr = mkIRExpr_HWord(size);
412 argv = mkIRExprVec_2(addr_expr, size_expr);
413 di = unsafeIRDirty_0_N(/*regparms*/2,
414 "drd_trace_store",
bart99edb292009-02-15 15:59:20 +0000415 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
bart09dc13f2009-02-14 15:13:31 +0000416 argv);
417 break;
418 }
419 addStmtToIRSB(bb, IRStmt_Dirty(di));
420}
421
bart1335ecc2009-02-14 16:10:53 +0000422IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
bart09dc13f2009-02-14 15:13:31 +0000423 IRSB* const bb_in,
424 VexGuestLayout* const layout,
425 VexGuestExtents* const vge,
426 IRType const gWordTy,
427 IRType const hWordTy)
428{
429 IRDirty* di;
430 Int i;
431 IRSB* bb;
432 IRExpr** argv;
433 Bool instrument = True;
434 Bool bus_locked = False;
435
436 /* Set up BB */
437 bb = emptyIRSB();
438 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
439 bb->next = deepCopyIRExpr(bb_in->next);
440 bb->jumpkind = bb_in->jumpkind;
441
442 for (i = 0; i < bb_in->stmts_used; i++)
443 {
444 IRStmt* const st = bb_in->stmts[i];
445 tl_assert(st);
446 if (st->tag == Ist_NoOp)
447 continue;
448
449 switch (st->tag)
450 {
451 /* Note: the code for not instrumenting the code in .plt */
452 /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21 */
453 /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4). */
454 /* This is because on this platform dynamic library symbols are */
455 /* relocated in another way than by later binutils versions. The */
456 /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
457 case Ist_IMark:
458 instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
459 != Vg_SectPLT;
460 addStmtToIRSB(bb, st);
461 break;
462
463 case Ist_MBE:
464 switch (st->Ist.MBE.event)
465 {
466 case Imbe_Fence:
467 break; /* not interesting */
468 case Imbe_BusLock:
469 case Imbe_SnoopedStoreBegin:
470 tl_assert(! bus_locked);
471 bus_locked = True;
472 break;
473 case Imbe_BusUnlock:
474 case Imbe_SnoopedStoreEnd:
475 tl_assert(bus_locked);
476 bus_locked = False;
477 break;
478 default:
479 tl_assert(0);
480 }
481 addStmtToIRSB(bb, st);
482 break;
483
484 case Ist_Store:
485 if (instrument && ! bus_locked)
486 {
487 instrument_store(bb,
488 st->Ist.Store.addr,
489 sizeofIRType(typeOfIRExpr(bb->tyenv,
490 st->Ist.Store.data)));
491 }
492 addStmtToIRSB(bb, st);
493 break;
494
495 case Ist_WrTmp:
496 if (instrument)
497 {
498 const IRExpr* const data = st->Ist.WrTmp.data;
499 if (data->tag == Iex_Load)
500 {
501 instrument_load(bb,
502 data->Iex.Load.addr,
503 sizeofIRType(data->Iex.Load.ty));
504 }
505 }
506 addStmtToIRSB(bb, st);
507 break;
508
509 case Ist_Dirty:
510 if (instrument)
511 {
512 IRDirty* d = st->Ist.Dirty.details;
513 IREffect const mFx = d->mFx;
514 switch (mFx) {
515 case Ifx_None:
516 break;
517 case Ifx_Read:
518 case Ifx_Write:
519 case Ifx_Modify:
520 tl_assert(d->mAddr);
521 tl_assert(d->mSize > 0);
522 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
523 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
524 di = unsafeIRDirty_0_N(
525 /*regparms*/2,
526 "drd_trace_load",
bart99edb292009-02-15 15:59:20 +0000527 VG_(fnptr_to_fnentry)(DRD_(trace_load)),
bart09dc13f2009-02-14 15:13:31 +0000528 argv);
529 addStmtToIRSB(bb, IRStmt_Dirty(di));
530 }
531 if ((mFx == Ifx_Write || mFx == Ifx_Modify)
532 && ! bus_locked)
533 {
534 di = unsafeIRDirty_0_N(
535 /*regparms*/2,
536 "drd_trace_store",
bart99edb292009-02-15 15:59:20 +0000537 VG_(fnptr_to_fnentry)(DRD_(trace_store)),
bart09dc13f2009-02-14 15:13:31 +0000538 argv);
539 addStmtToIRSB(bb, IRStmt_Dirty(di));
540 }
541 break;
542 default:
543 tl_assert(0);
544 }
545 }
546 addStmtToIRSB(bb, st);
547 break;
548
549 default:
550 addStmtToIRSB(bb, st);
551 break;
552 }
553 }
554
555 tl_assert(! bus_locked);
556
557 return bb;
558}
559