diff options
Diffstat (limited to 'pkg/csource')
| -rw-r--r-- | pkg/csource/common.go | 6 | ||||
| -rw-r--r-- | pkg/csource/csource.go | 23 | ||||
| -rw-r--r-- | pkg/csource/generated.go | 11 | ||||
| -rw-r--r-- | pkg/csource/options.go | 17 | ||||
| -rw-r--r-- | pkg/csource/options_test.go | 5 |
5 files changed, 48 insertions, 14 deletions
diff --git a/pkg/csource/common.go b/pkg/csource/common.go index ebc085c7a..a03fba056 100644 --- a/pkg/csource/common.go +++ b/pkg/csource/common.go @@ -95,6 +95,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) { if opts.Repeat { defines = append(defines, "SYZ_REPEAT") } + if opts.RepeatTimes > 1 { + defines = append(defines, "SYZ_REPEAT_TIMES") + } if opts.Procs > 1 { defines = append(defines, "SYZ_PROCS") } @@ -122,6 +125,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) { if opts.Repro { defines = append(defines, "SYZ_REPRO") } + if opts.Trace { + defines = append(defines, "SYZ_TRACE") + } for _, c := range p.Calls { defines = append(defines, "__NR_"+c.Meta.CallName) } diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go index 66958f22b..895856ea3 100644 --- a/pkg/csource/csource.go +++ b/pkg/csource/csource.go @@ -27,13 +27,13 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { calls: make(map[string]uint64), } - calls, vars, err := ctx.generateProgCalls(ctx.p) + calls, vars, err := ctx.generateProgCalls(ctx.p, opts.Trace) if err != nil { return nil, err } mmapProg := p.Target.GenerateUberMmapProg() - mmapCalls, _, err := ctx.generateProgCalls(mmapProg) + mmapCalls, _, err := ctx.generateProgCalls(mmapProg, false) if err != nil { return nil, err } @@ -60,6 +60,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } replacements := map[string]string{ "PROCS": fmt.Sprint(opts.Procs), + "REPEAT_TIMES": fmt.Sprint(opts.RepeatTimes), "NUM_CALLS": fmt.Sprint(len(p.Calls)), "MMAP_DATA": strings.Join(mmapCalls, ""), "SYSCALL_DEFINES": ctx.generateSyscallDefines(), @@ -94,17 +95,20 @@ func (ctx *context) generateSyscalls(calls []string, hasVars bool) string { opts := ctx.opts buf := new(bytes.Buffer) if !opts.Threaded && !opts.Collide { - if hasVars { + if hasVars || opts.Trace { fmt.Fprintf(buf, "\tlong res = 0;\n") } if opts.Repro { fmt.Fprintf(buf, "\tif (write(1, \"executing program\\n\", sizeof(\"executing program\\n\") - 1)) {}\n") } + if opts.Trace { + fmt.Fprintf(buf, "\tprintf(\"### start\\n\");\n") + } for _, c := range calls { fmt.Fprintf(buf, "%s", c) } } else { - if hasVars { + if hasVars || opts.Trace { fmt.Fprintf(buf, "\tlong res;") } fmt.Fprintf(buf, "\tswitch (call) {\n") @@ -145,7 +149,7 @@ func (ctx *context) generateSyscallDefines() string { return buf.String() } -func (ctx *context) generateProgCalls(p *prog.Prog) ([]string, []uint64, error) { +func (ctx *context) generateProgCalls(p *prog.Prog, trace bool) ([]string, []uint64, error) { exec := make([]byte, prog.ExecBufferSize) progSize, err := p.SerializeForExec(exec) if err != nil { @@ -155,11 +159,11 @@ func (ctx *context) generateProgCalls(p *prog.Prog) ([]string, []uint64, error) if err != nil { return nil, nil, err } - calls, vars := ctx.generateCalls(decoded) + calls, vars := ctx.generateCalls(decoded, trace) return calls, vars, nil } -func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) { +func (ctx *context) generateCalls(p prog.ExecProg, trace bool) ([]string, []uint64) { var calls []string csumSeq := 0 for ci, call := range p.Calls { @@ -185,7 +189,7 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) { if emitCall { native := ctx.sysTarget.SyscallNumbers && !strings.HasPrefix(callName, "syz_") fmt.Fprintf(w, "\t") - if resCopyout || argCopyout { + if resCopyout || argCopyout || trace { fmt.Fprintf(w, "res = ") } if native { @@ -219,6 +223,9 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) { } } fmt.Fprintf(w, ");\n") + if trace { + fmt.Fprintf(w, "\tprintf(\"### call=%v errno=%%d\\n\", res == -1 ? errno : 0);\n", ci) + } } // Copyout. diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go index 7cd6f8777..7be8ca329 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -15,6 +15,10 @@ var commonHeader = ` #include <stdlib.h> #include <string.h> +#if SYZ_TRACE +#include <errno.h> +#endif + #if SYZ_EXECUTOR && !GOOS_linux #include <unistd.h> NORETURN void doexit(int status) @@ -3613,6 +3617,9 @@ static void loop() if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } #endif +#if SYZ_TRACE + printf("### start\n"); +#endif int call, thread; #if SYZ_COLLIDE int collide = 0; @@ -3684,7 +3691,11 @@ static void loop() fail("pipe failed"); #endif int iter; +#if SYZ_REPEAT_TIMES + for (iter = 0; iter < [[REPEAT_TIMES]]; iter++) { +#else for (iter = 0;; iter++) { +#endif #if SYZ_EXECUTOR || SYZ_USE_TMP_DIR char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); diff --git a/pkg/csource/options.go b/pkg/csource/options.go index e60554120..a312c5db7 100644 --- a/pkg/csource/options.go +++ b/pkg/csource/options.go @@ -15,11 +15,12 @@ import ( // Options control various aspects of source generation. // Dashboard also provides serialized Options along with syzkaller reproducers. type Options struct { - Threaded bool `json:"threaded,omitempty"` - Collide bool `json:"collide,omitempty"` - Repeat bool `json:"repeat,omitempty"` - Procs int `json:"procs"` - Sandbox string `json:"sandbox"` + Threaded bool `json:"threaded,omitempty"` + Collide bool `json:"collide,omitempty"` + Repeat bool `json:"repeat,omitempty"` + RepeatTimes int `json:"repeat_times,omitempty"` // if non-0, repeat that many times + Procs int `json:"procs"` + Sandbox string `json:"sandbox"` Fault bool `json:"fault,omitempty"` // inject fault into FaultCall/FaultNth FaultCall int `json:"fault_call,omitempty"` @@ -34,8 +35,9 @@ type Options struct { HandleSegv bool `json:"segv,omitempty"` // Generate code for use with repro package to prints log messages, - // which allows to distinguish between a hang and an absent crash. + // which allows to detect hangs. Repro bool `json:"repro,omitempty"` + Trace bool `json:"trace,omitempty"` } // Check checks if the opts combination is valid or not. @@ -101,6 +103,9 @@ func (opts Options) Check(OS string) error { if opts.ResetNet && !opts.Repeat { return errors.New("ResetNet without Repeat") } + if !opts.Repeat && opts.RepeatTimes != 0 && opts.RepeatTimes != 1 { + return errors.New("RepeatTimes without Repeat") + } return nil } diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go index f43f2582e..ad86f8786 100644 --- a/pkg/csource/options_test.go +++ b/pkg/csource/options_test.go @@ -149,6 +149,11 @@ func enumerateField(OS string, opt Options, field int) []Options { fld.SetInt(procs) opts = append(opts, opt) } + } else if fldName == "RepeatTimes" { + for _, times := range []int64{0, 10} { + fld.SetInt(times) + opts = append(opts, opt) + } } else if fldName == "FaultCall" { opts = append(opts, opt) } else if fldName == "FaultNth" { |
