[sancov] coverage pc buffer

Differential Revision: http://reviews.llvm.org/D15871

llvm-svn: 256804
This commit is contained in:
Mike Aizatsky 2016-01-05 01:49:39 +00:00
parent 40b14d4893
commit 54fc6575c5
4 changed files with 77 additions and 0 deletions

View File

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

View File

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

View File

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

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