aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-04-16 17:38:36 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-04-19 10:26:57 +0200
commit90d17ab8980674c6a59f47a062adccb37f99b88a (patch)
tree63c96e2abc46f63d9092f07b16c8e70458b11444 /pkg
parent0781895e0f8359843b9215ac6ad16925a46b2703 (diff)
prog: introduce call attributes
Add common infrastructure for syscall attributes. Add few attributes we want, but they are not implemented for now (don't affect behavior, this will follow).
Diffstat (limited to 'pkg')
-rw-r--r--pkg/compiler/attrs.go22
-rw-r--r--pkg/compiler/check.go1
-rw-r--r--pkg/compiler/consts.go64
-rw-r--r--pkg/compiler/gen.go12
-rw-r--r--pkg/compiler/testdata/all.txt3
-rw-r--r--pkg/compiler/testdata/errors.txt3
6 files changed, 75 insertions, 30 deletions
diff --git a/pkg/compiler/attrs.go b/pkg/compiler/attrs.go
index 245da125f..c0fa04211 100644
--- a/pkg/compiler/attrs.go
+++ b/pkg/compiler/attrs.go
@@ -4,7 +4,10 @@
package compiler
import (
+ "reflect"
+
"github.com/google/syzkaller/pkg/ast"
+ "github.com/google/syzkaller/prog"
)
type attrDesc struct {
@@ -23,9 +26,12 @@ var (
structAttrs = makeAttrs(attrPacked, attrSize, attrAlign)
unionAttrs = makeAttrs(attrVarlen, attrSize)
+ callAttrs = make(map[string]*attrDesc)
)
func init() {
+ initCallAttrs()
+
attrSize.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) {
_, typ, name := parent.Info()
if comp.structIsVarlen(name) {
@@ -46,6 +52,22 @@ func init() {
}
}
+func initCallAttrs() {
+ attrs := reflect.TypeOf(prog.SyscallAttrs{})
+ for i := 0; i < attrs.NumField(); i++ {
+ attr := attrs.Field(i)
+ desc := &attrDesc{Name: attr.Name}
+ switch attr.Type.Kind() {
+ case reflect.Bool:
+ case reflect.Uint64:
+ desc.HasArg = true
+ default:
+ panic("unsupported syscall attribute type")
+ }
+ callAttrs[prog.CppName(desc.Name)] = desc
+ }
+}
+
func structOrUnionAttrs(n *ast.Struct) map[string]*attrDesc {
if n.IsUnion {
return unionAttrs
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 7ddb662d9..e22f217fd 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -713,6 +713,7 @@ func (comp *compiler) checkCall(n *ast.Call) {
if n.Ret != nil {
comp.checkType(checkCtx{}, n.Ret, checkIsArg|checkIsRet)
}
+ comp.parseAttrs(callAttrs, n, n.Attrs)
}
type checkFlags int
diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go
index 5c0a4e8b2..5a6dbd974 100644
--- a/pkg/compiler/consts.go
+++ b/pkg/compiler/consts.go
@@ -77,32 +77,11 @@ func (comp *compiler) extractConsts() map[string]*ConstInfo {
if comp.target.SyscallNumbers && !strings.HasPrefix(n.CallName, "syz_") {
comp.addConst(infos, pos, comp.target.SyscallPrefix+n.CallName)
}
- }
- }
-
- for _, decl := range comp.desc.Nodes {
- switch decl.(type) {
- case *ast.Call, *ast.Struct, *ast.Resource, *ast.TypeDef:
- comp.foreachType(decl, func(t *ast.Type, desc *typeDesc,
- args []*ast.Type, _ prog.IntTypeCommon) {
- for i, arg := range args {
- if desc.Args[i].Type.Kind == kindInt {
- if arg.Ident != "" {
- comp.addConst(infos, arg.Pos, arg.Ident)
- }
- for _, col := range arg.Colon {
- if col.Ident != "" {
- comp.addConst(infos, col.Pos, col.Ident)
- }
- }
- }
+ for _, attr := range n.Attrs {
+ if callAttrs[attr.Ident].HasArg {
+ comp.addConst(infos, attr.Pos, attr.Args[0].Ident)
}
- })
- }
- }
-
- for _, decl := range comp.desc.Nodes {
- switch n := decl.(type) {
+ }
case *ast.Struct:
for _, attr := range n.Attrs {
if structOrUnionAttrs(n)[attr.Ident].HasArg {
@@ -110,17 +89,36 @@ func (comp *compiler) extractConsts() map[string]*ConstInfo {
}
}
}
+ switch decl.(type) {
+ case *ast.Call, *ast.Struct, *ast.Resource, *ast.TypeDef:
+ comp.extractTypeConsts(infos, decl)
+ }
}
-
comp.desc.Walk(ast.Recursive(func(n0 ast.Node) {
if n, ok := n0.(*ast.Int); ok {
comp.addConst(infos, n.Pos, n.Ident)
}
}))
-
return convertConstInfo(infos)
}
+func (comp *compiler) extractTypeConsts(infos map[string]*constInfo, n ast.Node) {
+ comp.foreachType(n, func(t *ast.Type, desc *typeDesc, args []*ast.Type, _ prog.IntTypeCommon) {
+ for i, arg := range args {
+ if desc.Args[i].Type.Kind == kindInt {
+ if arg.Ident != "" {
+ comp.addConst(infos, arg.Pos, arg.Ident)
+ }
+ for _, col := range arg.Colon {
+ if col.Ident != "" {
+ comp.addConst(infos, col.Pos, col.Ident)
+ }
+ }
+ }
+ }
+ })
+}
+
func (comp *compiler) addConst(infos map[string]*constInfo, pos ast.Pos, name string) {
if _, builtin := comp.builtinConsts[name]; builtin {
return
@@ -220,12 +218,18 @@ func (comp *compiler) patchConsts(consts0 map[string]uint64) {
}
}
})
- if n, ok := decl.(*ast.Resource); ok {
+ switch n := decl.(type) {
+ case *ast.Resource:
for _, v := range n.Values {
comp.patchIntConst(v, consts, &missing)
}
- }
- if n, ok := decl.(*ast.Struct); ok {
+ case *ast.Call:
+ for _, attr := range n.Attrs {
+ if callAttrs[attr.Ident].HasArg {
+ comp.patchTypeConst(attr.Args[0], consts, &missing)
+ }
+ }
+ case *ast.Struct:
for _, attr := range n.Attrs {
if structOrUnionAttrs(n)[attr.Ident].HasArg {
comp.patchTypeConst(attr.Args[0], consts, &missing)
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go
index baafee0e2..f357adc24 100644
--- a/pkg/compiler/gen.go
+++ b/pkg/compiler/gen.go
@@ -5,6 +5,7 @@ package compiler
import (
"fmt"
+ "reflect"
"sort"
"github.com/google/syzkaller/pkg/ast"
@@ -111,6 +112,16 @@ func (comp *compiler) genSyscall(n *ast.Call, argSizes []uint64) *prog.Syscall {
if n.Ret != nil {
ret = comp.genType(n.Ret, "ret", prog.DirOut, comp.ptrSize)
}
+ var attrs prog.SyscallAttrs
+ descAttrs := comp.parseAttrs(callAttrs, n, n.Attrs)
+ for desc, val := range descAttrs {
+ fld := reflect.ValueOf(&attrs).Elem().FieldByName(desc.Name)
+ if desc.HasArg {
+ fld.SetUint(val)
+ } else {
+ fld.SetBool(val != 0)
+ }
+ }
return &prog.Syscall{
Name: n.Name.Name,
CallName: n.CallName,
@@ -118,6 +129,7 @@ func (comp *compiler) genSyscall(n *ast.Call, argSizes []uint64) *prog.Syscall {
MissingArgs: len(argSizes) - len(n.Args),
Args: comp.genFieldArray(n.Args, prog.DirIn, argSizes),
Ret: ret,
+ Attrs: attrs,
}
}
diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt
index 455ccbe60..f5f3f1070 100644
--- a/pkg/compiler/testdata/all.txt
+++ b/pkg/compiler/testdata/all.txt
@@ -14,6 +14,9 @@ foo_9(a ptr[out, ptr[in, string]])
foo_10(a ptr[out, buffer[in]])
foo_11(a int64[1:100, 2])
foo_12(a int64[0:-1, 0x1000])
+foo_13() (disabled)
+foo_14() r0 (timeout[100])
+foo_15() r0 (disabled, timeout[C1], prog_timeout[C2])
resource r0[intptr]
diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt
index 3b77ed4b9..5c7f923d6 100644
--- a/pkg/compiler/testdata/errors.txt
+++ b/pkg/compiler/testdata/errors.txt
@@ -125,6 +125,9 @@ foo$65(a int32, b len[1]) ### unexpected int 1 for len target argument of len ty
foo$66(a int32, b len[a:1]) ### unexpected int 1 after colon, expect identifier
foo$67(x int32[1:2:3, opt]) ### unexpected ':'
foo$68(a int32[15, 2]) ### first argument of int32 needs to be a range
+foo$69() (foo) ### unknown syscall foo$69 attribute foo
+foo$70() ("foo") ### unexpected string "foo", expect attribute
+foo$71() (42) ### unexpected int 42, expect attribute
opt { ### struct uses reserved name opt
f1 int32