tsan_rtl.cc revision 848531192777acecf79747dc7c1ffeedf5c1da9f
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_rtl.cc -------------------------------------------------------===// 27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The LLVM Compiler Infrastructure 47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source 67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details. 77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector. 117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Main file (entry points) for the TSan run-time. 137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 15fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h" 160969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include "sanitizer_common/sanitizer_common.h" 1716e0075746b21ed866ec3be21ef0d1e46f0efed5Kostya Serebryany#include "sanitizer_common/sanitizer_libc.h" 18848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov#include "sanitizer_common/sanitizer_stackdepot.h" 1947b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_defs.h" 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h" 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_suppressions.h" 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0; 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() { 29adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov __tsan_resumed = 1; 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 34b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 350a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64); 36b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 370a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64); 387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx; 407ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() { 417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return ctx; 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 447ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context() 457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : initialized() 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , report_mtx(MutexTypeReport, StatMtxReport) 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , nreported() 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , nmissed_expected() 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , thread_mtx(MutexTypeThreads, StatMtxThreads) 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , racy_stacks(MBlockRacyStacks) 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , racy_addresses(MBlockRacyAddresses) { 527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization. 55ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr stk_addr, uptr stk_size, 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr tls_addr, uptr tls_size) 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : fast_state(tid, epoch) 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Do not touch these, rely on zero initialization, 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // they may be accessed before the ctor. 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , fast_ignore_reads() 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , fast_ignore_writes() 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , in_rtl() 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , shadow_stack_pos(&shadow_stack[0]) 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tid(tid) 66ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov , unique_id(unique_id) 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , stk_addr(stk_addr) 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , stk_size(stk_size) 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tls_addr(tls_addr) 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tls_size(tls_size) { 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 737ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyThreadContext::ThreadContext(int tid) 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : tid(tid) 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , unique_id() 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , user_id() 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , thr() 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , status(ThreadStatusInvalid) 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , detached() 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , reuse_count() 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , epoch0() 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , epoch1() 839d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov , dead_info() 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , dead_next() { 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8726127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void WriteMemoryProfile(char *buf, uptr buf_size, int num) { 8826127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr shadow = GetShadowMemoryConsumption(); 8926127735454fddae3495794f38189d57dde6510fDmitry Vyukov 9026127735454fddae3495794f38189d57dde6510fDmitry Vyukov int nthread = 0; 9126127735454fddae3495794f38189d57dde6510fDmitry Vyukov int nlivethread = 0; 9226127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr threadmem = 0; 9326127735454fddae3495794f38189d57dde6510fDmitry Vyukov { 9426127735454fddae3495794f38189d57dde6510fDmitry Vyukov Lock l(&ctx->thread_mtx); 9526127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (unsigned i = 0; i < kMaxTid; i++) { 9626127735454fddae3495794f38189d57dde6510fDmitry Vyukov ThreadContext *tctx = ctx->threads[i]; 9726127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (tctx == 0) 9826127735454fddae3495794f38189d57dde6510fDmitry Vyukov continue; 9926127735454fddae3495794f38189d57dde6510fDmitry Vyukov nthread += 1; 10026127735454fddae3495794f38189d57dde6510fDmitry Vyukov threadmem += sizeof(ThreadContext); 10126127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (tctx->status != ThreadStatusRunning) 10226127735454fddae3495794f38189d57dde6510fDmitry Vyukov continue; 10326127735454fddae3495794f38189d57dde6510fDmitry Vyukov nlivethread += 1; 10426127735454fddae3495794f38189d57dde6510fDmitry Vyukov threadmem += sizeof(ThreadState); 10526127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 10626127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 10726127735454fddae3495794f38189d57dde6510fDmitry Vyukov 10826127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr nsync = 0; 10926127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync); 11026127735454fddae3495794f38189d57dde6510fDmitry Vyukov 111de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov internal_snprintf(buf, buf_size, "%d: shadow=%zuMB" 112de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov " thread=%zuMB(total=%d/live=%d)" 113de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov " sync=%zuMB(cnt=%zu)\n", 11426127735454fddae3495794f38189d57dde6510fDmitry Vyukov num, 11526127735454fddae3495794f38189d57dde6510fDmitry Vyukov shadow >> 20, 11626127735454fddae3495794f38189d57dde6510fDmitry Vyukov threadmem >> 20, nthread, nlivethread, 11726127735454fddae3495794f38189d57dde6510fDmitry Vyukov syncmem >> 20, nsync); 11826127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 11926127735454fddae3495794f38189d57dde6510fDmitry Vyukov 12026127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void MemoryProfileThread(void *arg) { 12126127735454fddae3495794f38189d57dde6510fDmitry Vyukov ScopedInRtl in_rtl; 12226127735454fddae3495794f38189d57dde6510fDmitry Vyukov fd_t fd = (fd_t)(uptr)arg; 12326127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (int i = 0; ; i++) { 12414c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov InternalScopedBuffer<char> buf(4096); 12514c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov WriteMemoryProfile(buf, buf.size(), i); 12614c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov internal_write(fd, buf, internal_strlen(buf)); 1270969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov SleepForSeconds(1); 12826127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 12926127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 13026127735454fddae3495794f38189d57dde6510fDmitry Vyukov 13126127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void InitializeMemoryProfile() { 13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0) 13326127735454fddae3495794f38189d57dde6510fDmitry Vyukov return; 13414c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov InternalScopedBuffer<char> filename(4096); 13514c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov internal_snprintf(filename, filename.size(), "%s.%d", 13626127735454fddae3495794f38189d57dde6510fDmitry Vyukov flags()->profile_memory, GetPid()); 13714c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov fd_t fd = internal_open(filename, true); 13826127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (fd == kInvalidFd) { 13967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("Failed to open memory profile file '%s'\n", &filename[0]); 14026127735454fddae3495794f38189d57dde6510fDmitry Vyukov Die(); 14126127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 14226127735454fddae3495794f38189d57dde6510fDmitry Vyukov internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd); 14326127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 14426127735454fddae3495794f38189d57dde6510fDmitry Vyukov 145adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void MemoryFlushThread(void *arg) { 146adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov ScopedInRtl in_rtl; 147adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov for (int i = 0; ; i++) { 1480969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov SleepForMillis(flags()->flush_memory_ms); 149adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov FlushShadowMemory(); 150adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov } 151adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov} 152adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov 153adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void InitializeMemoryFlush() { 154adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->flush_memory_ms == 0) 155adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov return; 156adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->flush_memory_ms < 100) 157adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov flags()->flush_memory_ms = 100; 158adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov internal_start_thread(&MemoryFlushThread, 0); 159adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov} 160adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov 1617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) { 1627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Thread safe because done before all threads exist. 1637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static bool is_initialized = false; 1647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (is_initialized) 1657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany is_initialized = true; 1677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 168bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO 1692e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov InitializeAllocator(); 170bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif 1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeInterceptors(); 1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *env = InitializePlatform(); 1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeMutex(); 1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeDynamicAnnotations(); 1757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx = new(ctx_placeholder) Context; 1767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeShadowMemory(); 1777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->dead_list_size = 0; 1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->dead_list_head = 0; 1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->dead_list_tail = 0; 1807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeFlags(&ctx->flags, env); 1817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeSuppressions(); 18226127735454fddae3495794f38189d57dde6510fDmitry Vyukov InitializeMemoryProfile(); 183adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov InitializeMemoryFlush(); 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->flags.verbosity) 18667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("***** Running under ThreadSanitizer v2 (pid %d) *****\n", 18767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov GetPid()); 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Initialize thread 0. 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->thread_seq = 0; 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = ThreadCreate(thr, 0, 0, true); 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(tid, 0); 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadStart(thr, tid); 1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(thr->in_rtl, 1); 1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->initialized = true; 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 197adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->stop_on_start) { 19867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("ThreadSanitizer is suspended at startup (pid %d)." 199adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov " Call __tsan_resume().\n", 200adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov GetPid()); 201adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov while (__tsan_resumed == 0); 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) { 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = __tsan::ctx; 2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool failed = false; 2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadFinalize(thr); 2117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nreported) { 2137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 21467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("ThreadSanitizer: reported %d warnings\n", ctx->nreported); 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nmissed_expected) { 2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 21967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov TsanPrintf("ThreadSanitizer: missed %d expected races\n", 2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->nmissed_expected); 2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatOutput(ctx->stat); 224b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov return failed ? flags()->exitcode : 0; 2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 227848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) { 228848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (thr->shadow_stack_pos == 0) // May happen during bootstrap. 229848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return 0; 230848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) { 231848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos[0] = pc; 232848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos++; 233848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov } 234848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov u32 id = StackDepotPut(thr->shadow_stack, 235848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos - thr->shadow_stack); 236848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) 237848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos--; 238848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return id; 239848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 240848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 241b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) { 2429ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc++; 2437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&thr->trace.mtx); 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % kTraceParts; 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceHeader *hdr = &thr->trace.headers[trace]; 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->epoch0 = thr->fast_state.epoch(); 2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->stack0.ObtainCurrent(thr, 0); 2499ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc--; 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 252b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() { 2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceSwitch(cur_thread()); 2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() { 2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportRace(cur_thread()); 2597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 260b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2627ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Shadow LoadShadow(u64 *p) { 2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed); 2657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return Shadow(raw); 2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreShadow(u64 *sp, u64 s) { 2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed); 2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2737ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 2747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreIfNotYetStored(u64 *sp, u64 *s) { 2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(sp, *s); 2767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *s = 0; 2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem, 2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur, Shadow old) { 2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[0] = cur.raw(); 2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[1] = old.raw(); 2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_shadow_addr = shadow_mem; 284b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HACKY_CALL(__tsan_report_race); 286b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 287b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov ReportRace(thr); 288b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool BothReads(Shadow s, int kAccessIsWrite) { 2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return !kAccessIsWrite && !s.is_write(); 2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsRWStronger(Shadow old, int kAccessIsWrite) { 2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return old.is_write() || !kAccessIsWrite; 2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsRWWeaker(Shadow old, int kAccessIsWrite) { 3007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return !old.is_write() || kAccessIsWrite; 3017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) { 3047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return old.epoch() >= thr->fast_synch_epoch; 3057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) { 3087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return thr->clock.get(old.tid()) >= old.epoch(); 3097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3117ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 3127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr, 3137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int kAccessSizeLog, bool kAccessIsWrite, FastState fast_state, 3147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem, Shadow cur) { 3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatMop); 3167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); 3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); 3187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // This potentially can live in an MMX/SSE scratch register. 3207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // The required intrinsics are: 3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // __m128i _mm_move_epi64(__m128i*); 3227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // _mm_storel_epi64(u64*, __m128i); 3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 store_word = cur.raw(); 3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // scan all the shadow values and dispatch to 4 categories: 3267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // same, replace, candidate and race (see comments below). 3277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we consider only 3 cases regarding access sizes: 3287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // equal, intersect and not intersect. initially I considered 3297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // larger and smaller as well, it allowed to replace some 3307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // 'candidates' with 'same' or 'replace', but I think 3317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // it's just not worth it (performance- and complexity-wise). 3327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow old(0); 3347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (kShadowCnt == 1) { 3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 2) { 3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 3397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 3417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 4) { 3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 3447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 3467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 8) { 3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 3557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 4; 3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 5; 3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 6; 3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 7; 3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(false); 3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 3717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we did not find any races and had already stored 3737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // the current access info, so we are done 3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (LIKELY(store_word == 0)) 3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 3767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // choose a random candidate slot and replace it 3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word); 3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatShadowReplace); 3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE: 3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HandleRace(thr, shadow_mem, cur, old); 3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3857ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr, 3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int kAccessSizeLog, bool kAccessIsWrite) { 3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem = (u64*)MemToShadow(addr); 3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf2("#%d: tsan::OnMemoryAccess: @%p %p size=%d" 390e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n", 3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)thr->fast_state.tid(), (void*)pc, (void*)addr, 3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem, 393e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[0], (uptr)shadow_mem[1], 394e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[2], (uptr)shadow_mem[3]); 3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsAppMem(addr)) { 397e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov TsanPrintf("Access to non app mem %zx\n", addr); 3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsAppMem(addr)); 3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsShadowMem((uptr)shadow_mem)) { 401e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr); 4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsShadowMem((uptr)shadow_mem)); 4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany FastState fast_state = thr->fast_state; 4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (fast_state.GetIgnoreBit()) 4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany fast_state.IncrementEpoch(); 4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state = fast_state; 4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur(fast_state); 4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog); 4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetWrite(kAccessIsWrite); 4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // We must not store to the trace if we do not store to the shadow. 4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // That is, this call must be moved somewhere below. 4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceAddEvent(thr, fast_state.epoch(), EventTypeMop, pc); 4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, fast_state, 4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany shadow_mem, cur); 4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, 4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 val) { 4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size == 0) 4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: fix me. 4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr offset = addr % kShadowCell; 4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (offset) { 4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany offset = kShadowCell - offset; 4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size <= offset) 4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany addr += offset; 4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size -= offset; 4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(addr % 8, 0); 4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(IsAppMem(addr)); 4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(IsAppMem(addr + size - 1)); 4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)thr; 4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)pc; 4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Some programs mmap like hundreds of GBs but actually used a small part. 4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // So, it's better to report a false positive on the memory 4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // then to hang here senselessly. 4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const uptr kMaxResetSize = 1024*1024*1024; 4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size > kMaxResetSize) 4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size = kMaxResetSize; 44726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1); 4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *p = (u64*)MemToShadow(addr); 4497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(IsShadowMem((uptr)p)); 4507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1))); 4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: may overwrite a part outside the region 45226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) { 45326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov p[i++] = val; 45426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 45526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov p[i++] = 0; 45626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov } 4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) { 4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryRangeSet(thr, pc, addr, size, 0); 4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) { 4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, addr, size, true); 465069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov Shadow s(thr->fast_state); 466069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.MarkAsFreed(); 467069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetWrite(true); 468069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 469069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 47226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) { 47326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov Shadow s(thr->fast_state); 47426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetWrite(true); 47526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 47626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 47726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov} 47826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov 4797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) { 4807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 4817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncEnter); 48225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); 4837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncEnter, pc); 4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Shadow stack maintenance can be replaced with 4877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // stack unwinding during trace switch (which presumably must be faster). 488769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]); 48925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 490769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 49125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else 49225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov if (thr->shadow_stack_pos == thr->shadow_stack_end) { 49325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int sz = thr->shadow_stack_end - thr->shadow_stack; 49425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int newsz = 2 * sz; 49525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack, 49625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov newsz * sizeof(uptr)); 49725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr)); 49825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_free(thr->shadow_stack); 49925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack = newstack; 50025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_pos = newstack + sz; 50125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_end = newstack + newsz; 50225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov } 50325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos[0] = pc; 5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos++; 5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) { 5097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncExit); 51125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); 5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncExit, 0); 5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 515769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]); 51625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 517769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 51825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos--; 5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) { 5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin); 5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->ignore_reads_and_writes += begin ? 1 : -1; 5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_GE(thr->ignore_reads_and_writes, 0); 5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (thr->ignore_reads_and_writes) 5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.SetIgnoreBit(); 5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 5297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.ClearIgnoreBit(); 5307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 532b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const { 533b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return hash[0] == other.hash[0] && hash[1] == other.hash[1]; 534b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 535b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 5377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {} 5387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 5397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {} 5407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 5417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS 5437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {} 5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {} 5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 5477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1 5497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {} 5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2 5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {} 5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4 5537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {} 5547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 5557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {} 5567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 5577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 5597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 560b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 5617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined. 5627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h" 563b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 564