<commit_before>// Copyright 2015/2016 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 sys

import (
	"fmt"
)

const ptrSize = 8

type Call struct {
	ID       int
	NR       int // kernel syscall number
	CallID   int
	Name     string
	CallName string
	Args     []Type
	Ret      Type
}

type Dir int

const (
	DirIn Dir = iota
	DirOut
	DirInOut
)

type Type interface {
	Name() string
	Dir() Dir
	Optional() bool
	Default() uintptr
	Size() uintptr
	Align() uintptr
	BitfieldOffset() uintptr
	BitfieldLength() uintptr
	BitfieldLast() bool
}

func IsPad(t Type) bool {
	if ct, ok := t.(*ConstType); ok && ct.IsPad {
		return true
	}
	return false
}

type TypeCommon struct {
	TypeName   string
	ArgDir     Dir
	IsOptional bool
}

func (t *TypeCommon) Name() string {
	return t.TypeName
}

func (t *TypeCommon) Optional() bool {
	return t.IsOptional
}

func (t *TypeCommon) Default() uintptr {
	return 0
}

func (t *TypeCommon) BitfieldOffset() uintptr {
	return 0
}

func (t *TypeCommon) BitfieldLength() uintptr {
	return 0
}

func (t *TypeCommon) BitfieldLast() bool {
	return false
}

func (t TypeCommon) Dir() Dir {
	return t.ArgDir
}

const (
	InvalidFD = ^uintptr(0)
)

type ResourceDesc struct {
	Name   string
	Type   Type
	Kind   []string
	Values []uintptr
}

type ResourceType struct {
	TypeCommon
	Desc *ResourceDesc
}

func (t *ResourceType) Default() uintptr {
	return t.Desc.Values[0]
}

func (t *ResourceType) SpecialValues() []uintptr {
	return t.Desc.Values
}

func (t *ResourceType) Size() uintptr {
	return t.Desc.Type.Size()
}

func (t *ResourceType) Align() uintptr {
	return t.Desc.Type.Align()
}

type IntTypeCommon struct {
	TypeCommon
	TypeSize    uintptr
	BigEndian   bool
	BitfieldOff uintptr
	BitfieldLen uintptr
	BitfieldLst bool
}

func (t *IntTypeCommon) Size() uintptr {
	return t.TypeSize
}

func (t *IntTypeCommon) Align() uintptr {
	return t.Size()
}

func (t *IntTypeCommon) BitfieldOffset() uintptr {
	return t.BitfieldOff
}

func (t *IntTypeCommon) BitfieldLength() uintptr {
	return t.BitfieldLen
}

func (t *IntTypeCommon) BitfieldLast() bool {
	return t.BitfieldLst
}

type ConstType struct {
	IntTypeCommon
	Val   uintptr
	IsPad bool
}

type IntKind int

const (
	IntPlain IntKind = iota
	IntSignalno
	IntFileoff // offset within a file
	IntRange
)

type IntType struct {
	IntTypeCommon
	Kind       IntKind
	RangeBegin int64
	RangeEnd   int64
}

type FlagsType struct {
	IntTypeCommon
	Vals []uintptr
}

type LenType struct {
	IntTypeCommon
	ByteSize uintptr // want size in multiple of bytes instead of array size
	Buf      string
}

type ProcType struct {
	IntTypeCommon
	ValuesStart   int64
	ValuesPerProc uint64
}

type VmaType struct {
	TypeCommon
	RangeBegin int64 // in pages
	RangeEnd   int64
}

func (t *VmaType) Size() uintptr {
	return ptrSize
}

func (t *VmaType) Align() uintptr {
	return t.Size()
}

type BufferKind int

const (
	BufferBlobRand BufferKind = iota
	BufferBlobRange
	BufferString
	BufferFilename
	BufferText
)

type TextKind int

const (
	Text_x86_real TextKind = iota
	Text_x86_16
	Text_x86_32
	Text_x86_64
	Text_arm64
)

type BufferType struct {
	TypeCommon
	Kind       BufferKind
	RangeBegin uintptr  // for BufferBlobRange kind
	RangeEnd   uintptr  // for BufferBlobRange kind
	Text       TextKind // for BufferText
	SubKind    string
	Values     []string // possible values for BufferString kind
}

