| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1 | /* | 
| bart | 86562bd | 2009-02-16 19:43:56 +0000 | [diff] [blame] | 2 |   This file is part of drd, a thread error detector. | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 3 |  | 
| bart | 922304f | 2011-03-13 12:02:44 +0000 | [diff] [blame] | 4 |   Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>. | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 5 |  | 
 | 6 |   This program is free software; you can redistribute it and/or | 
 | 7 |   modify it under the terms of the GNU General Public License as | 
 | 8 |   published by the Free Software Foundation; either version 2 of the | 
 | 9 |   License, or (at your option) any later version. | 
 | 10 |  | 
 | 11 |   This program is distributed in the hope that it will be useful, but | 
 | 12 |   WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 13 |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 14 |   General Public License for more details. | 
 | 15 |  | 
 | 16 |   You should have received a copy of the GNU General Public License | 
 | 17 |   along with this program; if not, write to the Free Software | 
 | 18 |   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | 
 | 19 |   02111-1307, USA. | 
 | 20 |  | 
 | 21 |   The GNU General Public License is contained in the file COPYING. | 
 | 22 | */ | 
 | 23 |  | 
 | 24 |  | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 25 | #include "drd_barrier.h" | 
| bart | 4bb53d8 | 2008-02-28 19:06:34 +0000 | [diff] [blame] | 26 | #include "drd_clientobj.h" | 
| bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 27 | #include "drd_clientreq.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 28 | #include "drd_cond.h" | 
 | 29 | #include "drd_error.h" | 
| bart | c182467 | 2011-03-12 14:07:09 +0000 | [diff] [blame] | 30 | #include "drd_hb.h" | 
| bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 31 | #include "drd_load_store.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 32 | #include "drd_malloc_wrappers.h" | 
 | 33 | #include "drd_mutex.h" | 
| bart | 5bd9f2d | 2008-03-03 20:31:58 +0000 | [diff] [blame] | 34 | #include "drd_rwlock.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 35 | #include "drd_segment.h" | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 36 | #include "drd_semaphore.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 37 | #include "drd_suppression.h" | 
 | 38 | #include "drd_thread.h" | 
| bart | eacd916 | 2008-06-16 20:22:18 +0000 | [diff] [blame] | 39 | #include "libvex_guest_offsets.h" | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 40 | #include "pub_drd_bitmap.h" | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 41 | #include "pub_tool_vki.h"         // Must be included before pub_tool_libcproc | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 42 | #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) | 
 | 47 | #include "pub_tool_libcproc.h" | 
 | 48 | #include "pub_tool_machine.h" | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 49 | #include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)() | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 50 | #include "pub_tool_options.h"     // command line options | 
| bart | ceded21 | 2008-03-26 17:39:52 +0000 | [diff] [blame] | 51 | #include "pub_tool_replacemalloc.h" | 
| bart | 72b751c | 2008-03-01 13:44:24 +0000 | [diff] [blame] | 52 | #include "pub_tool_threadstate.h" // VG_(get_running_tid)() | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 53 | #include "pub_tool_tooliface.h" | 
| sewardj | 234e558 | 2011-02-09 12:47:23 +0000 | [diff] [blame] | 54 | #include "pub_tool_aspacemgr.h"   // VG_(am_is_valid_for_client) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 55 |  | 
 | 56 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 57 | /* Local variables. */ | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 58 |  | 
| bart | 7d5f523 | 2011-03-13 09:08:10 +0000 | [diff] [blame] | 59 | static Bool s_print_stats; | 
 | 60 | static Bool s_var_info; | 
 | 61 | static Bool s_show_stack_usage; | 
 | 62 | static Bool s_trace_alloc; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 63 |  | 
 | 64 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 65 | /** | 
 | 66 |  * Implement the needs_command_line_options for drd. | 
 | 67 |  */ | 
 | 68 | static Bool DRD_(process_cmd_line_option)(Char* arg) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 69 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 70 |    int check_stack_accesses   = -1; | 
| bart | 6d956dc | 2011-07-28 09:54:37 +0000 | [diff] [blame] | 71 |    int join_list_vol          = -1; | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 72 |    int exclusive_threshold_ms = -1; | 
| bart | f98a569 | 2009-05-03 17:17:37 +0000 | [diff] [blame] | 73 |    int first_race_only        = -1; | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 74 |    int report_signal_unlocked = -1; | 
 | 75 |    int segment_merging        = -1; | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 76 |    int segment_merge_interval = -1; | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 77 |    int shared_threshold_ms    = -1; | 
 | 78 |    int show_confl_seg         = -1; | 
 | 79 |    int trace_barrier          = -1; | 
 | 80 |    int trace_clientobj        = -1; | 
 | 81 |    int trace_cond             = -1; | 
 | 82 |    int trace_csw              = -1; | 
 | 83 |    int trace_fork_join        = -1; | 
| bart | c182467 | 2011-03-12 14:07:09 +0000 | [diff] [blame] | 84 |    int trace_hb               = -1; | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 85 |    int trace_conflict_set     = -1; | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 86 |    int trace_conflict_set_bm  = -1; | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 87 |    int trace_mutex            = -1; | 
 | 88 |    int trace_rwlock           = -1; | 
 | 89 |    int trace_segment          = -1; | 
 | 90 |    int trace_semaphore        = -1; | 
 | 91 |    int trace_suppression      = -1; | 
 | 92 |    Char* trace_address        = 0; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 93 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 94 |    if      VG_BOOL_CLO(arg, "--check-stack-var",     check_stack_accesses) {} | 
| bart | 6d956dc | 2011-07-28 09:54:37 +0000 | [diff] [blame] | 95 |    else if VG_INT_CLO (arg, "--join-list-vol",       join_list_vol) {} | 
| bart | 75c1cba | 2010-08-29 07:20:30 +0000 | [diff] [blame] | 96 |    else if VG_BOOL_CLO(arg, "--drd-stats",           s_print_stats) {} | 
| bart | f98a569 | 2009-05-03 17:17:37 +0000 | [diff] [blame] | 97 |    else if VG_BOOL_CLO(arg, "--first-race-only",     first_race_only) {} | 
| bart | 7d5f523 | 2011-03-13 09:08:10 +0000 | [diff] [blame] | 98 |    else if VG_BOOL_CLO(arg, "--free-is-write",       DRD_(g_free_is_write)) {} | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 99 |    else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked) | 
 | 100 |    {} | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 101 |    else if VG_BOOL_CLO(arg, "--segment-merging",     segment_merging) {} | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 102 |    else if VG_INT_CLO (arg, "--segment-merging-interval", segment_merge_interval) | 
 | 103 |    {} | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 104 |    else if VG_BOOL_CLO(arg, "--show-confl-seg",      show_confl_seg) {} | 
