tsan_rtl.cc revision 68230a12bbd22c9402dd8f9af027fcb2e119f978
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" 208cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov#include "sanitizer_common/sanitizer_symbolizer.h" 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_defs.h" 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h" 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_suppressions.h" 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 27adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0; 287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() { 30adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov __tsan_resumed = 1; 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 35b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 360a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64); 37b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 380a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64); 397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx; 417ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() { 427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return ctx; 437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 457ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context() 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : initialized() 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , report_mtx(MutexTypeReport, StatMtxReport) 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , nreported() 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , nmissed_expected() 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , thread_mtx(MutexTypeThreads, StatMtxThreads) 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , racy_stacks(MBlockRacyStacks) 52158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov , racy_addresses(MBlockRacyAddresses) 53158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov , fired_suppressions(MBlockRacyAddresses) { 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization. 57ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr stk_addr, uptr stk_size, 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr tls_addr, uptr tls_size) 607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : fast_state(tid, epoch) 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Do not touch these, rely on zero initialization, 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // they may be accessed before the ctor. 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , fast_ignore_reads() 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , fast_ignore_writes() 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , in_rtl() 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , shadow_stack_pos(&shadow_stack[0]) 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tid(tid) 68ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov , unique_id(unique_id) 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , stk_addr(stk_addr) 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , stk_size(stk_size) 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tls_addr(tls_addr) 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tls_size(tls_size) { 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 757ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyThreadContext::ThreadContext(int tid) 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : tid(tid) 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , unique_id() 787dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov , os_id() 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , user_id() 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , thr() 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , status(ThreadStatusInvalid) 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , detached() 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , reuse_count() 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , epoch0() 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , epoch1() 869d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov , dead_info() 87aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov , dead_next() 88aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov , name() { 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 9126127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void WriteMemoryProfile(char *buf, uptr buf_size, int num) { 9226127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr shadow = GetShadowMemoryConsumption(); 9326127735454fddae3495794f38189d57dde6510fDmitry Vyukov 9426127735454fddae3495794f38189d57dde6510fDmitry Vyukov int nthread = 0; 9526127735454fddae3495794f38189d57dde6510fDmitry Vyukov int nlivethread = 0; 9626127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr threadmem = 0; 9726127735454fddae3495794f38189d57dde6510fDmitry Vyukov { 9826127735454fddae3495794f38189d57dde6510fDmitry Vyukov Lock l(&ctx->thread_mtx); 9926127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (unsigned i = 0; i < kMaxTid; i++) { 10026127735454fddae3495794f38189d57dde6510fDmitry Vyukov ThreadContext *tctx = ctx->threads[i]; 10126127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (tctx == 0) 10226127735454fddae3495794f38189d57dde6510fDmitry Vyukov continue; 10326127735454fddae3495794f38189d57dde6510fDmitry Vyukov nthread += 1; 10426127735454fddae3495794f38189d57dde6510fDmitry Vyukov threadmem += sizeof(ThreadContext); 10526127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (tctx->status != ThreadStatusRunning) 10626127735454fddae3495794f38189d57dde6510fDmitry Vyukov continue; 10726127735454fddae3495794f38189d57dde6510fDmitry Vyukov nlivethread += 1; 10826127735454fddae3495794f38189d57dde6510fDmitry Vyukov threadmem += sizeof(ThreadState); 10926127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 11026127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 11126127735454fddae3495794f38189d57dde6510fDmitry Vyukov 11226127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr nsync = 0; 11326127735454fddae3495794f38189d57dde6510fDmitry Vyukov uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync); 11426127735454fddae3495794f38189d57dde6510fDmitry Vyukov 115de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov internal_snprintf(buf, buf_size, "%d: shadow=%zuMB" 116de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov " thread=%zuMB(total=%d/live=%d)" 117de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov " sync=%zuMB(cnt=%zu)\n", 11826127735454fddae3495794f38189d57dde6510fDmitry Vyukov num, 11926127735454fddae3495794f38189d57dde6510fDmitry Vyukov shadow >> 20, 12026127735454fddae3495794f38189d57dde6510fDmitry Vyukov threadmem >> 20, nthread, nlivethread, 12126127735454fddae3495794f38189d57dde6510fDmitry Vyukov syncmem >> 20, nsync); 12226127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 12326127735454fddae3495794f38189d57dde6510fDmitry Vyukov 12426127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void MemoryProfileThread(void *arg) { 12526127735454fddae3495794f38189d57dde6510fDmitry Vyukov ScopedInRtl in_rtl; 12626127735454fddae3495794f38189d57dde6510fDmitry Vyukov fd_t fd = (fd_t)(uptr)arg; 12726127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (int i = 0; ; i++) { 12814c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov InternalScopedBuffer<char> buf(4096); 1291dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov WriteMemoryProfile(buf.data(), buf.size(), i); 1301dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov internal_write(fd, buf.data(), internal_strlen(buf.data())); 1310969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov SleepForSeconds(1); 13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 13326127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 13426127735454fddae3495794f38189d57dde6510fDmitry Vyukov 13526127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void InitializeMemoryProfile() { 13626127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0) 13726127735454fddae3495794f38189d57dde6510fDmitry Vyukov return; 13814c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov InternalScopedBuffer<char> filename(4096); 1391dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov internal_snprintf(filename.data(), filename.size(), "%s.%d", 14026127735454fddae3495794f38189d57dde6510fDmitry Vyukov flags()->profile_memory, GetPid()); 1411dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov fd_t fd = internal_open(filename.data(), true); 14226127735454fddae3495794f38189d57dde6510fDmitry Vyukov if (fd == kInvalidFd) { 143b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Failed to open memory profile file '%s'\n", &filename[0]); 14426127735454fddae3495794f38189d57dde6510fDmitry Vyukov Die(); 14526127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 14626127735454fddae3495794f38189d57dde6510fDmitry Vyukov internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd); 14726127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 14826127735454fddae3495794f38189d57dde6510fDmitry Vyukov 149adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void MemoryFlushThread(void *arg) { 150adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov ScopedInRtl in_rtl; 151adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov for (int i = 0; ; i++) { 1520969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov SleepForMillis(flags()->flush_memory_ms); 153adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov FlushShadowMemory(); 154adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov } 155adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov} 156adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov 157adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void InitializeMemoryFlush() { 158adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->flush_memory_ms == 0) 159adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov return; 160adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->flush_memory_ms < 100) 161adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov flags()->flush_memory_ms = 100; 162adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov internal_start_thread(&MemoryFlushThread, 0); 163adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov} 164adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov 165a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) { 1666b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier); 167a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov} 168a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov 1697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) { 1707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Thread safe because done before all threads exist. 1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static bool is_initialized = false; 1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (is_initialized) 1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany is_initialized = true; 175591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov // Install tool-specific callbacks in sanitizer_common. 176591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov SetCheckFailedCallback(TsanCheckFailed); 177591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 179bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO 1802e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov InitializeAllocator(); 181bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif 1827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeInterceptors(); 1837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *env = InitializePlatform(); 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeMutex(); 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeDynamicAnnotations(); 1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx = new(ctx_placeholder) Context; 187a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#ifndef TSAN_GO 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeShadowMemory(); 189a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->dead_list_size = 0; 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->dead_list_head = 0; 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->dead_list_tail = 0; 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeFlags(&ctx->flags, env); 194b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov // Setup correct file descriptor for error reports. 195cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov if (internal_strcmp(flags()->log_path, "stdout") == 0) 196cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_fd(kStdoutFd); 197cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov else if (internal_strcmp(flags()->log_path, "stderr") == 0) 198cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_fd(kStderrFd); 199cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov else 200cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_path(flags()->log_path); 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeSuppressions(); 20285a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#ifndef TSAN_GO 20368bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov // Initialize external symbolizer before internal threads are started. 2048cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov const char *external_symbolizer = flags()->external_symbolizer_path; 2058cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov if (external_symbolizer != 0 && external_symbolizer[0] != '\0') { 20693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (!InitializeExternalSymbolizer(external_symbolizer)) { 20793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov Printf("Failed to start external symbolizer: '%s'\n", 20893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov external_symbolizer); 20993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov Die(); 21093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov } 2118cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov } 21285a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#endif 21368bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov InitializeMemoryProfile(); 21468bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov InitializeMemoryFlush(); 2158cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->flags.verbosity) 217b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n", 21867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov GetPid()); 2197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Initialize thread 0. 2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->thread_seq = 0; 2227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = ThreadCreate(thr, 0, 0, true); 2237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(tid, 0); 2247dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov ThreadStart(thr, tid, GetPid()); 2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(thr->in_rtl, 1); 2267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->initialized = true; 2277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 228adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->stop_on_start) { 229b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer is suspended at startup (pid %d)." 230adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov " Call __tsan_resume().\n", 231adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov GetPid()); 232adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov while (__tsan_resumed == 0); 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) { 2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = __tsan::ctx; 2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool failed = false; 2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 24154e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1) 24254e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov SleepForMillis(flags()->atexit_sleep_ms); 24354e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov 244d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov // Wait for pending reports. 245d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov ctx->report_mtx.Lock(); 246d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov ctx->report_mtx.Unlock(); 247d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov 2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadFinalize(thr); 2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nreported) { 2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 252b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#ifndef TSAN_GO 253b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported); 254b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else 255b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Found %d data race(s)\n", ctx->nreported); 256b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif 2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nmissed_expected) { 2607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 261b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: missed %d expected races\n", 2627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->nmissed_expected); 2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26508adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov StatAggregate(ctx->stat, thr->stat); 2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatOutput(ctx->stat); 267b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov return failed ? flags()->exitcode : 0; 2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2700ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO 271848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) { 272848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (thr->shadow_stack_pos == 0) // May happen during bootstrap. 273848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return 0; 274848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) { 275848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos[0] = pc; 276848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos++; 277848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov } 278848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov u32 id = StackDepotPut(thr->shadow_stack, 279848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos - thr->shadow_stack); 280848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) 281848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos--; 282848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return id; 283848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 2840ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif 285848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 286b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) { 2879ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc++; 2887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Lock l(&thr->trace.mtx); 2900415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts(); 2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceHeader *hdr = &thr->trace.headers[trace]; 2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->epoch0 = thr->fast_state.epoch(); 2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->stack0.ObtainCurrent(thr, 0); 294ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov hdr->mset0 = thr->mset; 2959ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc--; 2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 298385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) { 299385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov Event *events = (Event*)GetThreadTrace(thr->tid); 300d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov uptr pc = events[thr->fast_state.GetTracePos()]; 301385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov return pc; 302385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov} 303385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov 304d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() { 305d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1)); 306d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov} 307d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov 3080415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() { 3090415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov return TraceSize() / kTracePartSize; 3100415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov} 3110415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov 312b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 3137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() { 3147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceSwitch(cur_thread()); 3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() { 3187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportRace(cur_thread()); 3197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 320b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Shadow LoadShadow(u64 *p) { 3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed); 3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return Shadow(raw); 3267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3287ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 3297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreShadow(u64 *sp, u64 s) { 3307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed); 3317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3337ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 3347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreIfNotYetStored(u64 *sp, u64 *s) { 3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(sp, *s); 3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *s = 0; 3377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem, 3407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur, Shadow old) { 3417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[0] = cur.raw(); 3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[1] = old.raw(); 3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_shadow_addr = shadow_mem; 344b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HACKY_CALL(__tsan_report_race); 346b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 347b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov ReportRace(thr); 348b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool BothReads(Shadow s, int kAccessIsWrite) { 3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return !kAccessIsWrite && !s.is_write(); 3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 355ed77156ba3c5754b4cfe4ca1d6d5d7a4fdfb7835Dmitry Vyukovstatic inline bool OldIsRWNotWeaker(Shadow old, int kAccessIsWrite) { 3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return old.is_write() || !kAccessIsWrite; 3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 359ed77156ba3c5754b4cfe4ca1d6d5d7a4fdfb7835Dmitry Vyukovstatic inline bool OldIsRWWeakerOrEqual(Shadow old, int kAccessIsWrite) { 3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return !old.is_write() || kAccessIsWrite; 3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) { 3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return old.epoch() >= thr->fast_synch_epoch; 3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) { 368c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov return thr->clock.get(old.TidWithIgnore()) >= old.epoch(); 3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3717ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr, 373bd9f4963dd50f2fe66ba47a74776dc2665f84d7dDmitry Vyukov int kAccessSizeLog, bool kAccessIsWrite, 3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem, Shadow cur) { 3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatMop); 3767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); 3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); 3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // This potentially can live in an MMX/SSE scratch register. 3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // The required intrinsics are: 3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // __m128i _mm_move_epi64(__m128i*); 3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // _mm_storel_epi64(u64*, __m128i); 3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 store_word = cur.raw(); 3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // scan all the shadow values and dispatch to 4 categories: 3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // same, replace, candidate and race (see comments below). 3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we consider only 3 cases regarding access sizes: 3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // equal, intersect and not intersect. initially I considered 3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // larger and smaller as well, it allowed to replace some 3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // 'candidates' with 'same' or 'replace', but I think 3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // it's just not worth it (performance- and complexity-wise). 3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow old(0); 3947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (kShadowCnt == 1) { 3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 2) { 3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 4) { 4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 8) { 4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 4; 4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 5; 4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 6; 4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 7; 4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(false); 4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we did not find any races and had already stored 4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // the current access info, so we are done 4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (LIKELY(store_word == 0)) 4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // choose a random candidate slot and replace it 4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word); 4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatShadowReplace); 4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE: 4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HandleRace(thr, shadow_mem, cur, old); 4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4457ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr, 4477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int kAccessSizeLog, bool kAccessIsWrite) { 4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem = (u64*)MemToShadow(addr); 44968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov DPrintf2("#%d: MemoryAccess: @%p %p size=%d" 450e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n", 4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)thr->fast_state.tid(), (void*)pc, (void*)addr, 4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem, 453e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[0], (uptr)shadow_mem[1], 454e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[2], (uptr)shadow_mem[3]); 4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsAppMem(addr)) { 457b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Access to non app mem %zx\n", addr); 4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsAppMem(addr)); 4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsShadowMem((uptr)shadow_mem)) { 461b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr); 4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsShadowMem((uptr)shadow_mem)); 4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 4657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany FastState fast_state = thr->fast_state; 4677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (fast_state.GetIgnoreBit()) 4687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany fast_state.IncrementEpoch(); 4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state = fast_state; 4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur(fast_state); 4727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog); 4737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetWrite(kAccessIsWrite); 4747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // We must not store to the trace if we do not store to the shadow. 4767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // That is, this call must be moved somewhere below. 477385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, fast_state, EventTypeMop, pc); 4787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 479bd9f4963dd50f2fe66ba47a74776dc2665f84d7dDmitry Vyukov MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, 4807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany shadow_mem, cur); 4817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, 4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 val) { 4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size == 0) 4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: fix me. 4887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr offset = addr % kShadowCell; 4897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (offset) { 4907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany offset = kShadowCell - offset; 4917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size <= offset) 4927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany addr += offset; 4947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size -= offset; 4957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 496aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov DCHECK_EQ(addr % 8, 0); 497aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov // If a user passes some insane arguments (memset(0)), 498aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov // let it just crash as usual. 499aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov if (!IsAppMem(addr) || !IsAppMem(addr + size - 1)) 500aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov return; 5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)thr; 5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)pc; 5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Some programs mmap like hundreds of GBs but actually used a small part. 5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // So, it's better to report a false positive on the memory 5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // then to hang here senselessly. 5069c6c5a26ec1e49f379515d2403b8b206bf2755c3Dmitry Vyukov const uptr kMaxResetSize = 4ull*1024*1024*1024; 5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size > kMaxResetSize) 5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size = kMaxResetSize; 50926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1); 5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *p = (u64*)MemToShadow(addr); 5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(IsShadowMem((uptr)p)); 5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1))); 5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: may overwrite a part outside the region 51426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) { 51526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov p[i++] = val; 51626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 51726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov p[i++] = 0; 51826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov } 5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) { 5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryRangeSet(thr, pc, addr, size, 0); 5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) { 5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, addr, size, true); 527069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov Shadow s(thr->fast_state); 528064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov s.ClearIgnoreBit(); 529069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.MarkAsFreed(); 530069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetWrite(true); 531069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 532069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 5337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 53526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) { 53626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov Shadow s(thr->fast_state); 537064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov s.ClearIgnoreBit(); 53826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetWrite(true); 53926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 54026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 54126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov} 54226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov 5436fa4cc3a81713a392b2f3e8e7d6ad411e4b3f421Dmitry VyukovALWAYS_INLINE 5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) { 5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncEnter); 54725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); 5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 549385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc); 5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Shadow stack maintenance can be replaced with 5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // stack unwinding during trace switch (which presumably must be faster). 553769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]); 55425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 555769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 55625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else 55725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov if (thr->shadow_stack_pos == thr->shadow_stack_end) { 55825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int sz = thr->shadow_stack_end - thr->shadow_stack; 55925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int newsz = 2 * sz; 56025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack, 56125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov newsz * sizeof(uptr)); 56225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr)); 56325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_free(thr->shadow_stack); 56425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack = newstack; 56525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_pos = newstack + sz; 56625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_end = newstack + newsz; 56725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov } 56825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 5697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos[0] = pc; 5707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos++; 5717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5736fa4cc3a81713a392b2f3e8e7d6ad411e4b3f421Dmitry VyukovALWAYS_INLINE 5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) { 5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncExit); 57725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); 5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 579385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0); 5807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 581769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]); 58225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 583769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 58425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos--; 5867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) { 5897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin); 5907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->ignore_reads_and_writes += begin ? 1 : -1; 5917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_GE(thr->ignore_reads_and_writes, 0); 5927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (thr->ignore_reads_and_writes) 5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.SetIgnoreBit(); 5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.ClearIgnoreBit(); 5967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 598b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const { 599b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return hash[0] == other.hash[0] && hash[1] == other.hash[1]; 600b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 601b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 6027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 6037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {} 6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {} 6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS 6097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {} 6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {} 6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1 6157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {} 6167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2 6177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {} 6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4 6197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {} 6207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {} 6227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 6257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 626b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 6277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined. 6287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h" 629b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 630