diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2025-04-10 11:34:39 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2025-04-10 17:07:48 +0000 |
| commit | 1bc60a19f725612590947493424fef2e314bd044 (patch) | |
| tree | 3be2c55ec8612d430845327602d832d6eb01b479 /pkg/declextract/interface.go | |
| parent | 2d9fa31cf7abaddf944824814053e67b4d5c478e (diff) | |
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.
Diffstat (limited to 'pkg/declextract/interface.go')
| -rw-r--r-- | pkg/declextract/interface.go | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/pkg/declextract/interface.go b/pkg/declextract/interface.go index e7a859da9..dd5bfa1d4 100644 --- a/pkg/declextract/interface.go +++ b/pkg/declextract/interface.go @@ -6,6 +6,8 @@ package declextract import ( "slices" "strings" + + "github.com/google/syzkaller/pkg/cover" ) type Interface struct { @@ -19,6 +21,8 @@ type Interface struct { ManualDescriptions bool AutoDescriptions bool ReachableLOC int + CoveredBlocks int + TotalBlocks int scopeArg int scopeVal string @@ -41,7 +45,7 @@ func (ctx *context) noteInterface(iface *Interface) { func (ctx *context) finishInterfaces() { for _, iface := range ctx.interfaces { - iface.ReachableLOC = ctx.reachableLOC(iface.Func, iface.Files[0], iface.scopeArg, iface.scopeVal) + ctx.calculateLOC(iface) slices.Sort(iface.Files) iface.Files = slices.Compact(iface.Files) if iface.Access == "" { @@ -60,7 +64,29 @@ func (ctx *context) processFunctions() { ctx.funcs[fn.Name] = fn } } + coverBlocks := make(map[string][]*cover.Block) + for _, file := range ctx.coverage { + for _, fn := range file.Functions { + coverBlocks[file.FilePath+fn.FuncName] = fn.Blocks + } + } for _, fn := range ctx.Functions { + for _, block := range coverBlocks[fn.File+fn.Name] { + var match *FunctionScope + for _, scope := range fn.Scopes { + if scope.Arg == -1 { + match = scope + } + if block.FromLine >= scope.StartLine && block.FromLine <= scope.EndLine { + match = scope + break + } + } + match.totalBlocks++ + if block.HitCount != 0 { + match.coveredBlocks++ + } + } for _, scope := range fn.Scopes { for _, callee := range scope.Calls { called := ctx.findFunc(callee, fn.File) @@ -74,19 +100,19 @@ func (ctx *context) processFunctions() { } } -func (ctx *context) reachableLOC(name, file string, scopeArg int, scopeVal string) int { - fn := ctx.findFunc(name, file) +func (ctx *context) calculateLOC(iface *Interface) { + fn := ctx.findFunc(iface.Func, iface.Files[0]) if fn == nil { - ctx.warn("can't find function %v called in %v", name, file) - return 0 + ctx.warn("can't find function %v called in %v", iface.Func, iface.Files[0]) + return } - scopeFnArgs := ctx.inferArgFlow(fnArg{fn, scopeArg}) + scopeFnArgs := ctx.inferArgFlow(fnArg{fn, iface.scopeArg}) visited := make(map[*Function]bool) - return ctx.collectLOC(fn, scopeFnArgs, scopeVal, visited) + iface.ReachableLOC = ctx.collectLOC(iface, fn, scopeFnArgs, iface.scopeVal, visited) } -func (ctx *context) collectLOC(fn *Function, scopeFnArgs map[fnArg]bool, scopeVal string, - visited map[*Function]bool) int { +func (ctx *context) collectLOC(iface *Interface, fn *Function, scopeFnArgs map[fnArg]bool, + scopeVal string, visited map[*Function]bool) int { // Ignore very common functions when computing reachability for complexity analysis. // Counting kmalloc/printk against each caller is not useful (they have ~10K calls). // 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 loc -= max(0, scope.EndLine-scope.StartLine) continue } + iface.TotalBlocks += scope.totalBlocks + iface.CoveredBlocks += scope.coveredBlocks for _, callee := range scope.calls { if visited[callee] || callee.callers >= commonFuncThreshold { continue } - loc += ctx.collectLOC(callee, scopeFnArgs, scopeVal, visited) + loc += ctx.collectLOC(iface, callee, scopeFnArgs, scopeVal, visited) } } return loc |
