Vendor import of compiler-rt trunk r302418:

https://llvm.org/svn/llvm-project/compiler-rt/trunk@302418
This commit is contained in:
Dimitry Andric 2017-05-08 17:13:22 +00:00
parent 285f392c55
commit 2109e2e418
36 changed files with 775 additions and 115 deletions

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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})

View File

@ -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>

View File

@ -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

View File

@ -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*

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -9,6 +9,7 @@ set(UBSAN_SOURCES
)
set(UBSAN_STANDALONE_SOURCES
ubsan_diag_standalone.cc
ubsan_init_standalone.cc
)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -132,6 +132,42 @@ 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.
@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -19,6 +19,7 @@
#include <complex.h>
#include <stdio.h>
// UNSUPPORTED: mips
// REQUIRES: c99-complex
// Returns: the quotient of (a + ib) / (c + id)

View File

@ -14,6 +14,8 @@
#include <stdio.h>
// UNSUPPORTED: mips
#if __LDBL_MANT_DIG__ == 113
#include "fp_test.h"

View File

@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
// UNSUPPORTED: mips
//===-- fixunsxfti_test.c - Test __fixunsxfti -----------------------------===//
//
// The LLVM Compiler Infrastructure

View File

@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
// UNSUPPORTED: mips
//===-- fixxfti_test.c - Test __fixxfti -----------------------------------===//
//
// The LLVM Compiler Infrastructure

View File

@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
// UNSUPPORTED: mips
//===-- floattixf.c - Test __floattixf ------------------------------------===//
//
// The LLVM Compiler Infrastructure

View File

@ -2,6 +2,8 @@
// XFAIL: aarch64
// test fails for aarch64 (see pr32260)
// UNSUPPORTED: mips
//===-- floatuntixf.c - Test __floatuntixf --------------------------------===//
//
// The LLVM Compiler Infrastructure

View File

@ -19,6 +19,7 @@
#include <complex.h>
#include <stdio.h>
// UNSUPPORTED: mips
// REQUIRES: c99-complex
// Returns: the product of a + ib and c + id

View File

@ -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;
}

View File

@ -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{{.*}}

View File

@ -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]]
}

View File

@ -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
}

View File

@ -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;
}