2016-08-08 13:32:48 +00:00
|
|
|
// Copyright 2015/2016 syzkaller project authors. All rights reserved.
|
2015-10-12 08:16:57 +00:00
|
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
|
2017-09-05 11:31:14 +00:00
|
|
|
package prog
|
2015-10-12 08:16:57 +00:00
|
|
|
|
2016-01-28 07:20:09 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
2020-01-03 08:58:37 +00:00
|
|
|
"strings"
|
2020-04-16 15:38:36 +00:00
|
|
|
"unicode"
|
2016-01-28 07:20:09 +00:00
|
|
|
)
|
|
|
|
|
2017-09-05 08:38:22 +00:00
|
|
|
type Syscall struct {
|
2018-12-27 12:08:02 +00:00
|
|
|
ID int
|
|
|
|
NR uint64 // kernel syscall number
|
|
|
|
Name string
|
|
|
|
CallName string
|
|
|
|
MissingArgs int // number of trailing args that should be zero-filled
|
|
|
|
Args []Type
|
|
|
|
Ret Type
|
2020-04-16 15:38:36 +00:00
|
|
|
Attrs SyscallAttrs
|
2019-12-30 10:41:20 +00:00
|
|
|
|
|
|
|
inputResources []*ResourceDesc
|
|
|
|
outputResources []*ResourceDesc
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 15:38:36 +00:00
|
|
|
// SyscallAttrs represents call attributes in syzlang.
|
|
|
|
//
|
|
|
|
// This structure is the source of truth for the all other parts of the system.
|
|
|
|
// pkg/compiler uses this structure to parse descriptions.
|
|
|
|
// syz-sysgen uses this structure to generate code for executor.
|
|
|
|
//
|
|
|
|
// Only bool's and uint64's are currently supported.
|
2020-04-18 15:09:59 +00:00
|
|
|
//
|
|
|
|
// See docs/syscall_descriptions_syntax.md for description of individual attributes.
|
2020-04-16 15:38:36 +00:00
|
|
|
type SyscallAttrs struct {
|
2020-04-18 15:09:59 +00:00
|
|
|
Disabled bool
|
|
|
|
Timeout uint64
|
|
|
|
ProgTimeout uint64
|
|
|
|
IgnoreReturn bool
|
|
|
|
BreaksReturns bool
|
2020-04-16 15:38:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-31 11:29:37 +00:00
|
|
|
// MaxArgs is maximum number of syscall arguments.
|
|
|
|
// Executor also knows about this value.
|
|
|
|
const MaxArgs = 9
|
|
|
|
|
2016-10-19 12:41:46 +00:00
|
|
|
type Dir int
|
|
|
|
|
|
|
|
const (
|
|
|
|
DirIn Dir = iota
|
|
|
|
DirOut
|
|
|
|
DirInOut
|
|
|
|
)
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (dir Dir) String() string {
|
|
|
|
switch dir {
|
|
|
|
case DirIn:
|
|
|
|
return "in"
|
|
|
|
case DirOut:
|
|
|
|
return "out"
|
|
|
|
case DirInOut:
|
|
|
|
return "inout"
|
|
|
|
default:
|
|
|
|
panic("unknown dir")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-07 18:07:30 +00:00
|
|
|
type BinaryFormat int
|
|
|
|
|
|
|
|
const (
|
|
|
|
FormatNative BinaryFormat = iota
|
|
|
|
FormatBigEndian
|
|
|
|
FormatStrDec
|
|
|
|
FormatStrHex
|
|
|
|
FormatStrOct
|
|
|
|
)
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type Type interface {
|
2018-02-24 13:33:36 +00:00
|
|
|
String() string
|
2015-10-12 08:16:57 +00:00
|
|
|
Name() string
|
2017-01-23 14:02:47 +00:00
|
|
|
FieldName() string
|
2020-01-03 08:58:37 +00:00
|
|
|
TemplateName() string // for template structs name without arguments
|
2016-10-19 12:41:46 +00:00
|
|
|
Dir() Dir
|
2015-10-12 08:16:57 +00:00
|
|
|
Optional() bool
|
2017-01-19 13:42:29 +00:00
|
|
|
Varlen() bool
|
2017-08-19 07:46:43 +00:00
|
|
|
Size() uint64
|
2019-09-11 16:20:17 +00:00
|
|
|
TypeBitSize() uint64
|
2018-07-07 18:07:30 +00:00
|
|
|
Format() BinaryFormat
|
2017-08-19 07:46:43 +00:00
|
|
|
BitfieldOffset() uint64
|
|
|
|
BitfieldLength() uint64
|
2019-12-18 17:30:39 +00:00
|
|
|
IsBitfield() bool
|
|
|
|
// For most of the types UnitSize is equal to Size.
|
|
|
|
// These are different only for all but last bitfield in the group,
|
|
|
|
// where Size == 0 and UnitSize equals to the underlying bitfield type size.
|
|
|
|
UnitSize() uint64
|
2019-12-20 12:57:42 +00:00
|
|
|
UnitOffset() uint64
|
2018-05-04 16:03:46 +00:00
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
DefaultArg() Arg
|
2018-08-01 17:24:21 +00:00
|
|
|
isDefaultArg(arg Arg) bool
|
2018-05-04 16:03:46 +00:00
|
|
|
generate(r *randGen, s *state) (arg Arg, calls []*Call)
|
2018-05-07 14:24:03 +00:00
|
|
|
mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool)
|
2019-07-31 09:44:44 +00:00
|
|
|
getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool)
|
2018-07-31 14:06:21 +00:00
|
|
|
minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 08:06:37 +00:00
|
|
|
type Ref uint32
|
|
|
|
|
|
|
|
func (ti Ref) String() string { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Name() string { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) FieldName() string { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) TemplateName() string { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Dir() Dir { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Optional() bool { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Varlen() bool { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Size() uint64 { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) TypeBitSize() uint64 { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Format() BinaryFormat { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) BitfieldOffset() uint64 { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) BitfieldLength() uint64 { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) IsBitfield() bool { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) UnitSize() uint64 { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) UnitOffset() uint64 { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) DefaultArg() Arg { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) Clone() Type { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) isDefaultArg(arg Arg) bool { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) generate(r *randGen, s *state) (Arg, []*Call) { panic("prog.Ref method called") }
|
|
|
|
func (ti Ref) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) ([]*Call, bool, bool) {
|
|
|
|
panic("prog.Ref method called")
|
|
|
|
}
|
|
|
|
func (ti Ref) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (float64, bool) {
|
|
|
|
panic("prog.Ref method called")
|
|
|
|
}
|
|
|
|
func (ti Ref) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool {
|
|
|
|
panic("prog.Ref method called")
|
|
|
|
}
|
|
|
|
|
2015-12-28 11:58:10 +00:00
|
|
|
func IsPad(t Type) bool {
|
2016-10-19 14:20:37 +00:00
|
|
|
if ct, ok := t.(*ConstType); ok && ct.IsPad {
|
2015-12-28 11:58:10 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type TypeCommon struct {
|
2019-12-18 17:30:39 +00:00
|
|
|
TypeName string
|
|
|
|
FldName string // for struct fields and named args
|
|
|
|
// Static size of the type, or 0 for variable size types and all but last bitfields in the group.
|
|
|
|
TypeSize uint64
|
2016-10-19 12:41:46 +00:00
|
|
|
ArgDir Dir
|
2015-10-12 08:16:57 +00:00
|
|
|
IsOptional bool
|
2018-01-12 09:45:32 +00:00
|
|
|
IsVarlen bool
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2016-10-19 14:20:37 +00:00
|
|
|
func (t *TypeCommon) Name() string {
|
2015-10-12 08:16:57 +00:00
|
|
|
return t.TypeName
|
|
|
|
}
|
|
|
|
|
2017-01-23 14:02:47 +00:00
|
|
|
func (t *TypeCommon) FieldName() string {
|
|
|
|
return t.FldName
|
|
|
|
}
|
|
|
|
|
2020-01-03 08:58:37 +00:00
|
|
|
func (t *TypeCommon) TemplateName() string {
|
|
|
|
name := t.TypeName
|
|
|
|
if pos := strings.IndexByte(name, '['); pos != -1 {
|
|
|
|
name = name[:pos]
|
|
|
|
}
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2016-10-19 14:20:37 +00:00
|
|
|
func (t *TypeCommon) Optional() bool {
|
2015-10-12 08:16:57 +00:00
|
|
|
return t.IsOptional
|
|
|
|
}
|
|
|
|
|
2017-09-04 17:53:05 +00:00
|
|
|
func (t *TypeCommon) Size() uint64 {
|
2018-01-12 09:45:32 +00:00
|
|
|
if t.IsVarlen {
|
2017-09-04 17:53:05 +00:00
|
|
|
panic(fmt.Sprintf("static type size is not known: %#v", t))
|
|
|
|
}
|
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
2019-09-11 16:20:17 +00:00
|
|
|
func (t *TypeCommon) TypeBitSize() uint64 {
|
|
|
|
panic("cannot get the bitsize for a non-integer type")
|
|
|
|
}
|
|
|
|
|
2017-01-19 13:42:29 +00:00
|
|
|
func (t *TypeCommon) Varlen() bool {
|
2018-01-12 09:45:32 +00:00
|
|
|
return t.IsVarlen
|
2017-01-19 13:42:29 +00:00
|
|
|
}
|
|
|
|
|
2018-07-07 18:07:30 +00:00
|
|
|
func (t *TypeCommon) Format() BinaryFormat {
|
|
|
|
return FormatNative
|
|
|
|
}
|
|
|
|
|
2017-08-19 07:46:43 +00:00
|
|
|
func (t *TypeCommon) BitfieldOffset() uint64 {
|
2017-01-10 15:45:52 +00:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2017-08-19 07:46:43 +00:00
|
|
|
func (t *TypeCommon) BitfieldLength() uint64 {
|
2017-01-10 15:45:52 +00:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2019-12-18 17:30:39 +00:00
|
|
|
func (t *TypeCommon) UnitSize() uint64 {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2019-12-20 12:57:42 +00:00
|
|
|
func (t *TypeCommon) UnitOffset() uint64 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2019-12-18 17:30:39 +00:00
|
|
|
func (t *TypeCommon) IsBitfield() bool {
|
2017-01-10 15:45:52 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-10-19 12:41:46 +00:00
|
|
|
func (t TypeCommon) Dir() Dir {
|
|
|
|
return t.ArgDir
|
|
|
|
}
|
|
|
|
|
2016-08-27 16:27:50 +00:00
|
|
|
type ResourceDesc struct {
|
|
|
|
Name string
|
|
|
|
Kind []string
|
2017-08-19 07:46:43 +00:00
|
|
|
Values []uint64
|
2019-08-21 18:05:22 +00:00
|
|
|
Ctors []ResourceCtor
|
|
|
|
}
|
|
|
|
|
|
|
|
type ResourceCtor struct {
|
|
|
|
Call int // Index in Target.Syscalls
|
|
|
|
Precise bool
|
2015-12-27 11:20:00 +00:00
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type ResourceType struct {
|
|
|
|
TypeCommon
|
2018-07-07 18:07:30 +00:00
|
|
|
ArgFormat BinaryFormat
|
|
|
|
Desc *ResourceDesc
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *ResourceType) String() string {
|
|
|
|
return t.Name()
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *ResourceType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeResultArg(t, nil, t.Default())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ResourceType) isDefaultArg(arg Arg) bool {
|
|
|
|
a := arg.(*ResultArg)
|
|
|
|
return a.Res == nil && a.OpDiv == 0 && a.OpAdd == 0 &&
|
|
|
|
len(a.uses) == 0 && a.Val == t.Default()
|
|
|
|
}
|
|
|
|
|
2017-08-19 07:46:43 +00:00
|
|
|
func (t *ResourceType) Default() uint64 {
|
2016-08-27 16:27:50 +00:00
|
|
|
return t.Desc.Values[0]
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2017-08-19 07:46:43 +00:00
|
|
|
func (t *ResourceType) SpecialValues() []uint64 {
|
2016-08-27 16:27:50 +00:00
|
|
|
return t.Desc.Values
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2018-07-07 18:07:30 +00:00
|
|
|
func (t *ResourceType) Format() BinaryFormat {
|
|
|
|
return t.ArgFormat
|
|
|
|
}
|
|
|
|
|
2017-01-10 15:45:52 +00:00
|
|
|
type IntTypeCommon struct {
|
|
|
|
TypeCommon
|
2019-12-20 12:57:42 +00:00
|
|
|
ArgFormat BinaryFormat
|
|
|
|
BitfieldOff uint64
|
|
|
|
BitfieldLen uint64
|
|
|
|
BitfieldUnit uint64
|
|
|
|
BitfieldUnitOff uint64
|
2017-01-10 15:45:52 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *IntTypeCommon) String() string {
|
|
|
|
return t.Name()
|
|
|
|
}
|
|
|
|
|
2018-07-07 18:07:30 +00:00
|
|
|
func (t *IntTypeCommon) Format() BinaryFormat {
|
|
|
|
return t.ArgFormat
|
|
|
|
}
|
|
|
|
|
2019-09-11 16:20:17 +00:00
|
|
|
// Returns the size in bits for integers in binary format or 64 for string-formatted integers. The return
|
|
|
|
// value is used in computing limits and truncating other values.
|
|
|
|
func (t *IntTypeCommon) TypeBitSize() uint64 {
|
|
|
|
if t.ArgFormat != FormatNative && t.ArgFormat != FormatBigEndian {
|
|
|
|
// TODO: add special cases for mutation and generation of string-formatted integers.
|
|
|
|
return 64
|
|
|
|
}
|
|
|
|
if t.BitfieldLen != 0 {
|
|
|
|
return t.BitfieldLen
|
|
|
|
}
|
|
|
|
return t.TypeSize * 8
|
|
|
|
}
|
|
|
|
|
2017-08-19 07:46:43 +00:00
|
|
|
func (t *IntTypeCommon) BitfieldOffset() uint64 {
|
2017-01-10 15:45:52 +00:00
|
|
|
return t.BitfieldOff
|
|
|
|
}
|
|
|
|
|
2017-08-19 07:46:43 +00:00
|
|
|
func (t *IntTypeCommon) BitfieldLength() uint64 {
|
2017-01-10 15:45:52 +00:00
|
|
|
return t.BitfieldLen
|
|
|
|
}
|
|
|
|
|
2019-12-18 17:30:39 +00:00
|
|
|
func (t *IntTypeCommon) UnitSize() uint64 {
|
|
|
|
if t.BitfieldLen != 0 {
|
|
|
|
return t.BitfieldUnit
|
|
|
|
}
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2019-12-20 12:57:42 +00:00
|
|
|
func (t *IntTypeCommon) UnitOffset() uint64 {
|
|
|
|
return t.BitfieldUnitOff
|
|
|
|
}
|
|
|
|
|
2019-12-18 17:30:39 +00:00
|
|
|
func (t *IntTypeCommon) IsBitfield() bool {
|
|
|
|
return t.BitfieldLen != 0
|
2017-01-10 15:45:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ConstType struct {
|
|
|
|
IntTypeCommon
|
2017-08-19 07:46:43 +00:00
|
|
|
Val uint64
|
2017-01-10 15:45:52 +00:00
|
|
|
IsPad bool
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *ConstType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeConstArg(t, t.Val)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ConstType) isDefaultArg(arg Arg) bool {
|
|
|
|
return arg.(*ConstArg).Val == t.Val
|
2018-07-11 04:44:36 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *ConstType) String() string {
|
|
|
|
if t.IsPad {
|
|
|
|
return fmt.Sprintf("pad[%v]", t.Size())
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("const[%v, %v]", t.Val, t.IntTypeCommon.String())
|
|
|
|
}
|
|
|
|
|
2017-01-10 15:45:52 +00:00
|
|
|
type IntKind int
|
|
|
|
|
|
|
|
const (
|
2019-10-26 13:31:00 +00:00
|
|
|
IntPlain IntKind = iota
|
2017-01-10 15:45:52 +00:00
|
|
|
IntRange
|
|
|
|
)
|
|
|
|
|
|
|
|
type IntType struct {
|
|
|
|
IntTypeCommon
|
|
|
|
Kind IntKind
|
2017-08-19 07:46:43 +00:00
|
|
|
RangeBegin uint64
|
|
|
|
RangeEnd uint64
|
2019-10-18 12:45:31 +00:00
|
|
|
Align uint64
|
2017-01-10 15:45:52 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *IntType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeConstArg(t, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *IntType) isDefaultArg(arg Arg) bool {
|
|
|
|
return arg.(*ConstArg).Val == 0
|
|
|
|
}
|
|
|
|
|
2017-01-10 15:45:52 +00:00
|
|
|
type FlagsType struct {
|
|
|
|
IntTypeCommon
|
2020-01-17 18:30:03 +00:00
|
|
|
Vals []uint64 // compiler ensures that it's not empty
|
2018-06-30 11:27:24 +00:00
|
|
|
BitMask bool
|
2017-01-10 15:45:52 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *FlagsType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeConstArg(t, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *FlagsType) isDefaultArg(arg Arg) bool {
|
|
|
|
return arg.(*ConstArg).Val == 0
|
|
|
|
}
|
|
|
|
|
2017-01-10 15:45:52 +00:00
|
|
|
type LenType struct {
|
|
|
|
IntTypeCommon
|
2017-12-31 13:58:00 +00:00
|
|
|
BitSize uint64 // want size in multiple of bits instead of array size
|
2019-05-16 16:05:05 +00:00
|
|
|
Offset bool // offset from the beginning of the parent struct or base object
|
2019-05-13 16:52:46 +00:00
|
|
|
Path []string
|
2017-01-10 15:45:52 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *LenType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeConstArg(t, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *LenType) isDefaultArg(arg Arg) bool {
|
|
|
|
return arg.(*ConstArg).Val == 0
|
|
|
|
}
|
|
|
|
|
2017-01-10 15:45:52 +00:00
|
|
|
type ProcType struct {
|
|
|
|
IntTypeCommon
|
2017-08-19 07:46:43 +00:00
|
|
|
ValuesStart uint64
|
2017-01-10 15:45:52 +00:00
|
|
|
ValuesPerProc uint64
|
|
|
|
}
|
|
|
|
|
2018-08-01 17:24:21 +00:00
|
|
|
const (
|
|
|
|
MaxPids = 32
|
|
|
|
procDefaultValue = 0xffffffffffffffff // special value denoting 0 for all procs
|
|
|
|
)
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *ProcType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeConstArg(t, procDefaultValue)
|
|
|
|
}
|
2018-07-25 08:38:58 +00:00
|
|
|
|
2018-08-01 17:24:21 +00:00
|
|
|
func (t *ProcType) isDefaultArg(arg Arg) bool {
|
|
|
|
return arg.(*ConstArg).Val == procDefaultValue
|
2018-01-01 10:23:45 +00:00
|
|
|
}
|
|
|
|
|
2017-01-25 15:18:05 +00:00
|
|
|
type CsumKind int
|
|
|
|
|
|
|
|
const (
|
2017-02-06 18:27:17 +00:00
|
|
|
CsumInet CsumKind = iota
|
2017-02-08 14:49:03 +00:00
|
|
|
CsumPseudo
|
2017-01-25 15:18:05 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type CsumType struct {
|
|
|
|
IntTypeCommon
|
2017-02-08 14:49:03 +00:00
|
|
|
Kind CsumKind
|
|
|
|
Buf string
|
|
|
|
Protocol uint64 // for CsumPseudo
|
2017-01-25 15:18:05 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *CsumType) String() string {
|
|
|
|
return "csum"
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *CsumType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
return MakeConstArg(t, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *CsumType) isDefaultArg(arg Arg) bool {
|
|
|
|
return arg.(*ConstArg).Val == 0
|
|
|
|
}
|
|
|
|
|
2017-01-10 15:45:52 +00:00
|
|
|
type VmaType struct {
|
|
|
|
TypeCommon
|
2017-08-19 07:46:43 +00:00
|
|
|
RangeBegin uint64 // in pages
|
|
|
|
RangeEnd uint64
|
2017-01-10 15:45:52 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *VmaType) String() string {
|
|
|
|
return "vma"
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *VmaType) DefaultArg() Arg {
|
2018-08-30 21:17:47 +00:00
|
|
|
return MakeSpecialPointerArg(t, 0)
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *VmaType) isDefaultArg(arg Arg) bool {
|
2018-08-30 21:17:47 +00:00
|
|
|
a := arg.(*PointerArg)
|
|
|
|
return a.IsSpecial() && a.Address == 0
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type BufferKind int
|
|
|
|
|
|
|
|
const (
|
2016-09-21 14:52:55 +00:00
|
|
|
BufferBlobRand BufferKind = iota
|
|
|
|
BufferBlobRange
|
2015-10-12 08:16:57 +00:00
|
|
|
BufferString
|
2016-10-29 21:55:35 +00:00
|
|
|
BufferFilename
|
2017-01-08 16:20:32 +00:00
|
|
|
BufferText
|
|
|
|
)
|
|
|
|
|
|
|
|
type TextKind int
|
|
|
|
|
|
|
|
const (
|
2018-08-31 04:10:38 +00:00
|
|
|
TextTarget TextKind = iota
|
|
|
|
TextX86Real
|
2018-05-07 15:59:06 +00:00
|
|
|
TextX86bit16
|
|
|
|
TextX86bit32
|
|
|
|
TextX86bit64
|
|
|
|
TextArm64
|
2015-10-12 08:16:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type BufferType struct {
|
|
|
|
TypeCommon
|
2016-09-21 14:52:55 +00:00
|
|
|
Kind BufferKind
|
2018-04-02 12:21:45 +00:00
|
|
|
RangeBegin uint64 // for BufferBlobRange kind
|
2017-08-19 07:46:43 +00:00
|
|
|
RangeEnd uint64 // for BufferBlobRange kind
|
2017-01-08 16:20:32 +00:00
|
|
|
Text TextKind // for BufferText
|
2016-10-31 21:15:13 +00:00
|
|
|
SubKind string
|
|
|
|
Values []string // possible values for BufferString kind
|
2018-04-02 12:21:45 +00:00
|
|
|
NoZ bool // non-zero terminated BufferString/BufferFilename
|
2015-12-11 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *BufferType) String() string {
|
|
|
|
return "buffer"
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *BufferType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
if t.Dir() == DirOut {
|
|
|
|
var sz uint64
|
|
|
|
if !t.Varlen() {
|
|
|
|
sz = t.Size()
|
|
|
|
}
|
|
|
|
return MakeOutDataArg(t, sz)
|
|
|
|
}
|
|
|
|
var data []byte
|
|
|
|
if !t.Varlen() {
|
|
|
|
data = make([]byte, t.Size())
|
|
|
|
}
|
|
|
|
return MakeDataArg(t, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *BufferType) isDefaultArg(arg Arg) bool {
|
|
|
|
a := arg.(*DataArg)
|
|
|
|
if a.Size() == 0 {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if a.Type().Varlen() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if a.Type().Dir() == DirOut {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
for _, v := range a.Data() {
|
|
|
|
if v != 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2016-09-15 11:45:06 +00:00
|
|
|
type ArrayKind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
ArrayRandLen ArrayKind = iota
|
|
|
|
ArrayRangeLen
|
|
|
|
)
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type ArrayType struct {
|
|
|
|
TypeCommon
|
2016-09-15 11:45:06 +00:00
|
|
|
Type Type
|
|
|
|
Kind ArrayKind
|
2017-08-19 07:46:43 +00:00
|
|
|
RangeBegin uint64
|
|
|
|
RangeEnd uint64
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *ArrayType) String() string {
|
|
|
|
return fmt.Sprintf("array[%v]", t.Type.String())
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *ArrayType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
var elems []Arg
|
|
|
|
if t.Kind == ArrayRangeLen && t.RangeBegin == t.RangeEnd {
|
|
|
|
for i := uint64(0); i < t.RangeBegin; i++ {
|
2018-12-06 17:44:26 +00:00
|
|
|
elems = append(elems, t.Type.DefaultArg())
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return MakeGroupArg(t, elems)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *ArrayType) isDefaultArg(arg Arg) bool {
|
|
|
|
a := arg.(*GroupArg)
|
|
|
|
if !a.fixedInnerSize() && len(a.Inner) != 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, elem := range a.Inner {
|
2018-08-01 19:06:38 +00:00
|
|
|
if !isDefault(elem) {
|
2018-08-01 17:24:21 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type PtrType struct {
|
|
|
|
TypeCommon
|
2017-09-04 17:53:05 +00:00
|
|
|
Type Type
|
2015-12-11 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *PtrType) String() string {
|
|
|
|
return fmt.Sprintf("ptr[%v, %v]", t.Dir(), t.Type.String())
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *PtrType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
if t.Optional() {
|
2018-08-30 21:17:47 +00:00
|
|
|
return MakeSpecialPointerArg(t, 0)
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
2018-12-06 17:44:26 +00:00
|
|
|
return MakePointerArg(t, 0, t.Type.DefaultArg())
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *PtrType) isDefaultArg(arg Arg) bool {
|
|
|
|
a := arg.(*PointerArg)
|
|
|
|
if t.Optional() {
|
2018-08-30 21:17:47 +00:00
|
|
|
return a.IsSpecial() && a.Address == 0
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
2018-08-30 21:17:47 +00:00
|
|
|
return a.Address == 0 && a.Res != nil && isDefault(a.Res)
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type StructType struct {
|
2017-09-04 17:53:05 +00:00
|
|
|
Key StructKey
|
|
|
|
FldName string
|
|
|
|
*StructDesc
|
2015-12-11 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *StructType) String() string {
|
|
|
|
return t.Name()
|
|
|
|
}
|
|
|
|
|
2017-09-04 17:53:05 +00:00
|
|
|
func (t *StructType) FieldName() string {
|
|
|
|
return t.FldName
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *StructType) DefaultArg() Arg {
|
2018-08-01 17:24:21 +00:00
|
|
|
inner := make([]Arg, len(t.Fields))
|
|
|
|
for i, field := range t.Fields {
|
2018-12-06 17:44:26 +00:00
|
|
|
inner[i] = field.DefaultArg()
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
return MakeGroupArg(t, inner)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *StructType) isDefaultArg(arg Arg) bool {
|
|
|
|
a := arg.(*GroupArg)
|
2018-08-01 19:06:38 +00:00
|
|
|
for _, elem := range a.Inner {
|
|
|
|
if !isDefault(elem) {
|
2018-08-01 17:24:21 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2015-12-29 14:00:57 +00:00
|
|
|
type UnionType struct {
|
2017-09-04 17:53:05 +00:00
|
|
|
Key StructKey
|
|
|
|
FldName string
|
|
|
|
*StructDesc
|
2017-01-19 13:42:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 13:33:36 +00:00
|
|
|
func (t *UnionType) String() string {
|
|
|
|
return t.Name()
|
|
|
|
}
|
|
|
|
|
2017-09-04 17:53:05 +00:00
|
|
|
func (t *UnionType) FieldName() string {
|
|
|
|
return t.FldName
|
2015-12-29 14:00:57 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 17:44:26 +00:00
|
|
|
func (t *UnionType) DefaultArg() Arg {
|
|
|
|
return MakeUnionArg(t, t.Fields[0].DefaultArg())
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *UnionType) isDefaultArg(arg Arg) bool {
|
|
|
|
a := arg.(*UnionArg)
|
2018-08-01 19:06:38 +00:00
|
|
|
return a.Option.Type().FieldName() == t.Fields[0].FieldName() && isDefault(a.Option)
|
2018-08-01 17:24:21 +00:00
|
|
|
}
|
|
|
|
|
2017-09-04 17:53:05 +00:00
|
|
|
type StructDesc struct {
|
|
|
|
TypeCommon
|
|
|
|
Fields []Type
|
|
|
|
AlignAttr uint64
|
2015-12-29 14:00:57 +00:00
|
|
|
}
|
|
|
|
|
2017-09-04 17:53:05 +00:00
|
|
|
func (t *StructDesc) FieldName() string {
|
|
|
|
panic("must not be called")
|
|
|
|
}
|
2017-05-26 13:32:51 +00:00
|
|
|
|
2017-08-28 13:59:22 +00:00
|
|
|
type StructKey struct {
|
|
|
|
Name string
|
|
|
|
Dir Dir
|
2017-05-26 13:32:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-04 17:53:05 +00:00
|
|
|
type KeyedStruct struct {
|
|
|
|
Key StructKey
|
|
|
|
Desc *StructDesc
|
2017-05-26 13:32:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-13 17:16:32 +00:00
|
|
|
type ConstValue struct {
|
|
|
|
Name string
|
|
|
|
Value uint64
|
|
|
|
}
|
|
|
|
|
2017-09-05 08:38:22 +00:00
|
|
|
func ForeachType(meta *Syscall, f func(Type)) {
|
2016-10-19 12:41:46 +00:00
|
|
|
var rec func(t Type)
|
2020-04-25 05:40:50 +00:00
|
|
|
seen := make(map[*StructDesc]bool)
|
|
|
|
recStruct := func(desc *StructDesc) {
|
|
|
|
if seen[desc] {
|
|
|
|
return // prune recursion via pointers to structs/unions
|
|
|
|
}
|
|
|
|
seen[desc] = true
|
|
|
|
for _, f := range desc.Fields {
|
|
|
|
rec(f)
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 12:41:46 +00:00
|
|
|
rec = func(t Type) {
|
|
|
|
f(t)
|
|
|
|
switch a := t.(type) {
|
|
|
|
case *PtrType:
|
|
|
|
rec(a.Type)
|
|
|
|
case *ArrayType:
|
|
|
|
rec(a.Type)
|
|
|
|
case *StructType:
|
2020-04-25 05:40:50 +00:00
|
|
|
recStruct(a.StructDesc)
|
2016-10-19 12:41:46 +00:00
|
|
|
case *UnionType:
|
2020-04-25 05:40:50 +00:00
|
|
|
recStruct(a.StructDesc)
|
2016-10-31 21:15:13 +00:00
|
|
|
case *ResourceType, *BufferType, *VmaType, *LenType,
|
2017-01-25 15:18:05 +00:00
|
|
|
*FlagsType, *ConstType, *IntType, *ProcType, *CsumType:
|
2016-10-19 12:41:46 +00:00
|
|
|
default:
|
|
|
|
panic("unknown type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, t := range meta.Args {
|
|
|
|
rec(t)
|
|
|
|
}
|
|
|
|
if meta.Ret != nil {
|
|
|
|
rec(meta.Ret)
|
|
|
|
}
|
|
|
|
}
|
2020-04-16 15:38:36 +00:00
|
|
|
|
|
|
|
// CppName transforms PascalStyleNames to cpp_style_names.
|
|
|
|
func CppName(name string) string {
|
|
|
|
var res []byte
|
|
|
|
for i := range name {
|
|
|
|
c := rune(name[i])
|
|
|
|
if unicode.IsUpper(c) && i != 0 && !unicode.IsUpper(rune(name[i-1])) {
|
|
|
|
res = append(res, '_')
|
|
|
|
}
|
|
|
|
res = append(res, byte(unicode.ToLower(c)))
|
|
|
|
}
|
|
|
|
return string(res)
|
|
|
|
}
|