1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of drd, a thread error detector.
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>.
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_barrier.h"
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_clientobj.h"
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_clientreq.h"
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_cond.h"
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_error.h"
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "drd_hb.h"
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_load_store.h"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_malloc_wrappers.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_mutex.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_rwlock.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_segment.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_semaphore.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_suppression.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_thread.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_offsets.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_drd_bitmap.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_vki.h"         // Must be included before pub_tool_libcproc
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h"   // VG_(describe_IP)()
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"  // tl_assert()
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"    // VG_(strcmp)
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"   // VG_(printf)
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcproc.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h"     // command line options
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_replacemalloc.h"
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h"
54f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#include "pub_tool_aspacemgr.h"   // VG_(am_is_valid_for_client)
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local variables. */
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool s_print_stats;
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool s_var_info;
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool s_show_stack_usage;
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool s_trace_alloc;
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool trace_sectsuppr;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Implement the needs_command_line_options for drd.
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool DRD_(process_cmd_line_option)(const HChar* arg)
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int check_stack_accesses   = -1;
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int join_list_vol          = -1;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int exclusive_threshold_ms = -1;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int first_race_only        = -1;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int report_signal_unlocked = -1;
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int segment_merging        = -1;
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int segment_merge_interval = -1;
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int shared_threshold_ms    = -1;
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int show_confl_seg         = -1;
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_barrier          = -1;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_clientobj        = -1;
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_cond             = -1;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_csw              = -1;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_fork_join        = -1;
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   int trace_hb               = -1;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_conflict_set     = -1;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_conflict_set_bm  = -1;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_mutex            = -1;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_rwlock           = -1;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_segment          = -1;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_semaphore        = -1;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int trace_suppression      = -1;
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* trace_address = 0;
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* ptrace_address= 0;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if      VG_BOOL_CLO(arg, "--check-stack-var",     check_stack_accesses) {}
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if VG_INT_CLO (arg, "--join-list-vol",       join_list_vol) {}
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--drd-stats",           s_print_stats) {}
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--first-race-only",     first_race_only) {}
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if VG_BOOL_CLO(arg, "--free-is-write",       DRD_(g_free_is_write)) {}
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked)
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {}
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--segment-merging",     segment_merging) {}
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_INT_CLO (arg, "--segment-merging-interval", segment_merge_interval)
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {}
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--show-confl-seg",      show_confl_seg) {}
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--show-stack-usage",    s_show_stack_usage) {}
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-alloc",         s_trace_alloc) {}
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-barrier",       trace_barrier) {}
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-clientobj",     trace_clientobj) {}
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-cond",          trace_cond) {}
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-conflict-set",  trace_conflict_set) {}
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-conflict-set-bm", trace_conflict_set_bm){}
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-csw",           trace_csw) {}
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-fork-join",     trace_fork_join) {}
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if VG_BOOL_CLO(arg, "--trace-hb",            trace_hb) {}
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-mutex",         trace_mutex) {}
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-rwlock",        trace_rwlock) {}
119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else if VG_BOOL_CLO(arg, "--trace-sectsuppr",     trace_sectsuppr) {}
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-segment",       trace_segment) {}
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-semaphore",     trace_semaphore) {}
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--trace-suppr",         trace_suppression) {}
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--var-info",            s_var_info) {}
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_INT_CLO (arg, "--exclusive-threshold", exclusive_threshold_ms) {}
125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if VG_STR_CLO (arg, "--ptrace-addr",         ptrace_address) {}
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_INT_CLO (arg, "--shared-threshold",    shared_threshold_ms)    {}
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_STR_CLO (arg, "--trace-addr",          trace_address) {}
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(replacement_malloc_process_cmd_line_option)(arg);
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (check_stack_accesses != -1)
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(set_check_stack_accesses)(check_stack_accesses);
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (exclusive_threshold_ms != -1)
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(mutex_set_lock_threshold)(exclusive_threshold_ms);
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(rwlock_set_exclusive_threshold)(exclusive_threshold_ms);
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (first_race_only != -1)
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(set_first_race_only)(first_race_only);
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (join_list_vol != -1)
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(thread_set_join_list_vol)(join_list_vol);
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (report_signal_unlocked != -1)
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(cond_set_report_signal_unlocked)(report_signal_unlocked);
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shared_threshold_ms != -1)
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(rwlock_set_shared_threshold)(shared_threshold_ms);
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (segment_merging != -1)
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_set_segment_merging)(segment_merging);
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (segment_merge_interval != -1)
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_set_segment_merge_interval)(segment_merge_interval);
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (show_confl_seg != -1)
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(set_show_conflicting_segments)(show_confl_seg);
158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (trace_address) {
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Addr addr = VG_(strtoll16)(trace_address, 0);
160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(start_tracing_address_range)(addr, addr + 1, False);
161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (ptrace_address) {
163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      char *plus = VG_(strchr)(ptrace_address, '+');
164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Addr addr, length;
165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (plus)
166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *plus = '\0';
167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addr = VG_(strtoll16)(ptrace_address, 0);
168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      length = plus ? VG_(strtoll16)(plus + 1, 0) : 1;
169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      DRD_(start_tracing_address_range)(addr, addr + length, True);
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_barrier != -1)
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(barrier_set_trace)(trace_barrier);
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_clientobj != -1)
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(clientobj_set_trace)(trace_clientobj);
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_cond != -1)
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(cond_set_trace)(trace_cond);
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_csw != -1)
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_trace_context_switches)(trace_csw);
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_fork_join != -1)
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_set_trace_fork_join)(trace_fork_join);
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (trace_hb != -1)
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(hb_set_trace)(trace_hb);
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_conflict_set != -1)
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_trace_conflict_set)(trace_conflict_set);
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_conflict_set_bm != -1)
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_trace_conflict_set_bm)(trace_conflict_set_bm);
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_mutex != -1)
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(mutex_set_trace)(trace_mutex);
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_rwlock != -1)
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(rwlock_set_trace)(trace_rwlock);
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_segment != -1)
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(sg_set_trace)(trace_segment);
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_semaphore != -1)
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(semaphore_set_trace)(trace_semaphore);
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_suppression != -1)
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(suppression_set_trace)(trace_suppression);
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(print_usage)(void)
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --check-stack-var=yes|no  Whether or not to report data races on\n"
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              stack variables [no].\n"
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --exclusive-threshold=<n> Print an error message if any mutex or\n"
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              writer lock is held longer than the specified\n"
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              time (in milliseconds) [off].\n"
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --first-race-only=yes|no  Only report the first data race that occurs on\n"
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              a memory location instead of all races [no].\n"
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --free-is-write=yes|no    Whether to report races between freeing memory\n"
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              and subsequent accesses of that memory[no].\n"
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --join-list-vol=<n>       Number of threads to delay cleanup for [10].\n"
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --report-signal-unlocked=yes|no Whether to report calls to\n"
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              pthread_cond_signal() where the mutex associated\n"
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              with the signal via pthread_cond_wait() is not\n"
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              locked at the time the signal is sent [yes].\n"
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --segment-merging=yes|no  Controls segment merging [yes].\n"
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        Segment merging is an algorithm to limit memory usage of the\n"
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        data race detection algorithm. Disabling segment merging may\n"
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        improve the accuracy of the so-called 'other segments' displayed\n"
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        in race reports but can also trigger an out of memory error.\n"
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --segment-merging-interval=<n> Perform segment merging every time n new\n"
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        segments have been created. Default: %d.\n"
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --shared-threshold=<n>    Print an error message if a reader lock\n"
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              is held longer than the specified time (in\n"
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              milliseconds) [off]\n"
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --show-confl-seg=yes|no   Show conflicting segments in race reports [yes].\n"
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --show-stack-usage=yes|no Print stack usage at thread exit time [no].\n"
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  drd options for monitoring process behavior:\n"
232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"    --ptrace-addr=<address>[+<length>] Trace all load and store activity for\n"
233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"                              the specified address range and keep doing that\n"
234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"                              even after the memory at that address has been\n"
235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"                              freed and reallocated [off].\n"
236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"    --trace-addr=<address>    Trace all load and store activity for the\n"
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              specified address [off].\n"
238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"    --trace-alloc=yes|no      Trace all memory allocations and deallocations\n"
239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"                              [no].\n"
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-barrier=yes|no    Trace all barrier activity [no].\n"
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-cond=yes|no       Trace all condition variable activity [no].\n"
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-fork-join=yes|no  Trace all thread fork/join activity [no].\n"
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --trace-hb=yes|no         Trace ANNOTATE_HAPPENS_BEFORE() etc. [no].\n"
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-mutex=yes|no      Trace all mutex activity [no].\n"
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-rwlock=yes|no     Trace all reader-writer lock activity[no].\n"
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-semaphore=yes|no  Trace all semaphore activity [no].\n",
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDRD_(thread_get_segment_merge_interval)()
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(print_debug_usage)(void)
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --drd-stats=yes|no        Print statistics about DRD activity [no].\n"
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-clientobj=yes|no  Trace all client object activity [no].\n"
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-csw=yes|no        Trace all scheduler context switches [no].\n"
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-conflict-set=yes|no Trace all conflict set updates [no].\n"
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-conflict-set-bm=yes|no Trace all conflict set bitmap\n"
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              updates [no]. Note: enabling this option\n"
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              will generate a lot of output !\n"
261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"    --trace-sectsuppr=yes|no  Trace which the dynamic library sections on\n"
262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"                              which data race detection is suppressed.\n"
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-segment=yes|no    Trace segment actions [no].\n"
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-suppr=yes|no      Trace all address suppression actions [no].\n"
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Implements the thread-related core callbacks.
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_pre_mem_read(const CorePart part,
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             const ThreadId tid,
275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             const HChar* const s,
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             const Addr a,
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             const SizeT size)
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2792ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (size > 0)
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(trace_load)(a, size);
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_pre_mem_read_asciiz(const CorePart part,
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    const ThreadId tid,
288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    const HChar* const s,
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    const Addr a)
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* p = (void*)a;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT size = 0;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   // Don't segfault if the string starts in an obviously stupid
295f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   // place.  Actually we should check the whole string, not just
296f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   // the start address, but that's too much trouble.  At least
297f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   // checking the first byte is better than nothing.  See #255009.
298f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   if (!VG_(am_is_valid_for_client) (a, 1, VKI_PROT_READ))
299f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      return;
300f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: the expression '*p' reads client memory and may crash if the */
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* client provided an invalid pointer !                               */
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (*p)
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p++;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size++;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (size > 0)
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(trace_load)(a, size);
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_post_mem_write(const CorePart part,
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               const ThreadId tid,
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               const Addr a,
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               const SizeT size)
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (size > 0)
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(trace_store)(a, size);
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_start_using_mem(const Addr a1, const SizeT len,
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         const Bool is_stack_mem)
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   const Addr a2 = a1 + len;
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(a1 <= a2);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!is_stack_mem && s_trace_alloc)
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("Started using memory range 0x%lx + %ld%s",
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      a1, len, DRD_(running_thread_inside_pthread_create)()
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      ? " (inside pthread_create())" : "");
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!is_stack_mem && DRD_(g_free_is_write))
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(thread_stop_using_mem)(a1, a2);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (UNLIKELY(DRD_(any_address_is_traced)()))
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(trace_mem_access)(a1, len, eStart, 0, 0);
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (UNLIKELY(DRD_(running_thread_inside_pthread_create)()))
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(start_suppression)(a1, a2, "pthread_create()");
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_start_using_mem_w_ecu(const Addr a1,
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      const SizeT len,
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      UInt ec_uniq)
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_start_using_mem(a1, len, False);
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_start_using_mem_w_tid(const Addr a1,
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      const SizeT len,
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ThreadId tid)
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_start_using_mem(a1, len, False);
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_stop_using_mem(const Addr a1, const SizeT len,
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        const Bool is_stack_mem)
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const Addr a2 = a1 + len;
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 <= a2);
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (UNLIKELY(DRD_(any_address_is_traced)()))
376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      DRD_(trace_mem_access)(a1, len, eEnd, 0, 0);
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!is_stack_mem && s_trace_alloc)
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("Stopped using memory range 0x%lx + %ld",
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      a1, len);
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!is_stack_mem || DRD_(get_check_stack_accesses)())
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (is_stack_mem || !DRD_(g_free_is_write))
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 DRD_(thread_stop_using_mem)(a1, a2);
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if (DRD_(g_free_is_write))
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 DRD_(trace_store)(a1, len);
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(clientobj_stop_using_mem)(a1, a2);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(suppression_stop_using_mem)(a1, a2);
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_stop_using_nonstack_mem(const Addr a1, const SizeT len)
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_stop_using_mem(a1, len, False);
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Discard all information DRD has about memory accesses and client objects
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * in the specified address range.
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(clean_memory)(const Addr a1, const SizeT len)
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const Bool is_stack_memory = DRD_(thread_address_on_any_stack)(a1);
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_stop_using_mem(a1, len, is_stack_memory);
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_start_using_mem(a1, len, is_stack_memory);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Suppress data race reports on all addresses contained in .plt, .got and
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * .got.plt sections inside the address range [ a, a + len [. The data in
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * these sections is modified by _dl_relocate_object() every time a function
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * in a shared library is called for the first time. Since the first call
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * to a function in a shared library can happen from a multithreaded context,
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * such calls can cause conflicting accesses. See also Ulrich Drepper's
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * paper "How to Write Shared Libraries" for more information about relocation
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * (http://people.redhat.com/drepper/dsohowto.pdf).
419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Note: the contents of the .got section is only modified by the MIPS resolver.
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(suppress_relocation_conflicts)(const Addr a, const SizeT len)
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const DebugInfo* di;
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (trace_sectsuppr)
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(dmsg)("Evaluating range @ 0x%lx size %ld\n", a, len);
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (di = VG_(next_DebugInfo)(0); di; di = VG_(next_DebugInfo)(di)) {
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr  avma;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT size;
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (trace_sectsuppr)
433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	 VG_(dmsg)("Examining %s / %s\n", VG_(DebugInfo_get_filename)(di),
434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		   VG_(DebugInfo_get_soname)(di));
435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /*
437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * Suppress the race report on the libpthread global variable
438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * __pthread_multiple_threads. See also
439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * http://bugs.kde.org/show_bug.cgi?id=323905.
440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       */
441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      avma = VG_(DebugInfo_get_bss_avma)(di);
442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      size = VG_(DebugInfo_get_bss_size)(di);
443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tl_assert((avma && size) || (avma == 0 && size == 0));
444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (size > 0 &&
445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          VG_(strcmp)(VG_(DebugInfo_get_soname)(di), "libpthread.so.0") == 0) {
446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	 if (trace_sectsuppr)
447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    VG_(dmsg)("Suppressing .bss @ 0x%lx size %ld\n", avma, size);
448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectBSS);
449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DRD_(start_suppression)(avma, avma + size, ".bss");
450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      avma = VG_(DebugInfo_get_plt_avma)(di);
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = VG_(DebugInfo_get_plt_size)(di);
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((avma && size) || (avma == 0 && size == 0));
455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (size > 0) {
456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	 if (trace_sectsuppr)
457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	    VG_(dmsg)("Suppressing .plt @ 0x%lx size %ld\n", avma, size);
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectPLT);
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(start_suppression)(avma, avma + size, ".plt");
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      avma = VG_(DebugInfo_get_gotplt_avma)(di);
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = VG_(DebugInfo_get_gotplt_size)(di);
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((avma && size) || (avma == 0 && size == 0));
465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (size > 0) {
466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	 if (trace_sectsuppr)
467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	    VG_(dmsg)("Suppressing .got.plt @ 0x%lx size %ld\n", avma, size);
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectGOTPLT);
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(start_suppression)(avma, avma + size, ".gotplt");
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      avma = VG_(DebugInfo_get_got_avma)(di);
473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      size = VG_(DebugInfo_get_got_size)(di);
474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tl_assert((avma && size) || (avma == 0 && size == 0));
475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (size > 0) {
476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	 if (trace_sectsuppr)
477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    VG_(dmsg)("Suppressing .got @ 0x%lx size %ld\n", avma, size);
478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectGOT);
479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         DRD_(start_suppression)(avma, avma + size, ".got");
480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_start_using_mem_w_perms(const Addr a, const SizeT len,
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 const Bool rr, const Bool ww, const Bool xx,
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 ULong di_handle)
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_start_using_mem(a, len, False);
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(suppress_relocation_conflicts)(a, len);
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/**
497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Called by the core when the stack of a thread grows, to indicate that
498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * the addresses in range [ a, a + len [ may now be used by the client.
499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Assumption: stacks grow downward.
500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid drd_start_using_mem_stack2(const DrdThreadId tid, const Addr a,
503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                const SizeT len)
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(thread_set_stack_min)(tid, a - VG_STACK_REDZONE_SZB);
506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   drd_start_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB,
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True);
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid drd_start_using_mem_stack(const Addr a, const SizeT len)
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   drd_start_using_mem_stack2(DRD_(thread_get_running_tid)(), a, len);
514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/**
517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Called by the core when the stack of a thread shrinks, to indicate that
518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * the addresses [ a, a + len [ are no longer accessible for the client.
519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Assumption: stacks grow downward.
520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */
521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic __inline__
522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid drd_stop_using_mem_stack2(const DrdThreadId tid, const Addr a,
523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               const SizeT len)
524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(thread_set_stack_min)(tid, a + len - VG_STACK_REDZONE_SZB);
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB,
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      True);
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic __inline__
531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid drd_stop_using_mem_stack(const Addr a, const SizeT len)
532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   drd_stop_using_mem_stack2(DRD_(thread_get_running_tid)(), a, len);
534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool on_alt_stack(const Addr a)
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId vg_tid;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr alt_min;
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT alt_size;
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_tid = VG_(get_running_tid)();
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   alt_min = VG_(thread_get_altstack_min)(vg_tid);
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   alt_size = VG_(thread_get_altstack_size)(vg_tid);
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (SizeT)(a - alt_min) < alt_size;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_start_using_mem_alt_stack(const Addr a, const SizeT len)
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!on_alt_stack(a))
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_start_using_mem_stack(a, len);
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_stop_using_mem_alt_stack(const Addr a, const SizeT len)
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!on_alt_stack(a))
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      drd_stop_using_mem_stack(a, len);
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Callback function invoked by the Valgrind core before a signal is delivered.
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_pre_deliver_signal(const ThreadId vg_tid, const Int sigNo,
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            const Bool alt_stack)
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DrdThreadId drd_tid;
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_on_alt_stack)(drd_tid, alt_stack);
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (alt_stack)
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * As soon a signal handler has been invoked on the alternate stack,
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * switch to stack memory handling functions that can handle the
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * alternate stack.
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(track_new_mem_stack)(drd_start_using_mem_alt_stack);
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(track_die_mem_stack)(drd_stop_using_mem_alt_stack);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Callback function invoked by the Valgrind core after a signal is delivered,
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * at least if the signal handler did not longjmp().
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_post_deliver_signal(const ThreadId vg_tid, const Int sigNo)
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DrdThreadId drd_tid;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_on_alt_stack)(drd_tid, False);
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(thread_get_threads_on_alt_stack)() == 0)
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(track_new_mem_stack)(drd_start_using_mem_stack);
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(track_die_mem_stack)(drd_stop_using_mem_stack);
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Callback function called by the Valgrind core before a stack area is
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * being used by a signal handler.
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * @param[in] a   Start of address range - VG_STACK_REDZONE_SZB.
609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * @param[in] len Address range length + VG_STACK_REDZONE_SZB.
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param[in] tid Valgrind thread ID for whom the signal frame is being
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *                constructed.
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_start_using_mem_stack_signal(const Addr a, const SizeT len,
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             ThreadId tid)
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   drd_start_using_mem(a + VG_STACK_REDZONE_SZB, len - VG_STACK_REDZONE_SZB,
618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       True);
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   drd_stop_using_mem(a + VG_STACK_REDZONE_SZB, len - VG_STACK_REDZONE_SZB,
624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      True);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_pre_thread_create(const ThreadId creator, const ThreadId created)
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const DrdThreadId drd_creator = DRD_(VgThreadIdToDrdThreadId)(creator);
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(created != VG_INVALID_THREADID);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_pre_create)(drd_creator, created);
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(IsValidDrdThreadId)(drd_creator))
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(thread_new_segment)(drd_creator);
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(thread_get_trace_fork_join)())
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("drd_pre_thread_create creator = %d, created = %d",
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      drd_creator, created);
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/**
645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Called by Valgrind's core before any loads or stores are performed on
646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * the context of thread "created".
647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_post_thread_create(const ThreadId vg_created)
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DrdThreadId drd_created;
652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Addr stack_max;
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(vg_created != VG_INVALID_THREADID);
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_created = DRD_(thread_post_create)(vg_created);
657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set up red zone before the code in glibc's clone.S is run. */
659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stack_max = DRD_(thread_get_stack_max)(drd_created);
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   drd_start_using_mem_stack2(drd_created, stack_max, 0);
661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(thread_get_trace_fork_join)())
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("drd_post_thread_create created = %d", drd_created);
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (! DRD_(get_check_stack_accesses)())
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(start_suppression)(DRD_(thread_get_stack_max)(drd_created)
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              - DRD_(thread_get_stack_size)(drd_created),
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              DRD_(thread_get_stack_max)(drd_created),
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "stack");
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Called after a thread has performed its last memory access. */
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_thread_finished(ThreadId vg_tid)
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DrdThreadId drd_tid;
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*
681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * Ignore if invoked because thread creation failed. See e.g.
682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * coregrind/m_syswrap/syswrap-amd64-linux.c
683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    */
684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (VG_(get_running_tid)() != vg_tid)
685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(drd_tid != DRD_INVALID_THREADID);
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DRD_(thread_get_trace_fork_join)())
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DRD_(trace_msg)("drd_thread_finished tid = %d%s", drd_tid,
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      DRD_(thread_get_joinable)(drd_tid)
693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      ? "" : " (which is a detached thread)");
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (s_show_stack_usage && !VG_(clo_xml)) {
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const SizeT stack_size = DRD_(thread_get_stack_size)(drd_tid);
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const SizeT used_stack
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = (DRD_(thread_get_stack_max)(drd_tid)
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - DRD_(thread_get_stack_min_min)(drd_tid));
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "thread %d%s finished and used %ld bytes out of %ld"
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   " on its stack. Margin: %ld bytes.\n",
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   drd_tid,
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(thread_get_joinable)(drd_tid)
705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   ? "" : " (which is a detached thread)",
706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   used_stack, stack_size, stack_size - used_stack);
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   drd_stop_using_mem(DRD_(thread_get_stack_min)(drd_tid),
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      DRD_(thread_get_stack_max)(drd_tid)
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      - DRD_(thread_get_stack_min)(drd_tid),
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      True);
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_record_loads)(drd_tid, False);
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_record_stores)(drd_tid, False);
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_finished)(drd_tid);
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
718f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*
719f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root * Called immediately after fork for the child process only. 'tid' is the
720f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root * only surviving thread in the child process. Cleans up thread state.
721f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root * See also http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html for a detailed discussion of using fork() in combination with mutexes.
722f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root */
723f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic
724f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootvoid drd__atfork_child(ThreadId tid)
725f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
726f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   DRD_(drd_thread_atfork_child)(tid);
727f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
728f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
729f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Implementation of the tool interface.
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(post_clo_init)(void)
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) || defined(VGO_darwin)
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* fine */
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\nWARNING: DRD has not yet been tested on this operating system.\n\n");
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s_var_info)
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(needs_var_info)();
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tid == VG_(get_running_tid)());
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(thread_set_vg_running_tid)(tid);
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void DRD_(fini)(Int exitcode)
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // thread_print_all();
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(message)(Vg_UserMsg, "For counts of detected and suppressed errors, "
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "rerun with: -v\n");
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ((VG_(clo_stats) || s_print_stats) && !VG_(clo_xml))
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong pu = DRD_(thread_get_update_conflict_set_count)();
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong pu_seg_cr = DRD_(thread_get_update_conflict_set_new_sg_count)();
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong pu_mtx_cv = DRD_(thread_get_update_conflict_set_sync_count)();
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong pu_join   = DRD_(thread_get_update_conflict_set_join_count)();
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "   thread: %lld context switches.\n",
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(thread_get_context_switch_count)());
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "confl set: %lld full updates and %lld partial updates;\n",
774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   DRD_(thread_get_compute_conflict_set_count)(),
775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   pu);
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "           %lld partial updates during segment creation,\n",
778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   pu_seg_cr);
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "           %lld because of mutex/sema/cond.var. operations,\n",
781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   pu_mtx_cv);
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "           %lld because of barrier/rwlock operations and\n",
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   pu - pu_seg_cr - pu_mtx_cv - pu_join);
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "           %lld partial updates because of thread join"
787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   " operations.\n",
788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   pu_join);
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   " segments: created %lld segments, max %lld alive,\n",
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(sg_get_segments_created_count)(),
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(sg_get_max_segments_alive_count)());
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "           %lld discard points and %lld merges.\n",
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(thread_get_discard_ordered_segments_count)(),
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(sg_get_segment_merge_count)());
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "segmnt cr: %lld mutex, %lld rwlock, %lld semaphore and"
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   " %lld barrier.\n",
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(get_mutex_segment_creation_count)(),
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(get_rwlock_segment_creation_count)(),
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(get_semaphore_segment_creation_count)(),
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(get_barrier_segment_creation_count)());
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "  bitmaps: %lld level one"
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   " and %lld level two bitmaps were allocated.\n",
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(bm_get_bitmap_creation_count)(),
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(bm_get_bitmap2_creation_count)());
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "    mutex: %lld non-recursive lock/unlock events.\n",
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   DRD_(get_mutex_lock_count)());
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(print_malloc_stats)();
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(bm_module_cleanup)();
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid drd_pre_clo_init(void)
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Basic tool stuff.
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_name)            ("drd");
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_version)         (NULL);
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_description)     ("a thread error detector");
825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(details_copyright_author)("Copyright (C) 2006-2013, and GNU GPL'd,"
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 " by Bart Van Assche.");
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_bug_reports_to)  (VG_BUGS_TO);
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(basic_tool_funcs)        (DRD_(post_clo_init),
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 DRD_(instrument),
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 DRD_(fini));
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Command line stuff.
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(needs_command_line_options)(DRD_(process_cmd_line_option),
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   DRD_(print_usage),
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   DRD_(print_debug_usage));
837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(needs_xml_output)          ();
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Error handling.
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(register_error_handlers)();
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Core event tracking.
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_pre_mem_read)         (drd_pre_mem_read);
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_pre_mem_read_asciiz)  (drd_pre_mem_read_asciiz);
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_post_mem_write)       (drd_post_mem_write);
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_new_mem_brk)          (drd_start_using_mem_w_tid);
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_new_mem_mmap)         (drd_start_using_mem_w_perms);
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_new_mem_stack)        (drd_start_using_mem_stack);
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_new_mem_startup)      (drd_start_using_mem_w_perms);
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_die_mem_brk)          (drd_stop_using_nonstack_mem);
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_die_mem_munmap)       (drd_stop_using_nonstack_mem);
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_die_mem_stack)        (drd_stop_using_mem_stack);
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_pre_deliver_signal)   (drd_pre_deliver_signal);
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_post_deliver_signal)  (drd_post_deliver_signal);
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_start_client_code)    (drd_start_client_code);
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_pre_thread_first_insn)(drd_post_thread_create);
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(track_pre_thread_ll_exit)   (drd_thread_finished);
861f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   VG_(atfork)                     (NULL/*pre*/, NULL/*parent*/,
862f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root				    drd__atfork_child/*child*/);
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Other stuff.
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu,
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  drd_stop_using_nonstack_mem);
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(bm_module_init)();
869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(clientreq_init)();
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(suppression_init)();
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(clientobj_init)();
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DRD_(thread_init)();
877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar* const smi = VG_(getenv)("DRD_SEGMENT_MERGING_INTERVAL");
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (smi)
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DRD_(thread_set_segment_merge_interval)(VG_(strtoll10)(smi, NULL));
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
887