func (t *BufferType) Size() uintptr {
	switch t.Kind {
	case BufferString:
		size := 0
		for _, s := range t.Values {
			if size != 0 && size != len(s) {
				size = 0
				break
			}
			size = len(s)
		}
		if size != 0 {
			return uintptr(size)
		}
	case BufferBlobRange:
		if t.RangeBegin == t.RangeEnd {
			return t.RangeBegin
		}
	}
	panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name()))
}

func (t *BufferType) Align() uintptr {
	return 1
}

type ArrayKind int

const (
	ArrayRandLen ArrayKind = iota
	ArrayRangeLen
)

type ArrayType struct {
	TypeCommon
	Type       Type
	Kind       ArrayKind
	RangeBegin uintptr
	RangeEnd   uintptr
}

func (t *ArrayType) Size() uintptr {
	if t.RangeBegin == t.RangeEnd {
		return t.RangeBegin * t.Type.Size()
	}
	return 0 // for trailing embed arrays
}

func (t *ArrayType) Align() uintptr {
	return t.Type.Align()
}

type PtrType struct {
	TypeCommon
	Type Type
}

func (t *PtrType) Size() uintptr {
	return ptrSize
}

func (t *PtrType) Align() uintptr {
	return t.Size()
}

type StructType struct {
	TypeCommon
	Fields []Type
	padded bool
	packed bool
	align  uintptr
}

func (t *StructType) Size() uintptr {
	if !t.padded {
		panic("struct is not padded yet")
	}
	var size uintptr
	for _, f := range t.Fields {
		size += f.Size()
	}
	return size
}

func (t *StructType) Align() uintptr {
	if t.align != 0 {
		return t.align // overrided by user attribute
	}
	var align uintptr
	for _, f := range t.Fields {
		if a1 := f.Align(); align < a1 {
			align = a1
		}
	}
	return align
}

