blob: 2f929e2f660d4fc73e8e68ae19d72a8f59398287 [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"
33#include "drd_segment.h"
sewardj85642922008-01-14 11:54:56 +000034#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000035#include "drd_suppression.h"
36#include "drd_thread.h"
37#include "drd_track.h"
38#include "drd_vc.h"
sewardj721ad7b2007-11-30 08:30:29 +000039#include "priv_drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000040#include "pub_drd_bitmap.h"
sewardjaf44c822007-11-25 14:01:38 +000041#include "pub_tool_basics.h"
42#include "pub_tool_debuginfo.h" // VG_(describe_IP)()
43#include "pub_tool_libcassert.h" // tl_assert()
44#include "pub_tool_libcbase.h" // VG_(strcmp)
45#include "pub_tool_libcprint.h" // VG_(printf)
sewardj85642922008-01-14 11:54:56 +000046#include "pub_tool_vki.h" // Must be included before pub_tool_libcproc
sewardjaf44c822007-11-25 14:01:38 +000047#include "pub_tool_libcproc.h"
48#include "pub_tool_machine.h"
49#include "pub_tool_options.h" // command line options
bart72b751c2008-03-01 13:44:24 +000050#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
sewardjaf44c822007-11-25 14:01:38 +000051#include "pub_tool_tooliface.h"
52
53
sewardjaf44c822007-11-25 14:01:38 +000054// Function declarations.
55
barteb8b8c82008-02-26 19:11:20 +000056static void instrument_memory_bus_event(IRSB* const bb,
57 const IRMBusEvent event);
sewardjaf44c822007-11-25 14:01:38 +000058static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
59static void drd_set_running_tid(const ThreadId tid);
barteb8b8c82008-02-26 19:11:20 +000060static void evh__bus_lock(void);
61static void evh__bus_unlock(void);
sewardjaf44c822007-11-25 14:01:38 +000062
63
64
65// Local variables.
66
67static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000068static Bool drd_trace_fork_join = False;
sewardj85642922008-01-14 11:54:56 +000069static Bool drd_trace_mem = False;
sewardjaf44c822007-11-25 14:01:38 +000070static Addr drd_trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000071
72
73//
74// Implement the needs_command_line_options for drd.
75//
76
77static Bool drd_process_cmd_line_option(Char* arg)
78{
sewardj85642922008-01-14 11:54:56 +000079 Bool trace_barrier = False;
bart72b751c2008-03-01 13:44:24 +000080 Bool trace_clientobj = False;
sewardjaf44c822007-11-25 14:01:38 +000081 Bool trace_cond = False;
bartecbf1662008-02-24 18:46:05 +000082 Bool trace_csw = False;
83 Bool trace_danger_set = False;
sewardjaf44c822007-11-25 14:01:38 +000084 Bool trace_mutex = False;
85 Bool trace_segment = False;
bart28230a32008-02-29 17:27:03 +000086 Bool trace_semaphore = False;
sewardjaf44c822007-11-25 14:01:38 +000087 Bool trace_suppression = False;
88 Char* trace_address = 0;
89
90 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
sewardj85642922008-01-14 11:54:56 +000091 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
bart72b751c2008-03-01 13:44:24 +000092 else VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj)
sewardjaf44c822007-11-25 14:01:38 +000093 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
bartecbf1662008-02-24 18:46:05 +000094 else VG_BOOL_CLO(arg, "--trace-csw", trace_csw)
95 else VG_BOOL_CLO(arg, "--trace-danger-set", trace_danger_set)
sewardjaf44c822007-11-25 14:01:38 +000096 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
97 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
98 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
99 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
bart28230a32008-02-29 17:27:03 +0000100 else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
sewardjaf44c822007-11-25 14:01:38 +0000101 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
102 else VG_STR_CLO (arg, "--trace-address", trace_address)
103 else
104 return False;
105
106 if (trace_address)
sewardjc0be9252008-02-11 11:00:51 +0000107 {
sewardjaf44c822007-11-25 14:01:38 +0000108 drd_trace_address = VG_(strtoll16)(trace_address, 0);
sewardjc0be9252008-02-11 11:00:51 +0000109 }
sewardj85642922008-01-14 11:54:56 +0000110 if (trace_barrier)
111 barrier_set_trace(trace_barrier);
bart72b751c2008-03-01 13:44:24 +0000112 if (trace_clientobj)
113 clientobj_set_trace(trace_clientobj);
sewardjaf44c822007-11-25 14:01:38 +0000114 if (trace_cond)
115 cond_set_trace(trace_cond);
bartecbf1662008-02-24 18:46:05 +0000116 if (trace_csw)
117 thread_trace_context_switches(trace_csw);
118 if (trace_danger_set)
119 thread_trace_danger_set(trace_danger_set);
sewardjaf44c822007-11-25 14:01:38 +0000120 if (trace_mutex)
121 mutex_set_trace(trace_mutex);
122 if (trace_segment)
123 sg_set_trace(trace_segment);
bart28230a32008-02-29 17:27:03 +0000124 if (trace_semaphore)
125 semaphore_set_trace(trace_semaphore);
sewardjaf44c822007-11-25 14:01:38 +0000126 if (trace_suppression)
127 suppression_set_trace(trace_suppression);
128
129 return True;
130}
131
132static void drd_print_usage(void)
133{
134 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
135 "\n"
136 " --trace-fork-join=no|yes Trace all thread creation and join"
137 " activity\n"
138 " --trace-mutex=no|yes Trace all mutex activity\n"
139 " --trace-segment=no|yes Trace segment actions\n"
140 );
141}
142
143static void drd_print_debug_usage(void)
144{
145}
146
147
148//
149// Implements the thread-related core callbacks.
150//
151
152static
153VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
154{
155 Segment* sg;
156
bart5e85d262008-03-01 10:49:37 +0000157 tl_assert(thread_get_running_tid()
158 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
sewardjaf44c822007-11-25 14:01:38 +0000159
160#if 1
161 if (drd_trace_mem || (addr == drd_trace_address))
162 {
163 VG_(message)(Vg_UserMsg, "load 0x%lx size %ld %s (vg %d / drd %d)",
164 addr,
165 size,
166 thread_get_name(thread_get_running_tid()),
167 VG_(get_running_tid)(),
168 thread_get_running_tid());
sewardj85642922008-01-14 11:54:56 +0000169 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
170 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000171 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
172 == VG_(get_running_tid)());
173 }
174#endif
175 sg = thread_get_segment(thread_get_running_tid());
176 bm_access_range(sg->bm, addr, size, eLoad);
177 if (thread_conflicting_access(addr, size, eLoad))
178 {
179 DataRaceErrInfo drei;
180 drei.tid = VG_(get_running_tid)();
181 drei.addr = addr;
182 drei.size = size;
183 drei.access_type = eLoad;
184 VG_(maybe_record_error)(VG_(get_running_tid)(),
185 DataRaceErr,
186 VG_(get_IP)(VG_(get_running_tid)()),
187 "Conflicting accesses",
188 &drei);
189 }
190}
191
192static
193VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
194{
195 Segment* sg;
196
bart5e85d262008-03-01 10:49:37 +0000197 tl_assert(thread_get_running_tid()
198 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
sewardjaf44c822007-11-25 14:01:38 +0000199
200#if 1
201 if (drd_trace_mem || (addr == drd_trace_address))
202 {
203 VG_(message)(Vg_UserMsg, "store 0x%lx size %ld %s (vg %d / drd %d / off %d)",
204 addr,
205 size,
206 thread_get_name(thread_get_running_tid()),
207 VG_(get_running_tid)(),
208 thread_get_running_tid(),
209 addr - thread_get_stack_min(thread_get_running_tid()));
sewardj85642922008-01-14 11:54:56 +0000210 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
211 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000212 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
213 == VG_(get_running_tid)());
214 }
215#endif
216 sg = thread_get_segment(thread_get_running_tid());
217 bm_access_range(sg->bm, addr, size, eStore);
218 if (thread_conflicting_access(addr, size, eStore))
219 {
220 DataRaceErrInfo drei;
221 drei.tid = VG_(get_running_tid)();
222 drei.addr = addr;
223 drei.size = size;
224 drei.access_type = eStore;
225 VG_(maybe_record_error)(VG_(get_running_tid)(),
226 DataRaceErr,
227 VG_(get_IP)(VG_(get_running_tid)()),
228 "Conflicting accesses",
229 &drei);
230 }
231}
232
233static void drd_pre_mem_read(const CorePart part,
234 const ThreadId tid,
235 Char* const s,
236 const Addr a,
237 const SizeT size)
238{
sewardj8b09d4f2007-12-04 21:27:18 +0000239 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000240 {
241 drd_trace_load(a, size);
242 }
243}
244
bart5e85d262008-03-01 10:49:37 +0000245static void drd_pre_mem_read_asciiz(const CorePart part,
246 const ThreadId tid,
247 Char* const s,
248 const Addr a)
249{
250 const char* p = (void*)a;
251 SizeT size = 0;
252
253 /* Note: the expression '*p' reads client memory and may crash if the */
254 /* client provided an invalid pointer ! */
255 while (*p)
256 {
257 p++;
258 size++;
259 }
260 // To do: find out what a reasonable upper limit on 'size' is.
261 tl_assert(size < 4096);
262 if (size > 0)
263 {
264 drd_trace_load(a, size);
265 }
266}
267
sewardjaf44c822007-11-25 14:01:38 +0000268static void drd_post_mem_write(const CorePart part,
269 const ThreadId tid,
270 const Addr a,
271 const SizeT size)
272{
bart5e85d262008-03-01 10:49:37 +0000273 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardj8b09d4f2007-12-04 21:27:18 +0000274 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000275 {
276 drd_trace_store(a, size);
277 }
278}
279
bart5e85d262008-03-01 10:49:37 +0000280static void drd_start_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000281{
bart5e85d262008-03-01 10:49:37 +0000282 const Addr a2 = a1 + len;
283
284 tl_assert(a1 < a2);
285
sewardj8b09d4f2007-12-04 21:27:18 +0000286 thread_set_vg_running_tid(VG_(get_running_tid)());
287
bart5e85d262008-03-01 10:49:37 +0000288 if (a1 <= drd_trace_address && drd_trace_address < a2)
sewardjaf44c822007-11-25 14:01:38 +0000289 {
290 VG_(message)(Vg_UserMsg, "start 0x%lx size %ld %s (tracing 0x%lx)",
291 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
292 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000293 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
294 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000295 }
296}
297
bart5e85d262008-03-01 10:49:37 +0000298static void drd_stop_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000299{
bart5e85d262008-03-01 10:49:37 +0000300 const Addr a2 = a1 + len;
301
302 tl_assert(a1 < a2);
303
304 if (a1 <= drd_trace_address && drd_trace_address < a2)
sewardjaf44c822007-11-25 14:01:38 +0000305 {
306 VG_(message)(Vg_UserMsg, "end 0x%lx size %ld %s (tracing 0x%lx)",
307 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
308 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000309 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
310 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000311 }
312 thread_stop_using_mem(a1, a2);
bart72b751c2008-03-01 13:44:24 +0000313 clientobj_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000314 drd_suppression_stop_using_mem(a1, a2);
315}
316
bart5e85d262008-03-01 10:49:37 +0000317static
318void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
319 const Bool rr, const Bool ww, const Bool xx)
320{
321 drd_start_using_mem(a, len);
322}
323
sewardjaf44c822007-11-25 14:01:38 +0000324/* Called by the core when the stack of a thread grows, to indicate that */
325/* the addresses in range [ a, a + len [ may now be used by the client. */
326/* Assumption: stacks grow downward. */
327static void drd_start_using_mem_stack(const Addr a, const SizeT len)
328{
329 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
bart5e85d262008-03-01 10:49:37 +0000330 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000331}
332
333/* Called by the core when the stack of a thread shrinks, to indicate that */
334/* the addresses [ a, a + len [ are no longer accessible for the client. */
335/* Assumption: stacks grow downward. */
336static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
337{
sewardj8b09d4f2007-12-04 21:27:18 +0000338 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardjaf44c822007-11-25 14:01:38 +0000339 thread_set_stack_min(thread_get_running_tid(),
340 a + len - VG_STACK_REDZONE_SZB);
bart5e85d262008-03-01 10:49:37 +0000341 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000342}
343
bart5e85d262008-03-01 10:49:37 +0000344static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000345{
bart5e85d262008-03-01 10:49:37 +0000346 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000347}
348
bart5e85d262008-03-01 10:49:37 +0000349static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000350{
bart5e85d262008-03-01 10:49:37 +0000351 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000352}
353
354static
355void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
356{
357 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
358 tl_assert(created != VG_INVALID_THREADID);
359 thread_pre_create(drd_creator, created);
sewardjaf44c822007-11-25 14:01:38 +0000360 if (IsValidDrdThreadId(drd_creator))
361 {
362 thread_new_segment(drd_creator);
363 }
364 if (drd_trace_fork_join)
365 {
366 VG_(message)(Vg_DebugMsg,
367 "drd_pre_thread_create creator = %d/%d, created = %d",
368 creator, drd_creator, created);
369 }
370}
371
372/* Called by Valgrind's core before any loads or stores are performed on */
373/* the context of thread "created". At startup, this function is called */
374/* with arguments (0,1). */
375static
376void drd_post_thread_create(const ThreadId created)
377{
378 const DrdThreadId drd_created = thread_post_create(created);
379 tl_assert(created != VG_INVALID_THREADID);
380 if (drd_trace_fork_join)
381 {
382 VG_(message)(Vg_DebugMsg,
383 "drd_post_thread_create created = %d/%d",
384 created, drd_created);
385 }
386}
387
388/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
389/* after thread drd_joiner joined thread drd_joinee. */
390void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
391{
392 tl_assert(IsValidDrdThreadId(drd_joiner));
393 tl_assert(IsValidDrdThreadId(drd_joinee));
394 thread_new_segment(drd_joinee);
395 thread_combine_vc(drd_joiner, drd_joinee);
396 thread_new_segment(drd_joiner);
397
398 if (drd_trace_fork_join)
399 {
400 char msg[256];
401 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
402 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
403 VG_(snprintf)(msg, sizeof(msg),
404 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
405 joiner, drd_joiner, joinee, drd_joinee);
406 if (joiner)
407 {
408 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
409 ", new vc: ");
410 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
411 thread_get_vc(drd_joiner));
412 }
413 VG_(message)(Vg_DebugMsg, msg);
414 }
415
416 thread_delete(drd_joinee);
417 mutex_thread_delete(drd_joinee);
sewardj85642922008-01-14 11:54:56 +0000418 cond_thread_delete(drd_joinee);
419 semaphore_thread_delete(drd_joinee);
420 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000421}
422
423/* Called after a thread has performed its last memory access. */
424static void drd_thread_finished(ThreadId tid)
425{
sewardj85642922008-01-14 11:54:56 +0000426 DrdThreadId drd_tid;
427
428 drd_set_running_tid(tid);
429
430 drd_tid = VgThreadIdToDrdThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000431 if (drd_trace_fork_join)
432 {
433 VG_(message)(Vg_DebugMsg,
434 "drd_thread_finished tid = %d/%d%s",
435 tid,
436 drd_tid,
437 thread_get_joinable(drd_tid)
438 ? ""
439 : " (which is a detached thread)");
440
441 }
442 thread_finished(drd_tid);
443}
444
sewardj347eeba2008-01-21 14:19:07 +0000445void drd_pre_mutex_init(const Addr mutex, const SizeT size,
446 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000447{
sewardj721ad7b2007-11-30 08:30:29 +0000448 mutex_init(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000449}
450
sewardj347eeba2008-01-21 14:19:07 +0000451void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000452{
sewardj347eeba2008-01-21 14:19:07 +0000453 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000454}
455
456void drd_pre_mutex_lock(const DrdThreadId drd_tid,
457 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000458 const SizeT size,
459 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000460{
bart8bba1f72008-02-27 16:13:05 +0000461 mutex_pre_lock(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000462}
463
464void drd_post_mutex_lock(const DrdThreadId drd_tid,
465 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000466 const SizeT size,
bart3b1ee452008-02-29 19:28:15 +0000467 const MutexT mutex_type,
468 const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000469{
bart3b1ee452008-02-29 19:28:15 +0000470 mutex_post_lock(mutex, size, mutex_type, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000471}
472
sewardj721ad7b2007-11-30 08:30:29 +0000473void drd_pre_mutex_unlock(const DrdThreadId drd_tid,
474 const Addr mutex,
475 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000476{
sewardj721ad7b2007-11-30 08:30:29 +0000477 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000478}
479
bart72b751c2008-03-01 13:44:24 +0000480void drd_pre_cond_init(Addr cond, SizeT s)
sewardjaf44c822007-11-25 14:01:38 +0000481{
bart72b751c2008-03-01 13:44:24 +0000482 cond_pre_init(cond, s);
sewardjaf44c822007-11-25 14:01:38 +0000483}
484
bart72b751c2008-03-01 13:44:24 +0000485void drd_post_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000486{
bart72b751c2008-03-01 13:44:24 +0000487 cond_post_destroy(cond);
sewardjaf44c822007-11-25 14:01:38 +0000488}
489
sewardj85642922008-01-14 11:54:56 +0000490void drd_semaphore_init(const Addr semaphore, const SizeT size,
491 const Word pshared, const Word value)
492{
493 semaphore_init(semaphore, size, pshared, value);
494}
495
496void drd_semaphore_destroy(const Addr semaphore)
497{
bart72b751c2008-03-01 13:44:24 +0000498 semaphore_destroy(semaphore);
sewardj85642922008-01-14 11:54:56 +0000499}
500
bart28230a32008-02-29 17:27:03 +0000501void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
502 const SizeT size)
sewardj85642922008-01-14 11:54:56 +0000503{
bart28230a32008-02-29 17:27:03 +0000504 semaphore_pre_wait(semaphore, size);
505}
506
507void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
508 const Bool waited)
509{
510 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000511}
512
513void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
514 const SizeT size)
515{
516 semaphore_pre_post(tid, semaphore, size);
517}
518
519void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
sewardje3b57aa2008-01-18 07:42:01 +0000520 const SizeT size, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000521{
sewardje3b57aa2008-01-18 07:42:01 +0000522 semaphore_post_post(tid, semaphore, size, waited);
sewardj85642922008-01-14 11:54:56 +0000523}
524
525
526void drd_barrier_init(const Addr barrier, const SizeT size, const Word count)
527{
528 barrier_init(barrier, size, count);
529}
530
531void drd_barrier_destroy(const Addr barrier)
532{
bart72b751c2008-03-01 13:44:24 +0000533 barrier_destroy(barrier);
sewardj85642922008-01-14 11:54:56 +0000534}
535
536void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
537{
538 barrier_pre_wait(tid, barrier);
539}
540
541void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
542 const Bool waited)
543{
544 barrier_post_wait(tid, barrier, waited);
545}
546
sewardjaf44c822007-11-25 14:01:38 +0000547
548//
549// Implementation of the tool interface.
550//
551
552static
553void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000554{
555# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
556 /* fine */
557# else
sewardj8b09d4f2007-12-04 21:27:18 +0000558 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000559# endif
560}
sewardjaf44c822007-11-25 14:01:38 +0000561
562static
563IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000564 IRSB* const bb_in,
565 VexGuestLayout* const layout,
566 VexGuestExtents* const vge,
567 IRType const gWordTy,
568 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000569{
570 IRDirty* di;
571 Int i;
572 IRSB* bb;
573 IRExpr** argv;
574 IRExpr* addr_expr;
575 IRExpr* size_expr;
576 Bool instrument = True;
577
578 /* Set up BB */
579 bb = emptyIRSB();
580 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
581 bb->next = deepCopyIRExpr(bb_in->next);
582 bb->jumpkind = bb_in->jumpkind;
583
584 for (i = 0; i < bb_in->stmts_used; i++)
585 {
586 IRStmt* const st = bb_in->stmts[i];
barteb8b8c82008-02-26 19:11:20 +0000587 tl_assert(st);
588 if (st->tag == Ist_NoOp)
sewardjaf44c822007-11-25 14:01:38 +0000589 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
barteb8b8c82008-02-26 19:11:20 +0000597 case Ist_MBE:
598 instrument_memory_bus_event(bb, st->Ist.MBE.event);
599 addStmtToIRSB(bb, st);
600 break;
601
sewardjaf44c822007-11-25 14:01:38 +0000602 case Ist_Store:
603 if (instrument)
604 {
605 addr_expr = st->Ist.Store.addr;
606 size_expr = mkIRExpr_HWord(
607 sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Store.data)));
608 argv = mkIRExprVec_2(addr_expr, size_expr);
609 di = unsafeIRDirty_0_N(/*regparms*/2,
610 "drd_trace_store",
611 VG_(fnptr_to_fnentry)(drd_trace_store),
612 argv);
613 addStmtToIRSB(bb, IRStmt_Dirty(di));
614 }
615 addStmtToIRSB(bb, st);
616 break;
617
618 case Ist_WrTmp:
619 if (instrument)
620 {
621 const IRExpr* const data = st->Ist.WrTmp.data;
622 if (data->tag == Iex_Load)
623 {
624 addr_expr = data->Iex.Load.addr;
625 size_expr = mkIRExpr_HWord(sizeofIRType(data->Iex.Load.ty));
626 argv = mkIRExprVec_2(addr_expr, size_expr);
627 di = unsafeIRDirty_0_N(/*regparms*/2,
628 "drd_trace_load",
629 VG_(fnptr_to_fnentry)(drd_trace_load),
630 argv);
631 addStmtToIRSB(bb, IRStmt_Dirty(di));
632 }
633 }
634 addStmtToIRSB(bb, st);
635 break;
636
637 case Ist_Dirty:
638 if (instrument)
639 {
640 IRDirty* d = st->Ist.Dirty.details;
641 IREffect const mFx = d->mFx;
642 switch (mFx) {
643 case Ifx_None:
644 break;
645 case Ifx_Read:
646 case Ifx_Write:
647 case Ifx_Modify:
648 tl_assert(d->mAddr);
649 tl_assert(d->mSize > 0);
650 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
651 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
652 di = unsafeIRDirty_0_N(
653 /*regparms*/2,
654 "drd_trace_load",
655 VG_(fnptr_to_fnentry)(drd_trace_load),
656 argv);
657 addStmtToIRSB(bb, IRStmt_Dirty(di));
658 }
659 if (mFx == Ifx_Write || mFx == Ifx_Modify) {
660 di = unsafeIRDirty_0_N(
661 /*regparms*/2,
662 "drd_trace_store",
663 VG_(fnptr_to_fnentry)(drd_trace_store),
664 argv);
665 addStmtToIRSB(bb, IRStmt_Dirty(di));
666 }
667 break;
668 default:
669 tl_assert(0);
670 }
671 }
672 addStmtToIRSB(bb, st);
673 break;
674
675 default:
676 addStmtToIRSB(bb, st);
677 break;
678 }
679 }
680
681 return bb;
682}
683
barteb8b8c82008-02-26 19:11:20 +0000684/* Based on the function with the same name in Helgrind's hg_main.c */
685static void instrument_memory_bus_event(IRSB* const bb,
bartbbb67992008-03-01 07:41:17 +0000686 const IRMBusEvent event)
barteb8b8c82008-02-26 19:11:20 +0000687{
688 switch (event)
689 {
690 case Imbe_Fence:
691 break; /* not interesting */
692 case Imbe_BusLock:
693 addStmtToIRSB(bb,
694 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_lock",
695 VG_(fnptr_to_fnentry)(&evh__bus_lock), mkIRExprVec_0())
696 ));
697 break;
698 case Imbe_BusUnlock:
699 addStmtToIRSB(bb,
700 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_unlock",
701 VG_(fnptr_to_fnentry)(&evh__bus_unlock), mkIRExprVec_0())
702 ));
703 break;
704 default:
705 tl_assert(0);
706 }
707}
708
709/** Locking the memory bus is a way to serialize store operations.
710 * What the lwarx / stwcx instructions do on PowerPC is to detect whether
711 * any other CPU has invalidated the cache line in which the location
712 * specified by lwarx resides has been invalidated at the time the stwcx
713 * instruction is executed.
714 */
715static void evh__bus_lock(void)
716{
717 /* To do: implement this function. */
718}
719
720static void evh__bus_unlock(void)
721{
722 /* To do: implement this function. */
723}
724
sewardj8b09d4f2007-12-04 21:27:18 +0000725static void drd_set_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000726{
sewardj8b09d4f2007-12-04 21:27:18 +0000727 static ThreadId s_last_vg_tid = VG_INVALID_THREADID;
728 if (vg_tid != s_last_vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000729 {
sewardj8b09d4f2007-12-04 21:27:18 +0000730 const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
sewardjaf44c822007-11-25 14:01:38 +0000731 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000732 s_last_vg_tid = vg_tid;
sewardjaf44c822007-11-25 14:01:38 +0000733 if (drd_trace_fork_join)
734 {
735 VG_(message)(Vg_DebugMsg,
736 "drd_track_thread_run tid = %d / drd tid %d",
sewardj8b09d4f2007-12-04 21:27:18 +0000737 vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000738 }
sewardj8b09d4f2007-12-04 21:27:18 +0000739 thread_set_running_tid(vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000740 }
741}
742
743static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
744{
745 drd_set_running_tid(tid);
746}
747
748static
749void drd_fini(Int exitcode)
750{
751 // thread_print_all();
sewardjaf44c822007-11-25 14:01:38 +0000752 if (VG_(clo_verbosity) > 1 || drd_print_stats)
753 {
754 VG_(message)(Vg_DebugMsg,
755 " thread: %lld context switches"
756 " / %lld updates of the danger set",
757 thread_get_context_switch_count(),
758 thread_get_update_danger_set_count());
sewardjaf44c822007-11-25 14:01:38 +0000759 VG_(message)(Vg_DebugMsg,
760 " segments: %lld total, %lld max, %lld discard points",
761 sg_get_segments_created_count(),
762 sg_get_max_segments_alive_count(),
763 thread_get_discard_ordered_segments_count());
764 VG_(message)(Vg_DebugMsg,
765 " bitmaps: %lld / %lld bitmaps were allocated"
766 " and %lld / %lld for danger set updates",
767 bm_get_bitmap_creation_count(),
768 bm_get_bitmap2_creation_count(),
769 thread_get_danger_set_bitmap_creation_count(),
770 thread_get_danger_set_bitmap2_creation_count());
771 VG_(message)(Vg_DebugMsg,
772 " mutex: %lld non-recursive lock/unlock events",
773 get_mutex_lock_count());
774 drd_print_malloc_stats();
775 }
776}
777
sewardjaf44c822007-11-25 14:01:38 +0000778static
779void drd_pre_clo_init(void)
780{
781 // Basic tool stuff.
782
783 VG_(details_name) ("exp-drd");
784 VG_(details_version) (NULL);
785 VG_(details_description) ("a data race detector");
sewardj85642922008-01-14 11:54:56 +0000786 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
sewardjaf44c822007-11-25 14:01:38 +0000787 " by Bart Van Assche.");
788 VG_(details_bug_reports_to) (VG_BUGS_TO);
789
790 VG_(basic_tool_funcs) (drd_post_clo_init,
791 drd_instrument,
792 drd_fini);
793
794 // Command line stuff.
795 VG_(needs_command_line_options)(drd_process_cmd_line_option,
796 drd_print_usage,
797 drd_print_debug_usage);
798
bart5e85d262008-03-01 10:49:37 +0000799 // Error handling.
sewardjaf44c822007-11-25 14:01:38 +0000800 drd_register_error_handlers();
801
802 // Core event tracking.
803 VG_(track_pre_mem_read) (drd_pre_mem_read);
bart5e85d262008-03-01 10:49:37 +0000804 VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz);
sewardjaf44c822007-11-25 14:01:38 +0000805 VG_(track_post_mem_write) (drd_post_mem_write);
bart5e85d262008-03-01 10:49:37 +0000806 VG_(track_new_mem_brk) (drd_start_using_mem);
807 VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms);
sewardjaf44c822007-11-25 14:01:38 +0000808 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
bart5e85d262008-03-01 10:49:37 +0000809 VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
810 VG_(track_new_mem_startup) (drd_start_using_mem_w_perms);
811 VG_(track_die_mem_brk) (drd_stop_using_mem);
812 VG_(track_die_mem_munmap) (drd_stop_using_mem);
sewardjaf44c822007-11-25 14:01:38 +0000813 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
bart5e85d262008-03-01 10:49:37 +0000814 VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
sewardjaf44c822007-11-25 14:01:38 +0000815 VG_(track_start_client_code) (drd_start_client_code);
816 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
817 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
818 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
819
820 // Other stuff.
821 VG_(needs_data_syms)();
822
823 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
824
825 drd_clientreq_init();
826
827 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +0000828
bart72b751c2008-03-01 13:44:24 +0000829 clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +0000830}
831
832
833VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
834
835
836/*
837 * Local variables:
838 * c-basic-offset: 3
839 * End:
840 */