2016-08-08 21:32:48 +08:00
|
|
|
// Copyright 2015/2016 syzkaller project authors. All rights reserved.
|
2015-10-12 10:16:57 +02:00
|
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package sys
|
|
|
|
|
2016-01-28 08:20:09 +01:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
2015-12-11 15:42:14 +01:00
|
|
|
const ptrSize = 8
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type Call struct {
|
|
|
|
ID int
|
2015-12-24 14:40:46 +01:00
|
|
|
NR int // kernel syscall number
|
2015-10-12 10:16:57 +02:00
|
|
|
CallID int
|
|
|
|
Name string
|
|
|
|
CallName string
|
|
|
|
Args []Type
|
|
|
|
Ret Type
|
|
|
|
}
|
|
|
|
|
|
|
|
type Type interface {
|
|
|
|
Name() string
|
|
|
|
Optional() bool
|
|
|
|
Default() uintptr
|
2015-12-11 15:42:14 +01:00
|
|
|
Size() uintptr
|
|
|
|
Align() uintptr
|
2016-10-11 14:24:25 +02:00
|
|
|
InnerType() Type // returns inner type for PtrType
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2015-12-28 12:58:10 +01:00
|
|
|
func IsPad(t Type) bool {
|
2016-10-19 16:20:37 +02:00
|
|
|
if ct, ok := t.(*ConstType); ok && ct.IsPad {
|
2015-12-28 12:58:10 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type TypeCommon struct {
|
|
|
|
TypeName string
|
|
|
|
IsOptional bool
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *TypeCommon) Name() string {
|
2015-10-12 10:16:57 +02:00
|
|
|
return t.TypeName
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *TypeCommon) Optional() bool {
|
2015-10-12 10:16:57 +02:00
|
|
|
return t.IsOptional
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *TypeCommon) Default() uintptr {
|
2015-10-12 10:16:57 +02:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2016-08-27 18:27:50 +02:00
|
|
|
InvalidFD = ^uintptr(0)
|
2015-10-12 10:16:57 +02:00
|
|
|
)
|
|
|
|
|
2016-08-27 18:27:50 +02:00
|
|
|
type ResourceDesc struct {
|
|
|
|
Name string
|
|
|
|
Type Type
|
|
|
|
Kind []string
|
|
|
|
Values []uintptr
|
2015-12-27 12:20:00 +01:00
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type ResourceType struct {
|
|
|
|
TypeCommon
|
2016-08-27 18:27:50 +02:00
|
|
|
Desc *ResourceDesc
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ResourceType) Default() uintptr {
|
2016-08-27 18:27:50 +02:00
|
|
|
return t.Desc.Values[0]
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ResourceType) SpecialValues() []uintptr {
|
2016-08-27 18:27:50 +02:00
|
|
|
return t.Desc.Values
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ResourceType) Size() uintptr {
|
2016-08-27 18:27:50 +02:00
|
|
|
return t.Desc.Type.Size()
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ResourceType) Align() uintptr {
|
2016-08-27 18:27:50 +02:00
|
|
|
return t.Desc.Type.Align()
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ResourceType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type FileoffType struct {
|
|
|
|
TypeCommon
|
2016-10-11 21:01:06 +02:00
|
|
|
TypeSize uintptr
|
|
|
|
BigEndian bool
|
|
|
|
File string
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FileoffType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FileoffType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FileoffType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type BufferKind int
|
|
|
|
|
|
|
|
const (
|
2016-09-21 16:52:55 +02:00
|
|
|
BufferBlobRand BufferKind = iota
|
|
|
|
BufferBlobRange
|
2015-10-12 10:16:57 +02:00
|
|
|
BufferString
|
|
|
|
BufferSockaddr
|
2015-10-15 17:58:37 +02:00
|
|
|
BufferFilesystem
|
2015-12-09 16:43:47 +01:00
|
|
|
BufferAlgType
|
|
|
|
BufferAlgName
|
2015-10-12 10:16:57 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type BufferType struct {
|
|
|
|
TypeCommon
|
2016-09-21 16:52:55 +02:00
|
|
|
Kind BufferKind
|
|
|
|
RangeBegin uintptr // for BufferBlobRange kind
|
|
|
|
RangeEnd uintptr // for BufferBlobRange kind
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *BufferType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
switch t.Kind {
|
|
|
|
case BufferAlgType:
|
|
|
|
return 14
|
|
|
|
case BufferAlgName:
|
|
|
|
return 64
|
2016-09-21 16:52:55 +02:00
|
|
|
case BufferBlobRange:
|
|
|
|
if t.RangeBegin == t.RangeEnd {
|
|
|
|
return t.RangeBegin
|
|
|
|
}
|
|
|
|
fallthrough
|
2015-12-11 15:42:14 +01:00
|
|
|
default:
|
2016-01-28 08:20:09 +01:00
|
|
|
panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name()))
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *BufferType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *BufferType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type VmaType struct {
|
|
|
|
TypeCommon
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *VmaType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return ptrSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *VmaType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *VmaType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type LenType struct {
|
|
|
|
TypeCommon
|
2016-10-11 21:01:06 +02:00
|
|
|
TypeSize uintptr
|
|
|
|
BigEndian bool
|
|
|
|
ByteSize bool // want size in bytes instead of array size
|
|
|
|
Buf string
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *LenType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *LenType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *LenType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type FlagsType struct {
|
|
|
|
TypeCommon
|
2016-10-11 21:01:06 +02:00
|
|
|
TypeSize uintptr
|
|
|
|
BigEndian bool
|
|
|
|
Vals []uintptr
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FlagsType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FlagsType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FlagsType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-16 18:16:10 +02:00
|
|
|
type ConstType struct {
|
|
|
|
TypeCommon
|
2016-10-11 21:01:06 +02:00
|
|
|
TypeSize uintptr
|
|
|
|
BigEndian bool
|
|
|
|
Val uintptr
|
|
|
|
IsPad bool
|
2015-10-16 18:16:10 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ConstType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ConstType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ConstType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-11-16 19:14:05 +01:00
|
|
|
type StrConstType struct {
|
|
|
|
TypeCommon
|
|
|
|
TypeSize uintptr
|
|
|
|
Val string
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *StrConstType) Size() uintptr {
|
2016-10-18 21:17:29 +02:00
|
|
|
return uintptr(len(t.Val))
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *StrConstType) Align() uintptr {
|
2016-10-18 21:17:29 +02:00
|
|
|
return 1
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *StrConstType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-13 20:10:22 +02:00
|
|
|
type IntKind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
IntPlain IntKind = iota
|
|
|
|
IntSignalno
|
|
|
|
IntInaddr
|
2015-12-30 13:04:00 +01:00
|
|
|
IntInport
|
2016-08-08 21:32:48 +08:00
|
|
|
IntRange
|
2015-10-13 20:10:22 +02:00
|
|
|
)
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type IntType struct {
|
|
|
|
TypeCommon
|
2016-08-13 09:02:44 -07:00
|
|
|
TypeSize uintptr
|
2016-10-11 21:01:06 +02:00
|
|
|
BigEndian bool
|
2016-08-13 09:02:44 -07:00
|
|
|
Kind IntKind
|
2016-08-08 21:32:48 +08:00
|
|
|
RangeBegin int64
|
2016-08-13 09:02:44 -07:00
|
|
|
RangeEnd int64
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *IntType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *IntType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *IntType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type FilenameType struct {
|
|
|
|
TypeCommon
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FilenameType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
panic("filename size is not statically known")
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FilenameType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *FilenameType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2016-09-15 13:45:06 +02:00
|
|
|
type ArrayKind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
ArrayRandLen ArrayKind = iota
|
|
|
|
ArrayRangeLen
|
|
|
|
)
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type ArrayType struct {
|
|
|
|
TypeCommon
|
2016-09-15 13:45:06 +02:00
|
|
|
Type Type
|
|
|
|
Kind ArrayKind
|
|
|
|
RangeBegin uintptr
|
|
|
|
RangeEnd uintptr
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ArrayType) Size() uintptr {
|
2016-09-29 13:28:03 +02:00
|
|
|
if t.RangeBegin == t.RangeEnd {
|
|
|
|
return t.RangeBegin * t.Type.Size()
|
|
|
|
}
|
|
|
|
return 0 // for trailing embed arrays
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ArrayType) Align() uintptr {
|
2016-09-29 13:28:03 +02:00
|
|
|
return t.Type.Align()
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *ArrayType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type PtrType struct {
|
|
|
|
TypeCommon
|
|
|
|
Type Type
|
|
|
|
Dir Dir
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *PtrType) Size() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return ptrSize
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *PtrType) Align() uintptr {
|
2015-12-11 15:42:14 +01:00
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (t *PtrType) InnerType() Type {
|
2016-10-11 14:24:25 +02:00
|
|
|
return t.Type.InnerType()
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type StructType struct {
|
|
|
|
TypeCommon
|
|
|
|
Fields []Type
|
2015-12-11 15:42:14 +01:00
|
|
|
padded bool
|
2015-12-30 13:53:09 +01:00
|
|
|
packed bool
|
|
|
|
align uintptr
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
|
2016-09-03 12:36:49 +02:00
|
|
|
func (t *StructType) Size() uintptr {
|
2016-09-29 13:28:03 +02:00
|
|
|
if !t.padded {
|
|
|
|
panic("struct is not padded yet")
|
|
|
|
}
|
|
|
|
var size uintptr
|
|
|
|
for _, f := range t.Fields {
|
|
|
|
size += f.Size()
|
|
|
|
}
|
|
|
|
return size
|
2015-12-11 15:42:14 +01:00
|
|
|
}
|
|
|
|
|
2016-09-03 12:36:49 +02:00
|
|
|
func (t *StructType) Align() uintptr {
|
2016-09-29 13:28:03 +02:00
|
|
|
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
|
2015-10-12 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2016-10-11 14:24:25 +02:00
|
|
|
func (t *StructType) InnerType() Type {
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-12-29 15:00:57 +01:00
|
|
|
type UnionType struct {
|
|
|
|
TypeCommon
|
|
|
|
Options []Type
|
2016-01-11 22:16:14 +01:00
|
|
|
varlen bool
|
2015-12-29 15:00:57 +01:00
|
|
|
}
|
|
|
|
|
2016-09-03 12:36:49 +02:00
|
|
|
func (t *UnionType) Size() uintptr {
|
2016-09-29 13:28:03 +02:00
|
|
|
if t.varlen {
|
|
|
|
panic("union size is not statically known")
|
|
|
|
}
|
|
|
|
size := t.Options[0].Size()
|
|
|
|
for _, opt := range t.Options {
|
|
|
|
if size < opt.Size() {
|
|
|
|
size = opt.Size()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return size
|
2015-12-29 15:00:57 +01:00
|
|
|
}
|
|
|
|
|
2016-09-03 12:36:49 +02:00
|
|
|
func (t *UnionType) Align() uintptr {
|
2016-09-29 13:28:03 +02:00
|
|
|
var align uintptr
|
|
|
|
for _, opt := range t.Options {
|
|
|
|
if a1 := opt.Align(); align < a1 {
|
|
|
|
align = a1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return align
|
2015-12-29 15:00:57 +01:00
|
|
|
}
|
|
|
|
|
2016-10-11 14:24:25 +02:00
|
|
|
func (t *UnionType) InnerType() Type {
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
type Dir int
|
|
|
|
|
|
|
|
const (
|
|
|
|
DirIn Dir = iota
|
|
|
|
DirOut
|
|
|
|
DirInOut
|
|
|
|
)
|
|
|
|
|
2016-08-27 18:27:50 +02:00
|
|
|
var ctors = make(map[string][]*Call)
|
2015-12-27 12:20:00 +01:00
|
|
|
|
2016-08-27 18:27:50 +02:00
|
|
|
// ResourceConstructors returns a list of calls that can create a resource of the given kind.
|
|
|
|
func ResourceConstructors(name string) []*Call {
|
|
|
|
return ctors[name]
|
2015-12-27 12:20:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func initResources() {
|
2016-08-27 18:27:50 +02:00
|
|
|
for name, res := range Resources {
|
|
|
|
ctors[name] = resourceCtors(res.Kind, false)
|
2015-12-27 12:20:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-27 18:27:50 +02:00
|
|
|
func resourceCtors(kind []string, precise bool) []*Call {
|
2015-12-27 12:20:00 +01:00
|
|
|
// Find calls that produce the necessary resources.
|
|
|
|
var metas []*Call
|
|
|
|
// Recurse into arguments to see if there is an out/inout arg of necessary type.
|
2016-09-03 12:36:49 +02:00
|
|
|
seen := make(map[Type]bool)
|
2015-12-27 12:20:00 +01:00
|
|
|
var checkArg func(typ Type, dir Dir) bool
|
|
|
|
checkArg = func(typ Type, dir Dir) bool {
|
2016-10-19 16:20:37 +02:00
|
|
|
if resarg, ok := typ.(*ResourceType); ok && dir != DirIn && isCompatibleResource(kind, resarg.Desc.Kind, precise) {
|
2015-12-27 12:20:00 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
switch typ1 := typ.(type) {
|
2016-10-19 16:20:37 +02:00
|
|
|
case *ArrayType:
|
2015-12-27 12:20:00 +01:00
|
|
|
if checkArg(typ1.Type, dir) {
|
|
|
|
return true
|
|
|
|
}
|
2016-09-03 12:36:49 +02:00
|
|
|
case *StructType:
|
|
|
|
if seen[typ1] {
|
|
|
|
return false // prune recursion via pointers to structs/unions
|
|
|
|
}
|
|
|
|
seen[typ1] = true
|
2015-12-27 12:20:00 +01:00
|
|
|
for _, fld := range typ1.Fields {
|
|
|
|
if checkArg(fld, dir) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2016-09-03 12:36:49 +02:00
|
|
|
case *UnionType:
|
|
|
|
if seen[typ1] {
|
|
|
|
return false // prune recursion via pointers to structs/unions
|
|
|
|
}
|
|
|
|
seen[typ1] = true
|
2015-12-29 15:00:57 +01:00
|
|
|
for _, opt := range typ1.Options {
|
|
|
|
if checkArg(opt, dir) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 16:20:37 +02:00
|
|
|
case *PtrType:
|
2015-12-27 12:20:00 +01:00
|
|
|
if checkArg(typ1.Type, typ1.Dir) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, meta := range Calls {
|
|
|
|
ok := false
|
|
|
|
for _, arg := range meta.Args {
|
|
|
|
if checkArg(arg, DirIn) {
|
|
|
|
ok = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !ok && meta.Ret != nil && checkArg(meta.Ret, DirOut) {
|
|
|
|
ok = true
|
|
|
|
}
|
|
|
|
if ok {
|
|
|
|
metas = append(metas, meta)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return metas
|
|
|
|
}
|
|
|
|
|
2016-08-27 18:27:50 +02:00
|
|
|
// IsCompatibleResource returns true if resource of kind src can be passed as an argument of kind dst.
|
|
|
|
func IsCompatibleResource(dst, src string) bool {
|
|
|
|
dstRes := Resources[dst]
|
|
|
|
if dstRes == nil {
|
|
|
|
panic(fmt.Sprintf("unknown resource '%v'", dst))
|
|
|
|
}
|
|
|
|
srcRes := Resources[src]
|
|
|
|
if srcRes == nil {
|
|
|
|
panic(fmt.Sprintf("unknown resource '%v'", src))
|
|
|
|
}
|
|
|
|
return isCompatibleResource(dstRes.Kind, srcRes.Kind, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
// isCompatibleResource returns true if resource of kind src can be passed as an argument of kind dst.
|
|
|
|
// If precise is true, then it does not allow passing a less specialized resource (e.g. fd)
|
|
|
|
// as a more specialized resource (e.g. socket). Otherwise it does.
|
|
|
|
func isCompatibleResource(dst, src []string, precise bool) bool {
|
|
|
|
if len(dst) > len(src) {
|
|
|
|
// dst is more specialized, e.g dst=socket, src=fd.
|
|
|
|
if precise {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
dst = dst[:len(src)]
|
|
|
|
}
|
|
|
|
if len(src) > len(dst) {
|
|
|
|
// src is more specialized, e.g dst=fd, src=socket.
|
|
|
|
src = src[:len(dst)]
|
|
|
|
}
|
|
|
|
for i, k := range dst {
|
|
|
|
if k != src[i] {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2016-10-19 16:20:37 +02:00
|
|
|
func (c *Call) InputResources() []*ResourceType {
|
|
|
|
var resources []*ResourceType
|
2016-09-03 12:36:49 +02:00
|
|
|
seen := make(map[Type]bool)
|
2015-12-27 12:20:00 +01:00
|
|
|
var checkArg func(typ Type, dir Dir)
|
|
|
|
checkArg = func(typ Type, dir Dir) {
|
|
|
|
switch typ1 := typ.(type) {
|
2016-10-19 16:20:37 +02:00
|
|
|
case *ResourceType:
|
2015-12-27 12:20:00 +01:00
|
|
|
if dir != DirOut && !typ1.IsOptional {
|
|
|
|
resources = append(resources, typ1)
|
|
|
|
}
|
2016-10-19 16:20:37 +02:00
|
|
|
case *ArrayType:
|
2015-12-27 12:20:00 +01:00
|
|
|
checkArg(typ1.Type, dir)
|
2016-10-19 16:20:37 +02:00
|
|
|
case *PtrType:
|
2015-12-27 12:20:00 +01:00
|
|
|
checkArg(typ1.Type, typ1.Dir)
|
2016-09-03 12:36:49 +02:00
|
|
|
case *StructType:
|
|
|
|
if seen[typ1] {
|
|
|
|
return // prune recursion via pointers to structs/unions
|
|
|
|
}
|
|
|
|
seen[typ1] = true
|
2015-12-27 12:20:00 +01:00
|
|
|
for _, fld := range typ1.Fields {
|
|
|
|
checkArg(fld, dir)
|
|
|
|
}
|
2016-09-03 12:36:49 +02:00
|
|
|
case *UnionType:
|
|
|
|
if seen[typ1] {
|
|
|
|
return // prune recursion via pointers to structs/unions
|
|
|
|
}
|
|
|
|
seen[typ1] = true
|
2015-12-29 15:00:57 +01:00
|
|
|
for _, opt := range typ1.Options {
|
|
|
|
checkArg(opt, dir)
|
|
|
|
}
|
2015-12-27 12:20:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, arg := range c.Args {
|
|
|
|
checkArg(arg, DirIn)
|
|
|
|
}
|
|
|
|
return resources
|
|
|
|
}
|
|
|
|
|
|
|
|
func TransitivelyEnabledCalls(enabled map[*Call]bool) map[*Call]bool {
|
|
|
|
supported := make(map[*Call]bool)
|
|
|
|
for c := range enabled {
|
|
|
|
supported[c] = true
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
n := len(supported)
|
|
|
|
for c := range enabled {
|
|
|
|
if !supported[c] {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
canCreate := true
|
|
|
|
for _, res := range c.InputResources() {
|
|
|
|
noctors := true
|
2016-08-27 18:27:50 +02:00
|
|
|
for _, ctor := range resourceCtors(res.Desc.Kind, true) {
|
2015-12-27 12:20:00 +01:00
|
|
|
if supported[ctor] {
|
|
|
|
noctors = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if noctors {
|
|
|
|
canCreate = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !canCreate {
|
|
|
|
delete(supported, c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if n == len(supported) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return supported
|
|
|
|
}
|
|
|
|
|
2015-10-12 10:16:57 +02:00
|
|
|
var (
|
2016-08-27 18:27:50 +02:00
|
|
|
Calls []*Call
|
2015-10-12 10:16:57 +02:00
|
|
|
CallCount int
|
|
|
|
CallMap = make(map[string]*Call)
|
|
|
|
CallID = make(map[string]int)
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2015-12-11 19:37:18 +01:00
|
|
|
initCalls()
|
2016-09-29 13:28:03 +02:00
|
|
|
initStructFields()
|
2015-12-27 12:20:00 +01:00
|
|
|
initResources()
|
2015-12-31 15:44:06 +01:00
|
|
|
initAlign()
|
2015-12-24 14:40:46 +01:00
|
|
|
|
2016-08-26 12:51:25 +02:00
|
|
|
for i, c := range Calls {
|
|
|
|
c.ID = i
|
2015-10-12 10:16:57 +02:00
|
|
|
if CallMap[c.Name] != nil {
|
|
|
|
println(c.Name)
|
|
|
|
panic("duplicate syscall")
|
|
|
|
}
|
|
|
|
id, ok := CallID[c.CallName]
|
|
|
|
if !ok {
|
|
|
|
id = len(CallID)
|
|
|
|
CallID[c.CallName] = id
|
|
|
|
}
|
|
|
|
c.CallID = id
|
|
|
|
CallMap[c.Name] = c
|
|
|
|
}
|
|
|
|
CallCount = len(CallID)
|
|
|
|
}
|