aboutsummaryrefslogtreecommitdiffstats
path: root/sys/syz-sysgen
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-08-26 21:36:08 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-08-27 11:51:40 +0200
commita3857c4e90fa4a3fbe78bd4b53cdc77aa91533cf (patch)
tree8bc28379a29112de7bc11c57f3d91d0baba84594 /sys/syz-sysgen
parent9ec49e082f811482ecdccc837c27961d68247d25 (diff)
pkg/compiler, sys/syz-sysgen: move const handling to pkg/compiler
Now pkg/compiler deals with consts.
Diffstat (limited to 'sys/syz-sysgen')
-rw-r--r--sys/syz-sysgen/syscallnr.go49
-rw-r--r--sys/syz-sysgen/sysgen.go210
2 files changed, 95 insertions, 164 deletions
diff --git a/sys/syz-sysgen/syscallnr.go b/sys/syz-sysgen/syscallnr.go
index d3138bc32..8a04719b3 100644
--- a/sys/syz-sysgen/syscallnr.go
+++ b/sys/syz-sysgen/syscallnr.go
@@ -33,21 +33,27 @@ var syzkalls = map[string]uint64{
"syz_extract_tcp_res": 1000008,
}
-func generateExecutorSyscalls(syscalls []Syscall, consts map[string]map[string]uint64) {
- var data SyscallsData
- for _, arch := range archs {
- var calls []SyscallData
- for _, c := range syscalls {
- syscallNR := -1
- if nr, ok := consts[arch.Name]["__NR_"+c.CallName]; ok {
- syscallNR = int(nr)
- }
- calls = append(calls, SyscallData{c.Name, syscallNR})
- }
- data.Archs = append(data.Archs, ArchData{arch.CARCH, calls})
+func generateExecutorSyscalls(arch *Arch, syscalls []Syscall) []byte {
+ data := ArchData{
+ CARCH: arch.CARCH,
+ }
+ for _, c := range syscalls {
+ data.Calls = append(data.Calls, SyscallData{c.Name, c.NR})
+ }
+ sort.Sort(SyscallArray(data.Calls))
+ 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) {
+ data := SyscallsData{
+ Archs: archs,
}
for name, nr := range syzkalls {
- data.FakeCalls = append(data.FakeCalls, SyscallData{name, int(nr)})
+ data.FakeCalls = append(data.FakeCalls, SyscallData{name, nr})
}
sort.Sort(SyscallArray(data.FakeCalls))
@@ -61,8 +67,8 @@ func generateExecutorSyscalls(syscalls []Syscall, consts map[string]map[string]u
}
type SyscallsData struct {
- Archs []ArchData
FakeCalls []SyscallData
+ Archs [][]byte
}
type ArchData struct {
@@ -72,7 +78,7 @@ type ArchData struct {
type SyscallData struct {
Name string
- NR int
+ NR uint64
}
type SyscallArray []SyscallData
@@ -93,11 +99,14 @@ struct call_t {
};
{{range $arch := $.Archs}}
-#if {{range $cdef := $arch.CARCH}}defined({{$cdef}}) || {{end}}0
+{{printf "%s" $arch}}
+{{end}}
+`))
+
+var archTempl = template.Must(template.New("").Parse(
+ `#if {{range $cdef := $.CARCH}}defined({{$cdef}}) || {{end}}0
static call_t syscalls[] = {
-{{range $c := $arch.Calls}} {"{{$c.Name}}", {{$c.NR}}},
+{{range $c := $.Calls}} {"{{$c.Name}}", {{$c.NR}}},
{{end}}
};
-#endif
-{{end}}
-`))
+#endif`))
diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go
index 623667daa..a197dffee 100644
--- a/sys/syz-sysgen/sysgen.go
+++ b/sys/syz-sysgen/sysgen.go
@@ -21,6 +21,7 @@ import (
"strings"
"github.com/google/syzkaller/pkg/ast"
+ "github.com/google/syzkaller/pkg/compiler"
)
var (
@@ -37,57 +38,44 @@ const (
func main() {
flag.Parse()
- top, ok := ast.ParseGlob("sys/*\\.txt", nil)
- if !ok {
+ top := ast.ParseGlob("sys/*\\.txt", nil)
+ if top == nil {
os.Exit(1)
}
- desc := astToDesc(top)
- unsupportedFlags := make(map[string]int)
- consts := make(map[string]map[string]uint64)
+ var syscallArchs [][]byte
+ unsupported := make(map[string]int)
for _, arch := range archs {
logf(0, "generating %v...", arch.Name)
- consts[arch.Name] = readConsts(arch.Name)
-
- unsupported := make(map[string]bool)
- archFlags := make(map[string][]string)
- for f, vals := range desc.Flags {
- var archVals []string
- for _, val := range vals {
- if isIdentifier(val) {
- if v, ok := consts[arch.Name][val]; ok {
- archVals = append(archVals, fmt.Sprint(v))
- } else {
- if !unsupported[val] {
- unsupported[val] = true
- unsupportedFlags[val]++
- logf(0, "unsupported flag: %v", val)
- }
- }
- } else {
- archVals = append(archVals, val)
- }
- }
- archFlags[f] = archVals
+ consts := readConsts(arch.Name)
+
+ prog := compiler.Compile(top, consts, nil)
+ if prog == nil {
+ os.Exit(1)
+ }
+ for u := range prog.Unsupported {
+ unsupported[u]++
}
+ desc := astToDesc(prog.Desc)
sysFile := filepath.Join("sys", "sys_"+arch.Name+".go")
logf(1, "Generate code to init system call data in %v", sysFile)
out := new(bytes.Buffer)
- archDesc := *desc
- archDesc.Flags = archFlags
- generate(arch.Name, &archDesc, consts[arch.Name], out)
+ generate(arch.Name, desc, consts, out)
writeSource(sysFile, out.Bytes())
logf(0, "")
+
+ archData := generateExecutorSyscalls(arch, desc.Syscalls)
+ syscallArchs = append(syscallArchs, archData)
}
- for flag, count := range unsupportedFlags {
+ for what, count := range unsupported {
if count == len(archs) {
- failf("flag %v is unsupported on all arches (typo?)", flag)
+ failf("%v is unsupported on all arches (typo?)", what)
}
}
- generateExecutorSyscalls(desc.Syscalls, consts)
+ writeExecutorSyscalls(syscallArchs)
if *flagMemProfile != "" {
f, err := os.Create(*flagMemProfile)
@@ -114,6 +102,7 @@ type Description struct {
type Syscall struct {
Name string
CallName string
+ NR uint64
Args [][]string
Ret []string
}
@@ -139,7 +128,7 @@ 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] }
-func astToDesc(top []interface{}) *Description {
+func astToDesc(top *ast.Description) *Description {
// As a temporal measure we just convert the new representation to the old one.
// TODO: check for duplicate defines, structs, resources.
// TODO: check for duplicate syscall argument names.
@@ -151,20 +140,15 @@ func astToDesc(top []interface{}) *Description {
Resources: make(map[string]Resource),
}
unnamedSeq := 0
- for _, decl := range top {
+ for _, decl := range top.Nodes {
switch n := decl.(type) {
case *ast.Resource:
var vals []string
for _, v := range n.Values {
- switch {
- case v.Ident != "":
- vals = append(vals, v.Ident)
- default:
- if v.ValueHex {
- vals = append(vals, fmt.Sprintf("0x%x", uintptr(v.Value)))
- } else {
- vals = append(vals, fmt.Sprint(uintptr(v.Value)))
- }
+ if v.ValueHex {
+ vals = append(vals, fmt.Sprintf("0x%x", uintptr(v.Value)))
+ } else {
+ vals = append(vals, fmt.Sprint(uintptr(v.Value)))
}
}
desc.Resources[n.Name.Name] = Resource{
@@ -176,6 +160,7 @@ func astToDesc(top []interface{}) *Description {
call := Syscall{
Name: n.Name.Name,
CallName: n.CallName,
+ NR: n.NR,
}
for _, a := range n.Args {
call.Args = append(call.Args, astToDescField(a, desc.Unnamed, &unnamedSeq))
@@ -239,15 +224,10 @@ func astToDesc(top []interface{}) *Description {
case *ast.IntFlags:
var vals []string
for _, v := range n.Values {
- switch {
- case v.Ident != "":
- vals = append(vals, v.Ident)
- default:
- if v.ValueHex {
- vals = append(vals, fmt.Sprintf("0x%x", uintptr(v.Value)))
- } else {
- vals = append(vals, fmt.Sprint(uintptr(v.Value)))
- }
+ if v.ValueHex {
+ vals = append(vals, fmt.Sprintf("0x%x", uintptr(v.Value)))
+ } else {
+ vals = append(vals, fmt.Sprint(uintptr(v.Value)))
}
}
desc.Flags[n.Name.Name] = vals
@@ -350,36 +330,16 @@ func readConsts(arch string) map[string]uint64 {
return consts
}
-var skipCurrentSyscall string
-
-func skipSyscall(why string) {
- if skipCurrentSyscall != "" {
- skipCurrentSyscall = why
- }
-}
-
func generate(arch string, desc *Description, consts map[string]uint64, out io.Writer) {
- unsupported := make(map[string]bool)
-
fmt.Fprintf(out, "// AUTOGENERATED FILE\n")
fmt.Fprintf(out, "package sys\n\n")
- generateResources(desc, consts, out)
- generateStructs(desc, consts, out)
+ generateResources(desc, out)
+ generateStructs(desc, out)
fmt.Fprintf(out, "var Calls = []*Call{\n")
for _, s := range desc.Syscalls {
logf(4, " generate population code for %v", s.Name)
- skipCurrentSyscall = ""
- syscallNR := -1
- if nr, ok := consts["__NR_"+s.CallName]; ok {
- syscallNR = int(nr)
- } else {
- if !unsupported[s.CallName] {
- unsupported[s.CallName] = true
- logf(0, "unsupported syscall: %v", s.CallName)
- }
- }
native := true
if _, ok := syzkalls[s.CallName]; ok {
native = false
@@ -387,7 +347,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W
fmt.Fprintf(out, "&Call{Name: \"%v\", CallName: \"%v\", Native: %v", s.Name, s.CallName, native)
if len(s.Ret) != 0 {
fmt.Fprintf(out, ", Ret: ")
- generateArg("", "ret", s.Ret[0], "out", s.Ret[1:], desc, consts, true, false, out)
+ generateArg("", "ret", s.Ret[0], "out", s.Ret[1:], desc, true, false, out)
}
fmt.Fprintf(out, ", Args: []Type{")
for i, a := range s.Args {
@@ -395,13 +355,9 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W
fmt.Fprintf(out, ", ")
}
logf(5, " generate description for arg %v", i)
- generateArg("", a[0], a[1], "in", a[2:], desc, consts, true, false, out)
- }
- if skipCurrentSyscall != "" {
- logf(0, "unsupported syscall: %v due to %v", s.Name, skipCurrentSyscall)
- syscallNR = -1
+ generateArg("", a[0], a[1], "in", a[2:], desc, true, false, out)
}
- fmt.Fprintf(out, "}, NR: %v},\n", syscallNR)
+ fmt.Fprintf(out, "}, NR: %v},\n", s.NR)
}
fmt.Fprintf(out, "}\n\n")
@@ -418,7 +374,7 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W
fmt.Fprintf(out, ")\n")
}
-func generateResources(desc *Description, consts map[string]uint64, out io.Writer) {
+func generateResources(desc *Description, out io.Writer) {
var resArray ResourceArray
for _, res := range desc.Resources {
resArray = append(resArray, res)
@@ -433,15 +389,7 @@ func generateResources(desc *Description, consts map[string]uint64, out io.Write
var values []string
loop:
for {
- var values1 []string
- for _, v := range res.Values {
- if v1, ok := consts[v]; ok {
- values1 = append(values1, fmt.Sprint(v1))
- } else if !isIdentifier(v) {
- values1 = append(values1, v)
- }
- }
- values = append(values1, values...)
+ values = append(append([]string{}, res.Values...), values...)
switch res.Base {
case "int8", "int16", "int32", "int64", "intptr":
underlying = res.Base
@@ -455,7 +403,7 @@ func generateResources(desc *Description, consts map[string]uint64, out io.Write
}
}
fmt.Fprintf(out, "&ResourceDesc{Name: \"%v\", Type: ", name)
- generateArg("", "resource-type", underlying, "inout", nil, desc, consts, true, true, out)
+ generateArg("", "resource-type", underlying, "inout", nil, desc, true, true, out)
fmt.Fprintf(out, ", Kind: []string{")
for i, k := range kind {
if i != 0 {
@@ -505,17 +453,17 @@ func generateStructEntry(str *Struct, out io.Writer) {
typ, str.Name, false, packed, align, varlen)
}
-func generateStructFields(str *Struct, key structKey, desc *Description, consts map[string]uint64, out io.Writer) {
+func generateStructFields(str *Struct, key structKey, desc *Description, out io.Writer) {
fmt.Fprintf(out, "{structKey{\"%v\", \"%v\", %v}, []Type{\n", key.name, key.field, fmtDir(key.dir))
for _, a := range str.Flds {
- generateArg(str.Name, a[0], a[1], key.dir, a[2:], desc, consts, false, true, out)
+ generateArg(str.Name, a[0], a[1], key.dir, a[2:], desc, false, true, out)
fmt.Fprintf(out, ",\n")
}
fmt.Fprintf(out, "}},\n")
}
-func generateStructs(desc *Description, consts map[string]uint64, out io.Writer) {
+func generateStructs(desc *Description, out io.Writer) {
// Struct fields can refer to other structs. Go compiler won't like if
// we refer to Structs during Structs initialization. So we do
// it in 2 passes: on the first pass create struct types without fields,
@@ -557,26 +505,18 @@ func generateStructs(desc *Description, consts map[string]uint64, out io.Writer)
}
sort.Sort(structKeySorter(sortedKeys))
for _, key := range sortedKeys {
- generateStructFields(structMap[key], key, desc, consts, out)
+ generateStructFields(structMap[key], key, desc, out)
}
fmt.Fprintf(out, "}\n")
}
-func parseRange(buffer string, consts map[string]uint64) (string, string) {
- lookupConst := func(name string) string {
- if v, ok := consts[name]; ok {
- return fmt.Sprint(v)
- }
- return name
- }
-
+func parseRange(buffer string) (string, string) {
parts := strings.Split(buffer, ":")
switch len(parts) {
case 1:
- v := lookupConst(buffer)
- return v, v
+ return buffer, buffer
case 2:
- return lookupConst(parts[0]), lookupConst(parts[1])
+ return parts[0], parts[1]
default:
failf("bad range: %v", buffer)
return "", ""
@@ -587,7 +527,6 @@ func generateArg(
parent, name, typ, dir string,
a []string,
desc *Description,
- consts map[string]uint64,
isArg, isField bool,
out io.Writer) {
origName := name
@@ -659,15 +598,11 @@ func generateArg(
}
var size uint64
if len(a) >= 2 {
- if v, ok := consts[a[1]]; ok {
- size = v
- } else {
- v, err := strconv.ParseUint(a[1], 10, 64)
- if err != nil {
- failf("failed to parse string length for %v", name, a[1])
- }
- size = v
+ v, err := strconv.ParseUint(a[1], 10, 64)
+ if err != nil {
+ failf("failed to parse string length for %v", name, a[1])
}
+ size = v
for i, s := range vals {
if uint64(len(s)) > size {
failf("string value %q exceeds buffer length %v for arg %v", s, size, name)
@@ -703,7 +638,7 @@ func generateArg(
switch len(a) {
case 0:
case 1:
- begin, end = parseRange(a[0], consts)
+ begin, end = parseRange(a[0])
default:
failf("wrong number of arguments for %v arg %v, want 0 or 1, got %v", typ, name, len(a))
}
@@ -744,15 +679,11 @@ func generateArg(
case "pseudo":
kind = "CsumPseudo"
size, bigEndian, bitfieldLen = decodeIntType(a[3])
- if v, ok := consts[a[2]]; ok {
- protocol = v
- } else {
- v, err := strconv.ParseUint(a[2], 10, 64)
- if err != nil {
- failf("failed to parse protocol %v", a[2])
- }
- protocol = v
+ v, err := strconv.ParseUint(a[2], 10, 64)
+ if err != nil {
+ failf("failed to parse protocol %v", a[2])
}
+ protocol = v
default:
failf("unknown checksum kind '%v'", a[0])
}
@@ -796,16 +727,7 @@ func generateArg(
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
}
- val := a[0]
- if v, ok := consts[a[0]]; ok {
- val = fmt.Sprint(v)
- } else if isIdentifier(a[0]) {
- // This is an identifier for which we don't have a value for this arch.
- // Skip this syscall on this arch.
- val = "0"
- skipSyscall(fmt.Sprintf("missing const %v", a[0]))
- }
- fmt.Fprintf(out, "&ConstType{%v, Val: uint64(%v)}", intCommon(size, bigEndian, bitfieldLen), val)
+ fmt.Fprintf(out, "&ConstType{%v, Val: uint64(%v)}", intCommon(size, bigEndian, bitfieldLen), a[0])
case "proc":
canBeArg = true
size := uint64(ptrSize)
@@ -877,14 +799,14 @@ func generateArg(
if a[0] == "int8" {
fmt.Fprintf(out, "&BufferType{%v, Kind: BufferBlobRand}", common())
} else {
- fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], dir, desc, consts))
+ fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], dir, desc))
}
} else {
- begin, end := parseRange(a[1], consts)
+ begin, end := parseRange(a[1])
if a[0] == "int8" {
fmt.Fprintf(out, "&BufferType{%v, Kind: BufferBlobRange, RangeBegin: %v, RangeEnd: %v}", common(), begin, end)
} else {
- fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], dir, desc, consts), begin, end)
+ fmt.Fprintf(out, "&ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], dir, desc), begin, end)
}
}
case "ptr":
@@ -893,7 +815,7 @@ func generateArg(
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
dir = "in"
- fmt.Fprintf(out, "&PtrType{%v, Type: %v}", common(), generateType(a[1], a[0], desc, consts))
+ fmt.Fprintf(out, "&PtrType{%v, Type: %v}", common(), generateType(a[1], a[0], desc))
default:
if intRegExp.MatchString(typ) {
canBeArg = true
@@ -902,7 +824,7 @@ func generateArg(
case 0:
fmt.Fprintf(out, "&IntType{%v}", intCommon(size, bigEndian, bitfieldLen))
case 1:
- begin, end := parseRange(a[0], consts)
+ begin, end := parseRange(a[0])
fmt.Fprintf(out, "&IntType{%v, Kind: IntRange, RangeBegin: %v, RangeEnd: %v}",
intCommon(size, bigEndian, bitfieldLen), begin, end)
default:
@@ -910,7 +832,7 @@ func generateArg(
}
} else if strings.HasPrefix(typ, "unnamed") {
if inner, ok := desc.Unnamed[typ]; ok {
- generateArg("", "", inner[0], dir, inner[1:], desc, consts, false, isField, out)
+ generateArg("", "", inner[0], dir, inner[1:], desc, false, isField, out)
} else {
failf("unknown unnamed type '%v'", typ)
}
@@ -934,9 +856,9 @@ func generateArg(
}
}
-func generateType(typ, dir string, desc *Description, consts map[string]uint64) string {
+func generateType(typ, dir string, desc *Description) string {
buf := new(bytes.Buffer)
- generateArg("", "", typ, dir, nil, desc, consts, false, true, buf)
+ generateArg("", "", typ, dir, nil, desc, false, true, buf)
return buf.String()
}