Skip to content

Commit a46d5a7

Browse files
author
Mohit K. Bhakkad
committedFeb 20, 2015
[TSan][MIPS] Adding support for MIPS64
Patch by Sagar Thakur Reviewers: dvyukov, samsonov, petarj, kcc, dsanders. Subscribers: mohit.bhakkad, Anand.Takale, llvm-commits. Differential Revision: http://reviews.llvm.org/D6291 llvm-svn: 229972
1 parent 97ea762 commit a46d5a7

9 files changed

+159
-59
lines changed
 

‎compiler-rt/cmake/config-ix.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
207207
filter_available_targets(MSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
208208
filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64
209209
mipsel mips64el aarch64 powerpc64 powerpc64le)
210-
filter_available_targets(TSAN_SUPPORTED_ARCH x86_64)
210+
filter_available_targets(TSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
211211
filter_available_targets(UBSAN_SUPPORTED_ARCH x86_64 i386 i686 arm aarch64 mips mipsel mips64 mips64el)
212212

213213
if(ANDROID)

‎compiler-rt/lib/tsan/CMakeLists.txt

+30-25
Original file line numberDiff line numberDiff line change
@@ -79,35 +79,40 @@ set(TSAN_HEADERS
7979
set(TSAN_RUNTIME_LIBRARIES)
8080
add_custom_target(tsan)
8181
# TSan is currently supported on 64-bit Linux only.
82-
if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE)
83-
set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S)
84-
# Pass ASM file directly to the C++ compiler.
85-
set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES
86-
LANGUAGE C)
87-
set(arch "x86_64")
88-
add_compiler_rt_runtime(clang_rt.tsan-${arch} ${arch} STATIC
89-
SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES}
90-
$<TARGET_OBJECTS:RTInterception.${arch}>
91-
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
92-
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
93-
CFLAGS ${TSAN_RTL_CFLAGS}
94-
DEFS ${TSAN_COMMON_DEFINITIONS})
95-
list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch})
96-
add_sanitizer_rt_symbols(clang_rt.tsan-${arch} rtl/tsan.syms.extra)
97-
add_dependencies(tsan clang_rt.tsan-${arch}
98-
clang_rt.tsan-${arch}-symbols)
82+
if(UNIX AND NOT APPLE)
83+
foreach(arch ${TSAN_SUPPORTED_ARCH})
84+
if(arch STREQUAL "x86_64")
85+
set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S)
86+
# Pass ASM file directly to the C++ compiler.
87+
set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES
88+
LANGUAGE C)
89+
# Sanity check for Go runtime.
90+
set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh)
91+
add_custom_target(GotsanRuntimeCheck
92+
COMMAND CC=${CMAKE_C_COMPILER} IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT}
93+
DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT}
94+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go
95+
COMMENT "Checking TSan Go runtime..."
96+
VERBATIM)
97+
else()
98+
set(TSAN_ASM_SOURCES)
99+
endif()
100+
add_compiler_rt_runtime(clang_rt.tsan-${arch} ${arch} STATIC
101+
SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES}
102+
$<TARGET_OBJECTS:RTInterception.${arch}>
103+
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
104+
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
105+
CFLAGS ${TSAN_RTL_CFLAGS}
106+
DEFS ${TSAN_COMMON_DEFINITIONS})
107+
list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch})
108+
add_sanitizer_rt_symbols(clang_rt.tsan-${arch} rtl/tsan.syms.extra)
109+
add_dependencies(tsan clang_rt.tsan-${arch}
110+
clang_rt.tsan-${arch}-symbols)
111+
endforeach()
99112
endif()
100113

101114
add_dependencies(compiler-rt tsan)
102115

103-
# Sanity check for Go runtime.
104-
set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh)
105-
add_custom_target(GotsanRuntimeCheck
106-
COMMAND CC=${CMAKE_C_COMPILER} IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT}
107-
DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT}
108-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go
109-
COMMENT "Checking TSan Go runtime..."
110-
VERBATIM)
111116

