Vendor import of compiler-rt trunk r302418:
https://llvm.org/svn/llvm-project/compiler-rt/trunk@302418
This commit is contained in:
parent
285f392c55
commit
2109e2e418
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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
|
||||
|
|
|
@ -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_
|
|
@ -9,6 +9,7 @@ set(UBSAN_SOURCES
|
|||
)
|
||||
|
||||
set(UBSAN_STANDALONE_SOURCES
|
||||
ubsan_diag_standalone.cc
|
||||
ubsan_init_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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -19,6 +19,7 @@
|
|||
#include <complex.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
// REQUIRES: c99-complex
|
||||
|
||||
// Returns: the quotient of (a + ib) / (c + id)
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
|
||||
#if __LDBL_MANT_DIG__ == 113
|
||||
|
||||
#include "fp_test.h"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// XFAIL: aarch64
|
||||
// test fails for aarch64 (see pr32260)
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
|
||||
//===-- fixunsxfti_test.c - Test __fixunsxfti -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// XFAIL: aarch64
|
||||
// test fails for aarch64 (see pr32260)
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
|
||||
//===-- fixxfti_test.c - Test __fixxfti -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// XFAIL: aarch64
|
||||
// test fails for aarch64 (see pr32260)
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
|
||||
//===-- floattixf.c - Test __floattixf ------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// XFAIL: aarch64
|
||||
// test fails for aarch64 (see pr32260)
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
|
||||
//===-- floatuntixf.c - Test __floatuntixf --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <complex.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// UNSUPPORTED: mips
|
||||
// REQUIRES: c99-complex
|
||||
|
||||
// Returns: the product of a + ib and c + id
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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{{.*}}
|
|
@ -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]]
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue