aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2016-09-03 21:37:29 +0200
committerDmitry Vyukov <dvyukov@google.com>2016-09-05 12:49:47 +0200
commitcb3e5c28a020e0b00ca237fe7e66f22041b60fbf (patch)
tree563b24f01089263ccbc682966713285ca63a385d /tools
parent01ac6a1076c709e967a9d8faa12a8aac014e792b (diff)
execprog: make syz-execprog work more like syz-fuzzer
Respect max concurrency. Optionally print programs to stdout.
Diffstat (limited to 'tools')
-rw-r--r--tools/syz-execprog/execprog.go99
1 files changed, 59 insertions, 40 deletions
diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go
index 5eacbb310..93097d0f8 100644
--- a/tools/syz-execprog/execprog.go
+++ b/tools/syz-execprog/execprog.go
@@ -29,6 +29,7 @@ var (
flagCoverFile = flag.String("coverfile", "", "write coverage to the file")
flagRepeat = flag.Int("repeat", 1, "repeat execution that many times (0 for infinite loop)")
flagProcs = flag.Int("procs", 1, "number of parallel processes to execute programs")
+ flagOutput = flag.String("output", "none", "write programs to none/stdout")
)
func main() {
@@ -66,11 +67,13 @@ func main() {
var wg sync.WaitGroup
wg.Add(*flagProcs)
- var posMu sync.Mutex
+ var posMu, logMu sync.Mutex
+ gate := ipc.NewGate(2**flagProcs, nil)
var pos int
var lastPrint time.Time
var shutdown uint32
for p := 0; p < *flagProcs; p++ {
+ pid := p
go func() {
defer wg.Done()
env, err := ipc.MakeEnv(*flagExecutor, timeout, flags)
@@ -79,47 +82,63 @@ func main() {
}
defer env.Close()
for {
- posMu.Lock()
- idx := pos
- pos++
- if idx%len(progs) == 0 && time.Since(lastPrint) > 5*time.Second {
- log.Printf("executed programs: %v", idx)
- lastPrint = time.Now()
- }
- posMu.Unlock()
- if *flagRepeat > 0 && idx >= len(progs)**flagRepeat {
- return
- }
- p := progs[idx%len(progs)]
- output, cov, _, failed, hanged, err := env.Exec(p)
- if atomic.LoadUint32(&shutdown) != 0 {
- return
- }
- if failed {
- fmt.Printf("BUG: executor-detected bug:\n%s", output)
- }
- if flags&ipc.FlagDebug != 0 || err != nil {
- fmt.Printf("result: failed=%v hanged=%v err=%v\n\n%s", failed, hanged, err, output)
- }
- if *flagCoverFile != "" {
- // 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, 0xffffffff))
- }
- err := ioutil.WriteFile(fmt.Sprintf("%v.%v", *flagCoverFile, i), buf.Bytes(), 0660)
- if err != nil {
- log.Fatalf("failed to write coverage file: %v", err)
+ if !func() bool {
+ // Limit concurrency window.
+ ticket := gate.Enter()
+ defer gate.Leave(ticket)
+
+ posMu.Lock()
+ idx := pos
+ pos++
+ if /*idx%len(progs) == 0 && time.Since(lastPrint) > 5*time.Second*/ (idx % 10) == 0 {
+ log.Printf("executed programs: %v", idx)
+ lastPrint = time.Now()
+ }
+ posMu.Unlock()
+ if *flagRepeat > 0 && idx >= len(progs)**flagRepeat {
+ return false
+ }
+ p := progs[idx%len(progs)]
+ switch *flagOutput {
+ case "stdout":
+ data := p.Serialize()
+ logMu.Lock()
+ log.Printf("executing program %v:\n%s", pid, data)
+ logMu.Unlock()
+ }
+ output, cov, _, failed, hanged, err := env.Exec(p)
+ if atomic.LoadUint32(&shutdown) != 0 {
+ return false
+ }
+ if failed {
+ fmt.Printf("BUG: executor-detected bug:\n%s", output)
+ }
+ if flags&ipc.FlagDebug != 0 || err != nil {
+ fmt.Printf("result: failed=%v hanged=%v err=%v\n\n%s", failed, hanged, err, output)
+ }
+ if *flagCoverFile != "" {
+ // 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, 0xffffffff))
+ }
+ err := ioutil.WriteFile(fmt.Sprintf("%v.%v", *flagCoverFile, i), buf.Bytes(), 0660)
+ if err != nil {
+ log.Fatalf("failed to write coverage file: %v", err)
+ }
}
}
+ return true
+ }() {
+ return
}
}
}()