aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-10-12 10:16:57 +0200
committerDmitry Vyukov <dvyukov@google.com>2015-10-12 10:16:57 +0200
commit874c5754bb22dbf77d6b600ff91f0f4f1fc5073a (patch)
tree0075fbd088046ad5c86e6e972235701d68b3ce7c /tools
initial commit
Diffstat (limited to 'tools')
-rw-r--r--tools/execlog/execlog.go83
-rw-r--r--tools/execprog/execprog.go62
-rw-r--r--tools/prog2c/prog2c.go31
-rw-r--r--tools/stress/stress.go104
4 files changed, 280 insertions, 0 deletions
diff --git a/tools/execlog/execlog.go b/tools/execlog/execlog.go
new file mode 100644
index 000000000..5d39bb955
--- /dev/null
+++ b/tools/execlog/execlog.go
@@ -0,0 +1,83 @@
+// 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.
+
+// execlog executes all programs from a log (for non-reproducible crashes).
+package main
+
+import (
+ "bufio"
+ "flag"
+ "log"
+ "os"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "github.com/google/syzkaller/ipc"
+ "github.com/google/syzkaller/prog"
+)
+
+var (
+ flagExecutor = flag.String("executor", "", "path to executor binary")
+ flagLog = flag.String("log", "", "comma-delimited list of log files to execute")
+)
+
+func main() {
+ flag.Parse()
+ var progs [][]byte
+ for _, fn := range strings.Split(*flagLog, ",") {
+ logf, err := os.Open(fn)
+ if err != nil {
+ log.Fatalf("failed to open log file: %v", err)
+ }
+ log.Printf("parsing log %v", fn)
+ s := bufio.NewScanner(logf)
+ var cur []byte
+ var last *prog.Prog
+ for s.Scan() {
+ ln := s.Text()
+ tmp := append(cur, ln...)
+ tmp = append(tmp, '\n')
+ p, err := prog.Deserialize(tmp)
+ if err == nil {
+ cur = tmp
+ last = p
+ continue
+ }
+ if last != nil {
+ progs = append(progs, last.SerializeForExec())
+ last = nil
+ cur = cur[:0]
+ }
+ }
+ if last != nil {
+ progs = append(progs, last.SerializeForExec())
+ }
+ }
+ log.Printf("parsed %v programs", len(progs))
+ if len(progs) == 0 {
+ return
+ }
+
+ var pos uint32
+ for p := 0; p < 16; p++ {
+ go func() {
+ env, err := ipc.MakeEnv(*flagExecutor, 5*time.Second, 0)
+ if err != nil {
+ log.Fatalf("failed to create ipc env: %v", err)
+ }
+ for {
+ idx := int(atomic.AddUint32(&pos, 1) - 1)
+ if idx%1000 == 0 {
+ log.Printf("executing %v\n", idx)
+ }
+ copy(env.In, progs[idx%len(progs)])
+ _, _, _, _, err := env.Exec()
+ if err != nil {
+ log.Printf("failed to execute program: %v", err)
+ }
+ }
+ }()
+ }
+ select {}
+}
diff --git a/tools/execprog/execprog.go b/tools/execprog/execprog.go
new file mode 100644
index 000000000..9ffe39119
--- /dev/null
+++ b/tools/execprog/execprog.go
@@ -0,0 +1,62 @@
+// 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.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "time"
+
+ "github.com/google/syzkaller/ipc"
+ "github.com/google/syzkaller/prog"
+)
+
+var (
+ flagExecutor = flag.String("executor", "", "path to executor binary")
+ flagProg = flag.String("prog", "", "file with a program to execute")
+ 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")
+)
+
+func main() {
+ flag.Parse()
+ data, err := ioutil.ReadFile(*flagProg)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err)
+ os.Exit(1)
+ }
+ p, err := prog.Deserialize(data)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err)
+ os.Exit(1)
+ }
+ var flags uint64
+ if *flagThreaded {
+ flags |= ipc.FlagThreaded
+ }
+ if *flagDebug {
+ flags |= ipc.FlagDebug
+ }
+ if *flagStrace {
+ flags |= ipc.FlagStrace
+ }
+ if *flagCover {
+ flags |= ipc.FlagCover
+ }
+ env, err := ipc.MakeEnv(*flagExecutor, 3*time.Second, flags)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to create execution environment: %v\n", err)
+ os.Exit(1)
+ }
+ copy(env.In, p.SerializeForExec())
+ output, strace, failed, hanged, err := env.Exec()
+ 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)
+ }
+}
diff --git a/tools/prog2c/prog2c.go b/tools/prog2c/prog2c.go
new file mode 100644
index 000000000..9b8e58efa
--- /dev/null
+++ b/tools/prog2c/prog2c.go
@@ -0,0 +1,31 @@
+// 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.
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/google/syzkaller/prog"
+)
+
+func main() {
+ if len(os.Args) != 2 {
+ fmt.Fprintf(os.Stderr, "usage: prog2c prog_file\n")
+ os.Exit(1)
+ }
+ data, err := ioutil.ReadFile(os.Args[1])
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err)
+ os.Exit(1)
+ }
+ p, err := prog.Deserialize(data)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err)
+ os.Exit(1)
+ }
+ src := p.WriteCSource()
+ os.Stdout.Write(src)
+}
diff --git a/tools/stress/stress.go b/tools/stress/stress.go
new file mode 100644
index 000000000..5b84e81b4
--- /dev/null
+++ b/tools/stress/stress.go
@@ -0,0 +1,104 @@
+// 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.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "os"
+ "path/filepath"
+ "regexp"
+ "time"
+
+ "github.com/google/syzkaller/ipc"
+ "github.com/google/syzkaller/prog"
+)
+
+var (
+ flagCorpus = flag.String("corpus", "", "corpus directory")
+ flagExecutor = flag.String("executor", "", "path to executor binary")
+ flagOutput = flag.Bool("output", false, "print executor output to console")
+ flagDebug = flag.Bool("debug", false, "executor debug output")
+
+ failedRe = regexp.MustCompile("runtime error: |panic: ")
+)
+
+func main() {
+ flag.Parse()
+ corpus := readCorpus()
+ flags := ipc.FlagThreaded
+ if *flagDebug {
+ flags |= ipc.FlagDebug
+ }
+ env, err := ipc.MakeEnv(*flagExecutor, 5*time.Second, flags)
+ if err != nil {
+ failf("failed to create execution environment: %v", err)
+ }
+ rs := rand.NewSource(time.Now().UnixNano())
+ rnd := rand.New(rs)
+ for i := 0; ; i++ {
+ var p *prog.Prog
+ if len(corpus) == 0 || i%10 != 0 {
+ p = prog.Generate(rs, 50, nil)
+ execute(env, p)
+ p.Mutate(rs, 50, nil)
+ execute(env, p)
+ } else {
+ p = corpus[rnd.Intn(len(corpus))].Clone()
+ p.Mutate(rs, 50, nil)
+ execute(env, p)
+ }
+ }
+}
+
+func execute(env *ipc.Env, p *prog.Prog) {
+ if *flagExecutor == "" {
+ return
+ }
+ copy(env.In, p.SerializeForExec())
+ output, _, _, _, err := env.Exec()
+ if err != nil {
+ fmt.Printf("failed to execute executor: %v\n", err)
+ }
+ failed := failedRe.Match(output)
+ if failed {
+ fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
+ }
+ if failed || *flagOutput {
+ os.Stdout.Write(output)
+ }
+}
+
+func readCorpus() []*prog.Prog {
+ if *flagCorpus == "" {
+ return nil
+ }
+ files, err := ioutil.ReadDir(*flagCorpus)
+ if err != nil {
+ failf("failed to read corpus dir: %v", err)
+ }
+ var progs []*prog.Prog
+ for _, f := range files {
+ if f.IsDir() {
+ continue
+ }
+ data, err := ioutil.ReadFile(filepath.Join(*flagCorpus, f.Name()))
+ if err != nil {
+ failf("failed to read corpus file: %v", err)
+ }
+ p, err := prog.Deserialize(data)
+ if err != nil {
+ failf("failed to deserialize corpus program: %v", err)
+ }
+ progs = append(progs, p)
+ }
+ return progs
+}
+
+func failf(msg string, args ...interface{}) {
+ log.Fatalf(msg, args...)
+}