diff options
| author | Space Meyer <spm@google.com> | 2022-09-13 15:24:23 +0000 |
|---|---|---|
| committer | Space Meyer <git@the-space.agency> | 2022-10-07 11:11:53 +0200 |
| commit | 79a5963585ac032cd3f390a37b5d276f7f9d0b5c (patch) | |
| tree | 593a2ad8c17be76a25b04654429f1604a565a0a2 | |
| parent | 8a2121976b8020f2006c1a953766af912ba709dd (diff) | |
pkg/bisect: use default compiler during bisection where possible
This allows us to bisect at least recently introduced bugs, where the
manager that found the bug uses a non standard compiler. This is usefull
during development of a new sanitizer for which a compiler with
non-upstreamed patches is required.
| -rw-r--r-- | pkg/bisect/bisect.go | 28 | ||||
| -rw-r--r-- | pkg/vcs/linux.go | 42 | ||||
| -rw-r--r-- | pkg/vcs/linux_test.go | 50 | ||||
| -rw-r--r-- | pkg/vcs/testos.go | 6 | ||||
| -rw-r--r-- | pkg/vcs/vcs.go | 4 | ||||
| -rw-r--r-- | syz-ci/jobs.go | 11 | ||||
| -rw-r--r-- | syz-ci/syz-ci.go | 16 | ||||
| -rw-r--r-- | tools/syz-bisect/bisect.go | 12 | ||||
| -rw-r--r-- | tools/syz-testbuild/testbuild.go | 3 |
9 files changed, 119 insertions, 53 deletions
diff --git a/pkg/bisect/bisect.go b/pkg/bisect/bisect.go index 939101a6e..5755bf562 100644 --- a/pkg/bisect/bisect.go +++ b/pkg/bisect/bisect.go @@ -19,16 +19,17 @@ import ( ) type Config struct { - Trace debugtracer.DebugTracer - Fix bool - BisectCompiler string - BinDir string - Ccache string - Timeout time.Duration - Kernel KernelConfig - Syzkaller SyzkallerConfig - Repro ReproConfig - Manager *mgrconfig.Config + Trace debugtracer.DebugTracer + Fix bool + DefaultCompiler string + CompilerType string + BinDir string + Ccache string + Timeout time.Duration + Kernel KernelConfig + Syzkaller SyzkallerConfig + Repro ReproConfig + Manager *mgrconfig.Config } type KernelConfig struct { @@ -420,7 +421,7 @@ func (env *env) commitRangeForFix() (*vcs.Commit, *vcs.Commit, *report.Report, [ func (env *env) commitRangeForBug() (*vcs.Commit, *vcs.Commit, *report.Report, []*testResult, error) { cfg := env.cfg - tags, err := env.bisecter.PreviousReleaseTags(cfg.Kernel.Commit, cfg.BisectCompiler) + tags, err := env.bisecter.PreviousReleaseTags(cfg.Kernel.Commit, cfg.CompilerType) if err != nil { return nil, nil, nil, nil, err } @@ -465,11 +466,12 @@ func (env *env) build() (*vcs.Commit, string, error) { return nil, "", err } - bisectEnv, err := env.bisecter.EnvForCommit(env.cfg.BisectCompiler, env.cfg.BinDir, current.Hash, env.kernelConfig) + bisectEnv, err := env.bisecter.EnvForCommit( + env.cfg.DefaultCompiler, env.cfg.CompilerType, env.cfg.BinDir, current.Hash, env.kernelConfig) if err != nil { return current, "", err } - env.log("testing commit %v %v", current.Hash, env.cfg.BisectCompiler) + env.log("testing commit %v %v", current.Hash, env.cfg.CompilerType) buildStart := time.Now() mgr := env.cfg.Manager if err := build.Clean(mgr.TargetOS, mgr.TargetVMArch, mgr.Type, mgr.KernelSrc); err != nil { diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go index 8ee801430..5e2ccf3e1 100644 --- a/pkg/vcs/linux.go +++ b/pkg/vcs/linux.go @@ -42,14 +42,14 @@ func newLinux(dir string, opts []RepoOpt, vmType string) *linux { } } -func (ctx *linux) PreviousReleaseTags(commit, bisectCompiler string) ([]string, error) { +func (ctx *linux) PreviousReleaseTags(commit, compilerType string) ([]string, error) { tags, err := ctx.git.previousReleaseTags(commit, false, false, false) if err != nil { return nil, err } cutoff := "" - if bisectCompiler == "gcc" { + if compilerType == "gcc" { // Initially we tried to stop at 3.8 because: // v3.8 does not work with modern perl, and as we go further in history // make stops to work, then binutils, glibc, etc. So we stop at v3.8. @@ -70,7 +70,7 @@ func (ctx *linux) PreviousReleaseTags(commit, bisectCompiler string) ([]string, // even more (as new releases are produced). Next good candidate may be 4.11 // because then we won't need gcc 5.5. cutoff = "v4.5" - } else if bisectCompiler == "clang" { + } else if compilerType == "clang" { // v5.3 was the first release with solid clang support, however I was able to // compile v5.1..v5.3 using a newer defconfig + make oldconfig. Everything older // would require further cherry-picks. @@ -132,7 +132,9 @@ func gitReleaseTagToInt(tag string, includeRC bool) uint64 { return v1*1e9 + v2*1e6 + rc*1e3 + v3 } -func (ctx *linux) EnvForCommit(bisectCompiler, binDir, commit string, kernelConfig []byte) (*BisectEnv, error) { +func (ctx *linux) EnvForCommit( + defaultCompiler, compilerType, binDir, commit string, kernelConfig []byte, +) (*BisectEnv, error) { tagList, err := ctx.previousReleaseTags(commit, true, false, false) if err != nil { return nil, err @@ -148,12 +150,12 @@ func (ctx *linux) EnvForCommit(bisectCompiler, binDir, commit string, kernelConf linuxAlterConfigs(cf, tags) compiler := "" - if bisectCompiler == "gcc" { - compiler = filepath.Join(binDir, "gcc-"+linuxGCCVersion(tags), "bin", "gcc") - } else if bisectCompiler == "clang" { - compiler = filepath.Join(binDir, "llvm-"+linuxClangVersion(tags), "bin", "clang") + if compilerType == "gcc" { + compiler = linuxGCCPath(tags, binDir, defaultCompiler) + } else if compilerType == "clang" { + compiler = linuxClangPath(tags, binDir, defaultCompiler) } else { - return nil, fmt.Errorf("unsupported bisect compiler: %v", bisectCompiler) + return nil, fmt.Errorf("unsupported bisect compiler: %v", compilerType) } env := &BisectEnv{ @@ -180,28 +182,34 @@ func (ctx *linux) EnvForCommit(bisectCompiler, binDir, commit string, kernelConf return env, nil } -func linuxClangVersion(tags map[string]bool) string { +func linuxClangPath(tags map[string]bool, binDir, defaultCompiler string) string { + version := "" switch { case tags["v5.9"]: - return "14.0.6" + // Verified to work with 14.0.6. + return defaultCompiler default: // everything before v5.3 might not work great // everything before v5.1 does not work - return "9.0.1" + version = "9.0.1" } + return filepath.Join(binDir, "llvm-"+version, "bin", "clang") } -func linuxGCCVersion(tags map[string]bool) string { +func linuxGCCPath(tags map[string]bool, binDir, defaultCompiler string) string { + version := "" switch { case tags["v5.9"]: - return "10.1.0" + // Verified to work with 10.1.0. + return defaultCompiler case tags["v4.12"]: - return "8.1.0" + version = "8.1.0" case tags["v4.11"]: - return "7.3.0" + version = "7.3.0" default: - return "5.5.0" + version = "5.5.0" } + return filepath.Join(binDir, "gcc-"+version, "bin", "gcc") } func linuxAlterConfigs(cf *kconfig.ConfigFile, tags map[string]bool) { diff --git a/pkg/vcs/linux_test.go b/pkg/vcs/linux_test.go new file mode 100644 index 000000000..1865aa2d6 --- /dev/null +++ b/pkg/vcs/linux_test.go @@ -0,0 +1,50 @@ +// Copyright 2022 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package vcs + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestClangVersion(t *testing.T) { + defaultCompiler := "/some/default/compiler" + binDir := "/some/dir/" + tags := make(map[string]bool) + + // No tags case. + actual := linuxClangPath(tags, binDir, defaultCompiler) + expected := binDir + "llvm-9.0.1/bin/clang" + assert.Equal(t, actual, expected, "unexpected clang path") + + // Recent tag case. + tags["v5.9"] = true + actual = linuxClangPath(tags, binDir, defaultCompiler) + expected = defaultCompiler + assert.Equal(t, actual, expected, "unexpected clang path") +} + +func TestGCCVersion(t *testing.T) { + defaultCompiler := "/some/default/compiler" + binDir := "/some/dir/" + tags := make(map[string]bool) + + // No tags case. + actual := linuxGCCPath(tags, binDir, defaultCompiler) + expected := binDir + "gcc-5.5.0/bin/gcc" + assert.Equal(t, actual, expected, "unexpected gcc path") + + // Somewhat old tag case. + tags["v4.12"] = true + actual = linuxGCCPath(tags, binDir, defaultCompiler) + expected = binDir + "gcc-8.1.0/bin/gcc" + assert.Equal(t, actual, expected, "unexpected gcc path") + + // Recent tag case. + tags["v5.9"] = true + actual = linuxGCCPath(tags, binDir, defaultCompiler) + expected = defaultCompiler + assert.Equal(t, actual, expected, "unexpected gcc path") +} diff --git a/pkg/vcs/testos.go b/pkg/vcs/testos.go index 0053a528e..fe7c3790f 100644 --- a/pkg/vcs/testos.go +++ b/pkg/vcs/testos.go @@ -22,11 +22,13 @@ func newTestos(dir string, opts []RepoOpt) *testos { } } -func (ctx *testos) PreviousReleaseTags(commit, bisectCompiler string) ([]string, error) { +func (ctx *testos) PreviousReleaseTags(commit, compilerType string) ([]string, error) { return ctx.git.previousReleaseTags(commit, false, false, false) } -func (ctx *testos) EnvForCommit(bisectCompiler, binDir, commit string, kernelConfig []byte) (*BisectEnv, error) { +func (ctx *testos) EnvForCommit( + defaultCompiler, compilerType, binDir, commit string, kernelConfig []byte, +) (*BisectEnv, error) { return &BisectEnv{KernelConfig: kernelConfig}, nil } diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go index 50e45252e..4b4f26e06 100644 --- a/pkg/vcs/vcs.go +++ b/pkg/vcs/vcs.go @@ -79,11 +79,11 @@ type Bisecter interface { // 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. - PreviousReleaseTags(commit, bisectCompiler string) ([]string, error) + PreviousReleaseTags(commit, compilerType string) ([]string, error) IsRelease(commit string) (bool, error) - EnvForCommit(bisectCompiler, binDir, commit string, kernelConfig []byte) (*BisectEnv, error) + EnvForCommit(defaultCompiler, compilerType, binDir, commit string, kernelConfig []byte) (*BisectEnv, error) } type ConfigMinimizer interface { diff --git a/syz-ci/jobs.go b/syz-ci/jobs.go index a49b9a7f6..588c3df2b 100644 --- a/syz-ci/jobs.go +++ b/syz-ci/jobs.go @@ -412,11 +412,12 @@ func (jp *JobProcessor) bisect(job *Job, mgrcfg *mgrconfig.Config) error { // compete with patch testing jobs (it's bad delaying patch testing). // When/if bisection jobs don't compete with patch testing, // it makes sense to increase this to 12-24h. - Timeout: 8 * time.Hour, - Fix: req.Type == dashapi.JobBisectFix, - BisectCompiler: mgr.mgrcfg.BisectCompiler, - BinDir: jp.cfg.BisectBinDir, - Ccache: jp.cfg.Ccache, + Timeout: 8 * time.Hour, + Fix: req.Type == dashapi.JobBisectFix, + DefaultCompiler: mgr.mgrcfg.Compiler, + CompilerType: mgr.mgrcfg.CompilerType, + BinDir: jp.cfg.BisectBinDir, + Ccache: jp.cfg.Ccache, Kernel: bisect.KernelConfig{ Repo: mgr.mgrcfg.Repo, Branch: mgr.mgrcfg.Branch, diff --git a/syz-ci/syz-ci.go b/syz-ci/syz-ci.go index 944c0c745..4abbe21c0 100644 --- a/syz-ci/syz-ci.go +++ b/syz-ci/syz-ci.go @@ -153,14 +153,14 @@ type ManagerConfig struct { Repo string `json:"repo"` // Short name of the repo (e.g. "linux-next"), used only for reporting. RepoAlias string `json:"repo_alias"` + Branch string `json:"branch"` // Defaults to "master". // Currently either 'gcc' or 'clang'. Note that pkg/bisect requires // explicit plumbing for every os/compiler combination. - BisectCompiler string `json:"bisect_compiler"` // Defaults to "gcc" - Branch string `json:"branch"` // Defaults to "master". - Compiler string `json:"compiler"` - Ccache string `json:"ccache"` - Userspace string `json:"userspace"` - KernelConfig string `json:"kernel_config"` + CompilerType string `json:"compiler_type"` // Defaults to "gcc" + Compiler string `json:"compiler"` + Ccache string `json:"ccache"` + Userspace string `json:"userspace"` + KernelConfig string `json:"kernel_config"` // Baseline config for bisection, see pkg/bisect.KernelConfig.BaselineConfig. KernelBaselineConfig string `json:"kernel_baseline_config"` // File with kernel cmdline values (optional). @@ -386,8 +386,8 @@ func loadManagerConfig(cfg *Config, mgr *ManagerConfig) error { if !managerNameRe.MatchString(mgr.Name) { return fmt.Errorf("param 'managers.name' has bad value: %q", mgr.Name) } - if mgr.BisectCompiler == "" { - mgr.BisectCompiler = "gcc" + if mgr.CompilerType == "" { + mgr.CompilerType = "gcc" } if mgr.Branch == "" { mgr.Branch = "master" diff --git a/tools/syz-bisect/bisect.go b/tools/syz-bisect/bisect.go index c4548de35..7fa17c25d 100644 --- a/tools/syz-bisect/bisect.go +++ b/tools/syz-bisect/bisect.go @@ -44,9 +44,10 @@ var ( ) type Config struct { + Compiler string `json:"compiler"` // Currently either 'gcc' or 'clang'. Note that pkg/bisect requires // explicit plumbing for every os/compiler combination. - BisectCompiler string `json:"bisect_compiler"` + CompilerType string `json:"compiler_type"` // BinDir must point to a dir that contains compilers required to build // older versions of the kernel. For linux, it needs to include several // compiler versions. @@ -97,10 +98,11 @@ func main() { TraceWriter: os.Stdout, OutDir: *flagCrash, }, - Fix: *flagFix, - BisectCompiler: mycfg.BisectCompiler, - BinDir: mycfg.BinDir, - Ccache: mycfg.Ccache, + Fix: *flagFix, + DefaultCompiler: mycfg.Compiler, + CompilerType: mycfg.CompilerType, + BinDir: mycfg.BinDir, + Ccache: mycfg.Ccache, Kernel: bisect.KernelConfig{ Repo: mycfg.KernelRepo, Branch: mycfg.KernelBranch, diff --git a/tools/syz-testbuild/testbuild.go b/tools/syz-testbuild/testbuild.go index be2718b3a..6b68b44fc 100644 --- a/tools/syz-testbuild/testbuild.go +++ b/tools/syz-testbuild/testbuild.go @@ -125,7 +125,8 @@ func main() { } func test(repo vcs.Repo, bisecter vcs.Bisecter, kernelConfig []byte, env instance.Env, com *vcs.Commit) { - bisectEnv, err := bisecter.EnvForCommit("gcc", *flagBisectBin, com.Hash, kernelConfig) + compiler, compilerType := "gcc", "gcc" + bisectEnv, err := bisecter.EnvForCommit(compiler, compilerType, *flagBisectBin, com.Hash, kernelConfig) if err != nil { tool.Fail(err) } |
