blob: baed74b444d1e4d28e20ba59d730769ad19d8698 [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
bart912ab8d2008-03-29 09:31:43 +000064static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000065static Bool drd_trace_fork_join = False;
bart912ab8d2008-03-29 09:31:43 +000066static Bool drd_trace_mem = False;
67static Addr drd_trace_address = 0;
68static Bool s_drd_var_info = False;
69static Bool s_show_stack_usage = False;
sewardjaf44c822007-11-25 14:01:38 +000070
71
72//
73// Implement the needs_command_line_options for drd.
74//
75
76static Bool drd_process_cmd_line_option(Char* arg)
77{
barta9c37392008-03-22 09:38:48 +000078 int segment_merging = -1;
79 int show_confl_seg = -1;
80 int trace_barrier = -1;
81 int trace_clientobj = -1;
82 int trace_cond = -1;
83 int trace_csw = -1;
84 int trace_danger_set = -1;
85 int trace_mutex = -1;
86 int trace_rwlock = -1;
87 int trace_segment = -1;
88 int trace_semaphore = -1;
89 int trace_suppression = -1;
90 Char* trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000091
bart3772a982008-03-15 08:11:03 +000092 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
barta9c37392008-03-22 09:38:48 +000093 else VG_BOOL_CLO(arg, "--segment-merging", segment_merging)
bart16d76e52008-03-18 17:08:08 +000094 else VG_BOOL_CLO(arg, "--show-confl-seg", show_confl_seg)
bart912ab8d2008-03-29 09:31:43 +000095 else VG_BOOL_CLO(arg, "--show-stack-usage", s_show_stack_usage)
bart3772a982008-03-15 08:11:03 +000096 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
97 else VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj)
98 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
99 else VG_BOOL_CLO(arg, "--trace-csw", trace_csw)
100 else VG_BOOL_CLO(arg, "--trace-danger-set", trace_danger_set)
101 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
102 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
103 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
104 else VG_BOOL_CLO(arg, "--trace-rwlock", trace_rwlock)
105 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
106 else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
107 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
bart95761b52008-03-29 08:34:03 +0000108 else VG_BOOL_CLO(arg, "--var-info", s_drd_var_info)
bart3772a982008-03-15 08:11:03 +0000109 else VG_STR_CLO (arg, "--trace-address", trace_address)
110 else
bartceded212008-03-26 17:39:52 +0000111 return VG_(replacement_malloc_process_cmd_line_option)(arg);
sewardjaf44c822007-11-25 14:01:38 +0000112
barta9c37392008-03-22 09:38:48 +0000113 if (segment_merging != -1)
114 thread_set_segment_merging(segment_merging);
115 if (show_confl_seg != -1)
bart16d76e52008-03-18 17:08:08 +0000116 set_show_conflicting_segments(show_confl_seg);
bart3772a982008-03-15 08:11:03 +0000117 if (trace_address)
118 {
119 drd_trace_address = VG_(strtoll16)(trace_address, 0);
120 }
barta9c37392008-03-22 09:38:48 +0000121 if (trace_barrier != -1)
bart3772a982008-03-15 08:11:03 +0000122 barrier_set_trace(trace_barrier);
barta9c37392008-03-22 09:38:48 +0000123 if (trace_clientobj != -1)
bart3772a982008-03-15 08:11:03 +0000124 clientobj_set_trace(trace_clientobj);
barta9c37392008-03-22 09:38:48 +0000125 if (trace_cond != -1)
bart3772a982008-03-15 08:11:03 +0000126 cond_set_trace(trace_cond);
barta9c37392008-03-22 09:38:48 +0000127 if (trace_csw != -1)
bart3772a982008-03-15 08:11:03 +0000128 thread_trace_context_switches(trace_csw);
barta9c37392008-03-22 09:38:48 +0000129 if (trace_danger_set != -1)
bart3772a982008-03-15 08:11:03 +0000130 thread_trace_danger_set(trace_danger_set);
barta9c37392008-03-22 09:38:48 +0000131 if (trace_mutex != -1)
bart3772a982008-03-15 08:11:03 +0000132 mutex_set_trace(trace_mutex);
barta9c37392008-03-22 09:38:48 +0000133 if (trace_rwlock != -1)
bart3772a982008-03-15 08:11:03 +0000134 rwlock_set_trace(trace_rwlock);
barta9c37392008-03-22 09:38:48 +0000135 if (trace_segment != -1)
bart3772a982008-03-15 08:11:03 +0000136 sg_set_trace(trace_segment);
barta9c37392008-03-22 09:38:48 +0000137 if (trace_semaphore != -1)
bart3772a982008-03-15 08:11:03 +0000138 semaphore_set_trace(trace_semaphore);
barta9c37392008-03-22 09:38:48 +0000139 if (trace_suppression != -1)
bart3772a982008-03-15 08:11:03 +0000140 suppression_set_trace(trace_suppression);
sewardjaf44c822007-11-25 14:01:38 +0000141
bart3772a982008-03-15 08:11:03 +0000142 return True;
sewardjaf44c822007-11-25 14:01:38 +0000143}
144
145static void drd_print_usage(void)
146{
bart3772a982008-03-15 08:11:03 +0000147 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
148 "\n"
149 " --trace-fork-join=no|yes Trace all thread creation and join"
150 " activity\n"
151 " --trace-mutex=no|yes Trace all mutex activity\n"
152 " --trace-segment=no|yes Trace segment actions\n"
153 );
sewardjaf44c822007-11-25 14:01:38 +0000154}
155
156static void drd_print_debug_usage(void)
157{
158}
159
160
161//
162// Implements the thread-related core callbacks.
163//
164
barta79df6e2008-03-14 17:07:51 +0000165static void drd_trace_mem_access(const Addr addr, const SizeT size,
166 const BmAccessTypeT access_type)
167{
bart3772a982008-03-15 08:11:03 +0000168 char vc[80];
169 vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
170 VG_(message)(Vg_UserMsg,
bart354009c2008-03-16 10:42:33 +0000171 "%s 0x%lx size %ld (vg %d / drd %d / vc %s)",
bartd5765912008-03-16 08:40:55 +0000172 access_type == eLoad
173 ? "load "
174 : access_type == eStore
175 ? "store"
176 : access_type == eStart
177 ? "start"
178 : access_type == eEnd
bartd43f8d32008-03-16 17:29:20 +0000179 ? "end "
bartd5765912008-03-16 08:40:55 +0000180 : "????",
bart3772a982008-03-15 08:11:03 +0000181 addr,
182 size,
bart3772a982008-03-15 08:11:03 +0000183 VG_(get_running_tid)(),
184 thread_get_running_tid(),
185 vc);
186 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
187 VG_(clo_backtrace_size));
188 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
189 == VG_(get_running_tid)());
barta79df6e2008-03-14 17:07:51 +0000190}
191
192static void drd_report_race(const Addr addr, const SizeT size,
193 const BmAccessTypeT access_type)
194{
bart49c3a112008-03-15 10:28:36 +0000195 DataRaceErrInfo drei;
196
bart7a282142008-03-15 08:34:23 +0000197 if (drd_is_suppressed(addr, addr + size))
198 return;
199
bart354009c2008-03-16 10:42:33 +0000200 drei.tid = thread_get_running_tid();
bart3772a982008-03-15 08:11:03 +0000201 drei.addr = addr;
202 drei.size = size;
203 drei.access_type = access_type;
204 VG_(maybe_record_error)(VG_(get_running_tid)(),
205 DataRaceErr,
206 VG_(get_IP)(VG_(get_running_tid)()),
207 "Conflicting accesses",
208 &drei);
barta79df6e2008-03-14 17:07:51 +0000209}
210
211static VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
sewardjaf44c822007-11-25 14:01:38 +0000212{
bart3772a982008-03-15 08:11:03 +0000213 Segment* sg;
sewardjaf44c822007-11-25 14:01:38 +0000214
bartf00a85b2008-03-13 18:49:23 +0000215#if 0
bart3772a982008-03-15 08:11:03 +0000216 /* The assert below has been commented out because of performance reasons.*/
217 tl_assert(thread_get_running_tid()
218 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bartf00a85b2008-03-13 18:49:23 +0000219#endif
sewardjaf44c822007-11-25 14:01:38 +0000220
bart3772a982008-03-15 08:11:03 +0000221 if (! running_thread_is_recording())
222 return;
bart0268dfa2008-03-11 20:10:21 +0000223
bart3772a982008-03-15 08:11:03 +0000224 if (drd_trace_mem || (addr == drd_trace_address))
225 {
226 drd_trace_mem_access(addr, size, eLoad);
227 }
228 sg = running_thread_get_segment();
229 bm_access_range_load(sg->bm, addr, addr + size);
bart7a282142008-03-15 08:34:23 +0000230 if (bm_load_has_conflict_with(thread_get_danger_set(), addr, addr + size))
bart3772a982008-03-15 08:11:03 +0000231 {
232 drd_report_race(addr, size, eLoad);
233 }
barta79df6e2008-03-14 17:07:51 +0000234}
235
236static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
237{
bart3772a982008-03-15 08:11:03 +0000238 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000239
bart3772a982008-03-15 08:11:03 +0000240 if (! running_thread_is_recording())
241 return;
barta79df6e2008-03-14 17:07:51 +0000242
bart3772a982008-03-15 08:11:03 +0000243 if (drd_trace_mem || (addr == drd_trace_address))
244 {
245 drd_trace_mem_access(addr, 1, eLoad);
246 }
247 sg = running_thread_get_segment();
248 bm_access_load_1(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000249 if (bm_load_1_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000250 {
251 drd_report_race(addr, 1, eLoad);
252 }
barta79df6e2008-03-14 17:07:51 +0000253}
254
255static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
256{
bart3772a982008-03-15 08:11:03 +0000257 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000258
bart3772a982008-03-15 08:11:03 +0000259 if (! running_thread_is_recording())
260 return;
barta79df6e2008-03-14 17:07:51 +0000261
bart3772a982008-03-15 08:11:03 +0000262 if (drd_trace_mem || (addr == drd_trace_address))
263 {
264 drd_trace_mem_access(addr, 2, eLoad);
265 }
266 sg = running_thread_get_segment();
267 bm_access_load_2(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000268 if (bm_load_2_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000269 {
270 drd_report_race(addr, 2, eLoad);
271 }
barta79df6e2008-03-14 17:07:51 +0000272}
273
274static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
275{
bart3772a982008-03-15 08:11:03 +0000276 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000277
bart3772a982008-03-15 08:11:03 +0000278 if (! running_thread_is_recording())
279 return;
barta79df6e2008-03-14 17:07:51 +0000280
bart3772a982008-03-15 08:11:03 +0000281 if (drd_trace_mem || (addr == drd_trace_address))
282 {
283 drd_trace_mem_access(addr, 4, eLoad);
284 }
285 sg = running_thread_get_segment();
286 bm_access_load_4(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000287 if (bm_load_4_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000288 {
289 drd_report_race(addr, 4, eLoad);
290 }
barta79df6e2008-03-14 17:07:51 +0000291}
292
293static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
294{
bart3772a982008-03-15 08:11:03 +0000295 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000296
bart3772a982008-03-15 08:11:03 +0000297 if (! running_thread_is_recording())
298 return;
barta79df6e2008-03-14 17:07:51 +0000299
bart3772a982008-03-15 08:11:03 +0000300 if (drd_trace_mem || (addr == drd_trace_address))
301 {
302 drd_trace_mem_access(addr, 8, eLoad);
303 }
304 sg = running_thread_get_segment();
305 bm_access_load_8(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000306 if (bm_load_8_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000307 {
308 drd_report_race(addr, 8, eLoad);
309 }
sewardjaf44c822007-11-25 14:01:38 +0000310}
311
312static
313VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
314{
bart3772a982008-03-15 08:11:03 +0000315 Segment* sg;
sewardjaf44c822007-11-25 14:01:38 +0000316
bartf00a85b2008-03-13 18:49:23 +0000317#if 0
bart3772a982008-03-15 08:11:03 +0000318 /* The assert below has been commented out because of performance reasons.*/
319 tl_assert(thread_get_running_tid()
320 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bartf00a85b2008-03-13 18:49:23 +0000321#endif
sewardjaf44c822007-11-25 14:01:38 +0000322
bart3772a982008-03-15 08:11:03 +0000323 if (! running_thread_is_recording())
324 return;
bart0268dfa2008-03-11 20:10:21 +0000325
bart3772a982008-03-15 08:11:03 +0000326 if (drd_trace_mem || (addr == drd_trace_address))
327 {
328 drd_trace_mem_access(addr, size, eStore);
329 }
330 sg = running_thread_get_segment();
331 bm_access_range_store(sg->bm, addr, addr + size);
bart7a282142008-03-15 08:34:23 +0000332 if (bm_store_has_conflict_with(thread_get_danger_set(), addr, addr + size))
bart3772a982008-03-15 08:11:03 +0000333 {
334 drd_report_race(addr, size, eStore);
335 }
barta79df6e2008-03-14 17:07:51 +0000336}
337
338static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
339{
bart3772a982008-03-15 08:11:03 +0000340 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000341
bart3772a982008-03-15 08:11:03 +0000342 if (! running_thread_is_recording())
343 return;
barta79df6e2008-03-14 17:07:51 +0000344
bart3772a982008-03-15 08:11:03 +0000345 if (drd_trace_mem || (addr == drd_trace_address))
346 {
347 drd_trace_mem_access(addr, 1, eStore);
348 }
349 sg = running_thread_get_segment();
350 bm_access_store_1(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000351 if (bm_store_1_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000352 {
353 drd_report_race(addr, 1, eStore);
354 }
barta79df6e2008-03-14 17:07:51 +0000355}
356
357static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
358{
bart3772a982008-03-15 08:11:03 +0000359 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000360
bart3772a982008-03-15 08:11:03 +0000361 if (! running_thread_is_recording())
362 return;
barta79df6e2008-03-14 17:07:51 +0000363
bart3772a982008-03-15 08:11:03 +0000364 if (drd_trace_mem || (addr == drd_trace_address))
365 {
366 drd_trace_mem_access(addr, 2, eStore);
367 }
368 sg = running_thread_get_segment();
369 bm_access_store_2(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000370 if (bm_store_2_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000371 {
372 drd_report_race(addr, 2, eStore);
373 }
barta79df6e2008-03-14 17:07:51 +0000374}
375
376static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
377{
bart3772a982008-03-15 08:11:03 +0000378 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000379
bart3772a982008-03-15 08:11:03 +0000380 if (! running_thread_is_recording())
381 return;
barta79df6e2008-03-14 17:07:51 +0000382
bart3772a982008-03-15 08:11:03 +0000383 if (drd_trace_mem || (addr == drd_trace_address))
384 {
385 drd_trace_mem_access(addr, 4, eStore);
386 }
387 sg = running_thread_get_segment();
388 bm_access_store_4(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000389 if (bm_store_4_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000390 {
391 drd_report_race(addr, 4, eStore);
392 }
barta79df6e2008-03-14 17:07:51 +0000393}
394
395static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
396{
bart3772a982008-03-15 08:11:03 +0000397 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000398
bart3772a982008-03-15 08:11:03 +0000399 if (! running_thread_is_recording())
400 return;
barta79df6e2008-03-14 17:07:51 +0000401
bart3772a982008-03-15 08:11:03 +0000402 if (drd_trace_mem || (addr == drd_trace_address))
403 {
404 drd_trace_mem_access(addr, 8, eStore);
405 }
406 sg = running_thread_get_segment();
407 bm_access_store_8(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000408 if (bm_store_8_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000409 {
410 drd_report_race(addr, 8, eStore);
411 }
sewardjaf44c822007-11-25 14:01:38 +0000412}
413
414static void drd_pre_mem_read(const CorePart part,
415 const ThreadId tid,
416 Char* const s,
417 const Addr a,
418 const SizeT size)
419{
bart3772a982008-03-15 08:11:03 +0000420 if (size > 0)
421 {
422 drd_trace_load(a, size);
423 }
sewardjaf44c822007-11-25 14:01:38 +0000424}
425
bart5e85d262008-03-01 10:49:37 +0000426static void drd_pre_mem_read_asciiz(const CorePart part,
427 const ThreadId tid,
428 Char* const s,
429 const Addr a)
430{
bart3772a982008-03-15 08:11:03 +0000431 const char* p = (void*)a;
432 SizeT size = 0;
bart5e85d262008-03-01 10:49:37 +0000433
bart3772a982008-03-15 08:11:03 +0000434 /* Note: the expression '*p' reads client memory and may crash if the */
435 /* client provided an invalid pointer ! */
436 while (*p)
437 {
438 p++;
439 size++;
440 }
441 // To do: find out what a reasonable upper limit on 'size' is.
442 tl_assert(size < 4096);
443 if (size > 0)
444 {
445 drd_trace_load(a, size);
446 }
bart5e85d262008-03-01 10:49:37 +0000447}
448
sewardjaf44c822007-11-25 14:01:38 +0000449static void drd_post_mem_write(const CorePart part,
450 const ThreadId tid,
451 const Addr a,
452 const SizeT size)
453{
bart3772a982008-03-15 08:11:03 +0000454 thread_set_vg_running_tid(VG_(get_running_tid)());
455 if (size > 0)
456 {
457 drd_trace_store(a, size);
458 }
sewardjaf44c822007-11-25 14:01:38 +0000459}
460
bart5e85d262008-03-01 10:49:37 +0000461static void drd_start_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000462{
bart3772a982008-03-15 08:11:03 +0000463 const Addr a2 = a1 + len;
bart5e85d262008-03-01 10:49:37 +0000464
bart3772a982008-03-15 08:11:03 +0000465 tl_assert(a1 < a2);
bart5e85d262008-03-01 10:49:37 +0000466
bart3772a982008-03-15 08:11:03 +0000467 if (a1 <= drd_trace_address && drd_trace_address < a2)
468 {
bartd5765912008-03-16 08:40:55 +0000469 drd_trace_mem_access(a1, len, eStart);
bart3772a982008-03-15 08:11:03 +0000470 }
sewardjaf44c822007-11-25 14:01:38 +0000471}
472
bart5e85d262008-03-01 10:49:37 +0000473static void drd_stop_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000474{
bart3772a982008-03-15 08:11:03 +0000475 const Addr a2 = a1 + len;
bart5e85d262008-03-01 10:49:37 +0000476
bart3772a982008-03-15 08:11:03 +0000477 tl_assert(a1 < a2);
bart5e85d262008-03-01 10:49:37 +0000478
bart3772a982008-03-15 08:11:03 +0000479 if (a1 <= drd_trace_address && drd_trace_address < a2)
480 {
bartd43f8d32008-03-16 17:29:20 +0000481 drd_trace_mem_access(a1, len, eEnd);
bart3772a982008-03-15 08:11:03 +0000482 }
483 thread_stop_using_mem(a1, a2);
484 clientobj_stop_using_mem(a1, a2);
485 drd_suppression_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000486}
487
bart5e85d262008-03-01 10:49:37 +0000488static
489void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
490 const Bool rr, const Bool ww, const Bool xx)
491{
bartd5765912008-03-16 08:40:55 +0000492 thread_set_vg_running_tid(VG_(get_running_tid)());
493
bart3772a982008-03-15 08:11:03 +0000494 drd_start_using_mem(a, len);
bart5e85d262008-03-01 10:49:37 +0000495}
496
sewardjaf44c822007-11-25 14:01:38 +0000497/* Called by the core when the stack of a thread grows, to indicate that */
498/* the addresses in range [ a, a + len [ may now be used by the client. */
499/* Assumption: stacks grow downward. */
500static void drd_start_using_mem_stack(const Addr a, const SizeT len)
501{
bartd43f8d32008-03-16 17:29:20 +0000502 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
503 drd_start_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB);
sewardjaf44c822007-11-25 14:01:38 +0000504}
505
506/* Called by the core when the stack of a thread shrinks, to indicate that */
507/* the addresses [ a, a + len [ are no longer accessible for the client. */
508/* Assumption: stacks grow downward. */
509static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
510{
bartd43f8d32008-03-16 17:29:20 +0000511 thread_set_stack_min(thread_get_running_tid(),
512 a + len - VG_STACK_REDZONE_SZB);
513 drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB);
sewardjaf44c822007-11-25 14:01:38 +0000514}
515
bart5e85d262008-03-01 10:49:37 +0000516static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000517{
bartd5765912008-03-16 08:40:55 +0000518 thread_set_vg_running_tid(VG_(get_running_tid)());
bart3772a982008-03-15 08:11:03 +0000519 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000520}
521
bart5e85d262008-03-01 10:49:37 +0000522static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000523{
bart3772a982008-03-15 08:11:03 +0000524 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000525}
526
527static
528void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
529{
bart3772a982008-03-15 08:11:03 +0000530 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
531 tl_assert(created != VG_INVALID_THREADID);
532 thread_pre_create(drd_creator, created);
533 if (IsValidDrdThreadId(drd_creator))
534 {
535 thread_new_segment(drd_creator);
536 }
537 if (drd_trace_fork_join)
538 {
539 VG_(message)(Vg_DebugMsg,
540 "drd_pre_thread_create creator = %d/%d, created = %d",
541 creator, drd_creator, created);
542 }
sewardjaf44c822007-11-25 14:01:38 +0000543}
544
545/* Called by Valgrind's core before any loads or stores are performed on */
546/* the context of thread "created". At startup, this function is called */
547/* with arguments (0,1). */
548static
549void drd_post_thread_create(const ThreadId created)
550{
bart3772a982008-03-15 08:11:03 +0000551 const DrdThreadId drd_created = thread_post_create(created);
552 tl_assert(created != VG_INVALID_THREADID);
553 if (drd_trace_fork_join)
554 {
555 VG_(message)(Vg_DebugMsg,
556 "drd_post_thread_create created = %d/%d",
557 created, drd_created);
558 }
sewardjaf44c822007-11-25 14:01:38 +0000559}
560
561/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
562/* after thread drd_joiner joined thread drd_joinee. */
563void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
564{
bart3772a982008-03-15 08:11:03 +0000565 tl_assert(IsValidDrdThreadId(drd_joiner));
566 tl_assert(IsValidDrdThreadId(drd_joinee));
567 thread_new_segment(drd_joinee);
568 thread_combine_vc(drd_joiner, drd_joinee);
569 thread_new_segment(drd_joiner);
sewardjaf44c822007-11-25 14:01:38 +0000570
bart3772a982008-03-15 08:11:03 +0000571 if (drd_trace_fork_join)
572 {
573 char msg[256];
574 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
575 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
576 VG_(snprintf)(msg, sizeof(msg),
577 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
578 joiner, drd_joiner, joinee, drd_joinee);
579 if (joiner)
580 {
581 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
582 ", new vc: ");
583 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
584 thread_get_vc(drd_joiner));
585 }
586 VG_(message)(Vg_DebugMsg, msg);
587 }
sewardjaf44c822007-11-25 14:01:38 +0000588
bart3772a982008-03-15 08:11:03 +0000589 thread_delete(drd_joinee);
590 mutex_thread_delete(drd_joinee);
591 cond_thread_delete(drd_joinee);
592 semaphore_thread_delete(drd_joinee);
593 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000594}
595
bart5bd9f2d2008-03-03 20:31:58 +0000596void drd_trace_addr(const Addr addr)
597{
bart3772a982008-03-15 08:11:03 +0000598 drd_trace_address = addr;
bart5bd9f2d2008-03-03 20:31:58 +0000599}
600
sewardjaf44c822007-11-25 14:01:38 +0000601/* Called after a thread has performed its last memory access. */
bartd43f8d32008-03-16 17:29:20 +0000602static void drd_thread_finished(ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000603{
bart3772a982008-03-15 08:11:03 +0000604 DrdThreadId drd_tid;
sewardj85642922008-01-14 11:54:56 +0000605
bartd43f8d32008-03-16 17:29:20 +0000606 tl_assert(VG_(get_running_tid)() == vg_tid);
sewardj85642922008-01-14 11:54:56 +0000607
bartd43f8d32008-03-16 17:29:20 +0000608 drd_tid = VgThreadIdToDrdThreadId(vg_tid);
bart3772a982008-03-15 08:11:03 +0000609 if (drd_trace_fork_join)
610 {
611 VG_(message)(Vg_DebugMsg,
612 "drd_thread_finished tid = %d/%d%s",
bartd43f8d32008-03-16 17:29:20 +0000613 vg_tid,
bart3772a982008-03-15 08:11:03 +0000614 drd_tid,
615 thread_get_joinable(drd_tid)
616 ? ""
617 : " (which is a detached thread)");
bart912ab8d2008-03-29 09:31:43 +0000618 }
619 if (s_show_stack_usage)
620 {
621 const SizeT stack_size = thread_get_stack_size(drd_tid);
622 const SizeT used_stack
623 = thread_get_stack_max(drd_tid) - thread_get_stack_min_min(drd_tid);
624 VG_(message)(Vg_UserMsg,
625 "thread %d/%d%s finished and used %ld bytes out of %ld"
626 " on its stack. Margin: %ld bytes.",
627 vg_tid,
628 drd_tid,
629 thread_get_joinable(drd_tid)
630 ? ""
631 : " (which is a detached thread)",
632 used_stack,
633 stack_size,
634 stack_size - used_stack);
sewardjaf44c822007-11-25 14:01:38 +0000635
bart3772a982008-03-15 08:11:03 +0000636 }
bartd43f8d32008-03-16 17:29:20 +0000637 drd_stop_using_mem(thread_get_stack_min(drd_tid),
638 thread_get_stack_max(drd_tid)
639 - thread_get_stack_min(drd_tid));
640 thread_stop_recording(drd_tid);
bart3772a982008-03-15 08:11:03 +0000641 thread_finished(drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000642}
643
bart0268dfa2008-03-11 20:10:21 +0000644void drd_pre_mutex_init(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000645{
bart3772a982008-03-15 08:11:03 +0000646 mutex_init(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000647}
648
sewardj347eeba2008-01-21 14:19:07 +0000649void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000650{
bart3772a982008-03-15 08:11:03 +0000651 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000652}
653
bart2e3a3c12008-03-24 08:33:47 +0000654void drd_pre_mutex_lock(const Addr mutex, const MutexT mutex_type,
655 const Bool trylock)
sewardjaf44c822007-11-25 14:01:38 +0000656{
bart2e3a3c12008-03-24 08:33:47 +0000657 mutex_pre_lock(mutex, mutex_type, trylock);
sewardjaf44c822007-11-25 14:01:38 +0000658}
659
bart00344642008-03-01 15:27:41 +0000660void drd_post_mutex_lock(const Addr mutex, const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000661{
bart3772a982008-03-15 08:11:03 +0000662 mutex_post_lock(mutex, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000663}
664
bart00344642008-03-01 15:27:41 +0000665void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000666{
bart3772a982008-03-15 08:11:03 +0000667 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000668}
669
bart0268dfa2008-03-11 20:10:21 +0000670void drd_pre_cond_init(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000671{
bart3772a982008-03-15 08:11:03 +0000672 cond_pre_init(cond);
sewardjaf44c822007-11-25 14:01:38 +0000673}
674
bart72b751c2008-03-01 13:44:24 +0000675void drd_post_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000676{
bart3772a982008-03-15 08:11:03 +0000677 cond_post_destroy(cond);
sewardjaf44c822007-11-25 14:01:38 +0000678}
679
bart0268dfa2008-03-11 20:10:21 +0000680void drd_semaphore_init(const Addr semaphore,
sewardj85642922008-01-14 11:54:56 +0000681 const Word pshared, const Word value)
682{
bart3772a982008-03-15 08:11:03 +0000683 semaphore_init(semaphore, pshared, value);
sewardj85642922008-01-14 11:54:56 +0000684}
685
686void drd_semaphore_destroy(const Addr semaphore)
687{
bart3772a982008-03-15 08:11:03 +0000688 semaphore_destroy(semaphore);
sewardj85642922008-01-14 11:54:56 +0000689}
690
bart0268dfa2008-03-11 20:10:21 +0000691void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore)
sewardj85642922008-01-14 11:54:56 +0000692{
bart3772a982008-03-15 08:11:03 +0000693 semaphore_pre_wait(semaphore);
bart28230a32008-02-29 17:27:03 +0000694}
695
696void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
697 const Bool waited)
698{
bart3772a982008-03-15 08:11:03 +0000699 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000700}
701
bart0268dfa2008-03-11 20:10:21 +0000702void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore)
sewardj85642922008-01-14 11:54:56 +0000703{
bart3772a982008-03-15 08:11:03 +0000704 semaphore_pre_post(tid, semaphore);
sewardj85642922008-01-14 11:54:56 +0000705}
706
707void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
bart0268dfa2008-03-11 20:10:21 +0000708 const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000709{
bart3772a982008-03-15 08:11:03 +0000710 semaphore_post_post(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000711}
712
713
bart0268dfa2008-03-11 20:10:21 +0000714void drd_barrier_init(const Addr barrier,
715 const BarrierT barrier_type, const Word count,
716 const Bool reinitialization)
sewardj85642922008-01-14 11:54:56 +0000717{
bart3772a982008-03-15 08:11:03 +0000718 barrier_init(barrier, barrier_type, count, reinitialization);
sewardj85642922008-01-14 11:54:56 +0000719}
720
bart0268dfa2008-03-11 20:10:21 +0000721void drd_barrier_destroy(const Addr barrier, const BarrierT barrier_type)
sewardj85642922008-01-14 11:54:56 +0000722{
bart3772a982008-03-15 08:11:03 +0000723 barrier_destroy(barrier, barrier_type);
sewardj85642922008-01-14 11:54:56 +0000724}
725
bart0268dfa2008-03-11 20:10:21 +0000726void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier,
727 const BarrierT barrier_type)
sewardj85642922008-01-14 11:54:56 +0000728{
bart3772a982008-03-15 08:11:03 +0000729 barrier_pre_wait(tid, barrier, barrier_type);
sewardj85642922008-01-14 11:54:56 +0000730}
731
732void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
bart0268dfa2008-03-11 20:10:21 +0000733 const BarrierT barrier_type, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000734{
bart3772a982008-03-15 08:11:03 +0000735 barrier_post_wait(tid, barrier, barrier_type, waited);
sewardj85642922008-01-14 11:54:56 +0000736}
737
sewardjaf44c822007-11-25 14:01:38 +0000738
739//
740// Implementation of the tool interface.
741//
742
743static
744void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000745{
746# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
bart3772a982008-03-15 08:11:03 +0000747 /* fine */
sewardjdcbb8d32007-11-26 21:34:30 +0000748# else
bart3772a982008-03-15 08:11:03 +0000749 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000750# endif
bart95761b52008-03-29 08:34:03 +0000751
752 if (s_drd_var_info)
753 {
754 VG_(needs_var_info)();
755 }
sewardjdcbb8d32007-11-26 21:34:30 +0000756}
sewardjaf44c822007-11-25 14:01:38 +0000757
barta79df6e2008-03-14 17:07:51 +0000758static void instrument_load(IRSB* const bb,
759 IRExpr* const addr_expr,
760 const HWord size)
761{
bart3772a982008-03-15 08:11:03 +0000762 IRExpr* size_expr;
763 IRExpr** argv;
764 IRDirty* di;
barta79df6e2008-03-14 17:07:51 +0000765
bart3772a982008-03-15 08:11:03 +0000766 switch (size)
767 {
768 case 1:
769 argv = mkIRExprVec_1(addr_expr);
770 di = unsafeIRDirty_0_N(/*regparms*/1,
771 "drd_trace_load_1",
772 VG_(fnptr_to_fnentry)(drd_trace_load_1),
773 argv);
774 break;
775 case 2:
776 argv = mkIRExprVec_1(addr_expr);
777 di = unsafeIRDirty_0_N(/*regparms*/1,
778 "drd_trace_load_2",
779 VG_(fnptr_to_fnentry)(drd_trace_load_2),
780 argv);
781 break;
782 case 4:
783 argv = mkIRExprVec_1(addr_expr);
784 di = unsafeIRDirty_0_N(/*regparms*/1,
785 "drd_trace_load_4",
786 VG_(fnptr_to_fnentry)(drd_trace_load_4),
787 argv);
788 break;
789 case 8:
790 argv = mkIRExprVec_1(addr_expr);
791 di = unsafeIRDirty_0_N(/*regparms*/1,
792 "drd_trace_load_8",
793 VG_(fnptr_to_fnentry)(drd_trace_load_8),
794 argv);
795 break;
796 default:
797 size_expr = mkIRExpr_HWord(size);
798 argv = mkIRExprVec_2(addr_expr, size_expr);
799 di = unsafeIRDirty_0_N(/*regparms*/2,
800 "drd_trace_load",
801 VG_(fnptr_to_fnentry)(drd_trace_load),
802 argv);
803 break;
804 }
805 addStmtToIRSB(bb, IRStmt_Dirty(di));
barta79df6e2008-03-14 17:07:51 +0000806}
807
808static void instrument_store(IRSB* const bb,
bart3772a982008-03-15 08:11:03 +0000809 IRExpr* const addr_expr,
810 const HWord size)
barta79df6e2008-03-14 17:07:51 +0000811{
bart3772a982008-03-15 08:11:03 +0000812 IRExpr* size_expr;
813 IRExpr** argv;
814 IRDirty* di;
barta79df6e2008-03-14 17:07:51 +0000815
bart3772a982008-03-15 08:11:03 +0000816 switch (size)
817 {
818 case 1:
819 argv = mkIRExprVec_1(addr_expr);
820 di = unsafeIRDirty_0_N(/*regparms*/1,
821 "drd_trace_store_1",
822 VG_(fnptr_to_fnentry)(drd_trace_store_1),
823 argv);
824 break;
825 case 2:
826 argv = mkIRExprVec_1(addr_expr);
827 di = unsafeIRDirty_0_N(/*regparms*/1,
828 "drd_trace_store_2",
829 VG_(fnptr_to_fnentry)(drd_trace_store_2),
830 argv);
831 break;
832 case 4:
833 argv = mkIRExprVec_1(addr_expr);
834 di = unsafeIRDirty_0_N(/*regparms*/1,
835 "drd_trace_store_4",
836 VG_(fnptr_to_fnentry)(drd_trace_store_4),
837 argv);
838 break;
839 case 8:
840 argv = mkIRExprVec_1(addr_expr);
841 di = unsafeIRDirty_0_N(/*regparms*/1,
842 "drd_trace_store_8",
843 VG_(fnptr_to_fnentry)(drd_trace_store_8),
844 argv);
845 break;
846 default:
847 size_expr = mkIRExpr_HWord(size);
848 argv = mkIRExprVec_2(addr_expr, size_expr);
849 di = unsafeIRDirty_0_N(/*regparms*/2,
850 "drd_trace_store",
851 VG_(fnptr_to_fnentry)(drd_trace_store),
852 argv);
853 break;
854 }
855 addStmtToIRSB(bb, IRStmt_Dirty(di));
barta79df6e2008-03-14 17:07:51 +0000856}
857
sewardjaf44c822007-11-25 14:01:38 +0000858static
859IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000860 IRSB* const bb_in,
861 VexGuestLayout* const layout,
862 VexGuestExtents* const vge,
863 IRType const gWordTy,
864 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000865{
bart3772a982008-03-15 08:11:03 +0000866 IRDirty* di;
867 Int i;
868 IRSB* bb;
869 IRExpr** argv;
870 Bool instrument = True;
871 Bool bus_locked = False;
sewardjaf44c822007-11-25 14:01:38 +0000872
bart3772a982008-03-15 08:11:03 +0000873 /* Set up BB */
874 bb = emptyIRSB();
875 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
876 bb->next = deepCopyIRExpr(bb_in->next);
877 bb->jumpkind = bb_in->jumpkind;
sewardjaf44c822007-11-25 14:01:38 +0000878
bart3772a982008-03-15 08:11:03 +0000879 for (i = 0; i < bb_in->stmts_used; i++)
880 {
881 IRStmt* const st = bb_in->stmts[i];
882 tl_assert(st);
883 if (st->tag == Ist_NoOp)
884 continue;
sewardjaf44c822007-11-25 14:01:38 +0000885
bart3772a982008-03-15 08:11:03 +0000886 switch (st->tag)
887 {
888 case Ist_IMark:
889 instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
890 != Vg_SectPLT;
891 break;
892
893 case Ist_MBE:
894 switch (st->Ist.MBE.event)
sewardjaf44c822007-11-25 14:01:38 +0000895 {
bart3772a982008-03-15 08:11:03 +0000896 case Imbe_Fence:
897 break; /* not interesting */
898 case Imbe_BusLock:
899 tl_assert(! bus_locked);
900 bus_locked = True;
901 break;
902 case Imbe_BusUnlock:
903 tl_assert(bus_locked);
904 bus_locked = False;
905 break;
sewardjaf44c822007-11-25 14:01:38 +0000906 default:
bart3772a982008-03-15 08:11:03 +0000907 tl_assert(0);
sewardjaf44c822007-11-25 14:01:38 +0000908 }
bart3772a982008-03-15 08:11:03 +0000909 addStmtToIRSB(bb, st);
910 break;
sewardjaf44c822007-11-25 14:01:38 +0000911
bart3772a982008-03-15 08:11:03 +0000912 case Ist_Store:
913 if (instrument && ! bus_locked)
914 {
915 instrument_store(bb,
916 st->Ist.Store.addr,
917 sizeofIRType(typeOfIRExpr(bb->tyenv,
918 st->Ist.Store.data)));
919 }
920 addStmtToIRSB(bb, st);
921 break;
barta47b3512008-03-07 17:22:26 +0000922
bart3772a982008-03-15 08:11:03 +0000923 case Ist_WrTmp:
924 if (instrument)
925 {
926 const IRExpr* const data = st->Ist.WrTmp.data;
927 if (data->tag == Iex_Load)
928 {
929 instrument_load(bb,
930 data->Iex.Load.addr,
931 sizeofIRType(data->Iex.Load.ty));
932 }
933 }
934 addStmtToIRSB(bb, st);
935 break;
936
937 case Ist_Dirty:
938 if (instrument)
939 {
940 IRDirty* d = st->Ist.Dirty.details;
941 IREffect const mFx = d->mFx;
942 switch (mFx) {
943 case Ifx_None:
944 break;
945 case Ifx_Read:
946 case Ifx_Write:
947 case Ifx_Modify:
948 tl_assert(d->mAddr);
949 tl_assert(d->mSize > 0);
950 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
951 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
952 di = unsafeIRDirty_0_N(
953 /*regparms*/2,
954 "drd_trace_load",
955 VG_(fnptr_to_fnentry)(drd_trace_load),
956 argv);
957 addStmtToIRSB(bb, IRStmt_Dirty(di));
958 }
959 if ((mFx == Ifx_Write || mFx == Ifx_Modify)
960 && ! bus_locked)
961 {
962 di = unsafeIRDirty_0_N(
963 /*regparms*/2,
964 "drd_trace_store",
965 VG_(fnptr_to_fnentry)(drd_trace_store),
966 argv);
967 addStmtToIRSB(bb, IRStmt_Dirty(di));
968 }
969 break;
970 default:
971 tl_assert(0);
972 }
973 }
974 addStmtToIRSB(bb, st);
975 break;
976
977 default:
978 addStmtToIRSB(bb, st);
979 break;
980 }
981 }
982
983 tl_assert(! bus_locked);
984
985 return bb;
sewardjaf44c822007-11-25 14:01:38 +0000986}
987
sewardjaf44c822007-11-25 14:01:38 +0000988static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
989{
bart3772a982008-03-15 08:11:03 +0000990 tl_assert(tid == VG_(get_running_tid)());
991 thread_set_vg_running_tid(tid);
sewardjaf44c822007-11-25 14:01:38 +0000992}
993
994static
995void drd_fini(Int exitcode)
996{
bart3772a982008-03-15 08:11:03 +0000997 // thread_print_all();
998 if (VG_(clo_verbosity) > 1 || drd_print_stats)
999 {
1000 VG_(message)(Vg_DebugMsg,
1001 " thread: %lld context switches"
1002 " / %lld updates of the danger set",
1003 thread_get_context_switch_count(),
1004 thread_get_update_danger_set_count());
1005 VG_(message)(Vg_DebugMsg,
1006 " segments: %lld total, %lld max, %lld discard points",
bart7102f102008-03-17 17:37:53 +00001007 sg_get_created_segments_count(),
1008 sg_get_max_alive_segments_count(),
bart3772a982008-03-15 08:11:03 +00001009 thread_get_discard_ordered_segments_count());
1010 VG_(message)(Vg_DebugMsg,
1011 " bitmaps: %lld / %lld bitmaps were allocated"
1012 " and %lld / %lld for danger set updates",
1013 bm_get_bitmap_creation_count(),
1014 bm_get_bitmap2_creation_count(),
1015 thread_get_danger_set_bitmap_creation_count(),
1016 thread_get_danger_set_bitmap2_creation_count());
1017 VG_(message)(Vg_DebugMsg,
1018 " mutex: %lld non-recursive lock/unlock events",
1019 get_mutex_lock_count());
1020 drd_print_malloc_stats();
1021 }
sewardjaf44c822007-11-25 14:01:38 +00001022}
1023
sewardjaf44c822007-11-25 14:01:38 +00001024static
1025void drd_pre_clo_init(void)
1026{
bart3772a982008-03-15 08:11:03 +00001027 // Basic tool stuff.
sewardjaf44c822007-11-25 14:01:38 +00001028
bart3772a982008-03-15 08:11:03 +00001029 VG_(details_name) ("exp-drd");
1030 VG_(details_version) (NULL);
1031 VG_(details_description) ("a data race detector");
1032 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
1033 " by Bart Van Assche.");
1034 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardjaf44c822007-11-25 14:01:38 +00001035
bart3772a982008-03-15 08:11:03 +00001036 VG_(basic_tool_funcs) (drd_post_clo_init,
1037 drd_instrument,
1038 drd_fini);
sewardjaf44c822007-11-25 14:01:38 +00001039
bart3772a982008-03-15 08:11:03 +00001040 // Command line stuff.
1041 VG_(needs_command_line_options)(drd_process_cmd_line_option,
1042 drd_print_usage,
1043 drd_print_debug_usage);
sewardjaf44c822007-11-25 14:01:38 +00001044
bart3772a982008-03-15 08:11:03 +00001045 // Error handling.
1046 drd_register_error_handlers();
sewardjaf44c822007-11-25 14:01:38 +00001047
bart3772a982008-03-15 08:11:03 +00001048 // Core event tracking.
1049 VG_(track_pre_mem_read) (drd_pre_mem_read);
1050 VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz);
1051 VG_(track_post_mem_write) (drd_post_mem_write);
1052 VG_(track_new_mem_brk) (drd_start_using_mem);
1053 VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms);
1054 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
1055 VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
1056 VG_(track_new_mem_startup) (drd_start_using_mem_w_perms);
1057 VG_(track_die_mem_brk) (drd_stop_using_mem);
1058 VG_(track_die_mem_munmap) (drd_stop_using_mem);
1059 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
1060 VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
1061 VG_(track_start_client_code) (drd_start_client_code);
1062 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
1063 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
1064 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
sewardjaf44c822007-11-25 14:01:38 +00001065
bart3772a982008-03-15 08:11:03 +00001066 // Other stuff.
bart3772a982008-03-15 08:11:03 +00001067 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
sewardjaf44c822007-11-25 14:01:38 +00001068
bart3772a982008-03-15 08:11:03 +00001069 drd_clientreq_init();
sewardjaf44c822007-11-25 14:01:38 +00001070
bart3772a982008-03-15 08:11:03 +00001071 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +00001072
bart3772a982008-03-15 08:11:03 +00001073 clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +00001074}
1075
1076
1077VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)