aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2021-03-17 09:51:20 +0100
committerDmitry Vyukov <dvyukov@google.com>2021-03-18 09:17:51 +0100
commit3d67c6a0759e6360bdcc0d7a8716b428354ca6bd (patch)
tree8839f0e0a40f2442e0a7b299c5f979e3f2fc011c /pkg
parent4fd7e7cf6192443813368e9bb984e2b517c5ac17 (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.go14
-rw-r--r--pkg/cover/backend/elf.go14
-rw-r--r--pkg/cover/backend/gvisor.go7
-rw-r--r--pkg/cover/backend/modules.go51
-rw-r--r--pkg/cover/report.go20
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
}