blob: d4634ffc73f2f4321dda7e2fbf10e2e58d870245 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
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.
11
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.
16
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
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
sewardj85642922008-01-14 11:54:56 +000026#include "drd_barrier.h"
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_clientreq.h"
28#include "drd_cond.h"
29#include "drd_error.h"
30#include "drd_malloc_wrappers.h"
31#include "drd_mutex.h"
32#include "drd_segment.h"
sewardj85642922008-01-14 11:54:56 +000033#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000034#include "drd_suppression.h"
35#include "drd_thread.h"
36#include "drd_track.h"
37#include "drd_vc.h"
sewardj721ad7b2007-11-30 08:30:29 +000038#include "priv_drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000039#include "pub_drd_bitmap.h"
sewardjaf44c822007-11-25 14:01:38 +000040#include "pub_tool_basics.h"
41#include "pub_tool_debuginfo.h" // VG_(describe_IP)()
42#include "pub_tool_libcassert.h" // tl_assert()
43#include "pub_tool_libcbase.h" // VG_(strcmp)
44#include "pub_tool_libcprint.h" // VG_(printf)
sewardj85642922008-01-14 11:54:56 +000045#include "pub_tool_vki.h" // Must be included before pub_tool_libcproc
sewardjaf44c822007-11-25 14:01:38 +000046#include "pub_tool_libcproc.h"
47#include "pub_tool_machine.h"
48#include "pub_tool_options.h" // command line options
49#include "pub_tool_threadstate.h" // VG_(get_running_tid)
50#include "pub_tool_tooliface.h"
51
52
sewardjaf44c822007-11-25 14:01:38 +000053// Function declarations.
54
55static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
56static void drd_set_running_tid(const ThreadId tid);
57
58
59
60// Local variables.
61
62static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000063static Bool drd_trace_fork_join = False;
sewardj85642922008-01-14 11:54:56 +000064static Bool drd_trace_mem = False;
sewardjaf44c822007-11-25 14:01:38 +000065static Addr drd_trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000066
67
68//
69// Implement the needs_command_line_options for drd.
70//
71
72static Bool drd_process_cmd_line_option(Char* arg)
73{
sewardj85642922008-01-14 11:54:56 +000074 Bool trace_barrier = False;
sewardjaf44c822007-11-25 14:01:38 +000075 Bool trace_cond = False;
76 Bool trace_mutex = False;
77 Bool trace_segment = False;
78 Bool trace_suppression = False;
79 Char* trace_address = 0;
80
81 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
sewardj85642922008-01-14 11:54:56 +000082 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
sewardjaf44c822007-11-25 14:01:38 +000083 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
84 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
85 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
86 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
87 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
88 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
89 else VG_STR_CLO (arg, "--trace-address", trace_address)
90 else
91 return False;
92
93 if (trace_address)
94 drd_trace_address = VG_(strtoll16)(trace_address, 0);
sewardj85642922008-01-14 11:54:56 +000095 if (trace_barrier)
96 barrier_set_trace(trace_barrier);
sewardjaf44c822007-11-25 14:01:38 +000097 if (trace_cond)
98 cond_set_trace(trace_cond);
99 if (trace_mutex)
100 mutex_set_trace(trace_mutex);
101 if (trace_segment)
102 sg_set_trace(trace_segment);
103 if (trace_suppression)
104 suppression_set_trace(trace_suppression);
105
106 return True;
107}
108
109static void drd_print_usage(void)
110{
111 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
112 "\n"
113 " --trace-fork-join=no|yes Trace all thread creation and join"
114 " activity\n"
115 " --trace-mutex=no|yes Trace all mutex activity\n"
116 " --trace-segment=no|yes Trace segment actions\n"
117 );
118}
119
120static void drd_print_debug_usage(void)
121{
122}
123
124
125//
126// Implements the thread-related core callbacks.
127//
128
129static
130VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
131{
132 Segment* sg;
133
sewardj8b09d4f2007-12-04 21:27:18 +0000134 thread_set_vg_running_tid(VG_(get_running_tid)());
135
sewardjaf44c822007-11-25 14:01:38 +0000136 if (! thread_is_recording(thread_get_running_tid()))
137 return;
138
139#if 1
140 if (drd_trace_mem || (addr == drd_trace_address))
141 {
142 VG_(message)(Vg_UserMsg, "load 0x%lx size %ld %s (vg %d / drd %d)",
143 addr,
144 size,
145 thread_get_name(thread_get_running_tid()),
146 VG_(get_running_tid)(),
147 thread_get_running_tid());
sewardj85642922008-01-14 11:54:56 +0000148 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
149 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000150 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
151 == VG_(get_running_tid)());
152 }
153#endif
154 sg = thread_get_segment(thread_get_running_tid());
155 bm_access_range(sg->bm, addr, size, eLoad);
156 if (thread_conflicting_access(addr, size, eLoad))
157 {
158 DataRaceErrInfo drei;
159 drei.tid = VG_(get_running_tid)();
160 drei.addr = addr;
161 drei.size = size;
162 drei.access_type = eLoad;
163 VG_(maybe_record_error)(VG_(get_running_tid)(),
164 DataRaceErr,
165 VG_(get_IP)(VG_(get_running_tid)()),
166 "Conflicting accesses",
167 &drei);
168 }
169}
170
171static
172VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
173{
174 Segment* sg;
175
sewardj8b09d4f2007-12-04 21:27:18 +0000176 thread_set_vg_running_tid(VG_(get_running_tid)());
177
sewardjaf44c822007-11-25 14:01:38 +0000178 if (! thread_is_recording(thread_get_running_tid()))
179 return;
180
181#if 1
182 if (drd_trace_mem || (addr == drd_trace_address))
183 {
184 VG_(message)(Vg_UserMsg, "store 0x%lx size %ld %s (vg %d / drd %d / off %d)",
185 addr,
186 size,
187 thread_get_name(thread_get_running_tid()),
188 VG_(get_running_tid)(),
189 thread_get_running_tid(),
190 addr - thread_get_stack_min(thread_get_running_tid()));
sewardj85642922008-01-14 11:54:56 +0000191 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
192 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000193 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
194 == VG_(get_running_tid)());
195 }
196#endif
197 sg = thread_get_segment(thread_get_running_tid());
198 bm_access_range(sg->bm, addr, size, eStore);
199 if (thread_conflicting_access(addr, size, eStore))
200 {
201 DataRaceErrInfo drei;
202 drei.tid = VG_(get_running_tid)();
203 drei.addr = addr;
204 drei.size = size;
205 drei.access_type = eStore;
206 VG_(maybe_record_error)(VG_(get_running_tid)(),
207 DataRaceErr,
208 VG_(get_IP)(VG_(get_running_tid)()),
209 "Conflicting accesses",
210 &drei);
211 }
212}
213
214static void drd_pre_mem_read(const CorePart part,
215 const ThreadId tid,
216 Char* const s,
217 const Addr a,
218 const SizeT size)
219{
sewardj8b09d4f2007-12-04 21:27:18 +0000220 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000221 {
222 drd_trace_load(a, size);
223 }
224}
225
226static void drd_post_mem_write(const CorePart part,
227 const ThreadId tid,
228 const Addr a,
229 const SizeT size)
230{
sewardj8b09d4f2007-12-04 21:27:18 +0000231 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000232 {
233 drd_trace_store(a, size);
234 }
235}
236
237static void drd_start_using_mem(const Addr a1, const Addr a2)
238{
sewardj8b09d4f2007-12-04 21:27:18 +0000239 thread_set_vg_running_tid(VG_(get_running_tid)());
240
sewardjaf44c822007-11-25 14:01:38 +0000241 if (a1 <= drd_trace_address && drd_trace_address < a2
242 && thread_is_recording(thread_get_running_tid()))
243 {
244 VG_(message)(Vg_UserMsg, "start 0x%lx size %ld %s (tracing 0x%lx)",
245 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
246 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000247 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
248 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000249 }
250}
251
252static void drd_stop_using_mem(const Addr a1, const Addr a2)
253{
254 if (a1 <= drd_trace_address && drd_trace_address < a2
255 && thread_is_recording(thread_get_running_tid()))
256 {
257 VG_(message)(Vg_UserMsg, "end 0x%lx size %ld %s (tracing 0x%lx)",
258 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
259 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000260 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
261 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000262 }
263 thread_stop_using_mem(a1, a2);
264 mutex_stop_using_mem(a1, a2);
265 cond_stop_using_mem(a1, a2);
sewardj85642922008-01-14 11:54:56 +0000266 semaphore_stop_using_mem(a1, a2);
267 barrier_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000268 drd_suppression_stop_using_mem(a1, a2);
269}
270
271static VG_REGPARM(2)
272 void drd_make_stack_uninit(const Addr base, const UWord len)
273{
274#if 0
275 VG_(message)(Vg_DebugMsg, "make_stack_uninit(0x%lx, %ld)", base, len);
276#endif
277 drd_stop_using_mem(base, base + len);
278}
279
280/* Called by the core when the stack of a thread grows, to indicate that */
281/* the addresses in range [ a, a + len [ may now be used by the client. */
282/* Assumption: stacks grow downward. */
283static void drd_start_using_mem_stack(const Addr a, const SizeT len)
284{
285 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
286 drd_start_using_mem(a - VG_STACK_REDZONE_SZB,
287 a - VG_STACK_REDZONE_SZB + len);
288}
289
290/* Called by the core when the stack of a thread shrinks, to indicate that */
291/* the addresses [ a, a + len [ are no longer accessible for the client. */
292/* Assumption: stacks grow downward. */
293static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
294{
sewardj8b09d4f2007-12-04 21:27:18 +0000295 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardjaf44c822007-11-25 14:01:38 +0000296 thread_set_stack_min(thread_get_running_tid(),
297 a + len - VG_STACK_REDZONE_SZB);
298 drd_stop_using_mem(a - VG_STACK_REDZONE_SZB,
299 a + len - VG_STACK_REDZONE_SZB);
300}
301
302static void drd_start_using_mem_mmap(Addr a, SizeT len,
303 Bool rr, Bool ww, Bool xx)
304{
305 drd_start_using_mem(a, a + len);
306}
307
308static void drd_stop_using_mem_munmap(Addr a, SizeT len)
309{
310 drd_stop_using_mem(a, a + len);
311}
312
313static
314void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
315{
316 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
317 tl_assert(created != VG_INVALID_THREADID);
318 thread_pre_create(drd_creator, created);
sewardjaf44c822007-11-25 14:01:38 +0000319 if (IsValidDrdThreadId(drd_creator))
320 {
321 thread_new_segment(drd_creator);
322 }
323 if (drd_trace_fork_join)
324 {
325 VG_(message)(Vg_DebugMsg,
326 "drd_pre_thread_create creator = %d/%d, created = %d",
327 creator, drd_creator, created);
328 }
329}
330
331/* Called by Valgrind's core before any loads or stores are performed on */
332/* the context of thread "created". At startup, this function is called */
333/* with arguments (0,1). */
334static
335void drd_post_thread_create(const ThreadId created)
336{
337 const DrdThreadId drd_created = thread_post_create(created);
338 tl_assert(created != VG_INVALID_THREADID);
339 if (drd_trace_fork_join)
340 {
341 VG_(message)(Vg_DebugMsg,
342 "drd_post_thread_create created = %d/%d",
343 created, drd_created);
344 }
345}
346
347/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
348/* after thread drd_joiner joined thread drd_joinee. */
349void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
350{
351 tl_assert(IsValidDrdThreadId(drd_joiner));
352 tl_assert(IsValidDrdThreadId(drd_joinee));
353 thread_new_segment(drd_joinee);
354 thread_combine_vc(drd_joiner, drd_joinee);
355 thread_new_segment(drd_joiner);
356
357 if (drd_trace_fork_join)
358 {
359 char msg[256];
360 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
361 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
362 VG_(snprintf)(msg, sizeof(msg),
363 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
364 joiner, drd_joiner, joinee, drd_joinee);
365 if (joiner)
366 {
367 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
368 ", new vc: ");
369 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
370 thread_get_vc(drd_joiner));
371 }
372 VG_(message)(Vg_DebugMsg, msg);
373 }
374
375 thread_delete(drd_joinee);
376 mutex_thread_delete(drd_joinee);
sewardj85642922008-01-14 11:54:56 +0000377 cond_thread_delete(drd_joinee);
378 semaphore_thread_delete(drd_joinee);
379 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000380}
381
382/* Called after a thread has performed its last memory access. */
383static void drd_thread_finished(ThreadId tid)
384{
sewardj85642922008-01-14 11:54:56 +0000385 DrdThreadId drd_tid;
386
387 drd_set_running_tid(tid);
388
389 drd_tid = VgThreadIdToDrdThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000390 if (drd_trace_fork_join)
391 {
392 VG_(message)(Vg_DebugMsg,
393 "drd_thread_finished tid = %d/%d%s",
394 tid,
395 drd_tid,
396 thread_get_joinable(drd_tid)
397 ? ""
398 : " (which is a detached thread)");
399
400 }
401 thread_finished(drd_tid);
402}
403
sewardj721ad7b2007-11-30 08:30:29 +0000404void drd_pre_mutex_init(Addr mutex, SizeT size, MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000405{
sewardj721ad7b2007-11-30 08:30:29 +0000406 mutex_init(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000407}
408
sewardj721ad7b2007-11-30 08:30:29 +0000409void drd_post_mutex_destroy(Addr mutex, MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000410{
411 struct mutex_info* p;
412
413 p = mutex_get(mutex);
sewardj85642922008-01-14 11:54:56 +0000414 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000415 if (p)
416 {
417 // TO DO: report an error in case the recursion count is not zero
418 // before asserting.
419 tl_assert(mutex_get_recursion_count(mutex) == 0);
420 mutex_destroy(p);
421 }
422}
423
424void drd_pre_mutex_lock(const DrdThreadId drd_tid,
425 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000426 const SizeT size,
427 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000428{
429 if (mutex_get(mutex) == 0)
430 {
sewardj721ad7b2007-11-30 08:30:29 +0000431 mutex_init(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000432 }
433}
434
435void drd_post_mutex_lock(const DrdThreadId drd_tid,
436 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000437 const SizeT size,
438 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000439{
sewardj721ad7b2007-11-30 08:30:29 +0000440 mutex_lock(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000441}
442
sewardj721ad7b2007-11-30 08:30:29 +0000443void drd_pre_mutex_unlock(const DrdThreadId drd_tid,
444 const Addr mutex,
445 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000446{
sewardj721ad7b2007-11-30 08:30:29 +0000447 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000448}
449
450void drd_post_cond_init(Addr cond, SizeT s)
451{
sewardjaf44c822007-11-25 14:01:38 +0000452 if (cond_get(cond))
453 {
454 CondErrInfo cei = { .cond = cond };
455 VG_(maybe_record_error)(VG_(get_running_tid)(),
456 CondErr,
457 VG_(get_IP)(VG_(get_running_tid)()),
458 "initialized twice",
459 &cei);
460 }
sewardj721ad7b2007-11-30 08:30:29 +0000461 cond_init(cond, s);
sewardjaf44c822007-11-25 14:01:38 +0000462}
463
sewardj721ad7b2007-11-30 08:30:29 +0000464void drd_pre_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000465{
466 struct cond_info* cond_p;
467
sewardjaf44c822007-11-25 14:01:38 +0000468 cond_p = cond_get(cond);
469 if (cond_p)
470 {
471 cond_destroy(cond_p);
472 }
473 else
474 {
475 CondErrInfo cei = { .cond = cond };
476 VG_(maybe_record_error)(VG_(get_running_tid)(),
477 CondErr,
478 VG_(get_IP)(VG_(get_running_tid)()),
479 "destroy requested but not initialized",
480 &cei);
481 }
482}
483
sewardj85642922008-01-14 11:54:56 +0000484void drd_semaphore_init(const Addr semaphore, const SizeT size,
485 const Word pshared, const Word value)
486{
487 semaphore_init(semaphore, size, pshared, value);
488}
489
490void drd_semaphore_destroy(const Addr semaphore)
491{
492 struct semaphore_info* p;
493
494 p = semaphore_get(semaphore);
495 tl_assert(p);
496 if (p)
497 {
498 semaphore_destroy(p);
499 }
500}
501
502void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
503 const SizeT size)
504{
505 semaphore_post_wait(tid, semaphore, size);
506}
507
508void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
509 const SizeT size)
510{
511 semaphore_pre_post(tid, semaphore, size);
512}
513
514void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
515 const SizeT size)
516{
517 semaphore_post_post(tid, semaphore, size);
518}
519
520
521void drd_barrier_init(const Addr barrier, const SizeT size, const Word count)
522{
523 barrier_init(barrier, size, count);
524}
525
526void drd_barrier_destroy(const Addr barrier)
527{
528 struct barrier_info* p;
529
530 p = barrier_get(barrier);
531 if (p)
532 {
533 barrier_destroy(p);
534 }
535}
536
537void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
538{
539 barrier_pre_wait(tid, barrier);
540}
541
542void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
543 const Bool waited)
544{
545 barrier_post_wait(tid, barrier, waited);
546}
547
sewardjaf44c822007-11-25 14:01:38 +0000548
549//
550// Implementation of the tool interface.
551//
552
553static
554void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000555{
556# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
557 /* fine */
558# else
sewardj8b09d4f2007-12-04 21:27:18 +0000559 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000560# endif
561}
sewardjaf44c822007-11-25 14:01:38 +0000562
563static
564IRSB* drd_instrument(VgCallbackClosure* const closure,
565 IRSB* const bb_in,
566 VexGuestLayout* const layout,
567 VexGuestExtents* const vge,
568 IRType const gWordTy,
569 IRType const hWordTy)
570{
571 IRDirty* di;
572 Int i;
573 IRSB* bb;
574 IRExpr** argv;
575 IRExpr* addr_expr;
576 IRExpr* size_expr;
577 Bool instrument = True;
578
579 /* Set up BB */
580 bb = emptyIRSB();
581 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
582 bb->next = deepCopyIRExpr(bb_in->next);
583 bb->jumpkind = bb_in->jumpkind;
584
585 for (i = 0; i < bb_in->stmts_used; i++)
586 {
587 IRStmt* const st = bb_in->stmts[i];
588 if (!st || st->tag == Ist_NoOp)
589 continue;
590
591 switch (st->tag)
592 {
593 case Ist_IMark:
594 instrument = VG_(seginfo_sect_kind)(st->Ist.IMark.addr) != Vg_SectPLT;
595 break;
596
597 case Ist_AbiHint:
598 addStmtToIRSB(bb,
599 IRStmt_Dirty(
600 unsafeIRDirty_0_N(
601 /*regparms*/2,
602 "drd_make_stack_uninit",
603 VG_(fnptr_to_fnentry)(drd_make_stack_uninit),
604 mkIRExprVec_2(st->Ist.AbiHint.base,
605 mkIRExpr_HWord((UInt)st->Ist.AbiHint.len))
606 )
607 )
608 );
609 break;
610
611 case Ist_Store:
612 if (instrument)
613 {
614 addr_expr = st->Ist.Store.addr;
615 size_expr = mkIRExpr_HWord(
616 sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Store.data)));
617 argv = mkIRExprVec_2(addr_expr, size_expr);
618 di = unsafeIRDirty_0_N(/*regparms*/2,
619 "drd_trace_store",
620 VG_(fnptr_to_fnentry)(drd_trace_store),
621 argv);
622 addStmtToIRSB(bb, IRStmt_Dirty(di));
623 }
624 addStmtToIRSB(bb, st);
625 break;
626
627 case Ist_WrTmp:
628 if (instrument)
629 {
630 const IRExpr* const data = st->Ist.WrTmp.data;
631 if (data->tag == Iex_Load)
632 {
633 addr_expr = data->Iex.Load.addr;
634 size_expr = mkIRExpr_HWord(sizeofIRType(data->Iex.Load.ty));
635 argv = mkIRExprVec_2(addr_expr, size_expr);
636 di = unsafeIRDirty_0_N(/*regparms*/2,
637 "drd_trace_load",
638 VG_(fnptr_to_fnentry)(drd_trace_load),
639 argv);
640 addStmtToIRSB(bb, IRStmt_Dirty(di));
641 }
642 }
643 addStmtToIRSB(bb, st);
644 break;
645
646 case Ist_Dirty:
647 if (instrument)
648 {
649 IRDirty* d = st->Ist.Dirty.details;
650 IREffect const mFx = d->mFx;
651 switch (mFx) {
652 case Ifx_None:
653 break;
654 case Ifx_Read:
655 case Ifx_Write:
656 case Ifx_Modify:
657 tl_assert(d->mAddr);
658 tl_assert(d->mSize > 0);
659 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
660 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
661 di = unsafeIRDirty_0_N(
662 /*regparms*/2,
663 "drd_trace_load",
664 VG_(fnptr_to_fnentry)(drd_trace_load),
665 argv);
666 addStmtToIRSB(bb, IRStmt_Dirty(di));
667 }
668 if (mFx == Ifx_Write || mFx == Ifx_Modify) {
669 di = unsafeIRDirty_0_N(
670 /*regparms*/2,
671 "drd_trace_store",
672 VG_(fnptr_to_fnentry)(drd_trace_store),
673 argv);
674 addStmtToIRSB(bb, IRStmt_Dirty(di));
675 }
676 break;
677 default:
678 tl_assert(0);
679 }
680 }
681 addStmtToIRSB(bb, st);
682 break;
683
684 default:
685 addStmtToIRSB(bb, st);
686 break;
687 }
688 }
689
690 return bb;
691}
692
sewardj8b09d4f2007-12-04 21:27:18 +0000693static void drd_set_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000694{
sewardj8b09d4f2007-12-04 21:27:18 +0000695 static ThreadId s_last_vg_tid = VG_INVALID_THREADID;
696 if (vg_tid != s_last_vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000697 {
sewardj8b09d4f2007-12-04 21:27:18 +0000698 const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
sewardjaf44c822007-11-25 14:01:38 +0000699 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000700 s_last_vg_tid = vg_tid;
sewardjaf44c822007-11-25 14:01:38 +0000701 if (drd_trace_fork_join)
702 {
703 VG_(message)(Vg_DebugMsg,
704 "drd_track_thread_run tid = %d / drd tid %d",
sewardj8b09d4f2007-12-04 21:27:18 +0000705 vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000706 }
sewardj8b09d4f2007-12-04 21:27:18 +0000707 thread_set_running_tid(vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000708 }
709}
710
711static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
712{
713 drd_set_running_tid(tid);
714}
715
716static
717void drd_fini(Int exitcode)
718{
719 // thread_print_all();
720#ifdef OLD_RACE_DETECTION_ALGORITHM
721 thread_report_all_races();
722#endif
723 if (VG_(clo_verbosity) > 1 || drd_print_stats)
724 {
725 VG_(message)(Vg_DebugMsg,
726 " thread: %lld context switches"
727 " / %lld updates of the danger set",
728 thread_get_context_switch_count(),
729 thread_get_update_danger_set_count());
730#ifdef OLD_RACE_DETECTION_ALGORITHM
731 VG_(message)(Vg_DebugMsg,
732 " analysis: %lld data race analysis points",
733 thread_get_report_races_count());
734#endif
735 VG_(message)(Vg_DebugMsg,
736 " segments: %lld total, %lld max, %lld discard points",
737 sg_get_segments_created_count(),
738 sg_get_max_segments_alive_count(),
739 thread_get_discard_ordered_segments_count());
740 VG_(message)(Vg_DebugMsg,
741 " bitmaps: %lld / %lld bitmaps were allocated"
742 " and %lld / %lld for danger set updates",
743 bm_get_bitmap_creation_count(),
744 bm_get_bitmap2_creation_count(),
745 thread_get_danger_set_bitmap_creation_count(),
746 thread_get_danger_set_bitmap2_creation_count());
747 VG_(message)(Vg_DebugMsg,
748 " mutex: %lld non-recursive lock/unlock events",
749 get_mutex_lock_count());
750 drd_print_malloc_stats();
751 }
752}
753
sewardjaf44c822007-11-25 14:01:38 +0000754static
755void drd_pre_clo_init(void)
756{
757 // Basic tool stuff.
758
759 VG_(details_name) ("exp-drd");
760 VG_(details_version) (NULL);
761 VG_(details_description) ("a data race detector");
sewardj85642922008-01-14 11:54:56 +0000762 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
sewardjaf44c822007-11-25 14:01:38 +0000763 " by Bart Van Assche.");
764 VG_(details_bug_reports_to) (VG_BUGS_TO);
765
766 VG_(basic_tool_funcs) (drd_post_clo_init,
767 drd_instrument,
768 drd_fini);
769
770 // Command line stuff.
771 VG_(needs_command_line_options)(drd_process_cmd_line_option,
772 drd_print_usage,
773 drd_print_debug_usage);
774
775 drd_register_error_handlers();
776
777 // Core event tracking.
778 VG_(track_pre_mem_read) (drd_pre_mem_read);
779 VG_(track_post_mem_write) (drd_post_mem_write);
780 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
781 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
782 VG_(track_new_mem_mmap) (drd_start_using_mem_mmap);
783 VG_(track_die_mem_munmap) (drd_stop_using_mem_munmap);
784 VG_(track_start_client_code) (drd_start_client_code);
785 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
786 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
787 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
788
789 // Other stuff.
790 VG_(needs_data_syms)();
791
792 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
793
794 drd_clientreq_init();
795
796 drd_suppression_init();
sewardjaf44c822007-11-25 14:01:38 +0000797}
798
799
800VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
801
802
803/*
804 * Local variables:
805 * c-basic-offset: 3
806 * End:
807 */