| bart | 75c1cba | 2010-08-29 07:20:30 +0000 | [diff] [blame] | 105 |    else if VG_BOOL_CLO(arg, "--show-stack-usage",    s_show_stack_usage) {} | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 106 |    else if VG_BOOL_CLO(arg, "--trace-alloc",         s_trace_alloc) {} | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 107 |    else if VG_BOOL_CLO(arg, "--trace-barrier",       trace_barrier) {} | 
 | 108 |    else if VG_BOOL_CLO(arg, "--trace-clientobj",     trace_clientobj) {} | 
 | 109 |    else if VG_BOOL_CLO(arg, "--trace-cond",          trace_cond) {} | 
 | 110 |    else if VG_BOOL_CLO(arg, "--trace-conflict-set",  trace_conflict_set) {} | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 111 |    else if VG_BOOL_CLO(arg, "--trace-conflict-set-bm", trace_conflict_set_bm){} | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 112 |    else if VG_BOOL_CLO(arg, "--trace-csw",           trace_csw) {} | 
 | 113 |    else if VG_BOOL_CLO(arg, "--trace-fork-join",     trace_fork_join) {} | 
| bart | c182467 | 2011-03-12 14:07:09 +0000 | [diff] [blame] | 114 |    else if VG_BOOL_CLO(arg, "--trace-hb",            trace_hb) {} | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 115 |    else if VG_BOOL_CLO(arg, "--trace-mutex",         trace_mutex) {} | 
 | 116 |    else if VG_BOOL_CLO(arg, "--trace-rwlock",        trace_rwlock) {} | 
 | 117 |    else if VG_BOOL_CLO(arg, "--trace-segment",       trace_segment) {} | 
 | 118 |    else if VG_BOOL_CLO(arg, "--trace-semaphore",     trace_semaphore) {} | 
 | 119 |    else if VG_BOOL_CLO(arg, "--trace-suppr",         trace_suppression) {} | 
| bart | 75c1cba | 2010-08-29 07:20:30 +0000 | [diff] [blame] | 120 |    else if VG_BOOL_CLO(arg, "--var-info",            s_var_info) {} | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 121 |    else if VG_INT_CLO (arg, "--exclusive-threshold", exclusive_threshold_ms) {} | 
 | 122 |    else if VG_INT_CLO (arg, "--shared-threshold",    shared_threshold_ms)    {} | 
 | 123 |    else if VG_STR_CLO (arg, "--trace-addr",          trace_address) {} | 
 | 124 |    else | 
 | 125 |       return VG_(replacement_malloc_process_cmd_line_option)(arg); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 126 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 127 |    if (check_stack_accesses != -1) | 
 | 128 |       DRD_(set_check_stack_accesses)(check_stack_accesses); | 
 | 129 |    if (exclusive_threshold_ms != -1) | 
 | 130 |    { | 
 | 131 |       DRD_(mutex_set_lock_threshold)(exclusive_threshold_ms); | 
 | 132 |       DRD_(rwlock_set_exclusive_threshold)(exclusive_threshold_ms); | 
 | 133 |    } | 
| bart | f98a569 | 2009-05-03 17:17:37 +0000 | [diff] [blame] | 134 |    if (first_race_only != -1) | 
 | 135 |    { | 
 | 136 |       DRD_(set_first_race_only)(first_race_only); | 
 | 137 |    } | 
| bart | 6d956dc | 2011-07-28 09:54:37 +0000 | [diff] [blame] | 138 |    if (join_list_vol != -1) | 
 | 139 |       DRD_(thread_set_join_list_vol)(join_list_vol); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 140 |    if (report_signal_unlocked != -1) | 
 | 141 |    { | 
 | 142 |       DRD_(cond_set_report_signal_unlocked)(report_signal_unlocked); | 
 | 143 |    } | 
 | 144 |    if (shared_threshold_ms != -1) | 
 | 145 |    { | 
 | 146 |       DRD_(rwlock_set_shared_threshold)(shared_threshold_ms); | 
 | 147 |    } | 
 | 148 |    if (segment_merging != -1) | 
 | 149 |       DRD_(thread_set_segment_merging)(segment_merging); | 
| bart | 109d5da | 2009-06-22 18:06:29 +0000 | [diff] [blame] | 150 |    if (segment_merge_interval != -1) | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 151 |       DRD_(thread_set_segment_merge_interval)(segment_merge_interval); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 152 |    if (show_confl_seg != -1) | 
 | 153 |       DRD_(set_show_conflicting_segments)(show_confl_seg); | 
 | 154 |    if (trace_address) | 
 | 155 |    { | 
 | 156 |       const Addr addr = VG_(strtoll16)(trace_address, 0); | 
 | 157 |       DRD_(start_tracing_address_range)(addr, addr + 1); | 
 | 158 |    } | 
 | 159 |    if (trace_barrier != -1) | 
 | 160 |       DRD_(barrier_set_trace)(trace_barrier); | 
 | 161 |    if (trace_clientobj != -1) | 
 | 162 |       DRD_(clientobj_set_trace)(trace_clientobj); | 
 | 163 |    if (trace_cond != -1) | 
 | 164 |       DRD_(cond_set_trace)(trace_cond); | 
 | 165 |    if (trace_csw != -1) | 
 | 166 |       DRD_(thread_trace_context_switches)(trace_csw); | 
 | 167 |    if (trace_fork_join != -1) | 
 | 168 |       DRD_(thread_set_trace_fork_join)(trace_fork_join); | 
