github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/compiler/attrs.go (about) 1 // Copyright 2020 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package compiler 5 6 import ( 7 "reflect" 8 9 "github.com/google/syzkaller/pkg/ast" 10 "github.com/google/syzkaller/prog" 11 ) 12 13 type attrDescAttrType int 14 15 const ( 16 flagAttr attrDescAttrType = iota 17 // TODO: Ultimately we want to replace intAttr with exprAttr. 18 // This will facilitate const expressions in e.g. size[] or align[]. 19 intAttr 20 exprAttr 21 ) 22 23 type attrDesc struct { 24 Name string 25 // For now we assume attributes can have only 1 argument and it's either an 26 // integer or an expression. 27 Type attrDescAttrType 28 // This function is not invoked for per-field attributes, only for whole 29 // structs/unions. 30 CheckConsts func(comp *compiler, parent ast.Node, attr *ast.Type) 31 } 32 33 var ( 34 attrPacked = &attrDesc{Name: "packed"} 35 attrVarlen = &attrDesc{Name: "varlen"} 36 attrSize = &attrDesc{Name: "size", Type: intAttr} 37 attrAlign = &attrDesc{Name: "align", Type: intAttr} 38 attrIn = &attrDesc{Name: "in"} 39 attrOut = &attrDesc{Name: "out"} 40 attrInOut = &attrDesc{Name: "inout"} 41 attrOutOverlay = &attrDesc{Name: "out_overlay"} 42 attrIf = &attrDesc{Name: "if", Type: exprAttr} 43 44 structAttrs = makeAttrs(attrPacked, attrSize, attrAlign) 45 unionAttrs = makeAttrs(attrVarlen, attrSize) 46 structFieldAttrs = makeAttrs(attrIn, attrOut, attrInOut, attrOutOverlay, attrIf) 47 unionFieldAttrs = makeAttrs(attrIn, attrIf) // attrIn is safe. 48 callAttrs = make(map[string]*attrDesc) 49 ) 50 51 func init() { 52 initCallAttrs() 53 54 attrSize.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) { 55 _, typ, name := parent.Info() 56 if comp.structIsVarlen(name) { 57 comp.error(attr.Pos, "varlen %v %v has size attribute", typ, name) 58 } 59 sz := attr.Args[0].Value 60 if sz == 0 || sz > 1<<20 { 61 comp.error(attr.Args[0].Pos, "size attribute has bad value %v"+ 62 ", expect [1, 1<<20]", sz) 63 } 64 } 65 attrAlign.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) { 66 _, _, name := parent.Info() 67 a := attr.Args[0].Value 68 if a&(a-1) != 0 || a == 0 || a > 1<<30 { 69 comp.error(attr.Pos, "bad struct %v alignment %v (must be a sane power of 2)", name, a) 70 } 71 } 72 } 73 74 func initCallAttrs() { 75 attrs := reflect.TypeOf(prog.SyscallAttrs{}) 76 for i := 0; i < attrs.NumField(); i++ { 77 attr := attrs.Field(i) 78 desc := &attrDesc{Name: attr.Name} 79 switch attr.Type.Kind() { 80 case reflect.Bool: 81 case reflect.Uint64: 82 desc.Type = intAttr 83 default: 84 panic("unsupported syscall attribute type") 85 } 86 callAttrs[prog.CppName(desc.Name)] = desc 87 } 88 } 89 90 func structOrUnionAttrs(n *ast.Struct) map[string]*attrDesc { 91 if n.IsUnion { 92 return unionAttrs 93 } 94 return structAttrs 95 } 96 97 func structOrUnionFieldAttrs(n *ast.Struct) map[string]*attrDesc { 98 if n.IsUnion { 99 return unionFieldAttrs 100 } 101 return structFieldAttrs 102 } 103 104 func makeAttrs(attrs ...*attrDesc) map[string]*attrDesc { 105 m := make(map[string]*attrDesc) 106 for _, attr := range attrs { 107 m[attr.Name] = attr 108 } 109 return m 110 }