Skip to content

Commit ee98204

Browse files
committed
[TSan] Add support for Android
1 parent 773e158 commit ee98204

File tree

5 files changed

+111
-80
lines changed

5 files changed

+111
-80
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,14 @@ INTERCEPTOR(int, puts, char *s) {
12871287
#if SANITIZER_INTERCEPT_PRCTL
12881288
INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
12891289
unsigned long arg4, unsigned long arg5) {
1290+
# if SANITIZER_ANDROID
1291+
static const int PR_PAC_RESET_KEYS = 54;
1292+
// workaround to avoid crash
1293+
if (option == PR_PAC_RESET_KEYS) {
1294+
return REAL(prctl)(option, arg2, arg3, arg4, arg5);
1295+
}
1296+
# endif
1297+
12901298
void *ctx;
12911299
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
12921300
static const int PR_SET_NAME = 15;

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

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

2414-
#if SANITIZER_LINUX
2414+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
24152415
TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
24162416
void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
24172417
SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
@@ -3120,7 +3120,7 @@ void InitializeInterceptors() {
31203120

31213121
TSAN_INTERCEPT(fork);
31223122
TSAN_INTERCEPT(vfork);
3123-
#if SANITIZER_LINUX
3123+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
31243124
TSAN_INTERCEPT(clone);
31253125
#endif
31263126
#if !SANITIZER_ANDROID

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

Lines changed: 96 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,16 @@ extern "C" void *__libc_stack_end;
6666
void *__libc_stack_end = 0;
6767
#endif
6868

69-
#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64)) && \
70-
!SANITIZER_GO
71-
# define INIT_LONGJMP_XOR_KEY 1
72-
#else
73-
# define INIT_LONGJMP_XOR_KEY 0
74-
#endif
69+
# if SANITIZER_LINUX && \
70+
(defined(__aarch64__) || defined(__loongarch_lp64)) && !SANITIZER_GO && \
71+
!SANITIZER_ANDROID
72+
# define INIT_LONGJMP_XOR_KEY 1
73+
# else
74+
# define INIT_LONGJMP_XOR_KEY 0
75+
# endif
7576

76-
#if INIT_LONGJMP_XOR_KEY
77-
#include "interception/interception.h"
77+
# if INIT_LONGJMP_XOR_KEY
78+
# include "interception/interception.h"
7879
// Must be declared outside of other namespaces.
7980
DECLARE_REAL(int, _setjmp, void *env)
8081
#endif
@@ -415,7 +416,7 @@ void InitializePlatform() {
415416
// is not compiled with -pie.
416417
#if !SANITIZER_GO
417418
{
418-
# if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64))
419+
# if INIT_LONGJMP_XOR_KEY
419420
// Initialize the xor key used in {sig}{set,long}jump.
420421
InitializeLongjmpXorKey();
421422
# endif
@@ -484,10 +485,56 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
484485
return res;
485486
}
486487

488+
# if SANITIZER_NETBSD
489+
# ifdef __x86_64__
490+
# define LONG_JMP_SP_ENV_SLOT 6
491+
# else
492+
# error unsupported
493+
# endif
494+
# elif defined(__powerpc__)
495+
# define LONG_JMP_SP_ENV_SLOT 0
496+
# elif SANITIZER_FREEBSD
497+
# ifdef __aarch64__
498+
# define LONG_JMP_SP_ENV_SLOT 1
499+
# else
500+
# define LONG_JMP_SP_ENV_SLOT 2
501+
# endif
502+
# elif SANITIZER_LINUX && !SANITIZER_ANDROID
503+
# ifdef __aarch64__
504+
# define LONG_JMP_SP_ENV_SLOT 13
505+
# elif defined(__loongarch__)
506+
# define LONG_JMP_SP_ENV_SLOT 1
507+
# elif defined(__mips64)
508+
# define LONG_JMP_SP_ENV_SLOT 1
509+
# elif SANITIZER_RISCV64
510+
# define LONG_JMP_SP_ENV_SLOT 13
511+
# elif defined(__s390x__)
512+
# define LONG_JMP_SP_ENV_SLOT 9
513+
# else
514+
# define LONG_JMP_SP_ENV_SLOT 6
515+
# endif
516+
# elif SANITIZER_ANDROID
517+
// https://android.googlesource.com/platform/bionic/+/refs/heads/android16-release/libc/arch-arm64/bionic/setjmp.S
518+
// https://android.googlesource.com/platform/bionic/+/refs/heads/android16-release/libc/arch-x86_64/bionic/setjmp.S
519+
// https://android.googlesource.com/platform/bionic/+/refs/heads/android16-release/libc/arch-riscv64/bionic/setjmp.S
520+
# if defined(__aarch64__) || SANITIZER_RISCV64
521+
# define LONG_JMP_SP_ENV_SLOT 3
522+
# define LONG_JMP_COOKIE_ENV_SLOT 0
523+
# elif defined(__x86_64__)
524+
# define LONG_JMP_SP_ENV_SLOT 6
525+
# define LONG_JMP_COOKIE_ENV_SLOT 8
526+
# else
527+
# error unsupported
528+
# endif
529+
# endif
530+
487531
// Reverse operation of libc stack pointer mangling
488-
static uptr UnmangleLongJmpSp(uptr mangled_sp) {
489-
#if defined(__x86_64__)
490-
# if SANITIZER_LINUX
532+
uptr ExtractLongJmpSp(uptr *env) {
533+
uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
534+
# if SANITIZER_ANDROID
535+
return mangled_sp ^ (env[LONG_JMP_COOKIE_ENV_SLOT] & ~1ULL);
536+
# elif defined(__x86_64__)
537+
# if SANITIZER_LINUX
491538
// Reverse of:
492539
// xor %fs:0x30, %rsi
493540
// rol $0x11, %rsi
@@ -497,25 +544,25 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
497544
: "=r" (sp)
498545
: "0" (mangled_sp));
499546
return sp;
500-
# else
547+
# else
501548
return mangled_sp;
502-
# endif
503-
#elif defined(__aarch64__)
504-
# if SANITIZER_LINUX
549+
# endif
550+
# elif defined(__aarch64__)
551+
# if SANITIZER_LINUX
505552
return mangled_sp ^ longjmp_xor_key;
506-
# else
553+
# else
507554
return mangled_sp;
508-
# endif
509-
#elif defined(__loongarch_lp64)
555+
# endif
556+
# elif defined(__loongarch_lp64)
510557
return mangled_sp ^ longjmp_xor_key;
511-
#elif defined(__powerpc64__)
558+
# elif defined(__powerpc64__)
512559
// Reverse of:
513560
// ld r4, -28696(r13)
514561
// xor r4, r3, r4
515562
uptr xor_key;
516563
asm("ld %0, -28696(%%r13)" : "=r" (xor_key));
517564
return mangled_sp ^ xor_key;
518-
#elif defined(__mips__)
565+
# elif defined(__mips__)
519566
return mangled_sp;
520567
# elif SANITIZER_RISCV64
521568
return mangled_sp;
@@ -528,42 +575,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
528575
# endif
529576
}
530577

531-
#if SANITIZER_NETBSD
532-
# ifdef __x86_64__
533-
# define LONG_JMP_SP_ENV_SLOT 6
534-
# else
535-
# error unsupported
536-
# endif
537-
#elif defined(__powerpc__)
538-
# define LONG_JMP_SP_ENV_SLOT 0
539-
#elif SANITIZER_FREEBSD
540-
# ifdef __aarch64__
541-
# define LONG_JMP_SP_ENV_SLOT 1
542-
# else
543-
# define LONG_JMP_SP_ENV_SLOT 2
544-
# 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
552-
# elif SANITIZER_RISCV64
553-
# define LONG_JMP_SP_ENV_SLOT 13
554-
# elif defined(__s390x__)
555-
# define LONG_JMP_SP_ENV_SLOT 9
556-
# else
557-
# define LONG_JMP_SP_ENV_SLOT 6
558-
# endif
559-
#endif
560-
561-
uptr ExtractLongJmpSp(uptr *env) {
562-
uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
563-
return UnmangleLongJmpSp(mangled_sp);
564-
}
565-
566-
#if INIT_LONGJMP_XOR_KEY
578+
# if INIT_LONGJMP_XOR_KEY
567579
// GLIBC mangles the function pointers in jmp_buf (used in {set,long}*jmp
568580
// functions) by XORing them with a random key. For AArch64 it is a global
569581
// variable rather than a TCB one (as for x86_64/powerpc). We obtain the key by
@@ -575,17 +587,17 @@ static void InitializeLongjmpXorKey() {
575587

576588
// 2. Retrieve vanilla/mangled SP.
577589
uptr sp;
578-
#ifdef __loongarch__
590+
# ifdef __loongarch__
579591
asm("move %0, $sp" : "=r" (sp));
580-
#else
592+
# else
581593
asm("mov %0, sp" : "=r" (sp));
582-
#endif
594+
# endif
583595
uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT];
584596

585597
// 3. xor SPs to obtain key.
586598
longjmp_xor_key = mangled_sp ^ sp;
587599
}
588-
#endif
600+
# endif
589601

590602
extern "C" void __tsan_tls_initialization() {}
591603

@@ -616,43 +628,51 @@ int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
616628
pthread_cleanup_pop(0);
617629
return res;
618630
}
619-
#endif // !SANITIZER_GO
631+
# endif // !SANITIZER_GO
620632

621-
#if !SANITIZER_GO
622-
void ReplaceSystemMalloc() { }
623-
#endif
633+
# if !SANITIZER_GO
634+
void ReplaceSystemMalloc() {}
635+
# endif
624636

625-
#if !SANITIZER_GO
626-
#if SANITIZER_ANDROID
637+
# if !SANITIZER_GO
638+
# if SANITIZER_ANDROID
627639
// On Android, one thread can call intercepted functions after
628640
// DestroyThreadState(), so add a fake thread state for "dead" threads.
629641
static ThreadState *dead_thread_state = nullptr;
630642

631643
ThreadState *cur_thread() {
632-
ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
644+
ThreadState *thr = reinterpret_cast<ThreadState *>(*get_android_tls_ptr());
633645
if (thr == nullptr) {
634646
__sanitizer_sigset_t emptyset;
635647
internal_sigfillset(&emptyset);
636648
__sanitizer_sigset_t oldset;
637649
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
638-
thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
650+
thr = reinterpret_cast<ThreadState *>(*get_android_tls_ptr());
639651
if (thr == nullptr) {
640-
thr = reinterpret_cast<ThreadState*>(MmapOrDie(sizeof(ThreadState),
641-
"ThreadState"));
652+
thr = reinterpret_cast<ThreadState *>(
653+
MmapOrDie(sizeof(ThreadState), "ThreadState"));
642654
*get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
643655
if (dead_thread_state == nullptr) {
644-
dead_thread_state = reinterpret_cast<ThreadState*>(
656+
dead_thread_state = reinterpret_cast<ThreadState *>(
645657
MmapOrDie(sizeof(ThreadState), "ThreadState"));
646658
dead_thread_state->fast_state.SetIgnoreBit();
647659
dead_thread_state->ignore_interceptors = 1;
648660
dead_thread_state->is_dead = true;
649-
*const_cast<u32*>(&dead_thread_state->tid) = -1;
661+
*const_cast<u32 *>(&dead_thread_state->tid) = -1;
650662
CHECK_EQ(0, internal_mprotect(dead_thread_state, sizeof(ThreadState),
651663
PROT_READ));
652664
}
653665
}
654666
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
655667
}
668+
669+
// This is a temporary workaround.
670+
// Somewhere wrote get_android_tls_ptr unexpected.
671+
uptr addr = reinterpret_cast<uptr>(thr);
672+
if (addr % 2 != 0) {
673+
return reinterpret_cast<ThreadState *>(addr & ~1ULL);
674+
}
675+
656676
return thr;
657677
}
658678

@@ -665,15 +685,15 @@ void cur_thread_finalize() {
665685
internal_sigfillset(&emptyset);
666686
__sanitizer_sigset_t oldset;
667687
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
668-
ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
688+
ThreadState *thr = reinterpret_cast<ThreadState *>(*get_android_tls_ptr());
669689
if (thr != dead_thread_state) {
670690
*get_android_tls_ptr() = reinterpret_cast<uptr>(dead_thread_state);
671691
UnmapOrDie(thr, sizeof(ThreadState));
672692
}
673693
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
674694
}
675-
#endif // SANITIZER_ANDROID
676-
#endif // if !SANITIZER_GO
695+
# endif // SANITIZER_ANDROID
696+
# endif // if !SANITIZER_GO
677697

678698
} // namespace __tsan
679699

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ void MapShadow(uptr addr, uptr size) {
662662
addr + size, meta_begin, meta_end);
663663
}
664664

665-
#if !SANITIZER_GO
665+
#if !SANITIZER_GO && !SANITIZER_ANDROID
666666
static void OnStackUnwind(const SignalContext &sig, const void *,
667667
BufferedStackTrace *stack) {
668668
stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
@@ -733,6 +733,9 @@ void Initialize(ThreadState *thr) {
733733
#if !SANITIZER_GO
734734
InitializeShadowMemory();
735735
InitializeAllocatorLate();
736+
#endif
737+
738+
#if !SANITIZER_GO && !SANITIZER_ANDROID
736739
InstallDeadlySignalHandlers(TsanOnDeadlySignal);
737740
#endif
738741
// Setup correct file descriptor for error reports.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
188188
}
189189
#endif
190190

191-
#if !SANITIZER_GO
191+
#if !SANITIZER_GO && !SANITIZER_ANDROID
192192
// Don't imitate stack/TLS writes for the main thread,
193193
// because its initialization is synchronized with all
194194
// subsequent threads anyway.

0 commit comments

Comments
 (0)