tsan_rtl.cc revision 9578a3ecfc35a264ede1135033398e2a77a6cad6
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" 26a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#include "tsan_symbolize.h" 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 28adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0; 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() { 31adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov __tsan_resumed = 1; 327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 36b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 370a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64); 38b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 390a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64); 407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4122881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov// Can be overriden by a front-end. 427c984ca2fc88e2cd82b30c5b3ef361af2a1f2062Dmitry Vyukovbool CPP_WEAK OnFinalize(bool failed) { 4322881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov return failed; 4422881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov} 4522881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx; 477ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() { 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return ctx; 497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 512bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic char thread_registry_placeholder[sizeof(ThreadRegistry)]; 522bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov 532bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic ThreadContextBase *CreateThreadContext(u32 tid) { 542bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov // Map thread trace when context is created. 552bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event)); 569743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov MapThreadTrace(GetThreadTraceHeader(tid), sizeof(Trace)); 579743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov new(ThreadTrace(tid)) Trace(); 589743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext)); 592bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov return new(mem) ThreadContext(tid); 602bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov} 612bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov 622bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#ifndef TSAN_GO 632bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic const u32 kThreadQuarantineSize = 16; 642bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#else 652bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic const u32 kThreadQuarantineSize = 64; 662bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#endif 672bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov 687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context() 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : initialized() 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , report_mtx(MutexTypeReport, StatMtxReport) 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , nreported() 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , nmissed_expected() 732bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov , thread_registry(new(thread_registry_placeholder) ThreadRegistry( 742bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov CreateThreadContext, kMaxTid, kThreadQuarantineSize)) 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , racy_stacks(MBlockRacyStacks) 76158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov , racy_addresses(MBlockRacyAddresses) 77158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov , fired_suppressions(MBlockRacyAddresses) { 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization. 81ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr stk_addr, uptr stk_size, 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr tls_addr, uptr tls_size) 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : fast_state(tid, epoch) 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Do not touch these, rely on zero initialization, 867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // they may be accessed before the ctor. 877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , fast_ignore_reads() 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , fast_ignore_writes() 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // , in_rtl() 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , shadow_stack_pos(&shadow_stack[0]) 918b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov#ifndef TSAN_GO 928b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov , jmp_bufs(MBlockJmpBuf) 938b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov#endif 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tid(tid) 95ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov , unique_id(unique_id) 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , stk_addr(stk_addr) 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , stk_size(stk_size) 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tls_addr(tls_addr) 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany , tls_size(tls_size) { 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 102a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukovstatic void MemoryProfiler(Context *ctx, fd_t fd, int i) { 1034bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov uptr n_threads; 1044bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov uptr n_running_threads; 1054bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads); 106a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov InternalScopedBuffer<char> buf(4096); 1074bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov internal_snprintf(buf.data(), buf.size(), "%d: nthr=%d nlive=%d\n", 1084bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov i, n_threads, n_running_threads); 1094bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov internal_write(fd, buf.data(), internal_strlen(buf.data())); 1104bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov WriteMemoryProfile(buf.data(), buf.size()); 1114bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov internal_write(fd, buf.data(), internal_strlen(buf.data())); 1124bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov} 1134bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 1144bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstatic void BackgroundThread(void *arg) { 1154bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov ScopedInRtl in_rtl; 116a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov Context *ctx = CTX(); 117f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov const u64 kMs2Ns = 1000 * 1000; 1184bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 1194bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov fd_t mprof_fd = kInvalidFd; 1204bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov if (flags()->profile_memory && flags()->profile_memory[0]) { 1214bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov InternalScopedBuffer<char> filename(4096); 1224bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov internal_snprintf(filename.data(), filename.size(), "%s.%d", 1234bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov flags()->profile_memory, GetPid()); 1249578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne uptr openrv = OpenFile(filename.data(), true); 1259578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne if (internal_iserror(openrv)) { 1264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov Printf("ThreadSanitizer: failed to open memory profile file '%s'\n", 1274bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov &filename[0]); 1289578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne } else { 1299578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne mprof_fd = openrv; 1304bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1314bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1324bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 1334bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov u64 last_flush = NanoTime(); 13426127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (int i = 0; ; i++) { 1350969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov SleepForSeconds(1); 1364bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov u64 now = NanoTime(); 13726127735454fddae3495794f38189d57dde6510fDmitry Vyukov 138a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov // Flush memory if requested. 1394bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov if (flags()->flush_memory_ms) { 140f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) { 1414bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov FlushShadowMemory(); 1424bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov last_flush = NanoTime(); 1434bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1444bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1454bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 146a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov // Write memory profile if requested. 1474bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov if (mprof_fd != kInvalidFd) 148a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov MemoryProfiler(ctx, mprof_fd, i); 149a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov 150a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#ifndef TSAN_GO 151f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov // Flush symbolizer cache if requested. 152f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov if (flags()->flush_symbolizer_ms > 0) { 153f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov u64 last = atomic_load(&ctx->last_symbolize_time_ns, 154f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov memory_order_relaxed); 155f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) { 156f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov Lock l(&ctx->report_mtx); 1577ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov SpinMutexLock l2(&CommonSanitizerReportMutex); 158f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov SymbolizeFlush(); 159f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed); 160f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov } 161a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov } 162a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#endif 16326127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 16426127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 16526127735454fddae3495794f38189d57dde6510fDmitry Vyukov 1667ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukovvoid DontNeedShadowFor(uptr addr, uptr size) { 1677ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov uptr shadow_beg = MemToShadow(addr); 1687ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov uptr shadow_end = MemToShadow(addr + size); 1697ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg); 1707ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov} 1717ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov 172a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) { 1736b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier); 174a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov} 175a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov 1766535c31c66569df262791f0b56852c496977c977Dmitry Vyukovvoid MapThreadTrace(uptr addr, uptr size) { 177dae1251f196f9694d428a04f14987b06112ae52cDmitry Vyukov DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size); 1786535c31c66569df262791f0b56852c496977c977Dmitry Vyukov CHECK_GE(addr, kTraceMemBegin); 1796535c31c66569df262791f0b56852c496977c977Dmitry Vyukov CHECK_LE(addr + size, kTraceMemBegin + kTraceMemSize); 1806535c31c66569df262791f0b56852c496977c977Dmitry Vyukov if (addr != (uptr)MmapFixedNoReserve(addr, size)) { 1816535c31c66569df262791f0b56852c496977c977Dmitry Vyukov Printf("FATAL: ThreadSanitizer can not mmap thread trace\n"); 1826535c31c66569df262791f0b56852c496977c977Dmitry Vyukov Die(); 1836535c31c66569df262791f0b56852c496977c977Dmitry Vyukov } 1846535c31c66569df262791f0b56852c496977c977Dmitry Vyukov} 1856535c31c66569df262791f0b56852c496977c977Dmitry Vyukov 1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) { 1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Thread safe because done before all threads exist. 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static bool is_initialized = false; 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (is_initialized) 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany is_initialized = true; 192859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany SanitizerToolName = "ThreadSanitizer"; 193591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov // Install tool-specific callbacks in sanitizer_common. 194591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov SetCheckFailedCallback(TsanCheckFailed); 195591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 197bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO 1982e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov InitializeAllocator(); 199bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif 2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeInterceptors(); 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *env = InitializePlatform(); 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeMutex(); 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeDynamicAnnotations(); 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx = new(ctx_placeholder) Context; 205a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#ifndef TSAN_GO 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeShadowMemory(); 207a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif 2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeFlags(&ctx->flags, env); 209b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov // Setup correct file descriptor for error reports. 210cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov if (internal_strcmp(flags()->log_path, "stdout") == 0) 211cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_fd(kStdoutFd); 212cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov else if (internal_strcmp(flags()->log_path, "stderr") == 0) 213cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_fd(kStderrFd); 214cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov else 215cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_path(flags()->log_path); 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeSuppressions(); 21785a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#ifndef TSAN_GO 21868bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov // Initialize external symbolizer before internal threads are started. 2198cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov const char *external_symbolizer = flags()->external_symbolizer_path; 2208cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov if (external_symbolizer != 0 && external_symbolizer[0] != '\0') { 22193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (!InitializeExternalSymbolizer(external_symbolizer)) { 22293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov Printf("Failed to start external symbolizer: '%s'\n", 22393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov external_symbolizer); 22493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov Die(); 22593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov } 2268cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov } 22785a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#endif 2284bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov internal_start_thread(&BackgroundThread, 0); 2298cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov 2307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->flags.verbosity) 231b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n", 23267a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov GetPid()); 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Initialize thread 0. 2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = ThreadCreate(thr, 0, 0, true); 2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(tid, 0); 2377dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov ThreadStart(thr, tid, GetPid()); 2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(thr->in_rtl, 1); 2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->initialized = true; 2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 241adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->stop_on_start) { 242b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer is suspended at startup (pid %d)." 243adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov " Call __tsan_resume().\n", 244adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov GetPid()); 245ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov while (__tsan_resumed == 0) {} 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) { 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = __tsan::ctx; 2527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool failed = false; 2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25454e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1) 25554e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov SleepForMillis(flags()->atexit_sleep_ms); 25654e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov 257d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov // Wait for pending reports. 258d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov ctx->report_mtx.Lock(); 2597ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov CommonSanitizerReportMutex.Lock(); 2607ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov CommonSanitizerReportMutex.Unlock(); 261d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov ctx->report_mtx.Unlock(); 262d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov 263bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#ifndef TSAN_GO 264bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov if (ctx->flags.verbosity) 265bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov AllocatorPrintStats(); 266bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#endif 267bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov 2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadFinalize(thr); 2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nreported) { 2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 272b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#ifndef TSAN_GO 273b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported); 274b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else 275b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Found %d data race(s)\n", ctx->nreported); 276b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif 2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nmissed_expected) { 2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 281b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: missed %d expected races\n", 2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->nmissed_expected); 2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 285f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov if (flags()->print_suppressions) 286f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov PrintMatchedSuppressions(); 2870fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#ifndef TSAN_GO 2880fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov if (flags()->print_benign) 2890fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov PrintMatchedBenignRaces(); 2900fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#endif 291f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov 29222881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov failed = OnFinalize(failed); 29322881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov 29408adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov StatAggregate(ctx->stat, thr->stat); 2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatOutput(ctx->stat); 296b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov return failed ? flags()->exitcode : 0; 2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2990ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO 300848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) { 301848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (thr->shadow_stack_pos == 0) // May happen during bootstrap. 302848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return 0; 303848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) { 304848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos[0] = pc; 305848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos++; 306848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov } 307848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov u32 id = StackDepotPut(thr->shadow_stack, 308848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos - thr->shadow_stack); 309848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) 310848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos--; 311848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return id; 312848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 3130ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif 314848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 315b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) { 3169ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc++; 3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 3189743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov Trace *thr_trace = ThreadTrace(thr->tid); 3199743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov Lock l(&thr_trace->mtx); 3200415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts(); 3219743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov TraceHeader *hdr = &thr_trace->headers[trace]; 3227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->epoch0 = thr->fast_state.epoch(); 3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->stack0.ObtainCurrent(thr, 0); 324ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov hdr->mset0 = thr->mset; 3259ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc--; 3267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3289743d74426ae43898e4da55e591b09be18f8aa6eDmitry VyukovTrace *ThreadTrace(int tid) { 3299743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov return (Trace*)GetThreadTraceHeader(tid); 3309743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov} 3319743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov 332385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) { 333385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov Event *events = (Event*)GetThreadTrace(thr->tid); 334d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov uptr pc = events[thr->fast_state.GetTracePos()]; 335385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov return pc; 336385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov} 337385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov 338d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() { 339d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1)); 340d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov} 341d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov 3420415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() { 3430415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov return TraceSize() / kTracePartSize; 3440415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov} 3450415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov 346b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() { 3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceSwitch(cur_thread()); 3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() { 3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportRace(cur_thread()); 3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 354b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 3557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3567ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 35743c36e4b055f348d6076e6da44f9cd3e4399568fTimur IskhodzhanovShadow LoadShadow(u64 *p) { 3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed); 3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return Shadow(raw); 3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3627ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 36343c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreShadow(u64 *sp, u64 s) { 3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed); 3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3677ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 36843c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreIfNotYetStored(u64 *sp, u64 *s) { 3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(sp, *s); 3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *s = 0; 3717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem, 3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur, Shadow old) { 3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[0] = cur.raw(); 3767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[1] = old.raw(); 3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_shadow_addr = shadow_mem; 378b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HACKY_CALL(__tsan_report_race); 380b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 381b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov ReportRace(thr); 382b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) { 3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return old.epoch() >= thr->fast_synch_epoch; 3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) { 390c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov return thr->clock.get(old.TidWithIgnore()) >= old.epoch(); 3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 393d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 3947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr, 395334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic, 3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem, Shadow cur) { 3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatMop); 3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); 3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); 4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // This potentially can live in an MMX/SSE scratch register. 4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // The required intrinsics are: 4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // __m128i _mm_move_epi64(__m128i*); 4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // _mm_storel_epi64(u64*, __m128i); 4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 store_word = cur.raw(); 4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // scan all the shadow values and dispatch to 4 categories: 4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // same, replace, candidate and race (see comments below). 4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we consider only 3 cases regarding access sizes: 4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // equal, intersect and not intersect. initially I considered 4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // larger and smaller as well, it allowed to replace some 4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // 'candidates' with 'same' or 'replace', but I think 4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // it's just not worth it (performance- and complexity-wise). 4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 415286c914d37d28df611ae083cac40148cf2622ee7Dmitry Vyukov Shadow old(0); 4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (kShadowCnt == 1) { 4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 2) { 4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 4) { 4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 8) { 4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 4; 4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 5; 4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 6; 4477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 7; 4497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(false); 4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we did not find any races and had already stored 4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // the current access info, so we are done 4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (LIKELY(store_word == 0)) 4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // choose a random candidate slot and replace it 4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word); 4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatShadowReplace); 4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE: 4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HandleRace(thr, shadow_mem, cur, old); 4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4678ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovvoid UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr, 4688ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov int size, bool kAccessIsWrite, bool kIsAtomic) { 4698ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov while (size) { 4708ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov int size1 = 1; 4718ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov int kAccessSizeLog = kSizeLog1; 4728ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov if (size >= 8 && (addr & ~7) == ((addr + 8) & ~7)) { 4738ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov size1 = 8; 4748ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov kAccessSizeLog = kSizeLog8; 4758ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } else if (size >= 4 && (addr & ~7) == ((addr + 4) & ~7)) { 4768ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov size1 = 4; 4778ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov kAccessSizeLog = kSizeLog4; 4788ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } else if (size >= 2 && (addr & ~7) == ((addr + 2) & ~7)) { 4798ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov size1 = 2; 4808ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov kAccessSizeLog = kSizeLog2; 4818ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 4828ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov MemoryAccess(thr, pc, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic); 4838ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov addr += size1; 4848ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov size -= size1; 4858ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov } 4868ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov} 4878ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov 488d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 4897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr, 490334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) { 4917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem = (u64*)MemToShadow(addr); 49268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov DPrintf2("#%d: MemoryAccess: @%p %p size=%d" 493e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n", 4947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)thr->fast_state.tid(), (void*)pc, (void*)addr, 4957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem, 496e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[0], (uptr)shadow_mem[1], 497e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[2], (uptr)shadow_mem[3]); 4987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 4997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsAppMem(addr)) { 500b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Access to non app mem %zx\n", addr); 5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsAppMem(addr)); 5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsShadowMem((uptr)shadow_mem)) { 504b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr); 5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsShadowMem((uptr)shadow_mem)); 5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 50982dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov if (*shadow_mem == kShadowRodata) { 51082dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov // Access to .rodata section, no races here. 51182dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov // Measurements show that it can be 10-20% of all memory accesses. 51282dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, StatMop); 51382dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); 51482dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); 51582dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, StatMopRodata); 51682dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov return; 51782dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov } 51882dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov 5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany FastState fast_state = thr->fast_state; 5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (fast_state.GetIgnoreBit()) 5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany fast_state.IncrementEpoch(); 5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state = fast_state; 5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur(fast_state); 5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog); 5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetWrite(kAccessIsWrite); 527334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov cur.SetAtomic(kIsAtomic); 5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // We must not store to the trace if we do not store to the shadow. 5307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // That is, this call must be moved somewhere below. 531385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, fast_state, EventTypeMop, pc); 5327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 533334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic, 5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany shadow_mem, cur); 5357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, 5387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 val) { 53974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov (void)thr; 54074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov (void)pc; 5417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size == 0) 5427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: fix me. 5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr offset = addr % kShadowCell; 5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (offset) { 5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany offset = kShadowCell - offset; 5477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size <= offset) 5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany addr += offset; 5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size -= offset; 5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 552aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov DCHECK_EQ(addr % 8, 0); 553aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov // If a user passes some insane arguments (memset(0)), 554aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov // let it just crash as usual. 555aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov if (!IsAppMem(addr) || !IsAppMem(addr + size - 1)) 556aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov return; 55774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Don't want to touch lots of shadow memory. 55874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // If a program maps 10MB stack, there is no need reset the whole range. 55926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1); 56074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov if (size < 64*1024) { 56174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *p = (u64*)MemToShadow(addr); 56274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov CHECK(IsShadowMem((uptr)p)); 56374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1))); 56474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // FIXME: may overwrite a part outside the region 56574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) { 56674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov p[i++] = val; 56774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 56874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov p[i++] = 0; 56974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } 57074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } else { 57174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // The region is big, reset only beginning and end. 57274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov const uptr kPageSize = 4096; 57374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *begin = (u64*)MemToShadow(addr); 57474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *end = begin + size / kShadowCell * kShadowCnt; 57574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *p = begin; 57674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Set at least first kPageSize/2 to page boundary. 57774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) { 57874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = val; 57974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 58074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = 0; 58174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } 58274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Reset middle part. 58374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *p1 = p; 58474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov p = RoundDown(end, kPageSize); 58574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov UnmapOrDie((void*)p1, (uptr)p - (uptr)p1); 58674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1); 58774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Set the ending. 58874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov while (p < end) { 58974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = val; 59074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 59174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = 0; 59274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } 59326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov } 5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) { 5977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryRangeSet(thr, pc, addr, size, 0); 5987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) { 60174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Processing more than 1k (4k of shadow) is expensive, 60274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // can cause excessive memory consumption (user does not necessary touch 60374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // the whole range) and most likely unnecessary. 60474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov if (size > 1024) 60574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov size = 1024; 6063285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov CHECK_EQ(thr->is_freeing, false); 6073285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov thr->is_freeing = true; 6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, addr, size, true); 6093285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov thr->is_freeing = false; 61046fea91f84311643cbe7c8daf70c7f81656cf3e1Dmitry Vyukov thr->fast_state.IncrementEpoch(); 61146fea91f84311643cbe7c8daf70c7f81656cf3e1Dmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc); 612069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov Shadow s(thr->fast_state); 613064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov s.ClearIgnoreBit(); 614069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.MarkAsFreed(); 615069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetWrite(true); 616069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 617069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 62026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) { 62146fea91f84311643cbe7c8daf70c7f81656cf3e1Dmitry Vyukov thr->fast_state.IncrementEpoch(); 62246fea91f84311643cbe7c8daf70c7f81656cf3e1Dmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc); 62326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov Shadow s(thr->fast_state); 624064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov s.ClearIgnoreBit(); 62526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetWrite(true); 62626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 62726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 62826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov} 62926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov 630d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 6317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) { 6327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 6337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncEnter); 63425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); 6357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 636385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc); 6377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Shadow stack maintenance can be replaced with 6397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // stack unwinding during trace switch (which presumably must be faster). 640769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]); 64125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 642769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 64325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else 64425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov if (thr->shadow_stack_pos == thr->shadow_stack_end) { 64525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int sz = thr->shadow_stack_end - thr->shadow_stack; 64625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int newsz = 2 * sz; 64725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack, 64825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov newsz * sizeof(uptr)); 64925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr)); 65025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_free(thr->shadow_stack); 65125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack = newstack; 65225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_pos = newstack + sz; 65325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_end = newstack + newsz; 65425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov } 65525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 6567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos[0] = pc; 6577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos++; 6587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 660d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 6617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) { 6627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 6637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncExit); 66425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); 6657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 666385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0); 6677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 668769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]); 66925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 670769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 67125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 6727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos--; 6737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) { 6767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin); 6777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->ignore_reads_and_writes += begin ? 1 : -1; 6787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_GE(thr->ignore_reads_and_writes, 0); 6797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (thr->ignore_reads_and_writes) 6807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.SetIgnoreBit(); 6817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 6827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.ClearIgnoreBit(); 6837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 685b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const { 686b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return hash[0] == other.hash[0] && hash[1] == other.hash[1]; 687b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 688b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 6897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 6907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {} 6917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {} 6937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS 6967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {} 6977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {} 6997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 7007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1 7027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {} 7037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2 7047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {} 7057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4 7067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {} 7077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 7087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {} 7097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 7107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 7127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 713b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 7147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined. 7157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h" 716b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 717