1 /* Copyright (c) 2008-2010, Google Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Neither the name of Google Inc. nor the names of its 11 * contributors may be used to endorse or promote products derived from 12 * this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 // This file is part of ThreadSanitizer, a dynamic data race detector. 28 // Author: Konstantin Serebryany. 29 //--------- Head ------------------- {{{1 30 #ifndef THREAD_SANITIZER_H_ 31 #define THREAD_SANITIZER_H_ 32 33 #include "ts_util.h" 34 #include "ts_atomic.h" 35 36 //--------- Utils ------------------- {{{1 37 38 void Report(const char *format, ...); 39 void PcToStrings(uintptr_t pc, bool demangle, 40 string *img_name, string *rtn_name, 41 string *file_name, int *line_no); 42 string PcToRtnNameAndFilePos(uintptr_t pc); 43 string PcToRtnName(uintptr_t pc, bool demangle); 44 string Demangle(const char *str); 45 46 47 //--------- FLAGS ---------------------------------- {{{1 48 struct FLAGS { 49 string input_type; // for ts_offline. 50 // Possible values: str, bin, decode. 51 bool ignore_stack; 52 intptr_t verbosity; 53 intptr_t show_stats; // 0 -- no stats; 1 -- some stats; 2 more stats. 54 bool trace_profile; 55 bool show_expected_races; 56 uintptr_t trace_addr; 57 uintptr_t segment_set_recycle_queue_size; 58 uintptr_t recent_segments_cache_size; 59 vector<string> file_prefix_to_cut; 60 vector<string> ignore; 61 vector<string> whitelist; 62 bool ignore_unknown_pcs; // Ignore PCs with no debug info. 63 vector<string> cut_stack_below; 64 string summary_file; 65 string log_file; 66 bool offline; 67 intptr_t max_n_threads; 68 bool compress_cache_lines; 69 bool unlock_on_mutex_destroy; 70 71 intptr_t sample_events; 72 intptr_t sample_events_depth; 73 74 intptr_t num_callers; 75 76 intptr_t keep_history; 77 bool pure_happens_before; 78 bool free_is_write; 79 bool exit_after_main; 80 bool demangle; 81 bool announce_threads; 82 bool full_output; 83 bool show_states; 84 bool show_proc_self_status; 85 bool show_valgrind_context; // debug-only 86 bool suggest_happens_before_arcs; 87 bool show_pc; 88 bool full_stack_frames; 89 bool color; // Colorify terminal output. 90 bool html; // Output in html format. 91 bool show_pid; 92 93 intptr_t debug_level; 94 bool save_ignore_context; // print stack if ignore_end was forgotten. 95 vector<string> debug_phase; 96 intptr_t trace_level; 97 98 intptr_t dry_run; 99 intptr_t max_sid; 100 intptr_t max_sid_before_flush; 101 intptr_t max_mem_in_mb; 102 intptr_t num_callers_in_history; 103 intptr_t flush_period; 104 105 intptr_t literace_sampling; 106 bool start_with_global_ignore_on; 107 108 intptr_t locking_scheme; // Used for internal experiments with locking. 109 110 bool report_races; 111 bool thread_coverage; 112 bool atomicity; 113 bool call_coverage; 114 string dump_events; // The name of log file. Debug mode only. 115 bool symbolize; 116 bool attach_mode; 117 118 string tsan_program_name; 119 string tsan_url; 120 121 vector<string> suppressions; 122 bool generate_suppressions; 123 124 intptr_t error_exitcode; 125 bool trace_children; 126 127 vector<string> race_verifier; 128 vector<string> race_verifier_extra; 129 intptr_t race_verifier_sleep_ms; 130 131 bool nacl_untrusted; 132 133 bool threaded_analysis; 134 135 bool sched_shake; 136 bool api_ambush; 137 138 bool enable_atomic; 139 }; 140 141 extern FLAGS *G_flags; 142 143 extern bool g_race_verifier_active; 144 145 extern bool debug_expected_races; 146 extern bool debug_malloc; 147 extern bool debug_free; 148 extern bool debug_thread; 149 extern bool debug_rtn; 150 extern bool debug_wrap; 151 extern bool debug_ins; 152 extern bool debug_shadow_stack; 153 extern bool debug_race_verifier; 154 155 // -------- CallStack ------------- {{{1 156 const size_t kMaxCallStackSize = 1 << 12; 157 158 struct CallStackPod { 159 uintptr_t *end_; 160 uintptr_t pcs_[kMaxCallStackSize]; 161 }; 162 163 struct CallStack: public CallStackPod { 164 165 CallStack() { Clear(); } 166 167 size_t size() { return (size_t)(end_ - pcs_); } 168 uintptr_t *pcs() { return pcs_; } 169 170 bool empty() { return end_ == pcs_; } 171 172 uintptr_t &back() { 173 DCHECK(!empty()); 174 return *(end_ - 1); 175 } 176 177 void pop_back() { 178 DCHECK(!empty()); 179 end_--; 180 } 181 182 void push_back(uintptr_t pc) { 183 DCHECK(size() < kMaxCallStackSize); 184 *end_ = pc; 185 end_++; 186 } 187 188 void Clear() { 189 end_ = pcs_; 190 } 191 192 uintptr_t &operator[] (size_t i) { 193 DCHECK(i < size()); 194 return pcs_[i]; 195 } 196 197 }; 198 199 //--------- TS Exports ----------------- {{{1 200 #include "ts_events.h" 201 #include "ts_trace_info.h" 202 203 struct TSanThread; 204 void ThreadSanitizerInit(); 205 void ThreadSanitizerFini(); 206 // TODO(glider): this is a temporary solution to avoid deadlocks after fork(). 207 #ifdef TS_LLVM 208 void ThreadSanitizerLockAcquire(); 209 void ThreadSanitizerLockRelease(); 210 #endif 211 void ThreadSanitizerHandleOneEvent(Event *event); 212 TSanThread *ThreadSanitizerGetThreadByTid(int32_t tid); 213 void ThreadSanitizerHandleTrace(int32_t tid, TraceInfo *trace_info, 214 uintptr_t *tleb); 215 void ThreadSanitizerHandleTrace(TSanThread *thr, TraceInfo *trace_info, 216 uintptr_t *tleb); 217 void ThreadSanitizerHandleOneMemoryAccess(TSanThread *thr, MopInfo mop, 218 uintptr_t addr); 219 void ThreadSanitizerParseFlags(vector<string>* args); 220 bool ThreadSanitizerWantToInstrumentSblock(uintptr_t pc); 221 bool ThreadSanitizerWantToCreateSegmentsOnSblockEntry(uintptr_t pc); 222 bool ThreadSanitizerIgnoreAccessesBelowFunction(uintptr_t pc); 223 224 typedef int (*ThreadSanitizerUnwindCallback)(uintptr_t* stack, int size, uintptr_t pc); 225 void ThreadSanitizerSetUnwindCallback(ThreadSanitizerUnwindCallback cb); 226 227 /** Atomic operation handler. 228 * @param tid ID of a thread that issues the operation. 229 * @param pc Program counter that should be associated with the operation. 230 * @param op Type of the operation (load, store, etc). 231 * @param mo Memory ordering associated with the operation 232 * (relaxed, acquire, release, etc). NB there are some restrictions on 233 * what memory orderings can be used with what types of operations. 234 * E.g. a store can't have an acquire semantics 235 * (see C++0x standard draft for details). 236 * @param fail_mo Memory ordering the operation has if it fails, 237 * applicable only to compare_exchange oprations. 238 * @param size Size of the memory access in bytes (1, 2, 4 or 8). 239 * @param a Address of the memory access. 240 * @param v Operand for the operation (e.g. a value to store). 241 * @param cmp Comparand for compare_exchange oprations. 242 * @return Result of the operation (e.g. loaded value). 243 */ 244 uint64_t ThreadSanitizerHandleAtomicOp(int32_t tid, 245 uintptr_t pc, 246 tsan_atomic_op op, 247 tsan_memory_order mo, 248 tsan_memory_order fail_mo, 249 size_t size, 250 void volatile* a, 251 uint64_t v, 252 uint64_t cmp); 253 254 enum IGNORE_BELOW_RTN { 255 IGNORE_BELOW_RTN_UNKNOWN, 256 IGNORE_BELOW_RTN_NO, 257 IGNORE_BELOW_RTN_YES 258 }; 259 260 void ThreadSanitizerHandleRtnCall(int32_t tid, uintptr_t call_pc, 261 uintptr_t target_pc, 262 IGNORE_BELOW_RTN ignore_below); 263 264 void ThreadSanitizerHandleRtnExit(int32_t tid); 265 266 void ThreadSanitizerPrintUsage(); 267 extern "C" const char *ThreadSanitizerQuery(const char *query); 268 bool PhaseDebugIsOn(const char *phase_name); 269 270 extern bool g_has_entered_main; 271 extern bool g_has_exited_main; 272 273 // -------- Stats ------------------- {{{1 274 #include "ts_stats.h" 275 extern Stats *G_stats; 276 277 // -------- Expected Race ---------------------- {{{1 278 // Information about expected races. 279 struct ExpectedRace { 280 uintptr_t ptr; 281 uintptr_t size; 282 bool is_verifiable; 283 bool is_nacl_untrusted; 284 int count; 285 const char *description; 286 uintptr_t pc; 287 }; 288 289 ExpectedRace* ThreadSanitizerFindExpectedRace(uintptr_t addr); 290 291 // Tell ThreadSanitizer about the location of NaCl untrusted region. 292 void ThreadSanitizerNaclUntrustedRegion(uintptr_t mem_start, uintptr_t mem_end); 293 294 // Returns true if accesses and locks at the given address should be ignored 295 // according to the current NaCl flags (--nacl-untrusted). Always false if not a 296 // NaCl program. 297 bool ThreadSanitizerIgnoreForNacl(uintptr_t addr); 298 299 // end. {{{1 300 #endif // THREAD_SANITIZER_H_ 301 302 // vim:shiftwidth=2:softtabstop=2:expandtab 303