112117
# Build libcxx instrumented with TSan.
113118
if(TSAN_SUPPORTED_ARCH AND

‎compiler-rt/lib/tsan/rtl/tsan_interceptors.cc

+25
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,27 @@ using namespace __tsan; // NOLINT
3939
#define stderr __stderrp
4040
#endif
4141

42+
#ifdef __mips__
43+
const int kSigCount = 129;
44+
#else
4245
const int kSigCount = 65;
46+
#endif
4347

4448
struct my_siginfo_t {
4549
// The size is determined by looking at sizeof of real siginfo_t on linux.
4650
u64 opaque[128 / sizeof(u64)];
4751
};
4852

53+
#ifdef __mips__
54+
struct ucontext_t {
55+
u64 opaque[768 / sizeof(u64) + 1];
56+
};
57+
#else
4958
struct ucontext_t {
5059
// The size is determined by looking at sizeof of real ucontext_t on linux.
5160
u64 opaque[936 / sizeof(u64) + 1];
5261
};
62+
#endif
5363

5464
extern "C" int pthread_attr_init(void *attr);
5565
extern "C" int pthread_attr_destroy(void *attr);
@@ -89,8 +99,13 @@ const int SIGFPE = 8;
8999
const int SIGSEGV = 11;
90100
const int SIGPIPE = 13;
91101
const int SIGTERM = 15;
102+
#ifdef __mips__
103+
const int SIGBUS = 10;
104+
const int SIGSYS = 12;
105+
#else
92106
const int SIGBUS = 7;
93107
const int SIGSYS = 31;
108+
#endif
94109
void *const MAP_FAILED = (void*)-1;
95110
const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
96111
const int MAP_FIXED = 0x10;
@@ -108,6 +123,9 @@ typedef void (*sighandler_t)(int sig);
108123
typedef void (*sigactionhandler_t)(int sig, my_siginfo_t *siginfo, void *uctx);
109124

110125
struct sigaction_t {
126+
#ifdef __mips__
127+
u32 sa_flags;
128+
#endif
111129
union {
112130
sighandler_t sa_handler;
113131
sigactionhandler_t sa_sigaction;
@@ -117,16 +135,23 @@ struct sigaction_t {
117135
__sanitizer_sigset_t sa_mask;
118136
#else
119137
__sanitizer_sigset_t sa_mask;
138+
#ifndef __mips__
120139
int sa_flags;
140+
#endif
121141
void (*sa_restorer)();
122142
#endif
123143
};
124144

125145
const sighandler_t SIG_DFL = (sighandler_t)0;
126146
const sighandler_t SIG_IGN = (sighandler_t)1;
127147
const sighandler_t SIG_ERR = (sighandler_t)-1;
148+
#ifdef __mips__
149+
const int SA_SIGINFO = 8;
150+
const int SIG_SETMASK = 3;
151+
#else
128152
const int SA_SIGINFO = 4;
129153
const int SIG_SETMASK = 2;
154+
#endif
130155

131156
namespace std {
132157
struct nothrow_t {};

‎compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cc

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ typedef unsigned short a16; // NOLINT
3333
typedef unsigned int a32;
3434
typedef unsigned long long a64; // NOLINT
3535
#if !defined(SANITIZER_GO) && (defined(__SIZEOF_INT128__) \
36-
|| (__clang_major__ * 100 + __clang_minor__ >= 302))
36+
|| (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64)
3737
__extension__ typedef __int128 a128;
3838
# define __TSAN_HAS_INT128 1
3939
#else
4040
# define __TSAN_HAS_INT128 0
4141
#endif
4242

43-
#ifndef SANITIZER_GO
43+
#if !defined(SANITIZER_GO) && __TSAN_HAS_INT128
4444
// Protects emulation of 128-bit atomic operations.
4545
static StaticSpinMutex mutex128;
4646
#endif
@@ -125,7 +125,8 @@ template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
125125
// Atomic ops are executed under tsan internal mutex,
126126
// here we assume that the atomic variables are not accessed
127127
// from non-instrumented code.
128-
#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !defined(SANITIZER_GO)
128+
#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !defined(SANITIZER_GO) \
129+
&& __TSAN_HAS_INT128
129130
a128 func_xchg(volatile a128 *v, a128 op) {
130131
SpinMutexLock lock(&mutex128);
131132
a128 cmp = *v;

‎compiler-rt/lib/tsan/rtl/tsan_platform.h

+34-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ namespace __tsan {
2626

2727
#if !defined(SANITIZER_GO)
2828

29+
#if defined(__x86_64__)
2930
/*
30-
C/C++ on linux and freebsd
31+
C/C++ on linux/x86_64 and freebsd/x86_64
3132
0000 0000 1000 - 0100 0000 0000: main binary and/or MAP_32BIT mappings
3233
0100 0000 0000 - 0200 0000 0000: -
3334
0200 0000 0000 - 1000 0000 0000: shadow
@@ -40,7 +41,6 @@ C/C++ on linux and freebsd
4041
7e00 0000 0000 - 7e80 0000 0000: -
4142
7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
4243
*/
43-
4444
const uptr kMetaShadowBeg = 0x300000000000ull;
4545
const uptr kMetaShadowEnd = 0x400000000000ull;
4646
const uptr kTraceMemBeg = 0x600000000000ull;
@@ -55,6 +55,38 @@ const uptr kHiAppMemBeg = 0x7e8000000000ull;
5555
const uptr kHiAppMemEnd = 0x800000000000ull;
5656
const uptr kAppMemMsk = 0x7c0000000000ull;
5757
const uptr kAppMemXor = 0x020000000000ull;
58+
const uptr kVdsoBeg = 0xf000000000000000ull;
59+
#elif defined(__mips64)
60+
/*
61+
C/C++ on linux/mips64
62+
0100 0000 00 - 0200 0000 00: main binary
63+
0200 0000 00 - 1400 0000 00: -
64+
1400 0000 00 - 2400 0000 00: shadow
65+
2400 0000 00 - 3000 0000 00: -
66+
3000 0000 00 - 4000 0000 00: metainfo (memory blocks and sync objects)
67+
4000 0000 00 - 6000 0000 00: -
68+
6000 0000 00 - 6200 0000 00: traces
69+
6200 0000 00 - fe00 0000 00: -
70+
fe00 0000 00 - ff00 0000 00: heap
71+
ff00 0000 00 - ff80 0000 00: -
72+
ff80 0000 00 - ffff ffff ff: modules and main thread stack
73+
*/
74+
const uptr kMetaShadowBeg = 0x3000000000ull;
75+
const uptr kMetaShadowEnd = 0x4000000000ull;
76+
const uptr kTraceMemBeg = 0x6000000000ull;
77+
const uptr kTraceMemEnd = 0x6200000000ull;
78+
const uptr kShadowBeg = 0x1400000000ull;
79+
const uptr kShadowEnd = 0x2400000000ull;
80+
const uptr kHeapMemBeg = 0xfe00000000ull;
81+
const uptr kHeapMemEnd = 0xff00000000ull;
82+
const uptr kLoAppMemBeg = 0x0100000000ull;
83+
const uptr kLoAppMemEnd = 0x0200000000ull;
84+
const uptr kHiAppMemBeg = 0xff80000000ull;
85+
const uptr kHiAppMemEnd = 0xffffffffffull;
86+
const uptr kAppMemMsk = 0xfc00000000ull;
87+
const uptr kAppMemXor = 0x0400000000ull;
88+
const uptr kVdsoBeg = 0xfffff00000ull;
89+
#endif
5890

5991
ALWAYS_INLINE
6092
bool IsAppMem(uptr mem) {

‎compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc

+13-8
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ namespace __tsan {
6666
static uptr g_data_start;
6767
static uptr g_data_end;
6868

69-
const uptr kPageSize = 4096;
70-
7169
enum {
7270
MemTotal = 0,
7371
MemShadow = 1,
@@ -173,7 +171,7 @@ static void MapRodata() {
173171
*p = kShadowRodata;
174172
internal_write(fd, marker.data(), marker.size());
175173
// Map the file into memory.
176-
uptr page = internal_mmap(0, kPageSize, PROT_READ | PROT_WRITE,
174+
uptr page = internal_mmap(0, GetPageSizeCached(), PROT_READ | PROT_WRITE,
177175
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
178176
if (internal_iserror(page)) {
179177
internal_close(fd);
@@ -216,8 +214,15 @@ void InitializeShadowMemory() {
216214
// a program uses a small part of large mmap. On some programs
217215
// we see 20% memory usage reduction without huge pages for this range.
218216
// FIXME: don't use constants here.
219-
NoHugePagesInRegion(MemToShadow(0x7f0000000000ULL),
220-
0x10000000000ULL * kShadowMultiplier);
217+
#if defined(__x86_64__)
218+
const uptr kMadviseRangeBeg = 0x7f0000000000ull;
219+
const uptr kMadviseRangeSize = 0x010000000000ull;
220+
#elif defined(__mips64)
221+
const uptr kMadviseRangeBeg = 0xff00000000ull;
222+
const uptr kMadviseRangeSize = 0x0100000000ull;
223+
#endif
224+
NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg),
225+
kMadviseRangeSize * kShadowMultiplier);
221226
if (common_flags()->use_madv_dontdump)
222227
DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg);
223228
DPrintf("memory shadow: %zx-%zx (%zuGB)\n",
@@ -289,9 +294,9 @@ static void CheckAndProtect() {
289294
if (IsAppMem(p))
290295
continue;
291296
if (p >= kHeapMemEnd &&
292-
p < kHeapMemEnd + PrimaryAllocator::AdditionalSize())
297+
p < HeapEnd())
293298
continue;
294-
if (p >= 0xf000000000000000ull) // vdso
299+
if (p >= kVdsoBeg) // vdso
295300
break;
296301
Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end);
297302
Die();
@@ -304,7 +309,7 @@ static void CheckAndProtect() {
304309
// Protect the whole range for now, so that user does not map something here.
305310
ProtectRange(kTraceMemBeg, kTraceMemEnd);
306311
ProtectRange(kTraceMemEnd, kHeapMemBeg);
307-
ProtectRange(kHeapMemEnd + PrimaryAllocator::AdditionalSize(), kHiAppMemBeg);
312+
ProtectRange(HeapEnd(), kHiAppMemBeg);
308313
}
309314
#endif // #ifndef SANITIZER_GO
310315

‎compiler-rt/lib/tsan/rtl/tsan_rtl.cc

+8-1
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,14 @@ static void StartBackgroundThread() {
217217
ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
218218
}
219219

220+
#ifndef __mips__
220221
static void StopBackgroundThread() {
221222
atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
222223
internal_join_thread(ctx->background_thread);
223224
ctx->background_thread = 0;
224225
}
225226
#endif
227+
#endif
226228

227229
void DontNeedShadowFor(uptr addr, uptr size) {
228230
uptr shadow_beg = MemToShadow(addr);
@@ -330,8 +332,13 @@ void Initialize(ThreadState *thr) {
330332
#ifndef SANITIZER_GO
331333
InitializeLibIgnore();
332334
Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
335+
// On MIPS, TSan initialization is run before
336+
// __pthread_initialize_minimal_internal() is finished, so we can not spawn
337+
// new threads.
338+
#ifndef __mips__
333339
StartBackgroundThread();
334340
SetSandboxingCallback(StopBackgroundThread);
341+
#endif
335342
#endif
336343
if (common_flags()->detect_deadlocks)
337344
ctx->dd = DDetector::Create(flags());
@@ -832,7 +839,7 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
832839
}
833840
} else {
834841
// The region is big, reset only beginning and end.
835-
const uptr kPageSize = 4096;
842+
const uptr kPageSize = GetPageSizeCached();
836843
u64 *begin = (u64*)MemToShadow(addr);
837844
u64 *end = begin + size / kShadowCell * kShadowCnt;
838845
u64 *p = begin;

‎compiler-rt/lib/tsan/rtl/tsan_rtl.h

+23
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,21 @@ namespace __tsan {
5454

5555
#ifndef SANITIZER_GO
5656
struct MapUnmapCallback;
57+
#ifdef __mips64
58+
static const uptr kAllocatorSpace = 0;
59+
static const uptr kAllocatorSize = SANITIZER_MMAP_RANGE_SIZE;
60+
static const uptr kAllocatorRegionSizeLog = 20;
61+
static const uptr kAllocatorNumRegions =
62+
kAllocatorSize >> kAllocatorRegionSizeLog;
63+
typedef TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12,
64+
MapUnmapCallback> ByteMap;
65+
typedef SizeClassAllocator32<kAllocatorSpace, kAllocatorSize, 0,
66+
CompactSizeClassMap, kAllocatorRegionSizeLog, ByteMap,
67+
MapUnmapCallback> PrimaryAllocator;
68+
#else
5769
typedef SizeClassAllocator64<kHeapMemBeg, kHeapMemEnd - kHeapMemBeg, 0,
5870
DefaultSizeClassMap, MapUnmapCallback> PrimaryAllocator;
71+
#endif
5972
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
6073
typedef LargeMmapAllocator<MapUnmapCallback> SecondaryAllocator;
6174
typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
@@ -738,6 +751,16 @@ void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
738751
*evp = ev;
739752
}
740753

754+
#ifndef SANITIZER_GO
755+
uptr ALWAYS_INLINE HeapEnd() {
756+
#if SANITIZER_CAN_USE_ALLOCATOR64
757+
return kHeapMemEnd + PrimaryAllocator::AdditionalSize();
758+
#else
759+
return kHeapMemEnd;
760+
#endif
761+
}
762+
#endif
763+
741764
} // namespace __tsan
742765

743766
#endif // TSAN_RTL_H

0 commit comments

Comments
 (0)
Please sign in to comment.