1 //===-- tsan_platform.h -----------------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 // Platform-specific code.
11 //===----------------------------------------------------------------------===//
13 #ifndef TSAN_PLATFORM_H
14 #define TSAN_PLATFORM_H
16 #if !defined(__LP64__) && !defined(_WIN64)
17 # error "Only 64-bit is supported"
20 #include "tsan_defs.h"
21 #include "tsan_trace.h"
28 C/C++ on linux and freebsd
29 0000 0000 1000 - 0100 0000 0000: main binary and/or MAP_32BIT mappings
30 0100 0000 0000 - 0200 0000 0000: -
31 0200 0000 0000 - 1000 0000 0000: shadow
32 1000 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 - 7e80 0000 0000: -
39 7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
42 const uptr kMetaShadowBeg
= 0x300000000000ull
;
43 const uptr kMetaShadowEnd
= 0x400000000000ull
;
44 const uptr kTraceMemBeg
= 0x600000000000ull
;
45 const uptr kTraceMemEnd
= 0x620000000000ull
;
46 const uptr kShadowBeg
= 0x020000000000ull
;
47 const uptr kShadowEnd
= 0x100000000000ull
;
48 const uptr kHeapMemBeg
= 0x7d0000000000ull
;
49 const uptr kHeapMemEnd
= 0x7e0000000000ull
;
50 const uptr kLoAppMemBeg
= 0x000000001000ull
;
51 const uptr kLoAppMemEnd
= 0x010000000000ull
;
52 const uptr kHiAppMemBeg
= 0x7e8000000000ull
;
53 const uptr kHiAppMemEnd
= 0x800000000000ull
;
54 const uptr kAppMemMsk
= 0x7c0000000000ull
;
55 const uptr kAppMemXor
= 0x020000000000ull
;
58 bool IsAppMem(uptr mem
) {
59 return (mem
>= kHeapMemBeg
&& mem
< kHeapMemEnd
) ||
60 (mem
>= kLoAppMemBeg
&& mem
< kLoAppMemEnd
) ||
61 (mem
>= kHiAppMemBeg
&& mem
< kHiAppMemEnd
);
65 bool IsShadowMem(uptr mem
) {
66 return mem
>= kShadowBeg
&& mem
<= kShadowEnd
;
70 bool IsMetaMem(uptr mem
) {
71 return mem
>= kMetaShadowBeg
&& mem
<= kMetaShadowEnd
;
75 uptr
MemToShadow(uptr x
) {
77 return (((x
) & ~(kAppMemMsk
| (kShadowCell
- 1)))
78 ^ kAppMemXor
) * kShadowCnt
;
82 u32
*MemToMeta(uptr x
) {
84 return (u32
*)(((((x
) & ~(kAppMemMsk
| (kMetaShadowCell
- 1)))
85 ^ kAppMemXor
) / kMetaShadowCell
* kMetaShadowSize
) | kMetaShadowBeg
);
89 uptr
ShadowToMem(uptr s
) {
90 CHECK(IsShadowMem(s
));
91 if (s
>= MemToShadow(kLoAppMemBeg
) && s
<= MemToShadow(kLoAppMemEnd
- 1))
92 return (s
/ kShadowCnt
) ^ kAppMemXor
;
94 return ((s
/ kShadowCnt
) ^ kAppMemXor
) | kAppMemMsk
;
97 static USED uptr UserRegions
[] = {
98 kLoAppMemBeg
, kLoAppMemEnd
,
99 kHiAppMemBeg
, kHiAppMemEnd
,
100 kHeapMemBeg
, kHeapMemEnd
,
103 #elif defined(TSAN_GO) && !SANITIZER_WINDOWS
105 /* Go on linux, darwin and freebsd
106 0000 0000 1000 - 0000 1000 0000: executable
107 0000 1000 0000 - 00c0 0000 0000: -
108 00c0 0000 0000 - 00e0 0000 0000: heap
109 00e0 0000 0000 - 2000 0000 0000: -
110 2000 0000 0000 - 2380 0000 0000: shadow
111 2380 0000 0000 - 3000 0000 0000: -
112 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
113 4000 0000 0000 - 6000 0000 0000: -
114 6000 0000 0000 - 6200 0000 0000: traces
115 6200 0000 0000 - 8000 0000 0000: -
118 const uptr kMetaShadowBeg
= 0x300000000000ull
;
119 const uptr kMetaShadowEnd
= 0x400000000000ull
;
120 const uptr kTraceMemBeg
= 0x600000000000ull
;
121 const uptr kTraceMemEnd
= 0x620000000000ull
;
122 const uptr kShadowBeg
= 0x200000000000ull
;
123 const uptr kShadowEnd
= 0x238000000000ull
;
124 const uptr kAppMemBeg
= 0x000000001000ull
;
125 const uptr kAppMemEnd
= 0x00e000000000ull
;
128 bool IsAppMem(uptr mem
) {
129 return mem
>= kAppMemBeg
&& mem
< kAppMemEnd
;
133 bool IsShadowMem(uptr mem
) {
134 return mem
>= kShadowBeg
&& mem
<= kShadowEnd
;
138 bool IsMetaMem(uptr mem
) {
139 return mem
>= kMetaShadowBeg
&& mem
<= kMetaShadowEnd
;
143 uptr
MemToShadow(uptr x
) {
145 return ((x
& ~(kShadowCell
- 1)) * kShadowCnt
) | kShadowBeg
;
149 u32
*MemToMeta(uptr x
) {
151 return (u32
*)(((x
& ~(kMetaShadowCell
- 1)) / \
152 kMetaShadowCell
* kMetaShadowSize
) | kMetaShadowBeg
);
156 uptr
ShadowToMem(uptr s
) {
157 CHECK(IsShadowMem(s
));
158 return (s
& ~kShadowBeg
) / kShadowCnt
;
161 static USED uptr UserRegions
[] = {
162 kAppMemBeg
, kAppMemEnd
,
165 #elif defined(TSAN_GO) && SANITIZER_WINDOWS
168 0000 0000 1000 - 0000 1000 0000: executable
169 0000 1000 0000 - 00f8 0000 0000: -
170 00c0 0000 0000 - 00e0 0000 0000: heap
171 00e0 0000 0000 - 0100 0000 0000: -
172 0100 0000 0000 - 0380 0000 0000: shadow
173 0380 0000 0000 - 0560 0000 0000: -
174 0560 0000 0000 - 0760 0000 0000: traces
175 0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
176 07d0 0000 0000 - 8000 0000 0000: -
179 const uptr kMetaShadowBeg
= 0x076000000000ull
;
180 const uptr kMetaShadowEnd
= 0x07d000000000ull
;
181 const uptr kTraceMemBeg
= 0x056000000000ull
;
182 const uptr kTraceMemEnd
= 0x076000000000ull
;
183 const uptr kShadowBeg
= 0x010000000000ull
;
184 const uptr kShadowEnd
= 0x038000000000ull
;
185 const uptr kAppMemBeg
= 0x000000001000ull
;
186 const uptr kAppMemEnd
= 0x00e000000000ull
;
189 bool IsAppMem(uptr mem
) {
190 return mem
>= kAppMemBeg
&& mem
< kAppMemEnd
;
194 bool IsShadowMem(uptr mem
) {
195 return mem
>= kShadowBeg
&& mem
<= kShadowEnd
;
199 bool IsMetaMem(uptr mem
) {
200 return mem
>= kMetaShadowBeg
&& mem
<= kMetaShadowEnd
;
204 uptr
MemToShadow(uptr x
) {
206 return ((x
& ~(kShadowCell
- 1)) * kShadowCnt
) | kShadowBeg
;
210 u32
*MemToMeta(uptr x
) {
212 return (u32
*)(((x
& ~(kMetaShadowCell
- 1)) / \
213 kMetaShadowCell
* kMetaShadowSize
) | kMetaShadowEnd
);
217 uptr
ShadowToMem(uptr s
) {
218 CHECK(IsShadowMem(s
));
219 // FIXME(dvyukov): this is most likely wrong as the mapping is not bijection.
220 return (x
& ~kShadowBeg
) / kShadowCnt
;
223 static USED uptr UserRegions
[] = {
224 kAppMemBeg
, kAppMemEnd
,
228 # error "Unknown platform"
231 // The additional page is to catch shadow stack overflow as paging fault.
232 // Windows wants 64K alignment for mmaps.
233 const uptr kTotalTraceSize
= (kTraceSize
* sizeof(Event
) + sizeof(Trace
)
234 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
236 uptr ALWAYS_INLINE
GetThreadTrace(int tid
) {
237 uptr p
= kTraceMemBeg
+ (uptr
)tid
* kTotalTraceSize
;
238 DCHECK_LT(p
, kTraceMemEnd
);
242 uptr ALWAYS_INLINE
GetThreadTraceHeader(int tid
) {
243 uptr p
= kTraceMemBeg
+ (uptr
)tid
* kTotalTraceSize
244 + kTraceSize
* sizeof(Event
);
245 DCHECK_LT(p
, kTraceMemEnd
);
249 void InitializePlatform();
250 void FlushShadowMemory();
251 void WriteMemoryProfile(char *buf
, uptr buf_size
, uptr nthread
, uptr nlive
);
254 void *internal_start_thread(void(*func
)(void*), void *arg
);
255 void internal_join_thread(void *th
);
257 // Says whether the addr relates to a global var.
258 // Guesses with high probability, may yield both false positives and negatives.
259 bool IsGlobalVar(uptr addr
);
260 int ExtractResolvFDs(void *state
, int *fds
, int nfd
);
261 int ExtractRecvmsgFDs(void *msg
, int *fds
, int nfd
);
263 int call_pthread_cancel_with_cleanup(int(*fn
)(void *c
, void *m
,
264 void *abstime
), void *c
, void *m
, void *abstime
,
265 void(*cleanup
)(void *arg
), void *arg
);
267 } // namespace __tsan
269 #endif // TSAN_PLATFORM_H