| bart | c182467 | 2011-03-12 14:07:09 +0000 | [diff] [blame] | 169 |    if (trace_hb != -1) | 
 | 170 |       DRD_(hb_set_trace)(trace_hb); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 171 |    if (trace_conflict_set != -1) | 
 | 172 |       DRD_(thread_trace_conflict_set)(trace_conflict_set); | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 173 |    if (trace_conflict_set_bm != -1) | 
 | 174 |       DRD_(thread_trace_conflict_set_bm)(trace_conflict_set_bm); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 175 |    if (trace_mutex != -1) | 
 | 176 |       DRD_(mutex_set_trace)(trace_mutex); | 
 | 177 |    if (trace_rwlock != -1) | 
 | 178 |       DRD_(rwlock_set_trace)(trace_rwlock); | 
 | 179 |    if (trace_segment != -1) | 
 | 180 |       DRD_(sg_set_trace)(trace_segment); | 
 | 181 |    if (trace_semaphore != -1) | 
 | 182 |       DRD_(semaphore_set_trace)(trace_semaphore); | 
 | 183 |    if (trace_suppression != -1) | 
 | 184 |       DRD_(suppression_set_trace)(trace_suppression); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 185 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 186 |    return True; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 187 | } | 
 | 188 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 189 | static void DRD_(print_usage)(void) | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 190 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 191 |    VG_(printf)( | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 192 | "    --check-stack-var=yes|no  Whether or not to report data races on\n" | 
 | 193 | "                              stack variables [no].\n" | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 194 | "    --exclusive-threshold=<n> Print an error message if any mutex or\n" | 
| bart | 8600c42 | 2010-10-25 18:18:54 +0000 | [diff] [blame] | 195 | "                              writer lock is held longer than the specified\n" | 
 | 196 | "                              time (in milliseconds) [off].\n" | 
| bart | 1a3b0b3 | 2009-05-03 17:07:34 +0000 | [diff] [blame] | 197 | "    --first-race-only=yes|no  Only report the first data race that occurs on\n" | 
 | 198 | "                              a memory location instead of all races [no].\n" | 
| bart | 639d0ad | 2011-03-12 14:26:01 +0000 | [diff] [blame] | 199 | "    --free-is-write=yes|no    Whether to report races between freeing memory\n" | 
 | 200 | "                              and subsequent accesses of that memory[no].\n" | 
| bart | 505b35c | 2011-10-13 18:51:47 +0000 | [diff] [blame] | 201 | "    --join-list-vol=<n>       Number of threads to delay cleanup for [10].\n" | 
| bart | 46b5fce | 2008-06-28 13:01:30 +0000 | [diff] [blame] | 202 | "    --report-signal-unlocked=yes|no Whether to report calls to\n" | 
 | 203 | "                              pthread_cond_signal() where the mutex associated\n" | 
 | 204 | "                              with the signal via pthread_cond_wait() is not\n" | 
 | 205 | "                              locked at the time the signal is sent [yes].\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 206 | "    --segment-merging=yes|no  Controls segment merging [yes].\n" | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 207 | "        Segment merging is an algorithm to limit memory usage of the\n" | 
 | 208 | "        data race detection algorithm. Disabling segment merging may\n" | 
 | 209 | "        improve the accuracy of the so-called 'other segments' displayed\n" | 
 | 210 | "        in race reports but can also trigger an out of memory error.\n" | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 211 | "    --segment-merging-interval=<n> Perform segment merging every time n new\n" | 
 | 212 | "        segments have been created. Default: %d.\n" | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 213 | "    --shared-threshold=<n>    Print an error message if a reader lock\n" | 
| bart | 8600c42 | 2010-10-25 18:18:54 +0000 | [diff] [blame] | 214 | "                              is held longer than the specified time (in\n" | 
 | 215 | "                              milliseconds) [off]\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 216 | "    --show-confl-seg=yes|no   Show conflicting segments in race reports [yes].\n" | 
 | 217 | "    --show-stack-usage=yes|no Print stack usage at thread exit time [no].\n" | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 218 | "\n" | 
| bart | ef1b972 | 2008-07-04 15:34:23 +0000 | [diff] [blame] | 219 | "  drd options for monitoring process behavior:\n" | 
| bart | 8c3de75 | 2011-12-12 15:49:00 +0000 | [diff] [blame] | 220 | "    --trace-addr=<address>    Trace all load and store activity for the\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 221 | "                              specified address [off].\n" | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 222 | "    --trace-alloc=yes|no      Trace all memory allocations and deallocations\n""                              [no].\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 223 | "    --trace-barrier=yes|no    Trace all barrier activity [no].\n" | 
 | 224 | "    --trace-cond=yes|no       Trace all condition variable activity [no].\n" | 
 | 225 | "    --trace-fork-join=yes|no  Trace all thread fork/join activity [no].\n" | 
| bart | 505b35c | 2011-10-13 18:51:47 +0000 | [diff] [blame] | 226 | "    --trace-hb=yes|no         Trace ANNOTATE_HAPPENS_BEFORE() etc. [no].\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 227 | "    --trace-mutex=yes|no      Trace all mutex activity [no].\n" | 
 | 228 | "    --trace-rwlock=yes|no     Trace all reader-writer lock activity[no].\n" | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 229 | "    --trace-semaphore=yes|no  Trace all semaphore activity [no].\n", | 
 | 230 | DRD_(thread_get_segment_merge_interval)() | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 231 | ); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 232 | } | 
 | 233 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 234 | static void DRD_(print_debug_usage)(void) | 
| bart | 31b983d | 2010-02-21 14:52:59 +0000 | [diff] [blame] | 235 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 236 |    VG_(printf)( | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 237 | "    --drd-stats=yes|no        Print statistics about DRD activity [no].\n" | 
 | 238 | "    --trace-clientobj=yes|no  Trace all client object activity [no].\n" | 
 | 239 | "    --trace-csw=yes|no        Trace all scheduler context switches [no].\n" | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 240 | "    --trace-conflict-set=yes|no Trace all conflict set updates [no].\n" | 
| bart | 8f822af | 2009-06-08 18:20:42 +0000 | [diff] [blame] | 241 | "    --trace-conflict-set-bm=yes|no Trace all conflict set bitmap\n" | 
 | 242 | "                              updates [no]. Note: enabling this option\n" | 
 | 243 | "                              will generate a lot of output !\n" | 
| bart | 987781d | 2008-06-27 15:00:07 +0000 | [diff] [blame] | 244 | "    --trace-segment=yes|no    Trace segment actions [no].\n" | 
 | 245 | "    --trace-suppr=yes|no      Trace all address suppression actions [no].\n" | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 246 | ); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 247 | } | 
 | 248 |  | 
 | 249 |  | 
 | 250 | // | 
 | 251 | // Implements the thread-related core callbacks. | 
 | 252 | // | 
 | 253 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 254 | static void drd_pre_mem_read(const CorePart part, | 
 | 255 |                              const ThreadId tid, | 
 | 256 |                              Char* const s, | 
 | 257 |                              const Addr a, | 
 | 258 |                              const SizeT size) | 
 | 259 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 260 |    if (size > 0) | 
 | 261 |    { | 
 | 262 |       DRD_(trace_load)(a, size); | 
 | 263 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 264 | } | 
 | 265 |  | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 266 | static void drd_pre_mem_read_asciiz(const CorePart part, | 
 | 267 |                                     const ThreadId tid, | 
 | 268 |                                     Char* const s, | 
 | 269 |                                     const Addr a) | 
 | 270 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 271 |    const char* p = (void*)a; | 
 | 272 |    SizeT size = 0; | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 273 |  | 
