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 | |
| parent | 29e95fbb262d0f19ee1f04a59bafda4bf8f97b63 (diff) | |
dump coverage in execprog command
| -rw-r--r-- | cover/cover.go | 4 | ||||
| -rw-r--r-- | manager/cover.go | 4 | ||||
| -rw-r--r-- | tools/execprog/execprog.go | 30 |
3 files changed, 34 insertions, 4 deletions
diff --git a/cover/cover.go b/cover/cover.go index c55f328e6..4c07314af 100644 --- a/cover/cover.go +++ b/cover/cover.go @@ -20,6 +20,10 @@ func Copy(cov Cover) Cover { return append(Cover{}, cov...) } +func RestorePC(pc uint32) uint64 { + return uint64(0xffffffff)<<32 + uint64(pc) +} + /* Canonicalize sorts and removes duplicates. */ func Canonicalize(cov []uint32) Cover { sort.Sort(Cover(cov)) diff --git a/manager/cover.go b/manager/cover.go index accc230f9..190fb6038 100644 --- a/manager/cover.go +++ b/manager/cover.go @@ -15,6 +15,8 @@ import ( "strconv" "strings" "sync" + + "github.com/google/syzkaller/cover" ) type LineInfo struct { @@ -171,7 +173,7 @@ func symbolize(vmlinux string, cov []uint32) error { defer cmd.Wait() go func() { for _, pc := range cov { - fmt.Fprintf(stdin, "0xffffffff%x\n", pc-1) + fmt.Fprintf(stdin, "0x%x\n", cover.RestorePC(pc)-1) } stdin.Close() }() 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) + } + } } |
