diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:04:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:05:05 +0000 |
| commit | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (patch) | |
| tree | 3a4038f3b7bafaeade9fd6146ea8021237616657 /compiler-rt | |
| parent | 6f8fc217eaa12bf657be1c6468ed9938d10168b3 (diff) | |
Diffstat (limited to 'compiler-rt')
23 files changed, 226 insertions, 187 deletions
diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc index 0544b6b2ef71..62054a6a3df5 100644 --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -660,6 +660,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, * generated profile, and 0 if this is a Clang FE generated profile. * 1 in bit 57 indicates there are context-sensitive records in the profile. * The 59th bit indicates whether to use debug info to correlate profiles. + * The 60th bit indicates single byte coverage instrumentation. + * The 61st bit indicates function entry instrumentation only. */ #define VARIANT_MASKS_ALL 0xff00000000000000ULL #define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) @@ -667,6 +669,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define VARIANT_MASK_CSIR_PROF (0x1ULL << 57) #define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58) #define VARIANT_MASK_DBG_CORRELATE (0x1ULL << 59) +#define VARIANT_MASK_BYTE_COVERAGE (0x1ULL << 60) +#define VARIANT_MASK_FUNCTION_ENTRY_ONLY (0x1ULL << 61) #define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version #define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime #define INSTR_PROF_PROFILE_COUNTER_BIAS_VAR __llvm_profile_counter_bias diff --git a/compiler-rt/include/profile/MemProfData.inc b/compiler-rt/include/profile/MemProfData.inc index d64227e4ba31..20f8308645c1 100644 --- a/compiler-rt/include/profile/MemProfData.inc +++ b/compiler-rt/include/profile/MemProfData.inc @@ -20,11 +20,10 @@ * \*===----------------------------------------------------------------------===*/ - #ifdef _MSC_VER -#define PACKED(__decl__) __pragma(pack(push,1)) __decl__ __pragma(pack(pop)) +#define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop)) #else -#define PACKED(__decl__) __decl__ __attribute__((__packed__)) +#define PACKED(...) __VA_ARGS__ __attribute__((__packed__)) #endif // A 64-bit magic number to uniquely identify the raw binary memprof profile file. @@ -47,14 +46,106 @@ PACKED(struct Header { uint64_t StackOffset; }); + // A struct describing the information necessary to describe a /proc/maps // segment entry for a particular binary/library identified by its build id. PACKED(struct SegmentEntry { uint64_t Start; uint64_t End; uint64_t Offset; - uint8_t BuildId[32]; + // This field is unused until sanitizer procmaps support for build ids for + // Linux-Elf is implemented. + uint8_t BuildId[32] = {0}; + + SegmentEntry(uint64_t S, uint64_t E, uint64_t O) : + Start(S), End(E), Offset(O) {} + + SegmentEntry(const SegmentEntry& S) { + Start = S.Start; + End = S.End; + Offset = S.Offset; + } + + SegmentEntry& operator=(const SegmentEntry& S) { + Start = S.Start; + End = S.End; + Offset = S.Offset; + return *this; + } + + bool operator==(const SegmentEntry& S) const { + return Start == S.Start && + End == S.End && + Offset == S.Offset; + } }); + +// A struct representing the heap allocation characteristics of a particular +// runtime context. This struct is shared between the compiler-rt runtime and +// the raw profile reader. The indexed format uses a separate, self-describing +// backwards compatible format. +PACKED(struct MemInfoBlock { + uint32_t alloc_count; + uint64_t total_access_count, min_access_count, max_access_count; + uint64_t total_size; + uint32_t min_size, max_size; + uint32_t alloc_timestamp, dealloc_timestamp; + uint64_t total_lifetime; + uint32_t min_lifetime, max_lifetime; + uint32_t alloc_cpu_id, dealloc_cpu_id; + uint32_t num_migrated_cpu; + + // Only compared to prior deallocated object currently. + uint32_t num_lifetime_overlaps; + uint32_t num_same_alloc_cpu; + uint32_t num_same_dealloc_cpu; + + uint64_t data_type_id; // TODO: hash of type name + + MemInfoBlock() : alloc_count(0) {} + + MemInfoBlock(uint32_t size, uint64_t access_count, uint32_t alloc_timestamp, + uint32_t dealloc_timestamp, uint32_t alloc_cpu, uint32_t dealloc_cpu) + : alloc_count(1), total_access_count(access_count), + min_access_count(access_count), max_access_count(access_count), + total_size(size), min_size(size), max_size(size), + alloc_timestamp(alloc_timestamp), dealloc_timestamp(dealloc_timestamp), + total_lifetime(dealloc_timestamp - alloc_timestamp), + min_lifetime(total_lifetime), max_lifetime(total_lifetime), + alloc_cpu_id(alloc_cpu), dealloc_cpu_id(dealloc_cpu), + num_lifetime_overlaps(0), num_same_alloc_cpu(0), + num_same_dealloc_cpu(0) { + num_migrated_cpu = alloc_cpu_id != dealloc_cpu_id; + } + + void Merge(const MemInfoBlock &newMIB) { + alloc_count += newMIB.alloc_count; + + total_access_count += newMIB.total_access_count; + min_access_count = newMIB.min_access_count < min_access_count ? newMIB.min_access_count : min_access_count; + max_access_count = newMIB.max_access_count < max_access_count ? newMIB.max_access_count : max_access_count; + + total_size += newMIB.total_size; + min_size = newMIB.min_size < min_size ? newMIB.min_size : min_size; + max_size = newMIB.max_size < max_size ? newMIB.max_size : max_size; + + total_lifetime += newMIB.total_lifetime; + min_lifetime = newMIB.min_lifetime < min_lifetime ? newMIB.min_lifetime : min_lifetime; + max_lifetime = newMIB.max_lifetime > max_lifetime ? newMIB.max_lifetime : max_lifetime; + + // We know newMIB was deallocated later, so just need to check if it was + // allocated before last one deallocated. + num_lifetime_overlaps += newMIB.alloc_timestamp < dealloc_timestamp; + alloc_timestamp = newMIB.alloc_timestamp; + dealloc_timestamp = newMIB.dealloc_timestamp; + + num_same_alloc_cpu += alloc_cpu_id == newMIB.alloc_cpu_id; + num_same_dealloc_cpu += dealloc_cpu_id == newMIB.dealloc_cpu_id; + alloc_cpu_id = newMIB.alloc_cpu_id; + dealloc_cpu_id = newMIB.dealloc_cpu_id; + } +}); + } // namespace memprof } // namespace llvm diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h index 692b8f70c969..ba58ad46f32d 100644 --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -211,6 +211,15 @@ void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf, // Same as __sanitizer_symbolize_pc, but for data section (i.e. globals). void __sanitizer_symbolize_global(void *data_ptr, const char *fmt, char *out_buf, size_t out_buf_size); +// Determine the return address. +#if !defined(_MSC_VER) || defined(__clang__) +#define __sanitizer_return_address() \ + __builtin_extract_return_addr(__builtin_return_address(0)) +#else +extern "C" void *_ReturnAddress(void); +#pragma intrinsic(_ReturnAddress) +#define __sanitizer_return_address() _ReturnAddress() +#endif /// Sets the callback to be called immediately before death on error. /// diff --git a/compiler-rt/lib/builtins/floatsisf.c b/compiler-rt/lib/builtins/floatsisf.c index fe060407755b..c01f81e41e8e 100644 --- a/compiler-rt/lib/builtins/floatsisf.c +++ b/compiler-rt/lib/builtins/floatsisf.c @@ -17,7 +17,7 @@ #include "int_lib.h" -COMPILER_RT_ABI fp_t __floatsisf(int a) { +COMPILER_RT_ABI fp_t __floatsisf(si_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -33,7 +33,7 @@ COMPILER_RT_ABI fp_t __floatsisf(int a) { } // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(a); + const int exponent = (aWidth - 1) - clzsi(a); rep_t result; // Shift a into the significand field, rounding if it is a right-shift diff --git a/compiler-rt/lib/builtins/floatsitf.c b/compiler-rt/lib/builtins/floatsitf.c index f56063f368d9..80a4ef08fb0e 100644 --- a/compiler-rt/lib/builtins/floatsitf.c +++ b/compiler-rt/lib/builtins/floatsitf.c @@ -16,7 +16,7 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -COMPILER_RT_ABI fp_t __floatsitf(int a) { +COMPILER_RT_ABI fp_t __floatsitf(si_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -26,14 +26,14 @@ COMPILER_RT_ABI fp_t __floatsitf(int a) { // All other cases begin by extracting the sign and absolute value of a rep_t sign = 0; - unsigned aAbs = (unsigned)a; + su_int aAbs = (su_int)a; if (a < 0) { sign = signBit; - aAbs = ~(unsigned)a + 1U; + aAbs = ~(su_int)a + (su_int)1U; } // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(aAbs); + const int exponent = (aWidth - 1) - clzsi(aAbs); rep_t result; // Shift a into the significand field and clear the implicit bit. diff --git a/compiler-rt/lib/builtins/floatunsisf.c b/compiler-rt/lib/builtins/floatunsisf.c index 33a1b5ae2a63..ec062b5943e9 100644 --- a/compiler-rt/lib/builtins/floatunsisf.c +++ b/compiler-rt/lib/builtins/floatunsisf.c @@ -17,7 +17,7 @@ #include "int_lib.h" -COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) { +COMPILER_RT_ABI fp_t __floatunsisf(su_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -26,7 +26,7 @@ COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) { return fromRep(0); // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(a); + const int exponent = (aWidth - 1) - clzsi(a); rep_t result; // Shift a into the significand field, rounding if it is a right-shift diff --git a/compiler-rt/lib/builtins/floatunsitf.c b/compiler-rt/lib/builtins/floatunsitf.c index a4bf0f65fe1c..7ba1fb6000dc 100644 --- a/compiler-rt/lib/builtins/floatunsitf.c +++ b/compiler-rt/lib/builtins/floatunsitf.c @@ -16,7 +16,7 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -COMPILER_RT_ABI fp_t __floatunsitf(unsigned int a) { +COMPILER_RT_ABI fp_t __floatunsitf(su_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -25,7 +25,7 @@ COMPILER_RT_ABI fp_t __floatunsitf(unsigned int a) { return fromRep(0); // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(a); + const int exponent = (aWidth - 1) - clzsi(a); rep_t result; // Shift a into the significand field and clear the implicit bit. diff --git a/compiler-rt/lib/builtins/fp_extend.h b/compiler-rt/lib/builtins/fp_extend.h index aad4436730dd..eee4722bf90e 100644 --- a/compiler-rt/lib/builtins/fp_extend.h +++ b/compiler-rt/lib/builtins/fp_extend.h @@ -33,9 +33,9 @@ static __inline int src_rep_t_clz(src_rep_t a) { return __builtin_clzl(a); #else if (a & REP_C(0xffffffff00000000)) - return __builtin_clz(a >> 32); + return clzsi(a >> 32); else - return 32 + __builtin_clz(a & REP_C(0xffffffff)); + return 32 + clzsi(a & REP_C(0xffffffff)); #endif } diff --git a/compiler-rt/lib/builtins/udivmoddi4.c b/compiler-rt/lib/builtins/udivmoddi4.c index ca17b36ce585..123e5fb05f8c 100644 --- a/compiler-rt/lib/builtins/udivmoddi4.c +++ b/compiler-rt/lib/builtins/udivmoddi4.c @@ -82,7 +82,7 @@ COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { r.s.high = n.s.high & (d.s.high - 1); *rem = r.all; } - return n.s.high >> __builtin_ctz(d.s.high); + return n.s.high >> ctzsi(d.s.high); } // K K // --- @@ -112,7 +112,7 @@ COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { *rem = n.s.low & (d.s.low - 1); if (d.s.low == 1) return n.all; - sr = __builtin_ctz(d.s.low); + sr = ctzsi(d.s.low); q.s.high = n.s.high >> sr; q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); return q.all; diff --git a/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp b/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp index fab017aae60b..ea7f5ce40b07 100644 --- a/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp +++ b/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp @@ -40,5 +40,5 @@ void *__hwasan_memmove(void *to, const void *from, uptr size) { reinterpret_cast<uptr>(to), size); CheckAddressSized<ErrorAction::Recover, AccessType::Load>( reinterpret_cast<uptr>(from), size); - return memmove(UntagPtr(to), UntagPtr(from), size); + return memmove(to, from, size); } diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index 9289e06b88fc..10b893391f47 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -401,6 +401,7 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) { // The following prologues cannot be patched because of the short jump // jumping to the patching region. +#if SANITIZER_WINDOWS64 // ntdll!wcslen in Win11 // 488bc1 mov rax,rcx // 0fb710 movzx edx,word ptr [rax] @@ -422,6 +423,7 @@ static const u8 kPrologueWithShortJump2[] = { 0x4c, 0x8b, 0xc1, 0x8a, 0x01, 0x48, 0xff, 0xc1, 0x84, 0xc0, 0x75, 0xf7, }; +#endif // Returns 0 on error. static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { diff --git a/compiler-rt/lib/memprof/memprof_allocator.cpp b/compiler-rt/lib/memprof/memprof_allocator.cpp index 0974b898666b..14e7bfe53534 100644 --- a/compiler-rt/lib/memprof/memprof_allocator.cpp +++ b/compiler-rt/lib/memprof/memprof_allocator.cpp @@ -15,11 +15,11 @@ #include "memprof_allocator.h" #include "memprof_mapping.h" -#include "memprof_meminfoblock.h" #include "memprof_mibmap.h" #include "memprof_rawprofile.h" #include "memprof_stack.h" #include "memprof_thread.h" +#include "profile/MemProfData.inc" #include "sanitizer_common/sanitizer_allocator_checks.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_allocator_report.h" @@ -36,6 +36,42 @@ #include <time.h> namespace __memprof { +namespace { +using ::llvm::memprof::MemInfoBlock; + +void Print(const MemInfoBlock &M, const u64 id, bool print_terse) { + u64 p; + + if (print_terse) { + p = M.total_size * 100 / M.alloc_count; + Printf("MIB:%llu/%u/%llu.%02llu/%u/%u/", id, M.alloc_count, p / 100, + p % 100, M.min_size, M.max_size); + p = M.total_access_count * 100 / M.alloc_count; + Printf("%llu.%02llu/%llu/%llu/", p / 100, p % 100, M.min_access_count, + M.max_access_count); + p = M.total_lifetime * 100 / M.alloc_count; + Printf("%llu.%02llu/%u/%u/", p / 100, p % 100, M.min_lifetime, + M.max_lifetime); + Printf("%u/%u/%u/%u\n", M.num_migrated_cpu, M.num_lifetime_overlaps, + M.num_same_alloc_cpu, M.num_same_dealloc_cpu); + } else { + p = M.total_size * 100 / M.alloc_count; + Printf("Memory allocation stack id = %llu\n", id); + Printf("\talloc_count %u, size (ave/min/max) %llu.%02llu / %u / %u\n", + M.alloc_count, p / 100, p % 100, M.min_size, M.max_size); + p = M.total_access_count * 100 / M.alloc_count; + Printf("\taccess_count (ave/min/max): %llu.%02llu / %llu / %llu\n", p / 100, + p % 100, M.min_access_count, M.max_access_count); + p = M.total_lifetime * 100 / M.alloc_count; + Printf("\tlifetime (ave/min/max): %llu.%02llu / %u / %u\n", p / 100, + p % 100, M.min_lifetime, M.max_lifetime); + Printf("\tnum migrated: %u, num lifetime overlaps: %u, num same alloc " + "cpu: %u, num same dealloc_cpu: %u\n", + M.num_migrated_cpu, M.num_lifetime_overlaps, M.num_same_alloc_cpu, + M.num_same_dealloc_cpu); + } +} +} // namespace static int GetCpuId(void) { // _memprof_preinit is called via the preinit_array, which subsequently calls @@ -240,7 +276,7 @@ struct Allocator { static void PrintCallback(const uptr Key, LockedMemInfoBlock *const &Value, void *Arg) { SpinMutexLock(&Value->mutex); - Value->mib.Print(Key, bool(Arg)); + Print(Value->mib, Key, bool(Arg)); } void FinishAndWrite() { diff --git a/compiler-rt/lib/memprof/memprof_meminfoblock.h b/compiler-rt/lib/memprof/memprof_meminfoblock.h deleted file mode 100644 index 19e424435e79..000000000000 --- a/compiler-rt/lib/memprof/memprof_meminfoblock.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef MEMPROF_MEMINFOBLOCK_H_ -#define MEMPROF_MEMINFOBLOCK_H_ - -#include "memprof_interface_internal.h" // For u32, u64 TODO: Move these out of the internal header. -#include "sanitizer_common/sanitizer_common.h" - -namespace __memprof { - -using __sanitizer::Printf; - -struct MemInfoBlock { - u32 alloc_count; - u64 total_access_count, min_access_count, max_access_count; - u64 total_size; - u32 min_size, max_size; - u32 alloc_timestamp, dealloc_timestamp; - u64 total_lifetime; - u32 min_lifetime, max_lifetime; - u32 alloc_cpu_id, dealloc_cpu_id; - u32 num_migrated_cpu; - - // Only compared to prior deallocated object currently. - u32 num_lifetime_overlaps; - u32 num_same_alloc_cpu; - u32 num_same_dealloc_cpu; - - u64 data_type_id; // TODO: hash of type name - - MemInfoBlock() : alloc_count(0) {} - - MemInfoBlock(u32 size, u64 access_count, u32 alloc_timestamp, - u32 dealloc_timestamp, u32 alloc_cpu, u32 dealloc_cpu) - : alloc_count(1), total_access_count(access_count), - min_access_count(access_count), max_access_count(access_count), - total_size(size), min_size(size), max_size(size), - alloc_timestamp(alloc_timestamp), dealloc_timestamp(dealloc_timestamp), - total_lifetime(dealloc_timestamp - alloc_timestamp), - min_lifetime(total_lifetime), max_lifetime(total_lifetime), - alloc_cpu_id(alloc_cpu), dealloc_cpu_id(dealloc_cpu), - num_lifetime_overlaps(0), num_same_alloc_cpu(0), - num_same_dealloc_cpu(0) { - num_migrated_cpu = alloc_cpu_id != dealloc_cpu_id; - } - - void Print(u64 id, bool print_terse) const { - u64 p; - - if (print_terse) { - p = total_size * 100 / alloc_count; - Printf("MIB:%llu/%u/%llu.%02llu/%u/%u/", id, alloc_count, p / 100, - p % 100, min_size, max_size); - p = total_access_count * 100 / alloc_count; - Printf("%llu.%02llu/%llu/%llu/", p / 100, p % 100, min_access_count, - max_access_count); - p = total_lifetime * 100 / alloc_count; - Printf("%llu.%02llu/%u/%u/", p / 100, p % 100, min_lifetime, - max_lifetime); - Printf("%u/%u/%u/%u\n", num_migrated_cpu, num_lifetime_overlaps, - num_same_alloc_cpu, num_same_dealloc_cpu); - } else { - p = total_size * 100 / alloc_count; - Printf("Memory allocation stack id = %llu\n", id); - Printf("\talloc_count %u, size (ave/min/max) %llu.%02llu / %u / %u\n", - alloc_count, p / 100, p % 100, min_size, max_size); - p = total_access_count * 100 / alloc_count; - Printf("\taccess_count (ave/min/max): %llu.%02llu / %llu / %llu\n", - p / 100, p % 100, min_access_count, max_access_count); - p = total_lifetime * 100 / alloc_count; - Printf("\tlifetime (ave/min/max): %llu.%02llu / %u / %u\n", p / 100, - p % 100, min_lifetime, max_lifetime); - Printf("\tnum migrated: %u, num lifetime overlaps: %u, num same alloc " - "cpu: %u, num same dealloc_cpu: %u\n", - num_migrated_cpu, num_lifetime_overlaps, num_same_alloc_cpu, - num_same_dealloc_cpu); - } - } - - static void printHeader() { - Printf("MIB:StackID/AllocCount/AveSize/MinSize/MaxSize/AveAccessCount/" - "MinAccessCount/MaxAccessCount/AveLifetime/MinLifetime/MaxLifetime/" - "NumMigratedCpu/NumLifetimeOverlaps/NumSameAllocCpu/" - "NumSameDeallocCpu\n"); - } - - void Merge(const MemInfoBlock &newMIB) { - alloc_count += newMIB.alloc_count; - - total_access_count += newMIB.total_access_count; - min_access_count = Min(min_access_count, newMIB.min_access_count); - max_access_count = Max(max_access_count, newMIB.max_access_count); - - total_size += newMIB.total_size; - min_size = Min(min_size, newMIB.min_size); - max_size = Max(max_size, newMIB.max_size); - - total_lifetime += newMIB.total_lifetime; - min_lifetime = Min(min_lifetime, newMIB.min_lifetime); - max_lifetime = Max(max_lifetime, newMIB.max_lifetime); - - // We know newMIB was deallocated later, so just need to check if it was - // allocated before last one deallocated. - num_lifetime_overlaps += newMIB.alloc_timestamp < dealloc_timestamp; - alloc_timestamp = newMIB.alloc_timestamp; - dealloc_timestamp = newMIB.dealloc_timestamp; - - num_same_alloc_cpu += alloc_cpu_id == newMIB.alloc_cpu_id; - num_same_dealloc_cpu += dealloc_cpu_id == newMIB.dealloc_cpu_id; - alloc_cpu_id = newMIB.alloc_cpu_id; - dealloc_cpu_id = newMIB.dealloc_cpu_id; - } - -} __attribute__((packed)); - -} // namespace __memprof - -#endif // MEMPROF_MEMINFOBLOCK_H_ diff --git a/compiler-rt/lib/memprof/memprof_mibmap.cpp b/compiler-rt/lib/memprof/memprof_mibmap.cpp index 47449cf9612b..32f0796c8f24 100644 --- a/compiler-rt/lib/memprof/memprof_mibmap.cpp +++ b/compiler-rt/lib/memprof/memprof_mibmap.cpp @@ -11,10 +11,12 @@ //===----------------------------------------------------------------------===// #include "memprof_mibmap.h" +#include "profile/MemProfData.inc" #include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_mutex.h" namespace __memprof { +using ::llvm::memprof::MemInfoBlock; void InsertOrMerge(const uptr Id, const MemInfoBlock &Block, MIBMapTy &Map) { MIBMapTy::Handle h(&Map, static_cast<uptr>(Id), /*remove=*/false, diff --git a/compiler-rt/lib/memprof/memprof_mibmap.h b/compiler-rt/lib/memprof/memprof_mibmap.h index ed5dda174fe5..a7cd420464e8 100644 --- a/compiler-rt/lib/memprof/memprof_mibmap.h +++ b/compiler-rt/lib/memprof/memprof_mibmap.h @@ -1,7 +1,9 @@ #ifndef MEMPROF_MIBMAP_H_ #define MEMPROF_MIBMAP_H_ -#include "memprof_meminfoblock.h" +#include <stdint.h> + +#include "profile/MemProfData.inc" #include "sanitizer_common/sanitizer_addrhashmap.h" #include "sanitizer_common/sanitizer_mutex.h" @@ -9,7 +11,7 @@ namespace __memprof { struct LockedMemInfoBlock { __sanitizer::StaticSpinMutex mutex; - MemInfoBlock mib; + ::llvm::memprof::MemInfoBlock mib; }; // The MIB map stores a mapping from stack ids to MemInfoBlocks. @@ -17,7 +19,8 @@ typedef __sanitizer::AddrHashMap<LockedMemInfoBlock *, 200003> MIBMapTy; // Insert a new MemInfoBlock or merge with an existing block identified by the // stack id. -void InsertOrMerge(const uptr Id, const MemInfoBlock &Block, MIBMapTy &Map); +void InsertOrMerge(const uptr Id, const ::llvm::memprof::MemInfoBlock &Block, + MIBMapTy &Map); } // namespace __memprof diff --git a/compiler-rt/lib/memprof/memprof_rawprofile.cpp b/compiler-rt/lib/memprof/memprof_rawprofile.cpp index c4800a6df34c..f065e8dbcabc 100644 --- a/compiler-rt/lib/memprof/memprof_rawprofile.cpp +++ b/compiler-rt/lib/memprof/memprof_rawprofile.cpp @@ -2,7 +2,6 @@ #include <stdlib.h> #include <string.h> -#include "memprof_meminfoblock.h" #include "memprof_rawprofile.h" #include "profile/MemProfData.inc" #include "sanitizer_common/sanitizer_allocator_internal.h" @@ -16,6 +15,7 @@ namespace __memprof { using ::__sanitizer::Vector; +using ::llvm::memprof::MemInfoBlock; using SegmentEntry = ::llvm::memprof::SegmentEntry; using Header = ::llvm::memprof::Header; @@ -65,11 +65,8 @@ void SerializeSegmentsToBuffer(MemoryMappingLayoutBase &Layout, for (Layout.Reset(); Layout.Next(&segment);) { if (segment.IsReadable() && segment.IsExecutable()) { - SegmentEntry Entry{}; - Entry.Start = segment.start; - Entry.End = segment.end; - Entry.Offset = segment.offset; - memcpy(Entry.BuildId, segment.uuid, sizeof(segment.uuid)); + // TODO: Record segment.uuid when it is implemented for Linux-Elf. + SegmentEntry Entry(segment.start, segment.end, segment.offset); memcpy(Ptr, &Entry, sizeof(SegmentEntry)); Ptr += sizeof(SegmentEntry); NumSegmentsRecorded++; diff --git a/compiler-rt/lib/memprof/tests/rawprofile.cpp b/compiler-rt/lib/memprof/tests/rawprofile.cpp index 829e18370737..6181d80fadf6 100644 --- a/compiler-rt/lib/memprof/tests/rawprofile.cpp +++ b/compiler-rt/lib/memprof/tests/rawprofile.cpp @@ -3,7 +3,6 @@ #include <cstdint> #include <memory> -#include "memprof/memprof_meminfoblock.h" #include "profile/MemProfData.inc" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_procmaps.h" @@ -14,13 +13,13 @@ namespace { -using ::__memprof::MemInfoBlock; using ::__memprof::MIBMapTy; using ::__memprof::SerializeToRawProfile; using ::__sanitizer::MemoryMappedSegment; using ::__sanitizer::MemoryMappingLayoutBase; using ::__sanitizer::StackDepotPut; using ::__sanitizer::StackTrace; +using ::llvm::memprof::MemInfoBlock; using ::testing::_; using ::testing::Action; using ::testing::DoAll; @@ -33,21 +32,21 @@ public: MOCK_METHOD(void, Reset, (), (override)); }; -u64 PopulateFakeMap(const MemInfoBlock &FakeMIB, uptr StackPCBegin, - MIBMapTy &FakeMap) { +uint64_t PopulateFakeMap(const MemInfoBlock &FakeMIB, uint64_t StackPCBegin, + MIBMapTy &FakeMap) { constexpr int kSize = 5; - uptr array[kSize]; + uint64_t array[kSize]; for (int i = 0; i < kSize; i++) { array[i] = StackPCBegin + i; } StackTrace St(array, kSize); - u32 Id = StackDepotPut(St); + uint32_t Id = StackDepotPut(St); InsertOrMerge(Id, FakeMIB, FakeMap); return Id; } -template <class T = u64> T Read(char *&Buffer) { +template <class T = uint64_t> T Read(char *&Buffer) { static_assert(std::is_pod<T>::value, "Must be a POD type."); assert(reinterpret_cast<size_t>(Buffer) % sizeof(T) == 0 && "Unaligned read!"); @@ -86,12 +85,12 @@ TEST(MemProf, Basic) { FakeMIB.alloc_count = 0x1; FakeMIB.total_access_count = 0x2; - u64 FakeIds[2]; + uint64_t FakeIds[2]; FakeIds[0] = PopulateFakeMap(FakeMIB, /*StackPCBegin=*/2, FakeMap); FakeIds[1] = PopulateFakeMap(FakeMIB, /*StackPCBegin=*/3, FakeMap); char *Ptr = nullptr; - u64 NumBytes = SerializeToRawProfile(FakeMap, Layout, Ptr); + uint64_t NumBytes = SerializeToRawProfile(FakeMap, Layout, Ptr); const char *Buffer = Ptr; ASSERT_GT(NumBytes, 0ULL); @@ -100,10 +99,10 @@ TEST(MemProf, Basic) { // Check the header. EXPECT_THAT(Read(Ptr), MEMPROF_RAW_MAGIC_64); EXPECT_THAT(Read(Ptr), MEMPROF_RAW_VERSION); - const u64 TotalSize = Read(Ptr); - const u64 SegmentOffset = Read(Ptr); - const u64 MIBOffset = Read(Ptr); - const u64 StackOffset = Read(Ptr); + const uint64_t TotalSize = Read(Ptr); + const uint64_t SegmentOffset = Read(Ptr); + const uint64_t MIBOffset = Read(Ptr); + const uint64_t StackOffset = Read(Ptr); // ============= Check sizes and padding. EXPECT_EQ(TotalSize, NumBytes); @@ -117,7 +116,7 @@ TEST(MemProf, Basic) { EXPECT_EQ(MIBOffset - SegmentOffset, 64ULL); EXPECT_EQ(MIBOffset, 112ULL); - // We expect 2 mib entry, 8b for the count and sizeof(u64) + + // We expect 2 mib entry, 8b for the count and sizeof(uint64_t) + // sizeof(MemInfoBlock) contains stack id + MeminfoBlock. EXPECT_EQ(StackOffset - MIBOffset, 8 + 2 * (8 + sizeof(MemInfoBlock))); @@ -129,19 +128,22 @@ TEST(MemProf, Basic) { EXPECT_GE(TotalSize - StackOffset, 8ULL + 2 * (8 + 8 + 5 * 8)); // ============= Check contents. + // The Uuid field is not yet populated on Linux-Elf by the sanitizer procmaps + // library, so we expect it to be filled with 0 for now. unsigned char ExpectedSegmentBytes[64] = { - 0x01, 0, 0, 0, 0, 0, 0, 0, // Number of entries - 0x10, 0, 0, 0, 0, 0, 0, 0, // Start - 0x20, 0, 0, 0, 0, 0, 0, 0, // End - 0x10, 0, 0, 0, 0, 0, 0, 0, // Offset - 0x0C, 0x0, 0xF, 0xF, 0xE, 0xE, // Uuid + 0x01, 0, 0, 0, 0, 0, 0, 0, // Number of entries + 0x10, 0, 0, 0, 0, 0, 0, 0, // Start + 0x20, 0, 0, 0, 0, 0, 0, 0, // End + 0x10, 0, 0, 0, 0, 0, 0, 0, // Offset + 0x0, // Uuid }; EXPECT_EQ(memcmp(Buffer + SegmentOffset, ExpectedSegmentBytes, 64), 0); // Check that the number of entries is 2. - EXPECT_EQ(*reinterpret_cast<const u64 *>(Buffer + MIBOffset), 2ULL); + EXPECT_EQ(*reinterpret_cast<const uint64_t *>(Buffer + MIBOffset), 2ULL); // Check that stack id is set. - EXPECT_EQ(*reinterpret_cast<const u64 *>(Buffer + MIBOffset + 8), FakeIds[0]); + EXPECT_EQ(*reinterpret_cast<const uint64_t *>(Buffer + MIBOffset + 8), + FakeIds[0]); // Only check a few fields of the first MemInfoBlock. unsigned char ExpectedMIBBytes[sizeof(MemInfoBlock)] = { @@ -159,9 +161,9 @@ TEST(MemProf, Basic) { 0); // Check that the number of entries is 2. - EXPECT_EQ(*reinterpret_cast<const u64 *>(Buffer + StackOffset), 2ULL); + EXPECT_EQ(*reinterpret_cast<const uint64_t *>(Buffer + StackOffset), 2ULL); // Check that the 1st stack id is set. - EXPECT_EQ(*reinterpret_cast<const u64 *>(Buffer + StackOffset + 8), + EXPECT_EQ(*reinterpret_cast<const uint64_t *>(Buffer + StackOffset + 8), FakeIds[0]); // Contents are num pcs, value of each pc - 1. unsigned char ExpectedStackBytes[2][6 * 8] = { @@ -184,7 +186,7 @@ TEST(MemProf, Basic) { // Check that the 2nd stack id is set. EXPECT_EQ( - *reinterpret_cast<const u64 *>(Buffer + StackOffset + 8 + 6 * 8 + 8), + *reinterpret_cast<const uint64_t *>(Buffer + StackOffset + 8 + 6 * 8 + 8), FakeIds[1]); EXPECT_EQ(memcmp(Buffer + StackOffset + 16 + 6 * 8 + 8, ExpectedStackBytes[1], diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp index d1b858930a7f..5317af6982a0 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cpp +++ b/compiler-rt/lib/msan/msan_interceptors.cpp @@ -666,7 +666,7 @@ INTERCEPTOR(int, fstat, int fd, void *buf) { #define MSAN_MAYBE_INTERCEPT_FSTAT #endif -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD +#if SANITIZER_GLIBC INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { ENSURE_MSAN_INITED(); int res = REAL(__fxstat)(magic, fd, buf); @@ -679,7 +679,7 @@ INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { #define MSAN_MAYBE_INTERCEPT___FXSTAT #endif -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD +#if SANITIZER_GLIBC INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) { ENSURE_MSAN_INITED(); int res = REAL(__fxstat64)(magic, fd, buf); @@ -704,7 +704,7 @@ INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) { # define MSAN_MAYBE_INTERCEPT_FSTATAT #endif -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD +#if SANITIZER_GLIBC INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf, int flags) { ENSURE_MSAN_INITED(); @@ -717,7 +717,7 @@ INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf, # define MSAN_MAYBE_INTERCEPT___FXSTATAT #endif -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD +#if SANITIZER_GLIBC INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf, int flags) { ENSURE_MSAN_INITED(); diff --git a/compiler-rt/lib/profile/InstrProfiling.c b/compiler-rt/lib/profile/InstrProfiling.c index 557c0da2dbae..ead5e9330734 100644 --- a/compiler-rt/lib/profile/InstrProfiling.c +++ b/compiler-rt/lib/profile/InstrProfiling.c @@ -45,7 +45,9 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) { char *I = __llvm_profile_begin_counters(); char *E = __llvm_profile_end_counters(); - memset(I, 0, E - I); + char ResetValue = + (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) ? 0xFF : 0; + memset(I, ResetValue, E - I); const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); diff --git a/compiler-rt/lib/profile/InstrProfilingBuffer.c b/compiler-rt/lib/profile/InstrProfilingBuffer.c index f3d15511452e..57f8b68919b1 100644 --- a/compiler-rt/lib/profile/InstrProfilingBuffer.c +++ b/compiler-rt/lib/profile/InstrProfilingBuffer.c @@ -65,6 +65,8 @@ uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin, } COMPILER_RT_VISIBILITY size_t __llvm_profile_counter_entry_size(void) { + if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) + return sizeof(uint8_t); return sizeof(uint64_t); } diff --git a/compiler-rt/lib/profile/InstrProfilingMerge.c b/compiler-rt/lib/profile/InstrProfilingMerge.c index 3a520f1488a7..adf866e52cf7 100644 --- a/compiler-rt/lib/profile/InstrProfilingMerge.c +++ b/compiler-rt/lib/profile/InstrProfilingMerge.c @@ -155,8 +155,14 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData, if (SrcCounters < SrcCountersStart || SrcCounters >= SrcNameStart || (SrcCounters + __llvm_profile_counter_entry_size() * NC) > SrcNameStart) return 1; - for (unsigned I = 0; I < NC; I++) - ((uint64_t *)DstCounters)[I] += ((uint64_t *)SrcCounters)[I]; + for (unsigned I = 0; I < NC; I++) { + if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) { + // A value of zero signifies the function is covered. + DstCounters[I] &= SrcCounters[I]; + } else { + ((uint64_t *)DstCounters)[I] += ((uint64_t *)SrcCounters)[I]; + } + } /* Now merge value profile data. */ if (!VPMergeHook) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h index fc13ca52dda7..c2b22cf572a6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h @@ -74,13 +74,12 @@ template <typename T> inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, typename T::Type xchg, memory_order mo) { - typedef typename T::Type Type; - Type cmpv = *cmp; - Type prev; - prev = __sync_val_compare_and_swap(&a->val_dont_use, cmpv, xchg); - if (prev == cmpv) return true; - *cmp = prev; - return false; + // Transitioned from __sync_val_compare_and_swap to support targets like + // SPARC V8 that cannot inline atomic cmpxchg. __atomic_compare_exchange + // can then be resolved from libatomic. __ATOMIC_SEQ_CST is used to best + // match the __sync builtin memory order. + return __atomic_compare_exchange(&a->val_dont_use, cmp, &xchg, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } template<typename T> diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 056bd15e0907..733ae5ee87ef 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -1536,7 +1536,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { return 0; } -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_GLIBC TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1562,7 +1562,7 @@ TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { #endif } -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_GLIBC TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1574,7 +1574,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_GLIBC TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) |
