aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2025-04-03 10:27:09 +0200
committerDmitry Vyukov <dvyukov@google.com>2025-04-03 20:00:12 +0000
commit6dc47718fdbb634024bcfe47cbc4d7cc781b4cc4 (patch)
tree27df5135e412a5f1cc816d418b75e8ce4e2d4a20
parentd7ae3a111bd75df44dda69b37da945b50d5133e2 (diff)
tools/syz-declextract: allow to run on subset of arches
This may be useful for downstream kernels that only build and are supposed to be used with a subset of arches. Some esoteric arches may be broken on such kernels. Allow to ignore them.
-rw-r--r--pkg/tool/flags.go26
-rw-r--r--pkg/tool/flags_test.go39
-rw-r--r--sys/syz-extract/extract.go19
-rw-r--r--tools/syz-declextract/declextract.go24
-rw-r--r--tools/syz-declextract/declextract_test.go2
5 files changed, 86 insertions, 24 deletions
diff --git a/pkg/tool/flags.go b/pkg/tool/flags.go
index ec0d3015f..c74026540 100644
--- a/pkg/tool/flags.go
+++ b/pkg/tool/flags.go
@@ -9,9 +9,11 @@ import (
"errors"
"flag"
"fmt"
+ "sort"
"strings"
"github.com/google/syzkaller/pkg/log"
+ "github.com/google/syzkaller/sys/targets"
)
type Flag struct {
@@ -50,6 +52,30 @@ func ParseFlags(set *flag.FlagSet, args []string) error {
return nil
}
+func ParseArchList(OS, archList string) ([]string, error) {
+ allArches := targets.List[OS]
+ if allArches == nil {
+ return nil, fmt.Errorf("bad OS %q", OS)
+ }
+ archMap := make(map[string]bool)
+ if archList != "" {
+ for _, arch := range strings.Split(archList, ",") {
+ if allArches[arch] == nil {
+ return nil, fmt.Errorf("bad arch %q for OS %q in arches flag", arch, OS)
+ }
+ archMap[arch] = true
+ }
+ }
+ var arches []string
+ for arch := range allArches {
+ if len(archMap) == 0 || archMap[arch] {
+ arches = append(arches, arch)
+ }
+ }
+ sort.Strings(arches)
+ return arches, nil
+}
+
const optionalFlag = "optional"
func serializeFlags(flags []Flag) string {
diff --git a/pkg/tool/flags_test.go b/pkg/tool/flags_test.go
index 0503c48fc..df642bca6 100644
--- a/pkg/tool/flags_test.go
+++ b/pkg/tool/flags_test.go
@@ -4,6 +4,7 @@
package tool
import (
+ "errors"
"flag"
"fmt"
"io"
@@ -11,6 +12,7 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
+ "github.com/stretchr/testify/assert"
)
func TestParseFlags(t *testing.T) {
@@ -84,3 +86,40 @@ func TestCfgsFlagAlreadySet(t *testing.T) {
t.Errorf("cfgs.Set got: nil, want: error")
}
}
+
+func TestParseArchList(t *testing.T) {
+ type Test struct {
+ OS string
+ In string
+ Out []string
+ Err error
+ }
+ tests := []Test{
+ {
+ OS: "foo",
+ Err: errors.New(`bad OS "foo"`),
+ },
+ {
+ OS: "linux",
+ In: "amd64,bar",
+ Err: errors.New(`bad arch "bar" for OS "linux" in arches flag`),
+ },
+ {
+ OS: "linux",
+ In: "",
+ Out: []string{"386", "amd64", "arm", "arm64", "mips64le", "ppc64le", "riscv64", "s390x"},
+ },
+ {
+ OS: "linux",
+ In: "ppc64le,386",
+ Out: []string{"386", "ppc64le"},
+ },
+ }
+ for i, test := range tests {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ got, err := ParseArchList(test.OS, test.In)
+ assert.Equal(t, err, test.Err)
+ assert.Equal(t, got, test.Out)
+ })
+ }
+}
diff --git a/sys/syz-extract/extract.go b/sys/syz-extract/extract.go
index deaeb3f09..aa020b029 100644
--- a/sys/syz-extract/extract.go
+++ b/sys/syz-extract/extract.go
@@ -11,7 +11,6 @@ import (
"path/filepath"
"runtime"
"sort"
- "strings"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/pkg/compiler"
@@ -80,7 +79,11 @@ func main() {
if extractor == nil {
tool.Failf("unknown os: %v", OS)
}
- arches, nfiles, err := createArches(OS, archList(OS, *flagArch), flag.Args())
+ archList, err := tool.ParseArchList(OS, *flagArch)
+ if err != nil {
+ tool.Failf("failed to parse arch flag: %v", err)
+ }
+ arches, nfiles, err := createArches(OS, archList, flag.Args())
if err != nil {
tool.Fail(err)
}
@@ -242,18 +245,6 @@ func createArches(OS string, archArray, files []string) ([]*Arch, int, error) {
return arches, nfiles, nil
}
-func archList(OS, arches string) []string {
- if arches != "" {
- return strings.Split(arches, ",")
- }
- var archArray []string
- for arch := range targets.List[OS] {
- archArray = append(archArray, arch)
- }
- sort.Strings(archArray)
- return archArray
-}
-
func checkUnsupportedCalls(arches []*Arch) bool {
supported := make(map[string]bool)
unsupported := make(map[string]string)
diff --git a/tools/syz-declextract/declextract.go b/tools/syz-declextract/declextract.go
index 1f33d1d6d..50eaf4fe9 100644
--- a/tools/syz-declextract/declextract.go
+++ b/tools/syz-declextract/declextract.go
@@ -37,6 +37,7 @@ func main() {
var (
flagConfig = flag.String("config", "", "manager config file")
flagBinary = flag.String("binary", "syz-declextract", "path to syz-declextract binary")
+ flagArches = flag.String("arches", "", "comma-separated list of arches to extract (all if empty)")
)
defer tool.Init()()
cfg, err := mgrconfig.LoadFile(*flagConfig)
@@ -46,7 +47,7 @@ func main() {
loadProbeInfo := func() (*ifaceprobe.Info, error) {
return probe(cfg, *flagConfig)
}
- if _, err := run(filepath.FromSlash("sys/linux/auto.txt"), loadProbeInfo, &clangtool.Config{
+ if _, err := run(filepath.FromSlash("sys/linux/auto.txt"), loadProbeInfo, *flagArches, &clangtool.Config{
ToolBin: *flagBinary,
KernelSrc: cfg.KernelSrc,
KernelObj: cfg.KernelObj,
@@ -57,9 +58,13 @@ func main() {
}
}
-func run(autoFile string, loadProbeInfo func() (*ifaceprobe.Info, error), cfg *clangtool.Config) (
+func run(autoFile string, loadProbeInfo func() (*ifaceprobe.Info, error), archList string, cfg *clangtool.Config) (
*declextract.Result, error) {
- out, probeInfo, syscallRename, err := prepare(loadProbeInfo, cfg)
+ arches, err := tool.ParseArchList(target.OS, archList)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse arches flag: %w", err)
+ }
+ out, probeInfo, syscallRename, err := prepare(loadProbeInfo, arches, cfg)
if err != nil {
return nil, err
}
@@ -123,7 +128,7 @@ func removeUnused(desc *ast.Description, autoFile string, unusedNodes []ast.Node
})
}
-func prepare(loadProbeInfo func() (*ifaceprobe.Info, error), cfg *clangtool.Config) (
+func prepare(loadProbeInfo func() (*ifaceprobe.Info, error), arches []string, cfg *clangtool.Config) (
*declextract.Output, *ifaceprobe.Info, map[string][]string, error) {
var eg errgroup.Group
var out *declextract.Output
@@ -147,7 +152,7 @@ func prepare(loadProbeInfo func() (*ifaceprobe.Info, error), cfg *clangtool.Conf
var syscallRename map[string][]string
eg.Go(func() error {
var err error
- syscallRename, err = buildSyscallRenameMap(cfg.KernelSrc)
+ syscallRename, err = buildSyscallRenameMap(cfg.KernelSrc, arches)
if err != nil {
return fmt.Errorf("failed to build syscall rename map: %w", err)
}
@@ -234,7 +239,7 @@ func finishInterfaces(interfaces []*declextract.Interface, consts map[string]*co
}
}
-func buildSyscallRenameMap(sourceDir string) (map[string][]string, error) {
+func buildSyscallRenameMap(sourceDir string, arches []string) (map[string][]string, error) {
// Some syscalls have different names and entry points and thus need to be renamed.
// e.g. SYSCALL_DEFINE1(setuid16, old_uid_t, uid) is referred to in the .tbl file with setuid.
// Parse *.tbl files that map functions defined with SYSCALL_DEFINE macros to actual syscall names.
@@ -244,7 +249,7 @@ func buildSyscallRenameMap(sourceDir string) (map[string][]string, error) {
// and then just order arches by name to have deterministic result.
// Note: some syscalls may have no record in the tables for the architectures we support.
syscalls := make(map[string][]tblSyscall)
- tblFiles, err := findTblFiles(sourceDir)
+ tblFiles, err := findTblFiles(sourceDir, arches)
if err != nil {
return nil, err
}
@@ -320,9 +325,10 @@ func parseTblFile(data []byte, arch string, syscalls map[string][]tblSyscall) {
}
}
-func findTblFiles(sourceDir string) (map[string][]string, error) {
+func findTblFiles(sourceDir string, arches []string) (map[string][]string, error) {
files := make(map[string][]string)
- for _, arch := range targets.List[target.OS] {
+ for _, name := range arches {
+ arch := targets.List[target.OS][name]
err := filepath.WalkDir(filepath.Join(sourceDir, "arch", arch.KernelHeaderArch),
func(file string, d fs.DirEntry, err error) error {
if err == nil && strings.HasSuffix(file, ".tbl") {
diff --git a/tools/syz-declextract/declextract_test.go b/tools/syz-declextract/declextract_test.go
index 22d6dba35..29f671d17 100644
--- a/tools/syz-declextract/declextract_test.go
+++ b/tools/syz-declextract/declextract_test.go
@@ -68,7 +68,7 @@ func TestDeclextract(t *testing.T) {
return probeInfo, nil
}
autoFile := filepath.Join(cfg.KernelObj, filepath.Base(file)+".txt")
- res, err := run(autoFile, loadProbeInfo, cfg)
+ res, err := run(autoFile, loadProbeInfo, "", cfg)
if err != nil {
if *flagUpdate {
osutil.CopyFile(autoFile, file+".txt")