diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2015-10-13 15:19:57 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2015-10-13 15:29:07 +0200 |
| commit | a02244e1146530937f091684775acc9eb1172986 (patch) | |
| tree | 8a2fd52fd1f00a3120edb7821feeabaea34d36b2 | |
| parent | c90d72859537bb8aaff047331bf8d22ca7cc85bc (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.cc | 25 | ||||
| -rw-r--r-- | fuzzer/fuzzer.go | 4 | ||||
| -rw-r--r-- | ipc/ipc.go | 9 | ||||
| -rw-r--r-- | tools/execprog/execprog.go | 4 |
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) |
