aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2024-02-12 10:53:25 +0100
committerAlexander Potapenko <glider@google.com>2024-02-13 11:13:49 +0000
commite66542d78f1cf0c783877440cd239a11fb73fb15 (patch)
tree61119f20f1ea889b58c85f226171254f0836b0ca /pkg
parent77b23aa147a898d1e1912a5f01e6716bbdc3a59e (diff)
pkg/cover, syz-manager: introduce the /cover?debug=1 parameter
Debugging coverage point validation warnings may require looking at specific addresses, which are not printed anywhere. Add a URL parameter that can be passed to prepareFileMap() to print a more meaningful error message. Also factor out the error message code from prepareFileMap() to reduce its cyclomatic complexity.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/cover/html.go38
-rw-r--r--pkg/cover/report.go19
-rw-r--r--pkg/cover/report_test.go11
3 files changed, 44 insertions, 24 deletions
diff --git a/pkg/cover/html.go b/pkg/cover/html.go
index bbfc11536..8cb9e7511 100644
--- a/pkg/cover/html.go
+++ b/pkg/cover/html.go
@@ -24,9 +24,15 @@ import (
"github.com/google/syzkaller/pkg/mgrconfig"
)
-func (rg *ReportGenerator) DoHTML(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
- progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
- files, err := rg.prepareFileMap(progs)
+type CoverHandlerParams struct {
+ Progs []Prog
+ CoverFilter map[uint32]uint32
+ Debug bool
+}
+
+func (rg *ReportGenerator) DoHTML(w io.Writer, params CoverHandlerParams) error {
+ var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
+ files, err := rg.prepareFileMap(progs, params.Debug)
if err != nil {
return err
}
@@ -127,9 +133,9 @@ type lineCoverExport struct {
Both []int `json:",omitempty"`
}
-func (rg *ReportGenerator) DoLineJSON(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
- progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
- files, err := rg.prepareFileMap(progs)
+func (rg *ReportGenerator) DoLineJSON(w io.Writer, params CoverHandlerParams) error {
+ var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
+ files, err := rg.prepareFileMap(progs, params.Debug)
if err != nil {
return err
}
@@ -291,7 +297,7 @@ var csvFilesHeader = []string{
}
func (rg *ReportGenerator) convertToStats(progs []Prog) ([]fileStats, error) {
- files, err := rg.prepareFileMap(progs)
+ files, err := rg.prepareFileMap(progs, false)
if err != nil {
return nil, err
}
@@ -341,8 +347,8 @@ func (rg *ReportGenerator) convertToStats(progs []Prog) ([]fileStats, error) {
return data, nil
}
-func (rg *ReportGenerator) DoCSVFiles(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
- progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
+func (rg *ReportGenerator) DoCSVFiles(w io.Writer, params CoverHandlerParams) error {
+ var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
data, err := rg.convertToStats(progs)
if err != nil {
return err
@@ -441,8 +447,8 @@ func groupCoverByFilePrefixes(datas []fileStats, subsystems []mgrconfig.Subsyste
return d
}
-func (rg *ReportGenerator) DoHTMLTable(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
- progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
+func (rg *ReportGenerator) DoHTMLTable(w io.Writer, params CoverHandlerParams) error {
+ var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
data, err := rg.convertToStats(progs)
if err != nil {
return err
@@ -517,8 +523,8 @@ func groupCoverByModule(datas []fileStats) map[string]map[string]string {
return d
}
-func (rg *ReportGenerator) DoModuleCover(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
- progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
+func (rg *ReportGenerator) DoModuleCover(w io.Writer, params CoverHandlerParams) error {
+ var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
data, err := rg.convertToStats(progs)
if err != nil {
return err
@@ -537,9 +543,9 @@ var csvHeader = []string{
"Total PCs",
}
-func (rg *ReportGenerator) DoCSV(w io.Writer, progs []Prog, coverFilter map[uint32]uint32) error {
- progs = fixUpPCs(rg.target.Arch, progs, coverFilter)
- files, err := rg.prepareFileMap(progs)
+func (rg *ReportGenerator) DoCSV(w io.Writer, params CoverHandlerParams) error {
+ var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
+ files, err := rg.prepareFileMap(progs, params.Debug)
if err != nil {
return err
}
diff --git a/pkg/cover/report.go b/pkg/cover/report.go
index 6bf7e0a6f..9d03811ad 100644
--- a/pkg/cover/report.go
+++ b/pkg/cover/report.go
@@ -74,7 +74,20 @@ type line struct {
progIndex int // example program index that covers this line
}
-func (rg *ReportGenerator) prepareFileMap(progs []Prog) (map[string]*file, error) {
+func coverageCallbackMismatch(debug bool, numPCs int, unmatchedProgPCs map[uint64]bool) error {
+ debugStr := ""
+ if debug {
+ debugStr += "\n\nUnmatched PCs:\n"
+ for pc := range unmatchedProgPCs {
+ debugStr += fmt.Sprintf("%x\n", pc)
+ }
+ }
+ // nolint: lll
+ return fmt.Errorf("%d out of %d PCs returned by kcov do not have matching coverage callbacks. Check the discoverModules() code.%s",
+ len(unmatchedProgPCs), numPCs, debugStr)
+}
+
+func (rg *ReportGenerator) prepareFileMap(progs []Prog, debug bool) (map[string]*file, error) {
if err := rg.lazySymbolize(progs); err != nil {
return nil, err
}
@@ -131,9 +144,7 @@ func (rg *ReportGenerator) prepareFileMap(progs []Prog) (map[string]*file, error
// If the backend provided coverage callback locations for the binaries, use them to
// verify data returned by kcov.
if verifyCoverPoints && (len(unmatchedProgPCs) > 0) {
- return nil, fmt.Errorf("%d out of %d PCs returned by kcov do not have matching "+
- "coverage callbacks. Check the discoverModules() code",
- len(unmatchedProgPCs), len(progPCs))
+ return nil, coverageCallbackMismatch(debug, len(progPCs), unmatchedProgPCs)
}
for _, unit := range rg.Units {
f := files[unit.Name]
diff --git a/pkg/cover/report_test.go b/pkg/cover/report_test.go
index c6c9d28f1..3d31841cc 100644
--- a/pkg/cover/report_test.go
+++ b/pkg/cover/report_test.go
@@ -365,20 +365,23 @@ func generateReport(t *testing.T, target *targets.Target, test *Test) ([]byte, [
progs = append(progs, Prog{Data: "main", PCs: pcs})
}
html := new(bytes.Buffer)
- if err := rg.DoHTML(html, progs, nil); err != nil {
+ params := CoverHandlerParams{
+ Progs: progs,
+ }
+ if err := rg.DoHTML(html, params); err != nil {
return nil, nil, err
}
htmlTable := new(bytes.Buffer)
- if err := rg.DoHTMLTable(htmlTable, progs, nil); err != nil {
+ if err := rg.DoHTMLTable(htmlTable, params); err != nil {
return nil, nil, err
}
_ = htmlTable
csv := new(bytes.Buffer)
- if err := rg.DoCSV(csv, progs, nil); err != nil {
+ if err := rg.DoCSV(csv, params); err != nil {
return nil, nil, err
}
csvFiles := new(bytes.Buffer)
- if err := rg.DoCSVFiles(csvFiles, progs, nil); err != nil {
+ if err := rg.DoCSVFiles(csvFiles, params); err != nil {
return nil, nil, err
}
_ = csvFiles