| sewardj | 234e558 | 2011-02-09 12:47:23 +0000 | [diff] [blame] | 274 |    // Don't segfault if the string starts in an obviously stupid | 
 | 275 |    // place.  Actually we should check the whole string, not just | 
 | 276 |    // the start address, but that's too much trouble.  At least | 
 | 277 |    // checking the first byte is better than nothing.  See #255009. | 
 | 278 |    if (!VG_(am_is_valid_for_client) (a, 1, VKI_PROT_READ)) | 
 | 279 |       return; | 
 | 280 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 281 |    /* Note: the expression '*p' reads client memory and may crash if the */ | 
 | 282 |    /* client provided an invalid pointer !                               */ | 
 | 283 |    while (*p) | 
 | 284 |    { | 
 | 285 |       p++; | 
 | 286 |       size++; | 
 | 287 |    } | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 288 |    if (size > 0) | 
 | 289 |    { | 
 | 290 |       DRD_(trace_load)(a, size); | 
 | 291 |    } | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 292 | } | 
 | 293 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 294 | static void drd_post_mem_write(const CorePart part, | 
 | 295 |                                const ThreadId tid, | 
 | 296 |                                const Addr a, | 
 | 297 |                                const SizeT size) | 
 | 298 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 299 |    DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); | 
 | 300 |    if (size > 0) | 
 | 301 |    { | 
 | 302 |       DRD_(trace_store)(a, size); | 
 | 303 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 304 | } | 
 | 305 |  | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 306 | static __inline__ | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 307 | void drd_start_using_mem(const Addr a1, const SizeT len, | 
 | 308 |                          const Bool is_stack_mem) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 309 | { | 
| bart | 639d0ad | 2011-03-12 14:26:01 +0000 | [diff] [blame] | 310 |    const Addr a2 = a1 + len; | 
 | 311 |  | 
 | 312 |    tl_assert(a1 <= a2); | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 313 |  | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 314 |    if (!is_stack_mem && s_trace_alloc) | 
| bart | ad994e8 | 2011-10-13 18:04:30 +0000 | [diff] [blame] | 315 |       DRD_(trace_msg)("Started using memory range 0x%lx + %ld%s", | 
| bart | b92ff0f | 2011-10-08 08:29:29 +0000 | [diff] [blame] | 316 |                       a1, len, DRD_(running_thread_inside_pthread_create)() | 
 | 317 |                       ? " (inside pthread_create())" : ""); | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 318 |  | 
| bart | 7d5f523 | 2011-03-13 09:08:10 +0000 | [diff] [blame] | 319 |    if (!is_stack_mem && DRD_(g_free_is_write)) | 
| bart | 639d0ad | 2011-03-12 14:26:01 +0000 | [diff] [blame] | 320 |       DRD_(thread_stop_using_mem)(a1, a2); | 
 | 321 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 322 |    if (UNLIKELY(DRD_(any_address_is_traced)())) | 
 | 323 |    { | 
| bart | 42f3263 | 2011-12-13 11:12:05 +0000 | [diff] [blame^] | 324 |       DRD_(trace_mem_access)(a1, len, eStart, 0, 0); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 325 |    } | 
| bart | 31b983d | 2010-02-21 14:52:59 +0000 | [diff] [blame] | 326 |  | 
| bart | dd75cdf | 2009-07-24 08:20:10 +0000 | [diff] [blame] | 327 |    if (UNLIKELY(DRD_(running_thread_inside_pthread_create)())) | 
 | 328 |    { | 
| bart | 639d0ad | 2011-03-12 14:26:01 +0000 | [diff] [blame] | 329 |       DRD_(start_suppression)(a1, a2, "pthread_create()"); | 
| bart | dd75cdf | 2009-07-24 08:20:10 +0000 | [diff] [blame] | 330 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 331 | } | 
 | 332 |  | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 333 | static void drd_start_using_mem_w_ecu(const Addr a1, | 
 | 334 |                                       const SizeT len, | 
 | 335 |                                       UInt ec_uniq) | 
 | 336 | { | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 337 |    drd_start_using_mem(a1, len, False); | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 338 | } | 
 | 339 |  | 
 | 340 | static void drd_start_using_mem_w_tid(const Addr a1, | 
 | 341 |                                       const SizeT len, | 
 | 342 |                                       ThreadId tid) | 
 | 343 | { | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 344 |    drd_start_using_mem(a1, len, False); | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 345 | } | 
 | 346 |  | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 347 | static __inline__ | 
 | 348 | void drd_stop_using_mem(const Addr a1, const SizeT len, | 
 | 349 |                         const Bool is_stack_mem) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 350 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 351 |    const Addr a2 = a1 + len; | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 352 |  | 
| bart | a300398 | 2010-09-08 16:29:17 +0000 | [diff] [blame] | 353 |    tl_assert(a1 <= a2); | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 354 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 355 |    if (UNLIKELY(DRD_(any_address_is_traced)())) | 
| bart | 42f3263 | 2011-12-13 11:12:05 +0000 | [diff] [blame^] | 356 |       DRD_(trace_mem_access)(a1, len, eEnd, 0, 0); | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 357 |  | 
 | 358 |    if (!is_stack_mem && s_trace_alloc) | 
| bart | ad994e8 | 2011-10-13 18:04:30 +0000 | [diff] [blame] | 359 |       DRD_(trace_msg)("Stopped using memory range 0x%lx + %ld", | 
| bart | b92ff0f | 2011-10-08 08:29:29 +0000 | [diff] [blame] | 360 |                       a1, len); | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 361 |  | 
| bart | 0759503 | 2010-08-29 09:51:06 +0000 | [diff] [blame] | 362 |    if (!is_stack_mem || DRD_(get_check_stack_accesses)()) | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 363 |    { | 
| bart | 7d5f523 | 2011-03-13 09:08:10 +0000 | [diff] [blame] | 364 |       if (is_stack_mem || !DRD_(g_free_is_write)) | 
| bart | 639d0ad | 2011-03-12 14:26:01 +0000 | [diff] [blame] | 365 | 	 DRD_(thread_stop_using_mem)(a1, a2); | 
| bart | 7d5f523 | 2011-03-13 09:08:10 +0000 | [diff] [blame] | 366 |       else if (DRD_(g_free_is_write)) | 
| bart | 639d0ad | 2011-03-12 14:26:01 +0000 | [diff] [blame] | 367 | 	 DRD_(trace_store)(a1, len); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 368 |       DRD_(clientobj_stop_using_mem)(a1, a2); | 
 | 369 |       DRD_(suppression_stop_using_mem)(a1, a2); | 
 | 370 |    } | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 371 | } | 
 | 372 |  | 
 | 373 | static __inline__ | 
 | 374 | void drd_stop_using_nonstack_mem(const Addr a1, const SizeT len) | 
 | 375 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 376 |    drd_stop_using_mem(a1, len, False); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 377 | } | 
 | 378 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 379 | /** | 
| bart | fdaa018 | 2009-03-10 09:25:32 +0000 | [diff] [blame] | 380 |  * Discard all information DRD has about memory accesses and client objects | 
 | 381 |  * in the specified address range. | 
 | 382 |  */ | 
 | 383 | void DRD_(clean_memory)(const Addr a1, const SizeT len) | 
 | 384 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 385 |    const Bool is_stack_memory = DRD_(thread_address_on_any_stack)(a1); | 
 | 386 |    drd_stop_using_mem(a1, len, is_stack_memory); | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 387 |    drd_start_using_mem(a1, len, is_stack_memory); | 
