aboutsummaryrefslogtreecommitdiffstats
path: root/tools/syz-execprog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-01-25 22:18:42 +0100
committerDmitry Vyukov <dvyukov@google.com>2017-01-27 20:46:18 +0100
commit8365c3838dd442ef23f3b622710963382f73f4df (patch)
treee981ba6710476e49d059e4d5fd36860d7b778d9e /tools/syz-execprog
parent1c190bb96354172fb7589a87a86747f4e06ad605 (diff)
all: implement edge coverage
Currently syzkaller uses per-call basic block (BB) coverage. This change implements edge (not-per-call) coverage. Edge coverage is more detailed than BB coverage as it captures not-taken branches, looping, etc. So it provides better feedback signal. This coverage is now called "signal" throughout the code. BB code coverage is also collected as it is required for visualisation. Not doing per-call coverage reduces corpus ~6-7x (from ~35K to ~5K), this has profound effect on fuzzing efficiency.
Diffstat (limited to 'tools/syz-execprog')
-rw-r--r--tools/syz-execprog/execprog.go17
1 files changed, 10 insertions, 7 deletions
diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go
index dba98f4ec..03518c2d3 100644
--- a/tools/syz-execprog/execprog.go
+++ b/tools/syz-execprog/execprog.go
@@ -60,9 +60,12 @@ func main() {
if err != nil {
Fatalf("%v", err)
}
+ needCover := flags&ipc.FlagSignal != 0
+ dedupCover := true
if *flagCoverFile != "" {
- flags |= ipc.FlagCover
- flags &= ^ipc.FlagDedupCover
+ flags |= ipc.FlagSignal
+ needCover = true
+ dedupCover = false
}
var wg sync.WaitGroup
@@ -106,7 +109,7 @@ func main() {
Logf(0, "executing program %v:\n%s", pid, data)
logMu.Unlock()
}
- output, cov, _, failed, hanged, err := env.Exec(p)
+ output, info, failed, hanged, err := env.Exec(p, needCover, dedupCover)
if atomic.LoadUint32(&shutdown) != 0 {
return false
}
@@ -120,14 +123,14 @@ func main() {
// Coverage is dumped in sanitizer format.
// github.com/google/sanitizers/tools/sancov command can be used to dump PCs,
// then they can be piped via addr2line to symbolize.
- for i, c := range cov {
- fmt.Printf("call #%v: coverage %v\n", i, len(c))
- if len(c) == 0 {
+ for i, inf := range info {
+ fmt.Printf("call #%v: signal %v, coverage %v\n", i, len(inf.Signal), len(inf.Cover))
+ if len(inf.Cover) == 0 {
continue
}
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, uint64(0xC0BFFFFFFFFFFF64))
- for _, pc := range c {
+ for _, pc := range inf.Cover {
binary.Write(buf, binary.LittleEndian, cover.RestorePC(pc, 0xffffffff))
}
err := ioutil.WriteFile(fmt.Sprintf("%v.%v", *flagCoverFile, i), buf.Bytes(), 0660)