From aff16d3fed742e27093858a70f8bd5cbf6f0dedd Mon Sep 17 00:00:00 2001 From: Joey Jiaojg Date: Wed, 3 Mar 2021 00:22:57 +0800 Subject: pkg/cover, syz-manager: show coverage summary * pkg/cover, syz-manager: show coverage summary The funccover or cover page is not easy for statistic purpose. So add /cover?type=rawfiles to show coverage based on each file. And /cover?type=table page to show coverage for group of components. If driver_path_map.json exists, /cover?type=table can show component coverage. Format example: { "all": [ "/" ], "audio": [ "/techpack/audio/asoc", "/techpack/audio/dsp", "/techpack/audio/ipc", "/sound/core" ] } If driver_path_map.json not exist, it will show one line summary. * pkg/cover: use subsystem naming * syz-manager: use /subsystemcover and /filecover * pkg/cover: use subsystem from config * pkg/mgrconfig: add kernel_subsystem * pkg/cover, tools/syz-cover: fix make test * all: fix presumit errors * pkg/cover, syz-manager: fix subsystem --- syz-manager/cover.go | 3 ++- syz-manager/html.go | 61 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 22 deletions(-) (limited to 'syz-manager') diff --git a/syz-manager/cover.go b/syz-manager/cover.go index f5ca86631..1d33b4d91 100644 --- a/syz-manager/cover.go +++ b/syz-manager/cover.go @@ -18,7 +18,8 @@ var getReportGenerator = func() func(cfg *mgrconfig.Config) (*cover.ReportGenera 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) + rg, err = cover.MakeReportGenerator(cfg.SysTarget, cfg.Type, cfg.KernelObj, cfg.KernelSrc, + cfg.KernelBuildSrc, cfg.KernelSubsystem) }) return rg, err } diff --git a/syz-manager/html.go b/syz-manager/html.go index 91b3cc68d..c5b3aac33 100644 --- a/syz-manager/html.go +++ b/syz-manager/html.go @@ -38,12 +38,14 @@ func (mgr *Manager) initHTTP() { http.HandleFunc("/corpus", mgr.httpCorpus) http.HandleFunc("/crash", mgr.httpCrash) http.HandleFunc("/cover", mgr.httpCover) + http.HandleFunc("/subsystemcover", mgr.httpSubsystemCover) http.HandleFunc("/prio", mgr.httpPrio) http.HandleFunc("/file", mgr.httpFile) http.HandleFunc("/report", mgr.httpReport) http.HandleFunc("/rawcover", mgr.httpRawCover) http.HandleFunc("/filterpcs", mgr.httpFilterPCs) http.HandleFunc("/funccover", mgr.httpFuncCover) + http.HandleFunc("/filecover", mgr.httpFileCover) http.HandleFunc("/input", mgr.httpInput) // Browsers like to request this, without special handler this goes to / handler. http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {}) @@ -208,26 +210,42 @@ func (mgr *Manager) httpCorpus(w http.ResponseWriter, r *http.Request) { executeTemplate(w, corpusTemplate, data) } +const ( + DoHTML int = iota + DoHTMLTable + DoCSV + DoCSVFiles +) + func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) { + mgr.httpCoverCover(w, r, DoHTML, true) +} + +func (mgr *Manager) httpSubsystemCover(w http.ResponseWriter, r *http.Request) { + mgr.httpCoverCover(w, r, DoHTMLTable, true) +} + +func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcFlag int, isHTMLCover bool) { if !mgr.cfg.Cover { - mgr.mu.Lock() - defer mgr.mu.Unlock() - mgr.httpCoverFallback(w, r) + if isHTMLCover { + mgr.mu.Lock() + defer mgr.mu.Unlock() + mgr.httpCoverFallback(w, r) + } else { + http.Error(w, "coverage is not enabled", http.StatusInternalServerError) + } + return } - // Note: initCover is executed without mgr.mu because it takes very long time - // (but it only reads config and it protected by initCoverOnce). + 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, rg, rg.DoHTML) -} -func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, - rg *cover.ReportGenerator, do func(io.Writer, []cover.Prog) error) { convert := coverToPCs if r.FormValue("filter") != "" && mgr.coverFilter != nil { convert = func(rg *cover.ReportGenerator, cover []uint32) (ret []uint64) { @@ -258,6 +276,14 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, }) } } + do := rg.DoHTML + if funcFlag == DoHTMLTable { + do = rg.DoHTMLTable + } else if funcFlag == DoCSV { + do = rg.DoCSV + } else if funcFlag == DoCSVFiles { + do = rg.DoCSVFiles + } if err := do(w, progs); err != nil { http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) return @@ -297,18 +323,11 @@ func (mgr *Manager) httpCoverFallback(w http.ResponseWriter, r *http.Request) { } func (mgr *Manager) httpFuncCover(w http.ResponseWriter, r *http.Request) { - if !mgr.cfg.Cover { - http.Error(w, "coverage is not enabled", http.StatusInternalServerError) - return - } - 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, rg, rg.DoCSV) + mgr.httpCoverCover(w, r, DoCSV, false) +} + +func (mgr *Manager) httpFileCover(w http.ResponseWriter, r *http.Request) { + mgr.httpCoverCover(w, r, DoCSVFiles, false) } func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) { -- cgit mrf-deployment