tsan_rtl.cc revision 7ed46ff7af911da0dd2067734d1408c6986c6657
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()); 1244bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov mprof_fd = OpenFile(filename.data(), true); 1254bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov if (mprof_fd == kInvalidFd) { 1264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov Printf("ThreadSanitizer: failed to open memory profile file '%s'\n", 1274bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov &filename[0]); 1284bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1294bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1304bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 1314bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov u64 last_flush = NanoTime(); 13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov for (int i = 0; ; i++) { 1330969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov SleepForSeconds(1); 1344bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov u64 now = NanoTime(); 13526127735454fddae3495794f38189d57dde6510fDmitry Vyukov 136a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov // Flush memory if requested. 1374bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov if (flags()->flush_memory_ms) { 138f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) { 1394bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov FlushShadowMemory(); 1404bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov last_flush = NanoTime(); 1414bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1424bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov } 1434bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov 144a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov // Write memory profile if requested. 1454bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov if (mprof_fd != kInvalidFd) 146a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov MemoryProfiler(ctx, mprof_fd, i); 147a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov 148a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#ifndef TSAN_GO 149f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov // Flush symbolizer cache if requested. 150f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov if (flags()->flush_symbolizer_ms > 0) { 151f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov u64 last = atomic_load(&ctx->last_symbolize_time_ns, 152f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov memory_order_relaxed); 153f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) { 154f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov Lock l(&ctx->report_mtx); 1557ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov SpinMutexLock l2(&CommonSanitizerReportMutex); 156f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov SymbolizeFlush(); 157f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed); 158f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov } 159a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov } 160a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#endif 16126127735454fddae3495794f38189d57dde6510fDmitry Vyukov } 16226127735454fddae3495794f38189d57dde6510fDmitry Vyukov} 16326127735454fddae3495794f38189d57dde6510fDmitry Vyukov 1647ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukovvoid DontNeedShadowFor(uptr addr, uptr size) { 1657ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov uptr shadow_beg = MemToShadow(addr); 1667ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov uptr shadow_end = MemToShadow(addr + size); 1677ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg); 1687ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov} 1697ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov 170a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) { 1716b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier); 172a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov} 173a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov 1746535c31c66569df262791f0b56852c496977c977Dmitry Vyukovvoid MapThreadTrace(uptr addr, uptr size) { 175dae1251f196f9694d428a04f14987b06112ae52cDmitry Vyukov DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size); 1766535c31c66569df262791f0b56852c496977c977Dmitry Vyukov CHECK_GE(addr, kTraceMemBegin); 1776535c31c66569df262791f0b56852c496977c977Dmitry Vyukov CHECK_LE(addr + size, kTraceMemBegin + kTraceMemSize); 1786535c31c66569df262791f0b56852c496977c977Dmitry Vyukov if (addr != (uptr)MmapFixedNoReserve(addr, size)) { 1796535c31c66569df262791f0b56852c496977c977Dmitry Vyukov Printf("FATAL: ThreadSanitizer can not mmap thread trace\n"); 1806535c31c66569df262791f0b56852c496977c977Dmitry Vyukov Die(); 1816535c31c66569df262791f0b56852c496977c977Dmitry Vyukov } 1826535c31c66569df262791f0b56852c496977c977Dmitry Vyukov} 1836535c31c66569df262791f0b56852c496977c977Dmitry Vyukov 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) { 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Thread safe because done before all threads exist. 1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static bool is_initialized = false; 1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (is_initialized) 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany is_initialized = true; 190859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany SanitizerToolName = "ThreadSanitizer"; 191591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov // Install tool-specific callbacks in sanitizer_common. 192591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov SetCheckFailedCallback(TsanCheckFailed); 193591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov 1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 195bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO 1962e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov InitializeAllocator(); 197bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif 1987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeInterceptors(); 1997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *env = InitializePlatform(); 2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeMutex(); 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeDynamicAnnotations(); 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx = new(ctx_placeholder) Context; 203a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#ifndef TSAN_GO 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeShadowMemory(); 205a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeFlags(&ctx->flags, env); 207b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov // Setup correct file descriptor for error reports. 208cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov if (internal_strcmp(flags()->log_path, "stdout") == 0) 209cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_fd(kStdoutFd); 210cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov else if (internal_strcmp(flags()->log_path, "stderr") == 0) 211cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_fd(kStderrFd); 212cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov else 213cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov __sanitizer_set_report_path(flags()->log_path); 2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany InitializeSuppressions(); 21585a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#ifndef TSAN_GO 21668bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov // Initialize external symbolizer before internal threads are started. 2178cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov const char *external_symbolizer = flags()->external_symbolizer_path; 2188cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov if (external_symbolizer != 0 && external_symbolizer[0] != '\0') { 21993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (!InitializeExternalSymbolizer(external_symbolizer)) { 22093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov Printf("Failed to start external symbolizer: '%s'\n", 22193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov external_symbolizer); 22293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov Die(); 22393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov } 2248cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov } 22585a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#endif 2264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov internal_start_thread(&BackgroundThread, 0); 2278cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov 2287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->flags.verbosity) 229b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n", 23067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov GetPid()); 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Initialize thread 0. 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = ThreadCreate(thr, 0, 0, true); 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(tid, 0); 2357dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov ThreadStart(thr, tid, GetPid()); 2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(thr->in_rtl, 1); 2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->initialized = true; 2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 239adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov if (flags()->stop_on_start) { 240b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer is suspended at startup (pid %d)." 241adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov " Call __tsan_resume().\n", 242adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov GetPid()); 243ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov while (__tsan_resumed == 0) {} 2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) { 2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Context *ctx = __tsan::ctx; 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool failed = false; 2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25254e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1) 25354e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov SleepForMillis(flags()->atexit_sleep_ms); 25454e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov 255d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov // Wait for pending reports. 256d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov ctx->report_mtx.Lock(); 2577ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov CommonSanitizerReportMutex.Lock(); 2587ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov CommonSanitizerReportMutex.Unlock(); 259d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov ctx->report_mtx.Unlock(); 260d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov 261bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#ifndef TSAN_GO 262bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov if (ctx->flags.verbosity) 263bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov AllocatorPrintStats(); 264bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#endif 265bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov 2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadFinalize(thr); 2677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nreported) { 2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 270b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#ifndef TSAN_GO 271b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported); 272b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else 273b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Found %d data race(s)\n", ctx->nreported); 274b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif 2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (ctx->nmissed_expected) { 2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany failed = true; 279b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: missed %d expected races\n", 2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ctx->nmissed_expected); 2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 283f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov if (flags()->print_suppressions) 284f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov PrintMatchedSuppressions(); 2850fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#ifndef TSAN_GO 2860fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov if (flags()->print_benign) 2870fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov PrintMatchedBenignRaces(); 2880fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#endif 289f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov 29022881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov failed = OnFinalize(failed); 29122881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov 29208adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov StatAggregate(ctx->stat, thr->stat); 2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatOutput(ctx->stat); 294b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov return failed ? flags()->exitcode : 0; 2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2970ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO 298848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) { 299848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (thr->shadow_stack_pos == 0) // May happen during bootstrap. 300848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return 0; 301848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) { 302848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos[0] = pc; 303848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos++; 304848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov } 305848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov u32 id = StackDepotPut(thr->shadow_stack, 306848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos - thr->shadow_stack); 307848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov if (pc) 308848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov thr->shadow_stack_pos--; 309848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return id; 310848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 3110ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif 312848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 313b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) { 3149ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc++; 3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ScopedInRtl in_rtl; 3169743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov Trace *thr_trace = ThreadTrace(thr->tid); 3179743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov Lock l(&thr_trace->mtx); 3180415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts(); 3199743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov TraceHeader *hdr = &thr_trace->headers[trace]; 3207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->epoch0 = thr->fast_state.epoch(); 3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany hdr->stack0.ObtainCurrent(thr, 0); 322ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov hdr->mset0 = thr->mset; 3239ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov thr->nomalloc--; 3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3269743d74426ae43898e4da55e591b09be18f8aa6eDmitry VyukovTrace *ThreadTrace(int tid) { 3279743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov return (Trace*)GetThreadTraceHeader(tid); 3289743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov} 3299743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov 330385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) { 331385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov Event *events = (Event*)GetThreadTrace(thr->tid); 332d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov uptr pc = events[thr->fast_state.GetTracePos()]; 333385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov return pc; 334385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov} 335385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov 336d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() { 337d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1)); 338d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov} 339d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov 3400415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() { 3410415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov return TraceSize() / kTracePartSize; 3420415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov} 3430415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov 344b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() { 3467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TraceSwitch(cur_thread()); 3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() { 3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ReportRace(cur_thread()); 3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 352b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 35543c36e4b055f348d6076e6da44f9cd3e4399568fTimur IskhodzhanovShadow LoadShadow(u64 *p) { 3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed); 3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return Shadow(raw); 3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3607ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 36143c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreShadow(u64 *sp, u64 s) { 3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed); 3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3657ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE 36643c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreIfNotYetStored(u64 *sp, u64 *s) { 3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(sp, *s); 3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *s = 0; 3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem, 3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur, Shadow old) { 3737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[0] = cur.raw(); 3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_state[1] = old.raw(); 3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->racy_shadow_addr = shadow_mem; 376b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HACKY_CALL(__tsan_report_race); 378b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else 379b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov ReportRace(thr); 380b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) { 3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return old.epoch() >= thr->fast_synch_epoch; 3857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) { 388c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov return thr->clock.get(old.TidWithIgnore()) >= old.epoch(); 3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 391d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr, 393334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic, 3947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem, Shadow cur) { 3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatMop); 3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); 3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); 3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // This potentially can live in an MMX/SSE scratch register. 4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // The required intrinsics are: 4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // __m128i _mm_move_epi64(__m128i*); 4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // _mm_storel_epi64(u64*, __m128i); 4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 store_word = cur.raw(); 4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // scan all the shadow values and dispatch to 4 categories: 4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // same, replace, candidate and race (see comments below). 4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we consider only 3 cases regarding access sizes: 4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // equal, intersect and not intersect. initially I considered 4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // larger and smaller as well, it allowed to replace some 4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // 'candidates' with 'same' or 'replace', but I think 4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // it's just not worth it (performance- and complexity-wise). 4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 413286c914d37d28df611ae083cac40148cf2622ee7Dmitry Vyukov Shadow old(0); 4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (kShadowCnt == 1) { 4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 2) { 4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 4) { 4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else if (kShadowCnt == 8) { 4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int idx = 0; 4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 1; 4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 2; 4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 3; 4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 4; 4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 5; 4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 6; 4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany idx = 7; 4477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h" 4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 4497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(false); 4507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // we did not find any races and had already stored 4537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // the current access info, so we are done 4547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (LIKELY(store_word == 0)) 4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // choose a random candidate slot and replace it 4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word); 4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatShadowReplace); 4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE: 4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany HandleRace(thr, shadow_mem, cur, old); 4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 465d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr, 467334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) { 4687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 *shadow_mem = (u64*)MemToShadow(addr); 46968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov DPrintf2("#%d: MemoryAccess: @%p %p size=%d" 470e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n", 4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)thr->fast_state.tid(), (void*)pc, (void*)addr, 4727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem, 473e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[0], (uptr)shadow_mem[1], 474e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (uptr)shadow_mem[2], (uptr)shadow_mem[3]); 4757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 4767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsAppMem(addr)) { 477b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Access to non app mem %zx\n", addr); 4787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsAppMem(addr)); 4797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsShadowMem((uptr)shadow_mem)) { 481b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr); 4827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK(IsShadowMem((uptr)shadow_mem)); 4837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 48682dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov if (*shadow_mem == kShadowRodata) { 48782dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov // Access to .rodata section, no races here. 48882dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov // Measurements show that it can be 10-20% of all memory accesses. 48982dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, StatMop); 49082dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead); 49182dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog)); 49282dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov StatInc(thr, StatMopRodata); 49382dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov return; 49482dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov } 49582dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov 4967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany FastState fast_state = thr->fast_state; 4977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (fast_state.GetIgnoreBit()) 4987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 4997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany fast_state.IncrementEpoch(); 5007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state = fast_state; 5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Shadow cur(fast_state); 5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog); 5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cur.SetWrite(kAccessIsWrite); 504334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov cur.SetAtomic(kIsAtomic); 5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // We must not store to the trace if we do not store to the shadow. 5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // That is, this call must be moved somewhere below. 508385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, fast_state, EventTypeMop, pc); 5097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 510334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic, 5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany shadow_mem, cur); 5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, 5157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 val) { 51674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov (void)thr; 51774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov (void)pc; 5187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size == 0) 5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // FIXME: fix me. 5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr offset = addr % kShadowCell; 5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (offset) { 5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany offset = kShadowCell - offset; 5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (size <= offset) 5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany addr += offset; 5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany size -= offset; 5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 529aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov DCHECK_EQ(addr % 8, 0); 530aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov // If a user passes some insane arguments (memset(0)), 531aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov // let it just crash as usual. 532aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov if (!IsAppMem(addr) || !IsAppMem(addr + size - 1)) 533aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov return; 53474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Don't want to touch lots of shadow memory. 53574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // If a program maps 10MB stack, there is no need reset the whole range. 53626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1); 53774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov if (size < 64*1024) { 53874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *p = (u64*)MemToShadow(addr); 53974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov CHECK(IsShadowMem((uptr)p)); 54074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1))); 54174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // FIXME: may overwrite a part outside the region 54274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) { 54374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov p[i++] = val; 54474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 54574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov p[i++] = 0; 54674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } 54774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } else { 54874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // The region is big, reset only beginning and end. 54974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov const uptr kPageSize = 4096; 55074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *begin = (u64*)MemToShadow(addr); 55174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *end = begin + size / kShadowCell * kShadowCnt; 55274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *p = begin; 55374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Set at least first kPageSize/2 to page boundary. 55474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) { 55574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = val; 55674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 55774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = 0; 55874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } 55974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Reset middle part. 56074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov u64 *p1 = p; 56174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov p = RoundDown(end, kPageSize); 56274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov UnmapOrDie((void*)p1, (uptr)p - (uptr)p1); 56374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1); 56474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Set the ending. 56574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov while (p < end) { 56674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = val; 56774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov for (uptr j = 1; j < kShadowCnt; j++) 56874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov *p++ = 0; 56974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov } 57026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov } 5717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) { 5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryRangeSet(thr, pc, addr, size, 0); 5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) { 57874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // Processing more than 1k (4k of shadow) is expensive, 57974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // can cause excessive memory consumption (user does not necessary touch 58074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov // the whole range) and most likely unnecessary. 58174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov if (size > 1024) 58274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov size = 1024; 5833285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov CHECK_EQ(thr->is_freeing, false); 5843285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov thr->is_freeing = true; 5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, addr, size, true); 5863285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov thr->is_freeing = false; 587069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov Shadow s(thr->fast_state); 588064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov s.ClearIgnoreBit(); 589069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.MarkAsFreed(); 590069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetWrite(true); 591069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 592069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 59526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) { 59626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov Shadow s(thr->fast_state); 597064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov s.ClearIgnoreBit(); 59826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetWrite(true); 59926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov s.SetAddr0AndSizeLog(0, 3); 60026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov MemoryRangeSet(thr, pc, addr, size, s.raw()); 60126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov} 60226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov 603d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) { 6057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncEnter); 60725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc); 6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 609385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc); 6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Shadow stack maintenance can be replaced with 6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // stack unwinding during trace switch (which presumably must be faster). 613769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]); 61425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 615769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 61625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else 61725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov if (thr->shadow_stack_pos == thr->shadow_stack_end) { 61825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int sz = thr->shadow_stack_end - thr->shadow_stack; 61925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov const int newsz = 2 * sz; 62025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack, 62125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov newsz * sizeof(uptr)); 62225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr)); 62325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov internal_free(thr->shadow_stack); 62425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack = newstack; 62525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_pos = newstack + sz; 62625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov thr->shadow_stack_end = newstack + newsz; 62725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov } 62825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 6297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos[0] = pc; 6307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos++; 6317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 633d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED 6347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) { 6357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(thr->in_rtl, 0); 6367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(thr, StatFuncExit); 63725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid()); 6387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.IncrementEpoch(); 639385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0); 6407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 641769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]); 64225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO 643769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); 64425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif 6457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->shadow_stack_pos--; 6467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) { 6497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin); 6507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->ignore_reads_and_writes += begin ? 1 : -1; 6517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_GE(thr->ignore_reads_and_writes, 0); 6527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (thr->ignore_reads_and_writes) 6537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.SetIgnoreBit(); 6547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 6557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany thr->fast_state.ClearIgnoreBit(); 6567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 658b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const { 659b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov return hash[0] == other.hash[0] && hash[1] == other.hash[1]; 660b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov} 661b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov 6627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG 6637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {} 6647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {} 6667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS 6697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {} 6707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {} 6727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1 6757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {} 6767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2 6777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {} 6787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4 6797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {} 6807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else 6817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {} 6827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 6837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 6847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 6857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 686b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO 6877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined. 6887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h" 689b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif 690