blob: 0262962edbcd243d81a636469caf9e87fb1b673d [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"
bart4bb53d82008-02-28 19:06:34 +000028#include "drd_clientobj.h"
sewardjaf44c822007-11-25 14:01:38 +000029#include "drd_cond.h"
30#include "drd_error.h"
31#include "drd_malloc_wrappers.h"
32#include "drd_mutex.h"
bart5bd9f2d2008-03-03 20:31:58 +000033#include "drd_rwlock.h"
sewardjaf44c822007-11-25 14:01:38 +000034#include "drd_segment.h"
sewardj85642922008-01-14 11:54:56 +000035#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000036#include "drd_suppression.h"
37#include "drd_thread.h"
38#include "drd_track.h"
39#include "drd_vc.h"
sewardj721ad7b2007-11-30 08:30:29 +000040#include "priv_drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000041#include "pub_drd_bitmap.h"
sewardjaf44c822007-11-25 14:01:38 +000042#include "pub_tool_basics.h"
43#include "pub_tool_debuginfo.h" // VG_(describe_IP)()
44#include "pub_tool_libcassert.h" // tl_assert()
45#include "pub_tool_libcbase.h" // VG_(strcmp)
46#include "pub_tool_libcprint.h" // VG_(printf)
sewardj85642922008-01-14 11:54:56 +000047#include "pub_tool_vki.h" // Must be included before pub_tool_libcproc
sewardjaf44c822007-11-25 14:01:38 +000048#include "pub_tool_libcproc.h"
49#include "pub_tool_machine.h"
50#include "pub_tool_options.h" // command line options
bart72b751c2008-03-01 13:44:24 +000051#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
sewardjaf44c822007-11-25 14:01:38 +000052#include "pub_tool_tooliface.h"
53
54
sewardjaf44c822007-11-25 14:01:38 +000055// Function declarations.
56
barteb8b8c82008-02-26 19:11:20 +000057static void instrument_memory_bus_event(IRSB* const bb,
58 const IRMBusEvent event);
sewardjaf44c822007-11-25 14:01:38 +000059static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
60static void drd_set_running_tid(const ThreadId tid);
barteb8b8c82008-02-26 19:11:20 +000061static void evh__bus_lock(void);
62static void evh__bus_unlock(void);
sewardjaf44c822007-11-25 14:01:38 +000063
64
65
66// Local variables.
67
68static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000069static Bool drd_trace_fork_join = False;
sewardj85642922008-01-14 11:54:56 +000070static Bool drd_trace_mem = False;
sewardjaf44c822007-11-25 14:01:38 +000071static Addr drd_trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000072
73
74//
75// Implement the needs_command_line_options for drd.
76//
77
78static Bool drd_process_cmd_line_option(Char* arg)
79{
sewardj85642922008-01-14 11:54:56 +000080 Bool trace_barrier = False;
bart72b751c2008-03-01 13:44:24 +000081 Bool trace_clientobj = False;
sewardjaf44c822007-11-25 14:01:38 +000082 Bool trace_cond = False;
bartecbf1662008-02-24 18:46:05 +000083 Bool trace_csw = False;
84 Bool trace_danger_set = False;
sewardjaf44c822007-11-25 14:01:38 +000085 Bool trace_mutex = False;
bart5bd9f2d2008-03-03 20:31:58 +000086 Bool trace_rwlock = False;
sewardjaf44c822007-11-25 14:01:38 +000087 Bool trace_segment = False;
bart28230a32008-02-29 17:27:03 +000088 Bool trace_semaphore = False;
sewardjaf44c822007-11-25 14:01:38 +000089 Bool trace_suppression = False;
90 Char* trace_address = 0;
91
92 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
sewardj85642922008-01-14 11:54:56 +000093 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
bart72b751c2008-03-01 13:44:24 +000094 else VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj)
sewardjaf44c822007-11-25 14:01:38 +000095 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
bartecbf1662008-02-24 18:46:05 +000096 else VG_BOOL_CLO(arg, "--trace-csw", trace_csw)
97 else VG_BOOL_CLO(arg, "--trace-danger-set", trace_danger_set)
sewardjaf44c822007-11-25 14:01:38 +000098 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
99 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
100 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
bart5bd9f2d2008-03-03 20:31:58 +0000101 else VG_BOOL_CLO(arg, "--trace-rwlock", trace_rwlock)
sewardjaf44c822007-11-25 14:01:38 +0000102 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
bart28230a32008-02-29 17:27:03 +0000103 else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
sewardjaf44c822007-11-25 14:01:38 +0000104 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
105 else VG_STR_CLO (arg, "--trace-address", trace_address)
106 else
107 return False;
108
109 if (trace_address)
sewardjc0be9252008-02-11 11:00:51 +0000110 {
sewardjaf44c822007-11-25 14:01:38 +0000111 drd_trace_address = VG_(strtoll16)(trace_address, 0);
sewardjc0be9252008-02-11 11:00:51 +0000112 }
sewardj85642922008-01-14 11:54:56 +0000113 if (trace_barrier)
114 barrier_set_trace(trace_barrier);
bart72b751c2008-03-01 13:44:24 +0000115 if (trace_clientobj)
116 clientobj_set_trace(trace_clientobj);
sewardjaf44c822007-11-25 14:01:38 +0000117 if (trace_cond)
118 cond_set_trace(trace_cond);
bartecbf1662008-02-24 18:46:05 +0000119 if (trace_csw)
120 thread_trace_context_switches(trace_csw);
121 if (trace_danger_set)
122 thread_trace_danger_set(trace_danger_set);
sewardjaf44c822007-11-25 14:01:38 +0000123 if (trace_mutex)
124 mutex_set_trace(trace_mutex);
bart5bd9f2d2008-03-03 20:31:58 +0000125 if (trace_rwlock)
126 rwlock_set_trace(trace_rwlock);
sewardjaf44c822007-11-25 14:01:38 +0000127 if (trace_segment)
128 sg_set_trace(trace_segment);
bart28230a32008-02-29 17:27:03 +0000129 if (trace_semaphore)
130 semaphore_set_trace(trace_semaphore);
sewardjaf44c822007-11-25 14:01:38 +0000131 if (trace_suppression)
132 suppression_set_trace(trace_suppression);
133
134 return True;
135}
136
137static void drd_print_usage(void)
138{
139 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
140 "\n"
141 " --trace-fork-join=no|yes Trace all thread creation and join"
142 " activity\n"
143 " --trace-mutex=no|yes Trace all mutex activity\n"
144 " --trace-segment=no|yes Trace segment actions\n"
145 );
146}
147
148static void drd_print_debug_usage(void)
149{
150}
151
152
153//
154// Implements the thread-related core callbacks.
155//
156
157static
158VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
159{
160 Segment* sg;
161
bart5e85d262008-03-01 10:49:37 +0000162 tl_assert(thread_get_running_tid()
163 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
sewardjaf44c822007-11-25 14:01:38 +0000164
165#if 1
166 if (drd_trace_mem || (addr == drd_trace_address))
167 {
bart5bd9f2d2008-03-03 20:31:58 +0000168 char vc[80];
169 vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
170 VG_(message)(Vg_UserMsg, "load 0x%lx size %ld %s (vg %d / drd %d / vc %s)",
sewardjaf44c822007-11-25 14:01:38 +0000171 addr,
172 size,
173 thread_get_name(thread_get_running_tid()),
174 VG_(get_running_tid)(),
bart5bd9f2d2008-03-03 20:31:58 +0000175 thread_get_running_tid(),
176 vc);
sewardj85642922008-01-14 11:54:56 +0000177 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
178 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000179 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
180 == VG_(get_running_tid)());
181 }
182#endif
183 sg = thread_get_segment(thread_get_running_tid());
184 bm_access_range(sg->bm, addr, size, eLoad);
185 if (thread_conflicting_access(addr, size, eLoad))
186 {
187 DataRaceErrInfo drei;
188 drei.tid = VG_(get_running_tid)();
189 drei.addr = addr;
190 drei.size = size;
191 drei.access_type = eLoad;
192 VG_(maybe_record_error)(VG_(get_running_tid)(),
193 DataRaceErr,
194 VG_(get_IP)(VG_(get_running_tid)()),
195 "Conflicting accesses",
196 &drei);
197 }
198}
199
200static
201VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
202{
203 Segment* sg;
204
bart5e85d262008-03-01 10:49:37 +0000205 tl_assert(thread_get_running_tid()
206 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
sewardjaf44c822007-11-25 14:01:38 +0000207
208#if 1
209 if (drd_trace_mem || (addr == drd_trace_address))
210 {
bart5bd9f2d2008-03-03 20:31:58 +0000211 char vc[80];
212 vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
213 VG_(message)(Vg_UserMsg, "store 0x%lx size %ld %s (vg %d / drd %d / off %d / vc %s)",
sewardjaf44c822007-11-25 14:01:38 +0000214 addr,
215 size,
216 thread_get_name(thread_get_running_tid()),
217 VG_(get_running_tid)(),
218 thread_get_running_tid(),
bart5bd9f2d2008-03-03 20:31:58 +0000219 addr - thread_get_stack_min(thread_get_running_tid()),
220 vc);
sewardj85642922008-01-14 11:54:56 +0000221 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
222 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000223 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
224 == VG_(get_running_tid)());
225 }
226#endif
227 sg = thread_get_segment(thread_get_running_tid());
228 bm_access_range(sg->bm, addr, size, eStore);
229 if (thread_conflicting_access(addr, size, eStore))
230 {
231 DataRaceErrInfo drei;
232 drei.tid = VG_(get_running_tid)();
233 drei.addr = addr;
234 drei.size = size;
235 drei.access_type = eStore;
236 VG_(maybe_record_error)(VG_(get_running_tid)(),
237 DataRaceErr,
238 VG_(get_IP)(VG_(get_running_tid)()),
239 "Conflicting accesses",
240 &drei);
241 }
242}
243
244static void drd_pre_mem_read(const CorePart part,
245 const ThreadId tid,
246 Char* const s,
247 const Addr a,
248 const SizeT size)
249{
sewardj8b09d4f2007-12-04 21:27:18 +0000250 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000251 {
252 drd_trace_load(a, size);
253 }
254}
255
bart5e85d262008-03-01 10:49:37 +0000256static void drd_pre_mem_read_asciiz(const CorePart part,
257 const ThreadId tid,
258 Char* const s,
259 const Addr a)
260{
261 const char* p = (void*)a;
262 SizeT size = 0;
263
264 /* Note: the expression '*p' reads client memory and may crash if the */
265 /* client provided an invalid pointer ! */
266 while (*p)
267 {
268 p++;
269 size++;
270 }
271 // To do: find out what a reasonable upper limit on 'size' is.
272 tl_assert(size < 4096);
273 if (size > 0)
274 {
275 drd_trace_load(a, size);
276 }
277}
278
sewardjaf44c822007-11-25 14:01:38 +0000279static void drd_post_mem_write(const CorePart part,
280 const ThreadId tid,
281 const Addr a,
282 const SizeT size)
283{
bart5e85d262008-03-01 10:49:37 +0000284 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardj8b09d4f2007-12-04 21:27:18 +0000285 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000286 {
287 drd_trace_store(a, size);
288 }
289}
290
bart5e85d262008-03-01 10:49:37 +0000291static void drd_start_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000292{
bart5e85d262008-03-01 10:49:37 +0000293 const Addr a2 = a1 + len;
294
295 tl_assert(a1 < a2);
296
sewardj8b09d4f2007-12-04 21:27:18 +0000297 thread_set_vg_running_tid(VG_(get_running_tid)());
298
bart5e85d262008-03-01 10:49:37 +0000299 if (a1 <= drd_trace_address && drd_trace_address < a2)
sewardjaf44c822007-11-25 14:01:38 +0000300 {
301 VG_(message)(Vg_UserMsg, "start 0x%lx size %ld %s (tracing 0x%lx)",
302 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
303 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000304 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
305 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000306 }
307}
308
bart5e85d262008-03-01 10:49:37 +0000309static void drd_stop_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000310{
bart5e85d262008-03-01 10:49:37 +0000311 const Addr a2 = a1 + len;
312
313 tl_assert(a1 < a2);
314
315 if (a1 <= drd_trace_address && drd_trace_address < a2)
sewardjaf44c822007-11-25 14:01:38 +0000316 {
317 VG_(message)(Vg_UserMsg, "end 0x%lx size %ld %s (tracing 0x%lx)",
318 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
319 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000320 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
321 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000322 }
323 thread_stop_using_mem(a1, a2);
bart72b751c2008-03-01 13:44:24 +0000324 clientobj_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000325 drd_suppression_stop_using_mem(a1, a2);
326}
327
bart5e85d262008-03-01 10:49:37 +0000328static
329void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
330 const Bool rr, const Bool ww, const Bool xx)
331{
332 drd_start_using_mem(a, len);
333}
334
sewardjaf44c822007-11-25 14:01:38 +0000335/* Called by the core when the stack of a thread grows, to indicate that */
336/* the addresses in range [ a, a + len [ may now be used by the client. */
337/* Assumption: stacks grow downward. */
338static void drd_start_using_mem_stack(const Addr a, const SizeT len)
339{
340 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
bart5e85d262008-03-01 10:49:37 +0000341 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000342}
343
344/* Called by the core when the stack of a thread shrinks, to indicate that */
345/* the addresses [ a, a + len [ are no longer accessible for the client. */
346/* Assumption: stacks grow downward. */
347static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
348{
sewardj8b09d4f2007-12-04 21:27:18 +0000349 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardjaf44c822007-11-25 14:01:38 +0000350 thread_set_stack_min(thread_get_running_tid(),
351 a + len - VG_STACK_REDZONE_SZB);
bart5e85d262008-03-01 10:49:37 +0000352 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000353}
354
bart5e85d262008-03-01 10:49:37 +0000355static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000356{
bart5e85d262008-03-01 10:49:37 +0000357 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000358}
359
bart5e85d262008-03-01 10:49:37 +0000360static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000361{
bart5e85d262008-03-01 10:49:37 +0000362 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000363}
364
365static
366void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
367{
368 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
369 tl_assert(created != VG_INVALID_THREADID);
370 thread_pre_create(drd_creator, created);
sewardjaf44c822007-11-25 14:01:38 +0000371 if (IsValidDrdThreadId(drd_creator))
372 {
373 thread_new_segment(drd_creator);
374 }
375 if (drd_trace_fork_join)
376 {
377 VG_(message)(Vg_DebugMsg,
378 "drd_pre_thread_create creator = %d/%d, created = %d",
379 creator, drd_creator, created);
380 }
381}
382
383/* Called by Valgrind's core before any loads or stores are performed on */
384/* the context of thread "created". At startup, this function is called */
385/* with arguments (0,1). */
386static
387void drd_post_thread_create(const ThreadId created)
388{
389 const DrdThreadId drd_created = thread_post_create(created);
390 tl_assert(created != VG_INVALID_THREADID);
391 if (drd_trace_fork_join)
392 {
393 VG_(message)(Vg_DebugMsg,
394 "drd_post_thread_create created = %d/%d",
395 created, drd_created);
396 }
397}
398
399/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
400/* after thread drd_joiner joined thread drd_joinee. */
401void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
402{
403 tl_assert(IsValidDrdThreadId(drd_joiner));
404 tl_assert(IsValidDrdThreadId(drd_joinee));
405 thread_new_segment(drd_joinee);
406 thread_combine_vc(drd_joiner, drd_joinee);
407 thread_new_segment(drd_joiner);
408
409 if (drd_trace_fork_join)
410 {
411 char msg[256];
412 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
413 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
414 VG_(snprintf)(msg, sizeof(msg),
415 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
416 joiner, drd_joiner, joinee, drd_joinee);
417 if (joiner)
418 {
419 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
420 ", new vc: ");
421 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
422 thread_get_vc(drd_joiner));
423 }
424 VG_(message)(Vg_DebugMsg, msg);
425 }
426
427 thread_delete(drd_joinee);
428 mutex_thread_delete(drd_joinee);
sewardj85642922008-01-14 11:54:56 +0000429 cond_thread_delete(drd_joinee);
430 semaphore_thread_delete(drd_joinee);
431 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000432}
433
bart5bd9f2d2008-03-03 20:31:58 +0000434void drd_trace_addr(const Addr addr)
435{
436 drd_trace_address = addr;
437}
438
sewardjaf44c822007-11-25 14:01:38 +0000439/* Called after a thread has performed its last memory access. */
440static void drd_thread_finished(ThreadId tid)
441{
sewardj85642922008-01-14 11:54:56 +0000442 DrdThreadId drd_tid;
443
444 drd_set_running_tid(tid);
445
446 drd_tid = VgThreadIdToDrdThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000447 if (drd_trace_fork_join)
448 {
449 VG_(message)(Vg_DebugMsg,
450 "drd_thread_finished tid = %d/%d%s",
451 tid,
452 drd_tid,
453 thread_get_joinable(drd_tid)
454 ? ""
455 : " (which is a detached thread)");
456
457 }
458 thread_finished(drd_tid);
459}
460
sewardj347eeba2008-01-21 14:19:07 +0000461void drd_pre_mutex_init(const Addr mutex, const SizeT size,
462 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000463{
sewardj721ad7b2007-11-30 08:30:29 +0000464 mutex_init(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000465}
466
sewardj347eeba2008-01-21 14:19:07 +0000467void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000468{
sewardj347eeba2008-01-21 14:19:07 +0000469 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000470}
471
bart00344642008-03-01 15:27:41 +0000472void drd_pre_mutex_lock(const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000473 const SizeT size,
474 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000475{
bart8bba1f72008-02-27 16:13:05 +0000476 mutex_pre_lock(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000477}
478
bart00344642008-03-01 15:27:41 +0000479void drd_post_mutex_lock(const Addr mutex, const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000480{
bart00344642008-03-01 15:27:41 +0000481 mutex_post_lock(mutex, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000482}
483
bart00344642008-03-01 15:27:41 +0000484void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000485{
sewardj721ad7b2007-11-30 08:30:29 +0000486 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000487}
488
bart72b751c2008-03-01 13:44:24 +0000489void drd_pre_cond_init(Addr cond, SizeT s)
sewardjaf44c822007-11-25 14:01:38 +0000490{
bart72b751c2008-03-01 13:44:24 +0000491 cond_pre_init(cond, s);
sewardjaf44c822007-11-25 14:01:38 +0000492}
493
bart72b751c2008-03-01 13:44:24 +0000494void drd_post_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000495{
bart72b751c2008-03-01 13:44:24 +0000496 cond_post_destroy(cond);
sewardjaf44c822007-11-25 14:01:38 +0000497}
498
sewardj85642922008-01-14 11:54:56 +0000499void drd_semaphore_init(const Addr semaphore, const SizeT size,
500 const Word pshared, const Word value)
501{
502 semaphore_init(semaphore, size, pshared, value);
503}
504
505void drd_semaphore_destroy(const Addr semaphore)
506{
bart72b751c2008-03-01 13:44:24 +0000507 semaphore_destroy(semaphore);
sewardj85642922008-01-14 11:54:56 +0000508}
509
bart28230a32008-02-29 17:27:03 +0000510void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
511 const SizeT size)
sewardj85642922008-01-14 11:54:56 +0000512{
bart28230a32008-02-29 17:27:03 +0000513 semaphore_pre_wait(semaphore, size);
514}
515
516void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
517 const Bool waited)
518{
519 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000520}
521
522void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
523 const SizeT size)
524{
525 semaphore_pre_post(tid, semaphore, size);
526}
527
528void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
sewardje3b57aa2008-01-18 07:42:01 +0000529 const SizeT size, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000530{
sewardje3b57aa2008-01-18 07:42:01 +0000531 semaphore_post_post(tid, semaphore, size, waited);
sewardj85642922008-01-14 11:54:56 +0000532}
533
534
535void drd_barrier_init(const Addr barrier, const SizeT size, const Word count)
536{
537 barrier_init(barrier, size, count);
538}
539
540void drd_barrier_destroy(const Addr barrier)
541{
bart72b751c2008-03-01 13:44:24 +0000542 barrier_destroy(barrier);
sewardj85642922008-01-14 11:54:56 +0000543}
544
545void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
546{
547 barrier_pre_wait(tid, barrier);
548}
549
550void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
551 const Bool waited)
552{
553 barrier_post_wait(tid, barrier, waited);
554}
555
sewardjaf44c822007-11-25 14:01:38 +0000556
557//
558// Implementation of the tool interface.
559//
560
561static
562void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000563{
564# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
565 /* fine */
566# else
sewardj8b09d4f2007-12-04 21:27:18 +0000567 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000568# endif
569}
sewardjaf44c822007-11-25 14:01:38 +0000570
571static
572IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000573 IRSB* const bb_in,
574 VexGuestLayout* const layout,
575 VexGuestExtents* const vge,
576 IRType const gWordTy,
577 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000578{
579 IRDirty* di;
580 Int i;
581 IRSB* bb;
582 IRExpr** argv;
583 IRExpr* addr_expr;
584 IRExpr* size_expr;
585 Bool instrument = True;
586
587 /* Set up BB */
588 bb = emptyIRSB();
589 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
590 bb->next = deepCopyIRExpr(bb_in->next);
591 bb->jumpkind = bb_in->jumpkind;
592
593 for (i = 0; i < bb_in->stmts_used; i++)
594 {
595 IRStmt* const st = bb_in->stmts[i];
barteb8b8c82008-02-26 19:11:20 +0000596 tl_assert(st);
597 if (st->tag == Ist_NoOp)
sewardjaf44c822007-11-25 14:01:38 +0000598 continue;
599
600 switch (st->tag)
601 {
602 case Ist_IMark:
sewardjb8b79ad2008-03-03 01:35:41 +0000603 instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
604 != Vg_SectPLT;
sewardjaf44c822007-11-25 14:01:38 +0000605 break;
606
barteb8b8c82008-02-26 19:11:20 +0000607 case Ist_MBE:
608 instrument_memory_bus_event(bb, st->Ist.MBE.event);
609 addStmtToIRSB(bb, st);
610 break;
611
sewardjaf44c822007-11-25 14:01:38 +0000612 case Ist_Store:
613 if (instrument)
614 {
615 addr_expr = st->Ist.Store.addr;
616 size_expr = mkIRExpr_HWord(
617 sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Store.data)));
618 argv = mkIRExprVec_2(addr_expr, size_expr);
619 di = unsafeIRDirty_0_N(/*regparms*/2,
620 "drd_trace_store",
621 VG_(fnptr_to_fnentry)(drd_trace_store),
622 argv);
623 addStmtToIRSB(bb, IRStmt_Dirty(di));
624 }
625 addStmtToIRSB(bb, st);
626 break;
627
628 case Ist_WrTmp:
629 if (instrument)
630 {
631 const IRExpr* const data = st->Ist.WrTmp.data;
632 if (data->tag == Iex_Load)
633 {
634 addr_expr = data->Iex.Load.addr;
635 size_expr = mkIRExpr_HWord(sizeofIRType(data->Iex.Load.ty));
636 argv = mkIRExprVec_2(addr_expr, size_expr);
637 di = unsafeIRDirty_0_N(/*regparms*/2,
638 "drd_trace_load",
639 VG_(fnptr_to_fnentry)(drd_trace_load),
640 argv);
641 addStmtToIRSB(bb, IRStmt_Dirty(di));
642 }
643 }
644 addStmtToIRSB(bb, st);
645 break;
646
647 case Ist_Dirty:
648 if (instrument)
649 {
650 IRDirty* d = st->Ist.Dirty.details;
651 IREffect const mFx = d->mFx;
652 switch (mFx) {
653 case Ifx_None:
654 break;
655 case Ifx_Read:
656 case Ifx_Write:
657 case Ifx_Modify:
658 tl_assert(d->mAddr);
659 tl_assert(d->mSize > 0);
660 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
661 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
662 di = unsafeIRDirty_0_N(
663 /*regparms*/2,
664 "drd_trace_load",
665 VG_(fnptr_to_fnentry)(drd_trace_load),
666 argv);
667 addStmtToIRSB(bb, IRStmt_Dirty(di));
668 }
669 if (mFx == Ifx_Write || mFx == Ifx_Modify) {
670 di = unsafeIRDirty_0_N(
671 /*regparms*/2,
672 "drd_trace_store",
673 VG_(fnptr_to_fnentry)(drd_trace_store),
674 argv);
675 addStmtToIRSB(bb, IRStmt_Dirty(di));
676 }
677 break;
678 default:
679 tl_assert(0);
680 }
681 }
682 addStmtToIRSB(bb, st);
683 break;
684
685 default:
686 addStmtToIRSB(bb, st);
687 break;
688 }
689 }
690
691 return bb;
692}
693
barteb8b8c82008-02-26 19:11:20 +0000694/* Based on the function with the same name in Helgrind's hg_main.c */
695static void instrument_memory_bus_event(IRSB* const bb,
bartbbb67992008-03-01 07:41:17 +0000696 const IRMBusEvent event)
barteb8b8c82008-02-26 19:11:20 +0000697{
698 switch (event)
699 {
700 case Imbe_Fence:
701 break; /* not interesting */
702 case Imbe_BusLock:
703 addStmtToIRSB(bb,
704 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_lock",
705 VG_(fnptr_to_fnentry)(&evh__bus_lock), mkIRExprVec_0())
706 ));
707 break;
708 case Imbe_BusUnlock:
709 addStmtToIRSB(bb,
710 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_unlock",
711 VG_(fnptr_to_fnentry)(&evh__bus_unlock), mkIRExprVec_0())
712 ));
713 break;
714 default:
715 tl_assert(0);
716 }
717}
718
719/** Locking the memory bus is a way to serialize store operations.
720 * What the lwarx / stwcx instructions do on PowerPC is to detect whether
721 * any other CPU has invalidated the cache line in which the location
722 * specified by lwarx resides has been invalidated at the time the stwcx
723 * instruction is executed.
724 */
725static void evh__bus_lock(void)
726{
727 /* To do: implement this function. */
728}
729
730static void evh__bus_unlock(void)
731{
732 /* To do: implement this function. */
733}
734
sewardj8b09d4f2007-12-04 21:27:18 +0000735static void drd_set_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000736{
sewardj8b09d4f2007-12-04 21:27:18 +0000737 static ThreadId s_last_vg_tid = VG_INVALID_THREADID;
738 if (vg_tid != s_last_vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000739 {
sewardj8b09d4f2007-12-04 21:27:18 +0000740 const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
sewardjaf44c822007-11-25 14:01:38 +0000741 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000742 s_last_vg_tid = vg_tid;
sewardjaf44c822007-11-25 14:01:38 +0000743 if (drd_trace_fork_join)
744 {
745 VG_(message)(Vg_DebugMsg,
746 "drd_track_thread_run tid = %d / drd tid %d",
sewardj8b09d4f2007-12-04 21:27:18 +0000747 vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000748 }
sewardj8b09d4f2007-12-04 21:27:18 +0000749 thread_set_running_tid(vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000750 }
751}
752
753static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
754{
755 drd_set_running_tid(tid);
756}
757
758static
759void drd_fini(Int exitcode)
760{
761 // thread_print_all();
sewardjaf44c822007-11-25 14:01:38 +0000762 if (VG_(clo_verbosity) > 1 || drd_print_stats)
763 {
764 VG_(message)(Vg_DebugMsg,
765 " thread: %lld context switches"
766 " / %lld updates of the danger set",
767 thread_get_context_switch_count(),
768 thread_get_update_danger_set_count());
sewardjaf44c822007-11-25 14:01:38 +0000769 VG_(message)(Vg_DebugMsg,
770 " segments: %lld total, %lld max, %lld discard points",
771 sg_get_segments_created_count(),
772 sg_get_max_segments_alive_count(),
773 thread_get_discard_ordered_segments_count());
774 VG_(message)(Vg_DebugMsg,
775 " bitmaps: %lld / %lld bitmaps were allocated"
776 " and %lld / %lld for danger set updates",
777 bm_get_bitmap_creation_count(),
778 bm_get_bitmap2_creation_count(),
779 thread_get_danger_set_bitmap_creation_count(),
780 thread_get_danger_set_bitmap2_creation_count());
781 VG_(message)(Vg_DebugMsg,
782 " mutex: %lld non-recursive lock/unlock events",
783 get_mutex_lock_count());
784 drd_print_malloc_stats();
785 }
786}
787
sewardjaf44c822007-11-25 14:01:38 +0000788static
789void drd_pre_clo_init(void)
790{
791 // Basic tool stuff.
792
793 VG_(details_name) ("exp-drd");
794 VG_(details_version) (NULL);
795 VG_(details_description) ("a data race detector");
sewardj85642922008-01-14 11:54:56 +0000796 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
sewardjaf44c822007-11-25 14:01:38 +0000797 " by Bart Van Assche.");
798 VG_(details_bug_reports_to) (VG_BUGS_TO);
799
800 VG_(basic_tool_funcs) (drd_post_clo_init,
801 drd_instrument,
802 drd_fini);
803
804 // Command line stuff.
805 VG_(needs_command_line_options)(drd_process_cmd_line_option,
806 drd_print_usage,
807 drd_print_debug_usage);
808
bart5e85d262008-03-01 10:49:37 +0000809 // Error handling.
sewardjaf44c822007-11-25 14:01:38 +0000810 drd_register_error_handlers();
811
812 // Core event tracking.
813 VG_(track_pre_mem_read) (drd_pre_mem_read);
bart5e85d262008-03-01 10:49:37 +0000814 VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz);
sewardjaf44c822007-11-25 14:01:38 +0000815 VG_(track_post_mem_write) (drd_post_mem_write);
bart5e85d262008-03-01 10:49:37 +0000816 VG_(track_new_mem_brk) (drd_start_using_mem);
817 VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms);
sewardjaf44c822007-11-25 14:01:38 +0000818 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
bart5e85d262008-03-01 10:49:37 +0000819 VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
820 VG_(track_new_mem_startup) (drd_start_using_mem_w_perms);
821 VG_(track_die_mem_brk) (drd_stop_using_mem);
822 VG_(track_die_mem_munmap) (drd_stop_using_mem);
sewardjaf44c822007-11-25 14:01:38 +0000823 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
bart5e85d262008-03-01 10:49:37 +0000824 VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
sewardjaf44c822007-11-25 14:01:38 +0000825 VG_(track_start_client_code) (drd_start_client_code);
826 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
827 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
828 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
829
830 // Other stuff.
sewardjb8b79ad2008-03-03 01:35:41 +0000831 VG_(needs_var_info)();
sewardjaf44c822007-11-25 14:01:38 +0000832
833 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
834
835 drd_clientreq_init();
836
837 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +0000838
bart72b751c2008-03-01 13:44:24 +0000839 clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +0000840}
841
842
843VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
844
845
846/*
847 * Local variables:
848 * c-basic-offset: 3
849 * End:
850 */