blob: fc9fc5c812c018380adb8f20d37933f0fa3ff490 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
sewardj85642922008-01-14 11:54:56 +000026#include "drd_barrier.h"
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_clientreq.h"
bart4bb53d82008-02-28 19:06:34 +000028#include "drd_clientobj.h"
sewardjaf44c822007-11-25 14:01:38 +000029#include "drd_cond.h"
30#include "drd_error.h"
31#include "drd_malloc_wrappers.h"
32#include "drd_mutex.h"
bart5bd9f2d2008-03-03 20:31:58 +000033#include "drd_rwlock.h"
sewardjaf44c822007-11-25 14:01:38 +000034#include "drd_segment.h"
sewardj85642922008-01-14 11:54:56 +000035#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000036#include "drd_suppression.h"
37#include "drd_thread.h"
38#include "drd_track.h"
39#include "drd_vc.h"
sewardj721ad7b2007-11-30 08:30:29 +000040#include "priv_drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000041#include "pub_drd_bitmap.h"
sewardjaf44c822007-11-25 14:01:38 +000042#include "pub_tool_basics.h"
43#include "pub_tool_debuginfo.h" // VG_(describe_IP)()
44#include "pub_tool_libcassert.h" // tl_assert()
45#include "pub_tool_libcbase.h" // VG_(strcmp)
46#include "pub_tool_libcprint.h" // VG_(printf)
sewardj85642922008-01-14 11:54:56 +000047#include "pub_tool_vki.h" // Must be included before pub_tool_libcproc
sewardjaf44c822007-11-25 14:01:38 +000048#include "pub_tool_libcproc.h"
49#include "pub_tool_machine.h"
50#include "pub_tool_options.h" // command line options
bart72b751c2008-03-01 13:44:24 +000051#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
sewardjaf44c822007-11-25 14:01:38 +000052#include "pub_tool_tooliface.h"
53
54
sewardjaf44c822007-11-25 14:01:38 +000055// Function declarations.
56
57static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
sewardjaf44c822007-11-25 14:01:38 +000058
59
60// Local variables.
61
62static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000063static Bool drd_trace_fork_join = False;
sewardj85642922008-01-14 11:54:56 +000064static Bool drd_trace_mem = False;
sewardjaf44c822007-11-25 14:01:38 +000065static Addr drd_trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000066
67
68//
69// Implement the needs_command_line_options for drd.
70//
71
72static Bool drd_process_cmd_line_option(Char* arg)
73{
bart3772a982008-03-15 08:11:03 +000074 Bool trace_barrier = False;
75 Bool trace_clientobj = False;
76 Bool trace_cond = False;
77 Bool trace_csw = False;
78 Bool trace_danger_set = False;
79 Bool trace_mutex = False;
80 Bool trace_rwlock = False;
81 Bool trace_segment = False;
82 Bool trace_semaphore = False;
83 Bool trace_suppression = False;
84 Char* trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000085
bart3772a982008-03-15 08:11:03 +000086 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
87 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
88 else VG_BOOL_CLO(arg, "--trace-clientobj", trace_clientobj)
89 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
90 else VG_BOOL_CLO(arg, "--trace-csw", trace_csw)
91 else VG_BOOL_CLO(arg, "--trace-danger-set", trace_danger_set)
92 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
93 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
94 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
95 else VG_BOOL_CLO(arg, "--trace-rwlock", trace_rwlock)
96 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
97 else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
98 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
99 else VG_STR_CLO (arg, "--trace-address", trace_address)
100 else
101 return False;
sewardjaf44c822007-11-25 14:01:38 +0000102
bart3772a982008-03-15 08:11:03 +0000103 if (trace_address)
104 {
105 drd_trace_address = VG_(strtoll16)(trace_address, 0);
106 }
107 if (trace_barrier)
108 barrier_set_trace(trace_barrier);
109 if (trace_clientobj)
110 clientobj_set_trace(trace_clientobj);
111 if (trace_cond)
112 cond_set_trace(trace_cond);
113 if (trace_csw)
114 thread_trace_context_switches(trace_csw);
115 if (trace_danger_set)
116 thread_trace_danger_set(trace_danger_set);
117 if (trace_mutex)
118 mutex_set_trace(trace_mutex);
119 if (trace_rwlock)
120 rwlock_set_trace(trace_rwlock);
121 if (trace_segment)
122 sg_set_trace(trace_segment);
123 if (trace_semaphore)
124 semaphore_set_trace(trace_semaphore);
125 if (trace_suppression)
126 suppression_set_trace(trace_suppression);
sewardjaf44c822007-11-25 14:01:38 +0000127
bart3772a982008-03-15 08:11:03 +0000128 return True;
sewardjaf44c822007-11-25 14:01:38 +0000129}
130
131static void drd_print_usage(void)
132{
bart3772a982008-03-15 08:11:03 +0000133 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
134 "\n"
135 " --trace-fork-join=no|yes Trace all thread creation and join"
136 " activity\n"
137 " --trace-mutex=no|yes Trace all mutex activity\n"
138 " --trace-segment=no|yes Trace segment actions\n"
139 );
sewardjaf44c822007-11-25 14:01:38 +0000140}
141
142static void drd_print_debug_usage(void)
143{
144}
145
146
147//
148// Implements the thread-related core callbacks.
149//
150
barta79df6e2008-03-14 17:07:51 +0000151static void drd_trace_mem_access(const Addr addr, const SizeT size,
152 const BmAccessTypeT access_type)
153{
bart3772a982008-03-15 08:11:03 +0000154 char vc[80];
155 vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid()));
156 VG_(message)(Vg_UserMsg,
157 "%s 0x%lx size %ld %s (vg %d / drd %d / vc %s)",
bartd5765912008-03-16 08:40:55 +0000158 access_type == eLoad
159 ? "load "
160 : access_type == eStore
161 ? "store"
162 : access_type == eStart
163 ? "start"
164 : access_type == eEnd
165 ? "end"
166 : "????",
bart3772a982008-03-15 08:11:03 +0000167 addr,
168 size,
169 thread_get_name(thread_get_running_tid()),
170 VG_(get_running_tid)(),
171 thread_get_running_tid(),
172 vc);
173 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
174 VG_(clo_backtrace_size));
175 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
176 == VG_(get_running_tid)());
barta79df6e2008-03-14 17:07:51 +0000177}
178
179static void drd_report_race(const Addr addr, const SizeT size,
180 const BmAccessTypeT access_type)
181{
bart49c3a112008-03-15 10:28:36 +0000182 DataRaceErrInfo drei;
183
bart7a282142008-03-15 08:34:23 +0000184 if (drd_is_suppressed(addr, addr + size))
185 return;
186
bart3772a982008-03-15 08:11:03 +0000187 drei.tid = VG_(get_running_tid)();
188 drei.addr = addr;
189 drei.size = size;
190 drei.access_type = access_type;
191 VG_(maybe_record_error)(VG_(get_running_tid)(),
192 DataRaceErr,
193 VG_(get_IP)(VG_(get_running_tid)()),
194 "Conflicting accesses",
195 &drei);
barta79df6e2008-03-14 17:07:51 +0000196}
197
198static VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
sewardjaf44c822007-11-25 14:01:38 +0000199{
bart3772a982008-03-15 08:11:03 +0000200 Segment* sg;
sewardjaf44c822007-11-25 14:01:38 +0000201
bartf00a85b2008-03-13 18:49:23 +0000202#if 0
bart3772a982008-03-15 08:11:03 +0000203 /* The assert below has been commented out because of performance reasons.*/
204 tl_assert(thread_get_running_tid()
205 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bartf00a85b2008-03-13 18:49:23 +0000206#endif
sewardjaf44c822007-11-25 14:01:38 +0000207
bart3772a982008-03-15 08:11:03 +0000208 if (! running_thread_is_recording())
209 return;
bart0268dfa2008-03-11 20:10:21 +0000210
bart3772a982008-03-15 08:11:03 +0000211 if (drd_trace_mem || (addr == drd_trace_address))
212 {
213 drd_trace_mem_access(addr, size, eLoad);
214 }
215 sg = running_thread_get_segment();
216 bm_access_range_load(sg->bm, addr, addr + size);
bart7a282142008-03-15 08:34:23 +0000217 if (bm_load_has_conflict_with(thread_get_danger_set(), addr, addr + size))
bart3772a982008-03-15 08:11:03 +0000218 {
219 drd_report_race(addr, size, eLoad);
220 }
barta79df6e2008-03-14 17:07:51 +0000221}
222
223static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
224{
bart3772a982008-03-15 08:11:03 +0000225 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000226
bart3772a982008-03-15 08:11:03 +0000227 if (! running_thread_is_recording())
228 return;
barta79df6e2008-03-14 17:07:51 +0000229
bart3772a982008-03-15 08:11:03 +0000230 if (drd_trace_mem || (addr == drd_trace_address))
231 {
232 drd_trace_mem_access(addr, 1, eLoad);
233 }
234 sg = running_thread_get_segment();
235 bm_access_load_1(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000236 if (bm_load_1_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000237 {
238 drd_report_race(addr, 1, eLoad);
239 }
barta79df6e2008-03-14 17:07:51 +0000240}
241
242static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
243{
bart3772a982008-03-15 08:11:03 +0000244 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000245
bart3772a982008-03-15 08:11:03 +0000246 if (! running_thread_is_recording())
247 return;
barta79df6e2008-03-14 17:07:51 +0000248
bart3772a982008-03-15 08:11:03 +0000249 if (drd_trace_mem || (addr == drd_trace_address))
250 {
251 drd_trace_mem_access(addr, 2, eLoad);
252 }
253 sg = running_thread_get_segment();
254 bm_access_load_2(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000255 if (bm_load_2_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000256 {
257 drd_report_race(addr, 2, eLoad);
258 }
barta79df6e2008-03-14 17:07:51 +0000259}
260
261static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
262{
bart3772a982008-03-15 08:11:03 +0000263 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000264
bart3772a982008-03-15 08:11:03 +0000265 if (! running_thread_is_recording())
266 return;
barta79df6e2008-03-14 17:07:51 +0000267
bart3772a982008-03-15 08:11:03 +0000268 if (drd_trace_mem || (addr == drd_trace_address))
269 {
270 drd_trace_mem_access(addr, 4, eLoad);
271 }
272 sg = running_thread_get_segment();
273 bm_access_load_4(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000274 if (bm_load_4_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000275 {
276 drd_report_race(addr, 4, eLoad);
277 }
barta79df6e2008-03-14 17:07:51 +0000278}
279
280static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
281{
bart3772a982008-03-15 08:11:03 +0000282 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000283
bart3772a982008-03-15 08:11:03 +0000284 if (! running_thread_is_recording())
285 return;
barta79df6e2008-03-14 17:07:51 +0000286
bart3772a982008-03-15 08:11:03 +0000287 if (drd_trace_mem || (addr == drd_trace_address))
288 {
289 drd_trace_mem_access(addr, 8, eLoad);
290 }
291 sg = running_thread_get_segment();
292 bm_access_load_8(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000293 if (bm_load_8_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000294 {
295 drd_report_race(addr, 8, eLoad);
296 }
sewardjaf44c822007-11-25 14:01:38 +0000297}
298
299static
300VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
301{
bart3772a982008-03-15 08:11:03 +0000302 Segment* sg;
sewardjaf44c822007-11-25 14:01:38 +0000303
bartf00a85b2008-03-13 18:49:23 +0000304#if 0
bart3772a982008-03-15 08:11:03 +0000305 /* The assert below has been commented out because of performance reasons.*/
306 tl_assert(thread_get_running_tid()
307 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
bartf00a85b2008-03-13 18:49:23 +0000308#endif
sewardjaf44c822007-11-25 14:01:38 +0000309
bart3772a982008-03-15 08:11:03 +0000310 if (! running_thread_is_recording())
311 return;
bart0268dfa2008-03-11 20:10:21 +0000312
bart3772a982008-03-15 08:11:03 +0000313 if (drd_trace_mem || (addr == drd_trace_address))
314 {
315 drd_trace_mem_access(addr, size, eStore);
316 }
317 sg = running_thread_get_segment();
318 bm_access_range_store(sg->bm, addr, addr + size);
bart7a282142008-03-15 08:34:23 +0000319 if (bm_store_has_conflict_with(thread_get_danger_set(), addr, addr + size))
bart3772a982008-03-15 08:11:03 +0000320 {
321 drd_report_race(addr, size, eStore);
322 }
barta79df6e2008-03-14 17:07:51 +0000323}
324
325static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
326{
bart3772a982008-03-15 08:11:03 +0000327 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000328
bart3772a982008-03-15 08:11:03 +0000329 if (! running_thread_is_recording())
330 return;
barta79df6e2008-03-14 17:07:51 +0000331
bart3772a982008-03-15 08:11:03 +0000332 if (drd_trace_mem || (addr == drd_trace_address))
333 {
334 drd_trace_mem_access(addr, 1, eStore);
335 }
336 sg = running_thread_get_segment();
337 bm_access_store_1(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000338 if (bm_store_1_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000339 {
340 drd_report_race(addr, 1, eStore);
341 }
barta79df6e2008-03-14 17:07:51 +0000342}
343
344static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
345{
bart3772a982008-03-15 08:11:03 +0000346 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000347
bart3772a982008-03-15 08:11:03 +0000348 if (! running_thread_is_recording())
349 return;
barta79df6e2008-03-14 17:07:51 +0000350
bart3772a982008-03-15 08:11:03 +0000351 if (drd_trace_mem || (addr == drd_trace_address))
352 {
353 drd_trace_mem_access(addr, 2, eStore);
354 }
355 sg = running_thread_get_segment();
356 bm_access_store_2(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000357 if (bm_store_2_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000358 {
359 drd_report_race(addr, 2, eStore);
360 }
barta79df6e2008-03-14 17:07:51 +0000361}
362
363static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
364{
bart3772a982008-03-15 08:11:03 +0000365 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000366
bart3772a982008-03-15 08:11:03 +0000367 if (! running_thread_is_recording())
368 return;
barta79df6e2008-03-14 17:07:51 +0000369
bart3772a982008-03-15 08:11:03 +0000370 if (drd_trace_mem || (addr == drd_trace_address))
371 {
372 drd_trace_mem_access(addr, 4, eStore);
373 }
374 sg = running_thread_get_segment();
375 bm_access_store_4(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000376 if (bm_store_4_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000377 {
378 drd_report_race(addr, 4, eStore);
379 }
barta79df6e2008-03-14 17:07:51 +0000380}
381
382static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
383{
bart3772a982008-03-15 08:11:03 +0000384 Segment* sg;
barta79df6e2008-03-14 17:07:51 +0000385
bart3772a982008-03-15 08:11:03 +0000386 if (! running_thread_is_recording())
387 return;
barta79df6e2008-03-14 17:07:51 +0000388
bart3772a982008-03-15 08:11:03 +0000389 if (drd_trace_mem || (addr == drd_trace_address))
390 {
391 drd_trace_mem_access(addr, 8, eStore);
392 }
393 sg = running_thread_get_segment();
394 bm_access_store_8(sg->bm, addr);
bart7a282142008-03-15 08:34:23 +0000395 if (bm_store_8_has_conflict_with(thread_get_danger_set(), addr))
bart3772a982008-03-15 08:11:03 +0000396 {
397 drd_report_race(addr, 8, eStore);
398 }
sewardjaf44c822007-11-25 14:01:38 +0000399}
400
401static void drd_pre_mem_read(const CorePart part,
402 const ThreadId tid,
403 Char* const s,
404 const Addr a,
405 const SizeT size)
406{
bart3772a982008-03-15 08:11:03 +0000407 if (size > 0)
408 {
409 drd_trace_load(a, size);
410 }
sewardjaf44c822007-11-25 14:01:38 +0000411}
412
bart5e85d262008-03-01 10:49:37 +0000413static void drd_pre_mem_read_asciiz(const CorePart part,
414 const ThreadId tid,
415 Char* const s,
416 const Addr a)
417{
bart3772a982008-03-15 08:11:03 +0000418 const char* p = (void*)a;
419 SizeT size = 0;
bart5e85d262008-03-01 10:49:37 +0000420
bart3772a982008-03-15 08:11:03 +0000421 /* Note: the expression '*p' reads client memory and may crash if the */
422 /* client provided an invalid pointer ! */
423 while (*p)
424 {
425 p++;
426 size++;
427 }
428 // To do: find out what a reasonable upper limit on 'size' is.
429 tl_assert(size < 4096);
430 if (size > 0)
431 {
432 drd_trace_load(a, size);
433 }
bart5e85d262008-03-01 10:49:37 +0000434}
435
sewardjaf44c822007-11-25 14:01:38 +0000436static void drd_post_mem_write(const CorePart part,
437 const ThreadId tid,
438 const Addr a,
439 const SizeT size)
440{
bart3772a982008-03-15 08:11:03 +0000441 thread_set_vg_running_tid(VG_(get_running_tid)());
442 if (size > 0)
443 {
444 drd_trace_store(a, size);
445 }
sewardjaf44c822007-11-25 14:01:38 +0000446}
447
bart5e85d262008-03-01 10:49:37 +0000448static void drd_start_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000449{
bart3772a982008-03-15 08:11:03 +0000450 const Addr a2 = a1 + len;
bart5e85d262008-03-01 10:49:37 +0000451
bart3772a982008-03-15 08:11:03 +0000452 tl_assert(a1 < a2);
bart5e85d262008-03-01 10:49:37 +0000453
bart3772a982008-03-15 08:11:03 +0000454 if (a1 <= drd_trace_address && drd_trace_address < a2)
455 {
bartd5765912008-03-16 08:40:55 +0000456 drd_trace_mem_access(a1, len, eStart);
bart3772a982008-03-15 08:11:03 +0000457 }
sewardjaf44c822007-11-25 14:01:38 +0000458}
459
bart5e85d262008-03-01 10:49:37 +0000460static void drd_stop_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000461{
bart3772a982008-03-15 08:11:03 +0000462 const Addr a2 = a1 + len;
bart5e85d262008-03-01 10:49:37 +0000463
bart3772a982008-03-15 08:11:03 +0000464 tl_assert(a1 < a2);
bart5e85d262008-03-01 10:49:37 +0000465
bart3772a982008-03-15 08:11:03 +0000466 if (a1 <= drd_trace_address && drd_trace_address < a2)
467 {
bartd5765912008-03-16 08:40:55 +0000468 drd_trace_mem_access(a1, len, eStart);
bart3772a982008-03-15 08:11:03 +0000469 }
470 thread_stop_using_mem(a1, a2);
471 clientobj_stop_using_mem(a1, a2);
472 drd_suppression_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000473}
474
bart5e85d262008-03-01 10:49:37 +0000475static
476void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
477 const Bool rr, const Bool ww, const Bool xx)
478{
bartd5765912008-03-16 08:40:55 +0000479 thread_set_vg_running_tid(VG_(get_running_tid)());
480
bart3772a982008-03-15 08:11:03 +0000481 drd_start_using_mem(a, len);
bart5e85d262008-03-01 10:49:37 +0000482}
483
sewardjaf44c822007-11-25 14:01:38 +0000484/* Called by the core when the stack of a thread grows, to indicate that */
485/* the addresses in range [ a, a + len [ may now be used by the client. */
486/* Assumption: stacks grow downward. */
487static void drd_start_using_mem_stack(const Addr a, const SizeT len)
488{
bartd5765912008-03-16 08:40:55 +0000489 thread_set_stack_min(thread_get_running_tid(), a);
bart3772a982008-03-15 08:11:03 +0000490 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000491}
492
493/* Called by the core when the stack of a thread shrinks, to indicate that */
494/* the addresses [ a, a + len [ are no longer accessible for the client. */
495/* Assumption: stacks grow downward. */
496static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
497{
bartd5765912008-03-16 08:40:55 +0000498 thread_set_stack_min(thread_get_running_tid(), a + len);
bart3772a982008-03-15 08:11:03 +0000499 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000500}
501
bart5e85d262008-03-01 10:49:37 +0000502static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000503{
bartd5765912008-03-16 08:40:55 +0000504 thread_set_vg_running_tid(VG_(get_running_tid)());
bart3772a982008-03-15 08:11:03 +0000505 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000506}
507
bart5e85d262008-03-01 10:49:37 +0000508static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000509{
bart3772a982008-03-15 08:11:03 +0000510 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000511}
512
513static
514void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
515{
bart3772a982008-03-15 08:11:03 +0000516 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
517 tl_assert(created != VG_INVALID_THREADID);
518 thread_pre_create(drd_creator, created);
519 if (IsValidDrdThreadId(drd_creator))
520 {
521 thread_new_segment(drd_creator);
522 }
523 if (drd_trace_fork_join)
524 {
525 VG_(message)(Vg_DebugMsg,
526 "drd_pre_thread_create creator = %d/%d, created = %d",
527 creator, drd_creator, created);
528 }
sewardjaf44c822007-11-25 14:01:38 +0000529}
530
531/* Called by Valgrind's core before any loads or stores are performed on */
532/* the context of thread "created". At startup, this function is called */
533/* with arguments (0,1). */
534static
535void drd_post_thread_create(const ThreadId created)
536{
bart3772a982008-03-15 08:11:03 +0000537 const DrdThreadId drd_created = thread_post_create(created);
538 tl_assert(created != VG_INVALID_THREADID);
539 if (drd_trace_fork_join)
540 {
541 VG_(message)(Vg_DebugMsg,
542 "drd_post_thread_create created = %d/%d",
543 created, drd_created);
544 }
sewardjaf44c822007-11-25 14:01:38 +0000545}
546
547/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
548/* after thread drd_joiner joined thread drd_joinee. */
549void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
550{
bart3772a982008-03-15 08:11:03 +0000551 tl_assert(IsValidDrdThreadId(drd_joiner));
552 tl_assert(IsValidDrdThreadId(drd_joinee));
553 thread_new_segment(drd_joinee);
554 thread_combine_vc(drd_joiner, drd_joinee);
555 thread_new_segment(drd_joiner);
sewardjaf44c822007-11-25 14:01:38 +0000556
bart3772a982008-03-15 08:11:03 +0000557 if (drd_trace_fork_join)
558 {
559 char msg[256];
560 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
561 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
562 VG_(snprintf)(msg, sizeof(msg),
563 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
564 joiner, drd_joiner, joinee, drd_joinee);
565 if (joiner)
566 {
567 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
568 ", new vc: ");
569 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
570 thread_get_vc(drd_joiner));
571 }
572 VG_(message)(Vg_DebugMsg, msg);
573 }
sewardjaf44c822007-11-25 14:01:38 +0000574
bart3772a982008-03-15 08:11:03 +0000575 thread_delete(drd_joinee);
576 mutex_thread_delete(drd_joinee);
577 cond_thread_delete(drd_joinee);
578 semaphore_thread_delete(drd_joinee);
579 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000580}
581
bart5bd9f2d2008-03-03 20:31:58 +0000582void drd_trace_addr(const Addr addr)
583{
bart3772a982008-03-15 08:11:03 +0000584 drd_trace_address = addr;
bart5bd9f2d2008-03-03 20:31:58 +0000585}
586
sewardjaf44c822007-11-25 14:01:38 +0000587/* Called after a thread has performed its last memory access. */
588static void drd_thread_finished(ThreadId tid)
589{
bart3772a982008-03-15 08:11:03 +0000590 DrdThreadId drd_tid;
sewardj85642922008-01-14 11:54:56 +0000591
bart3772a982008-03-15 08:11:03 +0000592 tl_assert(VG_(get_running_tid)() == tid);
sewardj85642922008-01-14 11:54:56 +0000593
bart3772a982008-03-15 08:11:03 +0000594 drd_tid = VgThreadIdToDrdThreadId(tid);
595 if (drd_trace_fork_join)
596 {
597 VG_(message)(Vg_DebugMsg,
598 "drd_thread_finished tid = %d/%d%s",
599 tid,
600 drd_tid,
601 thread_get_joinable(drd_tid)
602 ? ""
603 : " (which is a detached thread)");
sewardjaf44c822007-11-25 14:01:38 +0000604
bart3772a982008-03-15 08:11:03 +0000605 }
606 thread_finished(drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000607}
608
bart0268dfa2008-03-11 20:10:21 +0000609void drd_pre_mutex_init(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000610{
bart3772a982008-03-15 08:11:03 +0000611 mutex_init(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000612}
613
sewardj347eeba2008-01-21 14:19:07 +0000614void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000615{
bart3772a982008-03-15 08:11:03 +0000616 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000617}
618
bart0268dfa2008-03-11 20:10:21 +0000619void drd_pre_mutex_lock(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000620{
bart3772a982008-03-15 08:11:03 +0000621 mutex_pre_lock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000622}
623
bart00344642008-03-01 15:27:41 +0000624void drd_post_mutex_lock(const Addr mutex, const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000625{
bart3772a982008-03-15 08:11:03 +0000626 mutex_post_lock(mutex, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000627}
628
bart00344642008-03-01 15:27:41 +0000629void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000630{
bart3772a982008-03-15 08:11:03 +0000631 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000632}
633
bart0268dfa2008-03-11 20:10:21 +0000634void drd_pre_cond_init(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000635{
bart3772a982008-03-15 08:11:03 +0000636 cond_pre_init(cond);
sewardjaf44c822007-11-25 14:01:38 +0000637}
638
bart72b751c2008-03-01 13:44:24 +0000639void drd_post_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000640{
bart3772a982008-03-15 08:11:03 +0000641 cond_post_destroy(cond);
sewardjaf44c822007-11-25 14:01:38 +0000642}
643
bart0268dfa2008-03-11 20:10:21 +0000644void drd_semaphore_init(const Addr semaphore,
sewardj85642922008-01-14 11:54:56 +0000645 const Word pshared, const Word value)
646{
bart3772a982008-03-15 08:11:03 +0000647 semaphore_init(semaphore, pshared, value);
sewardj85642922008-01-14 11:54:56 +0000648}
649
650void drd_semaphore_destroy(const Addr semaphore)
651{
bart3772a982008-03-15 08:11:03 +0000652 semaphore_destroy(semaphore);
sewardj85642922008-01-14 11:54:56 +0000653}
654
bart0268dfa2008-03-11 20:10:21 +0000655void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore)
sewardj85642922008-01-14 11:54:56 +0000656{
bart3772a982008-03-15 08:11:03 +0000657 semaphore_pre_wait(semaphore);
bart28230a32008-02-29 17:27:03 +0000658}
659
660void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
661 const Bool waited)
662{
bart3772a982008-03-15 08:11:03 +0000663 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000664}
665
bart0268dfa2008-03-11 20:10:21 +0000666void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore)
sewardj85642922008-01-14 11:54:56 +0000667{
bart3772a982008-03-15 08:11:03 +0000668 semaphore_pre_post(tid, semaphore);
sewardj85642922008-01-14 11:54:56 +0000669}
670
671void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
bart0268dfa2008-03-11 20:10:21 +0000672 const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000673{
bart3772a982008-03-15 08:11:03 +0000674 semaphore_post_post(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000675}
676
677
bart0268dfa2008-03-11 20:10:21 +0000678void drd_barrier_init(const Addr barrier,
679 const BarrierT barrier_type, const Word count,
680 const Bool reinitialization)
sewardj85642922008-01-14 11:54:56 +0000681{
bart3772a982008-03-15 08:11:03 +0000682 barrier_init(barrier, barrier_type, count, reinitialization);
sewardj85642922008-01-14 11:54:56 +0000683}
684
bart0268dfa2008-03-11 20:10:21 +0000685void drd_barrier_destroy(const Addr barrier, const BarrierT barrier_type)
sewardj85642922008-01-14 11:54:56 +0000686{
bart3772a982008-03-15 08:11:03 +0000687 barrier_destroy(barrier, barrier_type);
sewardj85642922008-01-14 11:54:56 +0000688}
689
bart0268dfa2008-03-11 20:10:21 +0000690void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier,
691 const BarrierT barrier_type)
sewardj85642922008-01-14 11:54:56 +0000692{
bart3772a982008-03-15 08:11:03 +0000693 barrier_pre_wait(tid, barrier, barrier_type);
sewardj85642922008-01-14 11:54:56 +0000694}
695
696void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
bart0268dfa2008-03-11 20:10:21 +0000697 const BarrierT barrier_type, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000698{
bart3772a982008-03-15 08:11:03 +0000699 barrier_post_wait(tid, barrier, barrier_type, waited);
sewardj85642922008-01-14 11:54:56 +0000700}
701
sewardjaf44c822007-11-25 14:01:38 +0000702
703//
704// Implementation of the tool interface.
705//
706
707static
708void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000709{
710# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
bart3772a982008-03-15 08:11:03 +0000711 /* fine */
sewardjdcbb8d32007-11-26 21:34:30 +0000712# else
bart3772a982008-03-15 08:11:03 +0000713 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000714# endif
715}
sewardjaf44c822007-11-25 14:01:38 +0000716
barta79df6e2008-03-14 17:07:51 +0000717static void instrument_load(IRSB* const bb,
718 IRExpr* const addr_expr,
719 const HWord size)
720{
bart3772a982008-03-15 08:11:03 +0000721 IRExpr* size_expr;
722 IRExpr** argv;
723 IRDirty* di;
barta79df6e2008-03-14 17:07:51 +0000724
bart3772a982008-03-15 08:11:03 +0000725 switch (size)
726 {
727 case 1:
728 argv = mkIRExprVec_1(addr_expr);
729 di = unsafeIRDirty_0_N(/*regparms*/1,
730 "drd_trace_load_1",
731 VG_(fnptr_to_fnentry)(drd_trace_load_1),
732 argv);
733 break;
734 case 2:
735 argv = mkIRExprVec_1(addr_expr);
736 di = unsafeIRDirty_0_N(/*regparms*/1,
737 "drd_trace_load_2",
738 VG_(fnptr_to_fnentry)(drd_trace_load_2),
739 argv);
740 break;
741 case 4:
742 argv = mkIRExprVec_1(addr_expr);
743 di = unsafeIRDirty_0_N(/*regparms*/1,
744 "drd_trace_load_4",
745 VG_(fnptr_to_fnentry)(drd_trace_load_4),
746 argv);
747 break;
748 case 8:
749 argv = mkIRExprVec_1(addr_expr);
750 di = unsafeIRDirty_0_N(/*regparms*/1,
751 "drd_trace_load_8",
752 VG_(fnptr_to_fnentry)(drd_trace_load_8),
753 argv);
754 break;
755 default:
756 size_expr = mkIRExpr_HWord(size);
757 argv = mkIRExprVec_2(addr_expr, size_expr);
758 di = unsafeIRDirty_0_N(/*regparms*/2,
759 "drd_trace_load",
760 VG_(fnptr_to_fnentry)(drd_trace_load),
761 argv);
762 break;
763 }
764 addStmtToIRSB(bb, IRStmt_Dirty(di));
barta79df6e2008-03-14 17:07:51 +0000765}
766
767static void instrument_store(IRSB* const bb,
bart3772a982008-03-15 08:11:03 +0000768 IRExpr* const addr_expr,
769 const HWord size)
barta79df6e2008-03-14 17:07:51 +0000770{
bart3772a982008-03-15 08:11:03 +0000771 IRExpr* size_expr;
772 IRExpr** argv;
773 IRDirty* di;
barta79df6e2008-03-14 17:07:51 +0000774
bart3772a982008-03-15 08:11:03 +0000775 switch (size)
776 {
777 case 1:
778 argv = mkIRExprVec_1(addr_expr);
779 di = unsafeIRDirty_0_N(/*regparms*/1,
780 "drd_trace_store_1",
781 VG_(fnptr_to_fnentry)(drd_trace_store_1),
782 argv);
783 break;
784 case 2:
785 argv = mkIRExprVec_1(addr_expr);
786 di = unsafeIRDirty_0_N(/*regparms*/1,
787 "drd_trace_store_2",
788 VG_(fnptr_to_fnentry)(drd_trace_store_2),
789 argv);
790 break;
791 case 4:
792 argv = mkIRExprVec_1(addr_expr);
793 di = unsafeIRDirty_0_N(/*regparms*/1,
794 "drd_trace_store_4",
795 VG_(fnptr_to_fnentry)(drd_trace_store_4),
796 argv);
797 break;
798 case 8:
799 argv = mkIRExprVec_1(addr_expr);
800 di = unsafeIRDirty_0_N(/*regparms*/1,
801 "drd_trace_store_8",
802 VG_(fnptr_to_fnentry)(drd_trace_store_8),
803 argv);
804 break;
805 default:
806 size_expr = mkIRExpr_HWord(size);
807 argv = mkIRExprVec_2(addr_expr, size_expr);
808 di = unsafeIRDirty_0_N(/*regparms*/2,
809 "drd_trace_store",
810 VG_(fnptr_to_fnentry)(drd_trace_store),
811 argv);
812 break;
813 }
814 addStmtToIRSB(bb, IRStmt_Dirty(di));
barta79df6e2008-03-14 17:07:51 +0000815}
816
sewardjaf44c822007-11-25 14:01:38 +0000817static
818IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000819 IRSB* const bb_in,
820 VexGuestLayout* const layout,
821 VexGuestExtents* const vge,
822 IRType const gWordTy,
823 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000824{
bart3772a982008-03-15 08:11:03 +0000825 IRDirty* di;
826 Int i;
827 IRSB* bb;
828 IRExpr** argv;
829 Bool instrument = True;
830 Bool bus_locked = False;
sewardjaf44c822007-11-25 14:01:38 +0000831
bart3772a982008-03-15 08:11:03 +0000832 /* Set up BB */
833 bb = emptyIRSB();
834 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
835 bb->next = deepCopyIRExpr(bb_in->next);
836 bb->jumpkind = bb_in->jumpkind;
sewardjaf44c822007-11-25 14:01:38 +0000837
bart3772a982008-03-15 08:11:03 +0000838 for (i = 0; i < bb_in->stmts_used; i++)
839 {
840 IRStmt* const st = bb_in->stmts[i];
841 tl_assert(st);
842 if (st->tag == Ist_NoOp)
843 continue;
sewardjaf44c822007-11-25 14:01:38 +0000844
bart3772a982008-03-15 08:11:03 +0000845 switch (st->tag)
846 {
847 case Ist_IMark:
848 instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
849 != Vg_SectPLT;
850 break;
851
852 case Ist_MBE:
853 switch (st->Ist.MBE.event)
sewardjaf44c822007-11-25 14:01:38 +0000854 {
bart3772a982008-03-15 08:11:03 +0000855 case Imbe_Fence:
856 break; /* not interesting */
857 case Imbe_BusLock:
858 tl_assert(! bus_locked);
859 bus_locked = True;
860 break;
861 case Imbe_BusUnlock:
862 tl_assert(bus_locked);
863 bus_locked = False;
864 break;
sewardjaf44c822007-11-25 14:01:38 +0000865 default:
bart3772a982008-03-15 08:11:03 +0000866 tl_assert(0);
sewardjaf44c822007-11-25 14:01:38 +0000867 }
bart3772a982008-03-15 08:11:03 +0000868 addStmtToIRSB(bb, st);
869 break;
sewardjaf44c822007-11-25 14:01:38 +0000870
bart3772a982008-03-15 08:11:03 +0000871 case Ist_Store:
872 if (instrument && ! bus_locked)
873 {
874 instrument_store(bb,
875 st->Ist.Store.addr,
876 sizeofIRType(typeOfIRExpr(bb->tyenv,
877 st->Ist.Store.data)));
878 }
879 addStmtToIRSB(bb, st);
880 break;
barta47b3512008-03-07 17:22:26 +0000881
bart3772a982008-03-15 08:11:03 +0000882 case Ist_WrTmp:
883 if (instrument)
884 {
885 const IRExpr* const data = st->Ist.WrTmp.data;
886 if (data->tag == Iex_Load)
887 {
888 instrument_load(bb,
889 data->Iex.Load.addr,
890 sizeofIRType(data->Iex.Load.ty));
891 }
892 }
893 addStmtToIRSB(bb, st);
894 break;
895
896 case Ist_Dirty:
897 if (instrument)
898 {
899 IRDirty* d = st->Ist.Dirty.details;
900 IREffect const mFx = d->mFx;
901 switch (mFx) {
902 case Ifx_None:
903 break;
904 case Ifx_Read:
905 case Ifx_Write:
906 case Ifx_Modify:
907 tl_assert(d->mAddr);
908 tl_assert(d->mSize > 0);
909 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
910 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
911 di = unsafeIRDirty_0_N(
912 /*regparms*/2,
913 "drd_trace_load",
914 VG_(fnptr_to_fnentry)(drd_trace_load),
915 argv);
916 addStmtToIRSB(bb, IRStmt_Dirty(di));
917 }
918 if ((mFx == Ifx_Write || mFx == Ifx_Modify)
919 && ! bus_locked)
920 {
921 di = unsafeIRDirty_0_N(
922 /*regparms*/2,
923 "drd_trace_store",
924 VG_(fnptr_to_fnentry)(drd_trace_store),
925 argv);
926 addStmtToIRSB(bb, IRStmt_Dirty(di));
927 }
928 break;
929 default:
930 tl_assert(0);
931 }
932 }
933 addStmtToIRSB(bb, st);
934 break;
935
936 default:
937 addStmtToIRSB(bb, st);
938 break;
939 }
940 }
941
942 tl_assert(! bus_locked);
943
944 return bb;
sewardjaf44c822007-11-25 14:01:38 +0000945}
946
sewardjaf44c822007-11-25 14:01:38 +0000947static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
948{
bart3772a982008-03-15 08:11:03 +0000949 tl_assert(tid == VG_(get_running_tid)());
950 thread_set_vg_running_tid(tid);
sewardjaf44c822007-11-25 14:01:38 +0000951}
952
953static
954void drd_fini(Int exitcode)
955{
bart3772a982008-03-15 08:11:03 +0000956 // thread_print_all();
957 if (VG_(clo_verbosity) > 1 || drd_print_stats)
958 {
959 VG_(message)(Vg_DebugMsg,
960 " thread: %lld context switches"
961 " / %lld updates of the danger set",
962 thread_get_context_switch_count(),
963 thread_get_update_danger_set_count());
964 VG_(message)(Vg_DebugMsg,
965 " segments: %lld total, %lld max, %lld discard points",
966 sg_get_segments_created_count(),
967 sg_get_max_segments_alive_count(),
968 thread_get_discard_ordered_segments_count());
969 VG_(message)(Vg_DebugMsg,
970 " bitmaps: %lld / %lld bitmaps were allocated"
971 " and %lld / %lld for danger set updates",
972 bm_get_bitmap_creation_count(),
973 bm_get_bitmap2_creation_count(),
974 thread_get_danger_set_bitmap_creation_count(),
975 thread_get_danger_set_bitmap2_creation_count());
976 VG_(message)(Vg_DebugMsg,
977 " mutex: %lld non-recursive lock/unlock events",
978 get_mutex_lock_count());
979 drd_print_malloc_stats();
980 }
sewardjaf44c822007-11-25 14:01:38 +0000981}
982
sewardjaf44c822007-11-25 14:01:38 +0000983static
984void drd_pre_clo_init(void)
985{
bart3772a982008-03-15 08:11:03 +0000986 // Basic tool stuff.
sewardjaf44c822007-11-25 14:01:38 +0000987
bart3772a982008-03-15 08:11:03 +0000988 VG_(details_name) ("exp-drd");
989 VG_(details_version) (NULL);
990 VG_(details_description) ("a data race detector");
991 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
992 " by Bart Van Assche.");
993 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardjaf44c822007-11-25 14:01:38 +0000994
bart3772a982008-03-15 08:11:03 +0000995 VG_(basic_tool_funcs) (drd_post_clo_init,
996 drd_instrument,
997 drd_fini);
sewardjaf44c822007-11-25 14:01:38 +0000998
bart3772a982008-03-15 08:11:03 +0000999 // Command line stuff.
1000 VG_(needs_command_line_options)(drd_process_cmd_line_option,
1001 drd_print_usage,
1002 drd_print_debug_usage);
sewardjaf44c822007-11-25 14:01:38 +00001003
bart3772a982008-03-15 08:11:03 +00001004 // Error handling.
1005 drd_register_error_handlers();
sewardjaf44c822007-11-25 14:01:38 +00001006
bart3772a982008-03-15 08:11:03 +00001007 // Core event tracking.
1008 VG_(track_pre_mem_read) (drd_pre_mem_read);
1009 VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz);
1010 VG_(track_post_mem_write) (drd_post_mem_write);
1011 VG_(track_new_mem_brk) (drd_start_using_mem);
1012 VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms);
1013 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
1014 VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
1015 VG_(track_new_mem_startup) (drd_start_using_mem_w_perms);
1016 VG_(track_die_mem_brk) (drd_stop_using_mem);
1017 VG_(track_die_mem_munmap) (drd_stop_using_mem);
1018 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
1019 VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
1020 VG_(track_start_client_code) (drd_start_client_code);
1021 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
1022 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
1023 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
sewardjaf44c822007-11-25 14:01:38 +00001024
bart3772a982008-03-15 08:11:03 +00001025 // Other stuff.
1026 VG_(needs_var_info)();
sewardjaf44c822007-11-25 14:01:38 +00001027
bart3772a982008-03-15 08:11:03 +00001028 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
sewardjaf44c822007-11-25 14:01:38 +00001029
bart3772a982008-03-15 08:11:03 +00001030 drd_clientreq_init();
sewardjaf44c822007-11-25 14:01:38 +00001031
bart3772a982008-03-15 08:11:03 +00001032 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +00001033
bart3772a982008-03-15 08:11:03 +00001034 clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +00001035}
1036
1037
1038VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)