aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/fuzzer/job.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-03-29 15:02:10 +0100
committerDmitry Vyukov <dvyukov@google.com>2024-04-09 07:55:50 +0000
commit1be1a06281dccada078a2a51e8b483811af8f596 (patch)
tree6340df1c2d1704f1784ba63164d3088b7c91ef61 /pkg/fuzzer/job.go
parent73f4b622a34ffc998a542f5e109fb05a1d892272 (diff)
all: refactor stats
Add ability for each package to create and export own stats. Each stat is self-contained, describes how it should be presented, and there is not need to copy them from one package to another. Stats also keep historical data and allow building graphs over time.
Diffstat (limited to 'pkg/fuzzer/job.go')
-rw-r--r--pkg/fuzzer/job.go43
1 files changed, 21 insertions, 22 deletions
diff --git a/pkg/fuzzer/job.go b/pkg/fuzzer/job.go
index e287b9599..2086016bf 100644
--- a/pkg/fuzzer/job.go
+++ b/pkg/fuzzer/job.go
@@ -12,6 +12,7 @@ import (
"github.com/google/syzkaller/pkg/ipc"
"github.com/google/syzkaller/pkg/rpctype"
"github.com/google/syzkaller/pkg/signal"
+ "github.com/google/syzkaller/pkg/stats"
"github.com/google/syzkaller/prog"
)
@@ -71,7 +72,7 @@ func genProgRequest(fuzzer *Fuzzer, rnd *rand.Rand) *Request {
return &Request{
Prog: p,
NeedSignal: rpctype.NewSignal,
- stat: statGenerate,
+ stat: fuzzer.statExecGenerate,
}
}
@@ -90,11 +91,11 @@ func mutateProgRequest(fuzzer *Fuzzer, rnd *rand.Rand) *Request {
return &Request{
Prog: newP,
NeedSignal: rpctype.NewSignal,
- stat: statFuzz,
+ stat: fuzzer.statExecFuzz,
}
}
-func candidateRequest(input Candidate) *Request {
+func candidateRequest(fuzzer *Fuzzer, input Candidate) *Request {
flags := progCandidate
if input.Minimized {
flags |= progMinimized
@@ -105,7 +106,7 @@ func candidateRequest(input Candidate) *Request {
return &Request{
Prog: input.Prog,
NeedSignal: rpctype.NewSignal,
- stat: statCandidate,
+ stat: fuzzer.statExecCandidate,
flags: flags,
}
}
@@ -131,10 +132,11 @@ func triageJobPrio(flags ProgTypes) jobPriority {
}
func (job *triageJob) run(fuzzer *Fuzzer) {
+ fuzzer.statNewInputs.Add(1)
callName := fmt.Sprintf("call #%v %v", job.call, job.p.CallName(job.call))
fuzzer.Logf(3, "triaging input for %v (new signal=%v)", callName, job.newSignal.Len())
// Compute input coverage and non-flaky signal for minimization.
- info, stop := job.deflake(fuzzer.exec, fuzzer.Config.FetchRawCover)
+ info, stop := job.deflake(fuzzer.exec, fuzzer.statExecTriage, fuzzer.Config.FetchRawCover)
if stop || info.newStableSignal.Empty() {
return
}
@@ -149,7 +151,7 @@ func (job *triageJob) run(fuzzer *Fuzzer) {
}
fuzzer.Logf(2, "added new input for %v to the corpus: %s", callName, job.p)
if job.flags&progSmashed == 0 {
- fuzzer.startJob(&smashJob{
+ fuzzer.startJob(fuzzer.statJobsSmash, &smashJob{
p: job.p.Clone(),
call: job.call,
})
@@ -171,7 +173,8 @@ type deflakedCover struct {
rawCover []uint32
}
-func (job *triageJob) deflake(exec func(job, *Request) *Result, rawCover bool) (info deflakedCover, stop bool) {
+func (job *triageJob) deflake(exec func(job, *Request) *Result, stat *stats.Val, rawCover bool) (
+ info deflakedCover, stop bool) {
// As demonstrated in #4639, programs reproduce with a very high, but not 100% probability.
// The triage algorithm must tolerate this, so let's pick the signal that is common
// to 3 out of 5 runs.
@@ -196,7 +199,7 @@ func (job *triageJob) deflake(exec func(job, *Request) *Result, rawCover bool) (
NeedSignal: rpctype.AllSignal,
NeedCover: true,
NeedRawCover: rawCover,
- stat: statTriage,
+ stat: stat,
flags: progInTriage,
})
if result.Stop {
@@ -236,7 +239,7 @@ func (job *triageJob) minimize(fuzzer *Fuzzer, newSignal signal.Signal) (stop bo
Prog: p1,
NeedSignal: rpctype.AllSignal,
SignalFilter: newSignal,
- stat: statMinimize,
+ stat: fuzzer.statExecMinimize,
})
if result.Stop {
stop = true
@@ -292,7 +295,10 @@ func (job *smashJob) priority() priority {
func (job *smashJob) run(fuzzer *Fuzzer) {
fuzzer.Logf(2, "smashing the program %s (call=%d):", job.p, job.call)
if fuzzer.Config.Comparisons && job.call >= 0 {
- fuzzer.startJob(newHintsJob(job.p.Clone(), job.call))
+ fuzzer.startJob(fuzzer.statJobsHints, &hintsJob{
+ p: job.p.Clone(),
+ call: job.call,
+ })
}
const iters = 75
@@ -306,7 +312,7 @@ func (job *smashJob) run(fuzzer *Fuzzer) {
result := fuzzer.exec(job, &Request{
Prog: p,
NeedSignal: rpctype.NewSignal,
- stat: statSmash,
+ stat: fuzzer.statExecSmash,
})
if result.Stop {
return
@@ -314,7 +320,7 @@ func (job *smashJob) run(fuzzer *Fuzzer) {
if fuzzer.Config.Collide {
result := fuzzer.exec(job, &Request{
Prog: randomCollide(p, rnd),
- stat: statCollide,
+ stat: fuzzer.statExecCollide,
})
if result.Stop {
return
@@ -356,7 +362,7 @@ func (job *smashJob) faultInjection(fuzzer *Fuzzer) {
newProg.Calls[job.call].Props.FailNth = nth
result := fuzzer.exec(job, &Request{
Prog: job.p,
- stat: statSmash,
+ stat: fuzzer.statExecSmash,
})
if result.Stop {
return
@@ -374,13 +380,6 @@ type hintsJob struct {
call int
}
-func newHintsJob(p *prog.Prog, call int) *hintsJob {
- return &hintsJob{
- p: p,
- call: call,
- }
-}
-
func (job *hintsJob) priority() priority {
return priority{smashPrio}
}
@@ -391,7 +390,7 @@ func (job *hintsJob) run(fuzzer *Fuzzer) {
result := fuzzer.exec(job, &Request{
Prog: p,
NeedHints: true,
- stat: statSeed,
+ stat: fuzzer.statExecSeed,
})
if result.Stop || result.Info == nil {
return
@@ -404,7 +403,7 @@ func (job *hintsJob) run(fuzzer *Fuzzer) {
result := fuzzer.exec(job, &Request{
Prog: p,
NeedSignal: rpctype.NewSignal,
- stat: statHint,
+ stat: fuzzer.statExecHint,
})
return !result.Stop
})