/* Copyright (c) 2008-2010, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // This file is part of ThreadSanitizer, a dynamic data race detector. // Author: Konstantin Serebryany. //--------- Head ------------------- {{{1 #ifndef THREAD_SANITIZER_H_ #define THREAD_SANITIZER_H_ #include "ts_util.h" #include "ts_atomic.h" //--------- Utils ------------------- {{{1 void Report(const char *format, ...); void PcToStrings(uintptr_t pc, bool demangle, string *img_name, string *rtn_name, string *file_name, int *line_no); string PcToRtnNameAndFilePos(uintptr_t pc); string PcToRtnName(uintptr_t pc, bool demangle); string Demangle(const char *str); //--------- FLAGS ---------------------------------- {{{1 struct FLAGS { string input_type; // for ts_offline. // Possible values: str, bin, decode. bool ignore_stack; intptr_t verbosity; intptr_t show_stats; // 0 -- no stats; 1 -- some stats; 2 more stats. bool trace_profile; bool show_expected_races; uintptr_t trace_addr; uintptr_t segment_set_recycle_queue_size; uintptr_t recent_segments_cache_size; vector<string> file_prefix_to_cut; vector<string> ignore; vector<string> whitelist; bool ignore_unknown_pcs; // Ignore PCs with no debug info. vector<string> cut_stack_below; string summary_file; string log_file; bool offline; intptr_t max_n_threads; bool compress_cache_lines; bool unlock_on_mutex_destroy; intptr_t sample_events; intptr_t sample_events_depth; intptr_t num_callers; intptr_t keep_history; bool pure_happens_before; bool free_is_write; bool exit_after_main; bool demangle; bool announce_threads; bool full_output; bool show_states; bool show_proc_self_status; bool show_valgrind_context; // debug-only bool suggest_happens_before_arcs; bool show_pc; bool full_stack_frames; bool color; // Colorify terminal output. bool html; // Output in html format. bool show_pid; intptr_t debug_level; bool save_ignore_context; // print stack if ignore_end was forgotten. vector<string> debug_phase; intptr_t trace_level; intptr_t dry_run; intptr_t max_sid; intptr_t max_sid_before_flush; intptr_t max_mem_in_mb; intptr_t num_callers_in_history; intptr_t flush_period; intptr_t literace_sampling; bool start_with_global_ignore_on; intptr_t locking_scheme; // Used for internal experiments with locking. bool report_races; bool thread_coverage; bool atomicity; bool call_coverage; string dump_events; // The name of log file. Debug mode only. bool symbolize; bool attach_mode; string tsan_program_name; string tsan_url; vector<string> suppressions; bool generate_suppressions; intptr_t error_exitcode; bool trace_children; vector<string> race_verifier; vector<string> race_verifier_extra; intptr_t race_verifier_sleep_ms; bool nacl_untrusted; bool threaded_analysis; bool sched_shake; bool api_ambush; bool enable_atomic; }; extern FLAGS *G_flags; extern bool g_race_verifier_active; extern bool debug_expected_races; extern bool debug_malloc; extern bool debug_free; extern bool debug_thread; extern bool debug_rtn; extern bool debug_wrap; extern bool debug_ins; extern bool debug_shadow_stack; extern bool debug_race_verifier; // -------- CallStack ------------- {{{1 const size_t kMaxCallStackSize = 1 << 12; struct CallStackPod { uintptr_t *end_; uintptr_t pcs_[kMaxCallStackSize]; }; struct CallStack: public CallStackPod { CallStack() { Clear(); } size_t size() { return (size_t)(end_ - pcs_); } uintptr_t *pcs() { return pcs_; } bool empty() { return end_ == pcs_; } uintptr_t &back() { DCHECK(!empty()); return *(end_ - 1); } void pop_back() { DCHECK(!empty()); end_--; } void push_back(uintptr_t pc) { DCHECK(size() < kMaxCallStackSize); *end_ = pc; end_++; } void Clear() { end_ = pcs_; } uintptr_t &operator[] (size_t i) { DCHECK(i < size()); return pcs_[i]; } }; //--------- TS Exports ----------------- {{{1 #include "ts_events.h" #include "ts_trace_info.h" struct TSanThread; void ThreadSanitizerInit(); void ThreadSanitizerFini(); // TODO(glider): this is a temporary solution to avoid deadlocks after fork(). #ifdef TS_LLVM void ThreadSanitizerLockAcquire(); void ThreadSanitizerLockRelease(); #endif void ThreadSanitizerHandleOneEvent(Event *event); TSanThread *ThreadSanitizerGetThreadByTid(int32_t tid); void ThreadSanitizerHandleTrace(int32_t tid, TraceInfo *trace_info, uintptr_t *tleb); void ThreadSanitizerHandleTrace(TSanThread *thr, TraceInfo *trace_info, uintptr_t *tleb); void ThreadSanitizerHandleOneMemoryAccess(TSanThread *thr, MopInfo mop, uintptr_t addr); void ThreadSanitizerParseFlags(vector<string>* args); bool ThreadSanitizerWantToInstrumentSblock(uintptr_t pc); bool ThreadSanitizerWantToCreateSegmentsOnSblockEntry(uintptr_t pc); bool ThreadSanitizerIgnoreAccessesBelowFunction(uintptr_t pc); typedef int (*ThreadSanitizerUnwindCallback)(uintptr_t* stack, int size, uintptr_t pc); void ThreadSanitizerSetUnwindCallback(ThreadSanitizerUnwindCallback cb); /** Atomic operation handler. * @param tid ID of a thread that issues the operation. * @param pc Program counter that should be associated with the operation. * @param op Type of the operation (load, store, etc). * @param mo Memory ordering associated with the operation * (relaxed, acquire, release, etc). NB there are some restrictions on * what memory orderings can be used with what types of operations. * E.g. a store can't have an acquire semantics * (see C++0x standard draft for details). * @param fail_mo Memory ordering the operation has if it fails, * applicable only to compare_exchange oprations. * @param size Size of the memory access in bytes (1, 2, 4 or 8). * @param a Address of the memory access. * @param v Operand for the operation (e.g. a value to store). * @param cmp Comparand for compare_exchange oprations. * @return Result of the operation (e.g. loaded value). */ uint64_t ThreadSanitizerHandleAtomicOp(int32_t tid, uintptr_t pc, tsan_atomic_op op, tsan_memory_order mo, tsan_memory_order fail_mo, size_t size, void volatile* a, uint64_t v, uint64_t cmp); enum IGNORE_BELOW_RTN { IGNORE_BELOW_RTN_UNKNOWN, IGNORE_BELOW_RTN_NO, IGNORE_BELOW_RTN_YES }; void ThreadSanitizerHandleRtnCall(int32_t tid, uintptr_t call_pc, uintptr_t target_pc, IGNORE_BELOW_RTN ignore_below); void ThreadSanitizerHandleRtnExit(int32_t tid); void ThreadSanitizerPrintUsage(); extern "C" const char *ThreadSanitizerQuery(const char *query); bool PhaseDebugIsOn(const char *phase_name); extern bool g_has_entered_main; extern bool g_has_exited_main; // -------- Stats ------------------- {{{1 #include "ts_stats.h" extern Stats *G_stats; // -------- Expected Race ---------------------- {{{1 // Information about expected races. struct ExpectedRace { uintptr_t ptr; uintptr_t size; bool is_verifiable; bool is_nacl_untrusted; int count; const char *description; uintptr_t pc; }; ExpectedRace* ThreadSanitizerFindExpectedRace(uintptr_t addr); // Tell ThreadSanitizer about the location of NaCl untrusted region. void ThreadSanitizerNaclUntrustedRegion(uintptr_t mem_start, uintptr_t mem_end); // Returns true if accesses and locks at the given address should be ignored // according to the current NaCl flags (--nacl-untrusted). Always false if not a // NaCl program. bool ThreadSanitizerIgnoreForNacl(uintptr_t addr); // end. {{{1 #endif // THREAD_SANITIZER_H_ // vim:shiftwidth=2:softtabstop=2:expandtab