type UnionType struct {
	TypeCommon
	Options []Type
	varlen  bool<commit_msg>sys: packed structs have align of 1<commit_after>// Copyright 2015/2016 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 sys

import (
	"fmt"
)

const ptrSize = 8

type Call struct {
	ID       int
	NR       int // kernel syscall number
	CallID   int
	Name     string
	CallName string
	Args     []Type
	Ret      Type
}

type Dir int

const (
	DirIn Dir = iota
	DirOut
	DirInOut
)

type Type interface {
	Name() string
	Dir() Dir
	Optional() bool
	Default() uintptr
	Size() uintptr
	Align() uintptr
	BitfieldOffset() uintptr
	BitfieldLength() uintptr
	BitfieldLast() bool
}

func IsPad(t Type) bool {
	if ct, ok := t.(*ConstType); ok && ct.IsPad {
		return true
	}
	return false
}

type TypeCommon struct {
	TypeName   string
	ArgDir     Dir
	IsOptional bool
}

func (t *TypeCommon) Name() string {
	return t.TypeName
}

func (t *TypeCommon) Optional() bool {
	return t.IsOptional
}

func (t *TypeCommon) Default() uintptr {
	return 0
}

func (t *TypeCommon) BitfieldOffset() uintptr {
	return 0
}

func (t *TypeCommon) BitfieldLength() uintptr {
	return 0
}

func (t *TypeCommon) BitfieldLast() bool {
	return false
}

func (t TypeCommon) Dir() Dir {
	return t.ArgDir
}

const (
	InvalidFD = ^uintptr(0)
)

type ResourceDesc struct {
	Name   string
	Type   Type
	Kind   []string
	Values []uintptr
}

type ResourceType struct {
	TypeCommon
	Desc *ResourceDesc
}

func (t *ResourceType) Default() uintptr {
	return t.Desc.Values[0]
}

func (t *ResourceType) SpecialValues() []uintptr {
	return t.Desc.Values
}

func (t *ResourceType) Size() uintptr {
	return t.Desc.Type.Size()
}

func (t *ResourceType) Align() uintptr {
	return t.Desc.Type.Align()
}

type IntTypeCommon struct {
	TypeCommon
	TypeSize    uintptr
	BigEndian   bool
	BitfieldOff uintptr
	BitfieldLen uintptr
	BitfieldLst bool
}

func (t *IntTypeCommon) Size() uintptr {
	return t.TypeSize
}

func (t *IntTypeCommon) Align() uintptr {
	return t.Size()
}

func (t *IntTypeCommon) BitfieldOffset() uintptr {
	return t.BitfieldOff
}

func (t *IntTypeCommon) BitfieldLength() uintptr {
	return t.BitfieldLen
}

func (t *IntTypeCommon) BitfieldLast() bool {
	return t.BitfieldLst
}

type ConstType struct {
	IntTypeCommon
	Val   uintptr
	IsPad bool
}

type IntKind int

const (
	IntPlain IntKind = iota
	IntSignalno
	IntFileoff // offset within a file
	IntRange
)

type IntType struct {
	IntTypeCommon
	Kind       IntKind
	RangeBegin int64
	RangeEnd   int64
}

type FlagsType struct {
	IntTypeCommon
	Vals []uintptr
}

type LenType struct {
	IntTypeCommon
	ByteSize uintptr // want size in multiple of bytes instead of array size
	Buf      string
}

type ProcType struct {
	IntTypeCommon
	ValuesStart   int64
	ValuesPerProc uint64
}

type VmaType struct {
	TypeCommon
	RangeBegin int64 // in pages
	RangeEnd   int64
}

func (t *VmaType) Size() uintptr {
	return ptrSize
}

func (t *VmaType) Align() uintptr {
	return t.Size()
}

type BufferKind int

const (
	BufferBlobRand BufferKind = iota
	BufferBlobRange
	BufferString
	BufferFilename
	BufferText
)

type TextKind int

const (
	Text_x86_real TextKind = iota
	Text_x86_16
	Text_x86_32
	Text_x86_64
	Text_arm64
)

type BufferType struct {
	TypeCommon
	Kind       BufferKind
	RangeBegin uintptr  // for BufferBlobRange kind
	RangeEnd   uintptr  // for BufferBlobRange kind
	Text       TextKind // for BufferText
	SubKind    string
	Values     []string // possible values for BufferString kind
}

func (t *BufferType) Size() uintptr {
	switch t.Kind {
	case BufferString:
		size := 0
		for _, s := range t.Values {
			if size != 0 && size != len(s) {
				size = 0
				break
			}
			size = len(s)
		}
		if size != 0 {
			return uintptr(size)
		}
	case BufferBlobRange:
		if t.RangeBegin == t.RangeEnd {
			return t.RangeBegin
		}
	}
	panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name()))
}

func (t *BufferType) Align() uintptr {
	return 1
}

type ArrayKind int

const (
	ArrayRandLen ArrayKind = iota
	ArrayRangeLen
)

type ArrayType struct {
	TypeCommon
	Type       Type
	Kind       ArrayKind
	RangeBegin uintptr
	RangeEnd   uintptr
}

func (t *ArrayType) Size() uintptr {
	if t.RangeBegin == t.RangeEnd {
		return t.RangeBegin * t.Type.Size()
	}
	return 0 // for trailing embed arrays
}

func (t *ArrayType) Align() uintptr {
	return t.Type.Align()
}

type PtrType struct {
	TypeCommon
	Type Type
}

func (t *PtrType) Size() uintptr {
	return ptrSize
}

func (t *PtrType) Align() uintptr {
	return t.Size()
}

type StructType struct {
	TypeCommon
	Fields []Type
	padded bool
	packed bool
	align  uintptr
}

func (t *StructType) Size() uintptr {
	if !t.padded {
		panic("struct is not padded yet")
	}
	var size uintptr
	for _, f := range t.Fields {
		size += f.Size()
	}
	return size
}

func (t *StructType) Align() uintptr {
	if t.align != 0 {
		return t.align // overrided by user attribute
	}
	if t.packed {
		return 1
	}
	var align uintptr
	for _, f := range t.Fields {
		if a1 := f.Align(); align < a1 {
			align = a1
		}
	}
	return align
}

type UnionType struct {
	TypeCommon
	Options []Type
	varlen  bool
{'fraction_non_alphanumeric': 0.0912376672853375, 'fraction_numerical': 0.010549965810295985, 'mean_word_length': 3.345500848896435, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4062279', 'n_tokens_mistral': 3796, 'n_tokens_neox': 3582, 'n_words': 1173}