Skip to content

Commit 98b8be2

Browse files
committed
[TSan] Add support for Android
1 parent 1d131ff commit 98b8be2

File tree

3 files changed

+53
-13
lines changed

3 files changed

+53
-13
lines changed

compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,11 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {
24122412
}
24132413
#endif
24142414

2415-
#if SANITIZER_LINUX
2415+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
2416+
// Bionic's pthread_create internally calls clone. When the CLONE_THREAD flag is
2417+
// set, clone does not create a new process but a new thread. This is a
2418+
// workaround for Android. Disabling the interception of clone solves the
2419+
// problem in most scenarios.
24162420
TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
24172421
void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
24182422
SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
@@ -3135,7 +3139,7 @@ void InitializeInterceptors() {
31353139

31363140
TSAN_INTERCEPT(fork);
31373141
TSAN_INTERCEPT(vfork);
3138-
#if SANITIZER_LINUX
3142+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
31393143
TSAN_INTERCEPT(clone);
31403144
#endif
31413145
#if !SANITIZER_ANDROID

compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
486486

487487
// Reverse operation of libc stack pointer mangling
488488
static uptr UnmangleLongJmpSp(uptr mangled_sp) {
489-
#if defined(__x86_64__)
490-
# if SANITIZER_LINUX
489+
# if SANITIZER_ANDROID
490+
if (longjmp_xor_key == 0) {
491+
// bionic libc initialization process: __libc_init_globals ->
492+
// __libc_init_vdso (calls strcmp) -> __libc_init_setjmp_cookie. strcmp is
493+
// intercepted by TSan, so during TSan initialization the setjmp_cookie
494+
// remains uninitialized. On Android, longjmp_xor_key must be set on first
495+
// use.
496+
InitializeLongjmpXorKey();
497+
CHECK_NE(longjmp_xor_key, 0);
498+
}
499+
# endif
500+
501+
# if defined(__x86_64__)
502+
# if SANITIZER_LINUX
491503
// Reverse of:
492504
// xor %fs:0x30, %rsi
493505
// rol $0x11, %rsi
@@ -542,21 +554,31 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
542554
# else
543555
# define LONG_JMP_SP_ENV_SLOT 2
544556
# endif
545-
#elif SANITIZER_LINUX
546-
# ifdef __aarch64__
547-
# define LONG_JMP_SP_ENV_SLOT 13
548-
# elif defined(__loongarch__)
549-
# define LONG_JMP_SP_ENV_SLOT 1
550-
# elif defined(__mips64)
551-
# define LONG_JMP_SP_ENV_SLOT 1
557+
# elif SANITIZER_LINUX && !SANITIZER_ANDROID
558+
# ifdef __aarch64__
559+
# define LONG_JMP_SP_ENV_SLOT 13
560+
# elif defined(__loongarch__)
561+
# define LONG_JMP_SP_ENV_SLOT 1
562+
# elif defined(__mips64)
563+
# define LONG_JMP_SP_ENV_SLOT 1
552564
# elif SANITIZER_RISCV64
553565
# define LONG_JMP_SP_ENV_SLOT 13
554566
# elif defined(__s390x__)
555567
# define LONG_JMP_SP_ENV_SLOT 9
556568
# else
557569
# define LONG_JMP_SP_ENV_SLOT 6
558570
# endif
559-
#endif
571+
# elif SANITIZER_ANDROID
572+
# ifdef __aarch64__
573+
# define LONG_JMP_SP_ENV_SLOT 3
574+
# elif SANITIZER_RISCV64
575+
# define LONG_JMP_SP_ENV_SLOT 3
576+
# elif defined(__x86_64__)
577+
# define LONG_JMP_SP_ENV_SLOT 6
578+
# else
579+
# error unsupported
580+
# endif
581+
# endif
560582

561583
uptr ExtractLongJmpSp(uptr *env) {
562584
uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
@@ -653,6 +675,16 @@ ThreadState *cur_thread() {
653675
}
654676
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
655677
}
678+
679+
// https://android.googlesource.com/platform/external/skia/+/refs/tags/android-15.0.0_r36/src/ports/SkMemory_malloc.cpp#105
680+
// https://android.googlesource.com/platform/external/scudo/+/refs/tags/android-15.0.0_r36/standalone/tsd_shared.h#198
681+
// Workaround to get the correct ThreadState pointer. Scudo allocator uses the
682+
// last bit of TLS_SLOT_SANITIZER as a flag of disable memory initialization.
683+
// getPlatformAllocatorTlsSlot should not use TLS_SLOT_SANITIZER slot.
684+
uptr addr = reinterpret_cast<uptr>(thr);
685+
if (addr % 2 != 0) {
686+
return reinterpret_cast<ThreadState*>(addr & ~1ULL);
687+
}
656688
return thr;
657689
}
658690

compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,14 @@ void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
206206
}
207207
#endif
208208

209-
#if !SANITIZER_GO
209+
#if !SANITIZER_GO && !SANITIZER_ANDROID
210210
// Don't imitate stack/TLS writes for the main thread,
211211
// because its initialization is synchronized with all
212212
// subsequent threads anyway.
213+
// Because thr is created by MmapOrDie, the thr object
214+
// is not in tls, the pointer of thr object is in
215+
// TLS_SLOT_SANITIZER slot. So skip this check on
216+
// Android platform.
213217
if (tid != kMainTid) {
214218
if (stk_addr && stk_size) {
215219
const uptr pc = StackTrace::GetNextInstructionPc(

0 commit comments

Comments
 (0)