diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -277,9 +277,10 @@ endif() # Provide some common commmandline flags for Sanitizer runtimes. -if("${ANDROID_API_LEVEL}" GREATER_EQUAL 28) +if("${ANDROID_API_LEVEL}" GREATER_EQUAL 29) list(APPEND SANITIZER_COMMON_CFLAGS -fno-emulated-tls) string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " -fno-emulated-tls") + set(ANDROID_ELF_TLS_SUPPORTED TRUE) endif() if(NOT WIN32) append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC SANITIZER_COMMON_CFLAGS) @@ -611,6 +612,7 @@ endif() pythonize_bool(COMPILER_RT_HAS_LLD) pythonize_bool(COMPILER_RT_TEST_USE_LLD) +pythonize_bool(ANDROID_ELF_TLS_SUPPORTED) add_subdirectory(lib) diff --git a/compiler-rt/lib/scudo/CMakeLists.txt b/compiler-rt/lib/scudo/CMakeLists.txt --- a/compiler-rt/lib/scudo/CMakeLists.txt +++ b/compiler-rt/lib/scudo/CMakeLists.txt @@ -25,6 +25,9 @@ if (COMPILER_RT_HAS_Z_GLOBAL) list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -Wl,-z,global) endif() + if (ANDROID_ELF_TLS_SUPPORTED) + list(APPEND SCUDO_CFLAGS -DSCUDO_USE_ELF_TLS -fno-emulated-tls) + endif() endif() # The minimal Scudo runtime does not inlude the UBSan runtime. diff --git a/compiler-rt/lib/scudo/scudo_tsd_shared.cpp b/compiler-rt/lib/scudo/scudo_tsd_shared.cpp --- a/compiler-rt/lib/scudo/scudo_tsd_shared.cpp +++ b/compiler-rt/lib/scudo/scudo_tsd_shared.cpp @@ -25,7 +25,7 @@ static u32 CoPrimes[SCUDO_SHARED_TSD_POOL_SIZE]; static u32 NumberOfCoPrimes = 0; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && (!SANITIZER_ANDROID || defined(SCUDO_USE_ELF_TLS)) __attribute__((tls_model("initial-exec"))) THREADLOCAL ScudoTSD *CurrentTSD; #endif @@ -48,9 +48,9 @@ } ALWAYS_INLINE void setCurrentTSD(ScudoTSD *TSD) { -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID && !defined(SCUDO_USE_ELF_TLS) *get_android_tls_ptr() = reinterpret_cast(TSD); -#elif SANITIZER_LINUX +#elif SANITIZER_LINUX || defined(SCUDO_USE_ELF_TLS) CurrentTSD = TSD; #else CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast(TSD)), 0); diff --git a/compiler-rt/lib/scudo/scudo_tsd_shared.inc b/compiler-rt/lib/scudo/scudo_tsd_shared.inc --- a/compiler-rt/lib/scudo/scudo_tsd_shared.inc +++ b/compiler-rt/lib/scudo/scudo_tsd_shared.inc @@ -18,15 +18,15 @@ extern pthread_key_t PThreadKey; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && (!SANITIZER_ANDROID || defined(SCUDO_USE_ELF_TLS)) __attribute__((tls_model("initial-exec"))) extern THREADLOCAL ScudoTSD *CurrentTSD; #endif ALWAYS_INLINE ScudoTSD* getCurrentTSD() { -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID && !defined(SCUDO_USE_ELF_TLS) return reinterpret_cast(*get_android_tls_ptr()); -#elif SANITIZER_LINUX +#elif SANITIZER_LINUX || defined(SCUDO_USE_ELF_TLS) return CurrentTSD; #else return reinterpret_cast(pthread_getspecific(PThreadKey)); diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -356,10 +356,10 @@ except (subprocess.CalledProcessError, OSError): lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb) try: - android_api_level = int(android_api_level_str) + device_android_api_level = int(android_api_level_str) except ValueError: lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str)) - android_api_level = min(android_api_level, int(config.android_api_level)) + android_api_level = min(device_android_api_level, int(config.android_api_level)) for required in [26, 28, 30]: if android_api_level >= required: config.available_features.add('android-%s' % required) @@ -367,6 +367,14 @@ if android_api_level > 30 or (android_api_level == 30 and android_api_codename == 'S'): config.available_features.add('android-thread-properties-api') + if device_android_api_level >= 30 and not config.android_elf_tls_supported: + # Device has Scudo standalone as the default allocator, and it's occupying + # the sanitizer TLS slot. The API level being built for doesn't support ELF + # TLS, and thus Scudo (vanilla) will fight the platform Scudo standalone + # over the TLS slot. This causes problems, so we need to disable Scudo tests + # in these cases. + config.scudo_tls_slot_battle = True + # Prepare the device. android_tmpdir = '/data/local/tmp/Output' subprocess.check_call([adb, "shell", "mkdir", "-p", android_tmpdir], env=env) diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -46,6 +46,8 @@ set_default("have_rpc_xdr_h", @HAVE_RPC_XDR_H@) set_default("gwp_asan", @COMPILER_RT_HAS_GWP_ASAN_PYBOOL@) set_default("expensive_checks", @LLVM_ENABLE_EXPENSIVE_CHECKS_PYBOOL@) +set_default("android_elf_tls_supported", @ANDROID_ELF_TLS_SUPPORTED_PYBOOL@) +set_default("scudo_tls_slot_battle", False) config.available_features.add('target-is-%s' % config.target_arch) if config.enable_per_target_runtime_dir: diff --git a/compiler-rt/test/scudo/lit.cfg.py b/compiler-rt/test/scudo/lit.cfg.py --- a/compiler-rt/test/scudo/lit.cfg.py +++ b/compiler-rt/test/scudo/lit.cfg.py @@ -62,3 +62,6 @@ # Hardened Allocator tests are currently supported on Linux only. if config.host_os not in ['Linux']: config.unsupported = True + +if config.scudo_tls_slot_battle: + config.unsupported = True