forked from google/syzkaller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathattrs.go
84 lines (73 loc) · 2.16 KB
/
attrs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright 2020 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 compiler
import (
"reflect"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/prog"
)
type attrDesc struct {
Name string
// For now we assume attributes can have only 1 argument and it's an integer,
// enough to cover existing cases.
HasArg bool
CheckConsts func(comp *compiler, parent ast.Node, attr *ast.Type)
}
var (
attrPacked = &attrDesc{Name: "packed"}
attrVarlen = &attrDesc{Name: "varlen"}
attrSize = &attrDesc{Name: "size", HasArg: true}
attrAlign = &attrDesc{Name: "align", HasArg: true}
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) {
comp.error(attr.Pos, "varlen %v %v has size attribute", typ, name)
}
sz := attr.Args[0].Value
if sz == 0 || sz > 1<<20 {
comp.error(attr.Args[0].Pos, "size attribute has bad value %v"+
", expect [1, 1<<20]", sz)
}
}
attrAlign.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) {
_, _, name := parent.Info()
a := attr.Args[0].Value
if a&(a-1) != 0 || a == 0 || a > 1<<30 {
comp.error(attr.Pos, "bad struct %v alignment %v (must be a sane power of 2)", name, a)
}
}
}
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
}
return structAttrs
}
func makeAttrs(attrs ...*attrDesc) map[string]*attrDesc {
m := make(map[string]*attrDesc)
for _, attr := range attrs {
m[attr.Name] = attr
}
return m
}