diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-09-14 11:47:11 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 16:02:37 +0200 |
| commit | 487aa0d5371e9b020c69d2f9e4a955ed8e5b2555 (patch) | |
| tree | d930a1e07640a88a9c42a3bd85cc3f2f93a3a2aa /sys | |
| parent | 91def5c506951f8a55f31979ce54657de460f528 (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.go | 55 | ||||
| -rw-r--r-- | sys/syz-extract/extract.go | 13 | ||||
| -rw-r--r-- | sys/syz-sysgen/syscallnr.go | 95 | ||||
| -rw-r--r-- | sys/syz-sysgen/sysgen.go | 214 |
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 +`)) |