| bart | fdaa018 | 2009-03-10 09:25:32 +0000 | [diff] [blame] | 388 | } | 
 | 389 |  | 
 | 390 | /** | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 391 |  * Suppress data race reports on all addresses contained in .plt and | 
 | 392 |  * .got.plt sections inside the address range [ a, a + len [. The data in | 
 | 393 |  * these sections is modified by _dl_relocate_object() every time a function | 
 | 394 |  * in a shared library is called for the first time. Since the first call | 
 | 395 |  * to a function in a shared library can happen from a multithreaded context, | 
 | 396 |  * such calls can cause conflicting accesses. See also Ulrich Drepper's | 
 | 397 |  * paper "How to Write Shared Libraries" for more information about relocation | 
 | 398 |  * (http://people.redhat.com/drepper/dsohowto.pdf). | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 399 |  */ | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 400 | static void DRD_(suppress_relocation_conflicts)(const Addr a, const SizeT len) | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 401 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 402 |    const DebugInfo* di; | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 403 |  | 
 | 404 | #if 0 | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 405 |    VG_(printf)("Evaluating range @ 0x%lx size %ld\n", a, len); | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 406 | #endif | 
 | 407 |  | 
| sewardj | e3f1e59 | 2009-07-31 09:41:29 +0000 | [diff] [blame] | 408 |    for (di = VG_(next_DebugInfo)(0); di; di = VG_(next_DebugInfo)(di)) | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 409 |    { | 
 | 410 |       Addr  avma; | 
 | 411 |       SizeT size; | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 412 |  | 
| sewardj | e3f1e59 | 2009-07-31 09:41:29 +0000 | [diff] [blame] | 413 |       avma = VG_(DebugInfo_get_plt_avma)(di); | 
 | 414 |       size = VG_(DebugInfo_get_plt_size)(di); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 415 |       tl_assert((avma && size) || (avma == 0 && size == 0)); | 
 | 416 |       if (size > 0) | 
 | 417 |       { | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 418 | #if 0 | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 419 |          VG_(printf)("Suppressing .plt @ 0x%lx size %ld\n", avma, size); | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 420 | #endif | 
| sewardj | e3f1e59 | 2009-07-31 09:41:29 +0000 | [diff] [blame] | 421 |          tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectPLT); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 422 |          DRD_(start_suppression)(avma, avma + size, ".plt"); | 
 | 423 |       } | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 424 |  | 
| sewardj | e3f1e59 | 2009-07-31 09:41:29 +0000 | [diff] [blame] | 425 |       avma = VG_(DebugInfo_get_gotplt_avma)(di); | 
 | 426 |       size = VG_(DebugInfo_get_gotplt_size)(di); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 427 |       tl_assert((avma && size) || (avma == 0 && size == 0)); | 
 | 428 |       if (size > 0) | 
 | 429 |       { | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 430 | #if 0 | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 431 |          VG_(printf)("Suppressing .got.plt @ 0x%lx size %ld\n", avma, size); | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 432 | #endif | 
| sewardj | e3f1e59 | 2009-07-31 09:41:29 +0000 | [diff] [blame] | 433 |          tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectGOTPLT); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 434 |          DRD_(start_suppression)(avma, avma + size, ".gotplt"); | 
 | 435 |       } | 
 | 436 |    } | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 437 | } | 
 | 438 |  | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 439 | static | 
 | 440 | void drd_start_using_mem_w_perms(const Addr a, const SizeT len, | 
| sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 441 |                                  const Bool rr, const Bool ww, const Bool xx, | 
 | 442 |                                  ULong di_handle) | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 443 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 444 |    DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); | 
| bart | d576591 | 2008-03-16 08:40:55 +0000 | [diff] [blame] | 445 |  | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 446 |    drd_start_using_mem(a, len, False); | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 447 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 448 |    DRD_(suppress_relocation_conflicts)(a, len); | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 449 | } | 
 | 450 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 451 | /* Called by the core when the stack of a thread grows, to indicate that */ | 
 | 452 | /* the addresses in range [ a, a + len [ may now be used by the client.  */ | 
 | 453 | /* Assumption: stacks grow downward.                                     */ | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 454 | static __inline__ | 
 | 455 | void drd_start_using_mem_stack(const Addr a, const SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 456 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 457 |    DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(), | 
 | 458 |                               a - VG_STACK_REDZONE_SZB); | 
| bart | 31b983d | 2010-02-21 14:52:59 +0000 | [diff] [blame] | 459 |    drd_start_using_mem(a - VG_STACK_REDZONE_SZB, | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 460 |                        len + VG_STACK_REDZONE_SZB, | 
 | 461 |                        True); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 462 | } | 
 | 463 |  | 
 | 464 | /* Called by the core when the stack of a thread shrinks, to indicate that */ | 
 | 465 | /* the addresses [ a, a + len [ are no longer accessible for the client.   */ | 
 | 466 | /* Assumption: stacks grow downward.                                       */ | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 467 | static __inline__ | 
 | 468 | void drd_stop_using_mem_stack(const Addr a, const SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 469 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 470 |    DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(), | 
 | 471 |                               a + len - VG_STACK_REDZONE_SZB); | 
 | 472 |    drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB, | 
 | 473 |                       True); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 474 | } | 
 | 475 |  | 
