github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/coveragedb/functions.go (about) 1 // Copyright 2025 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package coveragedb 5 6 import ( 7 "context" 8 "fmt" 9 10 "cloud.google.com/go/spanner" 11 "github.com/google/syzkaller/pkg/coveragedb/spannerclient" 12 "google.golang.org/api/iterator" 13 ) 14 15 // FuncLines represents the 'functions' table records. 16 // It could be used to maps 'hitcounts' from 'files' table to the function names. 17 type FuncLines struct { 18 FilePath string 19 FuncName string 20 Lines []int64 // List of lines we know belong to this function name according to the addr2line output. 21 } 22 23 func MakeFuncFinder(ctx context.Context, client spannerclient.SpannerClient, ns string, timePeriod TimePeriod, 24 ) (*FunctionFinder, error) { 25 stmt := spanner.Statement{ 26 SQL: `select 27 filepath, funcname, lines 28 from merge_history 29 join functions 30 on merge_history.session = functions.session 31 where 32 merge_history.namespace=$1 and dateto=$2 and duration=$3`, 33 Params: map[string]interface{}{ 34 "p1": ns, 35 "p2": timePeriod.DateTo, 36 "p3": timePeriod.Days, 37 }, 38 } 39 iter := client.Single().Query(ctx, stmt) 40 defer iter.Stop() 41 42 ff := &FunctionFinder{} 43 for { 44 row, err := iter.Next() 45 if err == iterator.Done { 46 break 47 } 48 if err != nil { 49 return nil, fmt.Errorf("iter.Next(): %w", err) 50 } 51 var r FuncLines 52 if err = row.ToStruct(&r); err != nil { 53 return nil, fmt.Errorf("row.ToStruct(): %w", err) 54 } 55 56 for _, val := range r.Lines { 57 ff.addLine(r.FilePath, r.FuncName, int(val)) 58 } 59 } 60 return ff, nil 61 } 62 63 type FunctionFinder struct { 64 fileLineToFuncName map[string]map[int]string 65 } 66 67 func (ff *FunctionFinder) addLine(fileName, funcName string, line int) { 68 if ff.fileLineToFuncName == nil { 69 ff.fileLineToFuncName = map[string]map[int]string{} 70 } 71 if ff.fileLineToFuncName[fileName] == nil { 72 ff.fileLineToFuncName[fileName] = map[int]string{} 73 } 74 ff.fileLineToFuncName[fileName][line] = funcName 75 } 76 77 func (ff *FunctionFinder) FileLineToFuncName(filePath string, line int) (string, error) { 78 if _, ok := ff.fileLineToFuncName[filePath]; !ok { 79 return "", fmt.Errorf("file %s not found", filePath) 80 } 81 if _, ok := ff.fileLineToFuncName[filePath][line]; !ok { 82 return "", fmt.Errorf("file:line %s:%d function not found", filePath, line) 83 } 84 return ff.fileLineToFuncName[filePath][line], nil 85 }