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.
|
|
|
|
|
|
|
|
package sys
|
|
|
|
|
2016-01-28 07:20:09 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
const ptrSize = 8
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type Call struct {
|
|
|
|
ID int
|
2015-12-24 13:40:46 +00:00
|
|
|
NR int // kernel syscall number
|
2015-10-12 08:16:57 +00:00
|
|
|
CallID int
|
|
|
|
Name string
|
|
|
|
CallName string
|
|
|
|
Args []Type
|
|
|
|
Ret Type
|
|
|
|
}
|
|
|
|
|
|
|
|
type Type interface {
|
|
|
|
Name() string
|
|
|
|
Optional() bool
|
|
|
|
Default() uintptr
|
2015-12-11 14:42:14 +00:00
|
|
|
Size() uintptr
|
|
|
|
Align() uintptr
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2015-12-28 11:58:10 +00:00
|
|
|
func IsPad(t Type) bool {
|
|
|
|
if ct, ok := t.(ConstType); ok && ct.IsPad {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type TypeCommon struct {
|
|
|
|
TypeName string
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
type (
|
|
|
|
ResourceKind int
|
|
|
|
ResourceSubkind int
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
ResFD ResourceKind = iota
|
|
|
|
ResIOCtx
|
|
|
|
ResIPC
|
|
|
|
ResKey
|
|
|
|
ResInotifyDesc
|
|
|
|
ResPid
|
|
|
|
ResUid
|
|
|
|
ResGid
|
|
|
|
ResTimerid
|
2015-10-13 15:06:01 +00:00
|
|
|
ResIocbPtr
|
2016-01-15 23:23:47 +00:00
|
|
|
ResDrmCtx
|
2015-10-12 08:16:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
ResAny ResourceSubkind = iota
|
|
|
|
FdFile
|
|
|
|
FdSock
|
|
|
|
FdPipe
|
|
|
|
FdSignal
|
|
|
|
FdEvent
|
|
|
|
FdTimer
|
|
|
|
FdEpoll
|
|
|
|
FdDir
|
|
|
|
FdMq
|
|
|
|
FdInotify
|
|
|
|
FdFanotify
|
2015-11-16 18:14:05 +00:00
|
|
|
FdTty
|
2015-11-18 20:22:17 +00:00
|
|
|
FdDRI
|
2015-11-19 16:16:36 +00:00
|
|
|
FdFuse
|
2015-11-19 16:27:23 +00:00
|
|
|
FdKdbus
|
2015-11-29 10:05:08 +00:00
|
|
|
FdBpfMap
|
|
|
|
FdBpfProg
|
2015-11-29 11:19:58 +00:00
|
|
|
FdPerf
|
2015-11-30 15:31:45 +00:00
|
|
|
FdUserFault
|
2015-12-09 15:43:47 +00:00
|
|
|
FdAlg
|
|
|
|
FdAlgConn
|
2015-12-11 18:50:21 +00:00
|
|
|
FdNfcRaw
|
|
|
|
FdNfcLlcp
|
2015-12-16 17:38:50 +00:00
|
|
|
FdBtHci
|
|
|
|
FdBtSco
|
|
|
|
FdBtL2cap
|
|
|
|
FdBtRfcomm
|
|
|
|
FdBtHidp
|
|
|
|
FdBtCmtp
|
|
|
|
FdBtBnep
|
2015-12-28 18:11:03 +00:00
|
|
|
FdUnix
|
2015-12-30 12:04:00 +00:00
|
|
|
FdSctp
|
2016-01-22 23:54:53 +00:00
|
|
|
FdNetlink
|
2016-01-08 21:33:40 +00:00
|
|
|
FdKvm
|
|
|
|
FdKvmVm
|
|
|
|
FdKvmCpu
|
2016-01-11 21:16:14 +00:00
|
|
|
FdSndSeq
|
2016-01-12 19:14:56 +00:00
|
|
|
FdSndTimer
|
2016-01-13 14:20:09 +00:00
|
|
|
FdSndControl
|
2016-01-13 19:45:35 +00:00
|
|
|
FdInputEvent
|
2016-01-25 11:08:04 +00:00
|
|
|
FdTun
|
|
|
|
FdRandom
|
2016-06-10 13:57:19 +00:00
|
|
|
FdKcm
|
|
|
|
FdNetRom
|
2015-10-12 08:16:57 +00:00
|
|
|
|
|
|
|
IPCMsq
|
|
|
|
IPCSem
|
|
|
|
IPCShm
|
|
|
|
)
|
|
|
|
|
2015-12-27 11:20:00 +00:00
|
|
|
func ResourceKinds() []ResourceKind {
|
|
|
|
return []ResourceKind{
|
|
|
|
ResFD,
|
|
|
|
ResIOCtx,
|
|
|
|
ResIPC,
|
|
|
|
ResKey,
|
|
|
|
ResInotifyDesc,
|
|
|
|
ResPid,
|
|
|
|
ResUid,
|
|
|
|
ResGid,
|
|
|
|
ResTimerid,
|
|
|
|
ResIocbPtr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func ResourceSubkinds(kind ResourceKind) []ResourceSubkind {
|
|
|
|
switch kind {
|
|
|
|
case ResFD:
|
|
|
|
return []ResourceSubkind{ResAny, FdFile, FdSock, FdPipe, FdSignal, FdEvent,
|
|
|
|
FdTimer, FdEpoll, FdDir, FdMq, FdInotify, FdFanotify, FdTty,
|
|
|
|
FdDRI, FdFuse, FdKdbus, FdBpfMap, FdBpfProg, FdPerf, FdUserFault,
|
|
|
|
FdAlg, FdAlgConn, FdNfcRaw, FdNfcLlcp, FdBtHci, FdBtSco, FdBtL2cap,
|
2016-01-22 23:54:53 +00:00
|
|
|
FdBtRfcomm, FdBtHidp, FdBtCmtp, FdBtBnep, FdUnix, FdSctp, FdNetlink, FdKvm, FdKvmVm,
|
2016-06-10 13:57:19 +00:00
|
|
|
FdKvmCpu, FdSndSeq, FdSndTimer, FdSndControl, FdInputEvent, FdTun, FdRandom, FdKcm,
|
|
|
|
FdNetRom}
|
2015-12-27 11:20:00 +00:00
|
|
|
case ResIPC:
|
|
|
|
return []ResourceSubkind{IPCMsq, IPCSem, IPCShm}
|
2016-01-15 23:23:47 +00:00
|
|
|
case ResIOCtx, ResKey, ResInotifyDesc, ResPid, ResUid, ResGid, ResTimerid, ResIocbPtr, ResDrmCtx:
|
2015-12-27 11:20:00 +00:00
|
|
|
return []ResourceSubkind{ResAny}
|
|
|
|
default:
|
|
|
|
panic("unknown resource kind")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-30 17:24:26 +00:00
|
|
|
func SocketSubkinds() []ResourceSubkind {
|
|
|
|
return []ResourceSubkind{FdAlg, FdAlgConn, FdNfcRaw, FdNfcLlcp, FdBtHci, FdBtSco,
|
2016-01-22 23:54:53 +00:00
|
|
|
FdBtL2cap, FdBtRfcomm, FdBtHidp, FdBtCmtp, FdBtBnep, FdUnix, FdSctp, FdNetlink}
|
2015-12-30 17:24:26 +00:00
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
const (
|
|
|
|
InvalidFD = ^uintptr(0)
|
|
|
|
BogusFD = uintptr(100000 - 1)
|
|
|
|
)
|
|
|
|
|
|
|
|
type ResourceType struct {
|
|
|
|
TypeCommon
|
|
|
|
Kind ResourceKind
|
|
|
|
Subkind ResourceSubkind
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t ResourceType) Default() uintptr {
|
|
|
|
switch t.Kind {
|
|
|
|
case ResFD:
|
|
|
|
return InvalidFD
|
|
|
|
case ResIOCtx:
|
|
|
|
return 0
|
|
|
|
case ResIPC:
|
|
|
|
return 0
|
|
|
|
case ResKey:
|
|
|
|
return 0
|
|
|
|
case ResInotifyDesc:
|
|
|
|
return 0
|
|
|
|
case ResPid:
|
|
|
|
return 0
|
|
|
|
case ResUid:
|
|
|
|
return 0
|
|
|
|
case ResGid:
|
|
|
|
return 0
|
|
|
|
case ResTimerid:
|
|
|
|
return 0
|
2016-01-15 23:23:47 +00:00
|
|
|
case ResDrmCtx:
|
|
|
|
return 0
|
2015-10-12 08:16:57 +00:00
|
|
|
default:
|
|
|
|
panic("unknown resource type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t ResourceType) SpecialValues() []uintptr {
|
|
|
|
switch t.Kind {
|
|
|
|
case ResFD:
|
2016-08-26 05:09:25 +00:00
|
|
|
return []uintptr{InvalidFD, BogusFD, AT_FDCWD}
|
2015-10-12 08:16:57 +00:00
|
|
|
case ResIOCtx:
|
|
|
|
return []uintptr{0}
|
|
|
|
case ResIPC:
|
|
|
|
return []uintptr{0, ^uintptr(0)}
|
|
|
|
case ResKey:
|
2015-11-06 20:15:31 +00:00
|
|
|
// KEY_SPEC_THREAD_KEYRING values
|
2015-11-29 10:05:08 +00:00
|
|
|
return []uintptr{0, ^uintptr(0), ^uintptr(0) - 1, ^uintptr(0) - 2, ^uintptr(0) - 3,
|
|
|
|
^uintptr(0) - 4, ^uintptr(0) - 5, ^uintptr(0) - 6, ^uintptr(0) - 7}
|
2015-10-12 08:16:57 +00:00
|
|
|
case ResInotifyDesc:
|
|
|
|
return []uintptr{0}
|
|
|
|
case ResPid:
|
|
|
|
return []uintptr{0, ^uintptr(0)}
|
|
|
|
case ResUid:
|
|
|
|
return []uintptr{0, ^uintptr(0)}
|
|
|
|
case ResGid:
|
|
|
|
return []uintptr{0, ^uintptr(0)}
|
|
|
|
case ResTimerid:
|
|
|
|
return []uintptr{0}
|
2016-01-15 23:23:47 +00:00
|
|
|
case ResDrmCtx:
|
|
|
|
return []uintptr{0}
|
2015-10-12 08:16:57 +00:00
|
|
|
default:
|
|
|
|
panic("unknown resource kind")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t ResourceType) Size() uintptr {
|
|
|
|
switch t.Kind {
|
|
|
|
case ResFD:
|
|
|
|
return 4
|
|
|
|
case ResIOCtx:
|
|
|
|
return 8
|
|
|
|
case ResIPC:
|
|
|
|
return 4
|
|
|
|
case ResKey:
|
|
|
|
return 4
|
|
|
|
case ResInotifyDesc:
|
|
|
|
return 4
|
|
|
|
case ResPid:
|
|
|
|
return 4
|
|
|
|
case ResUid:
|
|
|
|
return 4
|
|
|
|
case ResGid:
|
|
|
|
return 4
|
|
|
|
case ResTimerid:
|
|
|
|
return 4
|
2016-01-15 23:23:47 +00:00
|
|
|
case ResDrmCtx:
|
|
|
|
return 4
|
2015-10-12 08:16:57 +00:00
|
|
|
default:
|
|
|
|
panic("unknown resource kind")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t ResourceType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
func (t ResourceType) SubKinds() []ResourceSubkind {
|
2015-12-27 11:20:00 +00:00
|
|
|
return ResourceSubkinds(t.Kind)
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type FileoffType struct {
|
|
|
|
TypeCommon
|
|
|
|
TypeSize uintptr
|
|
|
|
File string
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t FileoffType) Size() uintptr {
|
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t FileoffType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type BufferKind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
BufferBlob BufferKind = iota
|
|
|
|
BufferString
|
|
|
|
BufferSockaddr
|
2015-10-15 15:58:37 +00:00
|
|
|
BufferFilesystem
|
2015-12-09 15:43:47 +00:00
|
|
|
BufferAlgType
|
|
|
|
BufferAlgName
|
2015-10-12 08:16:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type BufferType struct {
|
|
|
|
TypeCommon
|
|
|
|
Kind BufferKind
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t BufferType) Size() uintptr {
|
|
|
|
switch t.Kind {
|
|
|
|
case BufferAlgType:
|
|
|
|
return 14
|
|
|
|
case BufferAlgName:
|
|
|
|
return 64
|
|
|
|
default:
|
2016-01-28 07:20:09 +00:00
|
|
|
panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name()))
|
2015-12-11 14:42:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t BufferType) Align() uintptr {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type VmaType struct {
|
|
|
|
TypeCommon
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t VmaType) Size() uintptr {
|
|
|
|
return ptrSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t VmaType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type LenType struct {
|
|
|
|
TypeCommon
|
|
|
|
TypeSize uintptr
|
2016-01-22 23:37:08 +00:00
|
|
|
ByteSize bool // want size in bytes instead of array size
|
2015-10-12 08:16:57 +00:00
|
|
|
Buf string
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t LenType) Size() uintptr {
|
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t LenType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type FlagsType struct {
|
|
|
|
TypeCommon
|
|
|
|
TypeSize uintptr
|
|
|
|
Vals []uintptr
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t FlagsType) Size() uintptr {
|
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t FlagsType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-16 16:16:10 +00:00
|
|
|
type ConstType struct {
|
|
|
|
TypeCommon
|
|
|
|
TypeSize uintptr
|
|
|
|
Val uintptr
|
2015-12-28 11:58:10 +00:00
|
|
|
IsPad bool
|
2015-10-16 16:16:10 +00:00
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t ConstType) Size() uintptr {
|
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t ConstType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-11-16 18:14:05 +00:00
|
|
|
type StrConstType struct {
|
|
|
|
TypeCommon
|
|
|
|
TypeSize uintptr
|
|
|
|
Val string
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t StrConstType) Size() uintptr {
|
|
|
|
return ptrSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t StrConstType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-13 18:10:22 +00:00
|
|
|
type IntKind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
IntPlain IntKind = iota
|
|
|
|
IntSignalno
|
|
|
|
IntInaddr
|
2015-12-30 12:04:00 +00:00
|
|
|
IntInport
|
2016-08-08 13:32:48 +00:00
|
|
|
IntRange
|
2015-10-13 18:10:22 +00:00
|
|
|
)
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type IntType struct {
|
|
|
|
TypeCommon
|
2016-08-13 16:02:44 +00:00
|
|
|
TypeSize uintptr
|
|
|
|
Kind IntKind
|
2016-08-08 13:32:48 +00:00
|
|
|
RangeBegin int64
|
2016-08-13 16:02:44 +00:00
|
|
|
RangeEnd int64
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t IntType) Size() uintptr {
|
|
|
|
return t.TypeSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t IntType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type FilenameType struct {
|
|
|
|
TypeCommon
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t FilenameType) Size() uintptr {
|
|
|
|
panic("filename size is not statically known")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t FilenameType) Align() uintptr {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type ArrayType struct {
|
|
|
|
TypeCommon
|
|
|
|
Type Type
|
2015-12-16 17:38:50 +00:00
|
|
|
Len uintptr // 0 if variable-length, unused for now
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t ArrayType) Size() uintptr {
|
2015-12-16 18:17:46 +00:00
|
|
|
if t.Len == 0 {
|
|
|
|
return 0 // for trailing embed arrays
|
|
|
|
}
|
|
|
|
return t.Len * t.Type.Size()
|
2015-12-11 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t ArrayType) Align() uintptr {
|
|
|
|
return t.Type.Align()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type PtrType struct {
|
|
|
|
TypeCommon
|
|
|
|
Type Type
|
|
|
|
Dir Dir
|
|
|
|
}
|
|
|
|
|
2015-12-11 14:42:14 +00:00
|
|
|
func (t PtrType) Size() uintptr {
|
|
|
|
return ptrSize
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t PtrType) Align() uintptr {
|
|
|
|
return t.Size()
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type StructType struct {
|
|
|
|
TypeCommon
|
|
|
|
Fields []Type
|
2015-12-11 14:42:14 +00:00
|
|
|
padded bool
|
2015-12-30 12:53:09 +00:00
|
|
|
packed bool
|
|
|
|
align uintptr
|
2015-12-11 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2015-12-30 12:53:09 +00:00
|
|
|
if t.align != 0 {
|
|
|
|
return t.align // overrided by user attribute
|
|
|
|
}
|
2015-12-11 14:42:14 +00:00
|
|
|
var align uintptr
|
|
|
|
for _, f := range t.Fields {
|
|
|
|
if a1 := f.Align(); align < a1 {
|
|
|
|
align = a1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return align
|
2015-10-12 08:16:57 +00:00
|
|
|
}
|
|
|
|
|
2015-12-29 14:00:57 +00:00
|
|
|
type UnionType struct {
|
|
|
|
TypeCommon
|
|
|
|
Options []Type
|
2016-01-11 21:16:14 +00:00
|
|
|
varlen bool
|
2015-12-29 14:00:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t UnionType) Size() uintptr {
|
2016-01-11 21:16:14 +00:00
|
|
|
if t.varlen {
|
|
|
|
panic("union size is not statically known")
|
|
|
|
}
|
2015-12-31 14:44:06 +00:00
|
|
|
size := t.Options[0].Size()
|
|
|
|
for _, opt := range t.Options {
|
2016-01-11 21:16:14 +00:00
|
|
|
if size < opt.Size() {
|
|
|
|
size = opt.Size()
|
2015-12-31 14:44:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return size
|
2015-12-29 14:00:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t UnionType) Align() uintptr {
|
|
|
|
var align uintptr
|
|
|
|
for _, opt := range t.Options {
|
|
|
|
if a1 := opt.Align(); align < a1 {
|
|
|
|
align = a1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return align
|
|
|
|
}
|
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
type Dir int
|
|
|
|
|
|
|
|
const (
|
|
|
|
DirIn Dir = iota
|
|
|
|
DirOut
|
|
|
|
DirInOut
|
|
|
|
)
|
|
|
|
|
2015-12-27 11:20:00 +00:00
|
|
|
var ctors = make(map[ResourceKind]map[ResourceSubkind][]*Call)
|
|
|
|
|
|
|
|
// ResourceConstructors returns a list of calls that can create a resource of the given kind/subkind.
|
|
|
|
func ResourceConstructors(kind ResourceKind, sk ResourceSubkind) []*Call {
|
|
|
|
return ctors[kind][sk]
|
|
|
|
}
|
|
|
|
|
|
|
|
func initResources() {
|
|
|
|
for _, kind := range ResourceKinds() {
|
|
|
|
ctors[kind] = make(map[ResourceSubkind][]*Call)
|
|
|
|
for _, sk := range ResourceSubkinds(kind) {
|
|
|
|
ctors[kind][sk] = ResourceCtors(kind, sk, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func ResourceCtors(kind ResourceKind, sk ResourceSubkind, precise bool) []*Call {
|
|
|
|
// 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.
|
|
|
|
var checkArg func(typ Type, dir Dir) bool
|
|
|
|
checkArg = func(typ Type, dir Dir) bool {
|
|
|
|
if resarg, ok := typ.(ResourceType); ok && dir != DirIn && resarg.Kind == kind &&
|
|
|
|
(sk == resarg.Subkind || sk == ResAny || (resarg.Subkind == ResAny && !precise)) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
switch typ1 := typ.(type) {
|
|
|
|
case ArrayType:
|
|
|
|
if checkArg(typ1.Type, dir) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
case StructType:
|
|
|
|
for _, fld := range typ1.Fields {
|
|
|
|
if checkArg(fld, dir) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2015-12-29 14:00:57 +00:00
|
|
|
case UnionType:
|
|
|
|
for _, opt := range typ1.Options {
|
|
|
|
if checkArg(opt, dir) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2015-12-27 11:20:00 +00:00
|
|
|
case PtrType:
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Call) InputResources() []ResourceType {
|
|
|
|
var resources []ResourceType
|
|
|
|
var checkArg func(typ Type, dir Dir)
|
|
|
|
checkArg = func(typ Type, dir Dir) {
|
|
|
|
switch typ1 := typ.(type) {
|
|
|
|
case ResourceType:
|
|
|
|
if dir != DirOut && !typ1.IsOptional {
|
|
|
|
resources = append(resources, typ1)
|
|
|
|
}
|
|
|
|
case ArrayType:
|
|
|
|
checkArg(typ1.Type, dir)
|
|
|
|
case PtrType:
|
|
|
|
checkArg(typ1.Type, typ1.Dir)
|
|
|
|
case StructType:
|
|
|
|
for _, fld := range typ1.Fields {
|
|
|
|
checkArg(fld, dir)
|
|
|
|
}
|
2015-12-29 14:00:57 +00:00
|
|
|
case UnionType:
|
|
|
|
for _, opt := range typ1.Options {
|
|
|
|
checkArg(opt, dir)
|
|
|
|
}
|
2015-12-27 11:20:00 +00: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
|
|
|
|
for _, ctor := range ResourceCtors(res.Kind, res.Subkind, true) {
|
|
|
|
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 08:16:57 +00:00
|
|
|
var (
|
|
|
|
CallCount int
|
|
|
|
CallMap = make(map[string]*Call)
|
|
|
|
CallID = make(map[string]int)
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2015-12-11 18:37:18 +00:00
|
|
|
initCalls()
|
2015-12-27 11:20:00 +00:00
|
|
|
initResources()
|
2015-12-31 14:44:06 +00:00
|
|
|
initAlign()
|
2015-12-24 13:40:46 +00:00
|
|
|
|
2015-10-12 08:16:57 +00:00
|
|
|
for _, c := range Calls {
|
|
|
|
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)
|
|
|
|
}
|