| bart | 68a8afa | 2010-09-02 14:50:41 +0000 | [diff] [blame] | 476 | static | 
 | 477 | Bool on_alt_stack(const Addr a) | 
 | 478 | { | 
 | 479 |    ThreadId vg_tid; | 
 | 480 |    Addr alt_min; | 
 | 481 |    SizeT alt_size; | 
 | 482 |  | 
 | 483 |    vg_tid = VG_(get_running_tid)(); | 
 | 484 |    alt_min = VG_(thread_get_altstack_min)(vg_tid); | 
 | 485 |    alt_size = VG_(thread_get_altstack_size)(vg_tid); | 
 | 486 |    return (SizeT)(a - alt_min) < alt_size; | 
 | 487 | } | 
 | 488 |  | 
 | 489 | static | 
 | 490 | void drd_start_using_mem_alt_stack(const Addr a, const SizeT len) | 
 | 491 | { | 
 | 492 |    if (!on_alt_stack(a)) | 
 | 493 |       drd_start_using_mem_stack(a, len); | 
 | 494 | } | 
 | 495 |  | 
 | 496 | static | 
 | 497 | void drd_stop_using_mem_alt_stack(const Addr a, const SizeT len) | 
 | 498 | { | 
 | 499 |    if (!on_alt_stack(a)) | 
 | 500 |       drd_stop_using_mem_stack(a, len); | 
 | 501 | } | 
 | 502 |  | 
 | 503 | /** | 
 | 504 |  * Callback function invoked by the Valgrind core before a signal is delivered. | 
 | 505 |  */ | 
 | 506 | static | 
 | 507 | void drd_pre_deliver_signal(const ThreadId vg_tid, const Int sigNo, | 
 | 508 |                             const Bool alt_stack) | 
 | 509 | { | 
 | 510 |    DrdThreadId drd_tid; | 
 | 511 |  | 
 | 512 |    drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); | 
 | 513 |    DRD_(thread_set_on_alt_stack)(drd_tid, alt_stack); | 
 | 514 |    if (alt_stack) | 
 | 515 |    { | 
 | 516 |       /* | 
 | 517 |        * As soon a signal handler has been invoked on the alternate stack, | 
 | 518 |        * switch to stack memory handling functions that can handle the | 
 | 519 |        * alternate stack. | 
 | 520 |        */ | 
 | 521 |       VG_(track_new_mem_stack)(drd_start_using_mem_alt_stack); | 
 | 522 |       VG_(track_die_mem_stack)(drd_stop_using_mem_alt_stack); | 
 | 523 |    } | 
 | 524 | } | 
 | 525 |  | 
 | 526 | /** | 
 | 527 |  * Callback function invoked by the Valgrind core after a signal is delivered, | 
 | 528 |  * at least if the signal handler did not longjmp(). | 
 | 529 |  */ | 
 | 530 | static | 
 | 531 | void drd_post_deliver_signal(const ThreadId vg_tid, const Int sigNo) | 
 | 532 | { | 
 | 533 |    DrdThreadId drd_tid; | 
 | 534 |  | 
 | 535 |    drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); | 
 | 536 |    DRD_(thread_set_on_alt_stack)(drd_tid, False); | 
 | 537 |    if (DRD_(thread_get_threads_on_alt_stack)() == 0) | 
 | 538 |    { | 
 | 539 |       VG_(track_new_mem_stack)(drd_start_using_mem_stack); | 
 | 540 |       VG_(track_die_mem_stack)(drd_stop_using_mem_stack); | 
 | 541 |    } | 
 | 542 | } | 
 | 543 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 544 | /** | 
 | 545 |  * Callback function called by the Valgrind core before a stack area is | 
 | 546 |  * being used by a signal handler. | 
 | 547 |  * | 
 | 548 |  * @param[in] a   Start of address range. | 
 | 549 |  * @param[in] len Address range length. | 
 | 550 |  * @param[in] tid Valgrind thread ID for whom the signal frame is being | 
 | 551 |  *                constructed. | 
 | 552 |  */ | 
 | 553 | static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len, | 
 | 554 |                                              ThreadId tid) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 555 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 556 |    DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)()); | 
| bart | f9427fd | 2010-08-29 09:19:07 +0000 | [diff] [blame] | 557 |    drd_start_using_mem(a, len, True); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 558 | } | 
 | 559 |  | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 560 | static void drd_stop_using_mem_stack_signal(Addr a, SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 561 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 562 |    drd_stop_using_mem(a, len, True); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 563 | } | 
 | 564 |  | 
 | 565 | static | 
 | 566 | void drd_pre_thread_create(const ThreadId creator, const ThreadId created) | 
 | 567 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 568 |    const DrdThreadId drd_creator = DRD_(VgThreadIdToDrdThreadId)(creator); | 
 | 569 |    tl_assert(created != VG_INVALID_THREADID); | 
 | 570 |    DRD_(thread_pre_create)(drd_creator, created); | 
 | 571 |    if (DRD_(IsValidDrdThreadId)(drd_creator)) | 
 | 572 |    { | 
 | 573 |       DRD_(thread_new_segment)(drd_creator); | 
 | 574 |    } | 
 | 575 |    if (DRD_(thread_get_trace_fork_join)()) | 
 | 576 |    { | 
| bart | ad994e8 | 2011-10-13 18:04:30 +0000 | [diff] [blame] | 577 |       DRD_(trace_msg)("drd_pre_thread_create creator = %d, created = %d", | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 578 |                       drd_creator, created); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 579 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 580 | } | 
 | 581 |  | 
 | 582 | /* Called by Valgrind's core before any loads or stores are performed on */ | 
 | 583 | /* the context of thread "created". At startup, this function is called  */ | 
 | 584 | /* with arguments (0,1).                                                 */ | 
 | 585 | static | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 586 | void drd_post_thread_create(const ThreadId vg_created) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 587 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 588 |    DrdThreadId drd_created; | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 589 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 590 |    tl_assert(vg_created != VG_INVALID_THREADID); | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 591 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 592 |    drd_created = DRD_(thread_post_create)(vg_created); | 
 | 593 |    if (DRD_(thread_get_trace_fork_join)()) | 
 | 594 |    { | 
| bart | ad994e8 | 2011-10-13 18:04:30 +0000 | [diff] [blame] | 595 |       DRD_(trace_msg)("drd_post_thread_create created = %d", drd_created); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 596 |    } | 
 | 597 |    if (! DRD_(get_check_stack_accesses)()) | 
 | 598 |    { | 
 | 599 |       DRD_(start_suppression)(DRD_(thread_get_stack_max)(drd_created) | 
 | 600 |                               - DRD_(thread_get_stack_size)(drd_created), | 
 | 601 |                               DRD_(thread_get_stack_max)(drd_created), | 
 | 602 |                               "stack"); | 
 | 603 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 604 | } | 
 | 605 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 606 | /* Called after a thread has performed its last memory access. */ | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 607 | static void drd_thread_finished(ThreadId vg_tid) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 608 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 609 |    DrdThreadId drd_tid; | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 610 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 611 |    tl_assert(VG_(get_running_tid)() == vg_tid); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 612 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 613 |    drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); | 
 | 614 |    if (DRD_(thread_get_trace_fork_join)()) | 
 | 615 |    { | 
| bart | ad994e8 | 2011-10-13 18:04:30 +0000 | [diff] [blame] | 616 |       DRD_(trace_msg)("drd_thread_finished tid = %d%s", drd_tid, | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 617 |                       DRD_(thread_get_joinable)(drd_tid) | 
 | 618 |                       ? "" : " (which is a detached thread)"); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 619 |    } | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 620 |    if (s_show_stack_usage && !VG_(clo_xml)) { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 621 |       const SizeT stack_size = DRD_(thread_get_stack_size)(drd_tid); | 
 | 622 |       const SizeT used_stack | 
 | 623 |          = (DRD_(thread_get_stack_max)(drd_tid) | 
 | 624 |             - DRD_(thread_get_stack_min_min)(drd_tid)); | 
 | 625 |       VG_(message)(Vg_UserMsg, | 
| bart | 63c92ea | 2009-07-19 17:53:56 +0000 | [diff] [blame] | 626 |                    "thread %d%s finished and used %ld bytes out of %ld" | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 627 |                    " on its stack. Margin: %ld bytes.\n", | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 628 |                    drd_tid, | 
 | 629 |                    DRD_(thread_get_joinable)(drd_tid) | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 630 |                    ? "" : " (which is a detached thread)", | 
 | 631 |                    used_stack, stack_size, stack_size - used_stack); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 632 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 633 |    } | 
 | 634 |    drd_stop_using_mem(DRD_(thread_get_stack_min)(drd_tid), | 
 | 635 |                       DRD_(thread_get_stack_max)(drd_tid) | 
 | 636 |                       - DRD_(thread_get_stack_min)(drd_tid), | 
 | 637 |                       True); | 
