tsan_platform.h revision 274201
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 - 6000 0000 0000: protected
206000 0000 0000 - 6200 0000 0000: traces
216200 0000 0000 - 7d00 0000 0000: -
227d00 0000 0000 - 7e00 0000 0000: heap
237e00 0000 0000 - 7fff ffff ffff: modules and main thread stack
24
25C++ COMPAT linux memory layout:
260000 0000 0000 - 0400 0000 0000: protected
270400 0000 0000 - 1000 0000 0000: shadow
281000 0000 0000 - 2900 0000 0000: protected
292900 0000 0000 - 2c00 0000 0000: modules
302c00 0000 0000 - 6000 0000 0000: -
316000 0000 0000 - 6200 0000 0000: traces
326200 0000 0000 - 7d00 0000 0000: -
337d00 0000 0000 - 7e00 0000 0000: heap
347e00 0000 0000 - 7f00 0000 0000: -
357f00 0000 0000 - 7fff ffff ffff: main thread stack
36
37Go linux and darwin memory layout:
380000 0000 0000 - 0000 1000 0000: executable
390000 1000 0000 - 00f8 0000 0000: -
4000c0 0000 0000 - 00e0 0000 0000: heap
4100e0 0000 0000 - 1000 0000 0000: -
421000 0000 0000 - 1380 0000 0000: shadow
431460 0000 0000 - 6000 0000 0000: -
446000 0000 0000 - 6200 0000 0000: traces
456200 0000 0000 - 7fff ffff ffff: -
46
47Go windows memory layout:
480000 0000 0000 - 0000 1000 0000: executable
490000 1000 0000 - 00f8 0000 0000: -
5000c0 0000 0000 - 00e0 0000 0000: heap
5100e0 0000 0000 - 0100 0000 0000: -
520100 0000 0000 - 0560 0000 0000: shadow
530560 0000 0000 - 0760 0000 0000: traces
540760 0000 0000 - 07ff ffff ffff: -
55*/
56
57#ifndef TSAN_PLATFORM_H
58#define TSAN_PLATFORM_H
59
60#include "tsan_defs.h"
61#include "tsan_trace.h"
62
63#if defined(__LP64__) || defined(_WIN64)
64namespace __tsan {
65
66#if defined(TSAN_GO)
67static const uptr kLinuxAppMemBeg = 0x000000000000ULL;
68static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL;
69# if SANITIZER_WINDOWS
70static const uptr kLinuxShadowMsk = 0x010000000000ULL;
71# else
72static const uptr kLinuxShadowMsk = 0x200000000000ULL;
73# endif
74// TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout,
75// when memory addresses are of the 0x2axxxxxxxxxx form.
76// The option is enabled with 'setarch x86_64 -L'.
77#elif defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
78static const uptr kLinuxAppMemBeg = 0x290000000000ULL;
79static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
80#else
81static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL;
82static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
83#endif
84
85static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL;
86
87#if SANITIZER_WINDOWS
88const uptr kTraceMemBegin = 0x056000000000ULL;
89#else
90const uptr kTraceMemBegin = 0x600000000000ULL;
91#endif
92const uptr kTraceMemSize = 0x020000000000ULL;
93
94// This has to be a macro to allow constant initialization of constants below.
95#ifndef TSAN_GO
96#define MemToShadow(addr) \
97    (((addr) & ~(kLinuxAppMemMsk | (kShadowCell - 1))) * kShadowCnt)
98#else
99#define MemToShadow(addr) \
100    ((((addr) & ~(kShadowCell - 1)) * kShadowCnt) | kLinuxShadowMsk)
101#endif
102
103static const uptr kLinuxShadowBeg = MemToShadow(kLinuxAppMemBeg);
104static const uptr kLinuxShadowEnd =
105    MemToShadow(kLinuxAppMemEnd) | 0xff;
106
107static inline bool IsAppMem(uptr mem) {
108  return mem >= kLinuxAppMemBeg && mem <= kLinuxAppMemEnd;
109}
110
111static inline bool IsShadowMem(uptr mem) {
112  return mem >= kLinuxShadowBeg && mem <= kLinuxShadowEnd;
113}
114
115static inline uptr ShadowToMem(uptr shadow) {
116  CHECK(IsShadowMem(shadow));
117#ifdef TSAN_GO
118  return (shadow & ~kLinuxShadowMsk) / kShadowCnt;
119#else
120  return (shadow / kShadowCnt) | kLinuxAppMemMsk;
121#endif
122}
123
124// For COMPAT mapping returns an alternative address
125// that mapped to the same shadow address.
126// COMPAT mapping is not quite one-to-one.
127static inline uptr AlternativeAddress(uptr addr) {
128#if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
129  return (addr & ~kLinuxAppMemMsk) | 0x280000000000ULL;
130#else
131  return 0;
132#endif
133}
134
135void FlushShadowMemory();
136void WriteMemoryProfile(char *buf, uptr buf_size);
137uptr GetRSS();
138
139const char *InitializePlatform();
140void FinalizePlatform();
141
142// The additional page is to catch shadow stack overflow as paging fault.
143const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace) + 4096
144    + 4095) & ~4095;
145
146uptr ALWAYS_INLINE GetThreadTrace(int tid) {
147  uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize;
148  DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
149  return p;
150}
151
152uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) {
153  uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize
154      + kTraceSize * sizeof(Event);
155  DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
156  return p;
157}
158
159void internal_start_thread(void(*func)(void*), void *arg);
160
161// Says whether the addr relates to a global var.
162// Guesses with high probability, may yield both false positives and negatives.
163bool IsGlobalVar(uptr addr);
164int ExtractResolvFDs(void *state, int *fds, int nfd);
165
166}  // namespace __tsan
167
168#else  // defined(__LP64__) || defined(_WIN64)
169# error "Only 64-bit is supported"
170#endif
171
172#endif  // TSAN_PLATFORM_H
173