• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*
16 C++ linux memory layout:
17 0000 0000 0000 - 03c0 0000 0000: protected
18 03c0 0000 0000 - 1000 0000 0000: shadow
19 1000 0000 0000 - 3000 0000 0000: protected
20 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
21 4000 0000 0000 - 6000 0000 0000: protected
22 6000 0000 0000 - 6200 0000 0000: traces
23 6200 0000 0000 - 7d00 0000 0000: -
24 7d00 0000 0000 - 7e00 0000 0000: heap
25 7e00 0000 0000 - 7fff ffff ffff: modules and main thread stack
26 
27 C++ COMPAT linux memory layout:
28 0000 0000 0000 - 0400 0000 0000: protected
29 0400 0000 0000 - 1000 0000 0000: shadow
30 1000 0000 0000 - 2900 0000 0000: protected
31 2900 0000 0000 - 2c00 0000 0000: modules
32 2c00 0000 0000 - 3000 0000 0000: -
33 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
34 4000 0000 0000 - 6000 0000 0000: -
35 6000 0000 0000 - 6200 0000 0000: traces
36 6200 0000 0000 - 7d00 0000 0000: -
37 7d00 0000 0000 - 7e00 0000 0000: heap
38 7e00 0000 0000 - 7f00 0000 0000: -
39 7f00 0000 0000 - 7fff ffff ffff: main thread stack
40 
41 Go linux and darwin memory layout:
42 0000 0000 0000 - 0000 1000 0000: executable
43 0000 1000 0000 - 00f8 0000 0000: -
44 00c0 0000 0000 - 00e0 0000 0000: heap
45 00e0 0000 0000 - 1000 0000 0000: -
46 1000 0000 0000 - 1380 0000 0000: shadow
47 1460 0000 0000 - 2000 0000 0000: -
48 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
49 4000 0000 0000 - 6000 0000 0000: -
50 6000 0000 0000 - 6200 0000 0000: traces
51 6200 0000 0000 - 7fff ffff ffff: -
52 
53 Go windows memory layout:
54 0000 0000 0000 - 0000 1000 0000: executable
55 0000 1000 0000 - 00f8 0000 0000: -
56 00c0 0000 0000 - 00e0 0000 0000: heap
57 00e0 0000 0000 - 0100 0000 0000: -
58 0100 0000 0000 - 0560 0000 0000: shadow
59 0560 0000 0000 - 0760 0000 0000: traces
60 0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
61 07d0 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)
71 namespace __tsan {
72 
73 #if defined(TSAN_GO)
74 static const uptr kLinuxAppMemBeg = 0x000000000000ULL;
75 static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL;
76 # if SANITIZER_WINDOWS
77 static const uptr kLinuxShadowMsk = 0x010000000000ULL;
78 static const uptr kMetaShadow     = 0x076000000000ULL;
79 static const uptr kMetaSize       = 0x007000000000ULL;
80 # else  // if SANITIZER_WINDOWS
81 static const uptr kLinuxShadowMsk = 0x200000000000ULL;
82 static const uptr kMetaShadow     = 0x300000000000ULL;
83 static const uptr kMetaSize       = 0x100000000000ULL;
84 # endif  // if SANITIZER_WINDOWS
85 #else  // defined(TSAN_GO)
86 static const uptr kMetaShadow     = 0x300000000000ULL;
87 static 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
92 static const uptr kLinuxAppMemBeg = 0x290000000000ULL;
93 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
94 static const uptr kAppMemGapBeg   = 0x2c0000000000ULL;
95 static const uptr kAppMemGapEnd   = 0x7d0000000000ULL;
96 # else
97 static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL;
98 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
99 # endif
100 #endif
101 
102 static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL;
103 
104 #if SANITIZER_WINDOWS
105 const uptr kTraceMemBegin = 0x056000000000ULL;
106 #else
107 const uptr kTraceMemBegin = 0x600000000000ULL;
108 #endif
109 const 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 
126 static const uptr kLinuxShadowBeg = MemToShadow(kLinuxAppMemBeg);
127 static const uptr kLinuxShadowEnd =
128     MemToShadow(kLinuxAppMemEnd) | 0xff;
129 
IsAppMem(uptr mem)130 static 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 
IsShadowMem(uptr mem)141 static inline bool IsShadowMem(uptr mem) {
142   return mem >= kLinuxShadowBeg && mem <= kLinuxShadowEnd;
143 }
144 
ShadowToMem(uptr shadow)145 static 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.
AlternativeAddress(uptr addr)157 static 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 
165 void FlushShadowMemory();
166 void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
167 uptr GetRSS();
168 
169 const char *InitializePlatform();
170 void FinalizePlatform();
171 
172 // The additional page is to catch shadow stack overflow as paging fault.
173 // Windows wants 64K alignment for mmaps.
174 const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
175     + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
176 
GetThreadTrace(int tid)177 uptr ALWAYS_INLINE GetThreadTrace(int tid) {
178   uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize;
179   DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
180   return p;
181 }
182 
GetThreadTraceHeader(int tid)183 uptr 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 
190 void *internal_start_thread(void(*func)(void*), void *arg);
191 void 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.
195 bool IsGlobalVar(uptr addr);
196 int ExtractResolvFDs(void *state, int *fds, int nfd);
197 int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
198 
199 int 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