diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-04-16 17:38:36 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-04-19 10:26:57 +0200 |
| commit | 90d17ab8980674c6a59f47a062adccb37f99b88a (patch) | |
| tree | 63c96e2abc46f63d9092f07b16c8e70458b11444 /pkg/compiler | |
| parent | 0781895e0f8359843b9215ac6ad16925a46b2703 (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/compiler')
| -rw-r--r-- | pkg/compiler/attrs.go | 22 | ||||
| -rw-r--r-- | pkg/compiler/check.go | 1 | ||||
| -rw-r--r-- | pkg/compiler/consts.go | 64 | ||||
| -rw-r--r-- | pkg/compiler/gen.go | 12 | ||||
| -rw-r--r-- | pkg/compiler/testdata/all.txt | 3 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors.txt | 3 |
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 |
