Skip to content

Commit 1bc60a1

Browse files
committed
tools/syz-declextract: add interface coverage info
Add coverage percent for kernel interfaces. The current data is generated with Mar coverage report on kernel commit 1e7857b28020ba57ca7fdafae7ac855ba326c697.
1 parent 2d9fa31 commit 1bc60a1

25 files changed

+2021
-1686
lines changed

pkg/cover/heatmap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func (thm *templateHeatmapRow) prepareDataFor(pageColumns []pageColumnTarget, sk
9191
var dateCoverage int64
9292
tp := pageColumn.TimePeriod
9393
if thm.instrumented[tp] != 0 {
94-
dateCoverage = percent(thm.covered[tp], thm.instrumented[tp])
94+
dateCoverage = Percent(thm.covered[tp], thm.instrumented[tp])
9595
}
9696
thm.Coverage = append(thm.Coverage, dateCoverage)
9797
thm.Tooltips = append(thm.Tooltips, fmt.Sprintf("Instrumented:\t%d blocks\nCovered:\t%d blocks",

pkg/cover/html.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ func addFunctionCoverage(file *file, data *templateData) {
877877
percentage := ""
878878
coveredTotal += function.covered
879879
if function.covered > 0 {
880-
percentage = fmt.Sprintf("%v%%", percent(function.covered, function.pcs))
880+
percentage = fmt.Sprintf("%v%%", Percent(function.covered, function.pcs))
881881
TotalInCoveredFunc += function.pcs
882882
} else {
883883
percentage = "---"
@@ -891,7 +891,7 @@ func addFunctionCoverage(file *file, data *templateData) {
891891
buf.WriteString("<span class='hover'>SUMMARY")
892892
percentInCoveredFunc := ""
893893
if TotalInCoveredFunc > 0 {
894-
percentInCoveredFunc = fmt.Sprintf("%v%%", percent(coveredTotal, TotalInCoveredFunc))
894+
percentInCoveredFunc = fmt.Sprintf("%v%%", Percent(coveredTotal, TotalInCoveredFunc))
895895
} else {
896896
percentInCoveredFunc = "---"
897897
}
@@ -915,21 +915,24 @@ func processDir(dir *templateDir) {
915915
for _, f := range dir.Files {
916916
dir.Total += f.Total
917917
dir.Covered += f.Covered
918-
f.Percent = percent(f.Covered, f.Total)
918+
f.Percent = Percent(f.Covered, f.Total)
919919
}
920920
for _, child := range dir.Dirs {
921921
processDir(child)
922922
dir.Total += child.Total
923923
dir.Covered += child.Covered
924924
}
925-
dir.Percent = percent(dir.Covered, dir.Total)
925+
dir.Percent = Percent(dir.Covered, dir.Total)
926926
if dir.Covered == 0 {
927927
dir.Dirs = nil
928928
dir.Files = nil
929929
}
930930
}
931931

932-
func percent[T int | int64](covered, total T) T {
932+
func Percent[T int | int64](covered, total T) T {
933+
if total == 0 {
934+
return 0
935+
}
933936
f := math.Ceil(float64(covered) / float64(total) * 100)
934937
if f == 100 && covered < total {
935938
f = 99

pkg/declextract/declextract.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"slices"
1313
"strings"
1414

15+
"github.com/google/syzkaller/pkg/cover"
1516
"github.com/google/syzkaller/pkg/ifaceprobe"
1617
)
1718

@@ -27,11 +28,12 @@ type StructInfo struct {
2728
Align int
2829
}
2930

30-
func Run(out *Output, probe *ifaceprobe.Info, syscallRename map[string][]string, trace io.Writer) (
31-
*Result, error) {
31+
func Run(out *Output, probe *ifaceprobe.Info, coverage []*cover.FileCoverage,
32+
syscallRename map[string][]string, trace io.Writer) (*Result, error) {
3233
ctx := &context{
3334
Output: out,
3435
probe: probe,
36+
coverage: coverage,
3537
syscallRename: syscallRename,
3638
structs: make(map[string]*Struct),
3739
funcs: make(map[string]*Function),
@@ -64,6 +66,7 @@ func Run(out *Output, probe *ifaceprobe.Info, syscallRename map[string][]string,
6466
type context struct {
6567
*Output
6668
probe *ifaceprobe.Info
69+
coverage []*cover.FileCoverage
6770
syscallRename map[string][]string // syscall function -> syscall names
6871
structs map[string]*Struct
6972
funcs map[string]*Function

pkg/declextract/entity.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ type FunctionScope struct {
4848
Calls []string `json:"calls,omitempty"`
4949
Facts []*TypingFact `json:"facts,omitempty"`
5050

51-
fn *Function
52-
calls []*Function
51+
fn *Function
52+
calls []*Function
53+
coveredBlocks int
54+
totalBlocks int
5355
}
5456

5557
type ConstInfo struct {

pkg/declextract/interface.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package declextract
66
import (
77
"slices"
88
"strings"
9+
10+
"github.com/google/syzkaller/pkg/cover"
911
)
1012

1113
type Interface struct {
@@ -19,6 +21,8 @@ type Interface struct {
1921
ManualDescriptions bool
2022
AutoDescriptions bool
2123
ReachableLOC int
24+
CoveredBlocks int
25+
TotalBlocks int
2226

2327
scopeArg int
2428
scopeVal string
@@ -41,7 +45,7 @@ func (ctx *context) noteInterface(iface *Interface) {
4145

4246
func (ctx *context) finishInterfaces() {
4347
for _, iface := range ctx.interfaces {
44-
iface.ReachableLOC = ctx.reachableLOC(iface.Func, iface.Files[0], iface.scopeArg, iface.scopeVal)
48+
ctx.calculateLOC(iface)
4549
slices.Sort(iface.Files)
4650
iface.Files = slices.Compact(iface.Files)
4751
if iface.Access == "" {
@@ -60,7 +64,29 @@ func (ctx *context) processFunctions() {
6064
ctx.funcs[fn.Name] = fn
6165
}
6266
}
67+
coverBlocks := make(map[string][]*cover.Block)
68+
for _, file := range ctx.coverage {
69+
for _, fn := range file.Functions {
70+
coverBlocks[file.FilePath+fn.FuncName] = fn.Blocks
71+
}
72+
}
6373
for _, fn := range ctx.Functions {
74+
for _, block := range coverBlocks[fn.File+fn.Name] {
75+
var match *FunctionScope
76+
for _, scope := range fn.Scopes {
77+
if scope.Arg == -1 {
78+
match = scope
79+
}
80+
if block.FromLine >= scope.StartLine && block.FromLine <= scope.EndLine {
81+
match = scope
82+
break
83+
}
84+
}
85+
match.totalBlocks++
86+
if block.HitCount != 0 {
87+
match.coveredBlocks++
88+
}
89+
}
6490
for _, scope := range fn.Scopes {
6591
for _, callee := range scope.Calls {
6692
called := ctx.findFunc(callee, fn.File)
@@ -74,19 +100,19 @@ func (ctx *context) processFunctions() {
74100
}
75101
}
76102

77-
func (ctx *context) reachableLOC(name, file string, scopeArg int, scopeVal string) int {
78-
fn := ctx.findFunc(name, file)
103+
func (ctx *context) calculateLOC(iface *Interface) {
104+
fn := ctx.findFunc(iface.Func, iface.Files[0])
79105
if fn == nil {
80-
ctx.warn("can't find function %v called in %v", name, file)
81-
return 0
106+
ctx.warn("can't find function %v called in %v", iface.Func, iface.Files[0])
107+
return
82108
}
83-
scopeFnArgs := ctx.inferArgFlow(fnArg{fn, scopeArg})
109+
scopeFnArgs := ctx.inferArgFlow(fnArg{fn, iface.scopeArg})
84110
visited := make(map[*Function]bool)
85-
return ctx.collectLOC(fn, scopeFnArgs, scopeVal, visited)
111+
iface.ReachableLOC = ctx.collectLOC(iface, fn, scopeFnArgs, iface.scopeVal, visited)
86112
}
87113

88-
func (ctx *context) collectLOC(fn *Function, scopeFnArgs map[fnArg]bool, scopeVal string,
89-
visited map[*Function]bool) int {
114+
func (ctx *context) collectLOC(iface *Interface, fn *Function, scopeFnArgs map[fnArg]bool,
115+
scopeVal string, visited map[*Function]bool) int {
90116
// Ignore very common functions when computing reachability for complexity analysis.
91117
// Counting kmalloc/printk against each caller is not useful (they have ~10K calls).
92118
// There are also subsystem common functions (e.g. functions called in some parts of fs/net).
@@ -104,11 +130,13 @@ func (ctx *context) collectLOC(fn *Function, scopeFnArgs map[fnArg]bool, scopeVa
104130
loc -= max(0, scope.EndLine-scope.StartLine)
105131
continue
106132
}
133+
iface.TotalBlocks += scope.totalBlocks
134+
iface.CoveredBlocks += scope.coveredBlocks
107135
for _, callee := range scope.calls {
108136
if visited[callee] || callee.callers >= commonFuncThreshold {
109137
continue
110138
}
111-
loc += ctx.collectLOC(callee, scopeFnArgs, scopeVal, visited)
139+
loc += ctx.collectLOC(iface, callee, scopeFnArgs, scopeVal, visited)
112140
}
113141
}
114142
return loc

sys/linux/auto.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ finit_module$auto(fd fd, uargs ptr[in, string], flags int32)
270270
flistxattr$auto(fd fd, list ptr[inout, string], size intptr)
271271
flock$auto(fd fd, cmd int32)
272272
fremovexattr$auto(fd fd, name ptr[in, string])
273-
fsconfig$auto(fd fd, cmd int32, _key ptr[in, string], _value ptr[in, array[auto_todo]], aux gid)
273+
fsconfig$auto(fd fd, cmd int32, _key ptr[in, string], _value ptr[in, array[auto_todo]], aux uid)
274274
fsconfig$auto_EROFS_MOUNT_DAX_ALWAYS(fd fd, cmd int32, _key ptr[in, string], _value ptr[in, array[auto_todo]], aux const[EROFS_MOUNT_DAX_ALWAYS])
275275
fsconfig$auto_EROFS_MOUNT_DAX_NEVER(fd fd, cmd int32, _key ptr[in, string], _value ptr[in, array[auto_todo]], aux const[EROFS_MOUNT_DAX_NEVER])
276276
fsconfig$auto_JFFS2_COMPR_MODE_FORCELZO(fd fd, cmd int32, _key ptr[in, string], _value ptr[in, array[auto_todo]], aux const[JFFS2_COMPR_MODE_FORCELZO])
@@ -9778,7 +9778,7 @@ xfs_growfs_log$auto {
97789778
}
97799779

97809780
xfs_growfs_rt$auto {
9781-
newblocks int64
9781+
newblocks auto_union[gid, int64]
97829782
extsize int32
97839783
}
97849784

0 commit comments

Comments
 (0)