diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2025-04-03 10:27:09 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2025-04-03 20:00:12 +0000 |
| commit | 6dc47718fdbb634024bcfe47cbc4d7cc781b4cc4 (patch) | |
| tree | 27df5135e412a5f1cc816d418b75e8ce4e2d4a20 | |
| parent | d7ae3a111bd75df44dda69b37da945b50d5133e2 (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.go | 26 | ||||
| -rw-r--r-- | pkg/tool/flags_test.go | 39 | ||||
| -rw-r--r-- | sys/syz-extract/extract.go | 19 | ||||
| -rw-r--r-- | tools/syz-declextract/declextract.go | 24 | ||||
| -rw-r--r-- | tools/syz-declextract/declextract_test.go | 2 |
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") |
