diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2021-03-17 09:51:20 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2021-03-18 09:17:51 +0100 |
| commit | 3d67c6a0759e6360bdcc0d7a8716b428354ca6bd (patch) | |
| tree | 8839f0e0a40f2442e0a7b299c5f979e3f2fc011c /pkg | |
| parent | 4fd7e7cf6192443813368e9bb984e2b517c5ac17 (diff) | |
pkg/cover: refactor module discovery interface
Make module discovery convert host.KernelModule to backend.Module.
Also error if we have modules on non-Linux
and make it possible to return errors from module discovery.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/cover/backend/backend.go | 14 | ||||
| -rw-r--r-- | pkg/cover/backend/elf.go | 14 | ||||
| -rw-r--r-- | pkg/cover/backend/gvisor.go | 7 | ||||
| -rw-r--r-- | pkg/cover/backend/modules.go | 51 | ||||
| -rw-r--r-- | pkg/cover/report.go | 20 |
5 files changed, 62 insertions, 44 deletions
diff --git a/pkg/cover/backend/backend.go b/pkg/cover/backend/backend.go index afc8b1958..afdea950a 100644 --- a/pkg/cover/backend/backend.go +++ b/pkg/cover/backend/backend.go @@ -4,6 +4,9 @@ package backend import ( + "fmt" + + "github.com/google/syzkaller/pkg/host" "github.com/google/syzkaller/sys/targets" ) @@ -59,10 +62,13 @@ type Range struct { const LineEnd = 1 << 30 -func Make(target *targets.Target, vm, srcDir, buildDir string, - moduleObj []string, modules []*Module) (*Impl, error) { +func Make(target *targets.Target, vm, objDir, srcDir, buildDir string, + moduleObj []string, modules []host.KernelModule) (*Impl, error) { + if objDir == "" { + return nil, fmt.Errorf("kernel obj directory is not specified") + } if vm == "gvisor" { - return makeGvisor(target, srcDir, buildDir, modules) + return makeGvisor(target, objDir, srcDir, buildDir, modules) } - return makeELF(target, srcDir, buildDir, moduleObj, modules) + return makeELF(target, objDir, srcDir, buildDir, moduleObj, modules) } diff --git a/pkg/cover/backend/elf.go b/pkg/cover/backend/elf.go index 8d24542c2..604ea8031 100644 --- a/pkg/cover/backend/elf.go +++ b/pkg/cover/backend/elf.go @@ -18,23 +18,25 @@ import ( "strings" "unsafe" + "github.com/google/syzkaller/pkg/host" "github.com/google/syzkaller/pkg/log" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/symbolizer" "github.com/google/syzkaller/sys/targets" ) -func makeELF(target *targets.Target, srcDir, buildDir string, - moduleObj []string, modules []*Module) (*Impl, error) { +func makeELF(target *targets.Target, objDir, srcDir, buildDir string, + moduleObj []string, hostModules []host.KernelModule) (*Impl, error) { + modules, err := discoverModules(target, objDir, moduleObj, hostModules) + if err != nil { + return nil, err + } // Here and below index 0 refers to coverage callbacks (__sanitizer_cov_trace_pc) // and index 1 refers to comparison callbacks (__sanitizer_cov_trace_cmp*). var allCoverPoints [2][]uint64 var allSymbols []*Symbol var allRanges []pcRange var allUnits []*CompileUnit - if target.OS == targets.Linux { - getModules(moduleObj, modules) - } var pcBase uint64 for _, module := range modules { if module.Path == "" { @@ -108,7 +110,7 @@ func makeELF(target *targets.Target, srcDir, buildDir string, if len(unit.PCs) == 0 { continue // drop the unit } - objDir := filepath.Dir(modules[0].Path) // TODO: won't work for out-of-tree modules + // TODO: objDir won't work for out-of-tree modules. unit.Name, unit.Path = cleanPath(unit.Name, objDir, srcDir, buildDir) allUnits[nunit] = unit nunit++ diff --git a/pkg/cover/backend/gvisor.go b/pkg/cover/backend/gvisor.go index 22f07a88b..3bb8e67ef 100644 --- a/pkg/cover/backend/gvisor.go +++ b/pkg/cover/backend/gvisor.go @@ -10,15 +10,16 @@ import ( "regexp" "strconv" + "github.com/google/syzkaller/pkg/host" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/sys/targets" ) -func makeGvisor(target *targets.Target, srcDir, buildDir string, modules []*Module) (*Impl, error) { - if len(modules) != 1 { +func makeGvisor(target *targets.Target, objDir, srcDir, buildDir string, modules []host.KernelModule) (*Impl, error) { + if len(modules) != 0 { return nil, fmt.Errorf("gvisor coverage does not support modules") } - bin := modules[0].Path + bin := filepath.Join(objDir, target.KernelObject) // pkg/build stores runsc as 'vmlinux' (we pretent to be linux), but a local build will have it as 'runsc'. if !osutil.IsExist(bin) { bin = filepath.Join(filepath.Dir(bin), "runsc") diff --git a/pkg/cover/backend/modules.go b/pkg/cover/backend/modules.go index c7a75ed22..41b61de23 100644 --- a/pkg/cover/backend/modules.go +++ b/pkg/cover/backend/modules.go @@ -11,22 +11,44 @@ import ( "path/filepath" "strings" + "github.com/google/syzkaller/pkg/host" "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/sys/targets" ) -func getModules(dirs []string, modules []*Module) { - byName := make(map[string]*Module) - for _, mod := range modules { +func discoverModules(target *targets.Target, objDir string, moduleObj []string, hostModules []host.KernelModule) ( + []*Module, error) { + modules := []*Module{ + {Path: filepath.Join(objDir, target.KernelObject)}, + } + if target.OS == targets.Linux { + modules1, err := discoverModulesLinux(append([]string{objDir}, moduleObj...), hostModules) + if err != nil { + return nil, err + } + modules = append(modules, modules1...) + } else if len(hostModules) != 0 { + return nil, fmt.Errorf("%v coverage does not support modules", target.OS) + } + return modules, nil +} + +func discoverModulesLinux(dirs []string, hostModules []host.KernelModule) ([]*Module, error) { + byName := make(map[string]host.KernelModule) + for _, mod := range hostModules { byName[mod.Name] = mod } + var modules []*Module files := findModulePaths(dirs) for _, path := range files { name := strings.TrimSuffix(filepath.Base(path), ".ko") - if module := byName[name]; module != nil { - if module.Path != "" { - continue - } - module.Path = path + if mod, ok := byName[name]; ok { + delete(byName, name) + modules = append(modules, &Module{ + Name: mod.Name, + Addr: mod.Addr, + Path: path, + }) continue } name, err := getModuleName(path) @@ -37,14 +59,17 @@ func getModules(dirs []string, modules []*Module) { if name == "" { continue } - if module := byName[name]; module != nil { - if module.Path != "" { - continue - } - module.Path = path + if mod, ok := byName[name]; ok { + delete(byName, name) + modules = append(modules, &Module{ + Name: mod.Name, + Addr: mod.Addr, + Path: path, + }) } } log.Logf(0, "kernel modules: %v", modules) + return modules, nil } func findModulePaths(dirs []string) []string { diff --git a/pkg/cover/report.go b/pkg/cover/report.go index b622af4a4..8f805fe10 100644 --- a/pkg/cover/report.go +++ b/pkg/cover/report.go @@ -5,7 +5,6 @@ package cover import ( "fmt" - "path/filepath" "sort" "github.com/google/syzkaller/pkg/cover/backend" @@ -30,23 +29,8 @@ type Prog struct { var RestorePC = backend.RestorePC func MakeReportGenerator(target *targets.Target, vm, objDir, srcDir, buildDir string, subsystem []mgrconfig.Subsystem, - moduleObj []string, hostModules []host.KernelModule) (*ReportGenerator, error) { - if objDir == "" { - return nil, fmt.Errorf("kernel obj directory is not specified") - } - moduleObj = append([]string{objDir}, moduleObj...) - modules := []*backend.Module{ - { - Path: filepath.Join(objDir, target.KernelObject), - }, - } - for _, mod := range hostModules { - modules = append(modules, &backend.Module{ - Name: mod.Name, - Addr: mod.Addr, - }) - } - impl, err := backend.Make(target, vm, srcDir, buildDir, moduleObj, modules) + moduleObj []string, modules []host.KernelModule) (*ReportGenerator, error) { + impl, err := backend.Make(target, vm, objDir, srcDir, buildDir, moduleObj, modules) if err != nil { return nil, err } |
