tsan_platform.h revision 5d71de26cedae3dafc17449fe0182045c0bd20e8
1//===-- tsan_platform.h -----------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of ThreadSanitizer (TSan), a race detector. 11// 12// Platform-specific code. 13//===----------------------------------------------------------------------===// 14 15/* 16C++ linux memory layout: 170000 0000 0000 - 03c0 0000 0000: protected 1803c0 0000 0000 - 1000 0000 0000: shadow 191000 0000 0000 - 3000 0000 0000: protected 203000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) 214000 0000 0000 - 6000 0000 0000: protected 226000 0000 0000 - 6200 0000 0000: traces 236200 0000 0000 - 7d00 0000 0000: - 247d00 0000 0000 - 7e00 0000 0000: heap 257e00 0000 0000 - 7fff ffff ffff: modules and main thread stack 26 27C++ COMPAT linux memory layout: 280000 0000 0000 - 0400 0000 0000: protected 290400 0000 0000 - 1000 0000 0000: shadow 301000 0000 0000 - 2900 0000 0000: protected 312900 0000 0000 - 2c00 0000 0000: modules 322c00 0000 0000 - 3000 0000 0000: - 333000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) 344000 0000 0000 - 6000 0000 0000: - 356000 0000 0000 - 6200 0000 0000: traces 366200 0000 0000 - 7d00 0000 0000: - 377d00 0000 0000 - 7e00 0000 0000: heap 387e00 0000 0000 - 7f00 0000 0000: - 397f00 0000 0000 - 7fff ffff ffff: main thread stack 40 41Go linux and darwin memory layout: 420000 0000 0000 - 0000 1000 0000: executable 430000 1000 0000 - 00f8 0000 0000: - 4400c0 0000 0000 - 00e0 0000 0000: heap 4500e0 0000 0000 - 1000 0000 0000: - 461000 0000 0000 - 1380 0000 0000: shadow 471460 0000 0000 - 2000 0000 0000: - 483000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) 494000 0000 0000 - 6000 0000 0000: - 506000 0000 0000 - 6200 0000 0000: traces 516200 0000 0000 - 7fff ffff ffff: - 52 53Go windows memory layout: 540000 0000 0000 - 0000 1000 0000: executable 550000 1000 0000 - 00f8 0000 0000: - 5600c0 0000 0000 - 00e0 0000 0000: heap 5700e0 0000 0000 - 0100 0000 0000: - 580100 0000 0000 - 0560 0000 0000: shadow 590560 0000 0000 - 0760 0000 0000: traces 600760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects) 6107d0 0000 0000 - 07ff ffff ffff: - 62*/ 63 64#ifndef TSAN_PLATFORM_H 65#define TSAN_PLATFORM_H 66 67#include "tsan_defs.h" 68#include "tsan_trace.h" 69 70#if defined(__LP64__) || defined(_WIN64) 71namespace __tsan { 72 73#if defined(TSAN_GO) 74static const uptr kLinuxAppMemBeg = 0x000000000000ULL; 75static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL; 76# if SANITIZER_WINDOWS 77static const uptr kLinuxShadowMsk = 0x010000000000ULL; 78static const uptr kMetaShadow = 0x076000000000ULL; 79static const uptr kMetaSize = 0x007000000000ULL; 80# else // if SANITIZER_WINDOWS 81static const uptr kLinuxShadowMsk = 0x200000000000ULL; 82static const uptr kMetaShadow = 0x300000000000ULL; 83static const uptr kMetaSize = 0x100000000000ULL; 84# endif // if SANITIZER_WINDOWS 85#else // defined(TSAN_GO) 86static const uptr kMetaShadow = 0x300000000000ULL; 87static const uptr kMetaSize = 0x100000000000ULL; 88// TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout, 89// when memory addresses are of the 0x2axxxxxxxxxx form. 90// The option is enabled with 'setarch x86_64 -L'. 91# if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 92static const uptr kLinuxAppMemBeg = 0x290000000000ULL; 93static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL; 94static const uptr kAppMemGapBeg = 0x2c0000000000ULL; 95static const uptr kAppMemGapEnd = 0x7d0000000000ULL; 96# else 97static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL; 98static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL; 99# endif 100#endif 101 102static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL; 103 104#if SANITIZER_WINDOWS 105const uptr kTraceMemBegin = 0x056000000000ULL; 106#else 107const uptr kTraceMemBegin = 0x600000000000ULL; 108#endif 109const uptr kTraceMemSize = 0x020000000000ULL; 110 111// This has to be a macro to allow constant initialization of constants below. 112#ifndef TSAN_GO 113#define MemToShadow(addr) \ 114 ((((uptr)addr) & ~(kLinuxAppMemMsk | (kShadowCell - 1))) * kShadowCnt) 115#define MemToMeta(addr) \ 116 (u32*)(((((uptr)addr) & ~(kLinuxAppMemMsk | (kMetaShadowCell - 1))) \ 117 / kMetaShadowCell * kMetaShadowSize) | kMetaShadow) 118#else 119#define MemToShadow(addr) \ 120 (((((uptr)addr) & ~(kShadowCell - 1)) * kShadowCnt) | kLinuxShadowMsk) 121#define MemToMeta(addr) \ 122 (u32*)(((((uptr)addr) & ~(kMetaShadowCell - 1)) \ 123 / kMetaShadowCell * kMetaShadowSize) | kMetaShadow) 124#endif 125 126static const uptr kLinuxShadowBeg = MemToShadow(kLinuxAppMemBeg); 127static const uptr kLinuxShadowEnd = 128 MemToShadow(kLinuxAppMemEnd) | 0xff; 129 130static inline bool IsAppMem(uptr mem) { 131#if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 132 return (mem >= kLinuxAppMemBeg && mem < kAppMemGapBeg) || 133 (mem >= kAppMemGapEnd && mem <= kLinuxAppMemEnd); 134#elif defined(TSAN_GO) 135 return mem <= kLinuxAppMemEnd; 136#else 137 return mem >= kLinuxAppMemBeg && mem <= kLinuxAppMemEnd; 138#endif 139} 140 141static inline bool IsShadowMem(uptr mem) { 142 return mem >= kLinuxShadowBeg && mem <= kLinuxShadowEnd; 143} 144 145static inline uptr ShadowToMem(uptr shadow) { 146 CHECK(IsShadowMem(shadow)); 147#ifdef TSAN_GO 148 return (shadow & ~kLinuxShadowMsk) / kShadowCnt; 149#else 150 return (shadow / kShadowCnt) | kLinuxAppMemMsk; 151#endif 152} 153 154// For COMPAT mapping returns an alternative address 155// that mapped to the same shadow address. 156// COMPAT mapping is not quite one-to-one. 157static inline uptr AlternativeAddress(uptr addr) { 158#if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 159 return (addr & ~kLinuxAppMemMsk) | 0x280000000000ULL; 160#else 161 return 0; 162#endif 163} 164 165void FlushShadowMemory(); 166void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); 167uptr GetRSS(); 168 169const char *InitializePlatform(); 170void FinalizePlatform(); 171 172// The additional page is to catch shadow stack overflow as paging fault. 173// Windows wants 64K alignment for mmaps. 174const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace) 175 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1); 176 177uptr ALWAYS_INLINE GetThreadTrace(int tid) { 178 uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize; 179 DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); 180 return p; 181} 182 183uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { 184 uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize 185 + kTraceSize * sizeof(Event); 186 DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); 187 return p; 188} 189 190void *internal_start_thread(void(*func)(void*), void *arg); 191void internal_join_thread(void *th); 192 193// Says whether the addr relates to a global var. 194// Guesses with high probability, may yield both false positives and negatives. 195bool IsGlobalVar(uptr addr); 196int ExtractResolvFDs(void *state, int *fds, int nfd); 197int ExtractRecvmsgFDs(void *msg, int *fds, int nfd); 198 199int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, 200 void *abstime), void *c, void *m, void *abstime, 201 void(*cleanup)(void *arg), void *arg); 202 203} // namespace __tsan 204 205#else // defined(__LP64__) || defined(_WIN64) 206# error "Only 64-bit is supported" 207#endif 208 209#endif // TSAN_PLATFORM_H 210