summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Aizatsky <aizatsky@chromium.org>2016-08-05 20:09:42 +0000
committerMike Aizatsky <aizatsky@chromium.org>2016-08-05 20:09:42 +0000
commit3ac7cf5c6b6f53bb09e4ba6ba20b152ae3c2e6b4 (patch)
treef36229fc6d97ee92be3a457ee43a46036ef2a7a4
parenta0b4c0e540a9fe703ef2ee8f515bb79b4255e996 (diff)
[sanitizers] trace buffer API to use user-allocated buffer.
Subscribers: kubabrecka Differential Revision: https://reviews.llvm.org/D23186 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@277858 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/sanitizer/coverage_interface.h16
-rw-r--r--lib/asan/asan_win_dll_thunk.cc3
-rw-r--r--lib/sanitizer_common/sanitizer_coverage_libcdep.cc27
-rw-r--r--lib/sanitizer_common/sanitizer_flags.inc3
-rw-r--r--test/asan/TestCases/coverage-pc-buffer.cc40
5 files changed, 45 insertions, 44 deletions
diff --git a/include/sanitizer/coverage_interface.h b/include/sanitizer/coverage_interface.h
index 2dcc09fc8..72ac843fa 100644
--- a/include/sanitizer/coverage_interface.h
+++ b/include/sanitizer/coverage_interface.h
@@ -41,13 +41,6 @@ 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.
@@ -65,6 +58,15 @@ extern "C" {
// __sanitizer_get_number_of_counters bytes long and 8-aligned.
uintptr_t
__sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
+
+ // EXPERIMENTAL API
+ // Set allocated buffer to record new coverage PCs as they are executed.
+ // Buffer length is specified in uptrs.
+ void __sanitizer_set_coverage_pc_buffer(uintptr_t *buffer, uintptr_t length);
+ // Number of pcs recorded in the buffer.
+ // Reset by __sanitizer_reset_coverage();
+ uintptr_t __sanitizer_get_coverage_pc_buffer_pos();
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc
index c8f486704..09c3b201c 100644
--- a/lib/asan/asan_win_dll_thunk.cc
+++ b/lib/asan/asan_win_dll_thunk.cc
@@ -320,7 +320,7 @@ INTERFACE_FUNCTION(__sanitizer_cov_trace_switch)
INTERFACE_FUNCTION(__sanitizer_cov_with_check)
INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)
-INTERFACE_FUNCTION(__sanitizer_get_coverage_pc_buffer)
+INTERFACE_FUNCTION(__sanitizer_get_coverage_pc_buffer_pos)
INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
@@ -338,6 +338,7 @@ INTERFACE_FUNCTION(__sanitizer_reset_coverage)
INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)
+INTERFACE_FUNCTION(__sanitizer_set_coverage_pc_buffer)
INTERFACE_FUNCTION(__sanitizer_set_death_callback)
INTERFACE_FUNCTION(__sanitizer_set_report_path)
INTERFACE_FUNCTION(__sanitizer_set_report_fd)
diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
index 00872666d..2c69788b1 100644
--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
@@ -110,7 +110,8 @@ class CoverageData {
uptr *data();
uptr size() const;
- uptr *buffer() const { return pc_buffer; }
+
+ void SetPcBuffer(uptr* data, uptr length);
private:
struct NamedPcRange {
@@ -143,6 +144,7 @@ class CoverageData {
fd_t pc_fd;
uptr *pc_buffer;
+ uptr pc_buffer_len;
// Vector of coverage guard arrays, protected by mu.
InternalMmapVectorNoCtor<s32*> guard_array_vec;
@@ -216,9 +218,7 @@ void CoverageData::Enable() {
}
pc_buffer = nullptr;
- if (common_flags()->coverage_pc_buffer)
- pc_buffer = reinterpret_cast<uptr *>(MmapNoReserveOrDie(
- sizeof(uptr) * kPcArrayMaxSize, "CovInit::pc_buffer"));
+ pc_buffer_len = 0;
cc_array = reinterpret_cast<uptr **>(MmapNoReserveOrDie(
sizeof(uptr *) * kCcArrayMaxSize, "CovInit::cc_array"));
@@ -257,10 +257,6 @@ 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 +
@@ -429,7 +425,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;
+ if (pc_buffer && counter < pc_buffer_len) pc_buffer[counter] = pc;
}
// Registers a pair caller=>callee.
@@ -883,6 +879,11 @@ void CoverageData::DumpAll() {
DumpCallerCalleePairs();
}
+void CoverageData::SetPcBuffer(uptr* data, uptr length) {
+ pc_buffer = data;
+ pc_buffer_len = length;
+}
+
void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
if (!args) return;
if (!coverage_enabled) return;
@@ -1018,8 +1019,12 @@ uptr __sanitizer_get_coverage_guards(uptr **data) {
}
SANITIZER_INTERFACE_ATTRIBUTE
-uptr __sanitizer_get_coverage_pc_buffer(uptr **data) {
- *data = coverage_data.buffer();
+void __sanitizer_set_coverage_pc_buffer(uptr *data, uptr length) {
+ coverage_data.SetPcBuffer(data, length);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_coverage_pc_buffer_pos() {
return __sanitizer_get_total_unique_coverage();
}
diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc
index 450436a68..8c9bc0e03 100644
--- a/lib/sanitizer_common/sanitizer_flags.inc
+++ b/lib/sanitizer_common/sanitizer_flags.inc
@@ -144,9 +144,6 @@ 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")
diff --git a/test/asan/TestCases/coverage-pc-buffer.cc b/test/asan/TestCases/coverage-pc-buffer.cc
index 5895a5c45..0e0434a5f 100644
--- a/test/asan/TestCases/coverage-pc-buffer.cc
+++ b/test/asan/TestCases/coverage-pc-buffer.cc
@@ -1,11 +1,13 @@
// Test __sanitizer_coverage_pc_buffer().
-// RUN: %clangxx_asan -fsanitize-coverage=edge %s -o %t && %run %t
+// RUN: %clangxx_asan -fsanitize-coverage=edge -std=c++11 %s -O3 -o %t && %run %t
// UNSUPPORTED: android
#include <assert.h>
+#include <memory>
#include <sanitizer/coverage_interface.h>
+#include <stdint.h>
#include <stdio.h>
static volatile int sink;
@@ -19,47 +21,41 @@ void assertNotZeroPcs(uintptr_t *buf, uintptr_t size) {
}
int main() {
+ uintptr_t buf_size = 1 << 20;
+ std::unique_ptr<uintptr_t[]> buf(new uintptr_t[buf_size]);
+ __sanitizer_set_coverage_pc_buffer(buf.get(), buf_size);
+
{
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
- assertNotZeroPcs(buf, sz);
+ uintptr_t sz = __sanitizer_get_coverage_pc_buffer_pos();
+ assertNotZeroPcs(buf.get(), sz);
assert(sz);
}
{
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
+ uintptr_t sz = __sanitizer_get_coverage_pc_buffer_pos();
// call functions for the first time.
foo();
bar();
- uintptr_t *buf1 = NULL;
- uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
- assertNotZeroPcs(buf1, sz1);
- assert(buf1 == buf);
+ uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer_pos();
+ assertNotZeroPcs(buf.get(), sz1);
assert(sz1 > sz);
}
{
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
+ uintptr_t sz = __sanitizer_get_coverage_pc_buffer_pos();
// second call shouldn't increase coverage.
bar();
- uintptr_t *buf1 = NULL;
- uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
- assertNotZeroPcs(buf1, sz1);
- assert(buf1 == buf);
+ uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer_pos();
assert(sz1 == sz);
+ assertNotZeroPcs(buf.get(), sz1);
}
{
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
+ uintptr_t sz = __sanitizer_get_coverage_pc_buffer_pos();
// reset coverage to 0.
__sanitizer_reset_coverage();
- uintptr_t *buf1 = NULL;
- uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
- assertNotZeroPcs(buf1, sz1);
- assert(buf1 == buf);
+ uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer_pos();
+ assertNotZeroPcs(buf.get(), sz1);
assert(sz1 < sz);
}
}