diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2015-10-13 14:58:50 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2015-10-13 15:29:07 +0200 |
| commit | c90d72859537bb8aaff047331bf8d22ca7cc85bc (patch) | |
| tree | ad38888e762004dd0f4fca9361e8ce2be28c5b35 /tools/execprog | |
| parent | 29e95fbb262d0f19ee1f04a59bafda4bf8f97b63 (diff) | |
dump coverage in execprog command
Diffstat (limited to 'tools/execprog')
| -rw-r--r-- | tools/execprog/execprog.go | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/tools/execprog/execprog.go b/tools/execprog/execprog.go index 9e0ac16a9..2521426f8 100644 --- a/tools/execprog/execprog.go +++ b/tools/execprog/execprog.go @@ -1,15 +1,20 @@ // Copyright 2015 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// execprog executes a single program passed via a flag +// and prints information about execution. package main import ( + "bytes" + "encoding/binary" "flag" "fmt" "io/ioutil" "os" "time" + "github.com/google/syzkaller/cover" "github.com/google/syzkaller/ipc" "github.com/google/syzkaller/prog" ) @@ -20,7 +25,7 @@ var ( flagThreaded = flag.Bool("threaded", false, "use threaded mode in executor") flagDebug = flag.Bool("debug", true, "debug output from executor") flagStrace = flag.Bool("strace", false, "run executor under strace") - flagCover = flag.Bool("cover", false, "collect coverage") + flagCover = flag.String("cover", "", "collect coverage and write to the file") ) func main() { @@ -45,7 +50,7 @@ func main() { if *flagStrace { flags |= ipc.FlagStrace } - if *flagCover { + if *flagCover != "" { flags |= ipc.FlagCover } env, err := ipc.MakeEnv(*flagExecutor, 3*time.Second, flags) @@ -53,9 +58,28 @@ func main() { fmt.Fprintf(os.Stderr, "failed to create execution environment: %v\n", err) os.Exit(1) } - output, strace, _, failed, hanged, err := env.Exec(p) + output, strace, cov, failed, hanged, err := env.Exec(p) fmt.Printf("result: failed=%v hanged=%v err=%v\n\n%s", failed, hanged, err, output) if *flagStrace { fmt.Printf("strace output:\n%s", strace) } + // 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 { + continue + } + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint64(0xC0BFFFFFFFFFFF64)) + for _, pc := range c { + binary.Write(buf, binary.LittleEndian, cover.RestorePC(pc)) + } + err := ioutil.WriteFile(fmt.Sprintf("%v.%v", *flagCover, i), buf.Bytes(), 0660) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to write coverage file: %v\n", err) + os.Exit(1) + } + } } |