| bart | d45d995 | 2009-05-31 18:53:54 +0000 | [diff] [blame] | 638 |    DRD_(thread_set_record_loads)(drd_tid, False); | 
 | 639 |    DRD_(thread_set_record_stores)(drd_tid, False); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 640 |    DRD_(thread_finished)(drd_tid); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 641 | } | 
 | 642 |  | 
| bart | 5c7e6b6 | 2011-02-03 17:47:50 +0000 | [diff] [blame] | 643 | /* | 
 | 644 |  * Called immediately after fork for the child process only. 'tid' is the | 
 | 645 |  * only surviving thread in the child process. Cleans up thread state. | 
 | 646 |  * See also http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html for a detailed discussion of using fork() in combination with mutexes. | 
 | 647 |  */ | 
 | 648 | static | 
 | 649 | void drd__atfork_child(ThreadId tid) | 
 | 650 | { | 
 | 651 |    DRD_(drd_thread_atfork_child)(tid); | 
 | 652 | } | 
 | 653 |  | 
 | 654 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 655 | // | 
 | 656 | // Implementation of the tool interface. | 
 | 657 | // | 
 | 658 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 659 | static void DRD_(post_clo_init)(void) | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 660 | { | 
| bart | 0c6bf35 | 2009-07-25 14:03:53 +0000 | [diff] [blame] | 661 | #if defined(VGO_linux) || defined(VGO_darwin) | 
| bart | c6ef4af | 2009-07-23 10:10:30 +0000 | [diff] [blame] | 662 |    /* fine */ | 
| bart | c6ef4af | 2009-07-23 10:10:30 +0000 | [diff] [blame] | 663 | #else | 
 | 664 |    VG_(printf)("\nWARNING: DRD has not yet been tested on this operating system.\n\n"); | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 665 | #  endif | 
| bart | 95761b5 | 2008-03-29 08:34:03 +0000 | [diff] [blame] | 666 |  | 
| bart | 75c1cba | 2010-08-29 07:20:30 +0000 | [diff] [blame] | 667 |    if (s_var_info) | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 668 |    { | 
 | 669 |       VG_(needs_var_info)(); | 
 | 670 |    } | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 671 | } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 672 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 673 | static void drd_start_client_code(const ThreadId tid, const ULong bbs_done) | 
 | 674 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 675 |    tl_assert(tid == VG_(get_running_tid)()); | 
 | 676 |    DRD_(thread_set_vg_running_tid)(tid); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 677 | } | 
 | 678 |  | 
| bart | 1335ecc | 2009-02-14 16:10:53 +0000 | [diff] [blame] | 679 | static void DRD_(fini)(Int exitcode) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 680 | { | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 681 |    // thread_print_all(); | 
| sewardj | 2d9e874 | 2009-08-07 15:46:56 +0000 | [diff] [blame] | 682 |    if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) { | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 683 |       VG_(message)(Vg_UserMsg, "For counts of detected and suppressed errors, " | 
| sewardj | 2d9e874 | 2009-08-07 15:46:56 +0000 | [diff] [blame] | 684 |                    "rerun with: -v\n"); | 
 | 685 |    } | 
 | 686 |  | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 687 |    if ((VG_(clo_stats) || s_print_stats) && !VG_(clo_xml)) | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 688 |    { | 
| bart | e521466 | 2009-06-21 11:51:23 +0000 | [diff] [blame] | 689 |       ULong pu = DRD_(thread_get_update_conflict_set_count)(); | 
 | 690 |       ULong pu_seg_cr = DRD_(thread_get_update_conflict_set_new_sg_count)(); | 
 | 691 |       ULong pu_mtx_cv = DRD_(thread_get_update_conflict_set_sync_count)(); | 
 | 692 |       ULong pu_join   = DRD_(thread_get_update_conflict_set_join_count)(); | 
 | 693 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 694 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 695 |                    "   thread: %lld context switches.\n", | 
| bart | 54803fe | 2009-06-21 09:26:27 +0000 | [diff] [blame] | 696 |                    DRD_(thread_get_context_switch_count)()); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 697 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 698 |                    "confl set: %lld full updates and %lld partial updates;\n", | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 699 |                    DRD_(thread_get_compute_conflict_set_count)(), | 
 | 700 |                    pu); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 701 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 702 |                    "           %lld partial updates during segment creation,\n", | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 703 |                    pu_seg_cr); | 
| bart | e521466 | 2009-06-21 11:51:23 +0000 | [diff] [blame] | 704 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 705 |                    "           %lld because of mutex/sema/cond.var. operations,\n", | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 706 |                    pu_mtx_cv); | 
| bart | e521466 | 2009-06-21 11:51:23 +0000 | [diff] [blame] | 707 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 708 |                    "           %lld because of barrier/rwlock operations and\n", | 
| bart | e521466 | 2009-06-21 11:51:23 +0000 | [diff] [blame] | 709 | 		   pu - pu_seg_cr - pu_mtx_cv - pu_join); | 
 | 710 |       VG_(message)(Vg_UserMsg, | 
 | 711 |                    "           %lld partial updates because of thread join" | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 712 |                    " operations.\n", | 
 | 713 |                    pu_join); | 
