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 //===----------------------------------------------------------------------===//
14 C++ linux memory layout:
15 0000 0000 0000 - 03c0 0000 0000: protected
16 03c0 0000 0000 - 1000 0000 0000: shadow
17 1000 0000 0000 - 3000 0000 0000: protected
18 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
19 4000 0000 0000 - 6000 0000 0000: protected
20 6000 0000 0000 - 6200 0000 0000: traces
21 6200 0000 0000 - 7d00 0000 0000: -
22 7d00 0000 0000 - 7e00 0000 0000: heap
23 7e00 0000 0000 - 7fff ffff ffff: modules and main thread stack
25 Go linux and darwin memory layout:
26 0000 0000 0000 - 0000 1000 0000: executable
27 0000 1000 0000 - 00f8 0000 0000: -
28 00c0 0000 0000 - 00e0 0000 0000: heap
29 00e0 0000 0000 - 1000 0000 0000: -
30 1000 0000 0000 - 1380 0000 0000: shadow
31 1460 0000 0000 - 2000 0000 0000: -
32 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
33 4000 0000 0000 - 6000 0000 0000: -
34 6000 0000 0000 - 6200 0000 0000: traces
35 6200 0000 0000 - 7fff ffff ffff: -
37 Go windows memory layout:
38 0000 0000 0000 - 0000 1000 0000: executable
39 0000 1000 0000 - 00f8 0000 0000: -
40 00c0 0000 0000 - 00e0 0000 0000: heap
41 00e0 0000 0000 - 0100 0000 0000: -
42 0100 0000 0000 - 0560 0000 0000: shadow
43 0560 0000 0000 - 0760 0000 0000: traces
44 0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
45 07d0 0000 0000 - 07ff ffff ffff: -
48 #ifndef TSAN_PLATFORM_H
49 #define TSAN_PLATFORM_H
51 #include "tsan_defs.h"
52 #include "tsan_trace.h"
54 #if defined(__LP64__) || defined(_WIN64)
58 static const uptr kLinuxAppMemBeg
= 0x000000000000ULL
;
59 static const uptr kLinuxAppMemEnd
= 0x04dfffffffffULL
;
60 # if SANITIZER_WINDOWS
61 static const uptr kLinuxShadowMsk
= 0x010000000000ULL
;
62 static const uptr kMetaShadow
= 0x076000000000ULL
;
63 static const uptr kMetaSize
= 0x007000000000ULL
;
64 # else // if SANITIZER_WINDOWS
65 static const uptr kLinuxShadowMsk
= 0x200000000000ULL
;
66 static const uptr kMetaShadow
= 0x300000000000ULL
;
67 static const uptr kMetaSize
= 0x100000000000ULL
;
68 # endif // if SANITIZER_WINDOWS
69 #else // defined(TSAN_GO)
70 static const uptr kMetaShadow
= 0x300000000000ULL
;
71 static const uptr kMetaSize
= 0x100000000000ULL
;
72 static const uptr kLinuxAppMemBeg
= 0x7cf000000000ULL
;
73 static const uptr kLinuxAppMemEnd
= 0x7fffffffffffULL
;
76 static const uptr kLinuxAppMemMsk
= 0x7c0000000000ULL
;
79 const uptr kTraceMemBegin
= 0x056000000000ULL
;
81 const uptr kTraceMemBegin
= 0x600000000000ULL
;
83 const uptr kTraceMemSize
= 0x020000000000ULL
;
85 // This has to be a macro to allow constant initialization of constants below.
87 #define MemToShadow(addr) \
88 ((((uptr)addr) & ~(kLinuxAppMemMsk | (kShadowCell - 1))) * kShadowCnt)
89 #define MemToMeta(addr) \
90 (u32*)(((((uptr)addr) & ~(kLinuxAppMemMsk | (kMetaShadowCell - 1))) \
91 / kMetaShadowCell * kMetaShadowSize) | kMetaShadow)
93 #define MemToShadow(addr) \
94 (((((uptr)addr) & ~(kShadowCell - 1)) * kShadowCnt) | kLinuxShadowMsk)
95 #define MemToMeta(addr) \
96 (u32*)(((((uptr)addr) & ~(kMetaShadowCell - 1)) \
97 / kMetaShadowCell * kMetaShadowSize) | kMetaShadow)
100 static const uptr kLinuxShadowBeg
= MemToShadow(kLinuxAppMemBeg
);
101 static const uptr kLinuxShadowEnd
=
102 MemToShadow(kLinuxAppMemEnd
) | 0xff;
104 static inline bool IsAppMem(uptr mem
) {
106 return mem
<= kLinuxAppMemEnd
;
108 return mem
>= kLinuxAppMemBeg
&& mem
<= kLinuxAppMemEnd
;
112 static inline bool IsShadowMem(uptr mem
) {
113 return mem
>= kLinuxShadowBeg
&& mem
<= kLinuxShadowEnd
;
116 static inline uptr
ShadowToMem(uptr shadow
) {
117 CHECK(IsShadowMem(shadow
));
119 return (shadow
& ~kLinuxShadowMsk
) / kShadowCnt
;
121 return (shadow
/ kShadowCnt
) | kLinuxAppMemMsk
;
125 void FlushShadowMemory();
126 void WriteMemoryProfile(char *buf
, uptr buf_size
, uptr nthread
, uptr nlive
);
129 void InitializePlatform();
130 void FinalizePlatform();
132 // The additional page is to catch shadow stack overflow as paging fault.
133 // Windows wants 64K alignment for mmaps.
134 const uptr kTotalTraceSize
= (kTraceSize
* sizeof(Event
) + sizeof(Trace
)
135 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
137 uptr ALWAYS_INLINE
GetThreadTrace(int tid
) {
138 uptr p
= kTraceMemBegin
+ (uptr
)tid
* kTotalTraceSize
;
139 DCHECK_LT(p
, kTraceMemBegin
+ kTraceMemSize
);
143 uptr ALWAYS_INLINE
GetThreadTraceHeader(int tid
) {
144 uptr p
= kTraceMemBegin
+ (uptr
)tid
* kTotalTraceSize
145 + kTraceSize
* sizeof(Event
);
146 DCHECK_LT(p
, kTraceMemBegin
+ kTraceMemSize
);
150 void *internal_start_thread(void(*func
)(void*), void *arg
);
151 void internal_join_thread(void *th
);
153 // Says whether the addr relates to a global var.
154 // Guesses with high probability, may yield both false positives and negatives.
155 bool IsGlobalVar(uptr addr
);
156 int ExtractResolvFDs(void *state
, int *fds
, int nfd
);
157 int ExtractRecvmsgFDs(void *msg
, int *fds
, int nfd
);
159 int call_pthread_cancel_with_cleanup(int(*fn
)(void *c
, void *m
,
160 void *abstime
), void *c
, void *m
, void *abstime
,
161 void(*cleanup
)(void *arg
), void *arg
);
163 } // namespace __tsan
165 #else // defined(__LP64__) || defined(_WIN64)
166 # error "Only 64-bit is supported"
169 #endif // TSAN_PLATFORM_H