mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-16 05:01:56 +00:00
[sancov] coverage pc buffer
Differential Revision: http://reviews.llvm.org/D15871 llvm-svn: 256804
This commit is contained in:
parent
40b14d4893
commit
54fc6575c5
@ -41,6 +41,13 @@ extern "C" {
|
||||
// Some of the entries in *data will be zero.
|
||||
uintptr_t __sanitizer_get_coverage_guards(uintptr_t **data);
|
||||
|
||||
// Set *data to the growing buffer with covered PCs and return the size
|
||||
// of the buffer. The entries are never zero.
|
||||
// When only unique pcs are collected, the size is equal to
|
||||
// __sanitizer_get_total_unique_coverage.
|
||||
// WARNING: EXPERIMENTAL API.
|
||||
uintptr_t __sanitizer_get_coverage_pc_buffer(uintptr_t **data);
|
||||
|
||||
// The coverage instrumentation may optionally provide imprecise counters.
|
||||
// Rather than exposing the counter values to the user we instead map
|
||||
// the counters to a bitset.
|
||||
|
@ -108,6 +108,7 @@ class CoverageData {
|
||||
|
||||
uptr *data();
|
||||
uptr size();
|
||||
uptr *buffer() const { return pc_buffer; }
|
||||
|
||||
private:
|
||||
void DirectOpen();
|
||||
@ -133,6 +134,8 @@ class CoverageData {
|
||||
// Descriptor of the file mapped pc array.
|
||||
fd_t pc_fd;
|
||||
|
||||
uptr *pc_buffer;
|
||||
|
||||
// Vector of coverage guard arrays, protected by mu.
|
||||
InternalMmapVectorNoCtor<s32*> guard_array_vec;
|
||||
|
||||
@ -209,6 +212,11 @@ void CoverageData::Enable() {
|
||||
atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed);
|
||||
}
|
||||
|
||||
pc_buffer = nullptr;
|
||||
if (common_flags()->coverage_pc_buffer)
|
||||
pc_buffer = reinterpret_cast<uptr *>(MmapNoReserveOrDie(
|
||||
sizeof(uptr) * kPcArrayMaxSize, "CovInit::pc_buffer"));
|
||||
|
||||
cc_array = reinterpret_cast<uptr **>(MmapNoReserveOrDie(
|
||||
sizeof(uptr *) * kCcArrayMaxSize, "CovInit::cc_array"));
|
||||
atomic_store(&cc_array_size, kCcArrayMaxSize, memory_order_relaxed);
|
||||
@ -246,6 +254,10 @@ void CoverageData::Disable() {
|
||||
UnmapOrDie(cc_array, sizeof(uptr *) * kCcArrayMaxSize);
|
||||
cc_array = nullptr;
|
||||
}
|
||||
if (pc_buffer) {
|
||||
UnmapOrDie(pc_buffer, sizeof(uptr) * kPcArrayMaxSize);
|
||||
pc_buffer = nullptr;
|
||||
}
|
||||
if (tr_event_array) {
|
||||
UnmapOrDie(tr_event_array,
|
||||
sizeof(tr_event_array[0]) * kTrEventArrayMaxSize +
|
||||
@ -414,6 +426,7 @@ void CoverageData::Add(uptr pc, u32 *guard) {
|
||||
atomic_load(&pc_array_size, memory_order_acquire));
|
||||
uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
|
||||
pc_array[idx] = BundlePcAndCounter(pc, counter);
|
||||
if (pc_buffer) pc_buffer[counter] = pc;
|
||||
}
|
||||
|
||||
// Registers a pair caller=>callee.
|
||||
@ -943,6 +956,12 @@ uptr __sanitizer_get_coverage_guards(uptr **data) {
|
||||
return coverage_data.size();
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
uptr __sanitizer_get_coverage_pc_buffer(uptr **data) {
|
||||
*data = coverage_data.buffer();
|
||||
return __sanitizer_get_total_unique_coverage();
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
uptr __sanitizer_get_number_of_counters() {
|
||||
return coverage_data.GetNumberOf8bitCounters();
|
||||
|
@ -144,6 +144,9 @@ COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID,
|
||||
COMMON_FLAG(const char *, coverage_dir, ".",
|
||||
"Target directory for coverage dumps. Defaults to the current "
|
||||
"directory.")
|
||||
COMMON_FLAG(bool, coverage_pc_buffer, true,
|
||||
"If set (and if 'coverage' is set too), the pcs would be collected "
|
||||
"in a buffer.")
|
||||
COMMON_FLAG(bool, full_address_space, false,
|
||||
"Sanitize complete address space; "
|
||||
"by default kernel area on 32-bit platforms will not be sanitized")
|
||||
|
48
compiler-rt/test/asan/TestCases/coverage-pc-buffer.cc
Normal file
48
compiler-rt/test/asan/TestCases/coverage-pc-buffer.cc
Normal file
@ -0,0 +1,48 @@
|
||||
// Test __sanitizer_coverage_pc_buffer().
|
||||
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=edge %s -o %t && %run %t
|
||||
|
||||
// UNSUPPORTED: android
|
||||
|
||||
#include <assert.h>
|
||||
#include <sanitizer/coverage_interface.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static volatile int sink;
|
||||
__attribute__((noinline)) void bar() { sink = 2; }
|
||||
__attribute__((noinline)) void foo() { sink = 1; }
|
||||
|
||||
void assertNotZeroPcs(uintptr_t *buf, uintptr_t size) {
|
||||
assert(buf);
|
||||
for (uintptr_t i = 0; i < size; ++i)
|
||||
assert(buf[i]);
|
||||
}
|
||||
|
||||
int main() {
|
||||
uintptr_t *buf = NULL;
|
||||
uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
|
||||
assertNotZeroPcs(buf, sz);
|
||||
assert(sz);
|
||||
|
||||
foo();
|
||||
bar();
|
||||
uintptr_t *buf1 = NULL;
|
||||
uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
|
||||
assertNotZeroPcs(buf1, sz1);
|
||||
assert(buf1 == buf);
|
||||
assert(sz1 > sz);
|
||||
|
||||
bar();
|
||||
uintptr_t *buf2 = NULL;
|
||||
uintptr_t sz2 = __sanitizer_get_coverage_pc_buffer(&buf2);
|
||||
assertNotZeroPcs(buf2, sz2);
|
||||
assert(buf2 == buf);
|
||||
assert(sz2 > sz1);
|
||||
|
||||
__sanitizer_reset_coverage();
|
||||
uintptr_t *buf3 = NULL;
|
||||
uintptr_t sz3 = __sanitizer_get_coverage_pc_buffer(&buf3);
|
||||
assertNotZeroPcs(buf3, sz3);
|
||||
assert(buf3 == buf);
|
||||
assert(sz3 < sz2);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user