aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoey Jiao <joeyjiaojg@gmail.com>2021-07-13 08:10:40 +0800
committerDmitry Vyukov <dvyukov@google.com>2021-07-14 20:01:00 +0200
commitb9a2f64e4081e5f8f66f00ebb376068d4064daee (patch)
tree9839ef85d2c0a47cb9353aa15a66b3c5b01a998d
parent94e0b7079acc1c1ab28a2043fd21321c978f1529 (diff)
all: add /modulecover page
-rw-r--r--pkg/cover/backend/backend.go3
-rw-r--r--pkg/cover/backend/dwarf.go1
-rw-r--r--pkg/cover/html.go84
-rw-r--r--pkg/cover/report.go7
-rw-r--r--syz-manager/html.go8
5 files changed, 97 insertions, 6 deletions
diff --git a/pkg/cover/backend/backend.go b/pkg/cover/backend/backend.go
index 1cebc7ecd..3bd95a6fa 100644
--- a/pkg/cover/backend/backend.go
+++ b/pkg/cover/backend/backend.go
@@ -26,7 +26,8 @@ type Module struct {
type CompileUnit struct {
ObjectUnit
- Path string
+ Path string
+ Module *Module
}
type Symbol struct {
diff --git a/pkg/cover/backend/dwarf.go b/pkg/cover/backend/dwarf.go
index 7a9abd221..8a2d524ea 100644
--- a/pkg/cover/backend/dwarf.go
+++ b/pkg/cover/backend/dwarf.go
@@ -272,6 +272,7 @@ func readTextRanges(debugInfo *dwarf.Data, module *Module, pcFix pcFixFn) (
ObjectUnit: ObjectUnit{
Name: attrName.(string),
},
+ Module: module,
}
units = append(units, unit)
ranges1, err := debugInfo.Ranges(ent)
diff --git a/pkg/cover/html.go b/pkg/cover/html.go
index 7afe8b54c..639adcf82 100644
--- a/pkg/cover/html.go
+++ b/pkg/cover/html.go
@@ -214,6 +214,7 @@ func (rg *ReportGenerator) DoFilterPCs(w http.ResponseWriter, progs []Prog, cove
type fileStats struct {
Name string
+ Module string
CoveredLines int
TotalLines int
CoveredPCs int
@@ -272,6 +273,7 @@ func (rg *ReportGenerator) convertToStats(progs []Prog) ([]fileStats, error) {
}
data = append(data, fileStats{
Name: fname,
+ Module: file.module,
CoveredLines: coveredLines,
TotalLines: totalLines,
CoveredPCs: file.coveredPCs,
@@ -374,7 +376,7 @@ func groupCoverByFilePrefixes(datas []fileStats, subsystems []mgrconfig.Subsyste
}
d[subsystem.Name] = map[string]string{
- "subsystem": subsystem.Name,
+ "name": subsystem.Name,
"lines": fmt.Sprintf("%v / %v / %.2f%%", coveredLines, totalLines, percentLines),
"PCsInFiles": fmt.Sprintf("%v / %v / %.2f%%", coveredPCsInFile, totalPCsInFile, percentPCsInFile),
"Funcs": fmt.Sprintf("%v / %v / %.2f%%", coveredFuncs, totalFuncs, percentCoveredFunc),
@@ -398,6 +400,82 @@ func (rg *ReportGenerator) DoHTMLTable(w io.Writer, progs []Prog, coverFilter ma
return coverTableTemplate.Execute(w, d)
}
+func groupCoverByModule(datas []fileStats) map[string]map[string]string {
+ d := make(map[string]map[string]string)
+
+ coveredLines := make(map[string]int)
+ totalLines := make(map[string]int)
+ coveredPCsInFile := make(map[string]int)
+ totalPCsInFile := make(map[string]int)
+ totalFuncs := make(map[string]int)
+ coveredFuncs := make(map[string]int)
+ coveredPCsInFuncs := make(map[string]int)
+ pcsInCoveredFuncs := make(map[string]int)
+ pcsInFuncs := make(map[string]int)
+ percentLines := make(map[string]float64)
+ percentPCsInFile := make(map[string]float64)
+ percentPCsInFunc := make(map[string]float64)
+ percentPCsInCoveredFunc := make(map[string]float64)
+ percentCoveredFunc := make(map[string]float64)
+
+ for _, data := range datas {
+ coveredLines[data.Module] += data.CoveredLines
+ totalLines[data.Module] += data.TotalLines
+ coveredPCsInFile[data.Module] += data.CoveredPCs
+ totalPCsInFile[data.Module] += data.TotalPCs
+ totalFuncs[data.Module] += data.TotalFunctions
+ coveredFuncs[data.Module] += data.CoveredFunctions
+ coveredPCsInFuncs[data.Module] += data.CoveredPCsInFunctions
+ pcsInFuncs[data.Module] += data.TotalPCsInFunctions
+ pcsInCoveredFuncs[data.Module] += data.TotalPCsInCoveredFunctions
+ }
+
+ for m := range totalLines {
+ if totalLines[m] != 0 {
+ percentLines[m] = 100.0 * float64(coveredLines[m]) / float64(totalLines[m])
+ }
+ if totalPCsInFile[m] != 0 {
+ percentPCsInFile[m] = 100.0 * float64(coveredPCsInFile[m]) / float64(totalPCsInFile[m])
+ }
+ if pcsInFuncs[m] != 0 {
+ percentPCsInFunc[m] = 100.0 * float64(coveredPCsInFuncs[m]) / float64(pcsInFuncs[m])
+ }
+ if pcsInCoveredFuncs[m] != 0 {
+ percentPCsInCoveredFunc[m] = 100.0 * float64(coveredPCsInFuncs[m]) / float64(pcsInCoveredFuncs[m])
+ }
+ if totalFuncs[m] != 0 {
+ percentCoveredFunc[m] = 100.0 * float64(coveredFuncs[m]) / float64(totalFuncs[m])
+ }
+ lines := fmt.Sprintf("%v / %v / %.2f%%", coveredLines[m], totalLines[m], percentLines[m])
+ pcsInFiles := fmt.Sprintf("%v / %v / %.2f%%", coveredPCsInFile[m], totalPCsInFile[m], percentPCsInFile[m])
+ funcs := fmt.Sprintf("%v / %v / %.2f%%", coveredFuncs[m], totalFuncs[m], percentCoveredFunc[m])
+ pcsInFuncs := fmt.Sprintf("%v / %v / %.2f%%", coveredPCsInFuncs[m], pcsInFuncs[m], percentPCsInFunc[m])
+ covedFuncs := fmt.Sprintf("%v / %v / %.2f%%", coveredPCsInFuncs[m], pcsInCoveredFuncs[m], percentPCsInCoveredFunc[m])
+ d[m] = map[string]string{
+ "name": m,
+ "lines": lines,
+ "PCsInFiles": pcsInFiles,
+ "Funcs": funcs,
+ "PCsInFuncs": pcsInFuncs,
+ "PCsInCoveredFuncs": covedFuncs,
+ }
+ }
+
+ return d
+}
+
+func (rg *ReportGenerator) DoModuleCover(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
+ progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
+ data, err := rg.convertToStats(progs)
+ if err != nil {
+ return err
+ }
+
+ d := groupCoverByModule(data)
+
+ return coverTableTemplate.Execute(w, d)
+}
+
var csvHeader = []string{
"Filename",
"Function",
@@ -898,7 +976,7 @@ var coverTableTemplate = template.Must(template.New("coverTable").Parse(`
<table>
<thead>
<tr>
- <th>Subsystem</th>
+ <th>Name</th>
<th>Covered / Total Lines / %</th>
<th>Covered / Total PCs in File / %</th>
<th>Covered / Total PCs in Function / %</th>
@@ -909,7 +987,7 @@ var coverTableTemplate = template.Must(template.New("coverTable").Parse(`
<tbody id="content">
{{range $i, $p := .}}
<tr>
- <td>{{$p.subsystem}}</td>
+ <td>{{$p.name}}</td>
<td>{{$p.lines}}</td>
<td>{{$p.PCsInFiles}}</td>
<td>{{$p.PCsInFuncs}}</td>
diff --git a/pkg/cover/report.go b/pkg/cover/report.go
index c7d96b703..788603119 100644
--- a/pkg/cover/report.go
+++ b/pkg/cover/report.go
@@ -49,6 +49,7 @@ func MakeReportGenerator(target *targets.Target, vm, objDir, srcDir, buildDir st
}
type file struct {
+ module string
filename string
lines map[int]line
functions []*function
@@ -76,6 +77,7 @@ func (rg *ReportGenerator) prepareFileMap(progs []Prog) (map[string]*file, error
files := make(map[string]*file)
for _, unit := range rg.Units {
files[unit.Name] = &file{
+ module: unit.Module.Name,
filename: unit.Path,
lines: make(map[int]line),
totalPCs: len(unit.PCs),
@@ -92,7 +94,7 @@ func (rg *ReportGenerator) prepareFileMap(progs []Prog) (map[string]*file, error
}
matchedPC := false
for _, frame := range rg.Frames {
- f := getFile(files, frame.Name, frame.Path)
+ f := getFile(files, frame.Name, frame.Path, frame.Module.Name)
ln := f.lines[frame.StartLine]
coveredBy := progPCs[frame.PC]
if len(coveredBy) == 0 {
@@ -190,10 +192,11 @@ func (rg *ReportGenerator) lazySymbolize(progs []Prog) error {
return nil
}
-func getFile(files map[string]*file, name, path string) *file {
+func getFile(files map[string]*file, name, path, module string) *file {
f := files[name]
if f == nil {
f = &file{
+ module: module,
filename: path,
lines: make(map[int]line),
// Special mark for header files, if a file does not have coverage at all it is not shown.
diff --git a/syz-manager/html.go b/syz-manager/html.go
index 449061a69..e7d58304e 100644
--- a/syz-manager/html.go
+++ b/syz-manager/html.go
@@ -44,6 +44,7 @@ func (mgr *Manager) initHTTP() {
mux.HandleFunc("/crash", mgr.httpCrash)
mux.HandleFunc("/cover", mgr.httpCover)
mux.HandleFunc("/subsystemcover", mgr.httpSubsystemCover)
+ mux.HandleFunc("/modulecover", mgr.httpModuleCover)
mux.HandleFunc("/prio", mgr.httpPrio)
mux.HandleFunc("/file", mgr.httpFile)
mux.HandleFunc("/report", mgr.httpReport)
@@ -238,6 +239,7 @@ func (mgr *Manager) httpDownloadCorpus(w http.ResponseWriter, r *http.Request) {
const (
DoHTML int = iota
DoHTMLTable
+ DoModuleCover
DoCSV
DoCSVFiles
DoRawCoverFiles
@@ -253,6 +255,10 @@ func (mgr *Manager) httpSubsystemCover(w http.ResponseWriter, r *http.Request) {
mgr.httpCoverCover(w, r, DoHTMLTable, true)
}
+func (mgr *Manager) httpModuleCover(w http.ResponseWriter, r *http.Request) {
+ mgr.httpCoverCover(w, r, DoModuleCover, true)
+}
+
func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcFlag int, isHTMLCover bool) {
if !mgr.cfg.Cover {
if isHTMLCover {
@@ -324,6 +330,8 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcF
do := rg.DoHTML
if funcFlag == DoHTMLTable {
do = rg.DoHTMLTable
+ } else if funcFlag == DoModuleCover {
+ do = rg.DoModuleCover
} else if funcFlag == DoCSV {
do = rg.DoCSV
} else if funcFlag == DoCSVFiles {