gcc/libsanitizer/tsan/tsan_platform.h
Marek Polacek c191b1abe9 Cherry-pick compiler-rt revision 318044 and 319180.
[PowerPC][tsan] Update tsan to handle changed memory layouts in newer kernels
    
    In more recent Linux kernels with 47 bit VMAs the layout of virtual memory
    for powerpc64 changed causing the thread sanitizer to not work properly. This
    patch adds support for 47 bit VMA kernels for powerpc64.
    
    Tested on several 4.x and 3.x kernel releases.

Regtested/bootstrapped on ppc64le-linux with kernel 4.14; applying to
trunk/8.3.

2018-08-01  Marek Polacek  <polacek@redhat.com>

	PR sanitizer/86759
	* tsan/tsan_platform.h: Cherry-pick compiler-rt revision 318044.
	* tsan/tsan_platform_linux.cc: Cherry-pick compiler-rt revision
	319180.

From-SVN: r263229
2018-08-01 17:17:29 +00:00

909 lines
29 KiB
C++

//===-- tsan_platform.h -----------------------------------------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
// Platform-specific code.
//===----------------------------------------------------------------------===//
#ifndef TSAN_PLATFORM_H
#define TSAN_PLATFORM_H
#if !defined(__LP64__) && !defined(_WIN64)
# error "Only 64-bit is supported"
#endif
#include "tsan_defs.h"
#include "tsan_trace.h"
namespace __tsan {
#if !SANITIZER_GO
#if defined(__x86_64__)
/*
C/C++ on linux/x86_64 and freebsd/x86_64
0000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
0040 0000 0000 - 0100 0000 0000: -
0100 0000 0000 - 2000 0000 0000: shadow
2000 0000 0000 - 3000 0000 0000: -
3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
4000 0000 0000 - 5500 0000 0000: -
5500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
5680 0000 0000 - 6000 0000 0000: -
6000 0000 0000 - 6200 0000 0000: traces
6200 0000 0000 - 7d00 0000 0000: -
7b00 0000 0000 - 7c00 0000 0000: heap
7c00 0000 0000 - 7e80 0000 0000: -
7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
*/
struct Mapping {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x340000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
static const uptr kTraceMemEnd = 0x620000000000ull;
static const uptr kShadowBeg = 0x010000000000ull;
static const uptr kShadowEnd = 0x200000000000ull;
static const uptr kHeapMemBeg = 0x7b0000000000ull;
static const uptr kHeapMemEnd = 0x7c0000000000ull;
static const uptr kLoAppMemBeg = 0x000000001000ull;
static const uptr kLoAppMemEnd = 0x008000000000ull;
static const uptr kMidAppMemBeg = 0x550000000000ull;
static const uptr kMidAppMemEnd = 0x568000000000ull;
static const uptr kHiAppMemBeg = 0x7e8000000000ull;
static const uptr kHiAppMemEnd = 0x800000000000ull;
static const uptr kAppMemMsk = 0x780000000000ull;
static const uptr kAppMemXor = 0x040000000000ull;
static const uptr kVdsoBeg = 0xf000000000000000ull;
};
#define TSAN_MID_APP_RANGE 1
#elif defined(__mips64)
/*
C/C++ on linux/mips64
0100 0000 00 - 0200 0000 00: main binary
0200 0000 00 - 1400 0000 00: -
1400 0000 00 - 2400 0000 00: shadow
2400 0000 00 - 3000 0000 00: -
3000 0000 00 - 4000 0000 00: metainfo (memory blocks and sync objects)
4000 0000 00 - 6000 0000 00: -
6000 0000 00 - 6200 0000 00: traces
6200 0000 00 - fe00 0000 00: -
fe00 0000 00 - ff00 0000 00: heap
ff00 0000 00 - ff80 0000 00: -
ff80 0000 00 - ffff ffff ff: modules and main thread stack
*/
struct Mapping {
static const uptr kMetaShadowBeg = 0x4000000000ull;
static const uptr kMetaShadowEnd = 0x5000000000ull;
static const uptr kTraceMemBeg = 0xb000000000ull;
static const uptr kTraceMemEnd = 0xb200000000ull;
static const uptr kShadowBeg = 0x2400000000ull;
static const uptr kShadowEnd = 0x4000000000ull;
static const uptr kHeapMemBeg = 0xfe00000000ull;
static const uptr kHeapMemEnd = 0xff00000000ull;
static const uptr kLoAppMemBeg = 0x0100000000ull;
static const uptr kLoAppMemEnd = 0x0200000000ull;
static const uptr kMidAppMemBeg = 0xaa00000000ull;
static const uptr kMidAppMemEnd = 0xab00000000ull;
static const uptr kHiAppMemBeg = 0xff80000000ull;
static const uptr kHiAppMemEnd = 0xffffffffffull;
static const uptr kAppMemMsk = 0xf800000000ull;
static const uptr kAppMemXor = 0x0800000000ull;
static const uptr kVdsoBeg = 0xfffff00000ull;
};
#define TSAN_MID_APP_RANGE 1
#elif defined(__aarch64__) && defined(__APPLE__)
/*
C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM)
0000 0000 00 - 0100 0000 00: - (4 GB)
0100 0000 00 - 0200 0000 00: main binary, modules, thread stacks (4 GB)
0200 0000 00 - 0300 0000 00: heap (4 GB)
0300 0000 00 - 0400 0000 00: - (4 GB)
0400 0000 00 - 0c00 0000 00: shadow memory (32 GB)
0c00 0000 00 - 0d00 0000 00: - (4 GB)
0d00 0000 00 - 0e00 0000 00: metainfo (4 GB)
0e00 0000 00 - 0f00 0000 00: - (4 GB)
0f00 0000 00 - 1000 0000 00: traces (4 GB)
*/
struct Mapping {
static const uptr kLoAppMemBeg = 0x0100000000ull;
static const uptr kLoAppMemEnd = 0x0200000000ull;
static const uptr kHeapMemBeg = 0x0200000000ull;
static const uptr kHeapMemEnd = 0x0300000000ull;
static const uptr kShadowBeg = 0x0400000000ull;
static const uptr kShadowEnd = 0x0c00000000ull;
static const uptr kMetaShadowBeg = 0x0d00000000ull;
static const uptr kMetaShadowEnd = 0x0e00000000ull;
static const uptr kTraceMemBeg = 0x0f00000000ull;
static const uptr kTraceMemEnd = 0x1000000000ull;
static const uptr kHiAppMemBeg = 0x1000000000ull;
static const uptr kHiAppMemEnd = 0x1000000000ull;
static const uptr kAppMemMsk = 0x0ull;
static const uptr kAppMemXor = 0x0ull;
static const uptr kVdsoBeg = 0x7000000000000000ull;
};
#elif defined(__aarch64__)
// AArch64 supports multiple VMA which leads to multiple address transformation
// functions. To support these multiple VMAS transformations and mappings TSAN
// runtime for AArch64 uses an external memory read (vmaSize) to select which
// mapping to use. Although slower, it make a same instrumented binary run on
// multiple kernels.
/*
C/C++ on linux/aarch64 (39-bit VMA)
0000 0010 00 - 0100 0000 00: main binary
0100 0000 00 - 0800 0000 00: -
0800 0000 00 - 2000 0000 00: shadow memory
2000 0000 00 - 3100 0000 00: -
3100 0000 00 - 3400 0000 00: metainfo
3400 0000 00 - 5500 0000 00: -
5500 0000 00 - 5600 0000 00: main binary (PIE)
5600 0000 00 - 6000 0000 00: -
6000 0000 00 - 6200 0000 00: traces
6200 0000 00 - 7d00 0000 00: -
7c00 0000 00 - 7d00 0000 00: heap
7d00 0000 00 - 7fff ffff ff: modules and main thread stack
*/
struct Mapping39 {
static const uptr kLoAppMemBeg = 0x0000001000ull;
static const uptr kLoAppMemEnd = 0x0100000000ull;
static const uptr kShadowBeg = 0x0800000000ull;
static const uptr kShadowEnd = 0x2000000000ull;
static const uptr kMetaShadowBeg = 0x3100000000ull;
static const uptr kMetaShadowEnd = 0x3400000000ull;
static const uptr kMidAppMemBeg = 0x5500000000ull;
static const uptr kMidAppMemEnd = 0x5600000000ull;
static const uptr kTraceMemBeg = 0x6000000000ull;
static const uptr kTraceMemEnd = 0x6200000000ull;
static const uptr kHeapMemBeg = 0x7c00000000ull;
static const uptr kHeapMemEnd = 0x7d00000000ull;
static const uptr kHiAppMemBeg = 0x7e00000000ull;
static const uptr kHiAppMemEnd = 0x7fffffffffull;
static const uptr kAppMemMsk = 0x7800000000ull;
static const uptr kAppMemXor = 0x0200000000ull;
static const uptr kVdsoBeg = 0x7f00000000ull;
};
/*
C/C++ on linux/aarch64 (42-bit VMA)
00000 0010 00 - 01000 0000 00: main binary
01000 0000 00 - 10000 0000 00: -
10000 0000 00 - 20000 0000 00: shadow memory
20000 0000 00 - 26000 0000 00: -
26000 0000 00 - 28000 0000 00: metainfo
28000 0000 00 - 2aa00 0000 00: -
2aa00 0000 00 - 2ab00 0000 00: main binary (PIE)
2ab00 0000 00 - 36200 0000 00: -
36200 0000 00 - 36240 0000 00: traces
36240 0000 00 - 3e000 0000 00: -
3e000 0000 00 - 3f000 0000 00: heap
3f000 0000 00 - 3ffff ffff ff: modules and main thread stack
*/
struct Mapping42 {
static const uptr kLoAppMemBeg = 0x00000001000ull;
static const uptr kLoAppMemEnd = 0x01000000000ull;
static const uptr kShadowBeg = 0x10000000000ull;
static const uptr kShadowEnd = 0x20000000000ull;
static const uptr kMetaShadowBeg = 0x26000000000ull;
static const uptr kMetaShadowEnd = 0x28000000000ull;
static const uptr kMidAppMemBeg = 0x2aa00000000ull;
static const uptr kMidAppMemEnd = 0x2ab00000000ull;
static const uptr kTraceMemBeg = 0x36200000000ull;
static const uptr kTraceMemEnd = 0x36400000000ull;
static const uptr kHeapMemBeg = 0x3e000000000ull;
static const uptr kHeapMemEnd = 0x3f000000000ull;
static const uptr kHiAppMemBeg = 0x3f000000000ull;
static const uptr kHiAppMemEnd = 0x3ffffffffffull;
static const uptr kAppMemMsk = 0x3c000000000ull;
static const uptr kAppMemXor = 0x04000000000ull;
static const uptr kVdsoBeg = 0x37f00000000ull;
};
struct Mapping48 {
static const uptr kLoAppMemBeg = 0x0000000001000ull;
static const uptr kLoAppMemEnd = 0x0000200000000ull;
static const uptr kShadowBeg = 0x0002000000000ull;
static const uptr kShadowEnd = 0x0004000000000ull;
static const uptr kMetaShadowBeg = 0x0005000000000ull;
static const uptr kMetaShadowEnd = 0x0006000000000ull;
static const uptr kMidAppMemBeg = 0x0aaaa00000000ull;
static const uptr kMidAppMemEnd = 0x0aaaf00000000ull;
static const uptr kTraceMemBeg = 0x0f06000000000ull;
static const uptr kTraceMemEnd = 0x0f06200000000ull;
static const uptr kHeapMemBeg = 0x0ffff00000000ull;
static const uptr kHeapMemEnd = 0x0ffff00000000ull;
static const uptr kHiAppMemBeg = 0x0ffff00000000ull;
static const uptr kHiAppMemEnd = 0x1000000000000ull;
static const uptr kAppMemMsk = 0x0fff800000000ull;
static const uptr kAppMemXor = 0x0000800000000ull;
static const uptr kVdsoBeg = 0xffff000000000ull;
};
// Indicates the runtime will define the memory regions at runtime.
#define TSAN_RUNTIME_VMA 1
// Indicates that mapping defines a mid range memory segment.
#define TSAN_MID_APP_RANGE 1
#elif defined(__powerpc64__)
// PPC64 supports multiple VMA which leads to multiple address transformation
// functions. To support these multiple VMAS transformations and mappings TSAN
// runtime for PPC64 uses an external memory read (vmaSize) to select which
// mapping to use. Although slower, it make a same instrumented binary run on
// multiple kernels.
/*
C/C++ on linux/powerpc64 (44-bit VMA)
0000 0000 0100 - 0001 0000 0000: main binary
0001 0000 0000 - 0001 0000 0000: -
0001 0000 0000 - 0b00 0000 0000: shadow
0b00 0000 0000 - 0b00 0000 0000: -
0b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects)
0d00 0000 0000 - 0d00 0000 0000: -
0d00 0000 0000 - 0f00 0000 0000: traces
0f00 0000 0000 - 0f00 0000 0000: -
0f00 0000 0000 - 0f50 0000 0000: heap
0f50 0000 0000 - 0f60 0000 0000: -
0f60 0000 0000 - 1000 0000 0000: modules and main thread stack
*/
struct Mapping44 {
static const uptr kMetaShadowBeg = 0x0b0000000000ull;
static const uptr kMetaShadowEnd = 0x0d0000000000ull;
static const uptr kTraceMemBeg = 0x0d0000000000ull;
static const uptr kTraceMemEnd = 0x0f0000000000ull;
static const uptr kShadowBeg = 0x000100000000ull;
static const uptr kShadowEnd = 0x0b0000000000ull;
static const uptr kLoAppMemBeg = 0x000000000100ull;
static const uptr kLoAppMemEnd = 0x000100000000ull;
static const uptr kHeapMemBeg = 0x0f0000000000ull;
static const uptr kHeapMemEnd = 0x0f5000000000ull;
static const uptr kHiAppMemBeg = 0x0f6000000000ull;
static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits
static const uptr kAppMemMsk = 0x0f0000000000ull;
static const uptr kAppMemXor = 0x002100000000ull;
static const uptr kVdsoBeg = 0x3c0000000000000ull;
};
/*
C/C++ on linux/powerpc64 (46-bit VMA)
0000 0000 1000 - 0100 0000 0000: main binary
0100 0000 0000 - 0200 0000 0000: -
0100 0000 0000 - 1000 0000 0000: shadow
1000 0000 0000 - 1000 0000 0000: -
1000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects)
2000 0000 0000 - 2000 0000 0000: -
2000 0000 0000 - 2200 0000 0000: traces
2200 0000 0000 - 3d00 0000 0000: -
3d00 0000 0000 - 3e00 0000 0000: heap
3e00 0000 0000 - 3e80 0000 0000: -
3e80 0000 0000 - 4000 0000 0000: modules and main thread stack
*/
struct Mapping46 {
static const uptr kMetaShadowBeg = 0x100000000000ull;
static const uptr kMetaShadowEnd = 0x200000000000ull;
static const uptr kTraceMemBeg = 0x200000000000ull;
static const uptr kTraceMemEnd = 0x220000000000ull;
static const uptr kShadowBeg = 0x010000000000ull;
static const uptr kShadowEnd = 0x100000000000ull;
static const uptr kHeapMemBeg = 0x3d0000000000ull;
static const uptr kHeapMemEnd = 0x3e0000000000ull;
static const uptr kLoAppMemBeg = 0x000000001000ull;
static const uptr kLoAppMemEnd = 0x010000000000ull;
static const uptr kHiAppMemBeg = 0x3e8000000000ull;
static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits
static const uptr kAppMemMsk = 0x3c0000000000ull;
static const uptr kAppMemXor = 0x020000000000ull;
static const uptr kVdsoBeg = 0x7800000000000000ull;
};
/*
C/C++ on linux/powerpc64 (47-bit VMA)
0000 0000 1000 - 0100 0000 0000: main binary
0100 0000 0000 - 0200 0000 0000: -
0100 0000 0000 - 1000 0000 0000: shadow
1000 0000 0000 - 1000 0000 0000: -
1000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects)
2000 0000 0000 - 2000 0000 0000: -
2000 0000 0000 - 2200 0000 0000: traces
2200 0000 0000 - 7d00 0000 0000: -
7d00 0000 0000 - 7e00 0000 0000: heap
7e00 0000 0000 - 7e80 0000 0000: -
7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
*/
struct Mapping47 {
static const uptr kMetaShadowBeg = 0x100000000000ull;
static const uptr kMetaShadowEnd = 0x200000000000ull;
static const uptr kTraceMemBeg = 0x200000000000ull;
static const uptr kTraceMemEnd = 0x220000000000ull;
static const uptr kShadowBeg = 0x010000000000ull;
static const uptr kShadowEnd = 0x100000000000ull;
static const uptr kHeapMemBeg = 0x7d0000000000ull;
static const uptr kHeapMemEnd = 0x7e0000000000ull;
static const uptr kLoAppMemBeg = 0x000000001000ull;
static const uptr kLoAppMemEnd = 0x010000000000ull;
static const uptr kHiAppMemBeg = 0x7e8000000000ull;
static const uptr kHiAppMemEnd = 0x800000000000ull; // 47 bits
static const uptr kAppMemMsk = 0x7c0000000000ull;
static const uptr kAppMemXor = 0x020000000000ull;
static const uptr kVdsoBeg = 0x7800000000000000ull;
};
// Indicates the runtime will define the memory regions at runtime.
#define TSAN_RUNTIME_VMA 1
#endif
#elif SANITIZER_GO && !SANITIZER_WINDOWS
/* Go on linux, darwin and freebsd
0000 0000 1000 - 0000 1000 0000: executable
0000 1000 0000 - 00c0 0000 0000: -
00c0 0000 0000 - 00e0 0000 0000: heap
00e0 0000 0000 - 2000 0000 0000: -
2000 0000 0000 - 2380 0000 0000: shadow
2380 0000 0000 - 3000 0000 0000: -
3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
4000 0000 0000 - 6000 0000 0000: -
6000 0000 0000 - 6200 0000 0000: traces
6200 0000 0000 - 8000 0000 0000: -
*/
struct Mapping {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x400000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
static const uptr kTraceMemEnd = 0x620000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x238000000000ull;
static const uptr kAppMemBeg = 0x000000001000ull;
static const uptr kAppMemEnd = 0x00e000000000ull;
};
#elif SANITIZER_GO && SANITIZER_WINDOWS
/* Go on windows
0000 0000 1000 - 0000 1000 0000: executable
0000 1000 0000 - 00f8 0000 0000: -
00c0 0000 0000 - 00e0 0000 0000: heap
00e0 0000 0000 - 0100 0000 0000: -
0100 0000 0000 - 0500 0000 0000: shadow
0500 0000 0000 - 0560 0000 0000: -
0560 0000 0000 - 0760 0000 0000: traces
0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
07d0 0000 0000 - 8000 0000 0000: -
*/
struct Mapping {
static const uptr kMetaShadowBeg = 0x076000000000ull;
static const uptr kMetaShadowEnd = 0x07d000000000ull;
static const uptr kTraceMemBeg = 0x056000000000ull;
static const uptr kTraceMemEnd = 0x076000000000ull;
static const uptr kShadowBeg = 0x010000000000ull;
static const uptr kShadowEnd = 0x050000000000ull;
static const uptr kAppMemBeg = 0x000000001000ull;
static const uptr kAppMemEnd = 0x00e000000000ull;
};
#else
# error "Unknown platform"
#endif
#ifdef TSAN_RUNTIME_VMA
extern uptr vmaSize;
#endif
enum MappingType {
MAPPING_LO_APP_BEG,
MAPPING_LO_APP_END,
MAPPING_HI_APP_BEG,
MAPPING_HI_APP_END,
#ifdef TSAN_MID_APP_RANGE
MAPPING_MID_APP_BEG,
MAPPING_MID_APP_END,
#endif
MAPPING_HEAP_BEG,
MAPPING_HEAP_END,
MAPPING_APP_BEG,
MAPPING_APP_END,
MAPPING_SHADOW_BEG,
MAPPING_SHADOW_END,
MAPPING_META_SHADOW_BEG,
MAPPING_META_SHADOW_END,
MAPPING_TRACE_BEG,
MAPPING_TRACE_END,
MAPPING_VDSO_BEG,
};
template<typename Mapping, int Type>
uptr MappingImpl(void) {
switch (Type) {
#if !SANITIZER_GO
case MAPPING_LO_APP_BEG: return Mapping::kLoAppMemBeg;
case MAPPING_LO_APP_END: return Mapping::kLoAppMemEnd;
# ifdef TSAN_MID_APP_RANGE
case MAPPING_MID_APP_BEG: return Mapping::kMidAppMemBeg;
case MAPPING_MID_APP_END: return Mapping::kMidAppMemEnd;
# endif
case MAPPING_HI_APP_BEG: return Mapping::kHiAppMemBeg;
case MAPPING_HI_APP_END: return Mapping::kHiAppMemEnd;
case MAPPING_HEAP_BEG: return Mapping::kHeapMemBeg;
case MAPPING_HEAP_END: return Mapping::kHeapMemEnd;
case MAPPING_VDSO_BEG: return Mapping::kVdsoBeg;
#else
case MAPPING_APP_BEG: return Mapping::kAppMemBeg;
case MAPPING_APP_END: return Mapping::kAppMemEnd;
#endif
case MAPPING_SHADOW_BEG: return Mapping::kShadowBeg;
case MAPPING_SHADOW_END: return Mapping::kShadowEnd;
case MAPPING_META_SHADOW_BEG: return Mapping::kMetaShadowBeg;
case MAPPING_META_SHADOW_END: return Mapping::kMetaShadowEnd;
case MAPPING_TRACE_BEG: return Mapping::kTraceMemBeg;
case MAPPING_TRACE_END: return Mapping::kTraceMemEnd;
}
}
template<int Type>
uptr MappingArchImpl(void) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return MappingImpl<Mapping39, Type>();
case 42: return MappingImpl<Mapping42, Type>();
case 48: return MappingImpl<Mapping48, Type>();
}
DCHECK(0);
return 0;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return MappingImpl<Mapping44, Type>();
case 46: return MappingImpl<Mapping46, Type>();
case 47: return MappingImpl<Mapping47, Type>();
}
DCHECK(0);
return 0;
#else
return MappingImpl<Mapping, Type>();
#endif
}
#if !SANITIZER_GO
ALWAYS_INLINE
uptr LoAppMemBeg(void) {
return MappingArchImpl<MAPPING_LO_APP_BEG>();
}
ALWAYS_INLINE
uptr LoAppMemEnd(void) {
return MappingArchImpl<MAPPING_LO_APP_END>();
}
#ifdef TSAN_MID_APP_RANGE
ALWAYS_INLINE
uptr MidAppMemBeg(void) {
return MappingArchImpl<MAPPING_MID_APP_BEG>();
}
ALWAYS_INLINE
uptr MidAppMemEnd(void) {
return MappingArchImpl<MAPPING_MID_APP_END>();
}
#endif
ALWAYS_INLINE
uptr HeapMemBeg(void) {
return MappingArchImpl<MAPPING_HEAP_BEG>();
}
ALWAYS_INLINE
uptr HeapMemEnd(void) {
return MappingArchImpl<MAPPING_HEAP_END>();
}
ALWAYS_INLINE
uptr HiAppMemBeg(void) {
return MappingArchImpl<MAPPING_HI_APP_BEG>();
}
ALWAYS_INLINE
uptr HiAppMemEnd(void) {
return MappingArchImpl<MAPPING_HI_APP_END>();
}
ALWAYS_INLINE
uptr VdsoBeg(void) {
return MappingArchImpl<MAPPING_VDSO_BEG>();
}
#else
ALWAYS_INLINE
uptr AppMemBeg(void) {
return MappingArchImpl<MAPPING_APP_BEG>();
}
ALWAYS_INLINE
uptr AppMemEnd(void) {
return MappingArchImpl<MAPPING_APP_END>();
}
#endif
static inline
bool GetUserRegion(int i, uptr *start, uptr *end) {
switch (i) {
default:
return false;
#if !SANITIZER_GO
case 0:
*start = LoAppMemBeg();
*end = LoAppMemEnd();
return true;
case 1:
*start = HiAppMemBeg();
*end = HiAppMemEnd();
return true;
case 2:
*start = HeapMemBeg();
*end = HeapMemEnd();
return true;
# ifdef TSAN_MID_APP_RANGE
case 3:
*start = MidAppMemBeg();
*end = MidAppMemEnd();
return true;
# endif
#else
case 0:
*start = AppMemBeg();
*end = AppMemEnd();
return true;
#endif
}
}
ALWAYS_INLINE
uptr ShadowBeg(void) {
return MappingArchImpl<MAPPING_SHADOW_BEG>();
}
ALWAYS_INLINE
uptr ShadowEnd(void) {
return MappingArchImpl<MAPPING_SHADOW_END>();
}
ALWAYS_INLINE
uptr MetaShadowBeg(void) {
return MappingArchImpl<MAPPING_META_SHADOW_BEG>();
}
ALWAYS_INLINE
uptr MetaShadowEnd(void) {
return MappingArchImpl<MAPPING_META_SHADOW_END>();
}
ALWAYS_INLINE
uptr TraceMemBeg(void) {
return MappingArchImpl<MAPPING_TRACE_BEG>();
}
ALWAYS_INLINE
uptr TraceMemEnd(void) {
return MappingArchImpl<MAPPING_TRACE_END>();
}
template<typename Mapping>
bool IsAppMemImpl(uptr mem) {
#if !SANITIZER_GO
return (mem >= Mapping::kHeapMemBeg && mem < Mapping::kHeapMemEnd) ||
# ifdef TSAN_MID_APP_RANGE
(mem >= Mapping::kMidAppMemBeg && mem < Mapping::kMidAppMemEnd) ||
# endif
(mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) ||
(mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd);
#else
return mem >= Mapping::kAppMemBeg && mem < Mapping::kAppMemEnd;
#endif
}
ALWAYS_INLINE
bool IsAppMem(uptr mem) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return IsAppMemImpl<Mapping39>(mem);
case 42: return IsAppMemImpl<Mapping42>(mem);
case 48: return IsAppMemImpl<Mapping48>(mem);
}
DCHECK(0);
return false;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return IsAppMemImpl<Mapping44>(mem);
case 46: return IsAppMemImpl<Mapping46>(mem);
case 47: return IsAppMemImpl<Mapping47>(mem);
}
DCHECK(0);
return false;
#else
return IsAppMemImpl<Mapping>(mem);
#endif
}
template<typename Mapping>
bool IsShadowMemImpl(uptr mem) {
return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
}
ALWAYS_INLINE
bool IsShadowMem(uptr mem) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return IsShadowMemImpl<Mapping39>(mem);
case 42: return IsShadowMemImpl<Mapping42>(mem);
case 48: return IsShadowMemImpl<Mapping48>(mem);
}
DCHECK(0);
return false;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return IsShadowMemImpl<Mapping44>(mem);
case 46: return IsShadowMemImpl<Mapping46>(mem);
case 47: return IsShadowMemImpl<Mapping47>(mem);
}
DCHECK(0);
return false;
#else
return IsShadowMemImpl<Mapping>(mem);
#endif
}
template<typename Mapping>
bool IsMetaMemImpl(uptr mem) {
return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
}
ALWAYS_INLINE
bool IsMetaMem(uptr mem) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return IsMetaMemImpl<Mapping39>(mem);
case 42: return IsMetaMemImpl<Mapping42>(mem);
case 48: return IsMetaMemImpl<Mapping48>(mem);
}
DCHECK(0);
return false;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return IsMetaMemImpl<Mapping44>(mem);
case 46: return IsMetaMemImpl<Mapping46>(mem);
case 47: return IsMetaMemImpl<Mapping47>(mem);
}
DCHECK(0);
return false;
#else
return IsMetaMemImpl<Mapping>(mem);
#endif
}
template<typename Mapping>
uptr MemToShadowImpl(uptr x) {
DCHECK(IsAppMem(x));
#if !SANITIZER_GO
return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1)))
^ Mapping::kAppMemXor) * kShadowCnt;
#else
# ifndef SANITIZER_WINDOWS
return ((x & ~(kShadowCell - 1)) * kShadowCnt) | Mapping::kShadowBeg;
# else
return ((x & ~(kShadowCell - 1)) * kShadowCnt) + Mapping::kShadowBeg;
# endif
#endif
}
ALWAYS_INLINE
uptr MemToShadow(uptr x) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return MemToShadowImpl<Mapping39>(x);
case 42: return MemToShadowImpl<Mapping42>(x);
case 48: return MemToShadowImpl<Mapping48>(x);
}
DCHECK(0);
return 0;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return MemToShadowImpl<Mapping44>(x);
case 46: return MemToShadowImpl<Mapping46>(x);
case 47: return MemToShadowImpl<Mapping47>(x);
}
DCHECK(0);
return 0;
#else
return MemToShadowImpl<Mapping>(x);
#endif
}
template<typename Mapping>
u32 *MemToMetaImpl(uptr x) {
DCHECK(IsAppMem(x));
#if !SANITIZER_GO
return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) /
kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
#else
# ifndef SANITIZER_WINDOWS
return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
# else
return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
kMetaShadowCell * kMetaShadowSize) + Mapping::kMetaShadowBeg);
# endif
#endif
}
ALWAYS_INLINE
u32 *MemToMeta(uptr x) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return MemToMetaImpl<Mapping39>(x);
case 42: return MemToMetaImpl<Mapping42>(x);
case 48: return MemToMetaImpl<Mapping48>(x);
}
DCHECK(0);
return 0;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return MemToMetaImpl<Mapping44>(x);
case 46: return MemToMetaImpl<Mapping46>(x);
case 47: return MemToMetaImpl<Mapping47>(x);
}
DCHECK(0);
return 0;
#else
return MemToMetaImpl<Mapping>(x);
#endif
}
template<typename Mapping>
uptr ShadowToMemImpl(uptr s) {
DCHECK(IsShadowMem(s));
#if !SANITIZER_GO
// The shadow mapping is non-linear and we've lost some bits, so we don't have
// an easy way to restore the original app address. But the mapping is a
// bijection, so we try to restore the address as belonging to low/mid/high
// range consecutively and see if shadow->app->shadow mapping gives us the
// same address.
uptr p = (s / kShadowCnt) ^ Mapping::kAppMemXor;
if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
MemToShadow(p) == s)
return p;
# ifdef TSAN_MID_APP_RANGE
p = ((s / kShadowCnt) ^ Mapping::kAppMemXor) +
(Mapping::kMidAppMemBeg & Mapping::kAppMemMsk);
if (p >= Mapping::kMidAppMemBeg && p < Mapping::kMidAppMemEnd &&
MemToShadow(p) == s)
return p;
# endif
return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk;
#else // #if !SANITIZER_GO
# ifndef SANITIZER_WINDOWS
return (s & ~Mapping::kShadowBeg) / kShadowCnt;
# else
return (s - Mapping::kShadowBeg) / kShadowCnt;
# endif // SANITIZER_WINDOWS
#endif
}
ALWAYS_INLINE
uptr ShadowToMem(uptr s) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return ShadowToMemImpl<Mapping39>(s);
case 42: return ShadowToMemImpl<Mapping42>(s);
case 48: return ShadowToMemImpl<Mapping48>(s);
}
DCHECK(0);
return 0;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return ShadowToMemImpl<Mapping44>(s);
case 46: return ShadowToMemImpl<Mapping46>(s);
case 47: return ShadowToMemImpl<Mapping47>(s);
}
DCHECK(0);
return 0;
#else
return ShadowToMemImpl<Mapping>(s);
#endif
}
// The additional page is to catch shadow stack overflow as paging fault.
// Windows wants 64K alignment for mmaps.
const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
+ (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
template<typename Mapping>
uptr GetThreadTraceImpl(int tid) {
uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize;
DCHECK_LT(p, Mapping::kTraceMemEnd);
return p;
}
ALWAYS_INLINE
uptr GetThreadTrace(int tid) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return GetThreadTraceImpl<Mapping39>(tid);
case 42: return GetThreadTraceImpl<Mapping42>(tid);
case 48: return GetThreadTraceImpl<Mapping48>(tid);
}
DCHECK(0);
return 0;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return GetThreadTraceImpl<Mapping44>(tid);
case 46: return GetThreadTraceImpl<Mapping46>(tid);
case 47: return GetThreadTraceImpl<Mapping47>(tid);
}
DCHECK(0);
return 0;
#else
return GetThreadTraceImpl<Mapping>(tid);
#endif
}
template<typename Mapping>
uptr GetThreadTraceHeaderImpl(int tid) {
uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize
+ kTraceSize * sizeof(Event);
DCHECK_LT(p, Mapping::kTraceMemEnd);
return p;
}
ALWAYS_INLINE
uptr GetThreadTraceHeader(int tid) {
#if defined(__aarch64__) && !defined(__APPLE__)
switch (vmaSize) {
case 39: return GetThreadTraceHeaderImpl<Mapping39>(tid);
case 42: return GetThreadTraceHeaderImpl<Mapping42>(tid);
case 48: return GetThreadTraceHeaderImpl<Mapping48>(tid);
}
DCHECK(0);
return 0;
#elif defined(__powerpc64__)
switch (vmaSize) {
case 44: return GetThreadTraceHeaderImpl<Mapping44>(tid);
case 46: return GetThreadTraceHeaderImpl<Mapping46>(tid);
case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid);
}
DCHECK(0);
return 0;
#else
return GetThreadTraceHeaderImpl<Mapping>(tid);
#endif
}
void InitializePlatform();
void InitializePlatformEarly();
void CheckAndProtect();
void InitializeShadowMemoryPlatform();
void FlushShadowMemory();
void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
int ExtractResolvFDs(void *state, int *fds, int nfd);
int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size);
int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
void *abstime), void *c, void *m, void *abstime,
void(*cleanup)(void *arg), void *arg);
void DestroyThreadState();
} // namespace __tsan
#endif // TSAN_PLATFORM_H