github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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  	stringAttr
    22  )
    23  
    24  type attrDesc struct {
    25  	Name string
    26  	// For now we assume attributes can have only 1 argument and it's either an
    27  	// integer or an expression.
    28  	Type attrDescAttrType
    29  	// This function is not invoked for per-field attributes, only for whole
    30  	// structs/unions.
    31  	CheckConsts func(comp *compiler, parent ast.Node, attr *ast.Type)
    32  }
    33  
    34  var (
    35  	attrPacked     = &attrDesc{Name: "packed"}
    36  	attrVarlen     = &attrDesc{Name: "varlen"}
    37  	attrSize       = &attrDesc{Name: "size", Type: intAttr}
    38  	attrAlign      = &attrDesc{Name: "align", Type: intAttr}
    39  	attrIn         = &attrDesc{Name: "in"}
    40  	attrOut        = &attrDesc{Name: "out"}
    41  	attrInOut      = &attrDesc{Name: "inout"}
    42  	attrOutOverlay = &attrDesc{Name: "out_overlay"}
    43  	attrIf         = &attrDesc{Name: "if", Type: exprAttr}
    44  
    45  	structAttrs      = makeAttrs(attrPacked, attrSize, attrAlign)
    46  	unionAttrs       = makeAttrs(attrVarlen, attrSize)
    47  	structFieldAttrs = makeAttrs(attrIn, attrOut, attrInOut, attrOutOverlay, attrIf)
    48  	unionFieldAttrs  = makeAttrs(attrIn, attrIf) // attrIn is safe.
    49  	callAttrs        = make(map[string]*attrDesc)
    50  )
    51  
    52  func init() {
    53  	initCallAttrs()
    54  
    55  	attrSize.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) {
    56  		_, typ, name := parent.Info()
    57  		if comp.structIsVarlen(name) {
    58  			comp.error(attr.Pos, "varlen %v %v has size attribute", typ, name)
    59  		}
    60  		sz := attr.Args[0].Value
    61  		if sz == 0 || sz > 1<<20 {
    62  			comp.error(attr.Args[0].Pos, "size attribute has bad value %v"+
    63  				", expect [1, 1<<20]", sz)
    64  		}
    65  	}
    66  	attrAlign.CheckConsts = func(comp *compiler, parent ast.Node, attr *ast.Type) {
    67  		_, _, name := parent.Info()
    68  		a := attr.Args[0].Value
    69  		if a&(a-1) != 0 || a == 0 || a > 1<<30 {
    70  			comp.error(attr.Pos, "bad struct %v alignment %v (must be a sane power of 2)", name, a)
    71  		}
    72  	}
    73  }
    74  
    75  func initCallAttrs() {
    76  	attrs := reflect.TypeOf(prog.SyscallAttrs{})
    77  	for i := 0; i < attrs.NumField(); i++ {
    78  		attr := attrs.Field(i)
    79  		desc := &attrDesc{Name: attr.Name}
    80  		switch attr.Type.Kind() {
    81  		case reflect.Bool:
    82  		case reflect.Uint64:
    83  			desc.Type = intAttr
    84  		case reflect.String:
    85  			desc.Type = stringAttr
    86  		default:
    87  			panic("unsupported syscall attribute type")
    88  		}
    89  		callAttrs[prog.CppName(desc.Name)] = desc
    90  	}
    91  }
    92  
    93  func structOrUnionAttrs(n *ast.Struct) map[string]*attrDesc {
    94  	if n.IsUnion {
    95  		return unionAttrs
    96  	}
    97  	return structAttrs
    98  }
    99  
   100  func structOrUnionFieldAttrs(n *ast.Struct) map[string]*attrDesc {
   101  	if n.IsUnion {
   102  		return unionFieldAttrs
   103  	}
   104  	return structFieldAttrs
   105  }
   106  
   107  func makeAttrs(attrs ...*attrDesc) map[string]*attrDesc {
   108  	m := make(map[string]*attrDesc)
   109  	for _, attr := range attrs {
   110  		m[attr.Name] = attr
   111  	}
   112  	return m
   113  }