diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-12-11 18:18:58 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-12-13 18:56:36 +0100 |
| commit | 3fc0a844bfb8efd6f8fe32585e4fd5d9f2af3fc3 (patch) | |
| tree | 9a6f4e9737e4312bb32ec9ea820cfa508e5add80 | |
| parent | 138959733bc731cc789fa7c7473e493b2e104bcc (diff) | |
syz-manager: better encapsulate report generator
Avoid global variables and implicit dependencies on previous initialization.
| -rw-r--r-- | pkg/cover/report.go | 3 | ||||
| -rw-r--r-- | syz-manager/cover.go | 36 | ||||
| -rw-r--r-- | syz-manager/covfilter.go | 11 | ||||
| -rw-r--r-- | syz-manager/html.go | 24 |
4 files changed, 38 insertions, 36 deletions
diff --git a/pkg/cover/report.go b/pkg/cover/report.go index 14c0b7422..e50e11d13 100644 --- a/pkg/cover/report.go +++ b/pkg/cover/report.go @@ -32,6 +32,9 @@ var ( ) func MakeReportGenerator(target *targets.Target, vm, objDir, srcDir, buildDir string) (*ReportGenerator, error) { + if objDir == "" { + return nil, fmt.Errorf("kernel obj directory is not specified") + } impl, err := backend.Make(target, vm, objDir) if err != nil { return nil, err diff --git a/syz-manager/cover.go b/syz-manager/cover.go index 39f2ed001..f5ca86631 100644 --- a/syz-manager/cover.go +++ b/syz-manager/cover.go @@ -4,36 +4,30 @@ package main import ( - "fmt" "sync" "github.com/google/syzkaller/pkg/cover" + "github.com/google/syzkaller/pkg/log" "github.com/google/syzkaller/pkg/mgrconfig" - "github.com/google/syzkaller/sys/targets" ) -var ( - initCoverOnce sync.Once - initCoverError error - reportGenerator *cover.ReportGenerator -) - -func initCover(cfg *mgrconfig.Config) error { - initCoverOnce.Do(func() { - if cfg.KernelObj == "" { - initCoverError = fmt.Errorf("kernel_obj is not specified") - return - } - reportGenerator, initCoverError = cover.MakeReportGenerator( - cfg.SysTarget, cfg.Type, cfg.KernelObj, cfg.KernelSrc, cfg.KernelBuildSrc) - }) - return initCoverError -} +var getReportGenerator = func() func(cfg *mgrconfig.Config) (*cover.ReportGenerator, error) { + var once sync.Once + var rg *cover.ReportGenerator + var err error + return func(cfg *mgrconfig.Config) (*cover.ReportGenerator, error) { + once.Do(func() { + log.Logf(0, "initializing coverage information...") + rg, err = cover.MakeReportGenerator(cfg.SysTarget, cfg.Type, cfg.KernelObj, cfg.KernelSrc, cfg.KernelBuildSrc) + }) + return rg, err + } +}() -func coverToPCs(target *targets.Target, cov []uint32) []uint64 { +func coverToPCs(rg *cover.ReportGenerator, cov []uint32) []uint64 { pcs := make([]uint64, 0, len(cov)) for _, pc := range cov { - pcs = append(pcs, reportGenerator.RestorePC(pc)) + pcs = append(pcs, rg.RestorePC(pc)) } return pcs } diff --git a/syz-manager/covfilter.go b/syz-manager/covfilter.go index 5b252603e..db4c5a64f 100644 --- a/syz-manager/covfilter.go +++ b/syz-manager/covfilter.go @@ -13,6 +13,7 @@ import ( "sort" "strconv" + "github.com/google/syzkaller/pkg/cover" "github.com/google/syzkaller/pkg/log" "github.com/google/syzkaller/pkg/mgrconfig" "github.com/google/syzkaller/pkg/osutil" @@ -23,11 +24,11 @@ func createCoverageFilter(cfg *mgrconfig.Config) (string, map[uint32]uint32, err pcs := make(map[uint32]uint32) filter := &cfg.CovFilter if len(filter.Files) != 0 || len(filter.Functions) != 0 { - log.Logf(0, "initializing coverage information...") - if err := initCover(cfg); err != nil { + rg, err := getReportGenerator(cfg) + if err != nil { return "", nil, err } - if err := initFilesFuncs(pcs, filter.Files, filter.Functions); err != nil { + if err := initFilesFuncs(pcs, filter.Files, filter.Functions, rg); err != nil { return "", nil, err } } @@ -48,7 +49,7 @@ func createCoverageFilter(cfg *mgrconfig.Config) (string, map[uint32]uint32, err return filename, pcs, nil } -func initFilesFuncs(pcs map[uint32]uint32, files, funcs []string) error { +func initFilesFuncs(pcs map[uint32]uint32, files, funcs []string, rg *cover.ReportGenerator) error { funcsRegexp, err := compileRegexps(funcs) if err != nil { return err @@ -59,7 +60,7 @@ func initFilesFuncs(pcs map[uint32]uint32, files, funcs []string) error { } fileDedup := make(map[string]bool) used := make(map[*regexp.Regexp][]string) - for _, sym := range reportGenerator.Symbols { + for _, sym := range rg.Symbols { matched := false for _, re := range funcsRegexp { if re.MatchString(sym.Name) { diff --git a/syz-manager/html.go b/syz-manager/html.go index 24126adb5..0b606f099 100644 --- a/syz-manager/html.go +++ b/syz-manager/html.go @@ -214,22 +214,24 @@ func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) { } // Note: initCover is executed without mgr.mu because it takes very long time // (but it only reads config and it protected by initCoverOnce). - if err := initCover(mgr.cfg); err != nil { + rg, err := getReportGenerator(mgr.cfg) + if err != nil { http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) return } mgr.mu.Lock() defer mgr.mu.Unlock() - mgr.httpCoverCover(w, r, reportGenerator.DoHTML) + mgr.httpCoverCover(w, r, rg, rg.DoHTML) } -func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, do func(io.Writer, []cover.Prog) error) { +func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, + rg *cover.ReportGenerator, do func(io.Writer, []cover.Prog) error) { var progs []cover.Prog if sig := r.FormValue("input"); sig != "" { inp := mgr.corpus[sig] progs = append(progs, cover.Prog{ Data: string(inp.Prog), - PCs: coverToPCs(mgr.sysTarget, inp.Cover), + PCs: coverToPCs(rg, inp.Cover), }) } else { call := r.FormValue("call") @@ -239,7 +241,7 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, do fu } progs = append(progs, cover.Prog{ Data: string(inp.Prog), - PCs: coverToPCs(mgr.sysTarget, inp.Cover), + PCs: coverToPCs(rg, inp.Cover), }) } } @@ -286,13 +288,14 @@ func (mgr *Manager) httpFuncCover(w http.ResponseWriter, r *http.Request) { http.Error(w, "coverage is not enabled", http.StatusInternalServerError) return } - if err := initCover(mgr.cfg); err != nil { + rg, err := getReportGenerator(mgr.cfg) + if err != nil { http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) return } mgr.mu.Lock() defer mgr.mu.Unlock() - mgr.httpCoverCover(w, r, reportGenerator.DoCSV) + mgr.httpCoverCover(w, r, rg, rg.DoCSV) } func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) { @@ -392,8 +395,9 @@ func (mgr *Manager) httpReport(w http.ResponseWriter, r *http.Request) { func (mgr *Manager) httpRawCover(w http.ResponseWriter, r *http.Request) { // Note: initCover is executed without mgr.mu because it takes very long time // (but it only reads config and it protected by initCoverOnce). - if err := initCover(mgr.cfg); err != nil { - http.Error(w, initCoverError.Error(), http.StatusInternalServerError) + rg, err := getReportGenerator(mgr.cfg) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) return } mgr.mu.Lock() @@ -403,7 +407,7 @@ func (mgr *Manager) httpRawCover(w http.ResponseWriter, r *http.Request) { for _, inp := range mgr.corpus { cov.Merge(inp.Cover) } - pcs := coverToPCs(mgr.sysTarget, cov.Serialize()) + pcs := coverToPCs(rg, cov.Serialize()) sort.Slice(pcs, func(i, j int) bool { return pcs[i] < pcs[j] }) |
