Merge compiler-rt trunk r338150 (just before the 7.0.0 branch point),

and resolve conflicts.
This commit is contained in:
Dimitry Andric 2018-08-02 18:07:21 +00:00
commit 51511c01aa
14 changed files with 165 additions and 67 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -178,7 +178,7 @@ public:
};
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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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