blob: 8c7246f6573c6c572e75755c0333a69d10cb166f [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
bartceded212008-03-26 17:39:52 +000051#include "pub_tool_replacemalloc.h"
bart72b751c2008-03-01 13:44:24 +000052#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
sewardjaf44c822007-11-25 14:01:38 +000053#include "pub_tool_tooliface.h"
bartceded212008-03-26 17:39:52 +000054#include "pub_tool_replacemalloc.h"
sewardjaf44c822007-11-25 14:01:38 +000055
56
sewardjaf44c822007-11-25 14:01:38 +000057// Function declarations.
58
59static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
sewardjaf44c822007-11-25 14:01:38 +000060
61
62// Local variables.
63
64static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000065static Bool drd_trace_fork_join = False;
sewardj85642922008-01-14 11:54:56 +000066static Bool drd_trace_mem = False;
sewardjaf44c822007-11-25 14:01:38 +000067static Addr drd_trace_address = 0;
bart95761b52008-03-29 08:34:03 +000068static Bool s_drd_var_info = False;
sewardjaf44c822007-11-25 14:01:38 +000069
70
71//
72// Implement the needs_command_line_options for drd.
73//
74
75static Bool drd_process_cmd_line_option(Char* arg)
76{
barta9c37392008-03-22 09:38:48 +000077 int segment_merging = -1;
78 int show_confl_seg = -1;
79 int trace_barrier = -1;
80 int trace_clientobj = -1;
81 int trace_cond = -1;
82 int trace_csw = -1;
83 int trace_danger_set = -1;
84 int trace_mutex = -1;
85 int trace_rwlock = -1;
86 int trace_segment = -1;
87 int trace_semaphore = -1;
88 int trace_suppression = -1;
89 Char* trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000090
bart3772a982008-03-15 08:11:03 +000091 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
barta9c37392008-03-22 09:38:48 +000092 else VG_BOOL_CLO(arg, "--segment-merging", segment_merging)
bart16d76e52008-03-18 17:08:08 +000093 else VG_BOOL_CLO(arg, "--show-confl-seg", show_confl_seg)
bart3772a982008-03-15 08:11:03 +000094 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
95 else VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj)
96 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
97 else VG_BOOL_CLO(arg, "--trace-csw", trace_csw)
98 else VG_BOOL_CLO(arg, "--trace-danger-set", trace_danger_set)
99 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
100 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
101 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
102 else VG_BOOL_CLO(arg, "--trace-rwlock", trace_rwlock)
103 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
104 else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
105 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
bart95761b52008-03-29 08:34:03 +0000106 else VG_BOOL_CLO(arg, "--var-info", s_drd_var_info)
bart3772a982008-03-15 08:11:03 +0000107 else VG_STR_CLO (arg, "--trace-address", trace_address)
108 else
bartceded212008-03-26 17:39:52 +0000109 return VG_(replacement_malloc_process_cmd_line_option)(arg);
sewardjaf44c822007-11-25 14:01:38 +0000110
barta9c37392008-03-22 09:38:48 +0000111 if (segment_merging != -1)
112 thread_set_segment_merging(segment_merging);
113 if (show_confl_seg != -1)
bart16d76e52008-03-18 17:08:08 +0000114 set_show_conflicting_segments(show_confl_seg);
bart3772a982008-03-15 08:11:03 +0000115 if (trace_address)
116 {
117 drd_trace_address = VG_(strtoll16)(trace_address, 0);
118 }
barta9c37392008-03-22 09:38:48 +0000119 if (trace_barrier != -1)
bart3772a982008-03-15 08:11:03 +0000120 barrier_set_trace(trace_barrier);
barta9c37392008-03-22 09:38:48 +0000121 if (trace_clientobj != -1)
bart3772a982008-03-15 08:11:03 +0000122 clientobj_set_trace(trace_clientobj);
barta9c37392008-03-22 09:38:48 +0000123 if (trace_cond != -1)
bart3772a982008-03-15 08:11:03 +0000124 cond_set_trace(trace_cond);
barta9c37392008-03-22 09:38:48 +0000125 if (trace_csw != -1)
bart3772a982008-03-15 08:11:03 +0000126 thread_trace_context_switches(trace_csw);
barta9c37392008-03-22 09:38:48 +0000127 if (trace_danger_set != -1)
bart3772a982008-03-15 08:11:03 +0000128 thread_trace_danger_set(trace_danger_set);
barta9c37392008-03-22 09:38:48 +0000129 if (trace_mutex != -1)
bart3772a982008-03-15 08:11:03 +0000130 mutex_set_trace(trace_mutex);
barta9c37392008-03-22 09:38:48 +0000131 if (trace_rwlock != -1)
bart3772a982008-03-15 08:11:03 +0000132 rwlock_set_trace(trace_rwlock);
barta9c37392008-03-22 09:38:48 +0000133 if (trace_segment != -1)
bart3772a982008-03-15 08:11:03 +0000134 sg_set_trace(trace_segment);
barta9c37392008-03-22 09:38:48 +0000135 if (trace_semaphore != -1)
bart3772a982008-03-15 08:11:03 +0000136 semaphore_set_trace(trace_semaphore);
barta9c37392008-03-22 09:38:48 +0000137 if (trace_suppression != -1)
bart3772a982008-03-15 08:11:03 +0000138 suppression_set_trace(trace_suppression);
sewardjaf44c822007-11-25 14:01:38 +0000139
bart3772a982008-03-15 08:11:03 +0000140 return True;
sewardjaf44c822007-11-25 14:01:38 +0000141}
142
143static void drd_print_usage(void)
144{
bart3772a982008-03-15 08:11:03 +0000145 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
146 "\n"
147 " --trace-fork-join=no|yes Trace all thread creation and join"
148 " activity\n"
149 " --trace-mutex=no|yes Trace all mutex activity\n"
150 " --trace-segment=no|yes Trace segment actions\n"
151 );
sewardjaf44c822007-11-25 14:01:38 +0000152}
153
154static void drd_print_debug_usage(void)
155{
156}
157
158
159//
160// Implements the thread-related core callbacks.
161//
162
barta79df6e2008-03-14 17:07:51 +0000163static void drd_trace_mem_access(const Addr addr, const SizeT size,
164 const BmAccessTypeT access_type)
165{
bart3772a982008-03-15 08:11:03 +0000166 char vc[80];
167 vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
168 VG_(message)(Vg_UserMsg,
bart354009c2008-03-16 10:42:33 +0000169 "%s 0x%lx size %ld (vg %d / drd %d / vc %s)",
bartd5765912008-03-16 08:40:55 +0000170 access_type == eLoad
171 ? "load "
172 : access_type == eStore
173 ? "store"
174 : access_type == eStart
175 ? "start"
176 : access_type == eEnd
bartd43f8d32008-03-16 17:29:20 +0000177 ? "end "
bartd5765912008-03-16 08:40:55 +0000178 : "????",
bart3772a982008-03-15 08:11:03 +0000179 addr,
180 size,
bart3772a982008-03-15 08:11:03 +0000181 VG_(get_running_tid)(),
182 thread_get_running_tid(),
183 vc);
184 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
185 VG_(clo_backtrace_size));
186 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
187 == VG_(get_running_tid)());
barta79df6e2008-03-14 17:07:51 +0000188}
189
190static void drd_report_race(const Addr addr, const SizeT size,
191 const BmAccessTypeT access_type)
192{
bart49c3a112008-03-15 10:28:36 +0000193 DataRaceErrInfo drei;
194
bart7a282142008-03-15 08:34:23 +0000195 if (drd_is_suppressed(addr, addr + size))
196 return;
197
bart354009c2008-03-16 10:42:33 +0000198 drei.tid = thread_get_running_tid();
bart3772a982008-03-15 08:11:03 +0000199 drei.addr = addr;
200 drei.size = size;
201 drei.access_type = access_type;
202 VG_(maybe_record_error)(VG_(get_running_tid)(),
203 DataRaceErr,
204 VG_(get_IP)(VG_(get_running_tid)()),
205 "Conflicting accesses",
206 &drei);
barta79df6e2008-03-14 17:07:51 +0000207}
208
209static VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
sewardjaf44c822007-11-25 14:01:38 +0000210{
bart3772a982008-03-15 08:11:03 +0000211 Segment* sg;
sewardjaf44c822007-11-25 14:01:38 +0000212
bartf00a85b2008-03-13 18:49:23 +0000213#if 0
bart3772a982008-03-15 08:11:03 +0000214 /* The assert below has been commented out because of performance reasons.*/
215 tl_assert(thread_get_running_tid()
216 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bartf00a85b2008-03-13 18:49:23 +0000217#endif
sewardjaf44c822007-11-25 14:01:38 +0000218
bart3772a982008-03-15 08:11:03 +0000219 if (! running_thread_is_recording())
220 return;
bart0268dfa2008-03-11 20:10:21 +0000221
bart3772a982008-03-15 08:11:03 +0000222 if (drd_trace_mem || (addr == drd_trace_address))
223 {
224 drd_trace_mem_access(addr, size, eLoad);
225 }
226 sg = running_thread_get_segment();
227 bm_access_range_load(sg->bm, addr, addr + size);
bart7a282142008-03-15 08:34:23 +0000228 if (bm_load_has_conflict_with(thread_get_danger_set(), addr, addr + size))
bart3772a982008-03-15 08:11:03 +0000229 {
230 drd_report_race(addr, size, eLoad);
231 }
barta79df6e2008-03-14 17:07:51 +0000232}
233
234static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
235{
bart3772a982008-03-15 08:11:03 +0000236 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000237
bart3772a982008-03-15 08:11:03 +0000238 if (! running_thread_is_recording())
239 return;
barta79df6e2008-03-14 17:07:51 +0000240
bart3772a982008-03-15 08:11:03 +0000241 if (drd_trace_mem || (addr == drd_trace_address))
242 {
243 drd_trace_mem_access(addr, 1, eLoad);
244 }
245 sg = running_thread_get_segment();
246 bm_access_load_1(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000247 if (bm_load_1_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000248 {
249 drd_report_race(addr, 1, eLoad);
250 }
barta79df6e2008-03-14 17:07:51 +0000251}
252
253static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
254{
bart3772a982008-03-15 08:11:03 +0000255 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000256
bart3772a982008-03-15 08:11:03 +0000257 if (! running_thread_is_recording())
258 return;
barta79df6e2008-03-14 17:07:51 +0000259
bart3772a982008-03-15 08:11:03 +0000260 if (drd_trace_mem || (addr == drd_trace_address))
261 {
262 drd_trace_mem_access(addr, 2, eLoad);
263 }
264 sg = running_thread_get_segment();
265 bm_access_load_2(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000266 if (bm_load_2_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000267 {
268 drd_report_race(addr, 2, eLoad);
269 }
barta79df6e2008-03-14 17:07:51 +0000270}
271
272static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
273{
bart3772a982008-03-15 08:11:03 +0000274 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000275
bart3772a982008-03-15 08:11:03 +0000276 if (! running_thread_is_recording())
277 return;
barta79df6e2008-03-14 17:07:51 +0000278
bart3772a982008-03-15 08:11:03 +0000279 if (drd_trace_mem || (addr == drd_trace_address))
280 {
281 drd_trace_mem_access(addr, 4, eLoad);
282 }
283 sg = running_thread_get_segment();
284 bm_access_load_4(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000285 if (bm_load_4_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000286 {
287 drd_report_race(addr, 4, eLoad);
288 }
barta79df6e2008-03-14 17:07:51 +0000289}
290
291static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
292{
bart3772a982008-03-15 08:11:03 +0000293 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000294
bart3772a982008-03-15 08:11:03 +0000295 if (! running_thread_is_recording())
296 return;
barta79df6e2008-03-14 17:07:51 +0000297
bart3772a982008-03-15 08:11:03 +0000298 if (drd_trace_mem || (addr == drd_trace_address))
299 {
300 drd_trace_mem_access(addr, 8, eLoad);
301 }
302 sg = running_thread_get_segment();
303 bm_access_load_8(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000304 if (bm_load_8_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000305 {
306 drd_report_race(addr, 8, eLoad);
307 }
sewardjaf44c822007-11-25 14:01:38 +0000308}
309
310static
311VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
312{
bart3772a982008-03-15 08:11:03 +0000313 Segment* sg;
sewardjaf44c822007-11-25 14:01:38 +0000314
bartf00a85b2008-03-13 18:49:23 +0000315#if 0
bart3772a982008-03-15 08:11:03 +0000316 /* The assert below has been commented out because of performance reasons.*/
317 tl_assert(thread_get_running_tid()
318 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bartf00a85b2008-03-13 18:49:23 +0000319#endif
sewardjaf44c822007-11-25 14:01:38 +0000320
bart3772a982008-03-15 08:11:03 +0000321 if (! running_thread_is_recording())
322 return;
bart0268dfa2008-03-11 20:10:21 +0000323
bart3772a982008-03-15 08:11:03 +0000324 if (drd_trace_mem || (addr == drd_trace_address))
325 {
326 drd_trace_mem_access(addr, size, eStore);
327 }
328 sg = running_thread_get_segment();
329 bm_access_range_store(sg->bm, addr, addr + size);
bart7a282142008-03-15 08:34:23 +0000330 if (bm_store_has_conflict_with(thread_get_danger_set(), addr, addr + size))
bart3772a982008-03-15 08:11:03 +0000331 {
332 drd_report_race(addr, size, eStore);
333 }
barta79df6e2008-03-14 17:07:51 +0000334}
335
336static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
337{
bart3772a982008-03-15 08:11:03 +0000338 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000339
bart3772a982008-03-15 08:11:03 +0000340 if (! running_thread_is_recording())
341 return;
barta79df6e2008-03-14 17:07:51 +0000342
bart3772a982008-03-15 08:11:03 +0000343 if (drd_trace_mem || (addr == drd_trace_address))
344 {
345 drd_trace_mem_access(addr, 1, eStore);
346 }
347 sg = running_thread_get_segment();
348 bm_access_store_1(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000349 if (bm_store_1_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000350 {
351 drd_report_race(addr, 1, eStore);
352 }
barta79df6e2008-03-14 17:07:51 +0000353}
354
355static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
356{
bart3772a982008-03-15 08:11:03 +0000357 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000358
bart3772a982008-03-15 08:11:03 +0000359 if (! running_thread_is_recording())
360 return;
barta79df6e2008-03-14 17:07:51 +0000361
bart3772a982008-03-15 08:11:03 +0000362 if (drd_trace_mem || (addr == drd_trace_address))
363 {
364 drd_trace_mem_access(addr, 2, eStore);
365 }
366 sg = running_thread_get_segment();
367 bm_access_store_2(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000368 if (bm_store_2_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000369 {
370 drd_report_race(addr, 2, eStore);
371 }
barta79df6e2008-03-14 17:07:51 +0000372}
373
374static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
375{
bart3772a982008-03-15 08:11:03 +0000376 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000377
bart3772a982008-03-15 08:11:03 +0000378 if (! running_thread_is_recording())
379 return;
barta79df6e2008-03-14 17:07:51 +0000380
bart3772a982008-03-15 08:11:03 +0000381 if (drd_trace_mem || (addr == drd_trace_address))
382 {
383 drd_trace_mem_access(addr, 4, eStore);
384 }
385 sg = running_thread_get_segment();
386 bm_access_store_4(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000387 if (bm_store_4_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000388 {
389 drd_report_race(addr, 4, eStore);
390 }
barta79df6e2008-03-14 17:07:51 +0000391}
392
393static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
394{
bart3772a982008-03-15 08:11:03 +0000395 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000396
bart3772a982008-03-15 08:11:03 +0000397 if (! running_thread_is_recording())
398 return;
barta79df6e2008-03-14 17:07:51 +0000399
bart3772a982008-03-15 08:11:03 +0000400 if (drd_trace_mem || (addr == drd_trace_address))
401 {
402 drd_trace_mem_access(addr, 8, eStore);
403 }
404 sg = running_thread_get_segment();
405 bm_access_store_8(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000406 if (bm_store_8_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000407 {
408 drd_report_race(addr, 8, eStore);
409 }
sewardjaf44c822007-11-25 14:01:38 +0000410}
411
412static void drd_pre_mem_read(const CorePart part,
413 const ThreadId tid,
414 Char* const s,
415 const Addr a,
416 const SizeT size)
417{
bart3772a982008-03-15 08:11:03 +0000418 if (size > 0)
419 {
420 drd_trace_load(a, size);
421 }
sewardjaf44c822007-11-25 14:01:38 +0000422}
423
bart5e85d262008-03-01 10:49:37 +0000424static void drd_pre_mem_read_asciiz(const CorePart part,
425 const ThreadId tid,
426 Char* const s,
427 const Addr a)
428{
bart3772a982008-03-15 08:11:03 +0000429 const char* p = (void*)a;
430 SizeT size = 0;
bart5e85d262008-03-01 10:49:37 +0000431
bart3772a982008-03-15 08:11:03 +0000432 /* Note: the expression '*p' reads client memory and may crash if the */
433 /* client provided an invalid pointer ! */
434 while (*p)
435 {
436 p++;
437 size++;
438 }
439 // To do: find out what a reasonable upper limit on 'size' is.
440 tl_assert(size < 4096);
441 if (size > 0)
442 {
443 drd_trace_load(a, size);
444 }
bart5e85d262008-03-01 10:49:37 +0000445}
446
sewardjaf44c822007-11-25 14:01:38 +0000447static void drd_post_mem_write(const CorePart part,
448 const ThreadId tid,
449 const Addr a,
450 const SizeT size)
451{
bart3772a982008-03-15 08:11:03 +0000452 thread_set_vg_running_tid(VG_(get_running_tid)());
453 if (size > 0)
454 {
455 drd_trace_store(a, size);
456 }
sewardjaf44c822007-11-25 14:01:38 +0000457}
458
bart5e85d262008-03-01 10:49:37 +0000459static void drd_start_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000460{
bart3772a982008-03-15 08:11:03 +0000461 const Addr a2 = a1 + len;
bart5e85d262008-03-01 10:49:37 +0000462
bart3772a982008-03-15 08:11:03 +0000463 tl_assert(a1 < a2);
bart5e85d262008-03-01 10:49:37 +0000464
bart3772a982008-03-15 08:11:03 +0000465 if (a1 <= drd_trace_address && drd_trace_address < a2)
466 {
bartd5765912008-03-16 08:40:55 +0000467 drd_trace_mem_access(a1, len, eStart);
bart3772a982008-03-15 08:11:03 +0000468 }
sewardjaf44c822007-11-25 14:01:38 +0000469}
470
bart5e85d262008-03-01 10:49:37 +0000471static void drd_stop_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000472{
bart3772a982008-03-15 08:11:03 +0000473 const Addr a2 = a1 + len;
bart5e85d262008-03-01 10:49:37 +0000474
bart3772a982008-03-15 08:11:03 +0000475 tl_assert(a1 < a2);
bart5e85d262008-03-01 10:49:37 +0000476
bart3772a982008-03-15 08:11:03 +0000477 if (a1 <= drd_trace_address && drd_trace_address < a2)
478 {
bartd43f8d32008-03-16 17:29:20 +0000479 drd_trace_mem_access(a1, len, eEnd);
bart3772a982008-03-15 08:11:03 +0000480 }
481 thread_stop_using_mem(a1, a2);
482 clientobj_stop_using_mem(a1, a2);
483 drd_suppression_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000484}
485
bart5e85d262008-03-01 10:49:37 +0000486static
487void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
488 const Bool rr, const Bool ww, const Bool xx)
489{
bartd5765912008-03-16 08:40:55 +0000490 thread_set_vg_running_tid(VG_(get_running_tid)());
491
bart3772a982008-03-15 08:11:03 +0000492 drd_start_using_mem(a, len);
bart5e85d262008-03-01 10:49:37 +0000493}
494
sewardjaf44c822007-11-25 14:01:38 +0000495/* Called by the core when the stack of a thread grows, to indicate that */
496/* the addresses in range [ a, a + len [ may now be used by the client. */
497/* Assumption: stacks grow downward. */
498static void drd_start_using_mem_stack(const Addr a, const SizeT len)
499{
bartd43f8d32008-03-16 17:29:20 +0000500 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
501 drd_start_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB);
sewardjaf44c822007-11-25 14:01:38 +0000502}
503
504/* Called by the core when the stack of a thread shrinks, to indicate that */
505/* the addresses [ a, a + len [ are no longer accessible for the client. */
506/* Assumption: stacks grow downward. */
507static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
508{
bartd43f8d32008-03-16 17:29:20 +0000509 thread_set_stack_min(thread_get_running_tid(),
510 a + len - VG_STACK_REDZONE_SZB);
511 drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB);
sewardjaf44c822007-11-25 14:01:38 +0000512}
513
bart5e85d262008-03-01 10:49:37 +0000514static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000515{
bartd5765912008-03-16 08:40:55 +0000516 thread_set_vg_running_tid(VG_(get_running_tid)());
bart3772a982008-03-15 08:11:03 +0000517 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000518}
519
bart5e85d262008-03-01 10:49:37 +0000520static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000521{
bart3772a982008-03-15 08:11:03 +0000522 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000523}
524
525static
526void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
527{
bart3772a982008-03-15 08:11:03 +0000528 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
529 tl_assert(created != VG_INVALID_THREADID);
530 thread_pre_create(drd_creator, created);
531 if (IsValidDrdThreadId(drd_creator))
532 {
533 thread_new_segment(drd_creator);
534 }
535 if (drd_trace_fork_join)
536 {
537 VG_(message)(Vg_DebugMsg,
538 "drd_pre_thread_create creator = %d/%d, created = %d",
539 creator, drd_creator, created);
540 }
sewardjaf44c822007-11-25 14:01:38 +0000541}
542
543/* Called by Valgrind's core before any loads or stores are performed on */
544/* the context of thread "created". At startup, this function is called */
545/* with arguments (0,1). */
546static
547void drd_post_thread_create(const ThreadId created)
548{
bart3772a982008-03-15 08:11:03 +0000549 const DrdThreadId drd_created = thread_post_create(created);
550 tl_assert(created != VG_INVALID_THREADID);
551 if (drd_trace_fork_join)
552 {
553 VG_(message)(Vg_DebugMsg,
554 "drd_post_thread_create created = %d/%d",
555 created, drd_created);
556 }
sewardjaf44c822007-11-25 14:01:38 +0000557}
558
559/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
560/* after thread drd_joiner joined thread drd_joinee. */
561void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
562{
bart3772a982008-03-15 08:11:03 +0000563 tl_assert(IsValidDrdThreadId(drd_joiner));
564 tl_assert(IsValidDrdThreadId(drd_joinee));
565 thread_new_segment(drd_joinee);
566 thread_combine_vc(drd_joiner, drd_joinee);
567 thread_new_segment(drd_joiner);
sewardjaf44c822007-11-25 14:01:38 +0000568
bart3772a982008-03-15 08:11:03 +0000569 if (drd_trace_fork_join)
570 {
571 char msg[256];
572 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
573 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
574 VG_(snprintf)(msg, sizeof(msg),
575 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
576 joiner, drd_joiner, joinee, drd_joinee);
577 if (joiner)
578 {
579 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
580 ", new vc: ");
581 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
582 thread_get_vc(drd_joiner));
583 }
584 VG_(message)(Vg_DebugMsg, msg);
585 }
sewardjaf44c822007-11-25 14:01:38 +0000586
bart3772a982008-03-15 08:11:03 +0000587 thread_delete(drd_joinee);
588 mutex_thread_delete(drd_joinee);
589 cond_thread_delete(drd_joinee);
590 semaphore_thread_delete(drd_joinee);
591 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000592}
593
bart5bd9f2d2008-03-03 20:31:58 +0000594void drd_trace_addr(const Addr addr)
595{
bart3772a982008-03-15 08:11:03 +0000596 drd_trace_address = addr;
bart5bd9f2d2008-03-03 20:31:58 +0000597}
598
sewardjaf44c822007-11-25 14:01:38 +0000599/* Called after a thread has performed its last memory access. */
bartd43f8d32008-03-16 17:29:20 +0000600static void drd_thread_finished(ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000601{
bart3772a982008-03-15 08:11:03 +0000602 DrdThreadId drd_tid;
sewardj85642922008-01-14 11:54:56 +0000603
bartd43f8d32008-03-16 17:29:20 +0000604 tl_assert(VG_(get_running_tid)() == vg_tid);
sewardj85642922008-01-14 11:54:56 +0000605
bartd43f8d32008-03-16 17:29:20 +0000606 drd_tid = VgThreadIdToDrdThreadId(vg_tid);
bart3772a982008-03-15 08:11:03 +0000607 if (drd_trace_fork_join)
608 {
609 VG_(message)(Vg_DebugMsg,
610 "drd_thread_finished tid = %d/%d%s",
bartd43f8d32008-03-16 17:29:20 +0000611 vg_tid,
bart3772a982008-03-15 08:11:03 +0000612 drd_tid,
613 thread_get_joinable(drd_tid)
614 ? ""
615 : " (which is a detached thread)");
sewardjaf44c822007-11-25 14:01:38 +0000616
bart3772a982008-03-15 08:11:03 +0000617 }
bartd43f8d32008-03-16 17:29:20 +0000618 drd_stop_using_mem(thread_get_stack_min(drd_tid),
619 thread_get_stack_max(drd_tid)
620 - thread_get_stack_min(drd_tid));
621 thread_stop_recording(drd_tid);
bart3772a982008-03-15 08:11:03 +0000622 thread_finished(drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000623}
624
bart0268dfa2008-03-11 20:10:21 +0000625void drd_pre_mutex_init(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000626{
bart3772a982008-03-15 08:11:03 +0000627 mutex_init(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000628}
629
sewardj347eeba2008-01-21 14:19:07 +0000630void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000631{
bart3772a982008-03-15 08:11:03 +0000632 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000633}
634
bart2e3a3c12008-03-24 08:33:47 +0000635void drd_pre_mutex_lock(const Addr mutex, const MutexT mutex_type,
636 const Bool trylock)
sewardjaf44c822007-11-25 14:01:38 +0000637{
bart2e3a3c12008-03-24 08:33:47 +0000638 mutex_pre_lock(mutex, mutex_type, trylock);
sewardjaf44c822007-11-25 14:01:38 +0000639}
640
bart00344642008-03-01 15:27:41 +0000641void drd_post_mutex_lock(const Addr mutex, const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000642{
bart3772a982008-03-15 08:11:03 +0000643 mutex_post_lock(mutex, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000644}
645
bart00344642008-03-01 15:27:41 +0000646void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000647{
bart3772a982008-03-15 08:11:03 +0000648 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000649}
650
bart0268dfa2008-03-11 20:10:21 +0000651void drd_pre_cond_init(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000652{
bart3772a982008-03-15 08:11:03 +0000653 cond_pre_init(cond);
sewardjaf44c822007-11-25 14:01:38 +0000654}
655
bart72b751c2008-03-01 13:44:24 +0000656void drd_post_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000657{
bart3772a982008-03-15 08:11:03 +0000658 cond_post_destroy(cond);
sewardjaf44c822007-11-25 14:01:38 +0000659}
660
bart0268dfa2008-03-11 20:10:21 +0000661void drd_semaphore_init(const Addr semaphore,
sewardj85642922008-01-14 11:54:56 +0000662 const Word pshared, const Word value)
663{
bart3772a982008-03-15 08:11:03 +0000664 semaphore_init(semaphore, pshared, value);
sewardj85642922008-01-14 11:54:56 +0000665}
666
667void drd_semaphore_destroy(const Addr semaphore)
668{
bart3772a982008-03-15 08:11:03 +0000669 semaphore_destroy(semaphore);
sewardj85642922008-01-14 11:54:56 +0000670}
671
bart0268dfa2008-03-11 20:10:21 +0000672void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore)
sewardj85642922008-01-14 11:54:56 +0000673{
bart3772a982008-03-15 08:11:03 +0000674 semaphore_pre_wait(semaphore);
bart28230a32008-02-29 17:27:03 +0000675}
676
677void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
678 const Bool waited)
679{
bart3772a982008-03-15 08:11:03 +0000680 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000681}
682
bart0268dfa2008-03-11 20:10:21 +0000683void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore)
sewardj85642922008-01-14 11:54:56 +0000684{
bart3772a982008-03-15 08:11:03 +0000685 semaphore_pre_post(tid, semaphore);
sewardj85642922008-01-14 11:54:56 +0000686}
687
688void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
bart0268dfa2008-03-11 20:10:21 +0000689 const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000690{
bart3772a982008-03-15 08:11:03 +0000691 semaphore_post_post(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000692}
693
694
bart0268dfa2008-03-11 20:10:21 +0000695void drd_barrier_init(const Addr barrier,
696 const BarrierT barrier_type, const Word count,
697 const Bool reinitialization)
sewardj85642922008-01-14 11:54:56 +0000698{
bart3772a982008-03-15 08:11:03 +0000699 barrier_init(barrier, barrier_type, count, reinitialization);
sewardj85642922008-01-14 11:54:56 +0000700}
701
bart0268dfa2008-03-11 20:10:21 +0000702void drd_barrier_destroy(const Addr barrier, const BarrierT barrier_type)
sewardj85642922008-01-14 11:54:56 +0000703{
bart3772a982008-03-15 08:11:03 +0000704 barrier_destroy(barrier, barrier_type);
sewardj85642922008-01-14 11:54:56 +0000705}
706
bart0268dfa2008-03-11 20:10:21 +0000707void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier,
708 const BarrierT barrier_type)
sewardj85642922008-01-14 11:54:56 +0000709{
bart3772a982008-03-15 08:11:03 +0000710 barrier_pre_wait(tid, barrier, barrier_type);
sewardj85642922008-01-14 11:54:56 +0000711}
712
713void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
bart0268dfa2008-03-11 20:10:21 +0000714 const BarrierT barrier_type, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000715{
bart3772a982008-03-15 08:11:03 +0000716 barrier_post_wait(tid, barrier, barrier_type, waited);
sewardj85642922008-01-14 11:54:56 +0000717}
718
sewardjaf44c822007-11-25 14:01:38 +0000719
720//
721// Implementation of the tool interface.
722//
723
724static
725void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000726{
727# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
bart3772a982008-03-15 08:11:03 +0000728 /* fine */
sewardjdcbb8d32007-11-26 21:34:30 +0000729# else
bart3772a982008-03-15 08:11:03 +0000730 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000731# endif
bart95761b52008-03-29 08:34:03 +0000732
733 if (s_drd_var_info)
734 {
735 VG_(needs_var_info)();
736 }
sewardjdcbb8d32007-11-26 21:34:30 +0000737}
sewardjaf44c822007-11-25 14:01:38 +0000738
barta79df6e2008-03-14 17:07:51 +0000739static void instrument_load(IRSB* const bb,
740 IRExpr* const addr_expr,
741 const HWord size)
742{
bart3772a982008-03-15 08:11:03 +0000743 IRExpr* size_expr;
744 IRExpr** argv;
745 IRDirty* di;
barta79df6e2008-03-14 17:07:51 +0000746
bart3772a982008-03-15 08:11:03 +0000747 switch (size)
748 {
749 case 1:
750 argv = mkIRExprVec_1(addr_expr);
751 di = unsafeIRDirty_0_N(/*regparms*/1,
752 "drd_trace_load_1",
753 VG_(fnptr_to_fnentry)(drd_trace_load_1),
754 argv);
755 break;
756 case 2:
757 argv = mkIRExprVec_1(addr_expr);
758 di = unsafeIRDirty_0_N(/*regparms*/1,
759 "drd_trace_load_2",
760 VG_(fnptr_to_fnentry)(drd_trace_load_2),
761 argv);
762 break;
763 case 4:
764 argv = mkIRExprVec_1(addr_expr);
765 di = unsafeIRDirty_0_N(/*regparms*/1,
766 "drd_trace_load_4",
767 VG_(fnptr_to_fnentry)(drd_trace_load_4),
768 argv);
769 break;
770 case 8:
771 argv = mkIRExprVec_1(addr_expr);
772 di = unsafeIRDirty_0_N(/*regparms*/1,
773 "drd_trace_load_8",
774 VG_(fnptr_to_fnentry)(drd_trace_load_8),
775 argv);
776 break;
777 default:
778 size_expr = mkIRExpr_HWord(size);
779 argv = mkIRExprVec_2(addr_expr, size_expr);
780 di = unsafeIRDirty_0_N(/*regparms*/2,
781 "drd_trace_load",
782 VG_(fnptr_to_fnentry)(drd_trace_load),
783 argv);
784 break;
785 }
786 addStmtToIRSB(bb, IRStmt_Dirty(di));
barta79df6e2008-03-14 17:07:51 +0000787}
788
789static void instrument_store(IRSB* const bb,
bart3772a982008-03-15 08:11:03 +0000790 IRExpr* const addr_expr,
791 const HWord size)
barta79df6e2008-03-14 17:07:51 +0000792{
bart3772a982008-03-15 08:11:03 +0000793 IRExpr* size_expr;
794 IRExpr** argv;
795 IRDirty* di;
barta79df6e2008-03-14 17:07:51 +0000796
bart3772a982008-03-15 08:11:03 +0000797 switch (size)
798 {
799 case 1:
800 argv = mkIRExprVec_1(addr_expr);
801 di = unsafeIRDirty_0_N(/*regparms*/1,
802 "drd_trace_store_1",
803 VG_(fnptr_to_fnentry)(drd_trace_store_1),
804 argv);
805 break;
806 case 2:
807 argv = mkIRExprVec_1(addr_expr);
808 di = unsafeIRDirty_0_N(/*regparms*/1,
809 "drd_trace_store_2",
810 VG_(fnptr_to_fnentry)(drd_trace_store_2),
811 argv);
812 break;
813 case 4:
814 argv = mkIRExprVec_1(addr_expr);
815 di = unsafeIRDirty_0_N(/*regparms*/1,
816 "drd_trace_store_4",
817 VG_(fnptr_to_fnentry)(drd_trace_store_4),
818 argv);
819 break;
820 case 8:
821 argv = mkIRExprVec_1(addr_expr);
822 di = unsafeIRDirty_0_N(/*regparms*/1,
823 "drd_trace_store_8",
824 VG_(fnptr_to_fnentry)(drd_trace_store_8),
825 argv);
826 break;
827 default:
828 size_expr = mkIRExpr_HWord(size);
829 argv = mkIRExprVec_2(addr_expr, size_expr);
830 di = unsafeIRDirty_0_N(/*regparms*/2,
831 "drd_trace_store",
832 VG_(fnptr_to_fnentry)(drd_trace_store),
833 argv);
834 break;
835 }
836 addStmtToIRSB(bb, IRStmt_Dirty(di));
barta79df6e2008-03-14 17:07:51 +0000837}
838
sewardjaf44c822007-11-25 14:01:38 +0000839static
840IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000841 IRSB* const bb_in,
842 VexGuestLayout* const layout,
843 VexGuestExtents* const vge,
844 IRType const gWordTy,
845 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000846{
bart3772a982008-03-15 08:11:03 +0000847 IRDirty* di;
848 Int i;
849 IRSB* bb;
850 IRExpr** argv;
851 Bool instrument = True;
852 Bool bus_locked = False;
sewardjaf44c822007-11-25 14:01:38 +0000853
bart3772a982008-03-15 08:11:03 +0000854 /* Set up BB */
855 bb = emptyIRSB();
856 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
857 bb->next = deepCopyIRExpr(bb_in->next);
858 bb->jumpkind = bb_in->jumpkind;
sewardjaf44c822007-11-25 14:01:38 +0000859
bart3772a982008-03-15 08:11:03 +0000860 for (i = 0; i < bb_in->stmts_used; i++)
861 {
862 IRStmt* const st = bb_in->stmts[i];
863 tl_assert(st);
864 if (st->tag == Ist_NoOp)
865 continue;
sewardjaf44c822007-11-25 14:01:38 +0000866
bart3772a982008-03-15 08:11:03 +0000867 switch (st->tag)
868 {
869 case Ist_IMark:
870 instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
871 != Vg_SectPLT;
872 break;
873
874 case Ist_MBE:
875 switch (st->Ist.MBE.event)
sewardjaf44c822007-11-25 14:01:38 +0000876 {
bart3772a982008-03-15 08:11:03 +0000877 case Imbe_Fence:
878 break; /* not interesting */
879 case Imbe_BusLock:
880 tl_assert(! bus_locked);
881 bus_locked = True;
882 break;
883 case Imbe_BusUnlock:
884 tl_assert(bus_locked);
885 bus_locked = False;
886 break;
sewardjaf44c822007-11-25 14:01:38 +0000887 default:
bart3772a982008-03-15 08:11:03 +0000888 tl_assert(0);
sewardjaf44c822007-11-25 14:01:38 +0000889 }
bart3772a982008-03-15 08:11:03 +0000890 addStmtToIRSB(bb, st);
891 break;
sewardjaf44c822007-11-25 14:01:38 +0000892
bart3772a982008-03-15 08:11:03 +0000893 case Ist_Store:
894 if (instrument && ! bus_locked)
895 {
896 instrument_store(bb,
897 st->Ist.Store.addr,
898 sizeofIRType(typeOfIRExpr(bb->tyenv,
899 st->Ist.Store.data)));
900 }
901 addStmtToIRSB(bb, st);
902 break;
barta47b3512008-03-07 17:22:26 +0000903
bart3772a982008-03-15 08:11:03 +0000904 case Ist_WrTmp:
905 if (instrument)
906 {
907 const IRExpr* const data = st->Ist.WrTmp.data;
908 if (data->tag == Iex_Load)
909 {
910 instrument_load(bb,
911 data->Iex.Load.addr,
912 sizeofIRType(data->Iex.Load.ty));
913 }
914 }
915 addStmtToIRSB(bb, st);
916 break;
917
918 case Ist_Dirty:
919 if (instrument)
920 {
921 IRDirty* d = st->Ist.Dirty.details;
922 IREffect const mFx = d->mFx;
923 switch (mFx) {
924 case Ifx_None:
925 break;
926 case Ifx_Read:
927 case Ifx_Write:
928 case Ifx_Modify:
929 tl_assert(d->mAddr);
930 tl_assert(d->mSize > 0);
931 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
932 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
933 di = unsafeIRDirty_0_N(
934 /*regparms*/2,
935 "drd_trace_load",
936 VG_(fnptr_to_fnentry)(drd_trace_load),
937 argv);
938 addStmtToIRSB(bb, IRStmt_Dirty(di));
939 }
940 if ((mFx == Ifx_Write || mFx == Ifx_Modify)
941 && ! bus_locked)
942 {
943 di = unsafeIRDirty_0_N(
944 /*regparms*/2,
945 "drd_trace_store",
946 VG_(fnptr_to_fnentry)(drd_trace_store),
947 argv);
948 addStmtToIRSB(bb, IRStmt_Dirty(di));
949 }
950 break;
951 default:
952 tl_assert(0);
953 }
954 }
955 addStmtToIRSB(bb, st);
956 break;
957
958 default:
959 addStmtToIRSB(bb, st);
960 break;
961 }
962 }
963
964 tl_assert(! bus_locked);
965
966 return bb;
sewardjaf44c822007-11-25 14:01:38 +0000967}
968
sewardjaf44c822007-11-25 14:01:38 +0000969static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
970{
bart3772a982008-03-15 08:11:03 +0000971 tl_assert(tid == VG_(get_running_tid)());
972 thread_set_vg_running_tid(tid);
sewardjaf44c822007-11-25 14:01:38 +0000973}
974
975static
976void drd_fini(Int exitcode)
977{
bart3772a982008-03-15 08:11:03 +0000978 // thread_print_all();
979 if (VG_(clo_verbosity) > 1 || drd_print_stats)
980 {
981 VG_(message)(Vg_DebugMsg,
982 " thread: %lld context switches"
983 " / %lld updates of the danger set",
984 thread_get_context_switch_count(),
985 thread_get_update_danger_set_count());
986 VG_(message)(Vg_DebugMsg,
987 " segments: %lld total, %lld max, %lld discard points",
bart7102f102008-03-17 17:37:53 +0000988 sg_get_created_segments_count(),
989 sg_get_max_alive_segments_count(),
bart3772a982008-03-15 08:11:03 +0000990 thread_get_discard_ordered_segments_count());
991 VG_(message)(Vg_DebugMsg,
992 " bitmaps: %lld / %lld bitmaps were allocated"
993 " and %lld / %lld for danger set updates",
994 bm_get_bitmap_creation_count(),
995 bm_get_bitmap2_creation_count(),
996 thread_get_danger_set_bitmap_creation_count(),
997 thread_get_danger_set_bitmap2_creation_count());
998 VG_(message)(Vg_DebugMsg,
999 " mutex: %lld non-recursive lock/unlock events",
1000 get_mutex_lock_count());
1001 drd_print_malloc_stats();
1002 }
sewardjaf44c822007-11-25 14:01:38 +00001003}
1004
sewardjaf44c822007-11-25 14:01:38 +00001005static
1006void drd_pre_clo_init(void)
1007{
bart3772a982008-03-15 08:11:03 +00001008 // Basic tool stuff.
sewardjaf44c822007-11-25 14:01:38 +00001009
bart3772a982008-03-15 08:11:03 +00001010 VG_(details_name) ("exp-drd");
1011 VG_(details_version) (NULL);
1012 VG_(details_description) ("a data race detector");
1013 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
1014 " by Bart Van Assche.");
1015 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardjaf44c822007-11-25 14:01:38 +00001016
bart3772a982008-03-15 08:11:03 +00001017 VG_(basic_tool_funcs) (drd_post_clo_init,
1018 drd_instrument,
1019 drd_fini);
sewardjaf44c822007-11-25 14:01:38 +00001020
bart3772a982008-03-15 08:11:03 +00001021 // Command line stuff.
1022 VG_(needs_command_line_options)(drd_process_cmd_line_option,
1023 drd_print_usage,
1024 drd_print_debug_usage);
sewardjaf44c822007-11-25 14:01:38 +00001025
bart3772a982008-03-15 08:11:03 +00001026 // Error handling.
1027 drd_register_error_handlers();
sewardjaf44c822007-11-25 14:01:38 +00001028
bart3772a982008-03-15 08:11:03 +00001029 // Core event tracking.
1030 VG_(track_pre_mem_read) (drd_pre_mem_read);
1031 VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz);
1032 VG_(track_post_mem_write) (drd_post_mem_write);
1033 VG_(track_new_mem_brk) (drd_start_using_mem);
1034 VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms);
1035 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
1036 VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
1037 VG_(track_new_mem_startup) (drd_start_using_mem_w_perms);
1038 VG_(track_die_mem_brk) (drd_stop_using_mem);
1039 VG_(track_die_mem_munmap) (drd_stop_using_mem);
1040 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
1041 VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
1042 VG_(track_start_client_code) (drd_start_client_code);
1043 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
1044 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
1045 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
sewardjaf44c822007-11-25 14:01:38 +00001046
bart3772a982008-03-15 08:11:03 +00001047 // Other stuff.
bart3772a982008-03-15 08:11:03 +00001048 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
sewardjaf44c822007-11-25 14:01:38 +00001049
bart3772a982008-03-15 08:11:03 +00001050 drd_clientreq_init();
sewardjaf44c822007-11-25 14:01:38 +00001051
bart3772a982008-03-15 08:11:03 +00001052 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +00001053
bart3772a982008-03-15 08:11:03 +00001054 clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +00001055}
1056
1057
1058VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)