aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-08 17:13:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-08 17:13:22 +0000
commit2109e2e4181555140883e9ec46807746a0eabad2 (patch)
tree81e6d3c4fac52ac6256179942b7f365d01b084d6
parent285f392c555459b82baeec68b944936685546972 (diff)
downloadsrc-2109e2e4181555140883e9ec46807746a0eabad2.tar.gz
src-2109e2e4181555140883e9ec46807746a0eabad2.zip
Vendor import of compiler-rt trunk r302418:vendor/compiler-rt/compiler-rt-trunk-r302418
Notes
Notes: svn path=/vendor/compiler-rt/dist/; revision=317953 svn path=/vendor/compiler-rt/compiler-rt-trunk-r302418/; revision=317954; tag=vendor/compiler-rt/compiler-rt-trunk-r302418
-rw-r--r--include/xray/xray_interface.h91
-rw-r--r--lib/asan/asan_interceptors.cc10
-rw-r--r--lib/asan/asan_interceptors.h6
-rw-r--r--lib/builtins/CMakeLists.txt48
-rw-r--r--lib/builtins/emutls.c2
-rw-r--r--lib/builtins/int_types.h4
-rw-r--r--lib/cfi/cfi_blacklist.txt5
-rw-r--r--lib/scudo/CMakeLists.txt1
-rw-r--r--lib/scudo/scudo_allocator.cpp9
-rw-r--r--lib/scudo/scudo_allocator.h8
-rw-r--r--lib/scudo/scudo_tls.h15
-rw-r--r--lib/scudo/scudo_tls_android.cpp95
-rw-r--r--lib/scudo/scudo_tls_android.inc44
-rw-r--r--lib/scudo/scudo_tls_context_android.inc54
-rw-r--r--lib/scudo/scudo_tls_context_linux.inc29
-rw-r--r--lib/scudo/scudo_tls_linux.cpp10
-rw-r--r--lib/scudo/scudo_tls_linux.inc (renamed from lib/scudo/scudo_tls_linux.h)16
-rw-r--r--lib/ubsan/CMakeLists.txt1
-rw-r--r--lib/ubsan/ubsan_diag_standalone.cc37
-rw-r--r--lib/ubsan/ubsan_handlers.cc3
-rw-r--r--lib/xray/xray_init.cc4
-rw-r--r--lib/xray/xray_interface.cc141
-rw-r--r--lib/xray/xray_interface_internal.h7
-rw-r--r--test/asan/TestCases/Linux/longjmp_chk.c51
-rw-r--r--test/builtins/Unit/divxc3_test.c1
-rw-r--r--test/builtins/Unit/fixunstfti_test.c2
-rw-r--r--test/builtins/Unit/fixunsxfti_test.c2
-rw-r--r--test/builtins/Unit/fixxfti_test.c2
-rw-r--r--test/builtins/Unit/floattixf_test.c2
-rw-r--r--test/builtins/Unit/floatuntixf_test.c2
-rw-r--r--test/builtins/Unit/mulxc3_test.c1
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc15
-rw-r--r--test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc23
-rw-r--r--test/ubsan/TestCases/Misc/bool.m14
-rw-r--r--test/xray/TestCases/Linux/coverage-sample.cc91
-rw-r--r--test/xray/TestCases/Linux/func-id-utils.cc44
36 files changed, 775 insertions, 115 deletions
diff --git a/include/xray/xray_interface.h b/include/xray/xray_interface.h
index 52a7e1d9e944..c90025e38aae 100644
--- a/include/xray/xray_interface.h
+++ b/include/xray/xray_interface.h
@@ -15,10 +15,11 @@
#define XRAY_XRAY_INTERFACE_H
#include <cstdint>
+#include <stddef.h>
extern "C" {
-// Synchronize this with AsmPrinter::SledKind in LLVM.
+/// Synchronize this with AsmPrinter::SledKind in LLVM.
enum XRayEntryType {
ENTRY = 0,
EXIT = 1,
@@ -26,32 +27,43 @@ enum XRayEntryType {
LOG_ARGS_ENTRY = 3,
};
-// Provide a function to invoke for when instrumentation points are hit. This is
-// a user-visible control surface that overrides the default implementation. The
-// function provided should take the following arguments:
-//
-// - function id: an identifier that indicates the id of a function; this id
-// is generated by xray; the mapping between the function id
-// and the actual function pointer is available through
-// __xray_table.
-// - entry type: identifies what kind of instrumentation point was encountered
-// (function entry, function exit, etc.). See the enum
-// XRayEntryType for more details.
-//
-// The user handler must handle correctly spurious calls after this handler is
-// removed or replaced with another handler, because it would be too costly for
-// XRay runtime to avoid spurious calls.
-// To prevent circular calling, the handler function itself and all its
-// direct&indirect callees must not be instrumented with XRay, which can be
-// achieved by marking them all with: __attribute__((xray_never_instrument))
-//
-// Returns 1 on success, 0 on error.
+/// Provide a function to invoke for when instrumentation points are hit. This
+/// is a user-visible control surface that overrides the default implementation.
+/// The function provided should take the following arguments:
+///
+/// - function id: an identifier that indicates the id of a function; this id
+/// is generated by xray; the mapping between the function id
+/// and the actual function pointer is available through
+/// __xray_table.
+/// - entry type: identifies what kind of instrumentation point was
+/// encountered (function entry, function exit, etc.). See the
+/// enum XRayEntryType for more details.
+///
+/// The user handler must handle correctly spurious calls after this handler is
+/// removed or replaced with another handler, because it would be too costly for
+/// XRay runtime to avoid spurious calls.
+/// To prevent circular calling, the handler function itself and all its
+/// direct&indirect callees must not be instrumented with XRay, which can be
+/// achieved by marking them all with: __attribute__((xray_never_instrument))
+///
+/// Returns 1 on success, 0 on error.
extern int __xray_set_handler(void (*entry)(int32_t, XRayEntryType));
-// This removes whatever the currently provided handler is. Returns 1 on
-// success, 0 on error.
+/// This removes whatever the currently provided handler is. Returns 1 on
+/// success, 0 on error.
extern int __xray_remove_handler();
+/// Use XRay to log the first argument of each (instrumented) function call.
+/// When this function exits, all threads will have observed the effect and
+/// start logging their subsequent affected function calls (if patched).
+///
+/// Returns 1 on success, 0 on error.
+extern int __xray_set_handler_arg1(void (*)(int32_t, XRayEntryType, uint64_t));
+
+/// Disables the XRay handler used to log first arguments of function calls.
+/// Returns 1 on success, 0 on error.
+extern int __xray_remove_handler_arg1();
+
enum XRayPatchingStatus {
NOT_INITIALIZED = 0,
SUCCESS = 1,
@@ -59,24 +71,31 @@ enum XRayPatchingStatus {
FAILED = 3,
};
-// This tells XRay to patch the instrumentation points. See XRayPatchingStatus
-// for possible result values.
+/// This tells XRay to patch the instrumentation points. See XRayPatchingStatus
+/// for possible result values.
extern XRayPatchingStatus __xray_patch();
-// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
-// result values.
+/// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
+/// result values.
extern XRayPatchingStatus __xray_unpatch();
-// Use XRay to log the first argument of each (instrumented) function call.
-// When this function exits, all threads will have observed the effect and
-// start logging their subsequent affected function calls (if patched).
-//
-// Returns 1 on success, 0 on error.
-extern int __xray_set_handler_arg1(void (*)(int32_t, XRayEntryType, uint64_t));
+/// This patches a specific function id. See XRayPatchingStatus for possible
+/// result values.
+extern XRayPatchingStatus __xray_patch_function(int32_t FuncId);
+
+/// This unpatches a specific function id. See XRayPatchingStatus for possible
+/// result values.
+extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);
+
+/// This function returns the address of the function provided a valid function
+/// id. We return 0 if we encounter any error, even if 0 may be a valid function
+/// address.
+extern uintptr_t __xray_function_address(int32_t FuncId);
+
+/// This function returns the maximum valid function id. Returns 0 if we
+/// encounter errors (when there are no instrumented functions, etc.).
+extern size_t __xray_max_function_id();
-// Disables the XRay handler used to log first arguments of function calls.
-// Returns 1 on success, 0 on error.
-extern int __xray_remove_handler_arg1();
}
#endif
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index 905dd2e23870..c6969c979a59 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -443,6 +443,13 @@ INTERCEPTOR(void, _longjmp, void *env, int val) {
}
#endif
+#if ASAN_INTERCEPT___LONGJMP_CHK
+INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(__longjmp_chk)(env, val);
+}
+#endif
+
#if ASAN_INTERCEPT_SIGLONGJMP
INTERCEPTOR(void, siglongjmp, void *env, int val) {
__asan_handle_no_return();
@@ -758,6 +765,9 @@ void InitializeAsanInterceptors() {
#if ASAN_INTERCEPT__LONGJMP
ASAN_INTERCEPT_FUNC(_longjmp);
#endif
+#if ASAN_INTERCEPT___LONGJMP_CHK
+ ASAN_INTERCEPT_FUNC(__longjmp_chk);
+#endif
#if ASAN_INTERCEPT_SIGLONGJMP
ASAN_INTERCEPT_FUNC(siglongjmp);
#endif
diff --git a/lib/asan/asan_interceptors.h b/lib/asan/asan_interceptors.h
index d747c31a5d0f..93fca4f67366 100644
--- a/lib/asan/asan_interceptors.h
+++ b/lib/asan/asan_interceptors.h
@@ -58,6 +58,12 @@
# define ASAN_INTERCEPT_SIGLONGJMP 0
#endif
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+# define ASAN_INTERCEPT___LONGJMP_CHK 1
+#else
+# define ASAN_INTERCEPT___LONGJMP_CHK 0
+#endif
+
// Android bug: https://code.google.com/p/android/issues/detail?id=61799
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && \
!(SANITIZER_ANDROID && defined(__i386))
diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt
index c30d9b3633fe..e3779ca79ceb 100644
--- a/lib/builtins/CMakeLists.txt
+++ b/lib/builtins/CMakeLists.txt
@@ -167,6 +167,26 @@ set(GENERIC_SOURCES
umodti3.c
emutls.c)
+set(GENERIC_TF_SOURCES
+ comparetf2.c
+ extenddftf2.c
+ extendsftf2.c
+ fixtfdi.c
+ fixtfsi.c
+ fixtfti.c
+ fixunstfdi.c
+ fixunstfsi.c
+ fixunstfti.c
+ floatditf.c
+ floatsitf.c
+ floattitf.c
+ floatunditf.c
+ floatunsitf.c
+ floatuntitf.c
+ multc3.c
+ trunctfdf2.c
+ trunctfsf2.c)
+
option(COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN
"Skip the atomic builtin (this may be needed if system headers are unavailable)"
Off)
@@ -390,7 +410,8 @@ if(MINGW)
udivmoddi4.c
udivmodsi4.c
udivsi3.c
- umoddi3.c)
+ umoddi3.c
+ emutls.c)
elseif(NOT WIN32)
# TODO the EABI sources should only be added to EABI targets
set(arm_SOURCES
@@ -404,24 +425,7 @@ elseif(NOT WIN32)
endif()
set(aarch64_SOURCES
- comparetf2.c
- extenddftf2.c
- extendsftf2.c
- fixtfdi.c
- fixtfsi.c
- fixtfti.c
- fixunstfdi.c
- fixunstfsi.c
- fixunstfti.c
- floatditf.c
- floatsitf.c
- floattitf.c
- floatunditf.c
- floatunsitf.c
- floatuntitf.c
- multc3.c
- trunctfdf2.c
- trunctfsf2.c
+ ${GENERIC_TF_SOURCES}
${GENERIC_SOURCES})
set(armhf_SOURCES ${arm_SOURCES})
@@ -437,8 +441,10 @@ set(armv7em_SOURCES ${arm_SOURCES})
set(mips_SOURCES ${GENERIC_SOURCES})
set(mipsel_SOURCES ${mips_SOURCES})
-set(mips64_SOURCES ${mips_SOURCES})
-set(mips64el_SOURCES ${mips_SOURCES})
+set(mips64_SOURCES ${GENERIC_TF_SOURCES}
+ ${mips_SOURCES})
+set(mips64el_SOURCES ${GENERIC_TF_SOURCES}
+ ${mips_SOURCES})
set(wasm32_SOURCES ${GENERIC_SOURCES})
set(wasm64_SOURCES ${GENERIC_SOURCES})
diff --git a/lib/builtins/emutls.c b/lib/builtins/emutls.c
index e8d5ddb22011..12aad3a42b76 100644
--- a/lib/builtins/emutls.c
+++ b/lib/builtins/emutls.c
@@ -98,7 +98,7 @@ static __inline emutls_address_array* emutls_getspecific() {
#else
-#include <Windows.h>
+#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <assert.h>
diff --git a/lib/builtins/int_types.h b/lib/builtins/int_types.h
index 660385ecd6ae..a92238c5b730 100644
--- a/lib/builtins/int_types.h
+++ b/lib/builtins/int_types.h
@@ -60,9 +60,7 @@ typedef union
}s;
} udwords;
-/* MIPS64 issue: PR 20098 */
-#if (defined(__LP64__) || defined(__wasm__)) && \
- !(defined(__mips__) && defined(__clang__))
+#if (defined(__LP64__) || defined(__wasm__) || defined(__mips64))
#define CRT_HAS_128BIT
#endif
diff --git a/lib/cfi/cfi_blacklist.txt b/lib/cfi/cfi_blacklist.txt
index 1f0eeb355617..cc111be8120e 100644
--- a/lib/cfi/cfi_blacklist.txt
+++ b/lib/cfi/cfi_blacklist.txt
@@ -24,3 +24,8 @@ fun:_ZNSt3__19addressof*
# Windows C++ stdlib headers that contain bad unrelated casts.
src:*xmemory0
src:*xstddef
+
+# std::_Sp_counted_ptr_inplace::_Sp_counted_ptr_inplace() (libstdc++).
+# This ctor is used by std::make_shared and needs to cast to uninitialized T*
+# in order to call std::allocator_traits<T>::construct.
+fun:_ZNSt23_Sp_counted_ptr_inplace*
diff --git a/lib/scudo/CMakeLists.txt b/lib/scudo/CMakeLists.txt
index 3a8f4ae4fa9e..14c199fa8227 100644
--- a/lib/scudo/CMakeLists.txt
+++ b/lib/scudo/CMakeLists.txt
@@ -14,6 +14,7 @@ set(SCUDO_SOURCES
scudo_interceptors.cpp
scudo_new_delete.cpp
scudo_termination.cpp
+ scudo_tls_android.cpp
scudo_tls_linux.cpp
scudo_utils.cpp)
diff --git a/lib/scudo/scudo_allocator.cpp b/lib/scudo/scudo_allocator.cpp
index 2ccdcd903dad..5420fc9649ca 100644
--- a/lib/scudo/scudo_allocator.cpp
+++ b/lib/scudo/scudo_allocator.cpp
@@ -368,11 +368,12 @@ struct ScudoAllocator {
void *Ptr;
uptr Salt;
uptr AllocationAlignment = FromPrimary ? MinAlignment : Alignment;
- ScudoThreadContext *ThreadContext = getThreadContext();
+ ScudoThreadContext *ThreadContext = getThreadContextAndLock();
if (LIKELY(ThreadContext)) {
Salt = getPrng(ThreadContext)->getNext();
Ptr = BackendAllocator.Allocate(getAllocatorCache(ThreadContext),
NeededSize, AllocationAlignment);
+ ThreadContext->unlock();
} else {
SpinMutexLock l(&FallbackMutex);
Salt = FallbackPrng.getNext();
@@ -434,9 +435,10 @@ struct ScudoAllocator {
if (BypassQuarantine) {
Chunk->eraseHeader();
void *Ptr = Chunk->getAllocBeg(Header);
- ScudoThreadContext *ThreadContext = getThreadContext();
+ ScudoThreadContext *ThreadContext = getThreadContextAndLock();
if (LIKELY(ThreadContext)) {
getBackendAllocator().Deallocate(getAllocatorCache(ThreadContext), Ptr);
+ ThreadContext->unlock();
} else {
SpinMutexLock Lock(&FallbackMutex);
getBackendAllocator().Deallocate(&FallbackAllocatorCache, Ptr);
@@ -445,12 +447,13 @@ struct ScudoAllocator {
UnpackedHeader NewHeader = *Header;
NewHeader.State = ChunkQuarantine;
Chunk->compareExchangeHeader(&NewHeader, Header);
- ScudoThreadContext *ThreadContext = getThreadContext();
+ ScudoThreadContext *ThreadContext = getThreadContextAndLock();
if (LIKELY(ThreadContext)) {
AllocatorQuarantine.Put(getQuarantineCache(ThreadContext),
QuarantineCallback(
getAllocatorCache(ThreadContext)),
Chunk, Size);
+ ThreadContext->unlock();
} else {
SpinMutexLock l(&FallbackMutex);
AllocatorQuarantine.Put(&FallbackQuarantineCache,
diff --git a/lib/scudo/scudo_allocator.h b/lib/scudo/scudo_allocator.h
index 2cac2de71cb0..f159deffb1d5 100644
--- a/lib/scudo/scudo_allocator.h
+++ b/lib/scudo/scudo_allocator.h
@@ -72,7 +72,13 @@ const uptr AlignedChunkHeaderSize =
#if SANITIZER_CAN_USE_ALLOCATOR64
const uptr AllocatorSpace = ~0ULL;
-const uptr AllocatorSize = 0x40000000000ULL; // 4TB.
+# if defined(__aarch64__) && SANITIZER_ANDROID
+const uptr AllocatorSize = 0x4000000000ULL; // 256G.
+# elif defined(__aarch64__)
+const uptr AllocatorSize = 0x10000000000ULL; // 1T.
+# else
+const uptr AllocatorSize = 0x40000000000ULL; // 4T.
+# endif
typedef DefaultSizeClassMap SizeClassMap;
struct AP {
static const uptr kSpaceBeg = AllocatorSpace;
diff --git a/lib/scudo/scudo_tls.h b/lib/scudo/scudo_tls.h
index 0d7d1bffd0b6..f6039bebec44 100644
--- a/lib/scudo/scudo_tls.h
+++ b/lib/scudo/scudo_tls.h
@@ -19,10 +19,16 @@
#include "scudo_allocator.h"
#include "scudo_utils.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
namespace __scudo {
-struct ALIGNED(64) ScudoThreadContext {
- public:
+// Platform specific base thread context definitions.
+#include "scudo_tls_context_android.inc"
+#include "scudo_tls_context_linux.inc"
+
+struct ALIGNED(64) ScudoThreadContext : public ScudoThreadContextPlatform {
AllocatorCache Cache;
Xorshift128Plus Prng;
uptr QuarantineCachePlaceHolder[4];
@@ -32,8 +38,9 @@ struct ALIGNED(64) ScudoThreadContext {
void initThread();
-// Fastpath functions are defined in the following platform specific headers.
-#include "scudo_tls_linux.h"
+// Platform specific dastpath functions definitions.
+#include "scudo_tls_android.inc"
+#include "scudo_tls_linux.inc"
} // namespace __scudo
diff --git a/lib/scudo/scudo_tls_android.cpp b/lib/scudo/scudo_tls_android.cpp
new file mode 100644
index 000000000000..0e3602b2faf0
--- /dev/null
+++ b/lib/scudo/scudo_tls_android.cpp
@@ -0,0 +1,95 @@
+//===-- scudo_tls_android.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Scudo thread local structure implementation for Android.
+///
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if SANITIZER_LINUX && SANITIZER_ANDROID
+
+#include "scudo_tls.h"
+
+#include <pthread.h>
+
+namespace __scudo {
+
+static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
+static pthread_key_t PThreadKey;
+
+static atomic_uint32_t ThreadContextCurrentIndex;
+static ScudoThreadContext *ThreadContexts;
+static uptr NumberOfContexts;
+
+// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used as they allocate memory.
+static uptr getNumberOfCPUs() {
+ cpu_set_t CPUs;
+ CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
+ return CPU_COUNT(&CPUs);
+}
+
+static void initOnce() {
+ // Hack: TLS_SLOT_TSAN was introduced in N. To be able to use it on M for
+ // testing, we create an unused key. Since the key_data array follows the tls
+ // array, it basically gives us the extra entry we need.
+ // TODO(kostyak): remove and restrict to N and above.
+ CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0);
+ initScudo();
+ NumberOfContexts = getNumberOfCPUs();
+ ThreadContexts = reinterpret_cast<ScudoThreadContext *>(
+ MmapOrDie(sizeof(ScudoThreadContext) * NumberOfContexts, __func__));
+ for (int i = 0; i < NumberOfContexts; i++)
+ ThreadContexts[i].init();
+}
+
+void initThread() {
+ pthread_once(&GlobalInitialized, initOnce);
+ // Initial context assignment is done in a plain round-robin fashion.
+ u32 Index = atomic_fetch_add(&ThreadContextCurrentIndex, 1,
+ memory_order_relaxed);
+ ScudoThreadContext *ThreadContext =
+ &ThreadContexts[Index % NumberOfContexts];
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
+}
+
+ScudoThreadContext *getThreadContextAndLockSlow() {
+ ScudoThreadContext *ThreadContext;
+ // Go through all the contexts and find the first unlocked one.
+ for (u32 i = 0; i < NumberOfContexts; i++) {
+ ThreadContext = &ThreadContexts[i];
+ if (ThreadContext->tryLock()) {
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
+ return ThreadContext;
+ }
+ }
+ // No luck, find the one with the lowest precedence, and slow lock it.
+ u64 Precedence = UINT64_MAX;
+ for (u32 i = 0; i < NumberOfContexts; i++) {
+ u64 SlowLockPrecedence = ThreadContexts[i].getSlowLockPrecedence();
+ if (SlowLockPrecedence && SlowLockPrecedence < Precedence) {
+ ThreadContext = &ThreadContexts[i];
+ Precedence = SlowLockPrecedence;
+ }
+ }
+ if (LIKELY(Precedence != UINT64_MAX)) {
+ ThreadContext->lock();
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
+ return ThreadContext;
+ }
+ // Last resort (can this happen?), stick with the current one.
+ ThreadContext =
+ reinterpret_cast<ScudoThreadContext *>(*get_android_tls_ptr());
+ ThreadContext->lock();
+ return ThreadContext;
+}
+
+} // namespace __scudo
+
+#endif // SANITIZER_LINUX && SANITIZER_ANDROID
diff --git a/lib/scudo/scudo_tls_android.inc b/lib/scudo/scudo_tls_android.inc
new file mode 100644
index 000000000000..8ecad7a30a6c
--- /dev/null
+++ b/lib/scudo/scudo_tls_android.inc
@@ -0,0 +1,44 @@
+//===-- scudo_tls_android.inc -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Scudo thread local structure fastpath functions implementation for Android.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TLS_ANDROID_H_
+#define SCUDO_TLS_ANDROID_H_
+
+#ifndef SCUDO_TLS_H_
+# error "This file must be included inside scudo_tls.h."
+#endif // SCUDO_TLS_H_
+
+#if SANITIZER_LINUX && SANITIZER_ANDROID
+
+ALWAYS_INLINE void initThreadMaybe() {
+ if (LIKELY(*get_android_tls_ptr()))
+ return;
+ initThread();
+}
+
+ScudoThreadContext *getThreadContextAndLockSlow();
+
+ALWAYS_INLINE ScudoThreadContext *getThreadContextAndLock() {
+ ScudoThreadContext *ThreadContext =
+ reinterpret_cast<ScudoThreadContext *>(*get_android_tls_ptr());
+ CHECK(ThreadContext);
+ // Try to lock the currently associated context.
+ if (ThreadContext->tryLock())
+ return ThreadContext;
+ // If it failed, go the slow path.
+ return getThreadContextAndLockSlow();
+}
+
+#endif // SANITIZER_LINUX && SANITIZER_ANDROID
+
+#endif // SCUDO_TLS_ANDROID_H_
diff --git a/lib/scudo/scudo_tls_context_android.inc b/lib/scudo/scudo_tls_context_android.inc
new file mode 100644
index 000000000000..f1951319d487
--- /dev/null
+++ b/lib/scudo/scudo_tls_context_android.inc
@@ -0,0 +1,54 @@
+//===-- scudo_tls_context_android.inc ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Android specific base thread context definition.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TLS_CONTEXT_ANDROID_INC_
+#define SCUDO_TLS_CONTEXT_ANDROID_INC_
+
+#ifndef SCUDO_TLS_H_
+# error "This file must be included inside scudo_tls.h."
+#endif // SCUDO_TLS_H_
+
+#if SANITIZER_LINUX && SANITIZER_ANDROID
+
+struct ScudoThreadContextPlatform {
+ INLINE bool tryLock() {
+ if (Mutex.TryLock()) {
+ atomic_store_relaxed(&SlowLockPrecedence, 0);
+ return true;
+ }
+ if (atomic_load_relaxed(&SlowLockPrecedence) == 0)
+ atomic_store_relaxed(&SlowLockPrecedence, NanoTime());
+ return false;
+ }
+
+ INLINE void lock() {
+ Mutex.Lock();
+ atomic_store_relaxed(&SlowLockPrecedence, 0);
+ }
+
+ INLINE void unlock() {
+ Mutex.Unlock();
+ }
+
+ INLINE u64 getSlowLockPrecedence() {
+ return atomic_load_relaxed(&SlowLockPrecedence);
+ }
+
+ private:
+ StaticSpinMutex Mutex;
+ atomic_uint64_t SlowLockPrecedence;
+};
+
+#endif // SANITIZER_LINUX && SANITIZER_ANDROID
+
+#endif // SCUDO_TLS_CONTEXT_ANDROID_INC_
diff --git a/lib/scudo/scudo_tls_context_linux.inc b/lib/scudo/scudo_tls_context_linux.inc
new file mode 100644
index 000000000000..8d292bdbc932
--- /dev/null
+++ b/lib/scudo/scudo_tls_context_linux.inc
@@ -0,0 +1,29 @@
+//===-- scudo_tls_context_linux.inc -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Linux specific base thread context definition.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TLS_CONTEXT_LINUX_INC_
+#define SCUDO_TLS_CONTEXT_LINUX_INC_
+
+#ifndef SCUDO_TLS_H_
+# error "This file must be included inside scudo_tls.h."
+#endif // SCUDO_TLS_H_
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+
+struct ScudoThreadContextPlatform {
+ ALWAYS_INLINE void unlock() {}
+};
+
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#endif // SCUDO_TLS_CONTEXT_LINUX_INC_
diff --git a/lib/scudo/scudo_tls_linux.cpp b/lib/scudo/scudo_tls_linux.cpp
index 3453367f8a53..5a9cc998bccf 100644
--- a/lib/scudo/scudo_tls_linux.cpp
+++ b/lib/scudo/scudo_tls_linux.cpp
@@ -14,7 +14,7 @@
#include "sanitizer_common/sanitizer_platform.h"
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
#include "scudo_tls.h"
@@ -26,8 +26,10 @@ namespace __scudo {
static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
static pthread_key_t PThreadKey;
-thread_local ThreadState ScudoThreadState = ThreadNotInitialized;
-thread_local ScudoThreadContext ThreadLocalContext;
+__attribute__((tls_model("initial-exec")))
+THREADLOCAL ThreadState ScudoThreadState = ThreadNotInitialized;
+__attribute__((tls_model("initial-exec")))
+THREADLOCAL ScudoThreadContext ThreadLocalContext;
static void teardownThread(void *Ptr) {
uptr Iteration = reinterpret_cast<uptr>(Ptr);
@@ -59,4 +61,4 @@ void initThread() {
} // namespace __scudo
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
diff --git a/lib/scudo/scudo_tls_linux.h b/lib/scudo/scudo_tls_linux.inc
index 0994f2d7b24d..242ee3329ea8 100644
--- a/lib/scudo/scudo_tls_linux.h
+++ b/lib/scudo/scudo_tls_linux.inc
@@ -1,4 +1,4 @@
-//===-- scudo_tls_linux.h ---------------------------------------*- C++ -*-===//
+//===-- scudo_tls_linux.inc -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,17 +19,17 @@
# error "This file must be included inside scudo_tls.h."
#endif // SCUDO_TLS_H_
-#include "sanitizer_common/sanitizer_platform.h"
-
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
enum ThreadState : u8 {
ThreadNotInitialized = 0,
ThreadInitialized,
ThreadTornDown,
};
-extern thread_local ThreadState ScudoThreadState;
-extern thread_local ScudoThreadContext ThreadLocalContext;
+__attribute__((tls_model("initial-exec")))
+extern THREADLOCAL ThreadState ScudoThreadState;
+__attribute__((tls_model("initial-exec")))
+extern THREADLOCAL ScudoThreadContext ThreadLocalContext;
ALWAYS_INLINE void initThreadMaybe() {
if (LIKELY(ScudoThreadState != ThreadNotInitialized))
@@ -37,12 +37,12 @@ ALWAYS_INLINE void initThreadMaybe() {
initThread();
}
-ALWAYS_INLINE ScudoThreadContext *getThreadContext() {
+ALWAYS_INLINE ScudoThreadContext *getThreadContextAndLock() {
if (UNLIKELY(ScudoThreadState == ThreadTornDown))
return nullptr;
return &ThreadLocalContext;
}
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
#endif // SCUDO_TLS_LINUX_H_
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt
index f35b40f3b1cc..7e10456e3142 100644
--- a/lib/ubsan/CMakeLists.txt
+++ b/lib/ubsan/CMakeLists.txt
@@ -9,6 +9,7 @@ set(UBSAN_SOURCES
)
set(UBSAN_STANDALONE_SOURCES
+ ubsan_diag_standalone.cc
ubsan_init_standalone.cc
)
diff --git a/lib/ubsan/ubsan_diag_standalone.cc b/lib/ubsan/ubsan_diag_standalone.cc
new file mode 100644
index 000000000000..df8ed5fcdf6d
--- /dev/null
+++ b/lib/ubsan/ubsan_diag_standalone.cc
@@ -0,0 +1,37 @@
+//===-- ubsan_diag_standalone.cc ------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Diagnostic reporting for the standalone UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_diag.h"
+
+using namespace __ubsan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ uptr top = 0;
+ uptr bottom = 0;
+ bool request_fast_unwind = common_flags()->fast_unwind_on_fatal;
+ if (request_fast_unwind)
+ __sanitizer::GetThreadStackTopAndBottom(false, &top, &bottom);
+
+ GET_REPORT_OPTIONS(false);
+ BufferedStackTrace stack;
+ stack.Unwind(kStackTraceMax, Opts.pc, Opts.bp, nullptr, top, bottom,
+ request_fast_unwind);
+ stack.Print();
+}
+} // extern "C"
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index de13ab893bec..d6a8f52a27b4 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -410,7 +410,8 @@ static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
SourceLocation Loc = Data->Loc.acquire();
// This check could be more precise if we used different handlers for
// -fsanitize=bool and -fsanitize=enum.
- bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'"));
+ bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")) ||
+ (0 == internal_strncmp(Data->Type.getTypeName(), "'BOOL'", 6));
ErrorType ET =
IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
diff --git a/lib/xray/xray_init.cc b/lib/xray/xray_init.cc
index 6f558d656147..aa660baa9920 100644
--- a/lib/xray/xray_init.cc
+++ b/lib/xray/xray_init.cc
@@ -25,6 +25,8 @@ extern "C" {
void __xray_init();
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
+extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak));
+extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak));
}
using namespace __xray;
@@ -55,6 +57,8 @@ void __xray_init() XRAY_NEVER_INSTRUMENT {
__sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
XRayInstrMap.Sleds = __start_xray_instr_map;
XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
+ XRayInstrMap.SledsIndex = __start_xray_fn_idx;
+ XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx;
}
__sanitizer::atomic_store(&XRayInitialized, true,
__sanitizer::memory_order_release);
diff --git a/lib/xray/xray_interface.cc b/lib/xray/xray_interface.cc
index 26ec161fe860..26f0ab122db2 100644
--- a/lib/xray/xray_interface.cc
+++ b/lib/xray/xray_interface.cc
@@ -132,12 +132,48 @@ CleanupInvoker<Function> scopeCleanup(Function Fn) XRAY_NEVER_INSTRUMENT {
return CleanupInvoker<Function>{Fn};
}
+inline bool patchSled(const XRaySledEntry &Sled, bool Enable,
+ int32_t FuncId) XRAY_NEVER_INSTRUMENT {
+ // While we're here, we should patch the nop sled. To do that we mprotect
+ // the page containing the function to be writeable.
+ const uint64_t PageSize = GetPageSizeCached();
+ void *PageAlignedAddr =
+ reinterpret_cast<void *>(Sled.Address & ~(PageSize - 1));
+ std::size_t MProtectLen = (Sled.Address + cSledLength) -
+ reinterpret_cast<uint64_t>(PageAlignedAddr);
+ MProtectHelper Protector(PageAlignedAddr, MProtectLen);
+ if (Protector.MakeWriteable() == -1) {
+ printf("Failed mprotect: %d\n", errno);
+ return XRayPatchingStatus::FAILED;
+ }
+
+ bool Success = false;
+ switch (Sled.Kind) {
+ case XRayEntryType::ENTRY:
+ Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);
+ break;
+ case XRayEntryType::EXIT:
+ Success = patchFunctionExit(Enable, FuncId, Sled);
+ break;
+ case XRayEntryType::TAIL:
+ Success = patchFunctionTailExit(Enable, FuncId, Sled);
+ break;
+ case XRayEntryType::LOG_ARGS_ENTRY:
+ Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);
+ break;
+ default:
+ Report("Unsupported sled kind '%d' @%04x\n", Sled.Address, int(Sled.Kind));
+ return false;
+ }
+ return Success;
+}
+
// controlPatching implements the common internals of the patching/unpatching
// implementation. |Enable| defines whether we're enabling or disabling the
// runtime XRay instrumentation.
XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
if (!__sanitizer::atomic_load(&XRayInitialized,
- __sanitizer::memory_order_acquire))
+ __sanitizer::memory_order_acquire))
return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.
uint8_t NotPatching = false;
@@ -179,38 +215,7 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
++FuncId;
CurFun = F;
}
-
- // While we're here, we should patch the nop sled. To do that we mprotect
- // the page containing the function to be writeable.
- void *PageAlignedAddr =
- reinterpret_cast<void *>(Sled.Address & ~(PageSize - 1));
- std::size_t MProtectLen = (Sled.Address + cSledLength) -
- reinterpret_cast<uint64_t>(PageAlignedAddr);
- MProtectHelper Protector(PageAlignedAddr, MProtectLen);
- if (Protector.MakeWriteable() == -1) {
- printf("Failed mprotect: %d\n", errno);
- return XRayPatchingStatus::FAILED;
- }
-
- bool Success = false;
- switch (Sled.Kind) {
- case XRayEntryType::ENTRY:
- Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);
- break;
- case XRayEntryType::EXIT:
- Success = patchFunctionExit(Enable, FuncId, Sled);
- break;
- case XRayEntryType::TAIL:
- Success = patchFunctionTailExit(Enable, FuncId, Sled);
- break;
- case XRayEntryType::LOG_ARGS_ENTRY:
- Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);
- break;
- default:
- Report("Unsupported sled kind: %d\n", int(Sled.Kind));
- continue;
- }
- (void)Success;
+ patchSled(Sled, Enable, FuncId);
}
__sanitizer::atomic_store(&XRayPatching, false,
__sanitizer::memory_order_release);
@@ -226,6 +231,64 @@ XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT {
return controlPatching(false);
}
+XRayPatchingStatus patchFunction(int32_t FuncId,
+ bool Enable) XRAY_NEVER_INSTRUMENT {
+ if (!__sanitizer::atomic_load(&XRayInitialized,
+ __sanitizer::memory_order_acquire))
+ return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.
+
+ uint8_t NotPatching = false;
+ if (!__sanitizer::atomic_compare_exchange_strong(
+ &XRayPatching, &NotPatching, true, __sanitizer::memory_order_acq_rel))
+ return XRayPatchingStatus::ONGOING; // Already patching.
+
+ // Next, we look for the function index.
+ XRaySledMap InstrMap;
+ {
+ __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
+ InstrMap = XRayInstrMap;
+ }
+
+ // If we don't have an index, we can't patch individual functions.
+ if (InstrMap.Functions == 0)
+ return XRayPatchingStatus::NOT_INITIALIZED;
+
+ // FuncId must be a positive number, less than the number of functions
+ // instrumented.
+ if (FuncId <= 0 || static_cast<size_t>(FuncId) > InstrMap.Functions) {
+ Report("Invalid function id provided: %d\n", FuncId);
+ return XRayPatchingStatus::FAILED;
+ }
+
+ // Now we patch ths sleds for this specific function.
+ auto SledRange = InstrMap.SledsIndex[FuncId - 1];
+ auto *f = SledRange.Begin;
+ auto *e = SledRange.End;
+
+ bool SucceedOnce = false;
+ while (f != e)
+ SucceedOnce |= patchSled(*f++, Enable, FuncId);
+
+ __sanitizer::atomic_store(&XRayPatching, false,
+ __sanitizer::memory_order_release);
+
+ if (!SucceedOnce) {
+ Report("Failed patching any sled for function '%d'.", FuncId);
+ return XRayPatchingStatus::FAILED;
+ }
+
+ return XRayPatchingStatus::SUCCESS;
+}
+
+XRayPatchingStatus __xray_patch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
+ return patchFunction(FuncId, true);
+}
+
+XRayPatchingStatus
+__xray_unpatch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
+ return patchFunction(FuncId, false);
+}
+
int __xray_set_handler_arg1(void (*Handler)(int32_t, XRayEntryType, uint64_t)) {
if (!__sanitizer::atomic_load(&XRayInitialized,
__sanitizer::memory_order_acquire))
@@ -239,3 +302,15 @@ int __xray_set_handler_arg1(void (*Handler)(int32_t, XRayEntryType, uint64_t)) {
return 1;
}
int __xray_remove_handler_arg1() { return __xray_set_handler_arg1(nullptr); }
+
+uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
+ __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
+ if (FuncId <= 0 || static_cast<size_t>(FuncId) > XRayInstrMap.Functions)
+ return 0;
+ return XRayInstrMap.SledsIndex[FuncId - 1].Begin->Address;
+}
+
+size_t __xray_max_function_id() XRAY_NEVER_INSTRUMENT {
+ __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
+ return XRayInstrMap.Functions;
+}
diff --git a/lib/xray/xray_interface_internal.h b/lib/xray/xray_interface_internal.h
index 0e3a251f3ad7..ef0c6b15809b 100644
--- a/lib/xray/xray_interface_internal.h
+++ b/lib/xray/xray_interface_internal.h
@@ -39,6 +39,11 @@ struct XRaySledEntry {
#error "Unsupported word size."
#endif
};
+
+struct XRayFunctionSledIndex {
+ const XRaySledEntry* Begin;
+ const XRaySledEntry* End;
+};
}
namespace __xray {
@@ -46,6 +51,8 @@ namespace __xray {
struct XRaySledMap {
const XRaySledEntry *Sleds;
size_t Entries;
+ const XRayFunctionSledIndex *SledsIndex;
+ size_t Functions;
};
bool patchFunctionEntry(bool Enable, uint32_t FuncId,
diff --git a/test/asan/TestCases/Linux/longjmp_chk.c b/test/asan/TestCases/Linux/longjmp_chk.c
new file mode 100644
index 000000000000..99a4a163054c
--- /dev/null
+++ b/test/asan/TestCases/Linux/longjmp_chk.c
@@ -0,0 +1,51 @@
+// Verify that use of longjmp() in a _FORTIFY_SOURCE'd library (without ASAN)
+// is correctly intercepted such that the stack is unpoisoned.
+// Note: it is essential that the external library is not built with ASAN,
+// otherwise it would be able to unpoison the stack before use.
+//
+// RUN: %clang -DIS_LIBRARY -D_FORTIFY_SOURCE=2 -O2 %s -c -o %t.o
+// RUN: %clang_asan -O2 %s %t.o -o %t
+// RUN: %run %t
+
+#ifdef IS_LIBRARY
+/* the library */
+#include <setjmp.h>
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+
+static jmp_buf jenv;
+
+void external_callme(void (*callback)(void)) {
+ if (setjmp(jenv) == 0) {
+ callback();
+ }
+}
+
+void external_longjmp(char *msg) {
+ longjmp(jenv, 1);
+}
+
+void external_check_stack(void) {
+ char buf[256] = "";
+ for (int i = 0; i < 256; i++) {
+ assert(!__asan_address_is_poisoned(buf + i));
+ }
+}
+#else
+/* main program */
+extern void external_callme(void (*callback)(void));
+extern void external_longjmp(char *msg);
+extern void external_check_stack(void);
+
+static void callback(void) {
+ char msg[16]; /* Note: this triggers addition of a redzone. */
+ /* Note: msg is passed to prevent compiler optimization from removing it. */
+ external_longjmp(msg);
+}
+
+int main() {
+ external_callme(callback);
+ external_check_stack();
+ return 0;
+}
+#endif
diff --git a/test/builtins/Unit/divxc3_test.c b/test/builtins/Unit/divxc3_test.c
index d0cdb0169ebf..6517ef124891 100644
--- a/test/builtins/Unit/divxc3_test.c
+++ b/test/builtins/Unit/divxc3_test.c
@@ -19,6 +19,7 @@
#include <complex.h>
#include <stdio.h>
+// UNSUPPORTED: mips
// REQUIRES: c99-complex
// Returns: the quotient of (a + ib) / (c + id)
diff --git a/test/builtins/Unit/fixunstfti_test.c b/test/builtins/Unit/fixunstfti_test.c
index 019b72049dd9..eaf4b8fb5ffc 100644
--- a/test/builtins/Unit/fixunstfti_test.c
+++ b/test/builtins/Unit/fixunstfti_test.c
@@ -14,6 +14,8 @@
#include <stdio.h>
+// UNSUPPORTED: mips
+
#if __LDBL_MANT_DIG__ == 113
#include "fp_test.h"
diff --git a/test/builtins/Unit/fixunsxfti_test.c b/test/builtins/Unit/fixunsxfti_test.c
index 28a7e9783c53..0a48a7332703 100644
--- a/test/builtins/Unit/fixunsxfti_test.c
+++ b/test/builtins/Unit/fixunsxfti_test.c
@@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
+// UNSUPPORTED: mips
+
//===-- fixunsxfti_test.c - Test __fixunsxfti -----------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/fixxfti_test.c b/test/builtins/Unit/fixxfti_test.c
index c6d42c6e1310..e5e15ab780d4 100644
--- a/test/builtins/Unit/fixxfti_test.c
+++ b/test/builtins/Unit/fixxfti_test.c
@@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
+// UNSUPPORTED: mips
+
//===-- fixxfti_test.c - Test __fixxfti -----------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/floattixf_test.c b/test/builtins/Unit/floattixf_test.c
index 00644fae19c0..3de4729342d2 100644
--- a/test/builtins/Unit/floattixf_test.c
+++ b/test/builtins/Unit/floattixf_test.c
@@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
+// UNSUPPORTED: mips
+
//===-- floattixf.c - Test __floattixf ------------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/floatuntixf_test.c b/test/builtins/Unit/floatuntixf_test.c
index 70ad5f36f3f7..2d71f0f88604 100644
--- a/test/builtins/Unit/floatuntixf_test.c
+++ b/test/builtins/Unit/floatuntixf_test.c
@@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
+// UNSUPPORTED: mips
+
//===-- floatuntixf.c - Test __floatuntixf --------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/mulxc3_test.c b/test/builtins/Unit/mulxc3_test.c
index 3260b7521dec..c48b0da50692 100644
--- a/test/builtins/Unit/mulxc3_test.c
+++ b/test/builtins/Unit/mulxc3_test.c
@@ -19,6 +19,7 @@
#include <complex.h>
#include <stdio.h>
+// UNSUPPORTED: mips
// REQUIRES: c99-complex
// Returns: the product of a + ib and c + id
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc
new file mode 100644
index 000000000000..8430539829b0
--- /dev/null
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc
@@ -0,0 +1,15 @@
+// Tests -fsanitize-coverage=no-prune
+//
+// REQUIRES: has_sancovcc,stable-runtime
+// UNSUPPORTED: i386-darwin
+// XFAIL: tsan,powerpc64,s390x,mips
+//
+// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc,bb,no-prune 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 3
+// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc,bb 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 2
+// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc,no-prune 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 4
+// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 3
+
+void foo(int *a) {
+ if (a)
+ *a = 1;
+}
diff --git a/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc b/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc
new file mode 100644
index 000000000000..341fd7a823b0
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc
@@ -0,0 +1,23 @@
+// RUN: %clangxx -fsanitize=undefined -O0 %s -o %t && UBSAN_OPTIONS=stack_trace_format=DEFAULT:fast_unwind_on_fatal=1 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx -fsanitize=undefined -O0 %s -o %t && UBSAN_OPTIONS=stack_trace_format=DEFAULT:fast_unwind_on_fatal=0 %run %t 2>&1 | FileCheck %s
+
+// This test is temporarily disabled due to broken unwinding on ARM.
+// UNSUPPORTED: -linux-
+
+// The test doesn't pass on Darwin in UBSan-TSan configuration, because TSan is
+// using the slow unwinder which is not supported on Darwin. The test should
+// be universal after landing of https://reviews.llvm.org/D32806.
+
+#include <sanitizer/common_interface_defs.h>
+
+static inline void FooBarBaz() {
+ __sanitizer_print_stack_trace();
+}
+
+int main() {
+ FooBarBaz();
+ return 0;
+}
+
+// CHECK: {{.*}} in FooBarBaz{{.*}}print_stack_trace.cc{{.*}}
+// CHECK: {{.*}} in main{{.*}}print_stack_trace.cc{{.*}}
diff --git a/test/ubsan/TestCases/Misc/bool.m b/test/ubsan/TestCases/Misc/bool.m
new file mode 100644
index 000000000000..0430b452b987
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/bool.m
@@ -0,0 +1,14 @@
+// RUN: %clang -fsanitize=bool %s -O3 -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: %env_ubsan_opts=print_summary=1:report_error_type=1 not %run %t 2>&1 | FileCheck %s --check-prefix=SUMMARY
+
+typedef char BOOL;
+unsigned char NotABool = 123;
+
+int main(int argc, char **argv) {
+ BOOL *p = (BOOL*)&NotABool;
+
+ // CHECK: bool.m:[[@LINE+1]]:10: runtime error: load of value 123, which is not a valid value for type 'BOOL'
+ return *p;
+ // SUMMARY: SUMMARY: {{.*}}Sanitizer: invalid-bool-load {{.*}}bool.m:[[@LINE-1]]
+}
diff --git a/test/xray/TestCases/Linux/coverage-sample.cc b/test/xray/TestCases/Linux/coverage-sample.cc
new file mode 100644
index 000000000000..df23d9f738de
--- /dev/null
+++ b/test/xray/TestCases/Linux/coverage-sample.cc
@@ -0,0 +1,91 @@
+// Check that we can patch and unpatch specific function ids.
+//
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t | FileCheck %s
+// FIXME: When run this test case causes a segementation fault on powerpc64le.
+// Remove the xfail when the problem is fixed.
+// XFAIL: powerpc64le
+
+#include "xray/xray_interface.h"
+
+#include <set>
+#include <cstdio>
+
+std::set<int32_t> function_ids;
+
+[[clang::xray_never_instrument]] void coverage_handler(int32_t fid,
+ XRayEntryType) {
+ thread_local bool patching = false;
+ if (patching) return;
+ patching = true;
+ function_ids.insert(fid);
+ __xray_unpatch_function(fid);
+ patching = false;
+}
+
+[[clang::xray_always_instrument]] void baz() {
+ // do nothing!
+}
+
+[[clang::xray_always_instrument]] void bar() {
+ baz();
+}
+
+[[clang::xray_always_instrument]] void foo() {
+ bar();
+}
+
+[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
+ __xray_set_handler(coverage_handler);
+ __xray_patch();
+ foo();
+ __xray_unpatch();
+
+ // print out the function_ids.
+ printf("first pass.\n");
+ for (const auto id : function_ids)
+ printf("patched: %d\n", id);
+
+ // CHECK-LABEL: first pass.
+ // CHECK-DAG: patched: [[F1:.*]]
+ // CHECK-DAG: patched: [[F2:.*]]
+ // CHECK-DAG: patched: [[F3:.*]]
+
+ // make a copy of the function_ids, then patch them later.
+ auto called_fns = function_ids;
+
+ // clear the function_ids.
+ function_ids.clear();
+
+ // patch the functions we've called before.
+ for (const auto id : called_fns)
+ __xray_patch_function(id);
+
+ // then call them again.
+ foo();
+ __xray_unpatch();
+
+ // confirm that we've seen the same functions again.
+ printf("second pass.\n");
+ for (const auto id : function_ids)
+ printf("patched: %d\n", id);
+ // CHECK-LABEL: second pass.
+ // CHECK-DAG: patched: [[F1]]
+ // CHECK-DAG: patched: [[F2]]
+ // CHECK-DAG: patched: [[F3]]
+
+ // Now we want to make sure that if we unpatch one, that we're only going to
+ // see two calls of the coverage_handler.
+ function_ids.clear();
+ __xray_patch();
+ __xray_unpatch_function(1);
+ foo();
+ __xray_unpatch();
+
+ // confirm that we don't see function id one called anymore.
+ printf("missing 1.\n");
+ for (const auto id : function_ids)
+ printf("patched: %d\n", id);
+ // CHECK-LABEL: missing 1.
+ // CHECK-NOT: patched: 1
+}
diff --git a/test/xray/TestCases/Linux/func-id-utils.cc b/test/xray/TestCases/Linux/func-id-utils.cc
new file mode 100644
index 000000000000..82ba34d30acc
--- /dev/null
+++ b/test/xray/TestCases/Linux/func-id-utils.cc
@@ -0,0 +1,44 @@
+// Check that we can turn a function id to a function address, and also get the
+// maximum function id for the current binary.
+//
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t
+// FIXME: When we know why this fails in ppc, un-xfail it.
+// XFAIL: powerpc64le
+
+#include "xray/xray_interface.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <iterator>
+#include <set>
+
+[[clang::xray_always_instrument]] void bar(){}
+
+[[clang::xray_always_instrument]] void foo() {
+ bar();
+}
+
+[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
+ assert(__xray_max_function_id() != 0 && "we need xray instrumentation!");
+ std::set<void *> must_be_instrumented = {reinterpret_cast<void *>(&foo),
+ reinterpret_cast<void *>(&bar),
+ reinterpret_cast<void *>(&main)};
+ std::set<void *> all_instrumented;
+ for (auto i = __xray_max_function_id(); i != 0; --i) {
+ auto addr = __xray_function_address(i);
+ all_instrumented.insert(reinterpret_cast<void *>(addr));
+ }
+ assert(all_instrumented.size() == __xray_max_function_id() &&
+ "each function id must be assigned to a unique function");
+
+ std::set<void *> common;
+ std::set_intersection(all_instrumented.begin(), all_instrumented.end(),
+ must_be_instrumented.begin(),
+ must_be_instrumented.end(),
+ std::inserter(common, common.begin()));
+ assert(
+ common == must_be_instrumented &&
+ "we should see all explicitly instrumented functions with function ids");
+ return common == must_be_instrumented ? 0 : 1;
+}