@@ -6,6 +6,8 @@ package declextract
66import (
77 "slices"
88 "strings"
9+
10+ "github.com/google/syzkaller/pkg/cover"
911)
1012
1113type 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
4246func (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
0 commit comments