diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-09-03 21:37:29 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-09-05 12:49:47 +0200 |
| commit | cb3e5c28a020e0b00ca237fe7e66f22041b60fbf (patch) | |
| tree | 563b24f01089263ccbc682966713285ca63a385d | |
| parent | 01ac6a1076c709e967a9d8faa12a8aac014e792b (diff) | |
execprog: make syz-execprog work more like syz-fuzzer
Respect max concurrency.
Optionally print programs to stdout.
| -rw-r--r-- | tools/syz-execprog/execprog.go | 99 |
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 } } }() |
