diff options
| author | Zubin Mithra <zsm@google.com> | 2023-03-07 16:21:41 -0800 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2023-03-10 07:45:18 +0100 |
| commit | 5205ef306e8b4217fc49cb8d8bd18670b7d08c3c (patch) | |
| tree | b91b96f1402ae75c5c6a86cff16b40100ef3ce0b /pkg/cover/html.go | |
| parent | f08b59ac0d8759f409d594ddca4f08c920e23237 (diff) | |
tools/syz-cover: allow for exporting source line coverage info
Add a `json` CLI flag that allows for writing out a JSON file with the
following coverage information.
* Module
* Filename
* Covered source lines
* Uncovered source lines
* Both source lines
This can be used to view syzkaller coverage information on other source
browsing/viewing tools.
Usage:
$ ./syz-cover -kernel_obj <path/to/vmlinux> -json <output_json> rawcover
Diffstat (limited to 'pkg/cover/html.go')
| -rw-r--r-- | pkg/cover/html.go | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/pkg/cover/html.go b/pkg/cover/html.go index c5c18c698..874160c8c 100644 --- a/pkg/cover/html.go +++ b/pkg/cover/html.go @@ -7,6 +7,7 @@ import ( "bufio" "bytes" "encoding/csv" + "encoding/json" "fmt" "html" "html/template" @@ -118,6 +119,66 @@ func (rg *ReportGenerator) DoHTML(w io.Writer, progs []Prog, coverFilter map[uin return coverTemplate.Execute(w, d) } +type lineCoverExport struct { + Module string `json:",omitempty"` + Filename string + Covered []int `json:",omitempty"` + Uncovered []int `json:",omitempty"` + 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) + if err != nil { + return err + } + var entries []lineCoverExport + for _, file := range files { + lines, err := parseFile(file.filename) + if err != nil { + // Ignore and continue onto the next file. + continue + } + entries = append(entries, fileLineContents(file, lines)) + } + encoder := json.NewEncoder(w) + encoder.SetIndent("", "\t") + if err := encoder.Encode(entries); err != nil { + return fmt.Errorf("encoding [%v] entries failed: %v", len(entries), err) + } + return nil +} + +func fileLineContents(file *file, lines [][]byte) lineCoverExport { + lce := lineCoverExport{ + Module: file.module, + Filename: file.filename, + } + lineCover := perLineCoverage(file.covered, file.uncovered) + for i, ln := range lines { + start := 0 + cover := append(lineCover[i+1], lineCoverChunk{End: backend.LineEnd}) + for _, cov := range cover { + end := cov.End - 1 + if end > len(ln) { + end = len(ln) + } + if end == start { + continue + } + if cov.Covered && cov.Uncovered { + lce.Both = append(lce.Both, i+1) + } else if cov.Covered { + lce.Covered = append(lce.Covered, i+1) + } else if cov.Uncovered { + lce.Uncovered = append(lce.Uncovered, i+1) + } + } + } + return lce +} + func (rg *ReportGenerator) DoRawCoverFiles(w http.ResponseWriter, progs []Prog, coverFilter map[uint32]uint32) error { progs = fixUpPCs(rg.target.Arch, progs, coverFilter) if err := rg.lazySymbolize(progs); err != nil { |
