mirror of
https://github.com/intel/llvm.git
synced 2026-01-19 09:31:59 +08:00
[asan] add interface function __sanitizer_get_total_unique_coverage; useful for coverage-guided in-process fuzzers
llvm-svn: 222060
This commit is contained in:
@@ -70,6 +70,9 @@ extern "C" {
|
||||
// descriptor. Returns -1 on failure, or if coverage dumping is disabled.
|
||||
// This is intended for use by sandboxing code.
|
||||
intptr_t __sanitizer_maybe_open_cov_file(const char *name);
|
||||
// Get the number of total unique covered entities (blocks, edges, calls).
|
||||
// This can be useful for coverage-directed in-process fuzzers.
|
||||
uintptr_t __sanitizer_get_total_unique_coverage();
|
||||
|
||||
// Annotate the current state of a contiguous container, such as
|
||||
// std::vector, std::string or similar.
|
||||
|
||||
@@ -41,7 +41,9 @@
|
||||
#include "sanitizer_symbolizer.h"
|
||||
#include "sanitizer_flags.h"
|
||||
|
||||
atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
|
||||
static atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
|
||||
|
||||
static atomic_uintptr_t coverage_counter;
|
||||
|
||||
// pc_array is the array containing the covered PCs.
|
||||
// To make the pc_array thread- and async-signal-safe it has to be large enough.
|
||||
@@ -201,6 +203,7 @@ void CoverageData::Add(uptr pc) {
|
||||
CHECK_LT(idx * sizeof(uptr),
|
||||
atomic_load(&pc_array_size, memory_order_acquire));
|
||||
pc_array[idx] = pc;
|
||||
atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Registers a pair caller=>callee.
|
||||
@@ -228,8 +231,10 @@ void CoverageData::IndirCall(uptr caller, uptr callee, uptr callee_cache[],
|
||||
for (uptr i = 2; i < cache_size; i++) {
|
||||
uptr was = 0;
|
||||
if (atomic_compare_exchange_strong(&atomic_callee_cache[i], &was, callee,
|
||||
memory_order_seq_cst))
|
||||
memory_order_seq_cst)) {
|
||||
atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
|
||||
return;
|
||||
}
|
||||
if (was == callee) // Already have this callee.
|
||||
return;
|
||||
}
|
||||
@@ -469,4 +474,8 @@ SANITIZER_INTERFACE_ATTRIBUTE
|
||||
sptr __sanitizer_maybe_open_cov_file(const char *name) {
|
||||
return MaybeOpenCovFile(name);
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
uptr __sanitizer_get_total_unique_coverage() {
|
||||
return atomic_load(&coverage_counter, memory_order_relaxed);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Test __sanitizer_get_total_unique_coverage for caller-callee coverage
|
||||
|
||||
// RUN: %clangxx_asan -fsanitize-coverage=4 %s -o %t
|
||||
// RUN: ASAN_OPTIONS=coverage=1 %run %t
|
||||
// RUN: rm -f caller-callee*.sancov
|
||||
//
|
||||
// REQUIRES: asan-64-bits
|
||||
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
int P = 0;
|
||||
struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
|
||||
struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
||||
struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
||||
|
||||
Foo *foo[3] = {new Foo, new Foo1, new Foo2};
|
||||
|
||||
uintptr_t CheckNewTotalUniqueCoverageIsLargerAndReturnIt(uintptr_t old_total) {
|
||||
uintptr_t new_total = __sanitizer_get_total_unique_coverage();
|
||||
assert(new_total > old_total);
|
||||
return new_total;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
uintptr_t total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(0);
|
||||
foo[0]->f();
|
||||
total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
|
||||
foo[1]->f();
|
||||
total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
|
||||
foo[2]->f();
|
||||
total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
|
||||
// Ok, called every function once.
|
||||
// Now call them again from another call site. Should get new coverage.
|
||||
foo[0]->f();
|
||||
total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
|
||||
foo[1]->f();
|
||||
total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
|
||||
foo[2]->f();
|
||||
total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
|
||||
// XFAIL: android
|
||||
|
||||
#include "sanitizer/common_interface_defs.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -29,8 +31,12 @@ int G[4];
|
||||
int main(int argc, char **argv) {
|
||||
fprintf(stderr, "PID: %d\n", getpid());
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "foo"))
|
||||
if (!strcmp(argv[i], "foo")) {
|
||||
uintptr_t old_coverage = __sanitizer_get_total_unique_coverage();
|
||||
foo();
|
||||
uintptr_t new_coverage = __sanitizer_get_total_unique_coverage();
|
||||
assert(new_coverage > old_coverage);
|
||||
}
|
||||
if (!strcmp(argv[i], "bar"))
|
||||
bar();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user