diff options
| author | Jouni Hogander <jouni.hogander@unikie.com> | 2020-11-10 15:01:26 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-12-10 12:57:35 +0100 |
| commit | cbdf514ebdff5b19bc93cdfcc81598587627330e (patch) | |
| tree | cec672b32afba297ff06bc3cd4d39205596cc78a /pkg | |
| parent | f86bec81e1bafa82d30486258de616fff295b5f7 (diff) | |
pkg/kconfig: store minimization results
Store config options identified using DebugTracer. Also change bisection
and configuration minimization code to use new DebugTracer.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/bisect/bisect.go | 14 | ||||
| -rw-r--r-- | pkg/bisect/bisect_test.go | 6 | ||||
| -rw-r--r-- | pkg/kconfig/minimize.go | 36 | ||||
| -rw-r--r-- | pkg/kconfig/minimize_test.go | 6 | ||||
| -rw-r--r-- | pkg/vcs/git.go | 9 | ||||
| -rw-r--r-- | pkg/vcs/git_repo_test.go | 10 | ||||
| -rw-r--r-- | pkg/vcs/linux.go | 15 | ||||
| -rw-r--r-- | pkg/vcs/testos.go | 6 | ||||
| -rw-r--r-- | pkg/vcs/vcs.go | 6 |
9 files changed, 50 insertions, 58 deletions
diff --git a/pkg/bisect/bisect.go b/pkg/bisect/bisect.go index 76c518e6c..07f47ccde 100644 --- a/pkg/bisect/bisect.go +++ b/pkg/bisect/bisect.go @@ -5,11 +5,10 @@ package bisect import ( "fmt" - "io" - "path/filepath" "time" "github.com/google/syzkaller/pkg/build" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/pkg/instance" "github.com/google/syzkaller/pkg/mgrconfig" @@ -19,11 +18,10 @@ import ( ) type Config struct { - Trace io.Writer + Trace debugtracer.DebugTracer Fix bool BinDir string Ccache string - DebugDir string Timeout time.Duration Kernel KernelConfig Syzkaller SyzkallerConfig @@ -540,11 +538,7 @@ func (env *env) processResults(current *vcs.Commit, results []error) (bad, good } func (env *env) saveDebugFile(hash string, idx int, data []byte) { - if env.cfg.DebugDir == "" || len(data) == 0 { - return - } - osutil.MkdirAll(env.cfg.DebugDir) - osutil.WriteFile(filepath.Join(env.cfg.DebugDir, fmt.Sprintf("%v.%v", hash, idx)), data) + env.cfg.Trace.SaveFile(fmt.Sprintf("%v.%v", hash, idx), data) } func checkConfig(cfg *Config) error { @@ -564,5 +558,5 @@ func checkConfig(cfg *Config) error { } func (env *env) log(msg string, args ...interface{}) { - fmt.Fprintf(env.cfg.Trace, msg+"\n", args...) + env.cfg.Trace.Log(msg, args...) } diff --git a/pkg/bisect/bisect_test.go b/pkg/bisect/bisect_test.go index db4409a5c..e71903c98 100644 --- a/pkg/bisect/bisect_test.go +++ b/pkg/bisect/bisect_test.go @@ -4,13 +4,13 @@ package bisect import ( - "bytes" "fmt" "io/ioutil" "os" "strconv" "testing" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/pkg/instance" "github.com/google/syzkaller/pkg/mgrconfig" @@ -122,10 +122,9 @@ func runBisection(t *testing.T, baseDir string, test BisectionTest) (*Result, er if err != nil { t.Fatal(err) } - trace := new(bytes.Buffer) cfg := &Config{ Fix: test.fix, - Trace: trace, + Trace: &debugtracer.TestTracer{T: t}, Manager: &mgrconfig.Config{ Derived: mgrconfig.Derived{ TargetOS: targets.TestOS, @@ -147,7 +146,6 @@ func runBisection(t *testing.T, baseDir string, test BisectionTest) (*Result, er test: test, } res, err := runImpl(cfg, r, inst) - t.Log(trace.String()) return res, err } diff --git a/pkg/kconfig/minimize.go b/pkg/kconfig/minimize.go index bbcb95414..bbc66c4c1 100644 --- a/pkg/kconfig/minimize.go +++ b/pkg/kconfig/minimize.go @@ -4,9 +4,10 @@ package kconfig import ( - "fmt" - "io" "sort" + + "github.com/google/syzkaller/pkg/debugtracer" + "github.com/google/syzkaller/pkg/osutil" ) // Minimize finds an equivalent with respect to the provided predicate, but smaller config. @@ -15,15 +16,14 @@ import ( // mostly by adding more configs. The minimization procedure thus consists of figuring out what set of configs that // are present in full and are not present in base affect the predicate. func (kconf *KConfig) Minimize(base, full *ConfigFile, pred func(*ConfigFile) (bool, error), - tw io.Writer) (*ConfigFile, error) { - trace := traceLogger{tw} + dt debugtracer.DebugTracer) (*ConfigFile, error) { diff, other := kconf.missingConfigs(base, full) - trace.log("kconfig minimization: base=%v full=%v diff=%v", len(base.Configs), len(full.Configs), len(diff)) + dt.Log("kconfig minimization: base=%v full=%v diff=%v", len(base.Configs), len(full.Configs), len(diff)) // First, check the base config as is, it is the smallest we can possibly get. if res, err := pred(base); err != nil { return nil, err } else if res { - trace.log("base config crashes") + dt.Log("base config crashes") return base, nil } // Since base does not crash, full config is our best bet for now. @@ -45,7 +45,7 @@ top: for len(diff) >= 2 { half := len(diff) / 2 for _, part := range [][]string{diff[:half], diff[half:]} { - trace.log("trying half: %v", part) + dt.Log("trying half: %v", part) closure := kconf.addDependencies(base, full, part) candidate := base.clone() // Always move all non-tristate configs from full to base as we don't minimize them. @@ -60,20 +60,21 @@ top: return nil, err } if res { - trace.log("half crashed") + dt.Log("half crashed") diff = part current = candidate suspects = closure continue top } } - trace.log("both halves did not crash") + dt.Log("both halves did not crash") break } if suspects != nil { - trace.log("resulting configs: %v", suspects) + dt.Log("resulting configs: %v", suspects) + kconf.writeSuspects(dt, suspects) } else { - trace.log("only full config crashes") + dt.Log("only full config crashes") } return current, nil } @@ -110,10 +111,15 @@ func (kconf *KConfig) addDependencies(base, full *ConfigFile, configs []string) return sorted } -type traceLogger struct{ io.Writer } +const CauseConfigFile = "cause.config" + +func (kconf *KConfig) writeSuspects(dt debugtracer.DebugTracer, suspects []string) { + cf := &ConfigFile{ + Map: make(map[string]*Config), + } -func (trace traceLogger) log(msg string, args ...interface{}) { - if trace.Writer != nil { - fmt.Fprintf(trace.Writer, msg+"\n", args...) + for _, cfg := range suspects { + cf.Set(cfg, Yes) } + osutil.WriteFile(CauseConfigFile, cf.Serialize()) } diff --git a/pkg/kconfig/minimize_test.go b/pkg/kconfig/minimize_test.go index 28dca33bd..1e1d2b0f2 100644 --- a/pkg/kconfig/minimize_test.go +++ b/pkg/kconfig/minimize_test.go @@ -4,10 +4,10 @@ package kconfig import ( - "bytes" "fmt" "testing" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/sys/targets" ) @@ -106,9 +106,7 @@ CONFIG_ROSE=y } for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { - trace := new(bytes.Buffer) - res, err := kconf.Minimize(base, full, test.pred, trace) - t.Log(trace.String()) + res, err := kconf.Minimize(base, full, test.pred, &debugtracer.TestTracer{T: t}) if err != nil { t.Fatal(err) } diff --git a/pkg/vcs/git.go b/pkg/vcs/git.go index 1a90341ac..163f3e497 100644 --- a/pkg/vcs/git.go +++ b/pkg/vcs/git.go @@ -7,7 +7,6 @@ import ( "bufio" "bytes" "fmt" - "io" "net/mail" "os" "os/exec" @@ -16,6 +15,7 @@ import ( "strings" "time" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/pkg/log" "github.com/google/syzkaller/pkg/osutil" @@ -431,7 +431,8 @@ func splitEmail(email string) (user, domain string, err error) { return } -func (git *git) Bisect(bad, good string, trace io.Writer, pred func() (BisectResult, error)) ([]*Commit, error) { +func (git *git) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult, + error)) ([]*Commit, error) { git.reset() firstBad, err := git.getCommit(bad) if err != nil { @@ -442,7 +443,7 @@ func (git *git) Bisect(bad, good string, trace io.Writer, pred func() (BisectRes return nil, err } defer git.reset() - fmt.Fprintf(trace, "# git bisect start %v %v\n%s", bad, good, output) + dt.Log("# git bisect start %v %v\n%s", bad, good, output) current, err := git.HeadCommit() if err != nil { return nil, err @@ -463,7 +464,7 @@ func (git *git) Bisect(bad, good string, trace io.Writer, pred func() (BisectRes firstBad = current } output, err = git.git("bisect", bisectTerms[res]) - fmt.Fprintf(trace, "# git bisect %v %v\n%s", bisectTerms[res], current.Hash, output) + dt.Log("# git bisect %v %v\n%s", bisectTerms[res], current.Hash, output) if err != nil { if bytes.Contains(output, []byte("There are only 'skip'ped commits left to test")) { return git.bisectInconclusive(output) diff --git a/pkg/vcs/git_repo_test.go b/pkg/vcs/git_repo_test.go index a2610315f..9a044e870 100644 --- a/pkg/vcs/git_repo_test.go +++ b/pkg/vcs/git_repo_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/google/syzkaller/pkg/debugtracer" ) func init() { @@ -378,7 +379,7 @@ func TestBisect(t *testing.T) { } for i, test := range tests { t.Logf("TEST %v", i) - result, err := repo.repo.Bisect(commits[4], commits[0], (*testWriter)(t), test.pred) + result, err := repo.repo.Bisect(commits[4], commits[0], &debugtracer.TestTracer{T: t}, test.pred) if err != nil { t.Fatal(err) } @@ -394,10 +395,3 @@ func TestBisect(t *testing.T) { } } } - -type testWriter testing.T - -func (t *testWriter) Write(data []byte) (int, error) { - (*testing.T)(t).Log(string(data)) - return len(data), nil -} diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go index a99215528..93c9ca045 100644 --- a/pkg/vcs/linux.go +++ b/pkg/vcs/linux.go @@ -6,7 +6,6 @@ package vcs import ( "bytes" "fmt" - "io" "net/mail" "path/filepath" "regexp" @@ -15,6 +14,7 @@ import ( "strings" "time" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/pkg/kconfig" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/prog" @@ -237,8 +237,9 @@ func linuxAlterConfigs(cf *kconfig.ConfigFile, tags map[string]bool) { } } -func (ctx *linux) Bisect(bad, good string, trace io.Writer, pred func() (BisectResult, error)) ([]*Commit, error) { - commits, err := ctx.git.Bisect(bad, good, trace, pred) +func (ctx *linux) Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult, + error)) ([]*Commit, error) { + commits, err := ctx.git.Bisect(bad, good, dt, pred) if len(commits) == 1 { ctx.addMaintainers(commits[0]) } @@ -309,10 +310,10 @@ func ParseMaintainersLinux(text []byte) Recipients { const configBisectTag = "# Minimized by syzkaller" -func (ctx *linux) Minimize(target *targets.Target, original, baseline []byte, trace io.Writer, - pred func(test []byte) (BisectResult, error)) ([]byte, error) { +func (ctx *linux) Minimize(target *targets.Target, original, baseline []byte, + dt debugtracer.DebugTracer, pred func(test []byte) (BisectResult, error)) ([]byte, error) { if bytes.HasPrefix(original, []byte(configBisectTag)) { - fmt.Fprintf(trace, "# configuration already minimized\n") + dt.Log("# configuration already minimized\n") return original, nil } kconf, err := kconfig.Parse(target, filepath.Join(ctx.git.dir, "Kconfig")) @@ -333,7 +334,7 @@ func (ctx *linux) Minimize(target *targets.Target, original, baseline []byte, tr res, err := pred(serialize(candidate)) return res == BisectBad, err } - minConfig, err := kconf.Minimize(baselineConfig, originalConfig, kconfPred, trace) + minConfig, err := kconf.Minimize(baselineConfig, originalConfig, kconfPred, dt) if err != nil { return nil, err } diff --git a/pkg/vcs/testos.go b/pkg/vcs/testos.go index fa9f7cc9b..c9acf1781 100644 --- a/pkg/vcs/testos.go +++ b/pkg/vcs/testos.go @@ -5,8 +5,8 @@ package vcs import ( "fmt" - "io" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/sys/targets" ) @@ -30,8 +30,8 @@ func (ctx *testos) EnvForCommit(binDir, commit string, kernelConfig []byte) (*Bi return &BisectEnv{KernelConfig: kernelConfig}, nil } -func (ctx *testos) Minimize(target *targets.Target, original, baseline []byte, trace io.Writer, - pred func(test []byte) (BisectResult, error)) ([]byte, error) { +func (ctx *testos) Minimize(target *targets.Target, original, baseline []byte, + dt debugtracer.DebugTracer, pred func(test []byte) (BisectResult, error)) ([]byte, error) { if res, err := pred(baseline); err != nil { return nil, err } else if res == BisectBad { diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go index acdb9837e..7ede983f6 100644 --- a/pkg/vcs/vcs.go +++ b/pkg/vcs/vcs.go @@ -7,7 +7,6 @@ package vcs import ( "bytes" "fmt" - "io" "net/mail" "regexp" "sort" @@ -15,6 +14,7 @@ import ( "time" "github.com/google/syzkaller/dashboard/dashapi" + "github.com/google/syzkaller/pkg/debugtracer" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/sys/targets" ) @@ -116,7 +116,7 @@ type Bisecter interface { // Progress of the process is streamed to the provided trace. // Returns the first commit on which the predicate returns BisectBad, // or multiple commits if bisection is inconclusive due to BisectSkip. - Bisect(bad, good string, trace io.Writer, pred func() (BisectResult, error)) ([]*Commit, error) + Bisect(bad, good string, dt debugtracer.DebugTracer, pred func() (BisectResult, error)) ([]*Commit, error) // PreviousReleaseTags returns list of preceding release tags that are reachable from the given commit. // If the commit itself has a release tag, this tag is not included. @@ -128,7 +128,7 @@ type Bisecter interface { } type ConfigMinimizer interface { - Minimize(target *targets.Target, original, baseline []byte, trace io.Writer, + Minimize(target *targets.Target, original, baseline []byte, dt debugtracer.DebugTracer, pred func(test []byte) (BisectResult, error)) ([]byte, error) } |
