Index: vendor/compiler-rt/dist/include/xray/xray_interface.h =================================================================== --- vendor/compiler-rt/dist/include/xray/xray_interface.h (revision 317952) +++ vendor/compiler-rt/dist/include/xray/xray_interface.h (revision 317953) @@ -1,82 +1,101 @@ //===-- xray_interface.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of XRay, a dynamic runtime instrumentation system. // // APIs for controlling XRay functionality explicitly. //===----------------------------------------------------------------------===// #ifndef XRAY_XRAY_INTERFACE_H #define XRAY_XRAY_INTERFACE_H #include +#include extern "C" { -// Synchronize this with AsmPrinter::SledKind in LLVM. +/// Synchronize this with AsmPrinter::SledKind in LLVM. enum XRayEntryType { ENTRY = 0, EXIT = 1, TAIL = 2, 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, ONGOING = 2, 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); -// 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(); +/// 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(); + } #endif Index: vendor/compiler-rt/dist/lib/asan/asan_interceptors.cc =================================================================== --- vendor/compiler-rt/dist/lib/asan/asan_interceptors.cc (revision 317952) +++ vendor/compiler-rt/dist/lib/asan/asan_interceptors.cc (revision 317953) @@ -1,794 +1,804 @@ //===-- asan_interceptors.cc ----------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // Intercept various libc functions. //===----------------------------------------------------------------------===// #include "asan_interceptors.h" #include "asan_allocator.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" #include "asan_suppressions.h" #include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_libc.h" #if SANITIZER_POSIX #include "sanitizer_common/sanitizer_posix.h" #endif #if defined(__i386) && SANITIZER_LINUX #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1" #elif defined(__mips__) && SANITIZER_LINUX #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2" #endif namespace __asan { // Return true if we can quickly decide that the region is unpoisoned. // We assume that a redzone is at least 16 bytes. static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { if (size == 0) return true; if (size <= 32) return !AddressIsPoisoned(beg) && !AddressIsPoisoned(beg + size - 1) && !AddressIsPoisoned(beg + size / 2); if (size <= 64) return !AddressIsPoisoned(beg) && !AddressIsPoisoned(beg + size / 4) && !AddressIsPoisoned(beg + size - 1) && !AddressIsPoisoned(beg + 3 * size / 4) && !AddressIsPoisoned(beg + size / 2); return false; } struct AsanInterceptorContext { const char *interceptor_name; }; // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, // and ASAN_WRITE_RANGE as macro instead of function so // that no extra frames are created, and stack trace contains // relevant information only. // We check all shadow bytes. #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \ uptr __offset = (uptr)(offset); \ uptr __size = (uptr)(size); \ uptr __bad = 0; \ if (__offset > __offset + __size) { \ GET_STACK_TRACE_FATAL_HERE; \ ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ } \ if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ (__bad = __asan_region_is_poisoned(__offset, __size))) { \ AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ bool suppressed = false; \ if (_ctx) { \ suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ if (!suppressed && HaveStackTraceBasedSuppressions()) { \ GET_STACK_TRACE_FATAL_HERE; \ suppressed = IsStackTraceSuppressed(&stack); \ } \ } \ if (!suppressed) { \ GET_CURRENT_PC_BP_SP; \ ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\ } \ } \ } while (0) // memcpy is called during __asan_init() from the internals of printf(...). // We do not treat memcpy with to==from as a bug. // See http://llvm.org/bugs/show_bug.cgi?id=11763. #define ASAN_MEMCPY_IMPL(ctx, to, from, size) \ do { \ if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \ if (asan_init_is_running) { \ return REAL(memcpy)(to, from, size); \ } \ ENSURE_ASAN_INITED(); \ if (flags()->replace_intrin) { \ if (to != from) { \ CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \ } \ ASAN_READ_RANGE(ctx, from, size); \ ASAN_WRITE_RANGE(ctx, to, size); \ } \ return REAL(memcpy)(to, from, size); \ } while (0) // memset is called inside Printf. #define ASAN_MEMSET_IMPL(ctx, block, c, size) \ do { \ if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \ if (asan_init_is_running) { \ return REAL(memset)(block, c, size); \ } \ ENSURE_ASAN_INITED(); \ if (flags()->replace_intrin) { \ ASAN_WRITE_RANGE(ctx, block, size); \ } \ return REAL(memset)(block, c, size); \ } while (0) #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ do { \ if (UNLIKELY(!asan_inited)) return internal_memmove(to, from, size); \ ENSURE_ASAN_INITED(); \ if (flags()->replace_intrin) { \ ASAN_READ_RANGE(ctx, from, size); \ ASAN_WRITE_RANGE(ctx, to, size); \ } \ return internal_memmove(to, from, size); \ } while (0) #define ASAN_READ_RANGE(ctx, offset, size) \ ACCESS_MEMORY_RANGE(ctx, offset, size, false) #define ASAN_WRITE_RANGE(ctx, offset, size) \ ACCESS_MEMORY_RANGE(ctx, offset, size, true) #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \ ASAN_READ_RANGE((ctx), (s), \ common_flags()->strict_string_checks ? (len) + 1 : (n)) #define ASAN_READ_STRING(ctx, s, n) \ ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n)) // Behavior of functions like "memcpy" or "strcpy" is undefined // if memory intervals overlap. We report error in this case. // Macro is used to avoid creation of new frames. static inline bool RangesOverlap(const char *offset1, uptr length1, const char *offset2, uptr length2) { return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); } #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ const char *offset1 = (const char*)_offset1; \ const char *offset2 = (const char*)_offset2; \ if (RangesOverlap(offset1, length1, offset2, length2)) { \ GET_STACK_TRACE_FATAL_HERE; \ ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ offset2, length2, &stack); \ } \ } while (0) static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { #if SANITIZER_INTERCEPT_STRNLEN if (REAL(strnlen)) { return REAL(strnlen)(s, maxlen); } #endif return internal_strnlen(s, maxlen); } void SetThreadName(const char *name) { AsanThread *t = GetCurrentThread(); if (t) asanThreadRegistry().SetThreadName(t->tid(), name); } int OnExit() { // FIXME: ask frontend whether we need to return failure. return 0; } } // namespace __asan // ---------------------- Wrappers ---------------- {{{1 using namespace __asan; // NOLINT DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) #define ASAN_INTERCEPTOR_ENTER(ctx, func) \ AsanInterceptorContext _ctx = {#func}; \ ctx = (void *)&_ctx; \ (void) ctx; \ #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name) #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ ASAN_INTERCEPT_FUNC_VER(name, ver) #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ ASAN_WRITE_RANGE(ctx, ptr, size) #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ ASAN_READ_RANGE(ctx, ptr, size) #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ ASAN_INTERCEPTOR_ENTER(ctx, func); \ do { \ if (asan_init_is_running) \ return REAL(func)(__VA_ARGS__); \ if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \ return REAL(func)(__VA_ARGS__); \ ENSURE_ASAN_INITED(); \ } while (false) #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ do { \ } while (false) #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ do { \ } while (false) #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ do { \ } while (false) #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ do { \ } while (false) #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name) // But asan does not remember UserId's for threads (pthread_t); // and remembers all ever existed threads, so the linear search by UserId // can be slow. #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ do { \ } while (false) #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) // Strict init-order checking is dlopen-hostile: // https://github.com/google/sanitizers/issues/178 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ do { \ if (flags()->strict_init_order) \ StopInitOrderChecking(); \ CheckNoDeepBind(filename, flag); \ } while (false) #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ CoverageUpdateMapping() #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping() #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ if (AsanThread *t = GetCurrentThread()) { \ *begin = t->tls_begin(); \ *end = t->tls_end(); \ } else { \ *begin = *end = 0; \ } #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ do { \ ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ } while (false) #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ do { \ ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ ASAN_MEMCPY_IMPL(ctx, to, from, size); \ } while (false) #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ do { \ ASAN_INTERCEPTOR_ENTER(ctx, memset); \ ASAN_MEMSET_IMPL(ctx, block, c, size); \ } while (false) #include "sanitizer_common/sanitizer_common_interceptors.inc" // Syscall interceptors don't have contexts, we don't support suppressions // for them. #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s) #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s) #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ do { \ (void)(p); \ (void)(s); \ } while (false) #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ do { \ (void)(p); \ (void)(s); \ } while (false) #include "sanitizer_common/sanitizer_common_syscalls.inc" struct ThreadStartParam { atomic_uintptr_t t; atomic_uintptr_t is_registered; }; #if ASAN_INTERCEPT_PTHREAD_CREATE static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { ThreadStartParam *param = reinterpret_cast(arg); AsanThread *t = nullptr; while ((t = reinterpret_cast( atomic_load(¶m->t, memory_order_acquire))) == nullptr) internal_sched_yield(); SetCurrentThread(t); return t->ThreadStart(GetTid(), ¶m->is_registered); } INTERCEPTOR(int, pthread_create, void *thread, void *attr, void *(*start_routine)(void*), void *arg) { EnsureMainThreadIDIsCorrect(); // Strict init-order checking is thread-hostile. if (flags()->strict_init_order) StopInitOrderChecking(); GET_STACK_TRACE_THREAD; int detached = 0; if (attr) REAL(pthread_attr_getdetachstate)(attr, &detached); ThreadStartParam param; atomic_store(¶m.t, 0, memory_order_relaxed); atomic_store(¶m.is_registered, 0, memory_order_relaxed); int result; { // Ignore all allocations made by pthread_create: thread stack/TLS may be // stored by pthread for future reuse even after thread destruction, and // the linked list it's stored in doesn't even hold valid pointers to the // objects, the latter are calculated by obscure pointer arithmetic. #if CAN_SANITIZE_LEAKS __lsan::ScopedInterceptorDisabler disabler; #endif result = REAL(pthread_create)(thread, attr, asan_thread_start, ¶m); } if (result == 0) { u32 current_tid = GetCurrentTidOrInvalid(); AsanThread *t = AsanThread::Create(start_routine, arg, current_tid, &stack, detached); atomic_store(¶m.t, reinterpret_cast(t), memory_order_release); // Wait until the AsanThread object is initialized and the ThreadRegistry // entry is in "started" state. One reason for this is that after this // interceptor exits, the child thread's stack may be the only thing holding // the |arg| pointer. This may cause LSan to report a leak if leak checking // happens at a point when the interceptor has already exited, but the stack // range for the child thread is not yet known. while (atomic_load(¶m.is_registered, memory_order_acquire) == 0) internal_sched_yield(); } return result; } INTERCEPTOR(int, pthread_join, void *t, void **arg) { return real_pthread_join(t, arg); } DEFINE_REAL_PTHREAD_FUNCTIONS #endif // ASAN_INTERCEPT_PTHREAD_CREATE #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION #if SANITIZER_ANDROID INTERCEPTOR(void*, bsd_signal, int signum, void *handler) { if (!IsHandledDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { return REAL(bsd_signal)(signum, handler); } return 0; } #endif INTERCEPTOR(void*, signal, int signum, void *handler) { if (!IsHandledDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { return REAL(signal)(signum, handler); } return nullptr; } INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) { if (!IsHandledDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { return REAL(sigaction)(signum, act, oldact); } return 0; } namespace __sanitizer { int real_sigaction(int signum, const void *act, void *oldact) { return REAL(sigaction)(signum, (const struct sigaction *)act, (struct sigaction *)oldact); } } // namespace __sanitizer #elif SANITIZER_POSIX // We need to have defined REAL(sigaction) on posix systems. DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION #if ASAN_INTERCEPT_SWAPCONTEXT static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { // Align to page size. uptr PageSize = GetPageSizeCached(); uptr bottom = stack & ~(PageSize - 1); ssize += stack - bottom; ssize = RoundUpTo(ssize, PageSize); static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) { PoisonShadow(bottom, ssize, 0); } } INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, struct ucontext_t *ucp) { static bool reported_warning = false; if (!reported_warning) { Report("WARNING: ASan doesn't fully support makecontext/swapcontext " "functions and may produce false positives in some cases!\n"); reported_warning = true; } // Clear shadow memory for new context (it may share stack // with current context). uptr stack, ssize; ReadContextStack(ucp, &stack, &ssize); ClearShadowMemoryForContextStack(stack, ssize); int res = REAL(swapcontext)(oucp, ucp); // swapcontext technically does not return, but program may swap context to // "oucp" later, that would look as if swapcontext() returned 0. // We need to clear shadow for ucp once again, as it may be in arbitrary // state. ClearShadowMemoryForContextStack(stack, ssize); return res; } #endif // ASAN_INTERCEPT_SWAPCONTEXT INTERCEPTOR(void, longjmp, void *env, int val) { __asan_handle_no_return(); REAL(longjmp)(env, val); } #if ASAN_INTERCEPT__LONGJMP INTERCEPTOR(void, _longjmp, void *env, int val) { __asan_handle_no_return(); REAL(_longjmp)(env, 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(); REAL(siglongjmp)(env, val); } #endif #if ASAN_INTERCEPT___CXA_THROW INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { CHECK(REAL(__cxa_throw)); __asan_handle_no_return(); REAL(__cxa_throw)(a, b, c); } #endif void *__asan_memcpy(void *to, const void *from, uptr size) { ASAN_MEMCPY_IMPL(nullptr, to, from, size); } void *__asan_memset(void *block, int c, uptr size) { ASAN_MEMSET_IMPL(nullptr, block, c, size); } void *__asan_memmove(void *to, const void *from, uptr size) { ASAN_MEMMOVE_IMPL(nullptr, to, from, size); } #if ASAN_INTERCEPT_INDEX # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX INTERCEPTOR(char*, index, const char *string, int c) ALIAS(WRAPPER_NAME(strchr)); # else # if SANITIZER_MAC DECLARE_REAL(char*, index, const char *string, int c) OVERRIDE_FUNCTION(index, strchr); # else DEFINE_REAL(char*, index, const char *string, int c) # endif # endif #endif // ASAN_INTERCEPT_INDEX // For both strcat() and strncat() we need to check the validity of |to| // argument irrespective of the |from| length. INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_length = REAL(strlen)(from); ASAN_READ_RANGE(ctx, from, from_length + 1); uptr to_length = REAL(strlen)(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); // If the copying actually happens, the |from| string should not overlap // with the resulting string starting at |to|, which has a length of // to_length + from_length + 1. if (from_length > 0) { CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from, from_length + 1); } } return REAL(strcat)(to, from); // NOLINT } INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncat); ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_length = MaybeRealStrnlen(from, size); uptr copy_length = Min(size, from_length + 1); ASAN_READ_RANGE(ctx, from, copy_length); uptr to_length = REAL(strlen)(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); if (from_length > 0) { CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, from, copy_length); } } return REAL(strncat)(to, from, size); } INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT #endif // strcpy is called from malloc_default_purgeable_zone() // in __asan::ReplaceSystemAlloc() on Mac. if (asan_init_is_running) { return REAL(strcpy)(to, from); // NOLINT } ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_size = REAL(strlen)(from) + 1; CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); ASAN_READ_RANGE(ctx, from, from_size); ASAN_WRITE_RANGE(ctx, to, from_size); } return REAL(strcpy)(to, from); // NOLINT } INTERCEPTOR(char*, strdup, const char *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strdup); if (UNLIKELY(!asan_inited)) return internal_strdup(s); ENSURE_ASAN_INITED(); uptr length = REAL(strlen)(s); if (flags()->replace_str) { ASAN_READ_RANGE(ctx, s, length + 1); } GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); REAL(memcpy)(new_mem, s, length + 1); return reinterpret_cast(new_mem); } #if ASAN_INTERCEPT___STRDUP INTERCEPTOR(char*, __strdup, const char *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strdup); if (UNLIKELY(!asan_inited)) return internal_strdup(s); ENSURE_ASAN_INITED(); uptr length = REAL(strlen)(s); if (flags()->replace_str) { ASAN_READ_RANGE(ctx, s, length + 1); } GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); REAL(memcpy)(new_mem, s, length + 1); return reinterpret_cast(new_mem); } #endif // ASAN_INTERCEPT___STRDUP INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, wcslen); SIZE_T length = internal_wcslen(s); if (!asan_init_is_running) { ENSURE_ASAN_INITED(); ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t)); } return length; } INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncpy); ENSURE_ASAN_INITED(); if (flags()->replace_str) { uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); ASAN_READ_RANGE(ctx, from, from_size); ASAN_WRITE_RANGE(ctx, to, size); } return REAL(strncpy)(to, from, size); } INTERCEPTOR(long, strtol, const char *nptr, // NOLINT char **endptr, int base) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strtol); ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(strtol)(nptr, endptr, base); } char *real_endptr; long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return result; } INTERCEPTOR(int, atoi, const char *nptr) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atoi); #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); #endif ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(atoi)(nptr); } char *real_endptr; // "man atoi" tells that behavior of atoi(nptr) is the same as // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the // parsed integer can't be stored in *long* type (even if it's // different from int). So, we just imitate this behavior. int result = REAL(strtol)(nptr, &real_endptr, 10); FixRealStrtolEndptr(nptr, &real_endptr); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); return result; } INTERCEPTOR(long, atol, const char *nptr) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atol); #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); #endif ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(atol)(nptr); } char *real_endptr; long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT FixRealStrtolEndptr(nptr, &real_endptr); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); return result; } #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT char **endptr, int base) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strtoll); ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(strtoll)(nptr, endptr, base); } char *real_endptr; long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return result; } INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atoll); ENSURE_ASAN_INITED(); if (!flags()->replace_str) { return REAL(atoll)(nptr); } char *real_endptr; long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT FixRealStrtolEndptr(nptr, &real_endptr); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); return result; } #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL #if ASAN_INTERCEPT___CXA_ATEXIT static void AtCxaAtexit(void *unused) { (void)unused; StopInitOrderChecking(); } INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, void *dso_handle) { #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); #endif ENSURE_ASAN_INITED(); int res = REAL(__cxa_atexit)(func, arg, dso_handle); REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); return res; } #endif // ASAN_INTERCEPT___CXA_ATEXIT #if ASAN_INTERCEPT_FORK INTERCEPTOR(int, fork, void) { ENSURE_ASAN_INITED(); if (common_flags()->coverage) CovBeforeFork(); int pid = REAL(fork)(); if (common_flags()->coverage) CovAfterFork(pid); return pid; } #endif // ASAN_INTERCEPT_FORK // ---------------------- InitializeAsanInterceptors ---------------- {{{1 namespace __asan { void InitializeAsanInterceptors() { static bool was_called_once; CHECK(!was_called_once); was_called_once = true; InitializeCommonInterceptors(); // Intercept str* functions. ASAN_INTERCEPT_FUNC(strcat); // NOLINT ASAN_INTERCEPT_FUNC(strcpy); // NOLINT ASAN_INTERCEPT_FUNC(wcslen); ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncpy); ASAN_INTERCEPT_FUNC(strdup); #if ASAN_INTERCEPT___STRDUP ASAN_INTERCEPT_FUNC(__strdup); #endif #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX ASAN_INTERCEPT_FUNC(index); #endif ASAN_INTERCEPT_FUNC(atoi); ASAN_INTERCEPT_FUNC(atol); ASAN_INTERCEPT_FUNC(strtol); #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL ASAN_INTERCEPT_FUNC(atoll); ASAN_INTERCEPT_FUNC(strtoll); #endif // Intecept signal- and jump-related functions. ASAN_INTERCEPT_FUNC(longjmp); #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION ASAN_INTERCEPT_FUNC(sigaction); #if SANITIZER_ANDROID ASAN_INTERCEPT_FUNC(bsd_signal); #endif ASAN_INTERCEPT_FUNC(signal); #endif #if ASAN_INTERCEPT_SWAPCONTEXT ASAN_INTERCEPT_FUNC(swapcontext); #endif #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 // Intercept exception handling functions. #if ASAN_INTERCEPT___CXA_THROW ASAN_INTERCEPT_FUNC(__cxa_throw); #endif // Intercept threading-related functions #if ASAN_INTERCEPT_PTHREAD_CREATE #if defined(ASAN_PTHREAD_CREATE_VERSION) ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); #else ASAN_INTERCEPT_FUNC(pthread_create); #endif ASAN_INTERCEPT_FUNC(pthread_join); #endif // Intercept atexit function. #if ASAN_INTERCEPT___CXA_ATEXIT ASAN_INTERCEPT_FUNC(__cxa_atexit); #endif #if ASAN_INTERCEPT_FORK ASAN_INTERCEPT_FUNC(fork); #endif InitializePlatformInterceptors(); VReport(1, "AddressSanitizer: libc interceptors initialized\n"); } } // namespace __asan Index: vendor/compiler-rt/dist/lib/asan/asan_interceptors.h =================================================================== --- vendor/compiler-rt/dist/lib/asan/asan_interceptors.h (revision 317952) +++ vendor/compiler-rt/dist/lib/asan/asan_interceptors.h (revision 317953) @@ -1,124 +1,130 @@ //===-- asan_interceptors.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // // ASan-private header for asan_interceptors.cc //===----------------------------------------------------------------------===// #ifndef ASAN_INTERCEPTORS_H #define ASAN_INTERCEPTORS_H #include "asan_internal.h" #include "interception/interception.h" #include "sanitizer_common/sanitizer_platform_interceptors.h" // Use macro to describe if specific function should be // intercepted on a given platform. #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1 # define ASAN_INTERCEPT__LONGJMP 1 # define ASAN_INTERCEPT_INDEX 1 # define ASAN_INTERCEPT_PTHREAD_CREATE 1 # define ASAN_INTERCEPT_FORK 1 #else # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0 # define ASAN_INTERCEPT__LONGJMP 0 # define ASAN_INTERCEPT_INDEX 0 # define ASAN_INTERCEPT_PTHREAD_CREATE 0 # define ASAN_INTERCEPT_FORK 0 #endif #if SANITIZER_FREEBSD || SANITIZER_LINUX # define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1 #else # define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0 #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID # define ASAN_INTERCEPT_SWAPCONTEXT 1 #else # define ASAN_INTERCEPT_SWAPCONTEXT 0 #endif #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1 #else # define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0 #endif #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT_SIGLONGJMP 1 #else # 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)) # define ASAN_INTERCEPT___CXA_THROW 1 #else # define ASAN_INTERCEPT___CXA_THROW 0 #endif #if !SANITIZER_WINDOWS # define ASAN_INTERCEPT___CXA_ATEXIT 1 #else # define ASAN_INTERCEPT___CXA_ATEXIT 0 #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID # define ASAN_INTERCEPT___STRDUP 1 #else # define ASAN_INTERCEPT___STRDUP 0 #endif DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size) DECLARE_REAL(void*, memcpy, void *to, const void *from, uptr size) DECLARE_REAL(void*, memset, void *block, int c, uptr size) DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(SIZE_T, strlen, const char *s) DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size) DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen) DECLARE_REAL(char*, strstr, const char *s1, const char *s2) struct sigaction; DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) #if !SANITIZER_MAC #define ASAN_INTERCEPT_FUNC(name) \ do { \ if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ } while (0) #define ASAN_INTERCEPT_FUNC_VER(name, ver) \ do { \ if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \ VReport( \ 1, "AddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \ } while (0) #else // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. #define ASAN_INTERCEPT_FUNC(name) #endif // SANITIZER_MAC namespace __asan { void InitializeAsanInterceptors(); void InitializePlatformInterceptors(); #define ENSURE_ASAN_INITED() do { \ CHECK(!asan_init_is_running); \ if (UNLIKELY(!asan_inited)) { \ AsanInitFromRtl(); \ } \ } while (0) } // namespace __asan #endif // ASAN_INTERCEPTORS_H Index: vendor/compiler-rt/dist/lib/builtins/CMakeLists.txt =================================================================== --- vendor/compiler-rt/dist/lib/builtins/CMakeLists.txt (revision 317952) +++ vendor/compiler-rt/dist/lib/builtins/CMakeLists.txt (revision 317953) @@ -1,503 +1,509 @@ # This directory contains a large amount of C code which provides # generic implementations of the core runtime library along with optimized # architecture-specific code in various subdirectories. if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) cmake_minimum_required(VERSION 3.4.3) project(CompilerRTBuiltins C ASM) set(COMPILER_RT_STANDALONE_BUILD TRUE) set(COMPILER_RT_BUILTINS_STANDALONE_BUILD TRUE) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/../../cmake" "${CMAKE_SOURCE_DIR}/../../cmake/Modules") include(base-config-ix) include(CompilerRTUtils) load_llvm_config() construct_compiler_rt_default_triple() if(APPLE) include(CompilerRTDarwinUtils) endif() include(AddCompilerRT) endif() include(builtin-config-ix) # TODO: Need to add a mechanism for logging errors when builtin source files are # added to a sub-directory and not this CMakeLists file. set(GENERIC_SOURCES absvdi2.c absvsi2.c absvti2.c adddf3.c addsf3.c addtf3.c addvdi3.c addvsi3.c addvti3.c apple_versioning.c ashldi3.c ashlti3.c ashrdi3.c ashrti3.c clear_cache.c clzdi2.c clzsi2.c clzti2.c cmpdi2.c cmpti2.c comparedf2.c comparesf2.c cpu_model.c ctzdi2.c ctzsi2.c ctzti2.c divdc3.c divdf3.c divdi3.c divmoddi4.c divmodsi4.c divsc3.c divsf3.c divsi3.c divtc3.c divti3.c divtf3.c divxc3.c enable_execute_stack.c eprintf.c extendsfdf2.c extendhfsf2.c ffsdi2.c ffssi2.c ffsti2.c fixdfdi.c fixdfsi.c fixdfti.c fixsfdi.c fixsfsi.c fixsfti.c fixunsdfdi.c fixunsdfsi.c fixunsdfti.c fixunssfdi.c fixunssfsi.c fixunssfti.c fixunsxfdi.c fixunsxfsi.c fixunsxfti.c fixxfdi.c fixxfti.c floatdidf.c floatdisf.c floatdixf.c floatsidf.c floatsisf.c floattidf.c floattisf.c floattixf.c floatundidf.c floatundisf.c floatundixf.c floatunsidf.c floatunsisf.c floatuntidf.c floatuntisf.c floatuntixf.c int_util.c lshrdi3.c lshrti3.c moddi3.c modsi3.c modti3.c muldc3.c muldf3.c muldi3.c mulodi4.c mulosi4.c muloti4.c mulsc3.c mulsf3.c multi3.c multf3.c mulvdi3.c mulvsi3.c mulvti3.c mulxc3.c negdf2.c negdi2.c negsf2.c negti2.c negvdi2.c negvsi2.c negvti2.c os_version_check.c paritydi2.c paritysi2.c parityti2.c popcountdi2.c popcountsi2.c popcountti2.c powidf2.c powisf2.c powitf2.c powixf2.c subdf3.c subsf3.c subvdi3.c subvsi3.c subvti3.c subtf3.c trampoline_setup.c truncdfhf2.c truncdfsf2.c truncsfhf2.c ucmpdi2.c ucmpti2.c udivdi3.c udivmoddi4.c udivmodsi4.c udivmodti4.c udivsi3.c udivti3.c umoddi3.c umodsi3.c 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) if(COMPILER_RT_HAS_ATOMIC_KEYWORD AND NOT COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN) set(GENERIC_SOURCES ${GENERIC_SOURCES} atomic.c) endif() if(APPLE) set(GENERIC_SOURCES ${GENERIC_SOURCES} atomic_flag_clear.c atomic_flag_clear_explicit.c atomic_flag_test_and_set.c atomic_flag_test_and_set_explicit.c atomic_signal_fence.c atomic_thread_fence.c) endif() if (HAVE_UNWIND_H) set(GENERIC_SOURCES ${GENERIC_SOURCES} gcc_personality_v0.c) endif () if (NOT MSVC) set(x86_64_SOURCES x86_64/chkstk.S x86_64/chkstk2.S x86_64/floatdidf.c x86_64/floatdisf.c x86_64/floatdixf.c x86_64/floatundidf.S x86_64/floatundisf.S x86_64/floatundixf.S ${GENERIC_SOURCES}) set(x86_64h_SOURCES ${x86_64_SOURCES}) if (WIN32) set(x86_64_SOURCES ${x86_64_SOURCES} x86_64/chkstk.S x86_64/chkstk2.S) endif() set(i386_SOURCES i386/ashldi3.S i386/ashrdi3.S i386/chkstk.S i386/chkstk2.S i386/divdi3.S i386/floatdidf.S i386/floatdisf.S i386/floatdixf.S i386/floatundidf.S i386/floatundisf.S i386/floatundixf.S i386/lshrdi3.S i386/moddi3.S i386/muldi3.S i386/udivdi3.S i386/umoddi3.S ${GENERIC_SOURCES}) if (WIN32) set(i386_SOURCES ${i386_SOURCES} i386/chkstk.S i386/chkstk2.S) endif() set(i686_SOURCES ${i386_SOURCES}) else () # MSVC # Use C versions of functions when building on MSVC # MSVC's assembler takes Intel syntax, not AT&T syntax. # Also use only MSVC compilable builtin implementations. set(x86_64_SOURCES x86_64/floatdidf.c x86_64/floatdisf.c x86_64/floatdixf.c ${GENERIC_SOURCES}) set(x86_64h_SOURCES ${x86_64_SOURCES}) set(i386_SOURCES ${GENERIC_SOURCES}) set(i686_SOURCES ${i386_SOURCES}) endif () # if (NOT MSVC) set(arm_SOURCES arm/bswapdi2.S arm/bswapsi2.S arm/clzdi2.S arm/clzsi2.S arm/comparesf2.S arm/divmodsi4.S arm/divsi3.S arm/modsi3.S arm/sync_fetch_and_add_4.S arm/sync_fetch_and_add_8.S arm/sync_fetch_and_and_4.S arm/sync_fetch_and_and_8.S arm/sync_fetch_and_max_4.S arm/sync_fetch_and_max_8.S arm/sync_fetch_and_min_4.S arm/sync_fetch_and_min_8.S arm/sync_fetch_and_nand_4.S arm/sync_fetch_and_nand_8.S arm/sync_fetch_and_or_4.S arm/sync_fetch_and_or_8.S arm/sync_fetch_and_sub_4.S arm/sync_fetch_and_sub_8.S arm/sync_fetch_and_umax_4.S arm/sync_fetch_and_umax_8.S arm/sync_fetch_and_umin_4.S arm/sync_fetch_and_umin_8.S arm/sync_fetch_and_xor_4.S arm/sync_fetch_and_xor_8.S arm/udivmodsi4.S arm/udivsi3.S arm/umodsi3.S ${GENERIC_SOURCES}) set(thumb1_SOURCES arm/divsi3.S arm/udivsi3.S arm/comparesf2.S arm/addsf3.S ${GENERIC_SOURCES}) set(arm_EABI_SOURCES arm/aeabi_cdcmp.S arm/aeabi_cdcmpeq_check_nan.c arm/aeabi_cfcmp.S arm/aeabi_cfcmpeq_check_nan.c arm/aeabi_dcmp.S arm/aeabi_div0.c arm/aeabi_drsub.c arm/aeabi_fcmp.S arm/aeabi_frsub.c arm/aeabi_idivmod.S arm/aeabi_ldivmod.S arm/aeabi_memcmp.S arm/aeabi_memcpy.S arm/aeabi_memmove.S arm/aeabi_memset.S arm/aeabi_uidivmod.S arm/aeabi_uldivmod.S) set(arm_Thumb1_JT_SOURCES arm/switch16.S arm/switch32.S arm/switch8.S arm/switchu8.S) set(arm_Thumb1_SjLj_EH_SOURCES arm/restore_vfp_d8_d15_regs.S arm/save_vfp_d8_d15_regs.S) set(arm_Thumb1_VFPv2_SOURCES arm/adddf3vfp.S arm/addsf3vfp.S arm/divdf3vfp.S arm/divsf3vfp.S arm/eqdf2vfp.S arm/eqsf2vfp.S arm/extendsfdf2vfp.S arm/fixdfsivfp.S arm/fixsfsivfp.S arm/fixunsdfsivfp.S arm/fixunssfsivfp.S arm/floatsidfvfp.S arm/floatsisfvfp.S arm/floatunssidfvfp.S arm/floatunssisfvfp.S arm/gedf2vfp.S arm/gesf2vfp.S arm/gtdf2vfp.S arm/gtsf2vfp.S arm/ledf2vfp.S arm/lesf2vfp.S arm/ltdf2vfp.S arm/ltsf2vfp.S arm/muldf3vfp.S arm/mulsf3vfp.S arm/nedf2vfp.S arm/negdf2vfp.S arm/negsf2vfp.S arm/nesf2vfp.S arm/subdf3vfp.S arm/subsf3vfp.S arm/truncdfsf2vfp.S arm/unorddf2vfp.S arm/unordsf2vfp.S) set(arm_Thumb1_icache_SOURCES arm/sync_synchronize.S) set(arm_Thumb1_SOURCES ${arm_Thumb1_JT_SOURCES} ${arm_Thumb1_SjLj_EH_SOURCES} ${arm_Thumb1_VFPv2_SOURCES} ${arm_Thumb1_icache_SOURCES}) if(MINGW) set(arm_SOURCES arm/aeabi_idivmod.S arm/aeabi_ldivmod.S arm/aeabi_uidivmod.S arm/aeabi_uldivmod.S divmoddi4.c divmodsi4.c divdi3.c divsi3.c fixdfdi.c fixsfdi.c fixunsdfdi.c fixunssfdi.c floatdidf.c floatdisf.c floatundidf.c floatundisf.c mingw_fixfloat.c moddi3.c 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 ${arm_SOURCES} ${arm_EABI_SOURCES} ${arm_Thumb1_SOURCES}) set(thumb1_SOURCES ${thumb1_SOURCES} ${arm_EABI_SOURCES}) 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}) set(armv7_SOURCES ${arm_SOURCES}) set(armv7s_SOURCES ${arm_SOURCES}) set(armv7k_SOURCES ${arm_SOURCES}) set(arm64_SOURCES ${aarch64_SOURCES}) # macho_embedded archs set(armv6m_SOURCES ${thumb1_SOURCES}) set(armv7m_SOURCES ${arm_SOURCES}) 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}) add_custom_target(builtins) set_target_properties(builtins PROPERTIES FOLDER "Compiler-RT Misc") if (APPLE) add_subdirectory(Darwin-excludes) add_subdirectory(macho_embedded) darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS}) else () set(BUILTIN_CFLAGS "") append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 BUILTIN_CFLAGS) # These flags would normally be added to CMAKE_C_FLAGS by the llvm # cmake step. Add them manually if this is a standalone build. if(COMPILER_RT_STANDALONE_BUILD) append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC BUILTIN_CFLAGS) append_list_if(COMPILER_RT_HAS_FNO_BUILTIN_FLAG -fno-builtin BUILTIN_CFLAGS) append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG -fvisibility=hidden BUILTIN_CFLAGS) if(NOT COMPILER_RT_DEBUG) append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fomit-frame-pointer BUILTIN_CFLAGS) endif() endif() set(BUILTIN_DEFS "") append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG VISIBILITY_HIDDEN BUILTIN_DEFS) foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if (CAN_TARGET_${arch}) # Filter out generic versions of routines that are re-implemented in # architecture specific manner. This prevents multiple definitions of the # same symbols, making the symbol selection non-deterministic. foreach (_file ${${arch}_SOURCES}) if (${_file} MATCHES ${arch}/*) get_filename_component(_name ${_file} NAME) string(REPLACE ".S" ".c" _cname "${_name}") list(REMOVE_ITEM ${arch}_SOURCES ${_cname}) endif () endforeach () # Needed for clear_cache on debug mode, due to r7's usage in inline asm. # Release mode already sets it via -O2/3, Debug mode doesn't. if (${arch} STREQUAL "armhf") list(APPEND BUILTIN_CFLAGS -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET) endif() add_compiler_rt_runtime(clang_rt.builtins STATIC ARCHS ${arch} SOURCES ${${arch}_SOURCES} DEFS ${BUILTIN_DEFS} CFLAGS ${BUILTIN_CFLAGS} PARENT_TARGET builtins) endif () endforeach () endif () add_dependencies(compiler-rt builtins) Index: vendor/compiler-rt/dist/lib/builtins/emutls.c =================================================================== --- vendor/compiler-rt/dist/lib/builtins/emutls.c (revision 317952) +++ vendor/compiler-rt/dist/lib/builtins/emutls.c (revision 317953) @@ -1,363 +1,363 @@ /* ===---------- emutls.c - Implements __emutls_get_address ---------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== */ #include #include #include #include "int_lib.h" #include "int_util.h" typedef struct emutls_address_array { uintptr_t size; /* number of elements in the 'data' array */ void* data[]; } emutls_address_array; static void emutls_shutdown(emutls_address_array *array); #ifndef _WIN32 #include static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t emutls_pthread_key; typedef unsigned int gcc_word __attribute__((mode(word))); typedef unsigned int gcc_pointer __attribute__((mode(pointer))); /* Default is not to use posix_memalign, so systems like Android * can use thread local data without heavier POSIX memory allocators. */ #ifndef EMUTLS_USE_POSIX_MEMALIGN #define EMUTLS_USE_POSIX_MEMALIGN 0 #endif static __inline void *emutls_memalign_alloc(size_t align, size_t size) { void *base; #if EMUTLS_USE_POSIX_MEMALIGN if (posix_memalign(&base, align, size) != 0) abort(); #else #define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void*)) char* object; if ((object = (char*)malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL) abort(); base = (void*)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES)) & ~(uintptr_t)(align - 1)); ((void**)base)[-1] = object; #endif return base; } static __inline void emutls_memalign_free(void *base) { #if EMUTLS_USE_POSIX_MEMALIGN free(base); #else /* The mallocated address is in ((void**)base)[-1] */ free(((void**)base)[-1]); #endif } static void emutls_key_destructor(void* ptr) { emutls_shutdown((emutls_address_array*)ptr); free(ptr); } static __inline void emutls_init(void) { if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0) abort(); } static __inline void emutls_init_once(void) { static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once(&once, emutls_init); } static __inline void emutls_lock() { pthread_mutex_lock(&emutls_mutex); } static __inline void emutls_unlock() { pthread_mutex_unlock(&emutls_mutex); } static __inline void emutls_setspecific(emutls_address_array *value) { pthread_setspecific(emutls_pthread_key, (void*) value); } static __inline emutls_address_array* emutls_getspecific() { return (emutls_address_array*) pthread_getspecific(emutls_pthread_key); } #else -#include +#include #include #include #include #include static LPCRITICAL_SECTION emutls_mutex; static DWORD emutls_tls_index = TLS_OUT_OF_INDEXES; typedef uintptr_t gcc_word; typedef void * gcc_pointer; static void win_error(DWORD last_err, const char *hint) { char *buffer = NULL; if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, last_err, 0, (LPSTR)&buffer, 1, NULL)) { fprintf(stderr, "Windows error: %s\n", buffer); } else { fprintf(stderr, "Unkown Windows error: %s\n", hint); } LocalFree(buffer); } static __inline void win_abort(DWORD last_err, const char *hint) { win_error(last_err, hint); abort(); } static __inline void *emutls_memalign_alloc(size_t align, size_t size) { void *base = _aligned_malloc(size, align); if (!base) win_abort(GetLastError(), "_aligned_malloc"); return base; } static __inline void emutls_memalign_free(void *base) { _aligned_free(base); } static void emutls_exit(void) { if (emutls_mutex) { DeleteCriticalSection(emutls_mutex); _aligned_free(emutls_mutex); emutls_mutex = NULL; } if (emutls_tls_index != TLS_OUT_OF_INDEXES) { emutls_shutdown((emutls_address_array*)TlsGetValue(emutls_tls_index)); TlsFree(emutls_tls_index); emutls_tls_index = TLS_OUT_OF_INDEXES; } } #pragma warning (push) #pragma warning (disable : 4100) static BOOL CALLBACK emutls_init(PINIT_ONCE p0, PVOID p1, PVOID *p2) { emutls_mutex = (LPCRITICAL_SECTION)_aligned_malloc(sizeof(CRITICAL_SECTION), 16); if (!emutls_mutex) { win_error(GetLastError(), "_aligned_malloc"); return FALSE; } InitializeCriticalSection(emutls_mutex); emutls_tls_index = TlsAlloc(); if (emutls_tls_index == TLS_OUT_OF_INDEXES) { emutls_exit(); win_error(GetLastError(), "TlsAlloc"); return FALSE; } atexit(&emutls_exit); return TRUE; } static __inline void emutls_init_once(void) { static INIT_ONCE once; InitOnceExecuteOnce(&once, emutls_init, NULL, NULL); } static __inline void emutls_lock() { EnterCriticalSection(emutls_mutex); } static __inline void emutls_unlock() { LeaveCriticalSection(emutls_mutex); } static __inline void emutls_setspecific(emutls_address_array *value) { if (TlsSetValue(emutls_tls_index, (LPVOID) value) == 0) win_abort(GetLastError(), "TlsSetValue"); } static __inline emutls_address_array* emutls_getspecific() { LPVOID value = TlsGetValue(emutls_tls_index); if (value == NULL) { const DWORD err = GetLastError(); if (err != ERROR_SUCCESS) win_abort(err, "TlsGetValue"); } return (emutls_address_array*) value; } /* Provide atomic load/store functions for emutls_get_index if built with MSVC. */ #if !defined(__ATOMIC_RELEASE) enum { __ATOMIC_ACQUIRE = 2, __ATOMIC_RELEASE = 3 }; static __inline uintptr_t __atomic_load_n(void *ptr, unsigned type) { assert(type == __ATOMIC_ACQUIRE); #ifdef _WIN64 return (uintptr_t) _load_be_u64(ptr); #else return (uintptr_t) _load_be_u32(ptr); #endif } static __inline void __atomic_store_n(void *ptr, uintptr_t val, unsigned type) { assert(type == __ATOMIC_RELEASE); #ifdef _WIN64 _store_be_u64(ptr, val); #else _store_be_u32(ptr, val); #endif } #endif #pragma warning (pop) #endif static size_t emutls_num_object = 0; /* number of allocated TLS objects */ /* Free the allocated TLS data */ static void emutls_shutdown(emutls_address_array *array) { if (array) { uintptr_t i; for (i = 0; i < array->size; ++i) { if (array->data[i]) emutls_memalign_free(array->data[i]); } } } /* For every TLS variable xyz, * there is one __emutls_control variable named __emutls_v.xyz. * If xyz has non-zero initial value, __emutls_v.xyz's "value" * will point to __emutls_t.xyz, which has the initial value. */ typedef struct __emutls_control { /* Must use gcc_word here, instead of size_t, to match GCC. When gcc_word is larger than size_t, the upper extra bits are all zeros. We can use variables of size_t to operate on size and align. */ gcc_word size; /* size of the object in bytes */ gcc_word align; /* alignment of the object in bytes */ union { uintptr_t index; /* data[index-1] is the object address */ void* address; /* object address, when in single thread env */ } object; void* value; /* null or non-zero initial value for the object */ } __emutls_control; /* Emulated TLS objects are always allocated at run-time. */ static __inline void *emutls_allocate_object(__emutls_control *control) { /* Use standard C types, check with gcc's emutls.o. */ COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer)); COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void*)); size_t size = control->size; size_t align = control->align; void* base; if (align < sizeof(void*)) align = sizeof(void*); /* Make sure that align is power of 2. */ if ((align & (align - 1)) != 0) abort(); base = emutls_memalign_alloc(align, size); if (control->value) memcpy(base, control->value, size); else memset(base, 0, size); return base; } /* Returns control->object.index; set index if not allocated yet. */ static __inline uintptr_t emutls_get_index(__emutls_control *control) { uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE); if (!index) { emutls_init_once(); emutls_lock(); index = control->object.index; if (!index) { index = ++emutls_num_object; __atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE); } emutls_unlock(); } return index; } /* Updates newly allocated thread local emutls_address_array. */ static __inline void emutls_check_array_set_size(emutls_address_array *array, uintptr_t size) { if (array == NULL) abort(); array->size = size; emutls_setspecific(array); } /* Returns the new 'data' array size, number of elements, * which must be no smaller than the given index. */ static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) { /* Need to allocate emutls_address_array with one extra slot * to store the data array size. * Round up the emutls_address_array size to multiple of 16. */ return ((index + 1 + 15) & ~((uintptr_t)15)) - 1; } /* Returns the size in bytes required for an emutls_address_array with * N number of elements for data field. */ static __inline uintptr_t emutls_asize(uintptr_t N) { return N * sizeof(void *) + sizeof(emutls_address_array); } /* Returns the thread local emutls_address_array. * Extends its size if necessary to hold address at index. */ static __inline emutls_address_array * emutls_get_address_array(uintptr_t index) { emutls_address_array* array = emutls_getspecific(); if (array == NULL) { uintptr_t new_size = emutls_new_data_array_size(index); array = (emutls_address_array*) malloc(emutls_asize(new_size)); if (array) memset(array->data, 0, new_size * sizeof(void*)); emutls_check_array_set_size(array, new_size); } else if (index > array->size) { uintptr_t orig_size = array->size; uintptr_t new_size = emutls_new_data_array_size(index); array = (emutls_address_array*) realloc(array, emutls_asize(new_size)); if (array) memset(array->data + orig_size, 0, (new_size - orig_size) * sizeof(void*)); emutls_check_array_set_size(array, new_size); } return array; } void* __emutls_get_address(__emutls_control* control) { uintptr_t index = emutls_get_index(control); emutls_address_array* array = emutls_get_address_array(index--); if (array->data[index] == NULL) array->data[index] = emutls_allocate_object(control); return array->data[index]; } Index: vendor/compiler-rt/dist/lib/builtins/int_types.h =================================================================== --- vendor/compiler-rt/dist/lib/builtins/int_types.h (revision 317952) +++ vendor/compiler-rt/dist/lib/builtins/int_types.h (revision 317953) @@ -1,166 +1,164 @@ /* ===-- int_lib.h - configuration header for compiler-rt -----------------=== * * The LLVM Compiler Infrastructure * * This file is dual licensed under the MIT and the University of Illinois Open * Source Licenses. See LICENSE.TXT for details. * * ===----------------------------------------------------------------------=== * * This file is not part of the interface of this library. * * This file defines various standard types, most importantly a number of unions * used to access parts of larger types. * * ===----------------------------------------------------------------------=== */ #ifndef INT_TYPES_H #define INT_TYPES_H #include "int_endianness.h" /* si_int is defined in Linux sysroot's asm-generic/siginfo.h */ #ifdef si_int #undef si_int #endif typedef int si_int; typedef unsigned su_int; typedef long long di_int; typedef unsigned long long du_int; typedef union { di_int all; struct { #if _YUGA_LITTLE_ENDIAN su_int low; si_int high; #else si_int high; su_int low; #endif /* _YUGA_LITTLE_ENDIAN */ }s; } dwords; typedef union { du_int all; struct { #if _YUGA_LITTLE_ENDIAN su_int low; su_int high; #else su_int high; su_int low; #endif /* _YUGA_LITTLE_ENDIAN */ }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 #ifdef CRT_HAS_128BIT typedef int ti_int __attribute__ ((mode (TI))); typedef unsigned tu_int __attribute__ ((mode (TI))); typedef union { ti_int all; struct { #if _YUGA_LITTLE_ENDIAN du_int low; di_int high; #else di_int high; du_int low; #endif /* _YUGA_LITTLE_ENDIAN */ }s; } twords; typedef union { tu_int all; struct { #if _YUGA_LITTLE_ENDIAN du_int low; du_int high; #else du_int high; du_int low; #endif /* _YUGA_LITTLE_ENDIAN */ }s; } utwords; static __inline ti_int make_ti(di_int h, di_int l) { twords r; r.s.high = h; r.s.low = l; return r.all; } static __inline tu_int make_tu(du_int h, du_int l) { utwords r; r.s.high = h; r.s.low = l; return r.all; } #endif /* CRT_HAS_128BIT */ typedef union { su_int u; float f; } float_bits; typedef union { udwords u; double f; } double_bits; typedef struct { #if _YUGA_LITTLE_ENDIAN udwords low; udwords high; #else udwords high; udwords low; #endif /* _YUGA_LITTLE_ENDIAN */ } uqwords; typedef union { uqwords u; long double f; } long_double_bits; #if __STDC_VERSION__ >= 199901L typedef float _Complex Fcomplex; typedef double _Complex Dcomplex; typedef long double _Complex Lcomplex; #define COMPLEX_REAL(x) __real__(x) #define COMPLEX_IMAGINARY(x) __imag__(x) #else typedef struct { float real, imaginary; } Fcomplex; typedef struct { double real, imaginary; } Dcomplex; typedef struct { long double real, imaginary; } Lcomplex; #define COMPLEX_REAL(x) (x).real #define COMPLEX_IMAGINARY(x) (x).imaginary #endif #endif /* INT_TYPES_H */ Index: vendor/compiler-rt/dist/lib/cfi/cfi_blacklist.txt =================================================================== --- vendor/compiler-rt/dist/lib/cfi/cfi_blacklist.txt (revision 317952) +++ vendor/compiler-rt/dist/lib/cfi/cfi_blacklist.txt (revision 317953) @@ -1,26 +1,31 @@ # Standard library types. type:std::* # The stdext namespace contains Microsoft standard library extensions. type:stdext::* # Types with a uuid attribute, i.e. COM types. type:attr:uuid # STL allocators (T *allocator::allocate(size_type, const void*)). # The type signature mandates a cast from uninitialized void* to T*. # size_type can either be unsigned int (j) or unsigned long (m). fun:*8allocateEjPKv fun:*8allocateEmPKv # std::get_temporary_buffer, likewise (libstdc++, libc++). fun:_ZSt20get_temporary_buffer* fun:_ZNSt3__120get_temporary_buffer* # STL address-of magic (libstdc++, libc++). fun:*__addressof* 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::construct. +fun:_ZNSt23_Sp_counted_ptr_inplace* Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.h =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.h (revision 317952) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.h (nonexistent) @@ -1,48 +0,0 @@ -//===-- scudo_tls_linux.h ---------------------------------------*- 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 platforms -/// supporting thread_local. -/// -//===----------------------------------------------------------------------===// - -#ifndef SCUDO_TLS_LINUX_H_ -#define SCUDO_TLS_LINUX_H_ - -#ifndef SCUDO_TLS_H_ -# error "This file must be included inside scudo_tls.h." -#endif // SCUDO_TLS_H_ - -#include "sanitizer_common/sanitizer_platform.h" - -#if SANITIZER_LINUX - -enum ThreadState : u8 { - ThreadNotInitialized = 0, - ThreadInitialized, - ThreadTornDown, -}; -extern thread_local ThreadState ScudoThreadState; -extern thread_local ScudoThreadContext ThreadLocalContext; - -ALWAYS_INLINE void initThreadMaybe() { - if (LIKELY(ScudoThreadState != ThreadNotInitialized)) - return; - initThread(); -} - -ALWAYS_INLINE ScudoThreadContext *getThreadContext() { - if (UNLIKELY(ScudoThreadState == ThreadTornDown)) - return nullptr; - return &ThreadLocalContext; -} - -#endif // SANITIZER_LINUX - -#endif // SCUDO_TLS_LINUX_H_ Property changes on: vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/scudo/CMakeLists.txt =================================================================== --- vendor/compiler-rt/dist/lib/scudo/CMakeLists.txt (revision 317952) +++ vendor/compiler-rt/dist/lib/scudo/CMakeLists.txt (revision 317953) @@ -1,43 +1,44 @@ add_compiler_rt_component(scudo) include_directories(..) set(SCUDO_CFLAGS ${SANITIZER_COMMON_CFLAGS}) # SANITIZER_COMMON_CFLAGS include -fno-builtin, but we actually want builtins! list(APPEND SCUDO_CFLAGS -fbuiltin) append_rtti_flag(OFF SCUDO_CFLAGS) set(SCUDO_SOURCES scudo_allocator.cpp scudo_flags.cpp scudo_crc32.cpp scudo_interceptors.cpp scudo_new_delete.cpp scudo_termination.cpp + scudo_tls_android.cpp scudo_tls_linux.cpp scudo_utils.cpp) # Enable the SSE 4.2 instruction set for scudo_crc32.cpp, if available. if (COMPILER_RT_HAS_MSSE4_2_FLAG) set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -msse4.2) endif() # Enable the AArch64 CRC32 feature for scudo_crc32.cpp, if available. # Note that it is enabled by default starting with armv8.1-a. if (COMPILER_RT_HAS_MCRC_FLAG) set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -mcrc) endif() if(COMPILER_RT_HAS_SCUDO) foreach(arch ${SCUDO_SUPPORTED_ARCH}) add_compiler_rt_runtime(clang_rt.scudo STATIC ARCHS ${arch} SOURCES ${SCUDO_SOURCES} $ $ $ CFLAGS ${SCUDO_CFLAGS} PARENT_TARGET scudo) endforeach() endif() Index: vendor/compiler-rt/dist/lib/scudo/scudo_allocator.cpp =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_allocator.cpp (revision 317952) +++ vendor/compiler-rt/dist/lib/scudo/scudo_allocator.cpp (revision 317953) @@ -1,705 +1,708 @@ //===-- scudo_allocator.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// Scudo Hardened Allocator implementation. /// It uses the sanitizer_common allocator as a base and aims at mitigating /// heap corruption vulnerabilities. It provides a checksum-guarded chunk /// header, a delayed free list, and additional sanity checks. /// //===----------------------------------------------------------------------===// #include "scudo_allocator.h" #include "scudo_tls.h" #include "scudo_utils.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_quarantine.h" #include #include #include namespace __scudo { // Global static cookie, initialized at start-up. static uptr Cookie; // We default to software CRC32 if the alternatives are not supported, either // at compilation or at runtime. static atomic_uint8_t HashAlgorithm = { CRC32Software }; SANITIZER_WEAK_ATTRIBUTE u32 computeHardwareCRC32(u32 Crc, uptr Data); INLINE u32 computeCRC32(u32 Crc, uptr Data, u8 HashType) { // If SSE4.2 is defined here, it was enabled everywhere, as opposed to only // for scudo_crc32.cpp. This means that other SSE instructions were likely // emitted at other places, and as a result there is no reason to not use // the hardware version of the CRC32. #if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) return computeHardwareCRC32(Crc, Data); #else if (computeHardwareCRC32 && HashType == CRC32Hardware) return computeHardwareCRC32(Crc, Data); else return computeSoftwareCRC32(Crc, Data); #endif // defined(__SSE4_2__) } static ScudoBackendAllocator &getBackendAllocator(); struct ScudoChunk : UnpackedHeader { // We can't use the offset member of the chunk itself, as we would double // fetch it without any warranty that it wouldn't have been tampered. To // prevent this, we work with a local copy of the header. void *getAllocBeg(UnpackedHeader *Header) { return reinterpret_cast( reinterpret_cast(this) - (Header->Offset << MinAlignmentLog)); } // Returns the usable size for a chunk, meaning the amount of bytes from the // beginning of the user data to the end of the backend allocated chunk. uptr getUsableSize(UnpackedHeader *Header) { uptr Size = getBackendAllocator().GetActuallyAllocatedSize( getAllocBeg(Header)); if (Size == 0) return 0; return Size - AlignedChunkHeaderSize - (Header->Offset << MinAlignmentLog); } // Compute the checksum of the Chunk pointer and its ChunkHeader. u16 computeChecksum(UnpackedHeader *Header) const { UnpackedHeader ZeroChecksumHeader = *Header; ZeroChecksumHeader.Checksum = 0; uptr HeaderHolder[sizeof(UnpackedHeader) / sizeof(uptr)]; memcpy(&HeaderHolder, &ZeroChecksumHeader, sizeof(HeaderHolder)); u8 HashType = atomic_load_relaxed(&HashAlgorithm); u32 Crc = computeCRC32(Cookie, reinterpret_cast(this), HashType); for (uptr i = 0; i < ARRAY_SIZE(HeaderHolder); i++) Crc = computeCRC32(Crc, HeaderHolder[i], HashType); return static_cast(Crc); } // Checks the validity of a chunk by verifying its checksum. It doesn't // incur termination in the event of an invalid chunk. bool isValid() { UnpackedHeader NewUnpackedHeader; const AtomicPackedHeader *AtomicHeader = reinterpret_cast(this); PackedHeader NewPackedHeader = atomic_load_relaxed(AtomicHeader); NewUnpackedHeader = bit_cast(NewPackedHeader); return (NewUnpackedHeader.Checksum == computeChecksum(&NewUnpackedHeader)); } // Nulls out a chunk header. When returning the chunk to the backend, there // is no need to store a valid ChunkAvailable header, as this would be // computationally expensive. Zeroing out serves the same purpose by making // the header invalid. In the extremely rare event where 0 would be a valid // checksum for the chunk, the state of the chunk is ChunkAvailable anyway. COMPILER_CHECK(ChunkAvailable == 0); void eraseHeader() { PackedHeader NullPackedHeader = 0; AtomicPackedHeader *AtomicHeader = reinterpret_cast(this); atomic_store_relaxed(AtomicHeader, NullPackedHeader); } // Loads and unpacks the header, verifying the checksum in the process. void loadHeader(UnpackedHeader *NewUnpackedHeader) const { const AtomicPackedHeader *AtomicHeader = reinterpret_cast(this); PackedHeader NewPackedHeader = atomic_load_relaxed(AtomicHeader); *NewUnpackedHeader = bit_cast(NewPackedHeader); if (UNLIKELY(NewUnpackedHeader->Checksum != computeChecksum(NewUnpackedHeader))) { dieWithMessage("ERROR: corrupted chunk header at address %p\n", this); } } // Packs and stores the header, computing the checksum in the process. void storeHeader(UnpackedHeader *NewUnpackedHeader) { NewUnpackedHeader->Checksum = computeChecksum(NewUnpackedHeader); PackedHeader NewPackedHeader = bit_cast(*NewUnpackedHeader); AtomicPackedHeader *AtomicHeader = reinterpret_cast(this); atomic_store_relaxed(AtomicHeader, NewPackedHeader); } // Packs and stores the header, computing the checksum in the process. We // compare the current header with the expected provided one to ensure that // we are not being raced by a corruption occurring in another thread. void compareExchangeHeader(UnpackedHeader *NewUnpackedHeader, UnpackedHeader *OldUnpackedHeader) { NewUnpackedHeader->Checksum = computeChecksum(NewUnpackedHeader); PackedHeader NewPackedHeader = bit_cast(*NewUnpackedHeader); PackedHeader OldPackedHeader = bit_cast(*OldUnpackedHeader); AtomicPackedHeader *AtomicHeader = reinterpret_cast(this); if (UNLIKELY(!atomic_compare_exchange_strong(AtomicHeader, &OldPackedHeader, NewPackedHeader, memory_order_relaxed))) { dieWithMessage("ERROR: race on chunk header at address %p\n", this); } } }; ScudoChunk *getScudoChunk(uptr UserBeg) { return reinterpret_cast(UserBeg - AlignedChunkHeaderSize); } struct AllocatorOptions { u32 QuarantineSizeMb; u32 ThreadLocalQuarantineSizeKb; bool MayReturnNull; s32 ReleaseToOSIntervalMs; bool DeallocationTypeMismatch; bool DeleteSizeMismatch; bool ZeroContents; void setFrom(const Flags *f, const CommonFlags *cf); void copyTo(Flags *f, CommonFlags *cf) const; }; void AllocatorOptions::setFrom(const Flags *f, const CommonFlags *cf) { MayReturnNull = cf->allocator_may_return_null; ReleaseToOSIntervalMs = cf->allocator_release_to_os_interval_ms; QuarantineSizeMb = f->QuarantineSizeMb; ThreadLocalQuarantineSizeKb = f->ThreadLocalQuarantineSizeKb; DeallocationTypeMismatch = f->DeallocationTypeMismatch; DeleteSizeMismatch = f->DeleteSizeMismatch; ZeroContents = f->ZeroContents; } void AllocatorOptions::copyTo(Flags *f, CommonFlags *cf) const { cf->allocator_may_return_null = MayReturnNull; cf->allocator_release_to_os_interval_ms = ReleaseToOSIntervalMs; f->QuarantineSizeMb = QuarantineSizeMb; f->ThreadLocalQuarantineSizeKb = ThreadLocalQuarantineSizeKb; f->DeallocationTypeMismatch = DeallocationTypeMismatch; f->DeleteSizeMismatch = DeleteSizeMismatch; f->ZeroContents = ZeroContents; } static void initScudoInternal(const AllocatorOptions &Options); static bool ScudoInitIsRunning = false; void initScudo() { SanitizerToolName = "Scudo"; CHECK(!ScudoInitIsRunning && "Scudo init calls itself!"); ScudoInitIsRunning = true; // Check is SSE4.2 is supported, if so, opt for the CRC32 hardware version. if (testCPUFeature(CRC32CPUFeature)) { atomic_store_relaxed(&HashAlgorithm, CRC32Hardware); } initFlags(); AllocatorOptions Options; Options.setFrom(getFlags(), common_flags()); initScudoInternal(Options); // TODO(kostyak): determine if MaybeStartBackgroudThread could be of some use. ScudoInitIsRunning = false; } struct QuarantineCallback { explicit QuarantineCallback(AllocatorCache *Cache) : Cache_(Cache) {} // Chunk recycling function, returns a quarantined chunk to the backend. void Recycle(ScudoChunk *Chunk) { UnpackedHeader Header; Chunk->loadHeader(&Header); if (UNLIKELY(Header.State != ChunkQuarantine)) { dieWithMessage("ERROR: invalid chunk state when recycling address %p\n", Chunk); } Chunk->eraseHeader(); void *Ptr = Chunk->getAllocBeg(&Header); getBackendAllocator().Deallocate(Cache_, Ptr); } /// Internal quarantine allocation and deallocation functions. void *Allocate(uptr Size) { // TODO(kostyak): figure out the best way to protect the batches. return getBackendAllocator().Allocate(Cache_, Size, MinAlignment); } void Deallocate(void *Ptr) { getBackendAllocator().Deallocate(Cache_, Ptr); } AllocatorCache *Cache_; }; typedef Quarantine ScudoQuarantine; typedef ScudoQuarantine::Cache ScudoQuarantineCache; COMPILER_CHECK(sizeof(ScudoQuarantineCache) <= sizeof(ScudoThreadContext::QuarantineCachePlaceHolder)); AllocatorCache *getAllocatorCache(ScudoThreadContext *ThreadContext) { return &ThreadContext->Cache; } ScudoQuarantineCache *getQuarantineCache(ScudoThreadContext *ThreadContext) { return reinterpret_cast< ScudoQuarantineCache *>(ThreadContext->QuarantineCachePlaceHolder); } Xorshift128Plus *getPrng(ScudoThreadContext *ThreadContext) { return &ThreadContext->Prng; } struct ScudoAllocator { static const uptr MaxAllowedMallocSize = FIRST_32_SECOND_64(2UL << 30, 1ULL << 40); ScudoBackendAllocator BackendAllocator; ScudoQuarantine AllocatorQuarantine; // The fallback caches are used when the thread local caches have been // 'detroyed' on thread tear-down. They are protected by a Mutex as they can // be accessed by different threads. StaticSpinMutex FallbackMutex; AllocatorCache FallbackAllocatorCache; ScudoQuarantineCache FallbackQuarantineCache; Xorshift128Plus FallbackPrng; bool DeallocationTypeMismatch; bool ZeroContents; bool DeleteSizeMismatch; explicit ScudoAllocator(LinkerInitialized) : AllocatorQuarantine(LINKER_INITIALIZED), FallbackQuarantineCache(LINKER_INITIALIZED) {} void init(const AllocatorOptions &Options) { // Verify that the header offset field can hold the maximum offset. In the // case of the Secondary allocator, it takes care of alignment and the // offset will always be 0. In the case of the Primary, the worst case // scenario happens in the last size class, when the backend allocation // would already be aligned on the requested alignment, which would happen // to be the maximum alignment that would fit in that size class. As a // result, the maximum offset will be at most the maximum alignment for the // last size class minus the header size, in multiples of MinAlignment. UnpackedHeader Header = {}; uptr MaxPrimaryAlignment = 1 << MostSignificantSetBitIndex( SizeClassMap::kMaxSize - MinAlignment); uptr MaxOffset = (MaxPrimaryAlignment - AlignedChunkHeaderSize) >> MinAlignmentLog; Header.Offset = MaxOffset; if (Header.Offset != MaxOffset) { dieWithMessage("ERROR: the maximum possible offset doesn't fit in the " "header\n"); } // Verify that we can fit the maximum size or amount of unused bytes in the // header. Given that the Secondary fits the allocation to a page, the worst // case scenario happens in the Primary. It will depend on the second to // last and last class sizes, as well as the dynamic base for the Primary. // The following is an over-approximation that works for our needs. uptr MaxSizeOrUnusedBytes = SizeClassMap::kMaxSize - 1; Header.SizeOrUnusedBytes = MaxSizeOrUnusedBytes; if (Header.SizeOrUnusedBytes != MaxSizeOrUnusedBytes) { dieWithMessage("ERROR: the maximum possible unused bytes doesn't fit in " "the header\n"); } DeallocationTypeMismatch = Options.DeallocationTypeMismatch; DeleteSizeMismatch = Options.DeleteSizeMismatch; ZeroContents = Options.ZeroContents; BackendAllocator.Init(Options.MayReturnNull, Options.ReleaseToOSIntervalMs); AllocatorQuarantine.Init( static_cast(Options.QuarantineSizeMb) << 20, static_cast(Options.ThreadLocalQuarantineSizeKb) << 10); BackendAllocator.InitCache(&FallbackAllocatorCache); FallbackPrng.initFromURandom(); Cookie = FallbackPrng.getNext(); } // Helper function that checks for a valid Scudo chunk. nullptr isn't. bool isValidPointer(const void *UserPtr) { initThreadMaybe(); if (!UserPtr) return false; uptr UserBeg = reinterpret_cast(UserPtr); if (!IsAligned(UserBeg, MinAlignment)) return false; return getScudoChunk(UserBeg)->isValid(); } // Allocates a chunk. void *allocate(uptr Size, uptr Alignment, AllocType Type, bool ForceZeroContents = false) { initThreadMaybe(); if (UNLIKELY(!IsPowerOfTwo(Alignment))) { dieWithMessage("ERROR: alignment is not a power of 2\n"); } if (Alignment > MaxAlignment) return BackendAllocator.ReturnNullOrDieOnBadRequest(); if (Alignment < MinAlignment) Alignment = MinAlignment; if (Size >= MaxAllowedMallocSize) return BackendAllocator.ReturnNullOrDieOnBadRequest(); if (Size == 0) Size = 1; uptr NeededSize = RoundUpTo(Size, MinAlignment) + AlignedChunkHeaderSize; if (Alignment > MinAlignment) NeededSize += Alignment; if (NeededSize >= MaxAllowedMallocSize) return BackendAllocator.ReturnNullOrDieOnBadRequest(); // Primary backed and Secondary backed allocations have a different // treatment. We deal with alignment requirements of Primary serviced // allocations here, but the Secondary will take care of its own alignment // needs, which means we also have to work around some limitations of the // combined allocator to accommodate the situation. bool FromPrimary = PrimaryAllocator::CanAllocate(NeededSize, MinAlignment); 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(); Ptr = BackendAllocator.Allocate(&FallbackAllocatorCache, NeededSize, AllocationAlignment); } if (!Ptr) return BackendAllocator.ReturnNullOrDieOnOOM(); uptr AllocBeg = reinterpret_cast(Ptr); // If the allocation was serviced by the secondary, the returned pointer // accounts for ChunkHeaderSize to pass the alignment check of the combined // allocator. Adjust it here. if (!FromPrimary) { AllocBeg -= AlignedChunkHeaderSize; if (Alignment > MinAlignment) NeededSize -= Alignment; } // If requested, we will zero out the entire contents of the returned chunk. if ((ForceZeroContents || ZeroContents) && FromPrimary) memset(Ptr, 0, BackendAllocator.GetActuallyAllocatedSize(Ptr)); uptr UserBeg = AllocBeg + AlignedChunkHeaderSize; if (!IsAligned(UserBeg, Alignment)) UserBeg = RoundUpTo(UserBeg, Alignment); CHECK_LE(UserBeg + Size, AllocBeg + NeededSize); UnpackedHeader Header = {}; Header.State = ChunkAllocated; uptr Offset = UserBeg - AlignedChunkHeaderSize - AllocBeg; Header.Offset = Offset >> MinAlignmentLog; Header.AllocType = Type; if (FromPrimary) { Header.FromPrimary = FromPrimary; Header.SizeOrUnusedBytes = Size; } else { // The secondary fits the allocations to a page, so the amount of unused // bytes is the difference between the end of the user allocation and the // next page boundary. uptr PageSize = GetPageSizeCached(); uptr TrailingBytes = (UserBeg + Size) & (PageSize - 1); if (TrailingBytes) Header.SizeOrUnusedBytes = PageSize - TrailingBytes; } Header.Salt = static_cast(Salt); getScudoChunk(UserBeg)->storeHeader(&Header); void *UserPtr = reinterpret_cast(UserBeg); // if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(UserPtr, Size); return UserPtr; } // Place a chunk in the quarantine. In the event of a zero-sized quarantine, // we directly deallocate the chunk, otherwise the flow would lead to the // chunk being loaded (and checked) twice, and stored (and checksummed) once, // with no additional security value. void quarantineOrDeallocateChunk(ScudoChunk *Chunk, UnpackedHeader *Header, uptr Size) { bool BypassQuarantine = (AllocatorQuarantine.GetCacheSize() == 0); 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); } } else { 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, QuarantineCallback(&FallbackAllocatorCache), Chunk, Size); } } } // Deallocates a Chunk, which means adding it to the delayed free list (or // Quarantine). void deallocate(void *UserPtr, uptr DeleteSize, AllocType Type) { initThreadMaybe(); // if (&__sanitizer_free_hook) __sanitizer_free_hook(UserPtr); if (!UserPtr) return; uptr UserBeg = reinterpret_cast(UserPtr); if (UNLIKELY(!IsAligned(UserBeg, MinAlignment))) { dieWithMessage("ERROR: attempted to deallocate a chunk not properly " "aligned at address %p\n", UserPtr); } ScudoChunk *Chunk = getScudoChunk(UserBeg); UnpackedHeader OldHeader; Chunk->loadHeader(&OldHeader); if (UNLIKELY(OldHeader.State != ChunkAllocated)) { dieWithMessage("ERROR: invalid chunk state when deallocating address " "%p\n", UserPtr); } if (DeallocationTypeMismatch) { // The deallocation type has to match the allocation one. if (OldHeader.AllocType != Type) { // With the exception of memalign'd Chunks, that can be still be free'd. if (OldHeader.AllocType != FromMemalign || Type != FromMalloc) { dieWithMessage("ERROR: allocation type mismatch on address %p\n", UserPtr); } } } uptr Size = OldHeader.FromPrimary ? OldHeader.SizeOrUnusedBytes : Chunk->getUsableSize(&OldHeader) - OldHeader.SizeOrUnusedBytes; if (DeleteSizeMismatch) { if (DeleteSize && DeleteSize != Size) { dieWithMessage("ERROR: invalid sized delete on chunk at address %p\n", UserPtr); } } // If a small memory amount was allocated with a larger alignment, we want // to take that into account. Otherwise the Quarantine would be filled with // tiny chunks, taking a lot of VA memory. This is an approximation of the // usable size, that allows us to not call GetActuallyAllocatedSize. uptr LiableSize = Size + (OldHeader.Offset << MinAlignment); quarantineOrDeallocateChunk(Chunk, &OldHeader, LiableSize); } // Reallocates a chunk. We can save on a new allocation if the new requested // size still fits in the chunk. void *reallocate(void *OldPtr, uptr NewSize) { initThreadMaybe(); uptr UserBeg = reinterpret_cast(OldPtr); if (UNLIKELY(!IsAligned(UserBeg, MinAlignment))) { dieWithMessage("ERROR: attempted to reallocate a chunk not properly " "aligned at address %p\n", OldPtr); } ScudoChunk *Chunk = getScudoChunk(UserBeg); UnpackedHeader OldHeader; Chunk->loadHeader(&OldHeader); if (UNLIKELY(OldHeader.State != ChunkAllocated)) { dieWithMessage("ERROR: invalid chunk state when reallocating address " "%p\n", OldPtr); } if (UNLIKELY(OldHeader.AllocType != FromMalloc)) { dieWithMessage("ERROR: invalid chunk type when reallocating address %p\n", OldPtr); } uptr UsableSize = Chunk->getUsableSize(&OldHeader); // The new size still fits in the current chunk, and the size difference // is reasonable. if (NewSize <= UsableSize && (UsableSize - NewSize) < (SizeClassMap::kMaxSize / 2)) { UnpackedHeader NewHeader = OldHeader; NewHeader.SizeOrUnusedBytes = OldHeader.FromPrimary ? NewSize : UsableSize - NewSize; Chunk->compareExchangeHeader(&NewHeader, &OldHeader); return OldPtr; } // Otherwise, we have to allocate a new chunk and copy the contents of the // old one. void *NewPtr = allocate(NewSize, MinAlignment, FromMalloc); if (NewPtr) { uptr OldSize = OldHeader.FromPrimary ? OldHeader.SizeOrUnusedBytes : UsableSize - OldHeader.SizeOrUnusedBytes; memcpy(NewPtr, OldPtr, Min(NewSize, OldSize)); quarantineOrDeallocateChunk(Chunk, &OldHeader, UsableSize); } return NewPtr; } // Helper function that returns the actual usable size of a chunk. uptr getUsableSize(const void *Ptr) { initThreadMaybe(); if (!Ptr) return 0; uptr UserBeg = reinterpret_cast(Ptr); ScudoChunk *Chunk = getScudoChunk(UserBeg); UnpackedHeader Header; Chunk->loadHeader(&Header); // Getting the usable size of a chunk only makes sense if it's allocated. if (UNLIKELY(Header.State != ChunkAllocated)) { dieWithMessage("ERROR: invalid chunk state when sizing address %p\n", Ptr); } return Chunk->getUsableSize(&Header); } void *calloc(uptr NMemB, uptr Size) { initThreadMaybe(); uptr Total = NMemB * Size; if (Size != 0 && Total / Size != NMemB) // Overflow check return BackendAllocator.ReturnNullOrDieOnBadRequest(); return allocate(Total, MinAlignment, FromMalloc, true); } void commitBack(ScudoThreadContext *ThreadContext) { AllocatorCache *Cache = getAllocatorCache(ThreadContext); AllocatorQuarantine.Drain(getQuarantineCache(ThreadContext), QuarantineCallback(Cache)); BackendAllocator.DestroyCache(Cache); } uptr getStats(AllocatorStat StatType) { initThreadMaybe(); uptr stats[AllocatorStatCount]; BackendAllocator.GetStats(stats); return stats[StatType]; } }; static ScudoAllocator Instance(LINKER_INITIALIZED); static ScudoBackendAllocator &getBackendAllocator() { return Instance.BackendAllocator; } static void initScudoInternal(const AllocatorOptions &Options) { Instance.init(Options); } void ScudoThreadContext::init() { getBackendAllocator().InitCache(&Cache); Prng.initFromURandom(); memset(QuarantineCachePlaceHolder, 0, sizeof(QuarantineCachePlaceHolder)); } void ScudoThreadContext::commitBack() { Instance.commitBack(this); } void *scudoMalloc(uptr Size, AllocType Type) { return Instance.allocate(Size, MinAlignment, Type); } void scudoFree(void *Ptr, AllocType Type) { Instance.deallocate(Ptr, 0, Type); } void scudoSizedFree(void *Ptr, uptr Size, AllocType Type) { Instance.deallocate(Ptr, Size, Type); } void *scudoRealloc(void *Ptr, uptr Size) { if (!Ptr) return Instance.allocate(Size, MinAlignment, FromMalloc); if (Size == 0) { Instance.deallocate(Ptr, 0, FromMalloc); return nullptr; } return Instance.reallocate(Ptr, Size); } void *scudoCalloc(uptr NMemB, uptr Size) { return Instance.calloc(NMemB, Size); } void *scudoValloc(uptr Size) { return Instance.allocate(Size, GetPageSizeCached(), FromMemalign); } void *scudoMemalign(uptr Alignment, uptr Size) { return Instance.allocate(Size, Alignment, FromMemalign); } void *scudoPvalloc(uptr Size) { uptr PageSize = GetPageSizeCached(); Size = RoundUpTo(Size, PageSize); if (Size == 0) { // pvalloc(0) should allocate one page. Size = PageSize; } return Instance.allocate(Size, PageSize, FromMemalign); } int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size) { *MemPtr = Instance.allocate(Size, Alignment, FromMemalign); return 0; } void *scudoAlignedAlloc(uptr Alignment, uptr Size) { // size must be a multiple of the alignment. To avoid a division, we first // make sure that alignment is a power of 2. CHECK(IsPowerOfTwo(Alignment)); CHECK_EQ((Size & (Alignment - 1)), 0); return Instance.allocate(Size, Alignment, FromMalloc); } uptr scudoMallocUsableSize(void *Ptr) { return Instance.getUsableSize(Ptr); } } // namespace __scudo using namespace __scudo; // MallocExtension helper functions uptr __sanitizer_get_current_allocated_bytes() { return Instance.getStats(AllocatorStatAllocated); } uptr __sanitizer_get_heap_size() { return Instance.getStats(AllocatorStatMapped); } uptr __sanitizer_get_free_bytes() { return 1; } uptr __sanitizer_get_unmapped_bytes() { return 1; } uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } int __sanitizer_get_ownership(const void *Ptr) { return Instance.isValidPointer(Ptr); } uptr __sanitizer_get_allocated_size(const void *Ptr) { return Instance.getUsableSize(Ptr); } Index: vendor/compiler-rt/dist/lib/scudo/scudo_allocator.h =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_allocator.h (revision 317952) +++ vendor/compiler-rt/dist/lib/scudo/scudo_allocator.h (revision 317953) @@ -1,126 +1,132 @@ //===-- scudo_allocator.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// Header for scudo_allocator.cpp. /// //===----------------------------------------------------------------------===// #ifndef SCUDO_ALLOCATOR_H_ #define SCUDO_ALLOCATOR_H_ #include "scudo_flags.h" #include "sanitizer_common/sanitizer_allocator.h" #if !SANITIZER_LINUX # error "The Scudo hardened allocator is currently only supported on Linux." #endif namespace __scudo { enum AllocType : u8 { FromMalloc = 0, // Memory block came from malloc, realloc, calloc, etc. FromNew = 1, // Memory block came from operator new. FromNewArray = 2, // Memory block came from operator new []. FromMemalign = 3, // Memory block came from memalign, posix_memalign, etc. }; enum ChunkState : u8 { ChunkAvailable = 0, ChunkAllocated = 1, ChunkQuarantine = 2 }; // Our header requires 64 bits of storage. Having the offset saves us from // using functions such as GetBlockBegin, that is fairly costly. Our first // implementation used the MetaData as well, which offers the advantage of // being stored away from the chunk itself, but accessing it was costly as // well. The header will be atomically loaded and stored. typedef u64 PackedHeader; struct UnpackedHeader { u64 Checksum : 16; u64 SizeOrUnusedBytes : 19; // Size for Primary backed allocations, amount of // unused bytes in the chunk for Secondary ones. u64 FromPrimary : 1; u64 State : 2; // available, allocated, or quarantined u64 AllocType : 2; // malloc, new, new[], or memalign u64 Offset : 16; // Offset from the beginning of the backend // allocation to the beginning of the chunk // itself, in multiples of MinAlignment. See // comment about its maximum value and in init(). u64 Salt : 8; }; typedef atomic_uint64_t AtomicPackedHeader; COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader)); // Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4); const uptr MaxAlignmentLog = 24; // 16 MB const uptr MinAlignment = 1 << MinAlignmentLog; const uptr MaxAlignment = 1 << MaxAlignmentLog; const uptr ChunkHeaderSize = sizeof(PackedHeader); const uptr AlignedChunkHeaderSize = (ChunkHeaderSize + MinAlignment - 1) & ~(MinAlignment - 1); #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; static const uptr kSpaceSize = AllocatorSize; static const uptr kMetadataSize = 0; typedef __scudo::SizeClassMap SizeClassMap; typedef NoOpMapUnmapCallback MapUnmapCallback; static const uptr kFlags = SizeClassAllocator64FlagMasks::kRandomShuffleChunks; }; typedef SizeClassAllocator64 PrimaryAllocator; #else // Currently, the 32-bit Sanitizer allocator has not yet benefited from all the // security improvements brought to the 64-bit one. This makes the 32-bit // version of Scudo slightly less toughened. static const uptr RegionSizeLog = 20; static const uptr NumRegions = SANITIZER_MMAP_RANGE_SIZE >> RegionSizeLog; # if SANITIZER_WORDSIZE == 32 typedef FlatByteMap ByteMap; # elif SANITIZER_WORDSIZE == 64 typedef TwoLevelByteMap<(NumRegions >> 12), 1 << 12> ByteMap; # endif // SANITIZER_WORDSIZE typedef DefaultSizeClassMap SizeClassMap; typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 0, SizeClassMap, RegionSizeLog, ByteMap> PrimaryAllocator; #endif // SANITIZER_CAN_USE_ALLOCATOR64 #include "scudo_allocator_secondary.h" typedef SizeClassAllocatorLocalCache AllocatorCache; typedef ScudoLargeMmapAllocator SecondaryAllocator; typedef CombinedAllocator ScudoBackendAllocator; void initScudo(); void *scudoMalloc(uptr Size, AllocType Type); void scudoFree(void *Ptr, AllocType Type); void scudoSizedFree(void *Ptr, uptr Size, AllocType Type); void *scudoRealloc(void *Ptr, uptr Size); void *scudoCalloc(uptr NMemB, uptr Size); void *scudoMemalign(uptr Alignment, uptr Size); void *scudoValloc(uptr Size); void *scudoPvalloc(uptr Size); int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size); void *scudoAlignedAlloc(uptr Alignment, uptr Size); uptr scudoMallocUsableSize(void *Ptr); } // namespace __scudo #endif // SCUDO_ALLOCATOR_H_ Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls.h =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls.h (revision 317952) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls.h (revision 317953) @@ -1,40 +1,47 @@ //===-- scudo_tls.h ---------------------------------------------*- 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 definition. /// Implementation will differ based on the thread local storage primitives /// offered by the underlying platform. /// //===----------------------------------------------------------------------===// #ifndef SCUDO_TLS_H_ #define SCUDO_TLS_H_ #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]; void init(); void commitBack(); }; 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 #endif // SCUDO_TLS_H_ Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.cpp =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.cpp (nonexistent) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.cpp (revision 317953) @@ -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 + +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( + 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(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(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(ThreadContext); + return ThreadContext; + } + // Last resort (can this happen?), stick with the current one. + ThreadContext = + reinterpret_cast(*get_android_tls_ptr()); + ThreadContext->lock(); + return ThreadContext; +} + +} // namespace __scudo + +#endif // SANITIZER_LINUX && SANITIZER_ANDROID Property changes on: vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.inc =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.inc (nonexistent) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.inc (revision 317953) @@ -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(*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_ Property changes on: vendor/compiler-rt/dist/lib/scudo/scudo_tls_android.inc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_android.inc =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_android.inc (nonexistent) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_android.inc (revision 317953) @@ -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_ Property changes on: vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_android.inc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_linux.inc =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_linux.inc (nonexistent) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_linux.inc (revision 317953) @@ -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_ Property changes on: vendor/compiler-rt/dist/lib/scudo/scudo_tls_context_linux.inc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.cpp =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.cpp (revision 317952) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.cpp (revision 317953) @@ -1,62 +1,64 @@ //===-- scudo_tls_linux.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 platforms supporting /// thread_local. /// //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID #include "scudo_tls.h" #include #include 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(Ptr); // The glibc POSIX thread-local-storage deallocation routine calls user // provided destructors in a loop of PTHREAD_DESTRUCTOR_ITERATIONS. // We want to be called last since other destructors might call free and the // like, so we wait until PTHREAD_DESTRUCTOR_ITERATIONS before draining the // quarantine and swallowing the cache. if (Iteration < PTHREAD_DESTRUCTOR_ITERATIONS) { pthread_setspecific(PThreadKey, reinterpret_cast(Iteration + 1)); return; } ThreadLocalContext.commitBack(); ScudoThreadState = ThreadTornDown; } static void initOnce() { CHECK_EQ(pthread_key_create(&PThreadKey, teardownThread), 0); initScudo(); } void initThread() { pthread_once(&GlobalInitialized, initOnce); pthread_setspecific(PThreadKey, reinterpret_cast(1)); ThreadLocalContext.init(); ScudoThreadState = ThreadInitialized; } } // namespace __scudo -#endif // SANITIZER_LINUX +#endif // SANITIZER_LINUX && !SANITIZER_ANDROID Index: vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.inc =================================================================== --- vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.inc (nonexistent) +++ vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.inc (revision 317953) @@ -0,0 +1,48 @@ +//===-- scudo_tls_linux.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 platforms +/// supporting thread_local. +/// +//===----------------------------------------------------------------------===// + +#ifndef SCUDO_TLS_LINUX_H_ +#define SCUDO_TLS_LINUX_H_ + +#ifndef SCUDO_TLS_H_ +# error "This file must be included inside scudo_tls.h." +#endif // SCUDO_TLS_H_ + +#if SANITIZER_LINUX && !SANITIZER_ANDROID + +enum ThreadState : u8 { + ThreadNotInitialized = 0, + ThreadInitialized, + ThreadTornDown, +}; +__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)) + return; + initThread(); +} + +ALWAYS_INLINE ScudoThreadContext *getThreadContextAndLock() { + if (UNLIKELY(ScudoThreadState == ThreadTornDown)) + return nullptr; + return &ThreadLocalContext; +} + +#endif // SANITIZER_LINUX && !SANITIZER_ANDROID + +#endif // SCUDO_TLS_LINUX_H_ Property changes on: vendor/compiler-rt/dist/lib/scudo/scudo_tls_linux.inc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/ubsan/CMakeLists.txt =================================================================== --- vendor/compiler-rt/dist/lib/ubsan/CMakeLists.txt (revision 317952) +++ vendor/compiler-rt/dist/lib/ubsan/CMakeLists.txt (revision 317953) @@ -1,159 +1,160 @@ # Build for the undefined behavior sanitizer runtime support library. set(UBSAN_SOURCES ubsan_diag.cc ubsan_init.cc ubsan_flags.cc ubsan_handlers.cc ubsan_value.cc ) set(UBSAN_STANDALONE_SOURCES + ubsan_diag_standalone.cc ubsan_init_standalone.cc ) set(UBSAN_CXXABI_SOURCES ubsan_handlers_cxx.cc ubsan_type_hash.cc ubsan_type_hash_itanium.cc ubsan_type_hash_win.cc ) include_directories(..) set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_rtti_flag(OFF UBSAN_CFLAGS) append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CFLAGS) set(UBSAN_STANDALONE_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_rtti_flag(OFF UBSAN_STANDALONE_CFLAGS) append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_STANDALONE_CFLAGS) set(UBSAN_CXXFLAGS ${SANITIZER_COMMON_CFLAGS}) append_rtti_flag(ON UBSAN_CXXFLAGS) append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CXXFLAGS) add_compiler_rt_component(ubsan) if(APPLE) set(UBSAN_COMMON_SOURCES ${UBSAN_SOURCES}) if(SANITIZER_CAN_USE_CXXABI) list(APPEND UBSAN_COMMON_SOURCES ${UBSAN_CXXABI_SOURCES}) endif() # Common parts of UBSan runtime. add_compiler_rt_object_libraries(RTUbsan OS ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} SOURCES ${UBSAN_COMMON_SOURCES} CFLAGS ${UBSAN_CXXFLAGS}) if(COMPILER_RT_HAS_UBSAN) # Initializer of standalone UBSan runtime. add_compiler_rt_object_libraries(RTUbsan_standalone OS ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} SOURCES ${UBSAN_STANDALONE_SOURCES} CFLAGS ${UBSAN_STANDALONE_CFLAGS}) add_weak_symbols("ubsan" WEAK_SYMBOL_LINK_FLAGS) add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) add_compiler_rt_runtime(clang_rt.ubsan SHARED OS ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} OBJECT_LIBS RTUbsan RTUbsan_standalone RTSanitizerCommon RTSanitizerCommonLibc LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS} PARENT_TARGET ubsan) endif() else() # Common parts of UBSan runtime. add_compiler_rt_object_libraries(RTUbsan ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} SOURCES ${UBSAN_SOURCES} CFLAGS ${UBSAN_CFLAGS}) if(SANITIZER_CAN_USE_CXXABI) # C++-specific parts of UBSan runtime. Requires a C++ ABI library. set(UBSAN_CXX_SOURCES ${UBSAN_CXXABI_SOURCES}) else() # Dummy target if we don't have C++ ABI library. file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cxx_dummy.cc "") set(UBSAN_CXX_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cxx_dummy.cc) endif() add_compiler_rt_object_libraries(RTUbsan_cxx ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} SOURCES ${UBSAN_CXX_SOURCES} CFLAGS ${UBSAN_CXXFLAGS}) if (WIN32) add_compiler_rt_object_libraries(UbsanWeakInterception ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} SOURCES ubsan_win_weak_interception.cc CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DYNAMIC DEFS ${UBSAN_COMMON_DEFINITIONS}) add_compiler_rt_object_libraries(UbsanDllThunk ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} SOURCES ubsan_win_dll_thunk.cc CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DLL_THUNK DEFS ${UBSAN_COMMON_DEFINITIONS}) set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") if(MSVC) list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") elseif(CMAKE_C_COMPILER_ID MATCHES Clang) list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") endif() add_compiler_rt_object_libraries(UbsanDynamicRuntimeThunk ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} SOURCES ubsan_win_dynamic_runtime_thunk.cc CFLAGS ${UBSAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} DEFS ${UBSAN_COMMON_DEFINITIONS}) endif() if(COMPILER_RT_HAS_UBSAN) # Initializer of standalone UBSan runtime. add_compiler_rt_object_libraries(RTUbsan_standalone ARCHS ${UBSAN_SUPPORTED_ARCH} SOURCES ${UBSAN_STANDALONE_SOURCES} CFLAGS ${UBSAN_STANDALONE_CFLAGS}) # Standalone UBSan runtimes. add_compiler_rt_runtime(clang_rt.ubsan_standalone STATIC ARCHS ${UBSAN_SUPPORTED_ARCH} OBJECT_LIBS RTSanitizerCommon RTSanitizerCommonLibc RTUbsan RTUbsan_standalone CFLAGS ${UBSAN_CFLAGS} PARENT_TARGET ubsan) add_compiler_rt_runtime(clang_rt.ubsan_standalone_cxx STATIC ARCHS ${UBSAN_SUPPORTED_ARCH} OBJECT_LIBS RTUbsan_cxx CFLAGS ${UBSAN_CXXFLAGS} PARENT_TARGET ubsan) if (UNIX) set(ARCHS_FOR_SYMBOLS ${UBSAN_SUPPORTED_ARCH}) list(REMOVE_ITEM ARCHS_FOR_SYMBOLS i386 i686) add_sanitizer_rt_symbols(clang_rt.ubsan_standalone ARCHS ${ARCHS_FOR_SYMBOLS} PARENT_TARGET ubsan EXTRA ubsan.syms.extra) add_sanitizer_rt_symbols(clang_rt.ubsan_standalone_cxx ARCHS ${ARCHS_FOR_SYMBOLS} PARENT_TARGET ubsan EXTRA ubsan.syms.extra) endif() endif() endif() Index: vendor/compiler-rt/dist/lib/ubsan/ubsan_diag_standalone.cc =================================================================== --- vendor/compiler-rt/dist/lib/ubsan/ubsan_diag_standalone.cc (nonexistent) +++ vendor/compiler-rt/dist/lib/ubsan/ubsan_diag_standalone.cc (revision 317953) @@ -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 Property changes on: vendor/compiler-rt/dist/lib/ubsan/ubsan_diag_standalone.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/lib/ubsan/ubsan_handlers.cc =================================================================== --- vendor/compiler-rt/dist/lib/ubsan/ubsan_handlers.cc (revision 317952) +++ vendor/compiler-rt/dist/lib/ubsan/ubsan_handlers.cc (revision 317953) @@ -1,614 +1,615 @@ //===-- ubsan_handlers.cc -------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Error logging entry points for the UBSan runtime. // //===----------------------------------------------------------------------===// #include "ubsan_platform.h" #if CAN_SANITIZE_UB #include "ubsan_handlers.h" #include "ubsan_diag.h" #include "sanitizer_common/sanitizer_common.h" using namespace __sanitizer; using namespace __ubsan; namespace __ubsan { bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) { // We are not allowed to skip error report: if we are in unrecoverable // handler, we have to terminate the program right now, and therefore // have to print some diagnostic. // // Even if source location is disabled, it doesn't mean that we have // already report an error to the user: some concurrently running // thread could have acquired it, but not yet printed the report. if (Opts.FromUnrecoverableHandler) return false; return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename()); } const char *TypeCheckKinds[] = { "load of", "store to", "reference binding to", "member access within", "member call on", "constructor call on", "downcast of", "downcast of", "upcast of", "cast to virtual base of", "_Nonnull binding to"}; } static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer, ReportOptions Opts) { Location Loc = Data->Loc.acquire(); uptr Alignment = (uptr)1 << Data->LogAlignment; ErrorType ET; if (!Pointer) ET = ErrorType::NullPointerUse; else if (Pointer & (Alignment - 1)) ET = ErrorType::MisalignedPointerUse; else ET = ErrorType::InsufficientObjectSize; // Use the SourceLocation from Data to track deduplication, even if it's // invalid. if (ignoreReport(Loc.getSourceLocation(), Opts, ET)) return; SymbolizedStackHolder FallbackLoc; if (Data->Loc.isInvalid()) { FallbackLoc.reset(getCallerLocation(Opts.pc)); Loc = FallbackLoc; } ScopedReport R(Opts, Loc, ET); switch (ET) { case ErrorType::NullPointerUse: Diag(Loc, DL_Error, "%0 null pointer of type %1") << TypeCheckKinds[Data->TypeCheckKind] << Data->Type; break; case ErrorType::MisalignedPointerUse: Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, " "which requires %2 byte alignment") << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Alignment << Data->Type; break; case ErrorType::InsufficientObjectSize: Diag(Loc, DL_Error, "%0 address %1 with insufficient space " "for an object of type %2") << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type; break; default: UNREACHABLE("unexpected error type!"); } if (Pointer) Diag(Pointer, DL_Note, "pointer points here"); } void __ubsan::__ubsan_handle_type_mismatch_v1(TypeMismatchData *Data, ValueHandle Pointer) { GET_REPORT_OPTIONS(false); handleTypeMismatchImpl(Data, Pointer, Opts); } void __ubsan::__ubsan_handle_type_mismatch_v1_abort(TypeMismatchData *Data, ValueHandle Pointer) { GET_REPORT_OPTIONS(true); handleTypeMismatchImpl(Data, Pointer, Opts); Die(); } /// \brief Common diagnostic emission for various forms of integer overflow. template static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS, const char *Operator, T RHS, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); bool IsSigned = Data->Type.isSignedIntegerTy(); ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow : ErrorType::UnsignedIntegerOverflow; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "%0 integer overflow: " "%1 %2 %3 cannot be represented in type %4") << (IsSigned ? "signed" : "unsigned") << Value(Data->Type, LHS) << Operator << RHS << Data->Type; } #define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \ void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \ ValueHandle RHS) { \ GET_REPORT_OPTIONS(unrecoverable); \ handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \ if (unrecoverable) \ Die(); \ } UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false) UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true) UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false) UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true) UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false) UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true) static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); bool IsSigned = Data->Type.isSignedIntegerTy(); ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow : ErrorType::UnsignedIntegerOverflow; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); if (IsSigned) Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1; " "cast to an unsigned type to negate this value to itself") << Value(Data->Type, OldVal) << Data->Type; else Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1") << Value(Data->Type, OldVal) << Data->Type; } void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data, ValueHandle OldVal) { GET_REPORT_OPTIONS(false); handleNegateOverflowImpl(Data, OldVal, Opts); } void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data, ValueHandle OldVal) { GET_REPORT_OPTIONS(true); handleNegateOverflowImpl(Data, OldVal, Opts); Die(); } static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS, ValueHandle RHS, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); Value LHSVal(Data->Type, LHS); Value RHSVal(Data->Type, RHS); ErrorType ET; if (RHSVal.isMinusOne()) ET = ErrorType::SignedIntegerOverflow; else if (Data->Type.isIntegerTy()) ET = ErrorType::IntegerDivideByZero; else ET = ErrorType::FloatDivideByZero; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); switch (ET) { case ErrorType::SignedIntegerOverflow: Diag(Loc, DL_Error, "division of %0 by -1 cannot be represented in type %1") << LHSVal << Data->Type; break; default: Diag(Loc, DL_Error, "division by zero"); break; } } void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data, ValueHandle LHS, ValueHandle RHS) { GET_REPORT_OPTIONS(false); handleDivremOverflowImpl(Data, LHS, RHS, Opts); } void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data, ValueHandle LHS, ValueHandle RHS) { GET_REPORT_OPTIONS(true); handleDivremOverflowImpl(Data, LHS, RHS, Opts); Die(); } static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data, ValueHandle LHS, ValueHandle RHS, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); Value LHSVal(Data->LHSType, LHS); Value RHSVal(Data->RHSType, RHS); ErrorType ET; if (RHSVal.isNegative() || RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth()) ET = ErrorType::InvalidShiftExponent; else ET = ErrorType::InvalidShiftBase; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); if (ET == ErrorType::InvalidShiftExponent) { if (RHSVal.isNegative()) Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal; else Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2") << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType; } else { if (LHSVal.isNegative()) Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal; else Diag(Loc, DL_Error, "left shift of %0 by %1 places cannot be represented in type %2") << LHSVal << RHSVal << Data->LHSType; } } void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data, ValueHandle LHS, ValueHandle RHS) { GET_REPORT_OPTIONS(false); handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts); } void __ubsan::__ubsan_handle_shift_out_of_bounds_abort( ShiftOutOfBoundsData *Data, ValueHandle LHS, ValueHandle RHS) { GET_REPORT_OPTIONS(true); handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts); Die(); } static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::OutOfBoundsIndex; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Value IndexVal(Data->IndexType, Index); Diag(Loc, DL_Error, "index %0 out of bounds for type %1") << IndexVal << Data->ArrayType; } void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data, ValueHandle Index) { GET_REPORT_OPTIONS(false); handleOutOfBoundsImpl(Data, Index, Opts); } void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, ValueHandle Index) { GET_REPORT_OPTIONS(true); handleOutOfBoundsImpl(Data, Index, Opts); Die(); } static void handleBuiltinUnreachableImpl(UnreachableData *Data, ReportOptions Opts) { ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall); Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); } void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { GET_REPORT_OPTIONS(true); handleBuiltinUnreachableImpl(Data, Opts); Die(); } static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) { ScopedReport R(Opts, Data->Loc, ErrorType::MissingReturn); Diag(Data->Loc, DL_Error, "execution reached the end of a value-returning function " "without returning a value"); } void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) { GET_REPORT_OPTIONS(true); handleMissingReturnImpl(Data, Opts); Die(); } static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::NonPositiveVLAIndex; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "variable length array bound evaluates to " "non-positive value %0") << Value(Data->Type, Bound); } void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data, ValueHandle Bound) { GET_REPORT_OPTIONS(false); handleVLABoundNotPositive(Data, Bound, Opts); } void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data, ValueHandle Bound) { GET_REPORT_OPTIONS(true); handleVLABoundNotPositive(Data, Bound, Opts); Die(); } static bool looksLikeFloatCastOverflowDataV1(void *Data) { // First field is either a pointer to filename or a pointer to a // TypeDescriptor. u8 *FilenameOrTypeDescriptor; internal_memcpy(&FilenameOrTypeDescriptor, Data, sizeof(FilenameOrTypeDescriptor)); // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known, // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename, // adding two printable characters will not yield such a value. Otherwise, // if one of them is 0xff, this is most likely TK_Unknown type descriptor. u16 MaybeFromTypeKind = FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1]; return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff || FilenameOrTypeDescriptor[1] == 0xff; } static void handleFloatCastOverflow(void *DataPtr, ValueHandle From, ReportOptions Opts) { SymbolizedStackHolder CallerLoc; Location Loc; const TypeDescriptor *FromType, *ToType; ErrorType ET = ErrorType::FloatCastOverflow; if (looksLikeFloatCastOverflowDataV1(DataPtr)) { auto Data = reinterpret_cast(DataPtr); CallerLoc.reset(getCallerLocation(Opts.pc)); Loc = CallerLoc; FromType = &Data->FromType; ToType = &Data->ToType; } else { auto Data = reinterpret_cast(DataPtr); SourceLocation SLoc = Data->Loc.acquire(); if (ignoreReport(SLoc, Opts, ET)) return; Loc = SLoc; FromType = &Data->FromType; ToType = &Data->ToType; } ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "%0 is outside the range of representable values of type %2") << Value(*FromType, From) << *FromType << *ToType; } void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) { GET_REPORT_OPTIONS(false); handleFloatCastOverflow(Data, From, Opts); } void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data, ValueHandle From) { GET_REPORT_OPTIONS(true); handleFloatCastOverflow(Data, From, Opts); Die(); } static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val, ReportOptions Opts) { 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; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") << Value(Data->Type, Val) << Data->Type; } void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data, ValueHandle Val) { GET_REPORT_OPTIONS(false); handleLoadInvalidValue(Data, Val, Opts); } void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, ValueHandle Val) { GET_REPORT_OPTIONS(true); handleLoadInvalidValue(Data, Val, Opts); Die(); } static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, ValueHandle Function, ReportOptions Opts) { SourceLocation CallLoc = Data->Loc.acquire(); ErrorType ET = ErrorType::FunctionTypeMismatch; if (ignoreReport(CallLoc, Opts, ET)) return; ScopedReport R(Opts, CallLoc, ET); SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); const char *FName = FLoc.get()->info.function; if (!FName) FName = "(unknown)"; Diag(CallLoc, DL_Error, "call to function %0 through pointer to incorrect function type %1") << FName << Data->Type; Diag(FLoc, DL_Note, "%0 defined here") << FName; } void __ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, ValueHandle Function) { GET_REPORT_OPTIONS(false); handleFunctionTypeMismatch(Data, Function, Opts); } void __ubsan::__ubsan_handle_function_type_mismatch_abort( FunctionTypeMismatchData *Data, ValueHandle Function) { GET_REPORT_OPTIONS(true); handleFunctionTypeMismatch(Data, Function, Opts); Die(); } static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts, bool IsAttr) { SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::InvalidNullReturn; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "null pointer returned from function declared to never " "return null"); if (!Data->AttrLoc.isInvalid()) Diag(Data->AttrLoc, DL_Note, "%0 specified here") << (IsAttr ? "returns_nonnull attribute" : "_Nonnull return type annotation"); } void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) { GET_REPORT_OPTIONS(false); handleNonNullReturn(Data, Opts, true); } void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) { GET_REPORT_OPTIONS(true); handleNonNullReturn(Data, Opts, true); Die(); } void __ubsan::__ubsan_handle_nullability_return(NonNullReturnData *Data) { GET_REPORT_OPTIONS(false); handleNonNullReturn(Data, Opts, false); } void __ubsan::__ubsan_handle_nullability_return_abort(NonNullReturnData *Data) { GET_REPORT_OPTIONS(true); handleNonNullReturn(Data, Opts, false); Die(); } static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts, bool IsAttr) { SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::InvalidNullArgument; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to " "never be null") << Data->ArgIndex; if (!Data->AttrLoc.isInvalid()) Diag(Data->AttrLoc, DL_Note, "%0 specified here") << (IsAttr ? "nonnull attribute" : "_Nonnull type annotation"); } void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) { GET_REPORT_OPTIONS(false); handleNonNullArg(Data, Opts, true); } void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) { GET_REPORT_OPTIONS(true); handleNonNullArg(Data, Opts, true); Die(); } void __ubsan::__ubsan_handle_nullability_arg(NonNullArgData *Data) { GET_REPORT_OPTIONS(false); handleNonNullArg(Data, Opts, false); } void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) { GET_REPORT_OPTIONS(true); handleNonNullArg(Data, Opts, false); Die(); } static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function, ReportOptions Opts) { if (Data->CheckKind != CFITCK_ICall) Die(); SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::CFIBadType; if (ignoreReport(Loc, Opts, ET)) return; ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " "indirect function call") << Data->Type; SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); const char *FName = FLoc.get()->info.function; if (!FName) FName = "(unknown)"; Diag(FLoc, DL_Note, "%0 defined here") << FName; } namespace __ubsan { #ifdef UBSAN_CAN_USE_CXXABI SANITIZER_WEAK_ATTRIBUTE void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable, ReportOptions Opts); #else static void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable, ReportOptions Opts) { Die(); } #endif } // namespace __ubsan void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data, ValueHandle Value, uptr ValidVtable) { GET_REPORT_OPTIONS(false); if (Data->CheckKind == CFITCK_ICall) handleCFIBadIcall(Data, Value, Opts); else HandleCFIBadType(Data, Value, ValidVtable, Opts); } void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data, ValueHandle Value, uptr ValidVtable) { GET_REPORT_OPTIONS(true); if (Data->CheckKind == CFITCK_ICall) handleCFIBadIcall(Data, Value, Opts); else HandleCFIBadType(Data, Value, ValidVtable, Opts); Die(); } #endif // CAN_SANITIZE_UB Index: vendor/compiler-rt/dist/lib/xray/xray_init.cc =================================================================== --- vendor/compiler-rt/dist/lib/xray/xray_init.cc (revision 317952) +++ vendor/compiler-rt/dist/lib/xray/xray_init.cc (revision 317953) @@ -1,67 +1,71 @@ //===-- xray_init.cc --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of XRay, a dynamic runtime instrumentation system. // // XRay initialisation logic. //===----------------------------------------------------------------------===// #include #include #include #include "sanitizer_common/sanitizer_common.h" #include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" 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; // When set to 'true' this means the XRay runtime has been initialised. We use // the weak symbols defined above (__start_xray_inst_map and // __stop_xray_instr_map) to initialise the instrumentation map that XRay uses // for runtime patching/unpatching of instrumentation points. // // FIXME: Support DSO instrumentation maps too. The current solution only works // for statically linked executables. __sanitizer::atomic_uint8_t XRayInitialized{0}; // This should always be updated before XRayInitialized is updated. __sanitizer::SpinMutex XRayInstrMapMutex; XRaySledMap XRayInstrMap; // __xray_init() will do the actual loading of the current process' memory map // and then proceed to look for the .xray_instr_map section/segment. void __xray_init() XRAY_NEVER_INSTRUMENT { initializeFlags(); if (__start_xray_instr_map == nullptr) { Report("XRay instrumentation map missing. Not initializing XRay.\n"); return; } { __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); if (flags()->patch_premain) __xray_patch(); } __attribute__((section(".preinit_array"), used)) void (*__local_xray_preinit)(void) = __xray_init; Index: vendor/compiler-rt/dist/lib/xray/xray_interface.cc =================================================================== --- vendor/compiler-rt/dist/lib/xray/xray_interface.cc (revision 317952) +++ vendor/compiler-rt/dist/lib/xray/xray_interface.cc (revision 317953) @@ -1,241 +1,316 @@ //===-- xray_interface.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of XRay, a dynamic runtime instrumentation system. // // Implementation of the API functions. // //===----------------------------------------------------------------------===// #include "xray_interface_internal.h" #include #include #include #include #include #include "sanitizer_common/sanitizer_common.h" #include "xray_defs.h" namespace __xray { #if defined(__x86_64__) // FIXME: The actual length is 11 bytes. Why was length 12 passed to mprotect() // ? static const int16_t cSledLength = 12; #elif defined(__aarch64__) static const int16_t cSledLength = 32; #elif defined(__arm__) static const int16_t cSledLength = 28; #elif SANITIZER_MIPS32 static const int16_t cSledLength = 48; #elif SANITIZER_MIPS64 static const int16_t cSledLength = 64; #elif defined(__powerpc64__) static const int16_t cSledLength = 8; #else #error "Unsupported CPU Architecture" #endif /* CPU architecture */ // This is the function to call when we encounter the entry or exit sleds. __sanitizer::atomic_uintptr_t XRayPatchedFunction{0}; // This is the function to call from the arg1-enabled sleds/trampolines. __sanitizer::atomic_uintptr_t XRayArgLogger{0}; // MProtectHelper is an RAII wrapper for calls to mprotect(...) that will undo // any successful mprotect(...) changes. This is used to make a page writeable // and executable, and upon destruction if it was successful in doing so returns // the page into a read-only and executable page. // // This is only used specifically for runtime-patching of the XRay // instrumentation points. This assumes that the executable pages are originally // read-and-execute only. class MProtectHelper { void *PageAlignedAddr; std::size_t MProtectLen; bool MustCleanup; public: explicit MProtectHelper(void *PageAlignedAddr, std::size_t MProtectLen) XRAY_NEVER_INSTRUMENT : PageAlignedAddr(PageAlignedAddr), MProtectLen(MProtectLen), MustCleanup(false) {} int MakeWriteable() XRAY_NEVER_INSTRUMENT { auto R = mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_WRITE | PROT_EXEC); if (R != -1) MustCleanup = true; return R; } ~MProtectHelper() XRAY_NEVER_INSTRUMENT { if (MustCleanup) { mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC); } } }; } // namespace __xray extern __sanitizer::SpinMutex XRayInstrMapMutex; extern __sanitizer::atomic_uint8_t XRayInitialized; extern __xray::XRaySledMap XRayInstrMap; int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) XRAY_NEVER_INSTRUMENT { if (__sanitizer::atomic_load(&XRayInitialized, __sanitizer::memory_order_acquire)) { __sanitizer::atomic_store(&__xray::XRayPatchedFunction, reinterpret_cast(entry), __sanitizer::memory_order_release); return 1; } return 0; } int __xray_remove_handler() XRAY_NEVER_INSTRUMENT { return __xray_set_handler(nullptr); } __sanitizer::atomic_uint8_t XRayPatching{0}; using namespace __xray; // FIXME: Figure out whether we can move this class to sanitizer_common instead // as a generic "scope guard". template class CleanupInvoker { Function Fn; public: explicit CleanupInvoker(Function Fn) XRAY_NEVER_INSTRUMENT : Fn(Fn) {} CleanupInvoker(const CleanupInvoker &) XRAY_NEVER_INSTRUMENT = default; CleanupInvoker(CleanupInvoker &&) XRAY_NEVER_INSTRUMENT = default; CleanupInvoker & operator=(const CleanupInvoker &) XRAY_NEVER_INSTRUMENT = delete; CleanupInvoker &operator=(CleanupInvoker &&) XRAY_NEVER_INSTRUMENT = delete; ~CleanupInvoker() XRAY_NEVER_INSTRUMENT { Fn(); } }; template CleanupInvoker scopeCleanup(Function Fn) XRAY_NEVER_INSTRUMENT { return CleanupInvoker{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(Sled.Address & ~(PageSize - 1)); + std::size_t MProtectLen = (Sled.Address + cSledLength) - + reinterpret_cast(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; if (!__sanitizer::atomic_compare_exchange_strong( &XRayPatching, &NotPatching, true, __sanitizer::memory_order_acq_rel)) return XRayPatchingStatus::ONGOING; // Already patching. uint8_t PatchingSuccess = false; auto XRayPatchingStatusResetter = scopeCleanup([&PatchingSuccess] { if (!PatchingSuccess) __sanitizer::atomic_store(&XRayPatching, false, __sanitizer::memory_order_release); }); // Step 1: Compute the function id, as a unique identifier per function in the // instrumentation map. XRaySledMap InstrMap; { __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex); InstrMap = XRayInstrMap; } if (InstrMap.Entries == 0) return XRayPatchingStatus::NOT_INITIALIZED; const uint64_t PageSize = GetPageSizeCached(); if ((PageSize == 0) || ((PageSize & (PageSize - 1)) != 0)) { Report("System page size is not a power of two: %lld\n", PageSize); return XRayPatchingStatus::FAILED; } uint32_t FuncId = 1; uint64_t CurFun = 0; for (std::size_t I = 0; I < InstrMap.Entries; I++) { auto Sled = InstrMap.Sleds[I]; auto F = Sled.Function; if (CurFun == 0) CurFun = F; if (F != CurFun) { ++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(Sled.Address & ~(PageSize - 1)); - std::size_t MProtectLen = (Sled.Address + cSledLength) - - reinterpret_cast(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); PatchingSuccess = true; return XRayPatchingStatus::SUCCESS; } XRayPatchingStatus __xray_patch() XRAY_NEVER_INSTRUMENT { return controlPatching(true); } 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(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)) return 0; // A relaxed write might not be visible even if the current thread gets // scheduled on a different CPU/NUMA node. We need to wait for everyone to // have this handler installed for consistency of collected data across CPUs. __sanitizer::atomic_store(&XRayArgLogger, reinterpret_cast(Handler), __sanitizer::memory_order_release); 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(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; +} Index: vendor/compiler-rt/dist/lib/xray/xray_interface_internal.h =================================================================== --- vendor/compiler-rt/dist/lib/xray/xray_interface_internal.h (revision 317952) +++ vendor/compiler-rt/dist/lib/xray/xray_interface_internal.h (revision 317953) @@ -1,68 +1,75 @@ //===-- xray_interface_internal.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of XRay, a dynamic runtime instrumentation system. // // Implementation of the API functions. See also include/xray/xray_interface.h. // //===----------------------------------------------------------------------===// #ifndef XRAY_INTERFACE_INTERNAL_H #define XRAY_INTERFACE_INTERNAL_H #include "sanitizer_common/sanitizer_platform.h" #include "xray/xray_interface.h" #include #include extern "C" { struct XRaySledEntry { #if SANITIZER_WORDSIZE == 64 uint64_t Address; uint64_t Function; unsigned char Kind; unsigned char AlwaysInstrument; unsigned char Padding[14]; // Need 32 bytes #elif SANITIZER_WORDSIZE == 32 uint32_t Address; uint32_t Function; unsigned char Kind; unsigned char AlwaysInstrument; unsigned char Padding[6]; // Need 16 bytes #else #error "Unsupported word size." #endif }; + +struct XRayFunctionSledIndex { + const XRaySledEntry* Begin; + const XRaySledEntry* End; +}; } namespace __xray { struct XRaySledMap { const XRaySledEntry *Sleds; size_t Entries; + const XRayFunctionSledIndex *SledsIndex; + size_t Functions; }; bool patchFunctionEntry(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, void (*Trampoline)()); bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); bool patchFunctionTailExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); } // namespace __xray extern "C" { // The following functions have to be defined in assembler, on a per-platform // basis. See xray_trampoline_*.S files for implementations. extern void __xray_FunctionEntry(); extern void __xray_FunctionExit(); extern void __xray_FunctionTailExit(); extern void __xray_ArgLoggerEntry(); } #endif Index: vendor/compiler-rt/dist/test/asan/TestCases/Linux/longjmp_chk.c =================================================================== --- vendor/compiler-rt/dist/test/asan/TestCases/Linux/longjmp_chk.c (nonexistent) +++ vendor/compiler-rt/dist/test/asan/TestCases/Linux/longjmp_chk.c (revision 317953) @@ -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 +#include +#include + +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 Property changes on: vendor/compiler-rt/dist/test/asan/TestCases/Linux/longjmp_chk.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/test/builtins/Unit/divxc3_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/divxc3_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/divxc3_test.c (revision 317953) @@ -1,382 +1,383 @@ // RUN: %clang_builtins %s %librt -lm -o %t && %run %t //===-- divxc3_test.c - Test __divxc3 -------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __divxc3 for the compiler_rt library. // //===----------------------------------------------------------------------===// #if !_ARCH_PPC #include "int_lib.h" #include #include #include +// UNSUPPORTED: mips // REQUIRES: c99-complex // Returns: the quotient of (a + ib) / (c + id) COMPILER_RT_ABI long double _Complex __divxc3(long double __a, long double __b, long double __c, long double __d); enum {zero, non_zero, inf, NaN, non_zero_nan}; int classify(long double _Complex x) { if (x == 0) return zero; if (isinf(creall(x)) || isinf(cimagl(x))) return inf; if (isnan(creall(x)) && isnan(cimagl(x))) return NaN; if (isnan(creall(x))) { if (cimagl(x) == 0) return NaN; return non_zero_nan; } if (isnan(cimagl(x))) { if (creall(x) == 0) return NaN; return non_zero_nan; } return non_zero; } int test__divxc3(long double a, long double b, long double c, long double d) { long double _Complex r = __divxc3(a, b, c, d); // printf("test__divxc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n", // a, b, c, d, creall(r), cimagl(r)); long double _Complex dividend; long double _Complex divisor; __real__ dividend = a; __imag__ dividend = b; __real__ divisor = c; __imag__ divisor = d; switch (classify(dividend)) { case zero: switch (classify(divisor)) { case zero: if (classify(r) != NaN) return 1; break; case non_zero: if (classify(r) != zero) return 1; break; case inf: if (classify(r) != zero) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case non_zero: switch (classify(divisor)) { case zero: if (classify(r) != inf) return 1; break; case non_zero: if (classify(r) != non_zero) return 1; { long double _Complex z = (a * c + b * d) / (c * c + d * d) + (b * c - a * d) / (c * c + d * d) * _Complex_I; if (cabs((r - z)/r) > 1.e-6) return 1; } break; case inf: if (classify(r) != zero) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case inf: switch (classify(divisor)) { case zero: if (classify(r) != inf) return 1; break; case non_zero: if (classify(r) != inf) return 1; break; case inf: if (classify(r) != NaN) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case NaN: switch (classify(divisor)) { case zero: if (classify(r) != NaN) return 1; break; case non_zero: if (classify(r) != NaN) return 1; break; case inf: if (classify(r) != NaN) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case non_zero_nan: switch (classify(divisor)) { case zero: if (classify(r) != inf) return 1; break; case non_zero: if (classify(r) != NaN) return 1; break; case inf: if (classify(r) != NaN) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; } return 0; } long double x[][2] = { { 1.e-6, 1.e-6}, {-1.e-6, 1.e-6}, {-1.e-6, -1.e-6}, { 1.e-6, -1.e-6}, { 1.e+6, 1.e-6}, {-1.e+6, 1.e-6}, {-1.e+6, -1.e-6}, { 1.e+6, -1.e-6}, { 1.e-6, 1.e+6}, {-1.e-6, 1.e+6}, {-1.e-6, -1.e+6}, { 1.e-6, -1.e+6}, { 1.e+6, 1.e+6}, {-1.e+6, 1.e+6}, {-1.e+6, -1.e+6}, { 1.e+6, -1.e+6}, {NAN, NAN}, {-INFINITY, NAN}, {-2, NAN}, {-1, NAN}, {-0.5, NAN}, {-0., NAN}, {+0., NAN}, {0.5, NAN}, {1, NAN}, {2, NAN}, {INFINITY, NAN}, {NAN, -INFINITY}, {-INFINITY, -INFINITY}, {-2, -INFINITY}, {-1, -INFINITY}, {-0.5, -INFINITY}, {-0., -INFINITY}, {+0., -INFINITY}, {0.5, -INFINITY}, {1, -INFINITY}, {2, -INFINITY}, {INFINITY, -INFINITY}, {NAN, -2}, {-INFINITY, -2}, {-2, -2}, {-1, -2}, {-0.5, -2}, {-0., -2}, {+0., -2}, {0.5, -2}, {1, -2}, {2, -2}, {INFINITY, -2}, {NAN, -1}, {-INFINITY, -1}, {-2, -1}, {-1, -1}, {-0.5, -1}, {-0., -1}, {+0., -1}, {0.5, -1}, {1, -1}, {2, -1}, {INFINITY, -1}, {NAN, -0.5}, {-INFINITY, -0.5}, {-2, -0.5}, {-1, -0.5}, {-0.5, -0.5}, {-0., -0.5}, {+0., -0.5}, {0.5, -0.5}, {1, -0.5}, {2, -0.5}, {INFINITY, -0.5}, {NAN, -0.}, {-INFINITY, -0.}, {-2, -0.}, {-1, -0.}, {-0.5, -0.}, {-0., -0.}, {+0., -0.}, {0.5, -0.}, {1, -0.}, {2, -0.}, {INFINITY, -0.}, {NAN, 0.}, {-INFINITY, 0.}, {-2, 0.}, {-1, 0.}, {-0.5, 0.}, {-0., 0.}, {+0., 0.}, {0.5, 0.}, {1, 0.}, {2, 0.}, {INFINITY, 0.}, {NAN, 0.5}, {-INFINITY, 0.5}, {-2, 0.5}, {-1, 0.5}, {-0.5, 0.5}, {-0., 0.5}, {+0., 0.5}, {0.5, 0.5}, {1, 0.5}, {2, 0.5}, {INFINITY, 0.5}, {NAN, 1}, {-INFINITY, 1}, {-2, 1}, {-1, 1}, {-0.5, 1}, {-0., 1}, {+0., 1}, {0.5, 1}, {1, 1}, {2, 1}, {INFINITY, 1}, {NAN, 2}, {-INFINITY, 2}, {-2, 2}, {-1, 2}, {-0.5, 2}, {-0., 2}, {+0., 2}, {0.5, 2}, {1, 2}, {2, 2}, {INFINITY, 2}, {NAN, INFINITY}, {-INFINITY, INFINITY}, {-2, INFINITY}, {-1, INFINITY}, {-0.5, INFINITY}, {-0., INFINITY}, {+0., INFINITY}, {0.5, INFINITY}, {1, INFINITY}, {2, INFINITY}, {INFINITY, INFINITY} }; #endif int main() { #if !_ARCH_PPC const unsigned N = sizeof(x) / sizeof(x[0]); unsigned i, j; for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { if (test__divxc3(x[i][0], x[i][1], x[j][0], x[j][1])) return 1; } } #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/builtins/Unit/fixunstfti_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/fixunstfti_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/fixunstfti_test.c (revision 317953) @@ -1,104 +1,106 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t //===-- fixunstfti_test.c - Test __fixunstfti -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __fixunstfti for the compiler_rt library. // //===----------------------------------------------------------------------===// #include +// UNSUPPORTED: mips + #if __LDBL_MANT_DIG__ == 113 #include "fp_test.h" #include "int_lib.h" // Returns: convert a to a unsigned long long, rounding toward zero. // Negative values all become zero. // Assumption: long double is a 128 bit floating point type // tu_int is a 128 bit integral type // value in long double is representable in tu_int or is negative // (no range checking performed) COMPILER_RT_ABI tu_int __fixunstfti(long double a); int test__fixunstfti(long double a, tu_int expected) { tu_int x = __fixunstfti(a); if (x != expected) { twords xt; xt.all = x; twords expectedt; expectedt.all = expected; printf("error in __fixunstfti(%.20Lf) = 0x%.16llX%.16llX, " "expected 0x%.16llX%.16llX\n", a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); } return x != expected; } char assumption_1[sizeof(tu_int) == 4*sizeof(su_int)] = {0}; char assumption_2[sizeof(tu_int)*CHAR_BIT == 128] = {0}; char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; #endif int main() { #if __LDBL_MANT_DIG__ == 113 if (test__fixunstfti(makeInf128(), make_ti(0xffffffffffffffffLL, 0xffffffffffffffffLL))) return 1; if (test__fixunstfti(0.0, 0)) return 1; if (test__fixunstfti(0.5, 0)) return 1; if (test__fixunstfti(0.99, 0)) return 1; if (test__fixunstfti(1.0, 1)) return 1; if (test__fixunstfti(1.5, 1)) return 1; if (test__fixunstfti(1.99, 1)) return 1; if (test__fixunstfti(2.0, 2)) return 1; if (test__fixunstfti(2.01, 2)) return 1; if (test__fixunstfti(-0.01, 0)) return 1; if (test__fixunstfti(-0.99, 0)) return 1; if (test__fixunstfti(0x1.p+128, make_ti(0xffffffffffffffffLL, 0xffffffffffffffffLL))) return 1; if (test__fixunstfti(0x1.FFFFFEp+126, make_ti(0x7fffff8000000000LL, 0x0))) return 1; if (test__fixunstfti(0x1.FFFFFEp+127, make_ti(0xffffff0000000000LL, 0x0))) return 1; if (test__fixunstfti(0x1.FFFFFEp+128, make_ti(0xffffffffffffffffLL, 0xffffffffffffffffLL))) return 1; if (test__fixunstfti(0x1.FFFFFEp+129, make_ti(0xffffffffffffffffLL, 0xffffffffffffffffLL))) return 1; #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/builtins/Unit/fixunsxfti_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/fixunsxfti_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/fixunsxfti_test.c (revision 317953) @@ -1,145 +1,147 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t // XFAIL: aarch64 // test fails for aarch64 (see pr32260) +// UNSUPPORTED: mips + //===-- fixunsxfti_test.c - Test __fixunsxfti -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __fixunsxfti for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "int_lib.h" #include #ifdef CRT_HAS_128BIT // Returns: convert a to a unsigned long long, rounding toward zero. // Negative values all become zero. // Assumption: long double is an intel 80 bit floating point type padded with 6 bytes // tu_int is a 64 bit integral type // value in long double is representable in tu_int or is negative // (no range checking performed) // gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | // 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm COMPILER_RT_ABI tu_int __fixunsxfti(long double a); int test__fixunsxfti(long double a, tu_int expected) { tu_int x = __fixunsxfti(a); if (x != expected) { utwords xt; xt.all = x; utwords expectedt; expectedt.all = expected; printf("error in __fixunsxfti(%LA) = 0x%.16llX%.16llX, expected 0x%.16llX%.16llX\n", a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); } return x != expected; } char assumption_1[sizeof(tu_int) == 2*sizeof(du_int)] = {0}; char assumption_2[sizeof(tu_int)*CHAR_BIT == 128] = {0}; char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; #endif int main() { #ifdef CRT_HAS_128BIT if (test__fixunsxfti(0.0, 0)) return 1; if (test__fixunsxfti(0.5, 0)) return 1; if (test__fixunsxfti(0.99, 0)) return 1; if (test__fixunsxfti(1.0, 1)) return 1; if (test__fixunsxfti(1.5, 1)) return 1; if (test__fixunsxfti(1.99, 1)) return 1; if (test__fixunsxfti(2.0, 2)) return 1; if (test__fixunsxfti(2.01, 2)) return 1; if (test__fixunsxfti(-0.5, 0)) return 1; if (test__fixunsxfti(-0.99, 0)) return 1; if (test__fixunsxfti(-1.0, 0)) return 1; if (test__fixunsxfti(-1.5, 0)) return 1; if (test__fixunsxfti(-1.99, 0)) return 1; if (test__fixunsxfti(-2.0, 0)) return 1; if (test__fixunsxfti(-2.01, 0)) return 1; if (test__fixunsxfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000LL)) return 1; if (test__fixunsxfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000LL)) return 1; if (test__fixunsxfti(-0x1.FFFFFEp+62, 0)) return 1; if (test__fixunsxfti(-0x1.FFFFFCp+62, 0)) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00LL)) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800LL)) return 1; if (test__fixunsxfti(-0x1.FFFFFFFFFFFFFp+62, 0)) return 1; if (test__fixunsxfti(-0x1.FFFFFFFFFFFFEp+62, 0)) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFFFEp+63L, 0xFFFFFFFFFFFFFFFFLL)) return 1; if (test__fixunsxfti(0x1.0000000000000002p+63L, 0x8000000000000001LL)) return 1; if (test__fixunsxfti(0x1.0000000000000000p+63L, 0x8000000000000000LL)) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFFFCp+62L, 0x7FFFFFFFFFFFFFFFLL)) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFFF8p+62L, 0x7FFFFFFFFFFFFFFELL)) return 1; if (test__fixunsxfti(-0x1.0000000000000000p+63L, 0)) return 1; if (test__fixunsxfti(-0x1.FFFFFFFFFFFFFFFCp+62L, 0)) return 1; if (test__fixunsxfti(-0x1.FFFFFFFFFFFFFFF8p+62L, 0)) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFFFEp+127L, make_ti(0xFFFFFFFFFFFFFFFFLL, 0))) return 1; if (test__fixunsxfti(0x1.0000000000000002p+127L, make_ti(0x8000000000000001LL, 0))) return 1; if (test__fixunsxfti(0x1.0000000000000000p+127L, make_ti(0x8000000000000000LL, 0))) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFFFCp+126L, make_ti(0x7FFFFFFFFFFFFFFFLL, 0))) return 1; if (test__fixunsxfti(0x1.FFFFFFFFFFFFFFF8p+126L, make_ti(0x7FFFFFFFFFFFFFFELL, 0))) return 1; #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/builtins/Unit/fixxfti_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/fixxfti_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/fixxfti_test.c (revision 317953) @@ -1,150 +1,152 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t // XFAIL: aarch64 // test fails for aarch64 (see pr32260) +// UNSUPPORTED: mips + //===-- fixxfti_test.c - Test __fixxfti -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __fixxfti for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "int_lib.h" #include #ifdef CRT_HAS_128BIT // Returns: convert a to a signed long long, rounding toward zero. // Assumption: long double is an intel 80 bit floating point type padded with 6 bytes // su_int is a 32 bit integral type // value in long double is representable in ti_int (no range checking performed) // gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | // 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm COMPILER_RT_ABI ti_int __fixxfti(long double a); int test__fixxfti(long double a, ti_int expected) { ti_int x = __fixxfti(a); if (x != expected) { utwords xt; xt.all = x; utwords expectedt; expectedt.all = expected; printf("error in __fixxfti(%LA) = 0x%.16llX%.16llX, expected 0x%.16llX%.16llX\n", a, xt.s.high, xt.s.low, expectedt.s.high, expectedt.s.low); } return x != expected; } char assumption_1[sizeof(ti_int) == 2*sizeof(di_int)] = {0}; char assumption_2[sizeof(su_int)*CHAR_BIT == 32] = {0}; char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; #endif int main() { #ifdef CRT_HAS_128BIT if (test__fixxfti(0.0, 0)) return 1; if (test__fixxfti(0.5, 0)) return 1; if (test__fixxfti(0.99, 0)) return 1; if (test__fixxfti(1.0, 1)) return 1; if (test__fixxfti(1.5, 1)) return 1; if (test__fixxfti(1.99, 1)) return 1; if (test__fixxfti(2.0, 2)) return 1; if (test__fixxfti(2.01, 2)) return 1; if (test__fixxfti(-0.5, 0)) return 1; if (test__fixxfti(-0.99, 0)) return 1; if (test__fixxfti(-1.0, -1)) return 1; if (test__fixxfti(-1.5, -1)) return 1; if (test__fixxfti(-1.99, -1)) return 1; if (test__fixxfti(-2.0, -2)) return 1; if (test__fixxfti(-2.01, -2)) return 1; if (test__fixxfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000LL)) return 1; if (test__fixxfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000LL)) return 1; if (test__fixxfti(-0x1.FFFFFEp+62, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000008000000000LL))) return 1; if (test__fixxfti(-0x1.FFFFFCp+62, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000010000000000LL))) return 1; if (test__fixxfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00LL)) return 1; if (test__fixxfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800LL)) return 1; if (test__fixxfti(-0x1.FFFFFFFFFFFFFp+62, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000000000000400LL))) return 1; if (test__fixxfti(-0x1.FFFFFFFFFFFFEp+62, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000000000000800LL))) return 1; if (test__fixxfti(0x1.FFFFFFFFFFFFFFFCp+62L, 0x7FFFFFFFFFFFFFFFLL)) return 1; if (test__fixxfti(0x1.FFFFFFFFFFFFFFF8p+62L, 0x7FFFFFFFFFFFFFFELL)) return 1; if (test__fixxfti(-0x1.0000000000000000p+63L, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000000000000000LL))) return 1; if (test__fixxfti(-0x1.FFFFFFFFFFFFFFFCp+62L, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000000000000001LL))) return 1; if (test__fixxfti(-0x1.FFFFFFFFFFFFFFF8p+62L, make_ti(0xFFFFFFFFFFFFFFFFLL, 0x8000000000000002LL))) return 1; if (test__fixxfti(0x1.FFFFFFFFFFFFFFFEp+126L, make_ti(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL))) return 1; if (test__fixxfti(0x1.FFFFFFFFFFFFFFFCp+126L, make_ti(0x7FFFFFFFFFFFFFFFLL, 0x0000000000000000LL))) return 1; if (test__fixxfti(-0x1.0000000000000000p+127L, make_ti(0x8000000000000000LL, 0x0000000000000000LL))) return 1; if (test__fixxfti(-0x1.FFFFFFFFFFFFFFFEp+126L, make_ti(0x8000000000000000LL, 0x8000000000000000LL))) return 1; if (test__fixxfti(-0x1.FFFFFFFFFFFFFFFCp+126L, make_ti(0x8000000000000001LL, 0x0000000000000000LL))) return 1; #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/builtins/Unit/floattixf_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/floattixf_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/floattixf_test.c (revision 317953) @@ -1,216 +1,218 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t // XFAIL: aarch64 // test fails for aarch64 (see pr32260) +// UNSUPPORTED: mips + //===-- floattixf.c - Test __floattixf ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __floattixf for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "int_lib.h" #include #include #ifdef CRT_HAS_128BIT // Returns: convert a to a long double, rounding toward even. // Assumption: long double is a IEEE 80 bit floating point type padded to 128 bits // ti_int is a 128 bit integral type // gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | // 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm COMPILER_RT_ABI long double __floattixf(ti_int a); int test__floattixf(ti_int a, long double expected) { long double x = __floattixf(a); if (x != expected) { twords at; at.all = a; printf("error in __floattixf(0x%.16llX%.16llX) = %LA, expected %LA\n", at.s.high, at.s.low, x, expected); } return x != expected; } char assumption_1[sizeof(ti_int) == 2*sizeof(di_int)] = {0}; char assumption_2[sizeof(ti_int)*CHAR_BIT == 128] = {0}; char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; #endif int main() { #ifdef CRT_HAS_128BIT if (test__floattixf(0, 0.0)) return 1; if (test__floattixf(1, 1.0)) return 1; if (test__floattixf(2, 2.0)) return 1; if (test__floattixf(20, 20.0)) return 1; if (test__floattixf(-1, -1.0)) return 1; if (test__floattixf(-2, -2.0)) return 1; if (test__floattixf(-20, -20.0)) return 1; if (test__floattixf(0x7FFFFF8000000000LL, 0x1.FFFFFEp+62)) return 1; if (test__floattixf(0x7FFFFFFFFFFFF800LL, 0x1.FFFFFFFFFFFFEp+62)) return 1; if (test__floattixf(0x7FFFFF0000000000LL, 0x1.FFFFFCp+62)) return 1; if (test__floattixf(0x7FFFFFFFFFFFF000LL, 0x1.FFFFFFFFFFFFCp+62)) return 1; if (test__floattixf(make_ti(0x8000008000000000LL, 0), -0x1.FFFFFEp+126)) return 1; if (test__floattixf(make_ti(0x8000000000000800LL, 0), -0x1.FFFFFFFFFFFFEp+126)) return 1; if (test__floattixf(make_ti(0x8000010000000000LL, 0), -0x1.FFFFFCp+126)) return 1; if (test__floattixf(make_ti(0x8000000000001000LL, 0), -0x1.FFFFFFFFFFFFCp+126)) return 1; if (test__floattixf(make_ti(0x8000000000000000LL, 0), -0x1.000000p+127)) return 1; if (test__floattixf(make_ti(0x8000000000000001LL, 0), -0x1.FFFFFFFFFFFFFFFCp+126L)) return 1; if (test__floattixf(0x0007FB72E8000000LL, 0x1.FEDCBAp+50)) return 1; if (test__floattixf(0x0007FB72EA000000LL, 0x1.FEDCBA8p+50)) return 1; if (test__floattixf(0x0007FB72EB000000LL, 0x1.FEDCBACp+50)) return 1; if (test__floattixf(0x0007FB72EBFFFFFFLL, 0x1.FEDCBAFFFFFFCp+50)) return 1; if (test__floattixf(0x0007FB72EC000000LL, 0x1.FEDCBBp+50)) return 1; if (test__floattixf(0x0007FB72E8000001LL, 0x1.FEDCBA0000004p+50)) return 1; if (test__floattixf(0x0007FB72E6000000LL, 0x1.FEDCB98p+50)) return 1; if (test__floattixf(0x0007FB72E7000000LL, 0x1.FEDCB9Cp+50)) return 1; if (test__floattixf(0x0007FB72E7FFFFFFLL, 0x1.FEDCB9FFFFFFCp+50)) return 1; if (test__floattixf(0x0007FB72E4000001LL, 0x1.FEDCB90000004p+50)) return 1; if (test__floattixf(0x0007FB72E4000000LL, 0x1.FEDCB9p+50)) return 1; if (test__floattixf(0x023479FD0E092DC0LL, 0x1.1A3CFE870496Ep+57)) return 1; if (test__floattixf(0x023479FD0E092DA1LL, 0x1.1A3CFE870496D08p+57L)) return 1; if (test__floattixf(0x023479FD0E092DB0LL, 0x1.1A3CFE870496D8p+57L)) return 1; if (test__floattixf(0x023479FD0E092DB8LL, 0x1.1A3CFE870496DCp+57L)) return 1; if (test__floattixf(0x023479FD0E092DB6LL, 0x1.1A3CFE870496DBp+57L)) return 1; if (test__floattixf(0x023479FD0E092DBFLL, 0x1.1A3CFE870496DF8p+57L)) return 1; if (test__floattixf(0x023479FD0E092DC1LL, 0x1.1A3CFE870496E08p+57L)) return 1; if (test__floattixf(0x023479FD0E092DC7LL, 0x1.1A3CFE870496E38p+57L)) return 1; if (test__floattixf(0x023479FD0E092DC8LL, 0x1.1A3CFE870496E4p+57L)) return 1; if (test__floattixf(0x023479FD0E092DCFLL, 0x1.1A3CFE870496E78p+57L)) return 1; if (test__floattixf(0x023479FD0E092DD0LL, 0x1.1A3CFE870496E8p+57L)) return 1; if (test__floattixf(0x023479FD0E092DD1LL, 0x1.1A3CFE870496E88p+57L)) return 1; if (test__floattixf(0x023479FD0E092DD8LL, 0x1.1A3CFE870496ECp+57L)) return 1; if (test__floattixf(0x023479FD0E092DDFLL, 0x1.1A3CFE870496EF8p+57L)) return 1; if (test__floattixf(0x023479FD0E092DE0LL, 0x1.1A3CFE870496Fp+57)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DC0LL, 0), 0x1.1A3CFE870496Ep+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DA1LL, 1), 0x1.1A3CFE870496D08p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DB0LL, 2), 0x1.1A3CFE870496D8p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DB8LL, 3), 0x1.1A3CFE870496DCp+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DB6LL, 4), 0x1.1A3CFE870496DBp+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DBFLL, 5), 0x1.1A3CFE870496DF8p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DC1LL, 6), 0x1.1A3CFE870496E08p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DC7LL, 7), 0x1.1A3CFE870496E38p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DC8LL, 8), 0x1.1A3CFE870496E4p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DCFLL, 9), 0x1.1A3CFE870496E78p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DD0LL, 0), 0x1.1A3CFE870496E8p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DD1LL, 11), 0x1.1A3CFE870496E88p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DD8LL, 12), 0x1.1A3CFE870496ECp+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DDFLL, 13), 0x1.1A3CFE870496EF8p+121L)) return 1; if (test__floattixf(make_ti(0x023479FD0E092DE0LL, 14), 0x1.1A3CFE870496Fp+121L)) return 1; if (test__floattixf(make_ti(0, 0xFFFFFFFFFFFFFFFFLL), 0x1.FFFFFFFFFFFFFFFEp+63L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x3456100000000001LL), 0x1.2345678901234562p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x3456200000000000LL), 0x1.2345678901234562p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x34562FFFFFFFFFFFLL), 0x1.2345678901234562p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x3456300000000000LL), 0x1.2345678901234564p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x3456400000000000LL), 0x1.2345678901234564p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x34564FFFFFFFFFFFLL), 0x1.2345678901234564p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x3456500000000000LL), 0x1.2345678901234564p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x3456500000000001LL), 0x1.2345678901234566p+108L)) return 1; if (test__floattixf(make_ti(0x0000123456789012LL, 0x34566FFFFFFFFFFFLL), 0x1.2345678901234566p+108L)) return 1; #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/builtins/Unit/floatuntixf_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/floatuntixf_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/floatuntixf_test.c (revision 317953) @@ -1,223 +1,225 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t // XFAIL: aarch64 // test fails for aarch64 (see pr32260) +// UNSUPPORTED: mips + //===-- floatuntixf.c - Test __floatuntixf --------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __floatuntixf for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "int_lib.h" #include #include #ifdef CRT_HAS_128BIT // Returns: convert a to a long double, rounding toward even. // Assumption: long double is a IEEE 80 bit floating point type padded to 128 bits // tu_int is a 128 bit integral type // gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee | // 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm COMPILER_RT_ABI long double __floatuntixf(tu_int a); int test__floatuntixf(tu_int a, long double expected) { long double x = __floatuntixf(a); if (x != expected) { utwords at; at.all = a; printf("error in __floatuntixf(0x%.16llX%.16llX) = %LA, expected %LA\n", at.s.high, at.s.low, x, expected); } return x != expected; } char assumption_1[sizeof(tu_int) == 2*sizeof(du_int)] = {0}; char assumption_2[sizeof(tu_int)*CHAR_BIT == 128] = {0}; char assumption_3[sizeof(long double)*CHAR_BIT == 128] = {0}; #endif int main() { #ifdef CRT_HAS_128BIT if (test__floatuntixf(0, 0.0)) return 1; if (test__floatuntixf(1, 1.0)) return 1; if (test__floatuntixf(2, 2.0)) return 1; if (test__floatuntixf(20, 20.0)) return 1; if (test__floatuntixf(0x7FFFFF8000000000ULL, 0x1.FFFFFEp+62)) return 1; if (test__floatuntixf(0x7FFFFFFFFFFFF800ULL, 0x1.FFFFFFFFFFFFEp+62)) return 1; if (test__floatuntixf(0x7FFFFF0000000000ULL, 0x1.FFFFFCp+62)) return 1; if (test__floatuntixf(0x7FFFFFFFFFFFF000ULL, 0x1.FFFFFFFFFFFFCp+62)) return 1; if (test__floatuntixf(0x7FFFFFFFFFFFFFFFULL, 0xF.FFFFFFFFFFFFFFEp+59L)) return 1; if (test__floatuntixf(0xFFFFFFFFFFFFFFFEULL, 0xF.FFFFFFFFFFFFFFEp+60L)) return 1; if (test__floatuntixf(0xFFFFFFFFFFFFFFFFULL, 0xF.FFFFFFFFFFFFFFFp+60L)) return 1; if (test__floatuntixf(0x8000008000000000ULL, 0x8.000008p+60)) return 1; if (test__floatuntixf(0x8000000000000800ULL, 0x8.0000000000008p+60)) return 1; if (test__floatuntixf(0x8000010000000000ULL, 0x8.00001p+60)) return 1; if (test__floatuntixf(0x8000000000001000ULL, 0x8.000000000001p+60)) return 1; if (test__floatuntixf(0x8000000000000000ULL, 0x8p+60)) return 1; if (test__floatuntixf(0x8000000000000001ULL, 0x8.000000000000001p+60L)) return 1; if (test__floatuntixf(0x0007FB72E8000000LL, 0x1.FEDCBAp+50)) return 1; if (test__floatuntixf(0x0007FB72EA000000LL, 0x1.FEDCBA8p+50)) return 1; if (test__floatuntixf(0x0007FB72EB000000LL, 0x1.FEDCBACp+50)) return 1; if (test__floatuntixf(0x0007FB72EBFFFFFFLL, 0x1.FEDCBAFFFFFFCp+50)) return 1; if (test__floatuntixf(0x0007FB72EC000000LL, 0x1.FEDCBBp+50)) return 1; if (test__floatuntixf(0x0007FB72E8000001LL, 0x1.FEDCBA0000004p+50)) return 1; if (test__floatuntixf(0x0007FB72E6000000LL, 0x1.FEDCB98p+50)) return 1; if (test__floatuntixf(0x0007FB72E7000000LL, 0x1.FEDCB9Cp+50)) return 1; if (test__floatuntixf(0x0007FB72E7FFFFFFLL, 0x1.FEDCB9FFFFFFCp+50)) return 1; if (test__floatuntixf(0x0007FB72E4000001LL, 0x1.FEDCB90000004p+50)) return 1; if (test__floatuntixf(0x0007FB72E4000000LL, 0x1.FEDCB9p+50)) return 1; if (test__floatuntixf(0x023479FD0E092DC0LL, 0x1.1A3CFE870496Ep+57)) return 1; if (test__floatuntixf(0x023479FD0E092DA1LL, 0x1.1A3CFE870496D08p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DB0LL, 0x1.1A3CFE870496D8p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DB8LL, 0x1.1A3CFE870496DCp+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DB6LL, 0x1.1A3CFE870496DBp+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DBFLL, 0x1.1A3CFE870496DF8p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DC1LL, 0x1.1A3CFE870496E08p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DC7LL, 0x1.1A3CFE870496E38p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DC8LL, 0x1.1A3CFE870496E4p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DCFLL, 0x1.1A3CFE870496E78p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DD0LL, 0x1.1A3CFE870496E8p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DD1LL, 0x1.1A3CFE870496E88p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DD8LL, 0x1.1A3CFE870496ECp+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DDFLL, 0x1.1A3CFE870496EF8p+57L)) return 1; if (test__floatuntixf(0x023479FD0E092DE0LL, 0x1.1A3CFE870496Fp+57)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DC0LL, 0), 0x1.1A3CFE870496Ep+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DA1LL, 1), 0x1.1A3CFE870496D08p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DB0LL, 2), 0x1.1A3CFE870496D8p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DB8LL, 3), 0x1.1A3CFE870496DCp+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DB6LL, 4), 0x1.1A3CFE870496DBp+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DBFLL, 5), 0x1.1A3CFE870496DF8p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DC1LL, 6), 0x1.1A3CFE870496E08p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DC7LL, 7), 0x1.1A3CFE870496E38p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DC8LL, 8), 0x1.1A3CFE870496E4p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DCFLL, 9), 0x1.1A3CFE870496E78p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DD0LL, 0), 0x1.1A3CFE870496E8p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DD1LL, 11), 0x1.1A3CFE870496E88p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DD8LL, 12), 0x1.1A3CFE870496ECp+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DDFLL, 13), 0x1.1A3CFE870496EF8p+121L)) return 1; if (test__floatuntixf(make_ti(0x023479FD0E092DE0LL, 14), 0x1.1A3CFE870496Fp+121L)) return 1; if (test__floatuntixf(make_ti(0, 0xFFFFFFFFFFFFFFFFLL), 0x1.FFFFFFFFFFFFFFFEp+63L)) return 1; if (test__floatuntixf(make_ti(0xFFFFFFFFFFFFFFFFLL, 0x0000000000000000LL), 0x1.FFFFFFFFFFFFFFFEp+127L)) return 1; if (test__floatuntixf(make_ti(0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL), 0x1.0000000000000000p+128L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x3456100000000001LL), 0x1.2345678901234562p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x3456200000000000LL), 0x1.2345678901234562p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x34562FFFFFFFFFFFLL), 0x1.2345678901234562p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x3456300000000000LL), 0x1.2345678901234564p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x3456400000000000LL), 0x1.2345678901234564p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x34564FFFFFFFFFFFLL), 0x1.2345678901234564p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x3456500000000000LL), 0x1.2345678901234564p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x3456500000000001LL), 0x1.2345678901234566p+108L)) return 1; if (test__floatuntixf(make_ti(0x0000123456789012LL, 0x34566FFFFFFFFFFFLL), 0x1.2345678901234566p+108L)) return 1; #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/builtins/Unit/mulxc3_test.c =================================================================== --- vendor/compiler-rt/dist/test/builtins/Unit/mulxc3_test.c (revision 317952) +++ vendor/compiler-rt/dist/test/builtins/Unit/mulxc3_test.c (revision 317953) @@ -1,378 +1,379 @@ // RUN: %clang_builtins %s %librt -lm -o %t && %run %t //===-- mulxc3_test.c - Test __mulxc3 -------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __mulxc3 for the compiler_rt library. // //===----------------------------------------------------------------------===// #if !_ARCH_PPC #include "int_lib.h" #include #include #include +// UNSUPPORTED: mips // REQUIRES: c99-complex // Returns: the product of a + ib and c + id COMPILER_RT_ABI long double _Complex __mulxc3(long double __a, long double __b, long double __c, long double __d); enum {zero, non_zero, inf, NaN, non_zero_nan}; int classify(long double _Complex x) { if (x == 0) return zero; if (isinf(creall(x)) || isinf(cimagl(x))) return inf; if (isnan(creall(x)) && isnan(cimagl(x))) return NaN; if (isnan(creall(x))) { if (cimagl(x) == 0) return NaN; return non_zero_nan; } if (isnan(cimagl(x))) { if (creall(x) == 0) return NaN; return non_zero_nan; } return non_zero; } int test__mulxc3(long double a, long double b, long double c, long double d) { long double _Complex r = __mulxc3(a, b, c, d); // printf("test__mulxc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n", // a, b, c, d, creall(r), cimagl(r)); long double _Complex dividend; long double _Complex divisor; __real__ dividend = a; __imag__ dividend = b; __real__ divisor = c; __imag__ divisor = d; switch (classify(dividend)) { case zero: switch (classify(divisor)) { case zero: if (classify(r) != zero) return 1; break; case non_zero: if (classify(r) != zero) return 1; break; case inf: if (classify(r) != NaN) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case non_zero: switch (classify(divisor)) { case zero: if (classify(r) != zero) return 1; break; case non_zero: if (classify(r) != non_zero) return 1; if (r != a * c - b * d + _Complex_I*(a * d + b * c)) return 1; break; case inf: if (classify(r) != inf) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case inf: switch (classify(divisor)) { case zero: if (classify(r) != NaN) return 1; break; case non_zero: if (classify(r) != inf) return 1; break; case inf: if (classify(r) != inf) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != inf) return 1; break; } break; case NaN: switch (classify(divisor)) { case zero: if (classify(r) != NaN) return 1; break; case non_zero: if (classify(r) != NaN) return 1; break; case inf: if (classify(r) != NaN) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; case non_zero_nan: switch (classify(divisor)) { case zero: if (classify(r) != NaN) return 1; break; case non_zero: if (classify(r) != NaN) return 1; break; case inf: if (classify(r) != inf) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != NaN) return 1; break; } break; } return 0; } long double x[][2] = { { 1.e-6, 1.e-6}, {-1.e-6, 1.e-6}, {-1.e-6, -1.e-6}, { 1.e-6, -1.e-6}, { 1.e+6, 1.e-6}, {-1.e+6, 1.e-6}, {-1.e+6, -1.e-6}, { 1.e+6, -1.e-6}, { 1.e-6, 1.e+6}, {-1.e-6, 1.e+6}, {-1.e-6, -1.e+6}, { 1.e-6, -1.e+6}, { 1.e+6, 1.e+6}, {-1.e+6, 1.e+6}, {-1.e+6, -1.e+6}, { 1.e+6, -1.e+6}, {NAN, NAN}, {-INFINITY, NAN}, {-2, NAN}, {-1, NAN}, {-0.5, NAN}, {-0., NAN}, {+0., NAN}, {0.5, NAN}, {1, NAN}, {2, NAN}, {INFINITY, NAN}, {NAN, -INFINITY}, {-INFINITY, -INFINITY}, {-2, -INFINITY}, {-1, -INFINITY}, {-0.5, -INFINITY}, {-0., -INFINITY}, {+0., -INFINITY}, {0.5, -INFINITY}, {1, -INFINITY}, {2, -INFINITY}, {INFINITY, -INFINITY}, {NAN, -2}, {-INFINITY, -2}, {-2, -2}, {-1, -2}, {-0.5, -2}, {-0., -2}, {+0., -2}, {0.5, -2}, {1, -2}, {2, -2}, {INFINITY, -2}, {NAN, -1}, {-INFINITY, -1}, {-2, -1}, {-1, -1}, {-0.5, -1}, {-0., -1}, {+0., -1}, {0.5, -1}, {1, -1}, {2, -1}, {INFINITY, -1}, {NAN, -0.5}, {-INFINITY, -0.5}, {-2, -0.5}, {-1, -0.5}, {-0.5, -0.5}, {-0., -0.5}, {+0., -0.5}, {0.5, -0.5}, {1, -0.5}, {2, -0.5}, {INFINITY, -0.5}, {NAN, -0.}, {-INFINITY, -0.}, {-2, -0.}, {-1, -0.}, {-0.5, -0.}, {-0., -0.}, {+0., -0.}, {0.5, -0.}, {1, -0.}, {2, -0.}, {INFINITY, -0.}, {NAN, 0.}, {-INFINITY, 0.}, {-2, 0.}, {-1, 0.}, {-0.5, 0.}, {-0., 0.}, {+0., 0.}, {0.5, 0.}, {1, 0.}, {2, 0.}, {INFINITY, 0.}, {NAN, 0.5}, {-INFINITY, 0.5}, {-2, 0.5}, {-1, 0.5}, {-0.5, 0.5}, {-0., 0.5}, {+0., 0.5}, {0.5, 0.5}, {1, 0.5}, {2, 0.5}, {INFINITY, 0.5}, {NAN, 1}, {-INFINITY, 1}, {-2, 1}, {-1, 1}, {-0.5, 1}, {-0., 1}, {+0., 1}, {0.5, 1}, {1, 1}, {2, 1}, {INFINITY, 1}, {NAN, 2}, {-INFINITY, 2}, {-2, 2}, {-1, 2}, {-0.5, 2}, {-0., 2}, {+0., 2}, {0.5, 2}, {1, 2}, {2, 2}, {INFINITY, 2}, {NAN, INFINITY}, {-INFINITY, INFINITY}, {-2, INFINITY}, {-1, INFINITY}, {-0.5, INFINITY}, {-0., INFINITY}, {+0., INFINITY}, {0.5, INFINITY}, {1, INFINITY}, {2, INFINITY}, {INFINITY, INFINITY} }; #endif int main() { #if !_ARCH_PPC const unsigned N = sizeof(x) / sizeof(x[0]); unsigned i, j; for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { if (test__mulxc3(x[i][0], x[i][1], x[j][0], x[j][1])) return 1; } } #else printf("skipped\n"); #endif return 0; } Index: vendor/compiler-rt/dist/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc =================================================================== --- vendor/compiler-rt/dist/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc (nonexistent) +++ vendor/compiler-rt/dist/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc (revision 317953) @@ -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; +} Property changes on: vendor/compiler-rt/dist/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc =================================================================== --- vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc (nonexistent) +++ vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc (revision 317953) @@ -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 + +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{{.*}} Property changes on: vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/Linux/print_stack_trace.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/bool.m =================================================================== --- vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/bool.m (nonexistent) +++ vendor/compiler-rt/dist/test/ubsan/TestCases/Misc/bool.m (revision 317953) @@ -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]] +} Index: vendor/compiler-rt/dist/test/xray/TestCases/Linux/coverage-sample.cc =================================================================== --- vendor/compiler-rt/dist/test/xray/TestCases/Linux/coverage-sample.cc (nonexistent) +++ vendor/compiler-rt/dist/test/xray/TestCases/Linux/coverage-sample.cc (revision 317953) @@ -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 +#include + +std::set 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 +} Property changes on: vendor/compiler-rt/dist/test/xray/TestCases/Linux/coverage-sample.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/compiler-rt/dist/test/xray/TestCases/Linux/func-id-utils.cc =================================================================== --- vendor/compiler-rt/dist/test/xray/TestCases/Linux/func-id-utils.cc (nonexistent) +++ vendor/compiler-rt/dist/test/xray/TestCases/Linux/func-id-utils.cc (revision 317953) @@ -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 +#include +#include +#include +#include + +[[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 must_be_instrumented = {reinterpret_cast(&foo), + reinterpret_cast(&bar), + reinterpret_cast(&main)}; + std::set all_instrumented; + for (auto i = __xray_max_function_id(); i != 0; --i) { + auto addr = __xray_function_address(i); + all_instrumented.insert(reinterpret_cast(addr)); + } + assert(all_instrumented.size() == __xray_max_function_id() && + "each function id must be assigned to a unique function"); + + std::set 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; +} Property changes on: vendor/compiler-rt/dist/test/xray/TestCases/Linux/func-id-utils.cc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property