| bart | e521466 | 2009-06-21 11:51:23 +0000 | [diff] [blame] | 714 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 715 |                    " segments: created %lld segments, max %lld alive,\n", | 
| bart | 9dedafe | 2009-06-21 18:09:02 +0000 | [diff] [blame] | 716 |                    DRD_(sg_get_segments_created_count)(), | 
 | 717 |                    DRD_(sg_get_max_segments_alive_count)()); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 718 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 719 |                    "           %lld discard points and %lld merges.\n", | 
| bart | 9dedafe | 2009-06-21 18:09:02 +0000 | [diff] [blame] | 720 |                    DRD_(thread_get_discard_ordered_segments_count)(), | 
| bart | 1a3b0b3 | 2009-05-03 17:07:34 +0000 | [diff] [blame] | 721 |                    DRD_(sg_get_segment_merge_count)()); | 
 | 722 |       VG_(message)(Vg_UserMsg, | 
| bart | 54803fe | 2009-06-21 09:26:27 +0000 | [diff] [blame] | 723 |                    "segmnt cr: %lld mutex, %lld rwlock, %lld semaphore and" | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 724 |                    " %lld barrier.\n", | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 725 |                    DRD_(get_mutex_segment_creation_count)(), | 
 | 726 |                    DRD_(get_rwlock_segment_creation_count)(), | 
 | 727 |                    DRD_(get_semaphore_segment_creation_count)(), | 
 | 728 |                    DRD_(get_barrier_segment_creation_count)()); | 
 | 729 |       VG_(message)(Vg_UserMsg, | 
| bart | 9dedafe | 2009-06-21 18:09:02 +0000 | [diff] [blame] | 730 |                    "  bitmaps: %lld level one" | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 731 |                    " and %lld level two bitmaps were allocated.\n", | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 732 |                    DRD_(bm_get_bitmap_creation_count)(), | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 733 |                    DRD_(bm_get_bitmap2_creation_count)()); | 
 | 734 |       VG_(message)(Vg_UserMsg, | 
| sewardj | 1e29ebc | 2009-07-15 14:49:17 +0000 | [diff] [blame] | 735 |                    "    mutex: %lld non-recursive lock/unlock events.\n", | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 736 |                    DRD_(get_mutex_lock_count)()); | 
 | 737 |       DRD_(print_malloc_stats)(); | 
 | 738 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 739 | } | 
 | 740 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 741 | static | 
 | 742 | void drd_pre_clo_init(void) | 
 | 743 | { | 
| njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 744 |    // Basic tool stuff. | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 745 |    VG_(details_name)            ("drd"); | 
 | 746 |    VG_(details_version)         (NULL); | 
 | 747 |    VG_(details_description)     ("a thread error detector"); | 
| bart | 922304f | 2011-03-13 12:02:44 +0000 | [diff] [blame] | 748 |    VG_(details_copyright_author)("Copyright (C) 2006-2011, and GNU GPL'd," | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 749 |                                  " by Bart Van Assche."); | 
 | 750 |    VG_(details_bug_reports_to)  (VG_BUGS_TO); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 751 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 752 |    VG_(basic_tool_funcs)        (DRD_(post_clo_init), | 
 | 753 |                                  DRD_(instrument), | 
 | 754 |                                  DRD_(fini)); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 755 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 756 |    // Command line stuff. | 
 | 757 |    VG_(needs_command_line_options)(DRD_(process_cmd_line_option), | 
 | 758 |                                    DRD_(print_usage), | 
 | 759 |                                    DRD_(print_debug_usage)); | 
| bart | e708600 | 2011-10-11 19:08:39 +0000 | [diff] [blame] | 760 |    VG_(needs_xml_output)          (); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 761 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 762 |    // Error handling. | 
 | 763 |    DRD_(register_error_handlers)(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 764 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 765 |    // Core event tracking. | 
 | 766 |    VG_(track_pre_mem_read)         (drd_pre_mem_read); | 
 | 767 |    VG_(track_pre_mem_read_asciiz)  (drd_pre_mem_read_asciiz); | 
 | 768 |    VG_(track_post_mem_write)       (drd_post_mem_write); | 
 | 769 |    VG_(track_new_mem_brk)          (drd_start_using_mem_w_tid); | 
 | 770 |    VG_(track_new_mem_mmap)         (drd_start_using_mem_w_perms); | 
 | 771 |    VG_(track_new_mem_stack)        (drd_start_using_mem_stack); | 
 | 772 |    VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal); | 
 | 773 |    VG_(track_new_mem_startup)      (drd_start_using_mem_w_perms); | 
 | 774 |    VG_(track_die_mem_brk)          (drd_stop_using_nonstack_mem); | 
 | 775 |    VG_(track_die_mem_munmap)       (drd_stop_using_nonstack_mem); | 
 | 776 |    VG_(track_die_mem_stack)        (drd_stop_using_mem_stack); | 
 | 777 |    VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal); | 
| bart | 68a8afa | 2010-09-02 14:50:41 +0000 | [diff] [blame] | 778 |    VG_(track_pre_deliver_signal)   (drd_pre_deliver_signal); | 
 | 779 |    VG_(track_post_deliver_signal)  (drd_post_deliver_signal); | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 780 |    VG_(track_start_client_code)    (drd_start_client_code); | 
 | 781 |    VG_(track_pre_thread_ll_create) (drd_pre_thread_create); | 
 | 782 |    VG_(track_pre_thread_first_insn)(drd_post_thread_create); | 
 | 783 |    VG_(track_pre_thread_ll_exit)   (drd_thread_finished); | 
| bart | 5c7e6b6 | 2011-02-03 17:47:50 +0000 | [diff] [blame] | 784 |    VG_(atfork)                     (NULL/*pre*/, NULL/*parent*/, | 
 | 785 | 				    drd__atfork_child/*child*/); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 786 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 787 |    // Other stuff. | 
 | 788 |    DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu, | 
 | 789 |                                   drd_stop_using_nonstack_mem); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 790 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 791 |    DRD_(clientreq_init)(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 792 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 793 |    DRD_(suppression_init)(); | 
| bart | 4bb53d8 | 2008-02-28 19:06:34 +0000 | [diff] [blame] | 794 |  | 
| bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 795 |    DRD_(clientobj_init)(); | 
| bart | e5e0efa | 2009-06-24 18:35:02 +0000 | [diff] [blame] | 796 |  | 
 | 797 |    { | 
 | 798 |       Char* const smi = VG_(getenv)("DRD_SEGMENT_MERGING_INTERVAL"); | 
 | 799 |       if (smi) | 
 | 800 |          DRD_(thread_set_segment_merge_interval)(VG_(strtoll10)(smi, NULL)); | 
 | 801 |    } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 802 | } | 
 | 803 |  | 
 | 804 |  | 
 | 805 | VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init) |