aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-10-13 15:19:57 +0200
committerDmitry Vyukov <dvyukov@google.com>2015-10-13 15:29:07 +0200
commita02244e1146530937f091684775acc9eb1172986 (patch)
tree8a2fd52fd1f00a3120edb7821feeabaea34d36b2
parentc90d72859537bb8aaff047331bf8d22ca7cc85bc (diff)
deduplicate coverare in executor
This allows to use larger coverage buffer and not overflow output at the same time.
-rw-r--r--executor/executor.cc25
-rw-r--r--fuzzer/fuzzer.go4
-rw-r--r--ipc/ipc.go9
-rw-r--r--tools/execprog/execprog.go4
4 files changed, 34 insertions, 8 deletions
diff --git a/executor/executor.cc b/executor/executor.cc
index e49303101..0fe86031d 100644
--- a/executor/executor.cc
+++ b/executor/executor.cc
@@ -16,6 +16,7 @@
#include <sys/stat.h>
#include <sys/mman.h>
#include <pthread.h>
+#include <algorithm>
#include "syscalls.h"
const int kInFd = 3;
@@ -42,6 +43,7 @@ const uint64_t default_value = -1;
bool flag_debug;
bool flag_cover;
bool flag_threaded;
+bool flag_deduplicate;
__attribute__((aligned(64 << 10))) char input_data[kMaxInput];
__attribute__((aligned(64 << 10))) char output_data[kMaxOutput];
@@ -93,6 +95,7 @@ uint64_t current_time_ms();
void cover_init(thread_t* th);
void cover_reset(thread_t* th);
int cover_read(thread_t* th);
+int cover_dedup(thread_t* th, int n);
int main()
{
@@ -105,6 +108,7 @@ int main()
flag_debug = flags & (1 << 0);
flag_cover = flags & (1 << 1);
flag_threaded = flags & (1 << 2);
+ flag_deduplicate = flags & (1 << 3);
output_pos = (uint32_t*)&output_data[0];
write_output(0); // Number of executed syscalls (updated later).
@@ -218,8 +222,7 @@ thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args,
fail("out of threads");
debug("scheduling call %d [%s] on thread %d\n", call_index, syscalls[call_num].name, th->id);
if (th->ready || !th->done || !th->handled)
- fail("bad thread state in schedule: ready=%d done=%d handled=%d",
- th->ready, th->done, th->handled);
+ fail("bad thread state in schedule: ready=%d done=%d handled=%d", th->ready, th->done, th->handled);
th->copyout_pos = pos;
th->done = false;
th->handled = false;
@@ -340,9 +343,27 @@ int cover_read(thread_t* th)
fail("cover read failed after %s (n=%d)", syscalls[th->call_num].name, n);
n /= sizeof(th->cover_data[0]);
debug("#%d: read /proc/cover = %d\n", th->id, n);
+ if (flag_deduplicate) {
+ n = cover_dedup(th, n);
+ debug("#%d: dedup cover %d\n", th->id, n);
+ }
return n;
}
+int cover_dedup(thread_t* th, int n)
+{
+ std::sort(th->cover_data, th->cover_data + n);
+ int w = 0;
+ uint32_t last = 0;
+ for (int i = 0; i < n; i++) {
+ uint32_t pc = th->cover_data[i];
+ if (pc == last)
+ continue;
+ th->cover_data[w++] = last = pc;
+ }
+ return w;
+}
+
void copyin(char* addr, uint64_t val, uint64_t size)
{
switch (size) {
diff --git a/fuzzer/fuzzer.go b/fuzzer/fuzzer.go
index d27196786..a10250d01 100644
--- a/fuzzer/fuzzer.go
+++ b/fuzzer/fuzzer.go
@@ -102,7 +102,7 @@ func main() {
if *flagParallel <= 0 {
*flagParallel = 1
}
- flags := ipc.FlagCover
+ flags := ipc.FlagCover | ipc.FlagDedupCover
if *flagStrace {
flags |= ipc.FlagStrace
}
@@ -356,7 +356,7 @@ retry:
}
cov := make([]cover.Cover, len(p.Calls))
for i, c := range rawCover {
- cov[i] = cover.Canonicalize(c)
+ cov[i] = cover.Cover(c)
}
return cov
}
diff --git a/ipc/ipc.go b/ipc/ipc.go
index 7702bba66..aa7a0e3a5 100644
--- a/ipc/ipc.go
+++ b/ipc/ipc.go
@@ -30,10 +30,11 @@ type Env struct {
}
const (
- FlagDebug = uint64(1) << iota // debug output from executor
- FlagCover // collect coverage
- FlagThreaded // use multiple threads to mitigate blocked syscalls
- FlagStrace // run executor under strace
+ FlagDebug = uint64(1) << iota // debug output from executor
+ FlagCover // collect coverage
+ FlagThreaded // use multiple threads to mitigate blocked syscalls
+ FlagDedupCover // deduplicate coverage in executor
+ FlagStrace // run executor under strace
)
func MakeEnv(bin string, timeout time.Duration, flags uint64) (*Env, error) {
diff --git a/tools/execprog/execprog.go b/tools/execprog/execprog.go
index 2521426f8..8f642fc66 100644
--- a/tools/execprog/execprog.go
+++ b/tools/execprog/execprog.go
@@ -26,6 +26,7 @@ var (
flagDebug = flag.Bool("debug", true, "debug output from executor")
flagStrace = flag.Bool("strace", false, "run executor under strace")
flagCover = flag.String("cover", "", "collect coverage and write to the file")
+ flagDedup = flag.Bool("dedup", false, "deduplicate coverage in executor")
)
func main() {
@@ -53,6 +54,9 @@ func main() {
if *flagCover != "" {
flags |= ipc.FlagCover
}
+ if *flagDedup {
+ flags |= ipc.FlagDedupCover
+ }
env, err := ipc.MakeEnv(*flagExecutor, 3*time.Second, flags)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create execution environment: %v\n", err)