Vendor import of compiler-rt trunk r338536:
https://llvm.org/svn/llvm-project/compiler-rt/trunk@338536
This commit is contained in:
parent
93c1b73a09
commit
005b7ed8f7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/compiler-rt/dist/; revision=337141 svn path=/vendor/compiler-rt/compiler-rt-trunk-r338536/; revision=337142; tag=vendor/compiler-rt/compiler-rt-trunk-r338536
@ -122,7 +122,7 @@
|
||||
// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
|
||||
// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
|
||||
//
|
||||
// Shadow mapping on NerBSD/i386 with SHADOW_OFFSET == 0x40000000:
|
||||
// Shadow mapping on NetBSD/i386 with SHADOW_OFFSET == 0x40000000:
|
||||
// || `[0x60000000, 0xfffff000]` || HighMem ||
|
||||
// || `[0x4c000000, 0x5fffffff]` || HighShadow ||
|
||||
// || `[0x48000000, 0x4bffffff]` || ShadowGap ||
|
||||
|
@ -963,7 +963,7 @@ TEST(AddressSanitizer, ThreadNamesTest) {
|
||||
#if ASAN_NEEDS_SEGV
|
||||
TEST(AddressSanitizer, ShadowGapTest) {
|
||||
#if SANITIZER_WORDSIZE == 32
|
||||
char *addr = (char*)0x22000000;
|
||||
char *addr = (char*)0x23000000;
|
||||
#else
|
||||
# if defined(__powerpc64__)
|
||||
char *addr = (char*)0x024000800000;
|
||||
|
@ -567,6 +567,15 @@ else ()
|
||||
set(_arch "arm")
|
||||
endif()
|
||||
|
||||
# For ARM archs, exclude any VFP builtins if VFP is not supported
|
||||
if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em)$")
|
||||
string(REPLACE ";" " " _TARGET_${arch}_CFLAGS "${TARGET_${arch}_CFLAGS}")
|
||||
check_compile_definition(__VFP_FP__ "${CMAKE_C_FLAGS} ${_TARGET_${arch}_CFLAGS}" COMPILER_RT_HAS_${arch}_VFP)
|
||||
if(NOT COMPILER_RT_HAS_${arch}_VFP)
|
||||
list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_SOURCES} ${arm_Thumb1_SjLj_EH_SOURCES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# 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.
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "InstrProfiling.h"
|
||||
#include "InstrProfilingUtil.h"
|
||||
|
||||
COMPILER_RT_WEAK unsigned lprofDirMode = 0755;
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void __llvm_profile_recursive_mkdir(char *path) {
|
||||
int i;
|
||||
@ -47,12 +49,19 @@ void __llvm_profile_recursive_mkdir(char *path) {
|
||||
#ifdef _WIN32
|
||||
_mkdir(path);
|
||||
#else
|
||||
mkdir(path, 0755); /* Some of these will fail, ignore it. */
|
||||
/* Some of these will fail, ignore it. */
|
||||
mkdir(path, __llvm_profile_get_dir_mode());
|
||||
#endif
|
||||
path[i] = save;
|
||||
}
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
void __llvm_profile_set_dir_mode(unsigned Mode) { lprofDirMode = Mode; }
|
||||
|
||||
COMPILER_RT_VISIBILITY
|
||||
unsigned __llvm_profile_get_dir_mode(void) { return lprofDirMode; }
|
||||
|
||||
#if COMPILER_RT_HAS_ATOMICS != 1
|
||||
COMPILER_RT_VISIBILITY
|
||||
uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
|
||||
|
@ -16,6 +16,12 @@
|
||||
/*! \brief Create a directory tree. */
|
||||
void __llvm_profile_recursive_mkdir(char *Pathname);
|
||||
|
||||
/*! Set the mode used when creating profile directories. */
|
||||
void __llvm_profile_set_dir_mode(unsigned Mode);
|
||||
|
||||
/*! Return the directory creation mode. */
|
||||
unsigned __llvm_profile_get_dir_mode(void);
|
||||
|
||||
int lprofLockFd(int fd);
|
||||
int lprofUnlockFd(int fd);
|
||||
|
||||
|
@ -73,13 +73,8 @@ class SpinMutex : public StaticSpinMutex {
|
||||
|
||||
class BlockingMutex {
|
||||
public:
|
||||
#if SANITIZER_WINDOWS
|
||||
// Windows does not currently support LinkerInitialized
|
||||
explicit BlockingMutex(LinkerInitialized);
|
||||
#else
|
||||
explicit constexpr BlockingMutex(LinkerInitialized)
|
||||
: opaque_storage_ {0, }, owner_(0) {}
|
||||
#endif
|
||||
: opaque_storage_ {0, }, owner_ {0} {}
|
||||
BlockingMutex();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
@ -767,43 +767,22 @@ void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
|
||||
void internal_join_thread(void *th) { }
|
||||
|
||||
// ---------------------- BlockingMutex ---------------- {{{1
|
||||
const uptr LOCK_UNINITIALIZED = 0;
|
||||
const uptr LOCK_READY = (uptr)-1;
|
||||
|
||||
BlockingMutex::BlockingMutex(LinkerInitialized li) {
|
||||
// FIXME: see comments in BlockingMutex::Lock() for the details.
|
||||
CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);
|
||||
|
||||
CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
|
||||
InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
|
||||
owner_ = LOCK_READY;
|
||||
}
|
||||
|
||||
BlockingMutex::BlockingMutex() {
|
||||
CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
|
||||
InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
|
||||
owner_ = LOCK_READY;
|
||||
CHECK(sizeof(SRWLOCK) <= sizeof(opaque_storage_));
|
||||
internal_memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void BlockingMutex::Lock() {
|
||||
if (owner_ == LOCK_UNINITIALIZED) {
|
||||
// FIXME: hm, global BlockingMutex objects are not initialized?!?
|
||||
// This might be a side effect of the clang+cl+link Frankenbuild...
|
||||
new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));
|
||||
|
||||
// FIXME: If it turns out the linker doesn't invoke our
|
||||
// constructors, we should probably manually Lock/Unlock all the global
|
||||
// locks while we're starting in one thread to avoid double-init races.
|
||||
}
|
||||
EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
|
||||
CHECK_EQ(owner_, LOCK_READY);
|
||||
AcquireSRWLockExclusive((PSRWLOCK)opaque_storage_);
|
||||
CHECK_EQ(owner_, 0);
|
||||
owner_ = GetThreadSelf();
|
||||
}
|
||||
|
||||
void BlockingMutex::Unlock() {
|
||||
CHECK_EQ(owner_, GetThreadSelf());
|
||||
owner_ = LOCK_READY;
|
||||
LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
|
||||
CheckLocked();
|
||||
owner_ = 0;
|
||||
ReleaseSRWLockExclusive((PSRWLOCK)opaque_storage_);
|
||||
}
|
||||
|
||||
void BlockingMutex::CheckLocked() {
|
||||
|
@ -30,6 +30,8 @@ UBSAN_CHECK(IntegerDivideByZero, "integer-divide-by-zero",
|
||||
"integer-divide-by-zero")
|
||||
UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", "float-divide-by-zero")
|
||||
UBSAN_CHECK(InvalidBuiltin, "invalid-builtin-use", "invalid-builtin-use")
|
||||
UBSAN_CHECK(ImplicitIntegerTruncation, "implicit-integer-truncation",
|
||||
"implicit-integer-truncation")
|
||||
UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "shift-base")
|
||||
UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", "shift-exponent")
|
||||
UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "bounds")
|
||||
|
@ -178,7 +178,7 @@ class Diag {
|
||||
};
|
||||
|
||||
private:
|
||||
static const unsigned MaxArgs = 5;
|
||||
static const unsigned MaxArgs = 8;
|
||||
static const unsigned MaxRanges = 1;
|
||||
|
||||
/// The arguments which have been added to this diagnostic so far.
|
||||
|
@ -451,6 +451,49 @@ void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
|
||||
Die();
|
||||
}
|
||||
|
||||
static void handleImplicitConversion(ImplicitConversionData *Data,
|
||||
ReportOptions Opts, ValueHandle Src,
|
||||
ValueHandle Dst) {
|
||||
SourceLocation Loc = Data->Loc.acquire();
|
||||
ErrorType ET = ErrorType::GenericUB;
|
||||
|
||||
switch (Data->Kind) {
|
||||
case ICCK_IntegerTruncation:
|
||||
ET = ErrorType::ImplicitIntegerTruncation;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ignoreReport(Loc, Opts, ET))
|
||||
return;
|
||||
|
||||
const TypeDescriptor &SrcTy = Data->FromType;
|
||||
const TypeDescriptor &DstTy = Data->ToType;
|
||||
|
||||
ScopedReport R(Opts, Loc, ET);
|
||||
|
||||
// FIXME: is it possible to dump the values as hex with fixed width?
|
||||
|
||||
Diag(Loc, DL_Error, ET,
|
||||
"implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
|
||||
"type %4 changed the value to %5 (%6-bit, %7signed)")
|
||||
<< SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
|
||||
<< (SrcTy.isSignedIntegerTy() ? "" : "un") << DstTy << Value(DstTy, Dst)
|
||||
<< DstTy.getIntegerBitWidth() << (DstTy.isSignedIntegerTy() ? "" : "un");
|
||||
}
|
||||
|
||||
void __ubsan::__ubsan_handle_implicit_conversion(ImplicitConversionData *Data,
|
||||
ValueHandle Src,
|
||||
ValueHandle Dst) {
|
||||
GET_REPORT_OPTIONS(false);
|
||||
handleImplicitConversion(Data, Opts, Src, Dst);
|
||||
}
|
||||
void __ubsan::__ubsan_handle_implicit_conversion_abort(
|
||||
ImplicitConversionData *Data, ValueHandle Src, ValueHandle Dst) {
|
||||
GET_REPORT_OPTIONS(true);
|
||||
handleImplicitConversion(Data, Opts, Src, Dst);
|
||||
Die();
|
||||
}
|
||||
|
||||
static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
|
||||
SourceLocation Loc = Data->Loc.acquire();
|
||||
ErrorType ET = ErrorType::InvalidBuiltin;
|
||||
|
@ -122,6 +122,23 @@ struct InvalidValueData {
|
||||
/// \brief Handle a load of an invalid value for the type.
|
||||
RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val)
|
||||
|
||||
/// Known implicit conversion check kinds.
|
||||
/// Keep in sync with the enum of the same name in CGExprScalar.cpp
|
||||
enum ImplicitConversionCheckKind : unsigned char {
|
||||
ICCK_IntegerTruncation = 0,
|
||||
};
|
||||
|
||||
struct ImplicitConversionData {
|
||||
SourceLocation Loc;
|
||||
const TypeDescriptor &FromType;
|
||||
const TypeDescriptor &ToType;
|
||||
/* ImplicitConversionCheckKind */ unsigned char Kind;
|
||||
};
|
||||
|
||||
/// \brief Implict conversion that changed the value.
|
||||
RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src,
|
||||
ValueHandle Dst)
|
||||
|
||||
/// Known builtin check kinds.
|
||||
/// Keep in sync with the enum of the same name in CodeGenFunction.h
|
||||
enum BuiltinCheckKind : unsigned char {
|
||||
|
@ -22,6 +22,8 @@ INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion_abort)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin_abort)
|
||||
INTERFACE_FUNCTION(__ubsan_handle_load_invalid_value)
|
||||
|
@ -109,6 +109,7 @@ HANDLER(float_cast_overflow, "float-cast-overflow")
|
||||
HANDLER(load_invalid_value, "load-invalid-value")
|
||||
HANDLER(invalid_builtin, "invalid-builtin")
|
||||
HANDLER(function_type_mismatch, "function-type-mismatch")
|
||||
HANDLER(implicit_conversion, "implicit-conversion")
|
||||
HANDLER(nonnull_arg, "nonnull-arg")
|
||||
HANDLER(nonnull_return, "nonnull-return")
|
||||
HANDLER(nullability_arg, "nullability-arg")
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "xray_profile_collector.h"
|
||||
#include "xray_profiling_flags.h"
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -24,6 +26,29 @@ namespace {
|
||||
|
||||
static constexpr auto kHeaderSize = 16u;
|
||||
|
||||
constexpr uptr ExpectedProfilingVersion = 0x20180424;
|
||||
|
||||
struct ExpectedProfilingFileHeader {
|
||||
const u64 MagicBytes = 0x7872617970726f66; // Identifier for XRay profiling
|
||||
// files 'xrayprof' in hex.
|
||||
const u64 Version = ExpectedProfilingVersion;
|
||||
u64 Timestamp = 0;
|
||||
u64 PID = 0;
|
||||
};
|
||||
|
||||
void ValidateFileHeaderBlock(XRayBuffer B) {
|
||||
ASSERT_NE(static_cast<const void *>(B.Data), nullptr);
|
||||
ASSERT_EQ(B.Size, sizeof(ExpectedProfilingFileHeader));
|
||||
typename std::aligned_storage<sizeof(ExpectedProfilingFileHeader)>::type
|
||||
FileHeaderStorage;
|
||||
ExpectedProfilingFileHeader ExpectedHeader;
|
||||
std::memcpy(&FileHeaderStorage, B.Data, B.Size);
|
||||
auto &FileHeader =
|
||||
*reinterpret_cast<ExpectedProfilingFileHeader *>(&FileHeaderStorage);
|
||||
ASSERT_EQ(ExpectedHeader.MagicBytes, FileHeader.MagicBytes);
|
||||
ASSERT_EQ(ExpectedHeader.Version, FileHeader.Version);
|
||||
}
|
||||
|
||||
void ValidateBlock(XRayBuffer B) {
|
||||
profilingFlags()->setDefaults();
|
||||
ASSERT_NE(static_cast<const void *>(B.Data), nullptr);
|
||||
@ -107,9 +132,13 @@ TEST(profileCollectorServiceTest, PostSerializeCollect) {
|
||||
// Then we serialize the data.
|
||||
profileCollectorService::serialize();
|
||||
|
||||
// Then we go through a single buffer to see whether we're getting the data we
|
||||
// expect.
|
||||
// Then we go through two buffers to see whether we're getting the data we
|
||||
// expect. The first block must always be as large as a file header, which
|
||||
// will have a fixed size.
|
||||
auto B = profileCollectorService::nextBuffer({nullptr, 0});
|
||||
ValidateFileHeaderBlock(B);
|
||||
|
||||
B = profileCollectorService::nextBuffer(B);
|
||||
ValidateBlock(B);
|
||||
u32 BlockSize;
|
||||
u32 BlockNum;
|
||||
@ -169,6 +198,9 @@ TEST(profileCollectorServiceTest, PostSerializeCollectMultipleThread) {
|
||||
|
||||
// Ensure that we see two buffers.
|
||||
auto B = profileCollectorService::nextBuffer({nullptr, 0});
|
||||
ValidateFileHeaderBlock(B);
|
||||
|
||||
B = profileCollectorService::nextBuffer(B);
|
||||
ValidateBlock(B);
|
||||
|
||||
B = profileCollectorService::nextBuffer(B);
|
||||
|
@ -13,17 +13,50 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "xray_buffer_queue.h"
|
||||
#include "sanitizer_common/sanitizer_allocator_internal.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
#include <memory>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
// no-op on NetBSD (at least), unsupported flag on FreeBSD
|
||||
#define MAP_NORESERVE 0
|
||||
#endif
|
||||
|
||||
using namespace __xray;
|
||||
using namespace __sanitizer;
|
||||
|
||||
template <class T> static T *allocRaw(size_t N) {
|
||||
// TODO: Report errors?
|
||||
// We use MAP_NORESERVE on platforms where it's supported to ensure that the
|
||||
// pages we're allocating for XRay never end up in pages that can be swapped
|
||||
// in/out. We're doing this because for FDR mode, we want to ensure that
|
||||
// writes to the buffers stay resident in memory to prevent XRay itself from
|
||||
// causing swapping/thrashing.
|
||||
//
|
||||
// In the case when XRay pages cannot be swapped in/out or there's not enough
|
||||
// RAM to back these pages, we're willing to cause a segmentation fault
|
||||
// instead of introducing latency in the measurement. We assume here that
|
||||
// there are enough pages that are swappable in/out outside of the buffers
|
||||
// being used by FDR mode (which are bounded and configurable anyway) to allow
|
||||
// us to keep using always-resident memory.
|
||||
//
|
||||
// TODO: Make this configurable?
|
||||
void *A = reinterpret_cast<void *>(
|
||||
internal_mmap(NULL, N * sizeof(T), PROT_WRITE | PROT_READ,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0));
|
||||
return (A == MAP_FAILED) ? nullptr : reinterpret_cast<T *>(A);
|
||||
}
|
||||
|
||||
template <class T> static void deallocRaw(T *ptr, size_t N) {
|
||||
// TODO: Report errors?
|
||||
if (ptr != nullptr)
|
||||
internal_munmap(ptr, N);
|
||||
}
|
||||
|
||||
template <class T> static T *initArray(size_t N) {
|
||||
auto A = reinterpret_cast<T *>(
|
||||
InternalAlloc(N * sizeof(T), nullptr, kCacheLineSize));
|
||||
auto A = allocRaw<T>(N);
|
||||
if (A != nullptr)
|
||||
while (N > 0)
|
||||
new (A + (--N)) T();
|
||||
@ -42,19 +75,19 @@ BufferQueue::BufferQueue(size_t B, size_t N, bool &Success)
|
||||
// Clean up the buffers we've already allocated.
|
||||
for (auto B = Buffers, E = Buffers + BufferCount; B != E; ++B)
|
||||
B->~BufferRep();
|
||||
InternalFree(Buffers);
|
||||
deallocRaw(Buffers, N);
|
||||
Success = false;
|
||||
return;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
auto &T = Buffers[i];
|
||||
void *Tmp = InternalAlloc(BufferSize, nullptr, 64);
|
||||
void *Tmp = allocRaw<char>(BufferSize);
|
||||
if (Tmp == nullptr) {
|
||||
Success = false;
|
||||
return;
|
||||
}
|
||||
void *Extents = InternalAlloc(sizeof(BufferExtents), nullptr, 64);
|
||||
auto *Extents = allocRaw<BufferExtents>(1);
|
||||
if (Extents == nullptr) {
|
||||
Success = false;
|
||||
return;
|
||||
@ -62,7 +95,7 @@ BufferQueue::BufferQueue(size_t B, size_t N, bool &Success)
|
||||
auto &Buf = T.Buff;
|
||||
Buf.Data = Tmp;
|
||||
Buf.Size = B;
|
||||
Buf.Extents = reinterpret_cast<BufferExtents *>(Extents);
|
||||
Buf.Extents = Extents;
|
||||
OwnedBuffers[i] = Tmp;
|
||||
}
|
||||
Success = true;
|
||||
@ -128,11 +161,11 @@ BufferQueue::~BufferQueue() {
|
||||
for (auto I = Buffers, E = Buffers + BufferCount; I != E; ++I) {
|
||||
auto &T = *I;
|
||||
auto &Buf = T.Buff;
|
||||
InternalFree(Buf.Data);
|
||||
InternalFree(Buf.Extents);
|
||||
deallocRaw(Buf.Data, Buf.Size);
|
||||
deallocRaw(Buf.Extents, 1);
|
||||
}
|
||||
for (auto B = Buffers, E = Buffers + BufferCount; B != E; ++B)
|
||||
B->~BufferRep();
|
||||
InternalFree(Buffers);
|
||||
InternalFree(OwnedBuffers);
|
||||
deallocRaw(Buffers, BufferCount);
|
||||
deallocRaw(OwnedBuffers, BufferCount);
|
||||
}
|
||||
|
@ -37,6 +37,19 @@ struct ProfileBuffer {
|
||||
size_t Size;
|
||||
};
|
||||
|
||||
// Current version of the profile format.
|
||||
constexpr u64 XRayProfilingVersion = 0x20180424;
|
||||
|
||||
// Identifier for XRay profiling files 'xrayprof' in hex.
|
||||
constexpr u64 XRayMagicBytes = 0x7872617970726f66;
|
||||
|
||||
struct XRayProfilingFileHeader {
|
||||
const u64 MagicBytes = XRayMagicBytes;
|
||||
const u64 Version = XRayProfilingVersion;
|
||||
u64 Timestamp = 0; // System time in nanoseconds.
|
||||
u64 PID = 0; // Process ID.
|
||||
};
|
||||
|
||||
struct BlockHeader {
|
||||
u32 BlockSize;
|
||||
u32 BlockNum;
|
||||
@ -302,7 +315,22 @@ XRayBuffer nextBuffer(XRayBuffer B) {
|
||||
if (ProfileBuffers == nullptr || ProfileBuffers->Size() == 0)
|
||||
return {nullptr, 0};
|
||||
|
||||
if (B.Data == nullptr)
|
||||
static pthread_once_t Once = PTHREAD_ONCE_INIT;
|
||||
static typename std::aligned_storage<sizeof(XRayProfilingFileHeader)>::type
|
||||
FileHeaderStorage;
|
||||
pthread_once(&Once,
|
||||
+[] { new (&FileHeaderStorage) XRayProfilingFileHeader{}; });
|
||||
|
||||
if (UNLIKELY(B.Data == nullptr)) {
|
||||
// The first buffer should always contain the file header information.
|
||||
auto &FileHeader =
|
||||
*reinterpret_cast<XRayProfilingFileHeader *>(&FileHeaderStorage);
|
||||
FileHeader.Timestamp = NanoTime();
|
||||
FileHeader.PID = internal_getpid();
|
||||
return {&FileHeaderStorage, sizeof(XRayProfilingFileHeader)};
|
||||
}
|
||||
|
||||
if (UNLIKELY(B.Data == &FileHeaderStorage))
|
||||
return {(*ProfileBuffers)[0].Data, (*ProfileBuffers)[0].Size};
|
||||
|
||||
BlockHeader Header;
|
||||
|
@ -32,16 +32,6 @@ namespace __xray {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uptr XRayProfilingVersion = 0x20180424;
|
||||
|
||||
struct XRayProfilingFileHeader {
|
||||
const u64 MagicBytes = 0x7872617970726f66; // Identifier for XRay profiling
|
||||
// files 'xrayprof' in hex.
|
||||
const uptr Version = XRayProfilingVersion;
|
||||
uptr Timestamp = 0; // System time in nanoseconds.
|
||||
uptr PID = 0; // Process ID.
|
||||
};
|
||||
|
||||
atomic_sint32_t ProfilerLogFlushStatus = {
|
||||
XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING};
|
||||
|
||||
@ -144,14 +134,7 @@ XRayLogFlushStatus profilingFlush() XRAY_NEVER_INSTRUMENT {
|
||||
if (Verbosity())
|
||||
Report("profiling: Failed to flush to file, dropping data.\n");
|
||||
} else {
|
||||
XRayProfilingFileHeader Header;
|
||||
Header.Timestamp = NanoTime();
|
||||
Header.PID = internal_getpid();
|
||||
retryingWriteAll(Fd, reinterpret_cast<const char *>(&Header),
|
||||
reinterpret_cast<const char *>(&Header) +
|
||||
sizeof(Header));
|
||||
|
||||
// Now for each of the threads, write out the profile data as we would
|
||||
// Now for each of the buffers, write out the profile data as we would
|
||||
// see it in memory, verbatim.
|
||||
while (B.Data != nullptr && B.Size != 0) {
|
||||
retryingWriteAll(Fd, reinterpret_cast<const char *>(B.Data),
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Regression test for
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=32434
|
||||
|
||||
// RUN: %clangxx_asan -O0 %s -o %t
|
||||
// RUN: %clangxx_asan -fexceptions -O0 %s -o %t
|
||||
// RUN: %run %t
|
||||
|
||||
#include <assert.h>
|
||||
|
27
test/fuzzer/ImplicitIntegerTruncationTest.cpp
Normal file
27
test/fuzzer/ImplicitIntegerTruncationTest.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// Test for signed-integer-overflow.
|
||||
#include <assert.h>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
static volatile int Sink;
|
||||
static unsigned char Large = UINT8_MAX;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
assert(Data);
|
||||
if (Size > 0 && Data[0] == 'H') {
|
||||
Sink = 1;
|
||||
if (Size > 1 && Data[1] == 'i') {
|
||||
Sink = 2;
|
||||
if (Size > 2 && Data[2] == '!') {
|
||||
Large = Large + 1; // 'char overflow'.
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
5
test/fuzzer/fuzzer-implicit-integer-truncation.test
Normal file
5
test/fuzzer/fuzzer-implicit-integer-truncation.test
Normal file
@ -0,0 +1,5 @@
|
||||
RUN: rm -f %t-ImplicitIntegerTruncationTest-Ubsan
|
||||
RUN: %cpp_compiler -fsanitize=implicit-integer-truncation -fno-sanitize-recover=all %S/ImplicitIntegerTruncationTest.cpp -o %t-ImplicitIntegerTruncationTest-Ubsan
|
||||
RUN: not %run %t-ImplicitIntegerTruncationTest-Ubsan 2>&1 | FileCheck %s
|
||||
CHECK: runtime error: implicit conversion from type 'int' of value 256 (32-bit, signed) to type 'unsigned char' changed the value to 0 (8-bit, unsigned)
|
||||
CHECK: Test unit written to ./crash-
|
15
test/profile/Inputs/instrprof-gcov-fork.c
Normal file
15
test/profile/Inputs/instrprof-gcov-fork.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <unistd.h>
|
||||
|
||||
void func1() {}
|
||||
void func2() {}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
func1();
|
||||
|
||||
fork();
|
||||
|
||||
func2();
|
||||
|
||||
return 0;
|
||||
}
|
23
test/profile/Inputs/instrprof-gcov-fork.c.gcov
Normal file
23
test/profile/Inputs/instrprof-gcov-fork.c.gcov
Normal file
@ -0,0 +1,23 @@
|
||||
// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-fork.c
|
||||
// CHECK-NEXT: -: 0:Graph:instrprof-gcov-fork.gcno
|
||||
// CHECK-NEXT: -: 0:Data:instrprof-gcov-fork.gcda
|
||||
// CHECK-NEXT: -: 0:Runs:1
|
||||
// CHECK-NEXT: -: 0:Programs:1
|
||||
// CHECK-NEXT: -: 1:#include <unistd.h>
|
||||
// CHECK-NEXT: -: 2:
|
||||
// CHECK-NEXT:function func1 called 1 returned 100% blocks executed 100%
|
||||
// CHECK-NEXT: 1: 3:void func1() {}
|
||||
// CHECK-NEXT:function func2 called 2 returned 100% blocks executed 100%
|
||||
// CHECK-NEXT: 2: 4:void func2() {}
|
||||
// CHECK-NEXT: -: 5:
|
||||
// CHECK-NEXT:function main called 1 returned 100% blocks executed 100%
|
||||
// CHECK-NEXT: -: 6:int main(void)
|
||||
// CHECK-NEXT: -: 7:{
|
||||
// CHECK-NEXT: 1: 8: func1();
|
||||
// CHECK-NEXT: -: 9:
|
||||
// CHECK-NEXT: 1: 10: fork();
|
||||
// CHECK-NEXT: -: 11:
|
||||
// CHECK-NEXT: 2: 12: func2();
|
||||
// CHECK-NEXT: -: 13:
|
||||
// CHECK-NEXT: 2: 14: return 0;
|
||||
// CHECK-NEXT: -: 15:}
|
18
test/profile/Inputs/instrprof-gcov-switch1.c
Normal file
18
test/profile/Inputs/instrprof-gcov-switch1.c
Normal file
@ -0,0 +1,18 @@
|
||||
int main(void)
|
||||
{
|
||||
int i = 22;
|
||||
|
||||
switch (i) {
|
||||
case 7:
|
||||
break;
|
||||
|
||||
case 22:
|
||||
i = 7;
|
||||
break;
|
||||
|
||||
case 42:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
23
test/profile/Inputs/instrprof-gcov-switch1.c.gcov
Normal file
23
test/profile/Inputs/instrprof-gcov-switch1.c.gcov
Normal file
@ -0,0 +1,23 @@
|
||||
// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-switch1.c
|
||||
// CHECK-NEXT: -: 0:Graph:instrprof-gcov-switch1.gcno
|
||||
// CHECK-NEXT: -: 0:Data:instrprof-gcov-switch1.gcda
|
||||
// CHECK-NEXT: -: 0:Runs:1
|
||||
// CHECK-NEXT: -: 0:Programs:1
|
||||
// CHECK-NEXT: -: 1:int main(void)
|
||||
// CHECK-NEXT: -: 2:{
|
||||
// CHECK-NEXT: 2: 3: int i = 22;
|
||||
// CHECK-NEXT: -: 4:
|
||||
// CHECK-NEXT: 2: 5: switch (i) {
|
||||
// CHECK-NEXT: -: 6: case 7:
|
||||
// CHECK-NEXT: #####: 7: break;
|
||||
// CHECK-NEXT: -: 8:
|
||||
// CHECK-NEXT: -: 9: case 22:
|
||||
// CHECK-NEXT: 1: 10: i = 7;
|
||||
// CHECK-NEXT: 1: 11: break;
|
||||
// CHECK-NEXT: -: 12:
|
||||
// CHECK-NEXT: -: 13: case 42:
|
||||
// CHECK-NEXT: #####: 14: break;
|
||||
// CHECK-NEXT: -: 15: }
|
||||
// CHECK-NEXT: -: 16:
|
||||
// CHECK-NEXT: 1: 17: return 0;
|
||||
// CHECK-NEXT: -: 18:}
|
18
test/profile/Inputs/instrprof-gcov-switch2.c
Normal file
18
test/profile/Inputs/instrprof-gcov-switch2.c
Normal file
@ -0,0 +1,18 @@
|
||||
int main(void)
|
||||
{
|
||||
int i = 22;
|
||||
|
||||
switch (i) {
|
||||
case 7:
|
||||
break;
|
||||
|
||||
case 22:
|
||||
i = 7;
|
||||
|
||||
case 42:
|
||||
i = 22;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
23
test/profile/Inputs/instrprof-gcov-switch2.c.gcov
Normal file
23
test/profile/Inputs/instrprof-gcov-switch2.c.gcov
Normal file
@ -0,0 +1,23 @@
|
||||
// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-switch2.c
|
||||
// CHECK-NEXT: -: 0:Graph:instrprof-gcov-switch2.gcno
|
||||
// CHECK-NEXT: -: 0:Data:instrprof-gcov-switch2.gcda
|
||||
// CHECK-NEXT: -: 0:Runs:1
|
||||
// CHECK-NEXT: -: 0:Programs:1
|
||||
// CHECK-NEXT: -: 1:int main(void)
|
||||
// CHECK-NEXT: -: 2:{
|
||||
// CHECK-NEXT: 3: 3: int i = 22;
|
||||
// CHECK-NEXT: -: 4:
|
||||
// CHECK-NEXT: 3: 5: switch (i) {
|
||||
// CHECK-NEXT: -: 6: case 7:
|
||||
// CHECK-NEXT: #####: 7: break;
|
||||
// CHECK-NEXT: -: 8:
|
||||
// CHECK-NEXT: -: 9: case 22:
|
||||
// CHECK-NEXT: 1: 10: i = 7;
|
||||
// CHECK-NEXT: -: 11:
|
||||
// CHECK-NEXT: -: 12: case 42:
|
||||
// CHECK-NEXT: 1: 13: i = 22;
|
||||
// CHECK-NEXT: 1: 14: break;
|
||||
// CHECK-NEXT: -: 15: }
|
||||
// CHECK-NEXT: -: 16:
|
||||
// CHECK-NEXT: 1: 17: return 0;
|
||||
// CHECK-NEXT: -: 18:}
|
12
test/profile/Posix/instrprof-gcov-fork.test
Normal file
12
test/profile/Posix/instrprof-gcov-fork.test
Normal file
@ -0,0 +1,12 @@
|
||||
XFAIL: *
|
||||
|
||||
RUN: mkdir -p %t.d
|
||||
RUN: cd %t.d
|
||||
|
||||
RUN: %clang --coverage -o %t %S/../Inputs/instrprof-gcov-fork.c
|
||||
RUN: test -f instrprof-gcov-fork.gcno
|
||||
|
||||
RUN: rm -f instrprof-gcov-fork.gcda
|
||||
RUN: %run %t
|
||||
RUN: llvm-cov gcov -b -c instrprof-gcov-fork.gcda
|
||||
RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-fork.c.gcov %S/../Inputs/instrprof-gcov-fork.c.gcov
|
16
test/profile/instrprof-gcov-switch.test
Normal file
16
test/profile/instrprof-gcov-switch.test
Normal file
@ -0,0 +1,16 @@
|
||||
RUN: mkdir -p %t.d
|
||||
RUN: cd %t.d
|
||||
|
||||
RUN: %clang --coverage -o %t %S/Inputs/instrprof-gcov-switch1.c
|
||||
RUN: test -f instrprof-gcov-switch1.gcno
|
||||
RUN: rm -f instrprof-gcov-switch1.gcda
|
||||
RUN: %run %t
|
||||
RUN: llvm-cov gcov instrprof-gcov-switch1.gcda
|
||||
RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-switch1.c.gcov %S/Inputs/instrprof-gcov-switch1.c.gcov
|
||||
|
||||
RUN: %clang --coverage -o %t %S/Inputs/instrprof-gcov-switch2.c
|
||||
RUN: test -f instrprof-gcov-switch2.gcno
|
||||
RUN: rm -f instrprof-gcov-switch2.gcda
|
||||
RUN: %run %t
|
||||
RUN: llvm-cov gcov instrprof-gcov-switch2.gcda
|
||||
RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-switch2.c.gcov %S/Inputs/instrprof-gcov-switch2.c.gcov
|
48
test/profile/instrprof-set-dir-mode.c
Normal file
48
test/profile/instrprof-set-dir-mode.c
Normal file
@ -0,0 +1,48 @@
|
||||
// UNSUPPORTED: windows
|
||||
// RUN: %clang_pgogen -o %t.bin %s -DTESTPATH=\"%t.dir\"
|
||||
// RUN: rm -rf %t.dir
|
||||
// RUN: %run %t.bin
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void __llvm_profile_set_dir_mode(unsigned Mode);
|
||||
unsigned __llvm_profile_get_dir_mode(void);
|
||||
void __llvm_profile_recursive_mkdir(char *Path);
|
||||
|
||||
static int test(unsigned Mode, const char *TestDir) {
|
||||
int Ret = 0;
|
||||
|
||||
/* Create a dir and set the mode accordingly. */
|
||||
char *Dir = strdup(TestDir);
|
||||
if (!Dir)
|
||||
return -1;
|
||||
__llvm_profile_set_dir_mode(Mode);
|
||||
__llvm_profile_recursive_mkdir(Dir);
|
||||
|
||||
if (Mode != __llvm_profile_get_dir_mode())
|
||||
Ret = -1;
|
||||
else {
|
||||
const unsigned Expected = ~umask(0) & Mode;
|
||||
struct stat DirSt;
|
||||
if (stat(Dir, &DirSt) == -1)
|
||||
Ret = -1;
|
||||
else if (DirSt.st_mode != Expected) {
|
||||
printf("Modes do not match: Expected %o but found %o (%s)\n", Expected,
|
||||
DirSt.st_mode, Dir);
|
||||
Ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(Dir);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
if (test(S_IFDIR | 0777, TESTPATH "/foo/bar/baz/") ||
|
||||
test(S_IFDIR | 0666, TESTPATH "/foo/bar/qux/"))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
|
||||
// I'm not sure this is actually *that* issue, but this seems oddly similar to the other XFAIL'ed cases.
|
||||
// XFAIL: android
|
||||
// UNSUPPORTED: ios
|
||||
|
||||
// RUN: rm -f %tmp
|
||||
// RUN: echo "[implicit-integer-truncation]" >> %tmp
|
||||
// RUN: echo "fun:*implicitTruncation*" >> %tmp
|
||||
// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O0 %s -o %t && not %run %t 2>&1
|
||||
// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O1 %s -o %t && not %run %t 2>&1
|
||||
// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O2 %s -o %t && not %run %t 2>&1
|
||||
// RUN: %clang -fsanitize=implicit-integer-truncation -fno-sanitize-recover=implicit-integer-truncation -fsanitize-blacklist=%tmp -O3 %s -o %t && not %run %t 2>&1
|
||||
|
||||
unsigned char implicitTruncation(unsigned int argc) {
|
||||
return argc; // BOOM
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return implicitTruncation(~0U);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// RUN: %clangxx -fsanitize=implicit-integer-truncation %s -o %t
|
||||
// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOTYPE
|
||||
// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TYPE
|
||||
// REQUIRES: !ubsan-standalone && !ubsan-standalone-static
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int main() {
|
||||
uint8_t t0 = (~(uint32_t(0)));
|
||||
// CHECK-NOTYPE: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]:16
|
||||
// CHECK-TYPE: SUMMARY: UndefinedBehaviorSanitizer: implicit-integer-truncation {{.*}}summary.cpp:[[@LINE-2]]:16
|
||||
return 0;
|
||||
}
|
63
test/ubsan/TestCases/ImplicitConversion/integer-truncation.c
Normal file
63
test/ubsan/TestCases/ImplicitConversion/integer-truncation.c
Normal file
@ -0,0 +1,63 @@
|
||||
// RUN: %clang -x c -fsanitize=implicit-integer-truncation %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK
|
||||
// RUN: %clangxx -x c++ -fsanitize=implicit-integer-truncation %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if !defined(__cplusplus)
|
||||
#define bool _Bool
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
// CHECK-NOT: integer-truncation.c
|
||||
|
||||
// Negative tests. Even if they produce unexpected results, this sanitizer does not care.
|
||||
int8_t n0 = (~((uint32_t)0)); // ~0 -> -1, but do not warn.
|
||||
uint8_t n2 = 128;
|
||||
uint8_t n3 = 255;
|
||||
// Bools do not count
|
||||
bool b0 = (~((uint32_t)0));
|
||||
bool b1 = 255;
|
||||
|
||||
// Explicit and-ing of bits will silence it.
|
||||
uint8_t nc0 = (~((uint32_t)0)) & 255;
|
||||
|
||||
// Explicit casts
|
||||
uint8_t i0 = (uint8_t)(~((uint32_t)0));
|
||||
|
||||
#if defined(__cplusplus)
|
||||
uint8_t i1 = uint8_t(~(uint32_t(0)));
|
||||
uint8_t i2 = static_cast<uint8_t>(~(uint32_t(0)));
|
||||
#endif
|
||||
|
||||
// Positive tests.
|
||||
|
||||
uint8_t t_b0 = (~((uint16_t)(0)));
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:18: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'uint8_t' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned)
|
||||
|
||||
uint8_t t_b1 = (~((uint32_t)0));
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:18: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 4294967295 (32-bit, unsigned) to type 'uint8_t' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned)
|
||||
uint16_t t_b2 = (~((uint32_t)0));
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:19: runtime error: implicit conversion from type 'uint32_t' (aka 'unsigned int') of value 4294967295 (32-bit, unsigned) to type 'uint16_t' (aka 'unsigned short') changed the value to 65535 (16-bit, unsigned)
|
||||
|
||||
uint8_t t_b3 = ~((uint64_t)0);
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:18: runtime error: implicit conversion from type 'uint64_t' (aka 'unsigned long{{[^']*}}') of value 18446744073709551615 (64-bit, unsigned) to type 'uint8_t' (aka 'unsigned char') changed the value to 255 (8-bit, unsigned)
|
||||
uint16_t t_b4 = ~((uint64_t)0);
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:19: runtime error: implicit conversion from type 'uint64_t' (aka 'unsigned long{{[^']*}}') of value 18446744073709551615 (64-bit, unsigned) to type 'uint16_t' (aka 'unsigned short') changed the value to 65535 (16-bit, unsigned)
|
||||
uint32_t t_b5 = ~((uint64_t)0);
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:19: runtime error: implicit conversion from type 'uint64_t' (aka 'unsigned long{{[^']*}}') of value 18446744073709551615 (64-bit, unsigned) to type 'uint32_t' (aka 'unsigned int') changed the value to 4294967295 (32-bit, unsigned)
|
||||
|
||||
int8_t t1 = 255;
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 255 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to -1 (8-bit, signed)
|
||||
uint8_t t2 = 256;
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:16: runtime error: implicit conversion from type 'int' of value 256 (32-bit, signed) to type 'uint8_t' (aka 'unsigned char') changed the value to 0 (8-bit, unsigned)
|
||||
int8_t t3 = 256;
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 256 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to 0 (8-bit, signed)
|
||||
uint8_t t4 = 257;
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:16: runtime error: implicit conversion from type 'int' of value 257 (32-bit, signed) to type 'uint8_t' (aka 'unsigned char') changed the value to 1 (8-bit, unsigned)
|
||||
int8_t t5 = 257;
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 257 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to 1 (8-bit, signed)
|
||||
int8_t t6 = 128;
|
||||
// CHECK: {{.*}}integer-truncation.c:[[@LINE-1]]:15: runtime error: implicit conversion from type 'int' of value 128 (32-bit, signed) to type 'int8_t' (aka 'signed char') changed the value to -128 (8-bit, signed)
|
||||
|
||||
return 0;
|
||||
}
|
24
test/ubsan_minimal/TestCases/implicit-integer-truncation.c
Normal file
24
test/ubsan_minimal/TestCases/implicit-integer-truncation.c
Normal file
@ -0,0 +1,24 @@
|
||||
// RUN: %clang -fsanitize=implicit-integer-truncation %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int main() {
|
||||
// CHECK-NOT: integer-truncation.c
|
||||
|
||||
// Negative tests. Even if they produce unexpected results, this sanitizer does not care.
|
||||
int8_t n0 = (~((uint32_t)(0))); // ~0 -> -1, but do not warn.
|
||||
uint8_t n2 = 128;
|
||||
uint8_t n3 = 255;
|
||||
// Bools do not count
|
||||
_Bool b0 = (~((uint32_t)(0)));
|
||||
_Bool b1 = 255;
|
||||
|
||||
// Explicit and-ing of bits will silence it.
|
||||
uint8_t nc0 = ((~((uint32_t)(0))) & 255);
|
||||
|
||||
// Positive tests.
|
||||
uint8_t t0 = (~((uint32_t)(0)));
|
||||
// CHECK: implicit-conversion
|
||||
|
||||
return 0;
|
||||
}
|
@ -51,7 +51,8 @@ volatile int buffer_counter = 0;
|
||||
assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED);
|
||||
assert(__xray_log_process_buffers(process_buffer) ==
|
||||
XRayLogFlushStatus::XRAY_LOG_FLUSHED);
|
||||
// We're running three threds, so we expect three buffers.
|
||||
assert(buffer_counter == 3);
|
||||
// We're running three threads, so we expect four buffers (including the file
|
||||
// header buffer).
|
||||
assert(buffer_counter == 4);
|
||||
assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
|
||||
}
|
||||
|
@ -47,7 +47,10 @@ volatile int buffer_counter = 0;
|
||||
f0();
|
||||
assert(__xray_log_process_buffers(process_buffer) ==
|
||||
XRayLogFlushStatus::XRAY_LOG_FLUSHED);
|
||||
assert(buffer_counter == 1);
|
||||
// There's always at least one buffer, containing the profile file header. We
|
||||
// assert that we have two, to indicate that we're expecting exactly one
|
||||
// thread's worth of data.
|
||||
assert(buffer_counter == 2);
|
||||
assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
|
||||
|
||||
// Let's reset the counter.
|
||||
@ -60,6 +63,6 @@ volatile int buffer_counter = 0;
|
||||
f0();
|
||||
assert(__xray_log_process_buffers(process_buffer) ==
|
||||
XRayLogFlushStatus::XRAY_LOG_FLUSHED);
|
||||
assert(buffer_counter == 1);
|
||||
assert(buffer_counter == 2);
|
||||
assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user