aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-14 11:47:11 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-15 16:02:37 +0200
commit487aa0d5371e9b020c69d2f9e4a955ed8e5b2555 (patch)
treed930a1e07640a88a9c42a3bd85cc3f2f93a3a2aa /sys
parent91def5c506951f8a55f31979ce54657de460f528 (diff)
sys: consolidate info about various targets
Info about targets (like C arch/CFLAGS) is required in multiple places: extract.sh syz-extract syz-sysgen csource vm/qemu ... Consolidate it in one place and use that in syz-sysgen.
Diffstat (limited to 'sys')
-rw-r--r--sys/sys.go55
-rw-r--r--sys/syz-extract/extract.go13
-rw-r--r--sys/syz-sysgen/syscallnr.go95
-rw-r--r--sys/syz-sysgen/sysgen.go214
4 files changed, 207 insertions, 170 deletions
diff --git a/sys/sys.go b/sys/sys.go
index f41d68dbc..d5ddd6028 100644
--- a/sys/sys.go
+++ b/sys/sys.go
@@ -6,3 +6,58 @@ package sys
import (
_ "github.com/google/syzkaller/sys/linux"
)
+
+type Target struct {
+ PtrSize uint64
+ CArch []string
+ CFlags []string
+ CCompiler string
+ KernelArch string
+ KernelHeaderArch string
+ KernelCrossCompile string
+}
+
+var Targets = map[string]map[string]*Target{
+ "linux": map[string]*Target{
+ "amd64": {
+ PtrSize: 8,
+ CArch: []string{"__x86_64__"},
+ CFlags: []string{"-m64"},
+ CCompiler: "x86_64-linux-gnu-",
+ KernelArch: "x86_64",
+ KernelHeaderArch: "x86",
+ },
+ "386": {
+ PtrSize: 4,
+ CArch: []string{"__i386__"},
+ CFlags: []string{"-m32"},
+ CCompiler: "x86_64-linux-gnu-",
+ KernelArch: "i386",
+ KernelHeaderArch: "x86",
+ },
+ "arm64": {
+ PtrSize: 8,
+ CArch: []string{"__aarch64__"},
+ CFlags: []string{},
+ CCompiler: "aarch64-linux-gnu-",
+ KernelArch: "arm64",
+ KernelHeaderArch: "arm64",
+ },
+ "arm": {
+ PtrSize: 4,
+ CArch: []string{"__arm__"},
+ CFlags: []string{"-D__LINUX_ARM_ARCH__=6", "-march=armv6t2", "-m32"},
+ CCompiler: "arm-linux-gnueabihf-",
+ KernelArch: "arm",
+ KernelHeaderArch: "arm",
+ },
+ "ppc64le": {
+ PtrSize: 8,
+ CArch: []string{"__ppc64__", "__PPC64__", "__powerpc64__"},
+ CFlags: []string{"-D__powerpc64__"},
+ CCompiler: "powerpc64le-linux-gnu-",
+ KernelArch: "powerpc",
+ KernelHeaderArch: "powerpc",
+ },
+ },
+}
diff --git a/sys/syz-extract/extract.go b/sys/syz-extract/extract.go
index 2da6a3f72..781f445d2 100644
--- a/sys/syz-extract/extract.go
+++ b/sys/syz-extract/extract.go
@@ -28,16 +28,15 @@ var (
type Arch struct {
CARCH []string
KernelHeaderArch string
- KernelInclude string
CFlags []string
}
var archs = map[string]*Arch{
- "amd64": {[]string{"__x86_64__"}, "x86", "asm/unistd.h", []string{"-m64"}},
- "386": {[]string{"__i386__"}, "x86", "asm/unistd.h", []string{"-m32"}},
- "arm64": {[]string{"__aarch64__"}, "arm64", "asm/unistd.h", []string{}},
- "arm": {[]string{"__arm__"}, "arm", "asm/unistd.h", []string{"-D__LINUX_ARM_ARCH__=6", "-m32"}},
- "ppc64le": {[]string{"__ppc64__", "__PPC64__", "__powerpc64__"}, "powerpc", "asm/unistd.h", []string{"-D__powerpc64__"}},
+ "amd64": {[]string{"__x86_64__"}, "x86", []string{"-m64"}},
+ "386": {[]string{"__i386__"}, "x86", []string{"-m32"}},
+ "arm64": {[]string{"__aarch64__"}, "arm64", []string{}},
+ "arm": {[]string{"__arm__"}, "arm", []string{"-D__LINUX_ARM_ARCH__=6", "-m32"}},
+ "ppc64le": {[]string{"__ppc64__", "__PPC64__", "__powerpc64__"}, "powerpc", []string{"-D__powerpc64__"}},
}
type File struct {
@@ -123,7 +122,7 @@ func processFile(inname string) (map[string]bool, error) {
return nil, nil
}
arch := archs[*flagArch]
- includes := append(info.Includes, arch.KernelInclude)
+ includes := append(info.Includes, "asm/unistd.h")
consts, undeclared, err := fetchValues(arch.KernelHeaderArch, info.Consts,
includes, info.Incdirs, arch.CFlags, info.Defines)
if err != nil {
diff --git a/sys/syz-sysgen/syscallnr.go b/sys/syz-sysgen/syscallnr.go
deleted file mode 100644
index da427a553..000000000
--- a/sys/syz-sysgen/syscallnr.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package main
-
-import (
- "bytes"
- "sort"
- "strings"
- "text/template"
-
- "github.com/google/syzkaller/prog"
-)
-
-type Arch struct {
- Name string
- PtrSize uint64
- CARCH []string
-}
-
-var archs = []*Arch{
- {"amd64", 8, []string{"__x86_64__"}},
- {"386", 4, []string{"__i386__"}},
- {"arm64", 8, []string{"__aarch64__"}},
- {"arm", 4, []string{"__arm__"}},
- {"ppc64le", 8, []string{"__ppc64__", "__PPC64__", "__powerpc64__"}},
-}
-
-func generateExecutorSyscalls(arch *Arch, syscalls []*prog.Syscall) []byte {
- data := ArchData{
- CARCH: arch.CARCH,
- }
- fake := make(map[string]uint64)
- for _, c := range syscalls {
- data.Calls = append(data.Calls, SyscallData{c.Name, int32(c.NR)})
- if strings.HasPrefix(c.CallName, "syz_") {
- fake[c.CallName] = c.NR
- }
- }
- for name, nr := range fake {
- data.Fake = append(data.Fake, SyscallData{name, int32(nr)})
- }
- sort.Sort(SyscallArray(data.Calls))
- sort.Sort(SyscallArray(data.Fake))
- buf := new(bytes.Buffer)
- if err := archTempl.Execute(buf, data); err != nil {
- failf("failed to execute arch template: %v", err)
- }
- return buf.Bytes()
-}
-
-func writeExecutorSyscalls(archs [][]byte) {
- buf := new(bytes.Buffer)
- buf.WriteString(syscallsTempl)
- for _, arch := range archs {
- buf.Write(arch)
- }
- writeFile("executor/syscalls.h", buf.Bytes())
-}
-
-type ArchData struct {
- CARCH []string
- Calls []SyscallData
- Fake []SyscallData
-}
-
-type SyscallData struct {
- Name string
- NR int32
-}
-
-type SyscallArray []SyscallData
-
-func (a SyscallArray) Len() int { return len(a) }
-func (a SyscallArray) Less(i, j int) bool { return a[i].Name < a[j].Name }
-func (a SyscallArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-
-var syscallsTempl = `// AUTOGENERATED FILE
-
-struct call_t {
- const char* name;
- int sys_nr;
-};
-`
-
-var archTempl = template.Must(template.New("").Parse(`
-#if {{range $cdef := $.CARCH}}defined({{$cdef}}) || {{end}}0
-{{range $c := $.Fake}}#define __NR_{{$c.Name}} {{$c.NR}}
-{{end}}
-static call_t syscalls[] = {
-{{range $c := $.Calls}} {"{{$c.Name}}", {{$c.NR}}},
-{{end}}
-};
-#endif
-`))
diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go
index a7b202715..920547297 100644
--- a/sys/syz-sysgen/sysgen.go
+++ b/sys/syz-sysgen/sysgen.go
@@ -15,12 +15,15 @@ import (
"runtime"
"runtime/pprof"
"sort"
+ "strings"
"sync"
+ "text/template"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/pkg/compiler"
"github.com/google/syzkaller/pkg/serializer"
"github.com/google/syzkaller/prog"
+ "github.com/google/syzkaller/sys"
)
var (
@@ -31,75 +34,86 @@ var (
func main() {
flag.Parse()
- top := ast.ParseGlob(filepath.Join("sys", "linux", "*\\.txt"), nil)
- if top == nil {
- os.Exit(1)
- }
+ for OS, archs := range sys.Targets {
+ top := ast.ParseGlob(filepath.Join("sys", OS, "*\\.txt"), nil)
+ if top == nil {
+ os.Exit(1)
+ }
- type Result struct {
- OK bool
- Errors []string
- Unsupported map[string]bool
- ArchData []byte
- }
- results := make([]Result, len(archs))
- var wg sync.WaitGroup
- wg.Add(len(archs))
-
- for i, arch := range archs {
- arch := arch
- res := &results[i]
- go func() {
- defer wg.Done()
- eh := func(pos ast.Pos, msg string) {
- res.Errors = append(res.Errors, fmt.Sprintf("%v: %v\n", pos, msg))
- }
- consts := compiler.DeserializeConstsGlob(filepath.Join("sys", "linux", "*_"+arch.Name+"\\.const"), eh)
- if consts == nil {
- return
- }
- prog := compiler.Compile(top, consts, arch.PtrSize, eh)
- if prog == nil {
- return
- }
- res.Unsupported = prog.Unsupported
+ type Job struct {
+ Arch string
+ Target *sys.Target
+ OK bool
+ Errors []string
+ Unsupported map[string]bool
+ ArchData []byte
+ }
+ var jobs []*Job
+ for arch, target := range archs {
+ jobs = append(jobs, &Job{
+ Arch: arch,
+ Target: target,
+ })
+ }
+ sort.Slice(jobs, func(i, j int) bool {
+ return jobs[i].Arch < jobs[j].Arch
+ })
+ var wg sync.WaitGroup
+ wg.Add(len(jobs))
- sysFile := filepath.Join("sys", "linux", arch.Name+".go")
- out := new(bytes.Buffer)
- generate(arch, prog, consts, out)
- writeSource(sysFile, out.Bytes())
+ for _, job := range jobs {
+ job := job
+ go func() {
+ defer wg.Done()
+ eh := func(pos ast.Pos, msg string) {
+ job.Errors = append(job.Errors, fmt.Sprintf("%v: %v\n", pos, msg))
+ }
+ consts := compiler.DeserializeConstsGlob(filepath.Join("sys", OS, "*_"+job.Arch+"\\.const"), eh)
+ if consts == nil {
+ return
+ }
+ prog := compiler.Compile(top, consts, job.Target.PtrSize, eh)
+ if prog == nil {
+ return
+ }
+ job.Unsupported = prog.Unsupported
- res.ArchData = generateExecutorSyscalls(arch, prog.Syscalls)
- res.OK = true
- }()
- }
- wg.Wait()
-
- var syscallArchs [][]byte
- unsupported := make(map[string]int)
- for i, arch := range archs {
- res := &results[i]
- fmt.Printf("generating %v...\n", arch.Name)
- for _, msg := range res.Errors {
- fmt.Print(msg)
- }
- if !res.OK {
- os.Exit(1)
+ sysFile := filepath.Join("sys", OS, job.Arch+".go")
+ out := new(bytes.Buffer)
+ generate(OS, job.Arch, job.Target, prog, consts, out)
+ writeSource(sysFile, out.Bytes())
+
+ job.ArchData = generateExecutorSyscalls(job.Target, prog.Syscalls)
+ job.OK = true
+ }()
}
- syscallArchs = append(syscallArchs, res.ArchData)
- for u := range res.Unsupported {
- unsupported[u]++
+ wg.Wait()
+
+ var syscallArchs [][]byte
+ unsupported := make(map[string]int)
+ for _, job := range jobs {
+ fmt.Printf("generating %v/%v...\n", OS, job.Arch)
+ for _, msg := range job.Errors {
+ fmt.Print(msg)
+ }
+ if !job.OK {
+ os.Exit(1)
+ }
+ syscallArchs = append(syscallArchs, job.ArchData)
+ for u := range job.Unsupported {
+ unsupported[u]++
+ }
+ fmt.Printf("\n")
}
- fmt.Printf("\n")
- }
- for what, count := range unsupported {
- if count == len(archs) {
- failf("%v is unsupported on all arches (typo?)", what)
+ for what, count := range unsupported {
+ if count == len(jobs) {
+ failf("%v is unsupported on all arches (typo?)", what)
+ }
}
- }
- writeExecutorSyscalls(syscallArchs)
+ writeExecutorSyscalls(syscallArchs)
+ }
if *flagMemProfile != "" {
f, err := os.Create(*flagMemProfile)
@@ -114,25 +128,25 @@ func main() {
}
}
-func generate(arch *Arch, prg *compiler.Prog, consts map[string]uint64, out io.Writer) {
+func generate(OS, arch string, target *sys.Target, prg *compiler.Prog, consts map[string]uint64, out io.Writer) {
fmt.Fprintf(out, "// AUTOGENERATED FILE\n")
- fmt.Fprintf(out, "package linux\n\n")
+ fmt.Fprintf(out, "package %v\n\n", OS)
fmt.Fprintf(out, "import . \"github.com/google/syzkaller/prog\"\n\n")
fmt.Fprintf(out, "func init() {\n")
fmt.Fprintf(out, "\tinitArch(syscalls_%v, resources_%v, structDescs_%v, consts_%v, %q, %v)\n",
- arch.Name, arch.Name, arch.Name, arch.Name, arch.Name, arch.PtrSize)
+ arch, arch, arch, arch, arch, target.PtrSize)
fmt.Fprintf(out, "}\n\n")
- fmt.Fprintf(out, "var resources_%v = ", arch.Name)
+ fmt.Fprintf(out, "var resources_%v = ", arch)
serializer.Write(out, prg.Resources)
fmt.Fprintf(out, "\n\n")
- fmt.Fprintf(out, "var structDescs_%v = ", arch.Name)
+ fmt.Fprintf(out, "var structDescs_%v = ", arch)
serializer.Write(out, prg.StructDescs)
fmt.Fprintf(out, "\n\n")
- fmt.Fprintf(out, "var syscalls_%v = ", arch.Name)
+ fmt.Fprintf(out, "var syscalls_%v = ", arch)
serializer.Write(out, prg.Syscalls)
fmt.Fprintf(out, "\n\n")
@@ -143,11 +157,56 @@ func generate(arch *Arch, prg *compiler.Prog, consts map[string]uint64, out io.W
sort.Slice(constArr, func(i, j int) bool {
return constArr[i].Name < constArr[j].Name
})
- fmt.Fprintf(out, "var consts_%v = ", arch.Name)
+ fmt.Fprintf(out, "var consts_%v = ", arch)
serializer.Write(out, constArr)
fmt.Fprintf(out, "\n")
}
+func generateExecutorSyscalls(target *sys.Target, syscalls []*prog.Syscall) []byte {
+ type SyscallData struct {
+ Name string
+ NR int32
+ }
+ type ArchData struct {
+ CARCH []string
+ Calls []SyscallData
+ Fake []SyscallData
+ }
+ data := ArchData{
+ CARCH: target.CArch,
+ }
+ fake := make(map[string]uint64)
+ for _, c := range syscalls {
+ data.Calls = append(data.Calls, SyscallData{c.Name, int32(c.NR)})
+ if strings.HasPrefix(c.CallName, "syz_") {
+ fake[c.CallName] = c.NR
+ }
+ }
+ for name, nr := range fake {
+ data.Fake = append(data.Fake, SyscallData{name, int32(nr)})
+ }
+ sort.Slice(data.Calls, func(i, j int) bool {
+ return data.Calls[i].Name < data.Calls[j].Name
+ })
+ sort.Slice(data.Fake, func(i, j int) bool {
+ return data.Fake[i].Name < data.Fake[j].Name
+ })
+ buf := new(bytes.Buffer)
+ if err := archTempl.Execute(buf, data); err != nil {
+ failf("failed to execute arch template: %v", err)
+ }
+ return buf.Bytes()
+}
+
+func writeExecutorSyscalls(archs [][]byte) {
+ buf := new(bytes.Buffer)
+ buf.WriteString(syscallsTempl)
+ for _, arch := range archs {
+ buf.Write(arch)
+ }
+ writeFile("executor/syscalls.h", buf.Bytes())
+}
+
func writeSource(file string, data []byte) {
src, err := format.Source(data)
if err != nil {
@@ -179,3 +238,22 @@ func logf(v int, msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, msg+"\n", args...)
}
}
+
+var syscallsTempl = `// AUTOGENERATED FILE
+
+struct call_t {
+ const char* name;
+ int sys_nr;
+};
+`
+
+var archTempl = template.Must(template.New("").Parse(`
+#if {{range $cdef := $.CARCH}}defined({{$cdef}}) || {{end}}0
+{{range $c := $.Fake}}#define __NR_{{$c.Name}} {{$c.NR}}
+{{end}}
+static call_t syscalls[] = {
+{{range $c := $.Calls}} {"{{$c.Name}}", {{$c.NR}}},
+{{end}}
+};
+#endif
+`))