blob: 135e16027132a22e85879d3fc35113fd932566e9 [file] [log] [blame]
Kostya Serebryany7ac41482012-05-10 13:48:04 +00001//===-- 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
Dmitry Vyukov5b266cb2012-07-16 13:02:40 +000015#ifndef TSAN_PLATFORM_H
16#define TSAN_PLATFORM_H
Kostya Serebryany7ac41482012-05-10 13:48:04 +000017
Stephen Hines6d186232014-11-26 17:56:19 -080018#if !defined(__LP64__) && !defined(_WIN64)
19# error "Only 64-bit is supported"
20#endif
21
Dmitry Vyukov385542a2012-11-28 10:35:31 +000022#include "tsan_defs.h"
23#include "tsan_trace.h"
Kostya Serebryany7ac41482012-05-10 13:48:04 +000024
Kostya Serebryany7ac41482012-05-10 13:48:04 +000025namespace __tsan {
26
Stephen Hines86277eb2015-03-23 12:06:32 -070027#if !defined(SANITIZER_GO)
Kostya Serebryany7ac41482012-05-10 13:48:04 +000028
Stephen Hines86277eb2015-03-23 12:06:32 -070029#if defined(__x86_64__)
Stephen Hines6d186232014-11-26 17:56:19 -080030/*
Stephen Hines86277eb2015-03-23 12:06:32 -070031C/C++ on linux/x86_64 and freebsd/x86_64
Stephen Hines6d186232014-11-26 17:56:19 -0800320000 0000 1000 - 0100 0000 0000: main binary and/or MAP_32BIT mappings
330100 0000 0000 - 0200 0000 0000: -
340200 0000 0000 - 1000 0000 0000: shadow
351000 0000 0000 - 3000 0000 0000: -
363000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
374000 0000 0000 - 6000 0000 0000: -
386000 0000 0000 - 6200 0000 0000: traces
396200 0000 0000 - 7d00 0000 0000: -
407d00 0000 0000 - 7e00 0000 0000: heap
417e00 0000 0000 - 7e80 0000 0000: -
427e80 0000 0000 - 8000 0000 0000: modules and main thread stack
43*/
Stephen Hines6d186232014-11-26 17:56:19 -080044const uptr kMetaShadowBeg = 0x300000000000ull;
45const uptr kMetaShadowEnd = 0x400000000000ull;
46const uptr kTraceMemBeg = 0x600000000000ull;
47const uptr kTraceMemEnd = 0x620000000000ull;
48const uptr kShadowBeg = 0x020000000000ull;
49const uptr kShadowEnd = 0x100000000000ull;
50const uptr kHeapMemBeg = 0x7d0000000000ull;
51const uptr kHeapMemEnd = 0x7e0000000000ull;
52const uptr kLoAppMemBeg = 0x000000001000ull;
53const uptr kLoAppMemEnd = 0x010000000000ull;
54const uptr kHiAppMemBeg = 0x7e8000000000ull;
55const uptr kHiAppMemEnd = 0x800000000000ull;
56const uptr kAppMemMsk = 0x7c0000000000ull;
57const uptr kAppMemXor = 0x020000000000ull;
Stephen Hines86277eb2015-03-23 12:06:32 -070058const uptr kVdsoBeg = 0xf000000000000000ull;
59#elif defined(__mips64)
60/*
61C/C++ on linux/mips64
620100 0000 00 - 0200 0000 00: main binary
630200 0000 00 - 1400 0000 00: -
641400 0000 00 - 2400 0000 00: shadow
652400 0000 00 - 3000 0000 00: -
663000 0000 00 - 4000 0000 00: metainfo (memory blocks and sync objects)
674000 0000 00 - 6000 0000 00: -
686000 0000 00 - 6200 0000 00: traces
696200 0000 00 - fe00 0000 00: -
70fe00 0000 00 - ff00 0000 00: heap
71ff00 0000 00 - ff80 0000 00: -
72ff80 0000 00 - ffff ffff ff: modules and main thread stack
73*/
74const uptr kMetaShadowBeg = 0x3000000000ull;
75const uptr kMetaShadowEnd = 0x4000000000ull;
76const uptr kTraceMemBeg = 0x6000000000ull;
77const uptr kTraceMemEnd = 0x6200000000ull;
78const uptr kShadowBeg = 0x1400000000ull;
79const uptr kShadowEnd = 0x2400000000ull;
80const uptr kHeapMemBeg = 0xfe00000000ull;
81const uptr kHeapMemEnd = 0xff00000000ull;
82const uptr kLoAppMemBeg = 0x0100000000ull;
83const uptr kLoAppMemEnd = 0x0200000000ull;
84const uptr kHiAppMemBeg = 0xff80000000ull;
85const uptr kHiAppMemEnd = 0xffffffffffull;
86const uptr kAppMemMsk = 0xfc00000000ull;
87const uptr kAppMemXor = 0x0400000000ull;
88const uptr kVdsoBeg = 0xfffff00000ull;
89#endif
Dmitry Vyukov385542a2012-11-28 10:35:31 +000090
Stephen Hines6d186232014-11-26 17:56:19 -080091ALWAYS_INLINE
92bool IsAppMem(uptr mem) {
93 return (mem >= kHeapMemBeg && mem < kHeapMemEnd) ||
94 (mem >= kLoAppMemBeg && mem < kLoAppMemEnd) ||
95 (mem >= kHiAppMemBeg && mem < kHiAppMemEnd);
Kostya Serebryany7ac41482012-05-10 13:48:04 +000096}
97
Stephen Hines6d186232014-11-26 17:56:19 -080098ALWAYS_INLINE
99bool IsShadowMem(uptr mem) {
100 return mem >= kShadowBeg && mem <= kShadowEnd;
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000101}
102
Stephen Hines6d186232014-11-26 17:56:19 -0800103ALWAYS_INLINE
104bool IsMetaMem(uptr mem) {
105 return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd;
106}
107
108ALWAYS_INLINE
109uptr MemToShadow(uptr x) {
110 DCHECK(IsAppMem(x));
111 return (((x) & ~(kAppMemMsk | (kShadowCell - 1)))
112 ^ kAppMemXor) * kShadowCnt;
113}
114
115ALWAYS_INLINE
116u32 *MemToMeta(uptr x) {
117 DCHECK(IsAppMem(x));
118 return (u32*)(((((x) & ~(kAppMemMsk | (kMetaShadowCell - 1)))
119 ^ kAppMemXor) / kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg);
120}
121
122ALWAYS_INLINE
123uptr ShadowToMem(uptr s) {
124 CHECK(IsShadowMem(s));
125 if (s >= MemToShadow(kLoAppMemBeg) && s <= MemToShadow(kLoAppMemEnd - 1))
126 return (s / kShadowCnt) ^ kAppMemXor;
127 else
128 return ((s / kShadowCnt) ^ kAppMemXor) | kAppMemMsk;
129}
130
131static USED uptr UserRegions[] = {
132 kLoAppMemBeg, kLoAppMemEnd,
133 kHiAppMemBeg, kHiAppMemEnd,
134 kHeapMemBeg, kHeapMemEnd,
135};
136
Stephen Hines86277eb2015-03-23 12:06:32 -0700137#elif defined(SANITIZER_GO) && !SANITIZER_WINDOWS
Stephen Hines6d186232014-11-26 17:56:19 -0800138
139/* Go on linux, darwin and freebsd
1400000 0000 1000 - 0000 1000 0000: executable
1410000 1000 0000 - 00c0 0000 0000: -
14200c0 0000 0000 - 00e0 0000 0000: heap
14300e0 0000 0000 - 2000 0000 0000: -
1442000 0000 0000 - 2380 0000 0000: shadow
1452380 0000 0000 - 3000 0000 0000: -
1463000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
1474000 0000 0000 - 6000 0000 0000: -
1486000 0000 0000 - 6200 0000 0000: traces
1496200 0000 0000 - 8000 0000 0000: -
150*/
151
152const uptr kMetaShadowBeg = 0x300000000000ull;
153const uptr kMetaShadowEnd = 0x400000000000ull;
154const uptr kTraceMemBeg = 0x600000000000ull;
155const uptr kTraceMemEnd = 0x620000000000ull;
156const uptr kShadowBeg = 0x200000000000ull;
157const uptr kShadowEnd = 0x238000000000ull;
158const uptr kAppMemBeg = 0x000000001000ull;
159const uptr kAppMemEnd = 0x00e000000000ull;
160
161ALWAYS_INLINE
162bool IsAppMem(uptr mem) {
163 return mem >= kAppMemBeg && mem < kAppMemEnd;
164}
165
166ALWAYS_INLINE
167bool IsShadowMem(uptr mem) {
168 return mem >= kShadowBeg && mem <= kShadowEnd;
169}
170
171ALWAYS_INLINE
172bool IsMetaMem(uptr mem) {
173 return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd;
174}
175
176ALWAYS_INLINE
177uptr MemToShadow(uptr x) {
178 DCHECK(IsAppMem(x));
179 return ((x & ~(kShadowCell - 1)) * kShadowCnt) | kShadowBeg;
180}
181
182ALWAYS_INLINE
183u32 *MemToMeta(uptr x) {
184 DCHECK(IsAppMem(x));
185 return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
186 kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg);
187}
188
189ALWAYS_INLINE
190uptr ShadowToMem(uptr s) {
191 CHECK(IsShadowMem(s));
192 return (s & ~kShadowBeg) / kShadowCnt;
193}
194
195static USED uptr UserRegions[] = {
196 kAppMemBeg, kAppMemEnd,
197};
198
Stephen Hines86277eb2015-03-23 12:06:32 -0700199#elif defined(SANITIZER_GO) && SANITIZER_WINDOWS
Stephen Hines6d186232014-11-26 17:56:19 -0800200
201/* Go on windows
2020000 0000 1000 - 0000 1000 0000: executable
2030000 1000 0000 - 00f8 0000 0000: -
20400c0 0000 0000 - 00e0 0000 0000: heap
20500e0 0000 0000 - 0100 0000 0000: -
Stephen Hines86277eb2015-03-23 12:06:32 -07002060100 0000 0000 - 0500 0000 0000: shadow
2070500 0000 0000 - 0560 0000 0000: -
Stephen Hines6d186232014-11-26 17:56:19 -08002080560 0000 0000 - 0760 0000 0000: traces
2090760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
21007d0 0000 0000 - 8000 0000 0000: -
211*/
212
213const uptr kMetaShadowBeg = 0x076000000000ull;
214const uptr kMetaShadowEnd = 0x07d000000000ull;
215const uptr kTraceMemBeg = 0x056000000000ull;
216const uptr kTraceMemEnd = 0x076000000000ull;
217const uptr kShadowBeg = 0x010000000000ull;
Stephen Hines86277eb2015-03-23 12:06:32 -0700218const uptr kShadowEnd = 0x050000000000ull;
Stephen Hines6d186232014-11-26 17:56:19 -0800219const uptr kAppMemBeg = 0x000000001000ull;
220const uptr kAppMemEnd = 0x00e000000000ull;
221
222ALWAYS_INLINE
223bool IsAppMem(uptr mem) {
224 return mem >= kAppMemBeg && mem < kAppMemEnd;
225}
226
227ALWAYS_INLINE
228bool IsShadowMem(uptr mem) {
229 return mem >= kShadowBeg && mem <= kShadowEnd;
230}
231
232ALWAYS_INLINE
233bool IsMetaMem(uptr mem) {
234 return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd;
235}
236
237ALWAYS_INLINE
238uptr MemToShadow(uptr x) {
239 DCHECK(IsAppMem(x));
Stephen Hines86277eb2015-03-23 12:06:32 -0700240 return ((x & ~(kShadowCell - 1)) * kShadowCnt) + kShadowBeg;
Stephen Hines6d186232014-11-26 17:56:19 -0800241}
242
243ALWAYS_INLINE
244u32 *MemToMeta(uptr x) {
245 DCHECK(IsAppMem(x));
246 return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
Stephen Hines86277eb2015-03-23 12:06:32 -0700247 kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg);
Stephen Hines6d186232014-11-26 17:56:19 -0800248}
249
250ALWAYS_INLINE
251uptr ShadowToMem(uptr s) {
252 CHECK(IsShadowMem(s));
253 // FIXME(dvyukov): this is most likely wrong as the mapping is not bijection.
Stephen Hines86277eb2015-03-23 12:06:32 -0700254 return (s - kShadowBeg) / kShadowCnt;
Stephen Hines6d186232014-11-26 17:56:19 -0800255}
256
257static USED uptr UserRegions[] = {
258 kAppMemBeg, kAppMemEnd,
259};
260
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000261#else
Stephen Hines6d186232014-11-26 17:56:19 -0800262# error "Unknown platform"
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000263#endif
Dmitry Vyukov01a7ce82013-10-16 15:35:12 +0000264
265// The additional page is to catch shadow stack overflow as paging fault.
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700266// Windows wants 64K alignment for mmaps.
267const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
268 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
Dmitry Vyukov01a7ce82013-10-16 15:35:12 +0000269
Timur Iskhodzhanovabfdbdf2013-03-28 18:52:40 +0000270uptr ALWAYS_INLINE GetThreadTrace(int tid) {
Stephen Hines6d186232014-11-26 17:56:19 -0800271 uptr p = kTraceMemBeg + (uptr)tid * kTotalTraceSize;
272 DCHECK_LT(p, kTraceMemEnd);
Dmitry Vyukov9743d742013-03-20 10:31:53 +0000273 return p;
274}
275
Timur Iskhodzhanovabfdbdf2013-03-28 18:52:40 +0000276uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) {
Stephen Hines6d186232014-11-26 17:56:19 -0800277 uptr p = kTraceMemBeg + (uptr)tid * kTotalTraceSize
Dmitry Vyukov01a7ce82013-10-16 15:35:12 +0000278 + kTraceSize * sizeof(Event);
Stephen Hines6d186232014-11-26 17:56:19 -0800279 DCHECK_LT(p, kTraceMemEnd);
Dmitry Vyukov385542a2012-11-28 10:35:31 +0000280 return p;
281}
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000282
Stephen Hines6d186232014-11-26 17:56:19 -0800283void InitializePlatform();
284void FlushShadowMemory();
285void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000286
Dmitry Vyukov0c2feef2012-09-07 18:08:02 +0000287// Says whether the addr relates to a global var.
288// Guesses with high probability, may yield both false positives and negatives.
289bool IsGlobalVar(uptr addr);
Dmitry Vyukov03f22482013-02-07 15:27:45 +0000290int ExtractResolvFDs(void *state, int *fds, int nfd);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700291int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
292
293int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
294 void *abstime), void *c, void *m, void *abstime,
295 void(*cleanup)(void *arg), void *arg);
Kostya Serebryany7ac41482012-05-10 13:48:04 +0000296
297} // namespace __tsan
298
Dmitry Vyukov5b266cb2012-07-16 13:02:40 +0000299#endif // TSAN_PLATFORM_H