mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-23 11:29:46 +00:00
prog, sys: move types to prog
Large overhaul moves syscalls and arg types from sys to prog. Sys package now depends on prog and contains only generated descriptions of syscalls. Introduce prog.Target type that encapsulates all targer properties, like syscall list, ptr/page size, etc. Also moves OS-dependent pieces like mmap call generation from prog to sys. Update #191
This commit is contained in:
parent
4fc4702694
commit
ffe7e17368
@ -9,7 +9,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/syzkaller/pkg/ast"
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
func (comp *compiler) check() {
|
||||
@ -191,7 +191,7 @@ func (comp *compiler) checkLenType(t *ast.Type, name string, fields []*ast.Field
|
||||
}
|
||||
return
|
||||
}
|
||||
_, args, _ := comp.getArgsBase(t, "", sys.DirIn, isArg)
|
||||
_, args, _ := comp.getArgsBase(t, "", prog.DirIn, isArg)
|
||||
for i, arg := range args {
|
||||
argDesc := desc.Args[i]
|
||||
if argDesc.Type == typeArgLenTarget {
|
||||
@ -232,7 +232,7 @@ func (comp *compiler) checkLenTarget(t *ast.Type, name, target string, fields []
|
||||
|
||||
type structDir struct {
|
||||
Struct string
|
||||
Dir sys.Dir
|
||||
Dir prog.Dir
|
||||
}
|
||||
|
||||
func (comp *compiler) checkConstructors() {
|
||||
@ -242,10 +242,10 @@ func (comp *compiler) checkConstructors() {
|
||||
switch n := decl.(type) {
|
||||
case *ast.Call:
|
||||
for _, arg := range n.Args {
|
||||
comp.checkTypeCtors(arg.Type, sys.DirIn, true, ctors, checked)
|
||||
comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, checked)
|
||||
}
|
||||
if n.Ret != nil {
|
||||
comp.checkTypeCtors(n.Ret, sys.DirOut, true, ctors, checked)
|
||||
comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,16 +261,16 @@ func (comp *compiler) checkConstructors() {
|
||||
}
|
||||
}
|
||||
|
||||
func (comp *compiler) checkTypeCtors(t *ast.Type, dir sys.Dir, isArg bool,
|
||||
func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,
|
||||
ctors map[string]bool, checked map[structDir]bool) {
|
||||
desc := comp.getTypeDesc(t)
|
||||
if desc == typeResource {
|
||||
// TODO(dvyukov): consider changing this to "dir == sys.DirOut".
|
||||
// TODO(dvyukov): consider changing this to "dir == prog.DirOut".
|
||||
// We have few questionable cases where resources can be created
|
||||
// only by inout struct fields. These structs should be split
|
||||
// into two different structs: one is in and second is out.
|
||||
// But that will require attaching dir to individual fields.
|
||||
if dir != sys.DirIn {
|
||||
if dir != prog.DirIn {
|
||||
r := comp.resources[t.Ident]
|
||||
for r != nil && !ctors[r.Name.Name] {
|
||||
ctors[r.Name.Name] = true
|
||||
@ -376,7 +376,7 @@ func (comp *compiler) recurseField(checked map[string]bool, t *ast.Type, path []
|
||||
comp.checkStructRecursion(checked, comp.structs[t.Ident], path)
|
||||
return
|
||||
}
|
||||
_, args, base := comp.getArgsBase(t, "", sys.DirIn, false)
|
||||
_, args, base := comp.getArgsBase(t, "", prog.DirIn, false)
|
||||
if desc == typePtr && base.IsOptional {
|
||||
return // optional pointers prune recursion
|
||||
}
|
||||
@ -464,7 +464,7 @@ func (comp *compiler) checkType(t *ast.Type, isArg, isRet, isStruct, isResourceB
|
||||
return
|
||||
}
|
||||
if desc.Check != nil {
|
||||
_, args, base := comp.getArgsBase(t, "", sys.DirIn, isArg)
|
||||
_, args, base := comp.getArgsBase(t, "", prog.DirIn, isArg)
|
||||
desc.Check(comp, t, args, base)
|
||||
}
|
||||
}
|
||||
@ -574,7 +574,7 @@ func (comp *compiler) checkVarlens() {
|
||||
}
|
||||
|
||||
func (comp *compiler) isVarlen(t *ast.Type) bool {
|
||||
desc, args, base := comp.getArgsBase(t, "", sys.DirIn, false)
|
||||
desc, args, base := comp.getArgsBase(t, "", prog.DirIn, false)
|
||||
return desc.Varlen != nil && desc.Varlen(comp, t, args, base)
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/syzkaller/pkg/ast"
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
// Overview of compilation process:
|
||||
@ -22,20 +22,20 @@ import (
|
||||
// This step also does verification of include/incdir/define AST nodes.
|
||||
// 3. User translates constants to values.
|
||||
// 4. Compile on AST and const values does the rest of the work and returns Prog
|
||||
// containing generated sys objects.
|
||||
// containing generated prog objects.
|
||||
// 4.1. assignSyscallNumbers: uses consts to assign syscall numbers.
|
||||
// This step also detects unsupported syscalls and discards no longer
|
||||
// needed AST nodes (inlcude, define, comments, etc).
|
||||
// 4.2. patchConsts: patches Int nodes refering to consts with corresponding values.
|
||||
// Also detects unsupported syscalls, structs, resources due to missing consts.
|
||||
// 4.3. check: does extensive semantical checks of AST.
|
||||
// 4.4. gen: generates sys objects from AST.
|
||||
// 4.4. gen: generates prog objects from AST.
|
||||
|
||||
// Prog is description compilation result.
|
||||
type Prog struct {
|
||||
Resources []*sys.ResourceDesc
|
||||
Syscalls []*sys.Syscall
|
||||
StructDescs []*sys.KeyedStruct
|
||||
Resources []*prog.ResourceDesc
|
||||
Syscalls []*prog.Syscall
|
||||
StructDescs []*prog.KeyedStruct
|
||||
// Set of unsupported syscalls/flags.
|
||||
Unsupported map[string]bool
|
||||
}
|
||||
@ -54,8 +54,8 @@ func Compile(desc *ast.Description, consts map[string]uint64, ptrSize uint64, eh
|
||||
structs: make(map[string]*ast.Struct),
|
||||
intFlags: make(map[string]*ast.IntFlags),
|
||||
strFlags: make(map[string]*ast.StrFlags),
|
||||
structDescs: make(map[sys.StructKey]*sys.StructDesc),
|
||||
structNodes: make(map[*sys.StructDesc]*ast.Struct),
|
||||
structDescs: make(map[prog.StructKey]*prog.StructDesc),
|
||||
structNodes: make(map[*prog.StructDesc]*ast.Struct),
|
||||
structVarlen: make(map[string]bool),
|
||||
}
|
||||
comp.assignSyscallNumbers(consts)
|
||||
@ -89,8 +89,8 @@ type compiler struct {
|
||||
intFlags map[string]*ast.IntFlags
|
||||
strFlags map[string]*ast.StrFlags
|
||||
|
||||
structDescs map[sys.StructKey]*sys.StructDesc
|
||||
structNodes map[*sys.StructDesc]*ast.Struct
|
||||
structDescs map[prog.StructKey]*prog.StructDesc
|
||||
structNodes map[*prog.StructDesc]*ast.Struct
|
||||
structVarlen map[string]bool
|
||||
}
|
||||
|
||||
@ -161,8 +161,8 @@ func (comp *compiler) getTypeDesc(t *ast.Type) *typeDesc {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (comp *compiler) getArgsBase(t *ast.Type, field string, dir sys.Dir, isArg bool) (
|
||||
*typeDesc, []*ast.Type, sys.IntTypeCommon) {
|
||||
func (comp *compiler) getArgsBase(t *ast.Type, field string, dir prog.Dir, isArg bool) (
|
||||
*typeDesc, []*ast.Type, prog.IntTypeCommon) {
|
||||
desc := comp.getTypeDesc(t)
|
||||
args, opt := removeOpt(t)
|
||||
size := sizeUnassigned
|
||||
@ -173,7 +173,7 @@ func (comp *compiler) getArgsBase(t *ast.Type, field string, dir sys.Dir, isArg
|
||||
if !isArg {
|
||||
baseType := args[len(args)-1]
|
||||
args = args[:len(args)-1]
|
||||
base = typeInt.Gen(comp, baseType, nil, base).(*sys.IntType).IntTypeCommon
|
||||
base = typeInt.Gen(comp, baseType, nil, base).(*prog.IntType).IntTypeCommon
|
||||
}
|
||||
}
|
||||
return desc, args, base
|
||||
|
@ -8,13 +8,13 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/google/syzkaller/pkg/ast"
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
const sizeUnassigned = ^uint64(0)
|
||||
|
||||
func (comp *compiler) genResources() []*sys.ResourceDesc {
|
||||
var resources []*sys.ResourceDesc
|
||||
func (comp *compiler) genResources() []*prog.ResourceDesc {
|
||||
var resources []*prog.ResourceDesc
|
||||
for _, decl := range comp.desc.Nodes {
|
||||
if n, ok := decl.(*ast.Resource); ok {
|
||||
resources = append(resources, comp.genResource(n))
|
||||
@ -26,8 +26,8 @@ func (comp *compiler) genResources() []*sys.ResourceDesc {
|
||||
return resources
|
||||
}
|
||||
|
||||
func (comp *compiler) genResource(n *ast.Resource) *sys.ResourceDesc {
|
||||
res := &sys.ResourceDesc{
|
||||
func (comp *compiler) genResource(n *ast.Resource) *prog.ResourceDesc {
|
||||
res := &prog.ResourceDesc{
|
||||
Name: n.Name.Name,
|
||||
}
|
||||
var base *ast.Type
|
||||
@ -40,12 +40,12 @@ func (comp *compiler) genResource(n *ast.Resource) *sys.ResourceDesc {
|
||||
if len(res.Values) == 0 {
|
||||
res.Values = []uint64{0}
|
||||
}
|
||||
res.Type = comp.genType(base, "", sys.DirIn, false)
|
||||
res.Type = comp.genType(base, "", prog.DirIn, false)
|
||||
return res
|
||||
}
|
||||
|
||||
func (comp *compiler) genSyscalls() []*sys.Syscall {
|
||||
var calls []*sys.Syscall
|
||||
func (comp *compiler) genSyscalls() []*prog.Syscall {
|
||||
var calls []*prog.Syscall
|
||||
for _, decl := range comp.desc.Nodes {
|
||||
if n, ok := decl.(*ast.Call); ok {
|
||||
calls = append(calls, comp.genSyscall(n))
|
||||
@ -60,32 +60,32 @@ func (comp *compiler) genSyscalls() []*sys.Syscall {
|
||||
return calls
|
||||
}
|
||||
|
||||
func (comp *compiler) genSyscall(n *ast.Call) *sys.Syscall {
|
||||
var ret sys.Type
|
||||
func (comp *compiler) genSyscall(n *ast.Call) *prog.Syscall {
|
||||
var ret prog.Type
|
||||
if n.Ret != nil {
|
||||
ret = comp.genType(n.Ret, "ret", sys.DirOut, true)
|
||||
ret = comp.genType(n.Ret, "ret", prog.DirOut, true)
|
||||
}
|
||||
return &sys.Syscall{
|
||||
return &prog.Syscall{
|
||||
Name: n.Name.Name,
|
||||
CallName: n.CallName,
|
||||
NR: n.NR,
|
||||
Args: comp.genFieldArray(n.Args, sys.DirIn, true),
|
||||
Args: comp.genFieldArray(n.Args, prog.DirIn, true),
|
||||
Ret: ret,
|
||||
}
|
||||
}
|
||||
|
||||
func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct {
|
||||
func (comp *compiler) genStructDescs(syscalls []*prog.Syscall) []*prog.KeyedStruct {
|
||||
// Calculate struct/union/array sizes, add padding to structs and detach
|
||||
// StructDesc's from StructType's. StructType's can be recursive so it's
|
||||
// not possible to write them out inline as other types. To break the
|
||||
// recursion detach them, and write StructDesc's out as separate array
|
||||
// of KeyedStruct's. sys package will reattach them during init.
|
||||
// of KeyedStruct's. prog package will reattach them during init.
|
||||
|
||||
padded := make(map[interface{}]bool)
|
||||
detach := make(map[**sys.StructDesc]bool)
|
||||
var structs []*sys.KeyedStruct
|
||||
var rec func(t sys.Type)
|
||||
checkStruct := func(key sys.StructKey, descp **sys.StructDesc) bool {
|
||||
detach := make(map[**prog.StructDesc]bool)
|
||||
var structs []*prog.KeyedStruct
|
||||
var rec func(t prog.Type)
|
||||
checkStruct := func(key prog.StructKey, descp **prog.StructDesc) bool {
|
||||
detach[descp] = true
|
||||
desc := *descp
|
||||
if padded[desc] {
|
||||
@ -101,17 +101,17 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
|
||||
return false
|
||||
}
|
||||
}
|
||||
structs = append(structs, &sys.KeyedStruct{
|
||||
structs = append(structs, &prog.KeyedStruct{
|
||||
Key: key,
|
||||
Desc: desc,
|
||||
})
|
||||
return true
|
||||
}
|
||||
rec = func(t0 sys.Type) {
|
||||
rec = func(t0 prog.Type) {
|
||||
switch t := t0.(type) {
|
||||
case *sys.PtrType:
|
||||
case *prog.PtrType:
|
||||
rec(t.Type)
|
||||
case *sys.ArrayType:
|
||||
case *prog.ArrayType:
|
||||
if padded[t] {
|
||||
return
|
||||
}
|
||||
@ -123,10 +123,10 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
|
||||
}
|
||||
padded[t] = true
|
||||
t.TypeSize = 0
|
||||
if t.Kind == sys.ArrayRangeLen && t.RangeBegin == t.RangeEnd && !t.Type.Varlen() {
|
||||
if t.Kind == prog.ArrayRangeLen && t.RangeBegin == t.RangeEnd && !t.Type.Varlen() {
|
||||
t.TypeSize = t.RangeBegin * t.Type.Size()
|
||||
}
|
||||
case *sys.StructType:
|
||||
case *prog.StructType:
|
||||
if !checkStruct(t.Key, &t.StructDesc) {
|
||||
return
|
||||
}
|
||||
@ -149,7 +149,7 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
|
||||
}
|
||||
}
|
||||
}
|
||||
case *sys.UnionType:
|
||||
case *prog.UnionType:
|
||||
if !checkStruct(t.Key, &t.StructDesc) {
|
||||
return
|
||||
}
|
||||
@ -182,7 +182,7 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
|
||||
}
|
||||
}
|
||||
|
||||
// Detach StructDesc's from StructType's. sys will reattach them again.
|
||||
// Detach StructDesc's from StructType's. prog will reattach them again.
|
||||
for descp := range detach {
|
||||
*descp = nil
|
||||
}
|
||||
@ -197,10 +197,10 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
|
||||
return structs
|
||||
}
|
||||
|
||||
func (comp *compiler) genStructDesc(res *sys.StructDesc, n *ast.Struct, dir sys.Dir) {
|
||||
func (comp *compiler) genStructDesc(res *prog.StructDesc, n *ast.Struct, dir prog.Dir) {
|
||||
// Leave node for genStructDescs to calculate size/padding.
|
||||
comp.structNodes[res] = n
|
||||
*res = sys.StructDesc{
|
||||
*res = prog.StructDesc{
|
||||
TypeCommon: genCommon(n.Name.Name, "", sizeUnassigned, dir, false),
|
||||
Fields: comp.genFieldArray(n.Fields, dir, false),
|
||||
}
|
||||
@ -227,7 +227,7 @@ func (comp *compiler) isStructVarlen(name string) bool {
|
||||
return varlen
|
||||
}
|
||||
|
||||
func (comp *compiler) markBitfields(fields []sys.Type) {
|
||||
func (comp *compiler) markBitfields(fields []prog.Type) {
|
||||
var bfOffset uint64
|
||||
for i, f := range fields {
|
||||
if f.BitfieldLength() == 0 {
|
||||
@ -245,25 +245,25 @@ func (comp *compiler) markBitfields(fields []sys.Type) {
|
||||
}
|
||||
}
|
||||
|
||||
func setBitfieldOffset(t0 sys.Type, offset uint64, middle bool) {
|
||||
func setBitfieldOffset(t0 prog.Type, offset uint64, middle bool) {
|
||||
switch t := t0.(type) {
|
||||
case *sys.IntType:
|
||||
case *prog.IntType:
|
||||
t.BitfieldOff, t.BitfieldMdl = offset, middle
|
||||
case *sys.ConstType:
|
||||
case *prog.ConstType:
|
||||
t.BitfieldOff, t.BitfieldMdl = offset, middle
|
||||
case *sys.LenType:
|
||||
case *prog.LenType:
|
||||
t.BitfieldOff, t.BitfieldMdl = offset, middle
|
||||
case *sys.FlagsType:
|
||||
case *prog.FlagsType:
|
||||
t.BitfieldOff, t.BitfieldMdl = offset, middle
|
||||
case *sys.ProcType:
|
||||
case *prog.ProcType:
|
||||
t.BitfieldOff, t.BitfieldMdl = offset, middle
|
||||
default:
|
||||
panic(fmt.Sprintf("type %#v can't be a bitfield", t))
|
||||
}
|
||||
}
|
||||
|
||||
func (comp *compiler) addAlignment(fields []sys.Type, varlen, packed bool, alignAttr uint64) []sys.Type {
|
||||
var newFields []sys.Type
|
||||
func (comp *compiler) addAlignment(fields []prog.Type, varlen, packed bool, alignAttr uint64) []prog.Type {
|
||||
var newFields []prog.Type
|
||||
if packed {
|
||||
// If a struct is packed, statically sized and has explicitly set alignment,
|
||||
// add a padding at the end.
|
||||
@ -312,19 +312,19 @@ func (comp *compiler) addAlignment(fields []sys.Type, varlen, packed bool, align
|
||||
return newFields
|
||||
}
|
||||
|
||||
func (comp *compiler) typeAlign(t0 sys.Type) uint64 {
|
||||
func (comp *compiler) typeAlign(t0 prog.Type) uint64 {
|
||||
switch t0.(type) {
|
||||
case *sys.IntType, *sys.ConstType, *sys.LenType, *sys.FlagsType, *sys.ProcType,
|
||||
*sys.CsumType, *sys.PtrType, *sys.VmaType, *sys.ResourceType:
|
||||
case *prog.IntType, *prog.ConstType, *prog.LenType, *prog.FlagsType, *prog.ProcType,
|
||||
*prog.CsumType, *prog.PtrType, *prog.VmaType, *prog.ResourceType:
|
||||
return t0.Size()
|
||||
case *sys.BufferType:
|
||||
case *prog.BufferType:
|
||||
return 1
|
||||
}
|
||||
|
||||
switch t := t0.(type) {
|
||||
case *sys.ArrayType:
|
||||
case *prog.ArrayType:
|
||||
return comp.typeAlign(t.Type)
|
||||
case *sys.StructType:
|
||||
case *prog.StructType:
|
||||
packed, alignAttr := comp.parseStructAttrs(comp.structNodes[t.StructDesc])
|
||||
if alignAttr != 0 {
|
||||
return alignAttr // overrided by user attribute
|
||||
@ -339,7 +339,7 @@ func (comp *compiler) typeAlign(t0 sys.Type) uint64 {
|
||||
}
|
||||
}
|
||||
return align
|
||||
case *sys.UnionType:
|
||||
case *prog.UnionType:
|
||||
align := uint64(0)
|
||||
for _, f := range t.Fields {
|
||||
if a := comp.typeAlign(f); align < a {
|
||||
@ -352,32 +352,32 @@ func (comp *compiler) typeAlign(t0 sys.Type) uint64 {
|
||||
}
|
||||
}
|
||||
|
||||
func genPad(size uint64) sys.Type {
|
||||
return &sys.ConstType{
|
||||
IntTypeCommon: genIntCommon(genCommon("pad", "", size, sys.DirIn, false), 0, false),
|
||||
func genPad(size uint64) prog.Type {
|
||||
return &prog.ConstType{
|
||||
IntTypeCommon: genIntCommon(genCommon("pad", "", size, prog.DirIn, false), 0, false),
|
||||
IsPad: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (comp *compiler) genField(f *ast.Field, dir sys.Dir, isArg bool) sys.Type {
|
||||
func (comp *compiler) genField(f *ast.Field, dir prog.Dir, isArg bool) prog.Type {
|
||||
return comp.genType(f.Type, f.Name.Name, dir, isArg)
|
||||
}
|
||||
|
||||
func (comp *compiler) genFieldArray(fields []*ast.Field, dir sys.Dir, isArg bool) []sys.Type {
|
||||
var res []sys.Type
|
||||
func (comp *compiler) genFieldArray(fields []*ast.Field, dir prog.Dir, isArg bool) []prog.Type {
|
||||
var res []prog.Type
|
||||
for _, f := range fields {
|
||||
res = append(res, comp.genField(f, dir, isArg))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (comp *compiler) genType(t *ast.Type, field string, dir sys.Dir, isArg bool) sys.Type {
|
||||
func (comp *compiler) genType(t *ast.Type, field string, dir prog.Dir, isArg bool) prog.Type {
|
||||
desc, args, base := comp.getArgsBase(t, field, dir, isArg)
|
||||
return desc.Gen(comp, t, args, base)
|
||||
}
|
||||
|
||||
func genCommon(name, field string, size uint64, dir sys.Dir, opt bool) sys.TypeCommon {
|
||||
return sys.TypeCommon{
|
||||
func genCommon(name, field string, size uint64, dir prog.Dir, opt bool) prog.TypeCommon {
|
||||
return prog.TypeCommon{
|
||||
TypeName: name,
|
||||
TypeSize: size,
|
||||
FldName: field,
|
||||
@ -386,8 +386,8 @@ func genCommon(name, field string, size uint64, dir sys.Dir, opt bool) sys.TypeC
|
||||
}
|
||||
}
|
||||
|
||||
func genIntCommon(com sys.TypeCommon, bitLen uint64, bigEndian bool) sys.IntTypeCommon {
|
||||
return sys.IntTypeCommon{
|
||||
func genIntCommon(com prog.TypeCommon, bitLen uint64, bigEndian bool) prog.IntTypeCommon {
|
||||
return prog.IntTypeCommon{
|
||||
TypeCommon: com,
|
||||
BigEndian: bigEndian,
|
||||
BitfieldLen: bitLen,
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/google/syzkaller/pkg/ast"
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
// typeDesc is arg/field type descriptor.
|
||||
@ -23,11 +23,11 @@ type typeDesc struct {
|
||||
OptArgs int // number of optional arguments in Args array
|
||||
Args []namedArg // type arguments
|
||||
// Check does custom verification of the type (optional).
|
||||
Check func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon)
|
||||
Check func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon)
|
||||
// Varlen returns if the type is variable-length (false if not set).
|
||||
Varlen func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool
|
||||
// Gen generates corresponding sys.Type.
|
||||
Gen func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type
|
||||
Varlen func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool
|
||||
// Gen generates corresponding prog.Type.
|
||||
Gen func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type
|
||||
}
|
||||
|
||||
// typeArg describes a type argument.
|
||||
@ -58,17 +58,17 @@ var typeInt = &typeDesc{
|
||||
ResourceBase: true,
|
||||
OptArgs: 1,
|
||||
Args: []namedArg{{"range", typeArgRange}},
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
|
||||
typeArgBase.Type.Check(comp, t)
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
size, be := comp.parseIntType(t.Ident)
|
||||
kind, rangeBegin, rangeEnd := sys.IntPlain, uint64(0), uint64(0)
|
||||
kind, rangeBegin, rangeEnd := prog.IntPlain, uint64(0), uint64(0)
|
||||
if len(args) > 0 {
|
||||
kind, rangeBegin, rangeEnd = sys.IntRange, args[0].Value, args[0].Value2
|
||||
kind, rangeBegin, rangeEnd = prog.IntRange, args[0].Value, args[0].Value2
|
||||
}
|
||||
base.TypeSize = size
|
||||
return &sys.IntType{
|
||||
return &prog.IntType{
|
||||
IntTypeCommon: genIntCommon(base.TypeCommon, t.Value2, be),
|
||||
Kind: kind,
|
||||
RangeBegin: rangeBegin,
|
||||
@ -81,13 +81,13 @@ var typePtr = &typeDesc{
|
||||
Names: []string{"ptr", "ptr64"},
|
||||
CanBeArg: true,
|
||||
Args: []namedArg{{"direction", typeArgDir}, {"type", typeArgType}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
base.ArgDir = sys.DirIn // pointers are always in
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
base.ArgDir = prog.DirIn // pointers are always in
|
||||
base.TypeSize = comp.ptrSize
|
||||
if t.Ident == "ptr64" {
|
||||
base.TypeSize = 8
|
||||
}
|
||||
return &sys.PtrType{
|
||||
return &prog.PtrType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Type: comp.genType(args[1], "", genDir(args[0]), false),
|
||||
}
|
||||
@ -99,13 +99,13 @@ var typeArray = &typeDesc{
|
||||
CantBeOpt: true,
|
||||
OptArgs: 1,
|
||||
Args: []namedArg{{"type", typeArgType}, {"size", typeArgRange}},
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
|
||||
if len(args) > 1 && args[1].Value == 0 && args[1].Value2 == 0 {
|
||||
// This is the only case that can yield 0 static type size.
|
||||
comp.error(args[1].Pos, "arrays of size 0 are not supported")
|
||||
}
|
||||
},
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
|
||||
if comp.isVarlen(args[0]) {
|
||||
return true
|
||||
}
|
||||
@ -114,23 +114,23 @@ var typeArray = &typeDesc{
|
||||
}
|
||||
return true
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
elemType := comp.genType(args[0], "", base.ArgDir, false)
|
||||
kind, begin, end := sys.ArrayRandLen, uint64(0), uint64(0)
|
||||
kind, begin, end := prog.ArrayRandLen, uint64(0), uint64(0)
|
||||
if len(args) > 1 {
|
||||
kind, begin, end = sys.ArrayRangeLen, args[1].Value, args[1].Value2
|
||||
kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value2
|
||||
}
|
||||
if it, ok := elemType.(*sys.IntType); ok && it.Kind == sys.IntPlain && it.TypeSize == 1 {
|
||||
if it, ok := elemType.(*prog.IntType); ok && it.Kind == prog.IntPlain && it.TypeSize == 1 {
|
||||
// Special case: buffer is better mutated.
|
||||
bufKind := sys.BufferBlobRand
|
||||
bufKind := prog.BufferBlobRand
|
||||
base.TypeSize = 0
|
||||
if kind == sys.ArrayRangeLen {
|
||||
bufKind = sys.BufferBlobRange
|
||||
if kind == prog.ArrayRangeLen {
|
||||
bufKind = prog.BufferBlobRange
|
||||
if begin == end {
|
||||
base.TypeSize = begin * elemType.Size()
|
||||
}
|
||||
}
|
||||
return &sys.BufferType{
|
||||
return &prog.BufferType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Kind: bufKind,
|
||||
RangeBegin: begin,
|
||||
@ -138,7 +138,7 @@ var typeArray = &typeDesc{
|
||||
}
|
||||
}
|
||||
// TypeSize is assigned later in genStructDescs.
|
||||
return &sys.ArrayType{
|
||||
return &prog.ArrayType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Type: elemType,
|
||||
Kind: kind,
|
||||
@ -155,7 +155,7 @@ var typeLen = &typeDesc{
|
||||
CantBeRet: true,
|
||||
NeedBase: true,
|
||||
Args: []namedArg{{"len target", typeArgLenTarget}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
var byteSize uint64
|
||||
switch t.Ident {
|
||||
case "bytesize":
|
||||
@ -163,7 +163,7 @@ var typeLen = &typeDesc{
|
||||
case "bytesize2", "bytesize4", "bytesize8":
|
||||
byteSize, _ = strconv.ParseUint(t.Ident[8:], 10, 8)
|
||||
}
|
||||
return &sys.LenType{
|
||||
return &prog.LenType{
|
||||
IntTypeCommon: base,
|
||||
Buf: args[0].Ident,
|
||||
ByteSize: byteSize,
|
||||
@ -177,8 +177,8 @@ var typeConst = &typeDesc{
|
||||
CantBeOpt: true,
|
||||
NeedBase: true,
|
||||
Args: []namedArg{{"value", typeArgInt}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
return &sys.ConstType{
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
return &prog.ConstType{
|
||||
IntTypeCommon: base,
|
||||
Val: args[0].Value,
|
||||
}
|
||||
@ -195,18 +195,18 @@ var typeFlags = &typeDesc{
|
||||
CantBeOpt: true,
|
||||
NeedBase: true,
|
||||
Args: []namedArg{{"flags", typeArgFlags}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
name := args[0].Ident
|
||||
base.TypeName = name
|
||||
f := comp.intFlags[name]
|
||||
if len(f.Values) == 0 {
|
||||
// We can get this if all values are unsupported consts.
|
||||
return &sys.IntType{
|
||||
return &prog.IntType{
|
||||
IntTypeCommon: base,
|
||||
Kind: sys.IntPlain,
|
||||
Kind: prog.IntPlain,
|
||||
}
|
||||
}
|
||||
return &sys.FlagsType{
|
||||
return &prog.FlagsType{
|
||||
IntTypeCommon: base,
|
||||
Vals: genIntArray(f.Values),
|
||||
}
|
||||
@ -226,14 +226,14 @@ var typeArgFlags = &typeArg{
|
||||
var typeFilename = &typeDesc{
|
||||
Names: []string{"filename"},
|
||||
CantBeOpt: true,
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
|
||||
return true
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
base.TypeSize = 0
|
||||
return &sys.BufferType{
|
||||
return &prog.BufferType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Kind: sys.BufferFilename,
|
||||
Kind: prog.BufferFilename,
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -243,10 +243,10 @@ var typeFileoff = &typeDesc{
|
||||
CanBeArg: true,
|
||||
CantBeOpt: true,
|
||||
NeedBase: true,
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
return &sys.IntType{
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
return &prog.IntType{
|
||||
IntTypeCommon: base,
|
||||
Kind: sys.IntFileoff,
|
||||
Kind: prog.IntFileoff,
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -256,13 +256,13 @@ var typeVMA = &typeDesc{
|
||||
CanBeArg: true,
|
||||
OptArgs: 1,
|
||||
Args: []namedArg{{"size range", typeArgRange}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
begin, end := uint64(0), uint64(0)
|
||||
if len(args) > 0 {
|
||||
begin, end = args[0].Value, args[0].Value2
|
||||
}
|
||||
base.TypeSize = comp.ptrSize
|
||||
return &sys.VmaType{
|
||||
return &prog.VmaType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
RangeBegin: begin,
|
||||
RangeEnd: end,
|
||||
@ -277,11 +277,11 @@ var typeSignalno = &typeDesc{
|
||||
Names: []string{"signalno"},
|
||||
CanBeArg: true,
|
||||
CantBeOpt: true,
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
base.TypeSize = 4
|
||||
return &sys.IntType{
|
||||
return &prog.IntType{
|
||||
IntTypeCommon: base,
|
||||
Kind: sys.IntRange,
|
||||
Kind: prog.IntRange,
|
||||
RangeBegin: 0,
|
||||
RangeEnd: 65,
|
||||
}
|
||||
@ -295,17 +295,17 @@ var typeCsum = &typeDesc{
|
||||
CantBeRet: true,
|
||||
OptArgs: 1,
|
||||
Args: []namedArg{{"csum target", typeArgLenTarget}, {"kind", typeArgCsumType}, {"proto", typeArgInt}},
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
|
||||
if len(args) > 2 && genCsumKind(args[1]) != sys.CsumPseudo {
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
|
||||
if len(args) > 2 && genCsumKind(args[1]) != prog.CsumPseudo {
|
||||
comp.error(args[2].Pos, "only pseudo csum can have proto")
|
||||
}
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
var proto uint64
|
||||
if len(args) > 2 {
|
||||
proto = args[2].Value
|
||||
}
|
||||
return &sys.CsumType{
|
||||
return &prog.CsumType{
|
||||
IntTypeCommon: base,
|
||||
Buf: args[0].Ident,
|
||||
Kind: genCsumKind(args[1]),
|
||||
@ -319,12 +319,12 @@ var typeArgCsumType = &typeArg{
|
||||
Names: []string{"inet", "pseudo"},
|
||||
}
|
||||
|
||||
func genCsumKind(t *ast.Type) sys.CsumKind {
|
||||
func genCsumKind(t *ast.Type) prog.CsumKind {
|
||||
switch t.Ident {
|
||||
case "inet":
|
||||
return sys.CsumInet
|
||||
return prog.CsumInet
|
||||
case "pseudo":
|
||||
return sys.CsumPseudo
|
||||
return prog.CsumPseudo
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown csum kind %q", t.Ident))
|
||||
}
|
||||
@ -336,7 +336,7 @@ var typeProc = &typeDesc{
|
||||
CantBeOpt: true,
|
||||
NeedBase: true,
|
||||
Args: []namedArg{{"range start", typeArgInt}, {"per-proc values", typeArgInt}},
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
|
||||
start := args[0].Value
|
||||
perProc := args[1].Value
|
||||
if perProc == 0 {
|
||||
@ -354,8 +354,8 @@ var typeProc = &typeDesc{
|
||||
}
|
||||
}
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
return &sys.ProcType{
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
return &prog.ProcType{
|
||||
IntTypeCommon: base,
|
||||
ValuesStart: args[0].Value,
|
||||
ValuesPerProc: args[1].Value,
|
||||
@ -367,14 +367,14 @@ var typeText = &typeDesc{
|
||||
Names: []string{"text"},
|
||||
CantBeOpt: true,
|
||||
Args: []namedArg{{"kind", typeArgTextType}},
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
|
||||
return true
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
base.TypeSize = 0
|
||||
return &sys.BufferType{
|
||||
return &prog.BufferType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Kind: sys.BufferText,
|
||||
Kind: prog.BufferText,
|
||||
Text: genTextType(args[0]),
|
||||
}
|
||||
},
|
||||
@ -385,18 +385,18 @@ var typeArgTextType = &typeArg{
|
||||
Names: []string{"x86_real", "x86_16", "x86_32", "x86_64", "arm64"},
|
||||
}
|
||||
|
||||
func genTextType(t *ast.Type) sys.TextKind {
|
||||
func genTextType(t *ast.Type) prog.TextKind {
|
||||
switch t.Ident {
|
||||
case "x86_real":
|
||||
return sys.Text_x86_real
|
||||
return prog.Text_x86_real
|
||||
case "x86_16":
|
||||
return sys.Text_x86_16
|
||||
return prog.Text_x86_16
|
||||
case "x86_32":
|
||||
return sys.Text_x86_32
|
||||
return prog.Text_x86_32
|
||||
case "x86_64":
|
||||
return sys.Text_x86_64
|
||||
return prog.Text_x86_64
|
||||
case "arm64":
|
||||
return sys.Text_arm64
|
||||
return prog.Text_arm64
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown text type %q", t.Ident))
|
||||
}
|
||||
@ -406,14 +406,14 @@ var typeBuffer = &typeDesc{
|
||||
Names: []string{"buffer"},
|
||||
CanBeArg: true,
|
||||
Args: []namedArg{{"direction", typeArgDir}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
base.TypeSize = comp.ptrSize
|
||||
return &sys.PtrType{
|
||||
return &prog.PtrType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Type: &sys.BufferType{
|
||||
Type: &prog.BufferType{
|
||||
// BufferBlobRand is always varlen.
|
||||
TypeCommon: genCommon("", "", 0, genDir(args[0]), false),
|
||||
Kind: sys.BufferBlobRand,
|
||||
Kind: prog.BufferBlobRand,
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -423,7 +423,7 @@ var typeString = &typeDesc{
|
||||
Names: []string{"string"},
|
||||
OptArgs: 2,
|
||||
Args: []namedArg{{"literal or flags", typeArgStringFlags}, {"size", typeArgInt}},
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
|
||||
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
|
||||
if len(args) > 1 {
|
||||
size := args[1].Value
|
||||
vals := []string{args[0].String}
|
||||
@ -439,10 +439,10 @@ var typeString = &typeDesc{
|
||||
}
|
||||
}
|
||||
},
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
|
||||
Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
|
||||
return comp.stringSize(args) == 0
|
||||
},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
subkind := ""
|
||||
var vals []string
|
||||
if len(args) > 0 {
|
||||
@ -465,9 +465,9 @@ var typeString = &typeDesc{
|
||||
vals[i] = s
|
||||
}
|
||||
base.TypeSize = comp.stringSize(args)
|
||||
return &sys.BufferType{
|
||||
return &prog.BufferType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
Kind: sys.BufferString,
|
||||
Kind: prog.BufferString,
|
||||
SubKind: subkind,
|
||||
Values: vals,
|
||||
}
|
||||
@ -527,15 +527,15 @@ var typeResource = &typeDesc{
|
||||
}
|
||||
|
||||
func init() {
|
||||
typeResource.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
typeResource.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
// Find and generate base type to get its size.
|
||||
var baseType *ast.Type
|
||||
for r := comp.resources[t.Ident]; r != nil; {
|
||||
baseType = r.Base
|
||||
r = comp.resources[r.Base.Ident]
|
||||
}
|
||||
base.TypeSize = comp.genType(baseType, "", sys.DirIn, false).Size()
|
||||
return &sys.ResourceType{
|
||||
base.TypeSize = comp.genType(baseType, "", prog.DirIn, false).Size()
|
||||
return &prog.ResourceType{
|
||||
TypeCommon: base.TypeCommon,
|
||||
}
|
||||
}
|
||||
@ -548,27 +548,27 @@ var typeStruct = &typeDesc{
|
||||
}
|
||||
|
||||
func init() {
|
||||
typeStruct.Varlen = func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
|
||||
typeStruct.Varlen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
|
||||
return comp.isStructVarlen(t.Ident)
|
||||
}
|
||||
typeStruct.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
|
||||
typeStruct.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
s := comp.structs[t.Ident]
|
||||
key := sys.StructKey{t.Ident, base.ArgDir}
|
||||
key := prog.StructKey{t.Ident, base.ArgDir}
|
||||
desc := comp.structDescs[key]
|
||||
if desc == nil {
|
||||
// Need to assign to structDescs before calling genStructDesc to break recursion.
|
||||
desc = new(sys.StructDesc)
|
||||
desc = new(prog.StructDesc)
|
||||
comp.structDescs[key] = desc
|
||||
comp.genStructDesc(desc, s, base.ArgDir)
|
||||
}
|
||||
if s.IsUnion {
|
||||
return &sys.UnionType{
|
||||
return &prog.UnionType{
|
||||
Key: key,
|
||||
FldName: base.FldName,
|
||||
StructDesc: desc,
|
||||
}
|
||||
} else {
|
||||
return &sys.StructType{
|
||||
return &prog.StructType{
|
||||
Key: key,
|
||||
FldName: base.FldName,
|
||||
StructDesc: desc,
|
||||
@ -582,14 +582,14 @@ var typeArgDir = &typeArg{
|
||||
Names: []string{"in", "out", "inout"},
|
||||
}
|
||||
|
||||
func genDir(t *ast.Type) sys.Dir {
|
||||
func genDir(t *ast.Type) prog.Dir {
|
||||
switch t.Ident {
|
||||
case "in":
|
||||
return sys.DirIn
|
||||
return prog.DirIn
|
||||
case "out":
|
||||
return sys.DirOut
|
||||
return prog.DirOut
|
||||
case "inout":
|
||||
return sys.DirInOut
|
||||
return prog.DirInOut
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown direction %q", t.Ident))
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/syzkaller/prog"
|
||||
"github.com/google/syzkaller/sys"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
@ -367,7 +367,7 @@ loop:
|
||||
fmt.Fprintf(w, "\twrite_file(\"/sys/kernel/debug/fail_futex/ignore-private\", \"N\");\n")
|
||||
fmt.Fprintf(w, "\tinject_fault(%v);\n", opts.FaultNth)
|
||||
}
|
||||
meta := sys.Syscalls[instr]
|
||||
meta := prog.Syscalls[instr]
|
||||
emitCall := true
|
||||
if meta.CallName == "syz_test" {
|
||||
emitCall = false
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func initTest(t *testing.T) (rand.Source, int) {
|
||||
|
@ -12,13 +12,13 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
// DetectSupportedSyscalls returns list on supported syscalls on host.
|
||||
func DetectSupportedSyscalls() (map[*sys.Syscall]bool, error) {
|
||||
func DetectSupportedSyscalls() (map[*prog.Syscall]bool, error) {
|
||||
// There are 3 possible strategies:
|
||||
// 1. Executes all syscalls with presumably invalid arguments and check for ENOSYS.
|
||||
// 1. Executes all syscalls with presumably invalid arguments and check for ENOprog.
|
||||
// But not all syscalls are safe to execute. For example, pause will hang,
|
||||
// while setpgrp will push the process into own process group.
|
||||
// 2. Check presence of /sys/kernel/debug/tracing/events/syscalls/sys_enter_* files.
|
||||
@ -28,8 +28,8 @@ func DetectSupportedSyscalls() (map[*sys.Syscall]bool, error) {
|
||||
// Requires CONFIG_KALLSYMS. Seems to be the most reliable. That's what we use here.
|
||||
|
||||
kallsyms, _ := ioutil.ReadFile("/proc/kallsyms")
|
||||
supported := make(map[*sys.Syscall]bool)
|
||||
for _, c := range sys.Syscalls {
|
||||
supported := make(map[*prog.Syscall]bool)
|
||||
for _, c := range prog.Syscalls {
|
||||
if isSupported(kallsyms, c) {
|
||||
supported[c] = true
|
||||
}
|
||||
@ -37,7 +37,7 @@ func DetectSupportedSyscalls() (map[*sys.Syscall]bool, error) {
|
||||
return supported, nil
|
||||
}
|
||||
|
||||
func isSupported(kallsyms []byte, c *sys.Syscall) bool {
|
||||
func isSupported(kallsyms []byte, c *prog.Syscall) bool {
|
||||
if c.NR == ^uint64(0) {
|
||||
return false // don't even have a syscall number
|
||||
}
|
||||
@ -59,12 +59,12 @@ func isSupported(kallsyms []byte, c *sys.Syscall) bool {
|
||||
return bytes.Index(kallsyms, []byte(" T sys_"+c.CallName+"\n")) != -1
|
||||
}
|
||||
|
||||
func isSupportedSyzkall(c *sys.Syscall) bool {
|
||||
func isSupportedSyzkall(c *prog.Syscall) bool {
|
||||
switch c.CallName {
|
||||
case "syz_test":
|
||||
return false
|
||||
case "syz_open_dev":
|
||||
if _, ok := c.Args[0].(*sys.ConstType); ok {
|
||||
if _, ok := c.Args[0].(*prog.ConstType); ok {
|
||||
// This is for syz_open_dev$char/block.
|
||||
// They are currently commented out, but in case one enables them.
|
||||
return true
|
||||
@ -112,8 +112,8 @@ func isSupportedSyzkall(c *sys.Syscall) bool {
|
||||
panic("unknown syzkall: " + c.Name)
|
||||
}
|
||||
|
||||
func isSupportedSocket(c *sys.Syscall) bool {
|
||||
af, ok := c.Args[0].(*sys.ConstType)
|
||||
func isSupportedSocket(c *prog.Syscall) bool {
|
||||
af, ok := c.Args[0].(*prog.ConstType)
|
||||
if !ok {
|
||||
println(c.Name)
|
||||
panic("socket family is not const")
|
||||
@ -125,7 +125,7 @@ func isSupportedSocket(c *sys.Syscall) bool {
|
||||
return err != syscall.ENOSYS && err != syscall.EAFNOSUPPORT
|
||||
}
|
||||
|
||||
func isSupportedOpen(c *sys.Syscall) bool {
|
||||
func isSupportedOpen(c *prog.Syscall) bool {
|
||||
fname, ok := extractStringConst(c.Args[0])
|
||||
if !ok {
|
||||
return true
|
||||
@ -137,7 +137,7 @@ func isSupportedOpen(c *sys.Syscall) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func isSupportedOpenAt(c *sys.Syscall) bool {
|
||||
func isSupportedOpenAt(c *prog.Syscall) bool {
|
||||
fname, ok := extractStringConst(c.Args[1])
|
||||
if !ok {
|
||||
return true
|
||||
@ -149,13 +149,13 @@ func isSupportedOpenAt(c *sys.Syscall) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func extractStringConst(typ sys.Type) (string, bool) {
|
||||
ptr, ok := typ.(*sys.PtrType)
|
||||
func extractStringConst(typ prog.Type) (string, bool) {
|
||||
ptr, ok := typ.(*prog.PtrType)
|
||||
if !ok {
|
||||
panic("first open arg is not a pointer to string const")
|
||||
}
|
||||
str, ok := ptr.Type.(*sys.BufferType)
|
||||
if !ok || str.Kind != sys.BufferString || len(str.Values) != 1 {
|
||||
str, ok := ptr.Type.(*prog.BufferType)
|
||||
if !ok || str.Kind != prog.BufferString || len(str.Values) != 1 {
|
||||
return "", false
|
||||
}
|
||||
v := str.Values[0]
|
||||
|
@ -7,7 +7,8 @@ import (
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
@ -18,7 +19,7 @@ func TestLog(t *testing.T) {
|
||||
t.Skipf("skipping: %v", err)
|
||||
}
|
||||
t.Logf("unsupported:")
|
||||
for _, c := range sys.Syscalls {
|
||||
for _, c := range prog.Syscalls {
|
||||
s, ok := supp[c]
|
||||
if ok && !s {
|
||||
t.Fatalf("map contains false value")
|
||||
@ -27,9 +28,9 @@ func TestLog(t *testing.T) {
|
||||
t.Logf("\t%v", c.Name)
|
||||
}
|
||||
}
|
||||
trans := sys.TransitivelyEnabledCalls(supp)
|
||||
trans := prog.TransitivelyEnabledCalls(supp)
|
||||
t.Logf("transitively unsupported:")
|
||||
for _, c := range sys.Syscalls {
|
||||
for _, c := range prog.Syscalls {
|
||||
s, ok := trans[c]
|
||||
if ok && !s {
|
||||
t.Fatalf("map contains false value")
|
||||
@ -58,7 +59,7 @@ func TestSupportedSyscalls(t *testing.T) {
|
||||
"stat",
|
||||
}
|
||||
for _, name := range safe {
|
||||
c := sys.SyscallMap[name]
|
||||
c := prog.SyscallMap[name]
|
||||
if c == nil {
|
||||
t.Fatalf("can't find syscall '%v'", name)
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/google/syzkaller/pkg/csource"
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
const timeout = 10 * time.Second
|
||||
|
124
prog/analysis.go
124
prog/analysis.go
@ -10,8 +10,6 @@ package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -68,43 +66,15 @@ func (s *state) analyze(c *Call) {
|
||||
}
|
||||
}
|
||||
})
|
||||
switch c.Meta.Name {
|
||||
case "mmap":
|
||||
// Filter out only very wrong arguments.
|
||||
length := c.Args[1].(*ConstArg)
|
||||
if length.Val == 0 {
|
||||
break
|
||||
start, npages, mapped := analyzeMmap(c)
|
||||
if npages != 0 {
|
||||
if start+npages > uint64(len(s.pages)) {
|
||||
panic(fmt.Sprintf("address is out of bounds: page=%v len=%v bound=%v",
|
||||
start, npages, len(s.pages)))
|
||||
}
|
||||
flags := c.Args[3].(*ConstArg)
|
||||
fd := c.Args[4].(*ResultArg)
|
||||
if flags.Val&MAP_ANONYMOUS == 0 && fd.Val == InvalidFD {
|
||||
break
|
||||
for i := uint64(0); i < npages; i++ {
|
||||
s.pages[start+i] = mapped
|
||||
}
|
||||
s.addressable(c.Args[0].(*PointerArg), length, true)
|
||||
case "munmap":
|
||||
s.addressable(c.Args[0].(*PointerArg), c.Args[1].(*ConstArg), false)
|
||||
case "mremap":
|
||||
s.addressable(c.Args[4].(*PointerArg), c.Args[2].(*ConstArg), true)
|
||||
case "io_submit":
|
||||
if arr := c.Args[2].(*PointerArg).Res; arr != nil {
|
||||
for _, ptr := range arr.(*GroupArg).Inner {
|
||||
p := ptr.(*PointerArg)
|
||||
if p.Res != nil && p.Res.Type().Name() == "iocb" {
|
||||
s.resources["iocbptr"] = append(s.resources["iocbptr"], ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *state) addressable(addr *PointerArg, size *ConstArg, ok bool) {
|
||||
sizePages := size.Val / pageSize
|
||||
if addr.PageIndex+sizePages > uint64(len(s.pages)) {
|
||||
panic(fmt.Sprintf("address is out of bounds: page=%v len=%v bound=%v\naddr: %+v\nsize: %+v",
|
||||
addr.PageIndex, sizePages, len(s.pages), addr, size))
|
||||
}
|
||||
for i := uint64(0); i < sizePages; i++ {
|
||||
s.pages[addr.PageIndex+i] = ok
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,86 +151,6 @@ func foreachSubargOffset(arg Arg, f func(arg Arg, offset uint64)) {
|
||||
rec(arg, 0)
|
||||
}
|
||||
|
||||
func sanitizeCall(c *Call) {
|
||||
switch c.Meta.CallName {
|
||||
case "mmap":
|
||||
// Add MAP_FIXED flag, otherwise it produces non-deterministic results.
|
||||
_, ok := c.Args[0].(*PointerArg)
|
||||
if !ok {
|
||||
panic("mmap address is not ArgPointer")
|
||||
}
|
||||
_, ok = c.Args[1].(*ConstArg)
|
||||
if !ok {
|
||||
panic("mmap length is not ArgPageSize")
|
||||
}
|
||||
flags, ok := c.Args[3].(*ConstArg)
|
||||
if !ok {
|
||||
panic("mmap flag arg is not const")
|
||||
}
|
||||
flags.Val |= MAP_FIXED
|
||||
case "mremap":
|
||||
// Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
|
||||
flags, ok := c.Args[3].(*ConstArg)
|
||||
if !ok {
|
||||
panic("mremap flag arg is not const")
|
||||
}
|
||||
if flags.Val&MREMAP_MAYMOVE != 0 {
|
||||
flags.Val |= MREMAP_FIXED
|
||||
}
|
||||
case "mknod", "mknodat":
|
||||
mode, ok1 := c.Args[1].(*ConstArg)
|
||||
dev, ok2 := c.Args[2].(*ConstArg)
|
||||
if c.Meta.CallName == "mknodat" {
|
||||
mode, ok1 = c.Args[2].(*ConstArg)
|
||||
dev, ok2 = c.Args[3].(*ConstArg)
|
||||
}
|
||||
if !ok1 || !ok2 {
|
||||
panic("mknod mode is not const")
|
||||
}
|
||||
// Char and block devices read/write io ports, kernel memory and do other nasty things.
|
||||
// TODO: not required if executor drops privileges.
|
||||
switch mode.Val & (S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK) {
|
||||
case S_IFREG, S_IFIFO, S_IFSOCK:
|
||||
case S_IFBLK:
|
||||
if dev.Val>>8 == 7 {
|
||||
break // loop
|
||||
}
|
||||
mode.Val &^= S_IFBLK
|
||||
mode.Val |= S_IFREG
|
||||
case S_IFCHR:
|
||||
mode.Val &^= S_IFCHR
|
||||
mode.Val |= S_IFREG
|
||||
}
|
||||
case "syslog":
|
||||
cmd := c.Args[0].(*ConstArg)
|
||||
// These disable console output, but we need it.
|
||||
if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON {
|
||||
cmd.Val = SYSLOG_ACTION_SIZE_UNREAD
|
||||
}
|
||||
case "ioctl":
|
||||
cmd := c.Args[1].(*ConstArg)
|
||||
// Freeze kills machine. Though, it is an interesting functions,
|
||||
// so we need to test it somehow.
|
||||
// TODO: not required if executor drops privileges.
|
||||
if uint32(cmd.Val) == FIFREEZE {
|
||||
cmd.Val = FITHAW
|
||||
}
|
||||
case "ptrace":
|
||||
req := c.Args[0].(*ConstArg)
|
||||
// PTRACE_TRACEME leads to unkillable processes, see:
|
||||
// https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
|
||||
if req.Val == PTRACE_TRACEME {
|
||||
req.Val = ^uint64(0)
|
||||
}
|
||||
case "exit", "exit_group":
|
||||
code := c.Args[0].(*ConstArg)
|
||||
// These codes are reserved by executor.
|
||||
if code.Val%128 == 67 || code.Val%128 == 68 {
|
||||
code.Val = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RequiresBitmasks(p *Prog) bool {
|
||||
result := false
|
||||
for _, c := range p.Calls {
|
||||
|
@ -5,8 +5,6 @@ package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
type CsumChunkKind int
|
||||
|
@ -1,23 +1,26 @@
|
||||
// Copyright 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 prog
|
||||
package prog_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func TestChecksumCalcRandom(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
for _, call := range p.Calls {
|
||||
calcChecksumsCall(call, i%32)
|
||||
CalcChecksumsCall(call, i%32)
|
||||
}
|
||||
for try := 0; try <= 10; try++ {
|
||||
p.Mutate(rs, 10, nil, nil)
|
||||
for _, call := range p.Calls {
|
||||
calcChecksumsCall(call, i%32)
|
||||
CalcChecksumsCall(call, i%32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2015 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
|
||||
package prog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -10,7 +10,7 @@ import (
|
||||
func TestResourceCtors(t *testing.T) {
|
||||
for _, c := range Syscalls {
|
||||
for _, res := range c.InputResources() {
|
||||
if len(resourceCtors(res.Desc.Kind, true)) == 0 {
|
||||
if len(calcResourceCtors(res.Desc.Kind, true)) == 0 {
|
||||
t.Errorf("call %v requires input resource %v, but there are no calls that can create this resource", c.Name, res.Desc.Name)
|
||||
}
|
||||
}
|
@ -10,8 +10,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
// String generates a very compact program description (mostly for debug output).
|
||||
@ -146,7 +144,7 @@ func Deserialize(data []byte) (prog *Prog, err error) {
|
||||
}
|
||||
c := &Call{
|
||||
Meta: meta,
|
||||
Ret: returnArg(meta.Ret),
|
||||
Ret: MakeReturnArg(meta.Ret),
|
||||
}
|
||||
prog.Calls = append(prog.Calls, c)
|
||||
p.Parse('(')
|
||||
@ -213,13 +211,13 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
}
|
||||
switch typ.(type) {
|
||||
case *ConstType, *IntType, *FlagsType, *ProcType, *LenType, *CsumType:
|
||||
arg = constArg(typ, v)
|
||||
arg = MakeConstArg(typ, v)
|
||||
case *ResourceType:
|
||||
arg = resultArg(typ, nil, v)
|
||||
arg = MakeResultArg(typ, nil, v)
|
||||
case *PtrType:
|
||||
arg = pointerArg(typ, 0, 0, 0, nil)
|
||||
arg = MakePointerArg(typ, 0, 0, 0, nil)
|
||||
case *VmaType:
|
||||
arg = pointerArg(typ, 0, 0, 0, nil)
|
||||
arg = MakePointerArg(typ, 0, 0, 0, nil)
|
||||
default:
|
||||
return nil, fmt.Errorf("bad const type %+v", typ)
|
||||
}
|
||||
@ -229,7 +227,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
if !ok || v == nil {
|
||||
return nil, fmt.Errorf("result %v references unknown variable (vars=%+v)", id, vars)
|
||||
}
|
||||
arg = resultArg(typ, v, 0)
|
||||
arg = MakeResultArg(typ, v, 0)
|
||||
if p.Char() == '/' {
|
||||
p.Parse('/')
|
||||
op := p.Ident()
|
||||
@ -267,7 +265,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arg = pointerArg(typ, page, off, size, inner)
|
||||
arg = MakePointerArg(typ, page, off, size, inner)
|
||||
case '(':
|
||||
// This used to parse length of VmaType and return ArgPageSize, which is now removed.
|
||||
// Leaving this for now for backwards compatibility.
|
||||
@ -275,7 +273,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arg = constArg(typ, pages*pageSize)
|
||||
arg = MakeConstArg(typ, pages*pageSize)
|
||||
case '"':
|
||||
p.Parse('"')
|
||||
val := ""
|
||||
@ -301,7 +299,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
}
|
||||
fld := t1.Fields[i]
|
||||
if IsPad(fld) {
|
||||
inner = append(inner, constArg(fld, 0))
|
||||
inner = append(inner, MakeConstArg(fld, 0))
|
||||
} else {
|
||||
arg, err := parseArg(fld, p, vars)
|
||||
if err != nil {
|
||||
@ -317,7 +315,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
for len(inner) < len(t1.Fields) {
|
||||
inner = append(inner, defaultArg(t1.Fields[len(inner)]))
|
||||
}
|
||||
arg = groupArg(typ, inner)
|
||||
arg = MakeGroupArg(typ, inner)
|
||||
case '[':
|
||||
t1, ok := typ.(*ArrayType)
|
||||
if !ok {
|
||||
@ -336,7 +334,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
|
||||
}
|
||||
}
|
||||
p.Parse(']')
|
||||
arg = groupArg(typ, inner)
|
||||
arg = MakeGroupArg(typ, inner)
|
||||
case '@':
|
||||
t1, ok := typ.(*UnionType)
|
||||
if !ok {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 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 prog
|
||||
package prog_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -9,6 +9,9 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
. "github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func setToArray(s map[string]struct{}) []string {
|
||||
@ -76,7 +79,7 @@ func TestCallSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCallSetRandom(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
calls0 := make(map[string]struct{})
|
||||
|
@ -9,8 +9,6 @@ package prog
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -37,9 +35,6 @@ const (
|
||||
|
||||
const (
|
||||
ExecBufferSize = 2 << 20
|
||||
|
||||
pageSize = 4 << 10
|
||||
dataOffset = 512 << 20
|
||||
)
|
||||
|
||||
type Args []Arg
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 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 prog
|
||||
package prog_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -9,13 +9,12 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
. "github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
const ptrSize = 8
|
||||
|
||||
func TestSerializeForExecRandom(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
buf := make([]byte, ExecBufferSize)
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
@ -46,6 +45,10 @@ func TestSerializeForExec(t *testing.T) {
|
||||
argResult = uint64(ExecArgResult)
|
||||
argData = uint64(ExecArgData)
|
||||
)
|
||||
var (
|
||||
dataOffset = DataOffset()
|
||||
ptrSize = PtrSize()
|
||||
)
|
||||
callID := func(name string) uint64 {
|
||||
c := SyscallMap[name]
|
||||
if c == nil {
|
||||
|
47
prog/export_test.go
Normal file
47
prog/export_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2017 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 prog
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Export guts for testing.
|
||||
|
||||
func init() {
|
||||
debug = true
|
||||
}
|
||||
|
||||
var (
|
||||
CalcChecksumsCall = calcChecksumsCall
|
||||
AssignSizesCall = assignSizesCall
|
||||
DefaultArg = defaultArg
|
||||
InitTest = initTest
|
||||
)
|
||||
|
||||
func PtrSize() uint64 {
|
||||
return ptrSize
|
||||
}
|
||||
|
||||
func DataOffset() uint64 {
|
||||
return dataOffset
|
||||
}
|
||||
|
||||
func PageSize() uint64 {
|
||||
return pageSize
|
||||
}
|
||||
|
||||
func initTest(t *testing.T) (rand.Source, int) {
|
||||
t.Parallel()
|
||||
iters := 10000
|
||||
if testing.Short() {
|
||||
iters = 100
|
||||
}
|
||||
seed := int64(time.Now().UnixNano())
|
||||
rs := rand.NewSource(seed)
|
||||
t.Logf("seed=%v", seed)
|
||||
return rs, iters
|
||||
}
|
@ -20,8 +20,6 @@ package prog
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
type uint64Set map[uint64]bool
|
||||
@ -95,7 +93,7 @@ func generateHints(p *Prog, compMap CompMap, c *Call, arg Arg, exec func(p *Prog
|
||||
|
||||
switch a := arg.(type) {
|
||||
case *ConstArg:
|
||||
originalArg = constArg(a.Type(), a.Val)
|
||||
originalArg = MakeConstArg(a.Type(), a.Val)
|
||||
checkConstArg(a, compMap, constArgCandidate)
|
||||
case *DataArg:
|
||||
originalArg = dataArg(a.Type(), a.Data)
|
||||
@ -105,7 +103,7 @@ func generateHints(p *Prog, compMap CompMap, c *Call, arg Arg, exec func(p *Prog
|
||||
|
||||
func checkConstArg(arg *ConstArg, compMap CompMap, cb func(newArg Arg)) {
|
||||
for replacer := range shrinkExpand(arg.Val, compMap) {
|
||||
cb(constArg(arg.typ, replacer))
|
||||
cb(MakeConstArg(arg.typ, replacer))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
type ConstArgTest struct {
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"unsafe"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Prog) {
|
||||
@ -178,11 +176,11 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
|
||||
arg1, calls1 := r.addr(s, t, size, a.Res)
|
||||
p.replaceArg(c, arg, arg1, calls1)
|
||||
case *StructType:
|
||||
ctor := isSpecialStruct(t)
|
||||
if ctor == nil {
|
||||
gen := specialStructs[t.Name()]
|
||||
if gen == nil {
|
||||
panic("bad arg returned by mutationArgs: StructType")
|
||||
}
|
||||
arg1, calls1 := ctor(r, s)
|
||||
arg1, calls1 := gen(&Gen{r, s}, t, arg.(*GroupArg))
|
||||
for i, f := range arg1.(*GroupArg).Inner {
|
||||
p.replaceArg(c, arg.(*GroupArg).Inner[i], f, calls1)
|
||||
calls1 = nil
|
||||
@ -255,7 +253,16 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
|
||||
// predicate pred. It iteratively generates simpler programs and asks pred
|
||||
// whether it is equal to the orginal program or not. If it is equivalent then
|
||||
// the simplification attempt is committed and the process continues.
|
||||
func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool) (*Prog, int) {
|
||||
func Minimize(p0 *Prog, callIndex0 int, pred0 func(*Prog, int) bool, crash bool) (*Prog, int) {
|
||||
pred := pred0
|
||||
if debug {
|
||||
pred = func(p *Prog, callIndex int) bool {
|
||||
if err := p.validate(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return pred0(p, callIndex)
|
||||
}
|
||||
}
|
||||
name0 := ""
|
||||
if callIndex0 != -1 {
|
||||
if callIndex0 < 0 || callIndex0 >= len(p0.Calls) {
|
||||
@ -291,7 +298,7 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
|
||||
}
|
||||
}
|
||||
// Prepend uber-mmap.
|
||||
mmap := createMmapCall(uint64(lo), uint64(hi-lo)+1)
|
||||
mmap := makeMmap(uint64(lo), uint64(hi-lo)+1)
|
||||
p.Calls = append([]*Call{mmap}, p.Calls...)
|
||||
if callIndex != -1 {
|
||||
callIndex++
|
||||
@ -496,7 +503,7 @@ func mutationArgs(c *Call) (args, bases []Arg) {
|
||||
foreachArg(c, func(arg, base Arg, _ *[]Arg) {
|
||||
switch typ := arg.Type().(type) {
|
||||
case *StructType:
|
||||
if isSpecialStruct(typ) == nil {
|
||||
if specialStructs[typ.Name()] == nil {
|
||||
// For structs only individual fields are updated.
|
||||
return
|
||||
}
|
||||
@ -524,7 +531,7 @@ func mutationArgs(c *Call) (args, bases []Arg) {
|
||||
return
|
||||
}
|
||||
if base != nil {
|
||||
if _, ok := base.Type().(*StructType); ok && isSpecialStruct(base.Type()) != nil {
|
||||
if _, ok := base.Type().(*StructType); ok && specialStructs[base.Type().Name()] != nil {
|
||||
// These special structs are mutated as a whole.
|
||||
return
|
||||
}
|
||||
|
@ -1,16 +1,19 @@
|
||||
// Copyright 2015 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 prog
|
||||
package prog_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
p1 := p.Clone()
|
||||
@ -23,7 +26,7 @@ func TestClone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMutate(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
next:
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
@ -47,7 +50,7 @@ next:
|
||||
}
|
||||
|
||||
func TestMutateCorpus(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
var corpus []*Prog
|
||||
for i := 0; i < 100; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
@ -137,7 +140,7 @@ func TestMutateTable(t *testing.T) {
|
||||
"readv(r0, &(0x7f0000000000)=[{&(0x7f0000001000)=\"00\", 0x1}, {&(0x7f0000002000)=\"00\", 0x2}, {&(0x7f0000000000)=\"00\", 0x3}], 0x3)\n",
|
||||
},
|
||||
}
|
||||
rs, _ := initTest(t)
|
||||
rs, _ := InitTest(t)
|
||||
nextTest:
|
||||
for ti, test := range tests {
|
||||
p, err := Deserialize([]byte(test[0]))
|
||||
@ -288,35 +291,23 @@ func TestMinimize(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMinimizeRandom(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
iters /= 10 // Long test.
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 5, nil)
|
||||
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
|
||||
if err := p1.validate(); err != nil {
|
||||
t.Fatalf("invalid program: %v", err)
|
||||
}
|
||||
return false
|
||||
}, true)
|
||||
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
|
||||
if err := p1.validate(); err != nil {
|
||||
t.Fatalf("invalid program: %v", err)
|
||||
}
|
||||
return true
|
||||
}, true)
|
||||
}
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 5, nil)
|
||||
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
|
||||
if err := p1.validate(); err != nil {
|
||||
t.Fatalf("invalid program: %v", err)
|
||||
}
|
||||
return false
|
||||
}, false)
|
||||
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
|
||||
if err := p1.validate(); err != nil {
|
||||
t.Fatalf("invalid program: %v", err)
|
||||
}
|
||||
return true
|
||||
}, false)
|
||||
}
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sort"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
// Calulation of call-to-call priorities.
|
||||
|
26
prog/prog.go
26
prog/prog.go
@ -5,8 +5,6 @@ package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
type Prog struct {
|
||||
@ -224,11 +222,11 @@ func encodeValue(value uint64, size uint64, bigEndian bool) uint64 {
|
||||
}
|
||||
}
|
||||
|
||||
func constArg(t Type, v uint64) Arg {
|
||||
func MakeConstArg(t Type, v uint64) Arg {
|
||||
return &ConstArg{ArgCommon: ArgCommon{typ: t}, Val: v}
|
||||
}
|
||||
|
||||
func resultArg(t Type, r Arg, v uint64) Arg {
|
||||
func MakeResultArg(t Type, r Arg, v uint64) Arg {
|
||||
arg := &ResultArg{ArgCommon: ArgCommon{typ: t}, Res: r, Val: v}
|
||||
if r == nil {
|
||||
return arg
|
||||
@ -249,11 +247,11 @@ func dataArg(t Type, data []byte) Arg {
|
||||
return &DataArg{ArgCommon: ArgCommon{typ: t}, Data: append([]byte{}, data...)}
|
||||
}
|
||||
|
||||
func pointerArg(t Type, page uint64, off int, npages uint64, obj Arg) Arg {
|
||||
func MakePointerArg(t Type, page uint64, off int, npages uint64, obj Arg) Arg {
|
||||
return &PointerArg{ArgCommon: ArgCommon{typ: t}, PageIndex: page, PageOffset: off, PagesNum: npages, Res: obj}
|
||||
}
|
||||
|
||||
func groupArg(t Type, inner []Arg) Arg {
|
||||
func MakeGroupArg(t Type, inner []Arg) Arg {
|
||||
return &GroupArg{ArgCommon: ArgCommon{typ: t}, Inner: inner}
|
||||
}
|
||||
|
||||
@ -261,16 +259,16 @@ func unionArg(t Type, opt Arg, typ Type) Arg {
|
||||
return &UnionArg{ArgCommon: ArgCommon{typ: t}, Option: opt, OptionType: typ}
|
||||
}
|
||||
|
||||
func returnArg(t Type) Arg {
|
||||
func MakeReturnArg(t Type) Arg {
|
||||
return &ReturnArg{ArgCommon: ArgCommon{typ: t}}
|
||||
}
|
||||
|
||||
func defaultArg(t Type) Arg {
|
||||
switch typ := t.(type) {
|
||||
case *IntType, *ConstType, *FlagsType, *LenType, *ProcType, *CsumType:
|
||||
return constArg(t, t.Default())
|
||||
return MakeConstArg(t, t.Default())
|
||||
case *ResourceType:
|
||||
return resultArg(t, nil, typ.Desc.Type.Default())
|
||||
return MakeResultArg(t, nil, typ.Desc.Type.Default())
|
||||
case *BufferType:
|
||||
var data []byte
|
||||
if typ.Kind == BufferString && typ.TypeSize != 0 {
|
||||
@ -278,23 +276,23 @@ func defaultArg(t Type) Arg {
|
||||
}
|
||||
return dataArg(t, data)
|
||||
case *ArrayType:
|
||||
return groupArg(t, nil)
|
||||
return MakeGroupArg(t, nil)
|
||||
case *StructType:
|
||||
var inner []Arg
|
||||
for _, field := range typ.Fields {
|
||||
inner = append(inner, defaultArg(field))
|
||||
}
|
||||
return groupArg(t, inner)
|
||||
return MakeGroupArg(t, inner)
|
||||
case *UnionType:
|
||||
return unionArg(t, defaultArg(typ.Fields[0]), typ.Fields[0])
|
||||
case *VmaType:
|
||||
return pointerArg(t, 0, 0, 1, nil)
|
||||
return MakePointerArg(t, 0, 0, 1, nil)
|
||||
case *PtrType:
|
||||
var res Arg
|
||||
if !t.Optional() && t.Dir() != DirOut {
|
||||
res = defaultArg(typ.Type)
|
||||
}
|
||||
return pointerArg(t, 0, 0, 0, res)
|
||||
return MakePointerArg(t, 0, 0, 0, res)
|
||||
default:
|
||||
panic("unknown arg type")
|
||||
}
|
||||
@ -364,7 +362,7 @@ func (p *Prog) removeArg(c *Call, arg0 Arg) {
|
||||
if _, ok := arg1.(*ResultArg); !ok {
|
||||
panic("use references not ArgResult")
|
||||
}
|
||||
arg2 := resultArg(arg1.Type(), nil, arg1.Type().Default())
|
||||
arg2 := MakeResultArg(arg1.Type(), nil, arg1.Type().Default())
|
||||
p.replaceArg(c, arg1, arg2, nil)
|
||||
}
|
||||
}
|
||||
|
@ -6,47 +6,29 @@ package prog
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
//. "github.com/google/syzkaller/prog"
|
||||
//_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func init() {
|
||||
debug = true
|
||||
}
|
||||
|
||||
func initTest(t *testing.T) (rand.Source, int) {
|
||||
t.Parallel()
|
||||
iters := 10000
|
||||
if testing.Short() {
|
||||
iters = 100
|
||||
}
|
||||
seed := int64(time.Now().UnixNano())
|
||||
rs := rand.NewSource(seed)
|
||||
t.Logf("seed=%v", seed)
|
||||
return rs, iters
|
||||
}
|
||||
|
||||
func TestGeneration(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
for i := 0; i < iters; i++ {
|
||||
Generate(rs, 20, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
initTest(t)
|
||||
InitTest(t)
|
||||
for _, meta := range SyscallMap {
|
||||
for _, t := range meta.Args {
|
||||
defaultArg(t)
|
||||
DefaultArg(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultCallArgs(t *testing.T) {
|
||||
initTest(t)
|
||||
InitTest(t)
|
||||
for _, meta := range SyscallMap {
|
||||
// Ensure that we can restore all arguments of all calls.
|
||||
prog := fmt.Sprintf("%v()", meta.Name)
|
||||
@ -61,7 +43,7 @@ func TestDefaultCallArgs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSerialize(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
data := p.Serialize()
|
||||
@ -83,9 +65,10 @@ func TestSerialize(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVmaType(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
meta := SyscallMap["syz_test$vma0"]
|
||||
r := newRand(rs)
|
||||
pageSize := PageSize()
|
||||
for i := 0; i < iters; i++ {
|
||||
s := newState(nil)
|
||||
calls := r.generateParticularCall(s, meta)
|
||||
|
141
prog/rand.go
141
prog/rand.go
@ -12,7 +12,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/google/syzkaller/pkg/ifuzz"
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
var pageStartPool = sync.Pool{New: func() interface{} { return new([]uint64) }}
|
||||
@ -224,102 +223,6 @@ func (r *randGen) randStringImpl(s *state, vals []string) []byte {
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func isSpecialStruct(typ Type) func(r *randGen, s *state) (Arg, []*Call) {
|
||||
a, ok := typ.(*StructType)
|
||||
if !ok {
|
||||
panic("must be a struct")
|
||||
}
|
||||
switch typ.Name() {
|
||||
case "timespec":
|
||||
return func(r *randGen, s *state) (Arg, []*Call) {
|
||||
return r.timespec(s, a, false)
|
||||
}
|
||||
case "timeval":
|
||||
return func(r *randGen, s *state) (Arg, []*Call) {
|
||||
return r.timespec(s, a, true)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *randGen) timespec(s *state, typ *StructType, usec bool) (arg Arg, calls []*Call) {
|
||||
// We need to generate timespec/timeval that are either (1) definitely in the past,
|
||||
// or (2) definitely in unreachable fututre, or (3) few ms ahead of now.
|
||||
// Note timespec/timeval can be absolute or relative to now.
|
||||
switch {
|
||||
case r.nOutOf(1, 4):
|
||||
// now for relative, past for absolute
|
||||
arg = groupArg(typ, []Arg{
|
||||
resultArg(typ.Fields[0], nil, 0),
|
||||
resultArg(typ.Fields[1], nil, 0),
|
||||
})
|
||||
case r.nOutOf(1, 3):
|
||||
// few ms ahead for relative, past for absolute
|
||||
nsec := uint64(10 * 1e6)
|
||||
if usec {
|
||||
nsec /= 1e3
|
||||
}
|
||||
arg = groupArg(typ, []Arg{
|
||||
resultArg(typ.Fields[0], nil, 0),
|
||||
resultArg(typ.Fields[1], nil, nsec),
|
||||
})
|
||||
case r.nOutOf(1, 2):
|
||||
// unreachable fututre for both relative and absolute
|
||||
arg = groupArg(typ, []Arg{
|
||||
resultArg(typ.Fields[0], nil, 2e9),
|
||||
resultArg(typ.Fields[1], nil, 0),
|
||||
})
|
||||
default:
|
||||
// few ms ahead for absolute
|
||||
meta := SyscallMap["clock_gettime"]
|
||||
ptrArgType := meta.Args[1].(*PtrType)
|
||||
argType := ptrArgType.Type.(*StructType)
|
||||
tp := groupArg(argType, []Arg{
|
||||
resultArg(argType.Fields[0], nil, 0),
|
||||
resultArg(argType.Fields[1], nil, 0),
|
||||
})
|
||||
var tpaddr Arg
|
||||
tpaddr, calls = r.addr(s, ptrArgType, 16, tp)
|
||||
gettime := &Call{
|
||||
Meta: meta,
|
||||
Args: []Arg{
|
||||
constArg(meta.Args[0], CLOCK_REALTIME),
|
||||
tpaddr,
|
||||
},
|
||||
Ret: returnArg(meta.Ret),
|
||||
}
|
||||
calls = append(calls, gettime)
|
||||
sec := resultArg(typ.Fields[0], tp.(*GroupArg).Inner[0], 0)
|
||||
nsec := resultArg(typ.Fields[1], tp.(*GroupArg).Inner[1], 0)
|
||||
if usec {
|
||||
nsec.(*ResultArg).OpDiv = 1e3
|
||||
nsec.(*ResultArg).OpAdd = 10 * 1e3
|
||||
} else {
|
||||
nsec.(*ResultArg).OpAdd = 10 * 1e6
|
||||
}
|
||||
arg = groupArg(typ, []Arg{sec, nsec})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range.
|
||||
func createMmapCall(start, npages uint64) *Call {
|
||||
meta := SyscallMap["mmap"]
|
||||
mmap := &Call{
|
||||
Meta: meta,
|
||||
Args: []Arg{
|
||||
pointerArg(meta.Args[0], start, 0, npages, nil),
|
||||
constArg(meta.Args[1], npages*pageSize),
|
||||
constArg(meta.Args[2], PROT_READ|PROT_WRITE),
|
||||
constArg(meta.Args[3], MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED),
|
||||
resultArg(meta.Args[4], nil, InvalidFD),
|
||||
constArg(meta.Args[5], 0),
|
||||
},
|
||||
Ret: returnArg(meta.Ret),
|
||||
}
|
||||
return mmap
|
||||
}
|
||||
|
||||
func (r *randGen) addr1(s *state, typ Type, size uint64, data Arg) (Arg, []*Call) {
|
||||
npages := (size + pageSize - 1) / pageSize
|
||||
if npages == 0 {
|
||||
@ -339,8 +242,8 @@ func (r *randGen) addr1(s *state, typ Type, size uint64, data Arg) (Arg, []*Call
|
||||
if !free {
|
||||
continue
|
||||
}
|
||||
c := createMmapCall(i, npages)
|
||||
return pointerArg(typ, i, 0, 0, data), []*Call{c}
|
||||
c := makeMmap(i, npages)
|
||||
return MakePointerArg(typ, i, 0, 0, data), []*Call{c}
|
||||
}
|
||||
return r.randPageAddr(s, typ, npages, data, false), nil
|
||||
}
|
||||
@ -357,7 +260,7 @@ func (r *randGen) addr(s *state, typ Type, size uint64, data Arg) (Arg, []*Call)
|
||||
case r.nOutOf(50, 52):
|
||||
a.PageOffset = -int(size)
|
||||
case r.nOutOf(1, 2):
|
||||
a.PageOffset = r.Intn(pageSize)
|
||||
a.PageOffset = r.Intn(int(pageSize))
|
||||
default:
|
||||
if size > 0 {
|
||||
a.PageOffset = -r.Intn(int(size))
|
||||
@ -395,13 +298,13 @@ func (r *randGen) randPageAddr(s *state, typ Type, npages uint64, data Arg, vma
|
||||
}
|
||||
*poolPtr = starts
|
||||
pageStartPool.Put(poolPtr)
|
||||
return pointerArg(typ, page, 0, npages, data)
|
||||
return MakePointerArg(typ, page, 0, npages, data)
|
||||
}
|
||||
|
||||
func (r *randGen) createResource(s *state, res *ResourceType) (arg Arg, calls []*Call) {
|
||||
if r.inCreateResource {
|
||||
special := res.SpecialValues()
|
||||
return resultArg(res, nil, special[r.Intn(len(special))]), nil
|
||||
return MakeResultArg(res, nil, special[r.Intn(len(special))]), nil
|
||||
}
|
||||
r.inCreateResource = true
|
||||
defer func() { r.inCreateResource = false }()
|
||||
@ -428,7 +331,7 @@ func (r *randGen) createResource(s *state, res *ResourceType) (arg Arg, calls []
|
||||
metas = append(metas, meta)
|
||||
}
|
||||
if len(metas) == 0 {
|
||||
return resultArg(res, nil, res.Default()), nil
|
||||
return MakeResultArg(res, nil, res.Default()), nil
|
||||
}
|
||||
|
||||
// Now we have a set of candidate calls that can create the necessary resource.
|
||||
@ -447,7 +350,7 @@ func (r *randGen) createResource(s *state, res *ResourceType) (arg Arg, calls []
|
||||
}
|
||||
if len(allres) != 0 {
|
||||
// Bingo!
|
||||
arg := resultArg(res, allres[r.Intn(len(allres))], 0)
|
||||
arg := MakeResultArg(res, allres[r.Intn(len(allres))], 0)
|
||||
return arg, calls
|
||||
}
|
||||
// Discard unsuccessful calls.
|
||||
@ -550,7 +453,7 @@ func (r *randGen) generateCall(s *state, p *Prog) []*Call {
|
||||
func (r *randGen) generateParticularCall(s *state, meta *Syscall) (calls []*Call) {
|
||||
c := &Call{
|
||||
Meta: meta,
|
||||
Ret: returnArg(meta.Ret),
|
||||
Ret: MakeReturnArg(meta.Ret),
|
||||
}
|
||||
c.Args, calls = r.generateArgs(s, meta.Args)
|
||||
assignSizesCall(c)
|
||||
@ -629,7 +532,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
}
|
||||
}()
|
||||
if r.recDepth[str.Name()] >= 3 {
|
||||
return pointerArg(typ, 0, 0, 0, nil), nil
|
||||
return MakePointerArg(typ, 0, 0, 0, nil), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -650,7 +553,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
}
|
||||
}
|
||||
if len(allres) != 0 {
|
||||
arg = resultArg(a, allres[r.Intn(len(allres))], 0)
|
||||
arg = MakeResultArg(a, allres[r.Intn(len(allres))], 0)
|
||||
} else {
|
||||
arg, calls = r.createResource(s, a)
|
||||
}
|
||||
@ -659,7 +562,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
arg, calls = r.createResource(s, a)
|
||||
default:
|
||||
special := a.SpecialValues()
|
||||
arg = resultArg(a, nil, special[r.Intn(len(special))])
|
||||
arg = MakeResultArg(a, nil, special[r.Intn(len(special))])
|
||||
}
|
||||
return arg, calls
|
||||
case *BufferType:
|
||||
@ -707,9 +610,9 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
arg := r.randPageAddr(s, a, npages, nil, true)
|
||||
return arg, nil
|
||||
case *FlagsType:
|
||||
return constArg(a, r.flags(a.Vals)), nil
|
||||
return MakeConstArg(a, r.flags(a.Vals)), nil
|
||||
case *ConstType:
|
||||
return constArg(a, a.Val), nil
|
||||
return MakeConstArg(a, a.Val), nil
|
||||
case *IntType:
|
||||
v := r.randInt()
|
||||
switch a.Kind {
|
||||
@ -725,9 +628,9 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
case IntRange:
|
||||
v = r.randRangeInt(a.RangeBegin, a.RangeEnd)
|
||||
}
|
||||
return constArg(a, v), nil
|
||||
return MakeConstArg(a, v), nil
|
||||
case *ProcType:
|
||||
return constArg(a, r.rand(int(a.ValuesPerProc))), nil
|
||||
return MakeConstArg(a, r.rand(int(a.ValuesPerProc))), nil
|
||||
case *ArrayType:
|
||||
var count uint64
|
||||
switch a.Kind {
|
||||
@ -743,14 +646,14 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
inner = append(inner, arg1)
|
||||
calls = append(calls, calls1...)
|
||||
}
|
||||
return groupArg(a, inner), calls
|
||||
return MakeGroupArg(a, inner), calls
|
||||
case *StructType:
|
||||
if ctor := isSpecialStruct(a); ctor != nil && a.Dir() != DirOut {
|
||||
arg, calls = ctor(r, s)
|
||||
if gen := specialStructs[a.Name()]; gen != nil && a.Dir() != DirOut {
|
||||
arg, calls = gen(&Gen{r, s}, a, nil)
|
||||
return
|
||||
}
|
||||
args, calls := r.generateArgs(s, a.Fields)
|
||||
group := groupArg(a, args)
|
||||
group := MakeGroupArg(a, args)
|
||||
return group, calls
|
||||
case *UnionType:
|
||||
optType := a.Fields[r.Intn(len(a.Fields))]
|
||||
@ -763,7 +666,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
// So try to reuse a previously used address.
|
||||
addrs := s.resources["iocbptr"]
|
||||
addr := addrs[r.Intn(len(addrs))].(*PointerArg)
|
||||
arg = pointerArg(a, addr.PageIndex, addr.PageOffset, addr.PagesNum, inner)
|
||||
arg = MakePointerArg(a, addr.PageIndex, addr.PageOffset, addr.PagesNum, inner)
|
||||
return arg, calls
|
||||
}
|
||||
arg, calls1 := r.addr(s, a, inner.Size(), inner)
|
||||
@ -771,9 +674,9 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
|
||||
return arg, calls
|
||||
case *LenType:
|
||||
// Return placeholder value of 0 while generating len arg.
|
||||
return constArg(a, 0), nil
|
||||
return MakeConstArg(a, 0), nil
|
||||
case *CsumType:
|
||||
return constArg(a, 0), nil
|
||||
return MakeConstArg(a, 0), nil
|
||||
default:
|
||||
panic("unknown argument type")
|
||||
}
|
||||
|
14
prog/size.go
14
prog/size.go
@ -5,32 +5,30 @@ package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func generateSize(arg Arg, lenType *LenType) Arg {
|
||||
if arg == nil {
|
||||
// Arg is an optional pointer, set size to 0.
|
||||
return constArg(lenType, 0)
|
||||
return MakeConstArg(lenType, 0)
|
||||
}
|
||||
|
||||
switch arg.Type().(type) {
|
||||
case *VmaType:
|
||||
a := arg.(*PointerArg)
|
||||
return constArg(lenType, a.PagesNum*pageSize)
|
||||
return MakeConstArg(lenType, a.PagesNum*pageSize)
|
||||
case *ArrayType:
|
||||
a := arg.(*GroupArg)
|
||||
if lenType.ByteSize != 0 {
|
||||
return constArg(lenType, a.Size()/lenType.ByteSize)
|
||||
return MakeConstArg(lenType, a.Size()/lenType.ByteSize)
|
||||
} else {
|
||||
return constArg(lenType, uint64(len(a.Inner)))
|
||||
return MakeConstArg(lenType, uint64(len(a.Inner)))
|
||||
}
|
||||
default:
|
||||
if lenType.ByteSize != 0 {
|
||||
return constArg(lenType, arg.Size()/lenType.ByteSize)
|
||||
return MakeConstArg(lenType, arg.Size()/lenType.ByteSize)
|
||||
} else {
|
||||
return constArg(lenType, arg.Size())
|
||||
return MakeConstArg(lenType, arg.Size())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,24 @@
|
||||
// Copyright 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 prog
|
||||
package prog_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func TestAssignSizeRandom(t *testing.T) {
|
||||
rs, iters := initTest(t)
|
||||
rs, iters := InitTest(t)
|
||||
for i := 0; i < iters; i++ {
|
||||
p := Generate(rs, 10, nil)
|
||||
data0 := p.Serialize()
|
||||
for _, call := range p.Calls {
|
||||
assignSizesCall(call)
|
||||
AssignSizesCall(call)
|
||||
}
|
||||
if data1 := p.Serialize(); !bytes.Equal(data0, data1) {
|
||||
t.Fatalf("different lens assigned, initial: %v, new: %v", data0, data1)
|
||||
@ -23,7 +26,7 @@ func TestAssignSizeRandom(t *testing.T) {
|
||||
p.Mutate(rs, 10, nil, nil)
|
||||
data0 = p.Serialize()
|
||||
for _, call := range p.Calls {
|
||||
assignSizesCall(call)
|
||||
AssignSizesCall(call)
|
||||
}
|
||||
if data1 := p.Serialize(); !bytes.Equal(data0, data1) {
|
||||
t.Fatalf("different lens assigned, initial: %v, new: %v", data0, data1)
|
||||
@ -128,7 +131,7 @@ func TestAssignSize(t *testing.T) {
|
||||
t.Fatalf("failed to deserialize prog %v: %v", i, err)
|
||||
}
|
||||
for _, call := range p.Calls {
|
||||
assignSizesCall(call)
|
||||
AssignSizesCall(call)
|
||||
}
|
||||
p1 := strings.TrimSpace(string(p.Serialize()))
|
||||
if p1 != test.sizedProg {
|
||||
|
117
prog/target.go
Normal file
117
prog/target.go
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright 2017 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 prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Target describes target OS/arch pair.
|
||||
type Target struct {
|
||||
OS string
|
||||
Arch string
|
||||
PtrSize uint64
|
||||
PageSize uint64
|
||||
DataOffset uint64
|
||||
|
||||
Syscalls []*Syscall
|
||||
Resources []*ResourceDesc
|
||||
|
||||
// MakeMmap creates call that maps [start, start+npages) page range.
|
||||
MakeMmap func(start, npages uint64) *Call
|
||||
|
||||
// AnalyzeMmap analyzes the call c regarding mapping/unmapping memory.
|
||||
// If it maps/unmaps any memory returns [start, start+npages) range,
|
||||
// otherwise returns npages = 0.
|
||||
AnalyzeMmap func(c *Call) (start, npages uint64, mapped bool)
|
||||
|
||||
// SanitizeCall neutralizes harmful calls.
|
||||
SanitizeCall func(c *Call)
|
||||
|
||||
// SpecialStructs allows target to do custom generation/mutation for some struct types.
|
||||
// Map key is struct name for which custom generation/mutation is required.
|
||||
// Map value is custom generation/mutation function that will be called
|
||||
// for the corresponding structs. g is helper object that allows generate random numbers,
|
||||
// allocate memory, etc. typ is the struct type. old is the old value of the struct
|
||||
// for mutation, or nil for generation. The function returns a new value of the struct,
|
||||
// and optionally any calls that need to be inserted before the arg reference.
|
||||
SpecialStructs map[string]func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
|
||||
|
||||
resourceMap map[string]*ResourceDesc
|
||||
syscallMap map[string]*Syscall
|
||||
resourceCtors map[string][]*Syscall
|
||||
}
|
||||
|
||||
type StructGen func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
|
||||
|
||||
var targets = make(map[string]*Target)
|
||||
|
||||
func RegisterTarget(target *Target) {
|
||||
key := target.OS + "/" + target.Arch
|
||||
if targets[key] != nil {
|
||||
panic(fmt.Sprintf("duplicate target %v", key))
|
||||
}
|
||||
initTarget(target)
|
||||
targets[key] = target
|
||||
|
||||
// For now we copy target to global vars
|
||||
// because majority of the code is not prepared for multiple targets.
|
||||
if len(targets) > 1 {
|
||||
panic("only 1 target is supported")
|
||||
}
|
||||
Syscalls = target.Syscalls
|
||||
SyscallMap = target.syscallMap
|
||||
Resources = target.resourceMap
|
||||
resourceCtors = target.resourceCtors
|
||||
ptrSize = target.PtrSize
|
||||
pageSize = target.PageSize
|
||||
dataOffset = target.DataOffset
|
||||
|
||||
makeMmap = target.MakeMmap
|
||||
analyzeMmap = target.AnalyzeMmap
|
||||
sanitizeCall = target.SanitizeCall
|
||||
specialStructs = target.SpecialStructs
|
||||
}
|
||||
|
||||
func initTarget(target *Target) {
|
||||
target.syscallMap = make(map[string]*Syscall)
|
||||
for _, c := range target.Syscalls {
|
||||
target.syscallMap[c.Name] = c
|
||||
}
|
||||
target.resourceMap = make(map[string]*ResourceDesc)
|
||||
target.resourceCtors = make(map[string][]*Syscall)
|
||||
for _, r := range target.Resources {
|
||||
target.resourceMap[r.Name] = r
|
||||
target.resourceCtors[r.Name] = calcResourceCtors(r.Kind, false)
|
||||
}
|
||||
}
|
||||
|
||||
type Gen struct {
|
||||
r *randGen
|
||||
s *state
|
||||
}
|
||||
|
||||
func (g *Gen) NOutOf(n, outOf int) bool {
|
||||
return g.r.nOutOf(n, outOf)
|
||||
}
|
||||
|
||||
func (g *Gen) Alloc(ptrType Type, data Arg) (Arg, []*Call) {
|
||||
return g.r.addr(g.s, ptrType, data.Size(), data)
|
||||
}
|
||||
|
||||
var (
|
||||
ptrSize uint64
|
||||
pageSize uint64
|
||||
dataOffset uint64
|
||||
|
||||
Syscalls []*Syscall
|
||||
SyscallMap map[string]*Syscall
|
||||
Resources map[string]*ResourceDesc
|
||||
resourceCtors map[string][]*Syscall
|
||||
|
||||
makeMmap func(start, npages uint64) *Call
|
||||
analyzeMmap func(c *Call) (start, npages uint64, mapped bool)
|
||||
sanitizeCall func(c *Call)
|
||||
specialStructs map[string]func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
|
||||
)
|
@ -1,7 +1,7 @@
|
||||
// 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
|
||||
package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -95,10 +95,6 @@ func (t TypeCommon) Dir() Dir {
|
||||
return t.ArgDir
|
||||
}
|
||||
|
||||
const (
|
||||
InvalidFD = ^uint64(0)
|
||||
)
|
||||
|
||||
type ResourceDesc struct {
|
||||
Name string
|
||||
Type Type
|
||||
@ -267,12 +263,6 @@ func (t *UnionType) FieldName() string {
|
||||
return t.FldName
|
||||
}
|
||||
|
||||
var (
|
||||
SyscallMap = make(map[string]*Syscall)
|
||||
Resources map[string]*ResourceDesc
|
||||
ctors = make(map[string][]*Syscall)
|
||||
)
|
||||
|
||||
type StructDesc struct {
|
||||
TypeCommon
|
||||
Fields []Type
|
||||
@ -293,53 +283,12 @@ type KeyedStruct struct {
|
||||
Desc *StructDesc
|
||||
}
|
||||
|
||||
func initStructFields() {
|
||||
keyedStructs := make(map[StructKey]*StructDesc)
|
||||
for _, desc := range structDescs {
|
||||
keyedStructs[desc.Key] = desc.Desc
|
||||
}
|
||||
|
||||
for _, c := range Syscalls {
|
||||
ForeachType(c, func(t Type) {
|
||||
switch s := t.(type) {
|
||||
case *StructType:
|
||||
s.StructDesc = keyedStructs[s.Key]
|
||||
if s.StructDesc == nil {
|
||||
panic("no struct desc")
|
||||
}
|
||||
case *UnionType:
|
||||
s.StructDesc = keyedStructs[s.Key]
|
||||
if s.StructDesc == nil {
|
||||
panic("no union desc")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceConstructors returns a list of calls that can create a resource of the given kind.
|
||||
func ResourceConstructors(name string) []*Syscall {
|
||||
return ctors[name]
|
||||
return resourceCtors[name]
|
||||
}
|
||||
|
||||
func initResources() {
|
||||
Resources = make(map[string]*ResourceDesc)
|
||||
for _, res := range resourceArray {
|
||||
Resources[res.Name] = res
|
||||
}
|
||||
for _, c := range Syscalls {
|
||||
ForeachType(c, func(t Type) {
|
||||
if r, ok := t.(*ResourceType); ok {
|
||||
r.Desc = Resources[r.TypeName]
|
||||
}
|
||||
})
|
||||
}
|
||||
for _, res := range resourceArray {
|
||||
ctors[res.Name] = resourceCtors(res.Kind, false)
|
||||
}
|
||||
}
|
||||
|
||||
func resourceCtors(kind []string, precise bool) []*Syscall {
|
||||
func calcResourceCtors(kind []string, precise bool) []*Syscall {
|
||||
// Find calls that produce the necessary resources.
|
||||
var metas []*Syscall
|
||||
for _, meta := range Syscalls {
|
||||
@ -426,7 +375,7 @@ func TransitivelyEnabledCalls(enabled map[*Syscall]bool) map[*Syscall]bool {
|
||||
if _, ok := ctors[res.Desc.Name]; ok {
|
||||
continue
|
||||
}
|
||||
ctors[res.Desc.Name] = resourceCtors(res.Desc.Kind, true)
|
||||
ctors[res.Desc.Name] = calcResourceCtors(res.Desc.Kind, true)
|
||||
}
|
||||
}
|
||||
for {
|
||||
@ -506,17 +455,3 @@ func ForeachType(meta *Syscall, f func(Type)) {
|
||||
rec(meta.Ret)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
initStructFields()
|
||||
initResources()
|
||||
structDescs = nil
|
||||
|
||||
for _, c := range Syscalls {
|
||||
if SyscallMap[c.Name] != nil {
|
||||
println(c.Name)
|
||||
panic("duplicate syscall")
|
||||
}
|
||||
SyscallMap[c.Name] = c
|
||||
}
|
||||
}
|
@ -5,8 +5,6 @@ package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
var debug = false // enabled in tests
|
||||
|
257
sys/init.go
Normal file
257
sys/init.go
Normal file
@ -0,0 +1,257 @@
|
||||
// Copyright 2017 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 (
|
||||
"runtime"
|
||||
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
lazyInit()
|
||||
target := &prog.Target{
|
||||
OS: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
PtrSize: ptrSize,
|
||||
PageSize: pageSize,
|
||||
DataOffset: dataOffset,
|
||||
Syscalls: syscalls,
|
||||
Resources: resources,
|
||||
MakeMmap: makeMmap,
|
||||
AnalyzeMmap: analyzeMmap,
|
||||
SanitizeCall: sanitizeCall,
|
||||
SpecialStructs: map[string]func(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (prog.Arg, []*prog.Call){
|
||||
"timespec": generateTimespec,
|
||||
"timeval": generateTimespec,
|
||||
},
|
||||
}
|
||||
prog.RegisterTarget(target)
|
||||
}
|
||||
|
||||
const (
|
||||
// TODO(dvyukov): dehardcode
|
||||
ptrSize = 8
|
||||
pageSize = 4 << 10
|
||||
dataOffset = 512 << 20
|
||||
invalidFD = ^uint64(0)
|
||||
)
|
||||
|
||||
var (
|
||||
mmapSyscall *prog.Syscall
|
||||
clockGettimeSyscall *prog.Syscall
|
||||
)
|
||||
|
||||
// createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range.
|
||||
func makeMmap(start, npages uint64) *prog.Call {
|
||||
return &prog.Call{
|
||||
Meta: mmapSyscall,
|
||||
Args: []prog.Arg{
|
||||
prog.MakePointerArg(mmapSyscall.Args[0], start, 0, npages, nil),
|
||||
prog.MakeConstArg(mmapSyscall.Args[1], npages*pageSize),
|
||||
prog.MakeConstArg(mmapSyscall.Args[2], PROT_READ|PROT_WRITE),
|
||||
prog.MakeConstArg(mmapSyscall.Args[3], MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED),
|
||||
prog.MakeResultArg(mmapSyscall.Args[4], nil, invalidFD),
|
||||
prog.MakeConstArg(mmapSyscall.Args[5], 0),
|
||||
},
|
||||
Ret: prog.MakeReturnArg(mmapSyscall.Ret),
|
||||
}
|
||||
}
|
||||
|
||||
func analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) {
|
||||
switch c.Meta.Name {
|
||||
case "mmap":
|
||||
// Filter out only very wrong arguments.
|
||||
npages = c.Args[1].(*prog.ConstArg).Val / pageSize
|
||||
if npages == 0 {
|
||||
return
|
||||
}
|
||||
flags := c.Args[3].(*prog.ConstArg).Val
|
||||
fd := c.Args[4].(*prog.ResultArg).Val
|
||||
if flags&MAP_ANONYMOUS == 0 && fd == invalidFD {
|
||||
return
|
||||
}
|
||||
start = c.Args[0].(*prog.PointerArg).PageIndex
|
||||
mapped = true
|
||||
return
|
||||
case "munmap":
|
||||
start = c.Args[0].(*prog.PointerArg).PageIndex
|
||||
npages = c.Args[1].(*prog.ConstArg).Val / pageSize
|
||||
mapped = false
|
||||
return
|
||||
case "mremap":
|
||||
start = c.Args[4].(*prog.PointerArg).PageIndex
|
||||
npages = c.Args[2].(*prog.ConstArg).Val / pageSize
|
||||
mapped = true
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeCall(c *prog.Call) {
|
||||
switch c.Meta.CallName {
|
||||
case "mmap":
|
||||
// Add MAP_FIXED flag, otherwise it produces non-deterministic results.
|
||||
c.Args[3].(*prog.ConstArg).Val |= MAP_FIXED
|
||||
case "mremap":
|
||||
// Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
|
||||
flags := c.Args[3].(*prog.ConstArg)
|
||||
if flags.Val&MREMAP_MAYMOVE != 0 {
|
||||
flags.Val |= MREMAP_FIXED
|
||||
}
|
||||
case "mknod", "mknodat":
|
||||
pos := 1
|
||||
if c.Meta.CallName == "mknodat" {
|
||||
pos = 2
|
||||
}
|
||||
mode := c.Args[pos].(*prog.ConstArg)
|
||||
dev := c.Args[pos+1].(*prog.ConstArg)
|
||||
// Char and block devices read/write io ports, kernel memory and do other nasty things.
|
||||
// TODO: not required if executor drops privileges.
|
||||
switch mode.Val & (S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK) {
|
||||
case S_IFREG, S_IFIFO, S_IFSOCK:
|
||||
case S_IFBLK:
|
||||
if dev.Val>>8 == 7 {
|
||||
break // loop
|
||||
}
|
||||
mode.Val &^= S_IFBLK
|
||||
mode.Val |= S_IFREG
|
||||
case S_IFCHR:
|
||||
mode.Val &^= S_IFCHR
|
||||
mode.Val |= S_IFREG
|
||||
}
|
||||
case "syslog":
|
||||
cmd := c.Args[0].(*prog.ConstArg)
|
||||
// These disable console output, but we need it.
|
||||
if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON {
|
||||
cmd.Val = SYSLOG_ACTION_SIZE_UNREAD
|
||||
}
|
||||
case "ioctl":
|
||||
cmd := c.Args[1].(*prog.ConstArg)
|
||||
// Freeze kills machine. Though, it is an interesting functions,
|
||||
// so we need to test it somehow.
|
||||
// TODO: not required if executor drops privileges.
|
||||
if uint32(cmd.Val) == FIFREEZE {
|
||||
cmd.Val = FITHAW
|
||||
}
|
||||
case "ptrace":
|
||||
req := c.Args[0].(*prog.ConstArg)
|
||||
// PTRACE_TRACEME leads to unkillable processes, see:
|
||||
// https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
|
||||
if req.Val == PTRACE_TRACEME {
|
||||
req.Val = ^uint64(0)
|
||||
}
|
||||
case "exit", "exit_group":
|
||||
code := c.Args[0].(*prog.ConstArg)
|
||||
// These codes are reserved by executor.
|
||||
if code.Val%128 == 67 || code.Val%128 == 68 {
|
||||
code.Val = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (arg prog.Arg, calls []*prog.Call) {
|
||||
// We need to generate timespec/timeval that are either
|
||||
// (1) definitely in the past, or
|
||||
// (2) definitely in unreachable fututre, or
|
||||
// (3) few ms ahead of now.
|
||||
// Note timespec/timeval can be absolute or relative to now.
|
||||
usec := typ.Name() == "timeval"
|
||||
switch {
|
||||
case g.NOutOf(1, 4):
|
||||
// Now for relative, past for absolute.
|
||||
arg = prog.MakeGroupArg(typ, []prog.Arg{
|
||||
prog.MakeResultArg(typ.Fields[0], nil, 0),
|
||||
prog.MakeResultArg(typ.Fields[1], nil, 0),
|
||||
})
|
||||
case g.NOutOf(1, 3):
|
||||
// Few ms ahead for relative, past for absolute
|
||||
nsec := uint64(10 * 1e6)
|
||||
if usec {
|
||||
nsec /= 1e3
|
||||
}
|
||||
arg = prog.MakeGroupArg(typ, []prog.Arg{
|
||||
prog.MakeResultArg(typ.Fields[0], nil, 0),
|
||||
prog.MakeResultArg(typ.Fields[1], nil, nsec),
|
||||
})
|
||||
case g.NOutOf(1, 2):
|
||||
// Unreachable fututre for both relative and absolute
|
||||
arg = prog.MakeGroupArg(typ, []prog.Arg{
|
||||
prog.MakeResultArg(typ.Fields[0], nil, 2e9),
|
||||
prog.MakeResultArg(typ.Fields[1], nil, 0),
|
||||
})
|
||||
default:
|
||||
// Few ms ahead for absolute.
|
||||
meta := clockGettimeSyscall
|
||||
ptrArgType := meta.Args[1].(*prog.PtrType)
|
||||
argType := ptrArgType.Type.(*prog.StructType)
|
||||
tp := prog.MakeGroupArg(argType, []prog.Arg{
|
||||
prog.MakeResultArg(argType.Fields[0], nil, 0),
|
||||
prog.MakeResultArg(argType.Fields[1], nil, 0),
|
||||
})
|
||||
var tpaddr prog.Arg
|
||||
tpaddr, calls = g.Alloc(ptrArgType, tp)
|
||||
gettime := &prog.Call{
|
||||
Meta: meta,
|
||||
Args: []prog.Arg{
|
||||
prog.MakeConstArg(meta.Args[0], CLOCK_REALTIME),
|
||||
tpaddr,
|
||||
},
|
||||
Ret: prog.MakeReturnArg(meta.Ret),
|
||||
}
|
||||
calls = append(calls, gettime)
|
||||
sec := prog.MakeResultArg(typ.Fields[0], tp.(*prog.GroupArg).Inner[0], 0)
|
||||
nsec := prog.MakeResultArg(typ.Fields[1], tp.(*prog.GroupArg).Inner[1], 0)
|
||||
if usec {
|
||||
nsec.(*prog.ResultArg).OpDiv = 1e3
|
||||
nsec.(*prog.ResultArg).OpAdd = 10 * 1e3
|
||||
} else {
|
||||
nsec.(*prog.ResultArg).OpAdd = 10 * 1e6
|
||||
}
|
||||
arg = prog.MakeGroupArg(typ, []prog.Arg{sec, nsec})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lazyInit() {
|
||||
resourceMap := make(map[string]*prog.ResourceDesc)
|
||||
for _, res := range resources {
|
||||
resourceMap[res.Name] = res
|
||||
}
|
||||
|
||||
keyedStructs := make(map[prog.StructKey]*prog.StructDesc)
|
||||
for _, desc := range structDescs {
|
||||
keyedStructs[desc.Key] = desc.Desc
|
||||
}
|
||||
structDescs = nil
|
||||
|
||||
for _, c := range syscalls {
|
||||
prog.ForeachType(c, func(t0 prog.Type) {
|
||||
switch t := t0.(type) {
|
||||
case *prog.ResourceType:
|
||||
t.Desc = resourceMap[t.TypeName]
|
||||
if t.Desc == nil {
|
||||
panic("no resource desc")
|
||||
}
|
||||
case *prog.StructType:
|
||||
t.StructDesc = keyedStructs[t.Key]
|
||||
if t.StructDesc == nil {
|
||||
panic("no struct desc")
|
||||
}
|
||||
case *prog.UnionType:
|
||||
t.StructDesc = keyedStructs[t.Key]
|
||||
if t.StructDesc == nil {
|
||||
panic("no union desc")
|
||||
}
|
||||
}
|
||||
})
|
||||
switch c.Name {
|
||||
case "mmap":
|
||||
mmapSyscall = c
|
||||
case "clock_gettime":
|
||||
clockGettimeSyscall = c
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
// AUTOGENERATED FILE
|
||||
package sys
|
||||
|
||||
var resourceArray = []*ResourceDesc{
|
||||
import . "github.com/google/syzkaller/prog"
|
||||
|
||||
var resources = []*ResourceDesc{
|
||||
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
|
||||
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
|
||||
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
|
||||
@ -5892,7 +5894,7 @@ var structDescs = []*KeyedStruct{
|
||||
}}},
|
||||
}
|
||||
|
||||
var Syscalls = []*Syscall{
|
||||
var syscalls = []*Syscall{
|
||||
{NR: 18446744073709551615, Name: "accept", CallName: "accept", Args: []Type{
|
||||
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 4, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
|
||||
|
@ -1,7 +1,9 @@
|
||||
// AUTOGENERATED FILE
|
||||
package sys
|
||||
|
||||
var resourceArray = []*ResourceDesc{
|
||||
import . "github.com/google/syzkaller/prog"
|
||||
|
||||
var resources = []*ResourceDesc{
|
||||
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
|
||||
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
|
||||
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
|
||||
@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
|
||||
}}},
|
||||
}
|
||||
|
||||
var Syscalls = []*Syscall{
|
||||
var syscalls = []*Syscall{
|
||||
{NR: 43, Name: "accept", CallName: "accept", Args: []Type{
|
||||
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
|
||||
|
@ -1,7 +1,9 @@
|
||||
// AUTOGENERATED FILE
|
||||
package sys
|
||||
|
||||
var resourceArray = []*ResourceDesc{
|
||||
import . "github.com/google/syzkaller/prog"
|
||||
|
||||
var resources = []*ResourceDesc{
|
||||
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
|
||||
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
|
||||
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
|
||||
@ -5892,7 +5894,7 @@ var structDescs = []*KeyedStruct{
|
||||
}}},
|
||||
}
|
||||
|
||||
var Syscalls = []*Syscall{
|
||||
var syscalls = []*Syscall{
|
||||
{NR: 9437469, Name: "accept", CallName: "accept", Args: []Type{
|
||||
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 4, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
|
||||
|
@ -1,7 +1,9 @@
|
||||
// AUTOGENERATED FILE
|
||||
package sys
|
||||
|
||||
var resourceArray = []*ResourceDesc{
|
||||
import . "github.com/google/syzkaller/prog"
|
||||
|
||||
var resources = []*ResourceDesc{
|
||||
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
|
||||
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
|
||||
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
|
||||
@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
|
||||
}}},
|
||||
}
|
||||
|
||||
var Syscalls = []*Syscall{
|
||||
var syscalls = []*Syscall{
|
||||
{NR: 202, Name: "accept", CallName: "accept", Args: []Type{
|
||||
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
|
||||
|
@ -1,7 +1,9 @@
|
||||
// AUTOGENERATED FILE
|
||||
package sys
|
||||
|
||||
var resourceArray = []*ResourceDesc{
|
||||
import . "github.com/google/syzkaller/prog"
|
||||
|
||||
var resources = []*ResourceDesc{
|
||||
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
|
||||
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
|
||||
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
|
||||
@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
|
||||
}}},
|
||||
}
|
||||
|
||||
var Syscalls = []*Syscall{
|
||||
var syscalls = []*Syscall{
|
||||
{NR: 330, Name: "accept", CallName: "accept", Args: []Type{
|
||||
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
)
|
||||
|
||||
type Arch struct {
|
||||
@ -26,7 +26,7 @@ var archs = []*Arch{
|
||||
{"ppc64le", 8, []string{"__ppc64__", "__PPC64__", "__powerpc64__"}},
|
||||
}
|
||||
|
||||
func generateExecutorSyscalls(arch *Arch, syscalls []*sys.Syscall) []byte {
|
||||
func generateExecutorSyscalls(arch *Arch, syscalls []*prog.Syscall) []byte {
|
||||
data := ArchData{
|
||||
CARCH: arch.CARCH,
|
||||
}
|
||||
|
@ -116,8 +116,9 @@ func main() {
|
||||
func generate(arch string, prog *compiler.Prog, consts map[string]uint64, out io.Writer) {
|
||||
fmt.Fprintf(out, "// AUTOGENERATED FILE\n")
|
||||
fmt.Fprintf(out, "package sys\n\n")
|
||||
fmt.Fprintf(out, "import . \"github.com/google/syzkaller/prog\"\n\n")
|
||||
|
||||
fmt.Fprintf(out, "var resourceArray = ")
|
||||
fmt.Fprintf(out, "var resources = ")
|
||||
serializer.Write(out, prog.Resources)
|
||||
fmt.Fprintf(out, "\n\n")
|
||||
|
||||
@ -133,7 +134,7 @@ func generate(arch string, prog *compiler.Prog, consts map[string]uint64, out io
|
||||
serializer.Write(out, prog.StructDescs)
|
||||
fmt.Fprintf(out, "\n\n")
|
||||
|
||||
fmt.Fprintf(out, "var Syscalls = ")
|
||||
fmt.Fprintf(out, "var syscalls = ")
|
||||
serializer.Write(out, prog.Syscalls)
|
||||
fmt.Fprintf(out, "\n\n")
|
||||
|
||||
|
@ -202,10 +202,10 @@ func main() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if _, ok := calls[sys.SyscallMap["syz_emit_ethernet"]]; ok {
|
||||
if _, ok := calls[prog.SyscallMap["syz_emit_ethernet"]]; ok {
|
||||
config.Flags |= ipc.FlagEnableTun
|
||||
}
|
||||
if _, ok := calls[sys.SyscallMap["syz_extract_tcp_res"]]; ok {
|
||||
if _, ok := calls[prog.SyscallMap["syz_extract_tcp_res"]]; ok {
|
||||
config.Flags |= ipc.FlagEnableTun
|
||||
}
|
||||
if faultInjectionEnabled {
|
||||
@ -407,18 +407,18 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func buildCallList(enabledCalls string) map[*sys.Syscall]bool {
|
||||
calls := make(map[*sys.Syscall]bool)
|
||||
func buildCallList(enabledCalls string) map[*prog.Syscall]bool {
|
||||
calls := make(map[*prog.Syscall]bool)
|
||||
if enabledCalls != "" {
|
||||
for _, id := range strings.Split(enabledCalls, ",") {
|
||||
n, err := strconv.ParseUint(id, 10, 64)
|
||||
if err != nil || n >= uint64(len(sys.Syscalls)) {
|
||||
if err != nil || n >= uint64(len(prog.Syscalls)) {
|
||||
panic(fmt.Sprintf("invalid syscall in -calls flag: '%v", id))
|
||||
}
|
||||
calls[sys.Syscalls[n]] = true
|
||||
calls[prog.Syscalls[n]] = true
|
||||
}
|
||||
} else {
|
||||
for _, c := range sys.Syscalls {
|
||||
for _, c := range prog.Syscalls {
|
||||
calls[c] = true
|
||||
}
|
||||
}
|
||||
@ -434,7 +434,7 @@ func buildCallList(enabledCalls string) map[*sys.Syscall]bool {
|
||||
}
|
||||
}
|
||||
|
||||
trans := sys.TransitivelyEnabledCalls(calls)
|
||||
trans := prog.TransitivelyEnabledCalls(calls)
|
||||
for c := range calls {
|
||||
if !trans[c] {
|
||||
Logf(1, "disabling transitively unsupported syscall: %v", c.Name)
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/pkg/report"
|
||||
"github.com/google/syzkaller/prog"
|
||||
"github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
const dateFormat = "Jan 02 2006 15:04:05 MST"
|
||||
@ -196,7 +195,7 @@ func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) {
|
||||
mgr.minimizeCorpus()
|
||||
call := r.FormValue("call")
|
||||
idx := -1
|
||||
for i, c := range sys.Syscalls {
|
||||
for i, c := range prog.Syscalls {
|
||||
if c.CallName == call {
|
||||
idx = i
|
||||
break
|
||||
@ -209,7 +208,7 @@ func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
data := &UIPrioData{Call: call}
|
||||
for i, p := range mgr.prios[idx] {
|
||||
data.Prios = append(data.Prios, UIPrio{sys.Syscalls[i].Name, p})
|
||||
data.Prios = append(data.Prios, UIPrio{prog.Syscalls[i].Name, p})
|
||||
}
|
||||
sort.Sort(UIPrioArray(data.Prios))
|
||||
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"github.com/google/syzkaller/pkg/repro"
|
||||
. "github.com/google/syzkaller/pkg/rpctype"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/syz-manager/mgrconfig"
|
||||
"github.com/google/syzkaller/vm"
|
||||
)
|
||||
|
@ -12,7 +12,8 @@ import (
|
||||
|
||||
"github.com/google/syzkaller/pkg/config"
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/vm"
|
||||
)
|
||||
|
||||
@ -149,7 +150,7 @@ func load(data []byte, filename string) (*Config, map[int]bool, error) {
|
||||
}
|
||||
|
||||
func parseSyscalls(cfg *Config) (map[int]bool, error) {
|
||||
match := func(call *sys.Syscall, str string) bool {
|
||||
match := func(call *prog.Syscall, str string) bool {
|
||||
if str == call.CallName || str == call.Name {
|
||||
return true
|
||||
}
|
||||
@ -163,7 +164,7 @@ func parseSyscalls(cfg *Config) (map[int]bool, error) {
|
||||
if len(cfg.Enable_Syscalls) != 0 {
|
||||
for _, c := range cfg.Enable_Syscalls {
|
||||
n := 0
|
||||
for _, call := range sys.Syscalls {
|
||||
for _, call := range prog.Syscalls {
|
||||
if match(call, c) {
|
||||
syscalls[call.ID] = true
|
||||
n++
|
||||
@ -174,13 +175,13 @@ func parseSyscalls(cfg *Config) (map[int]bool, error) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, call := range sys.Syscalls {
|
||||
for _, call := range prog.Syscalls {
|
||||
syscalls[call.ID] = true
|
||||
}
|
||||
}
|
||||
for _, c := range cfg.Disable_Syscalls {
|
||||
n := 0
|
||||
for _, call := range sys.Syscalls {
|
||||
for _, call := range prog.Syscalls {
|
||||
if match(call, c) {
|
||||
delete(syscalls, call.ID)
|
||||
n++
|
||||
@ -191,7 +192,7 @@ func parseSyscalls(cfg *Config) (map[int]bool, error) {
|
||||
}
|
||||
}
|
||||
// mmap is used to allocate memory.
|
||||
syscalls[sys.SyscallMap["mmap"].ID] = true
|
||||
syscalls[prog.SyscallMap["mmap"].ID] = true
|
||||
|
||||
return syscalls, nil
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
. "github.com/google/syzkaller/pkg/log"
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"github.com/google/syzkaller/pkg/ipc"
|
||||
. "github.com/google/syzkaller/pkg/log"
|
||||
"github.com/google/syzkaller/prog"
|
||||
"github.com/google/syzkaller/sys"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -129,21 +129,21 @@ func readCorpus() []*prog.Prog {
|
||||
return progs
|
||||
}
|
||||
|
||||
func buildCallList() map[*sys.Syscall]bool {
|
||||
func buildCallList() map[*prog.Syscall]bool {
|
||||
calls, err := host.DetectSupportedSyscalls()
|
||||
if err != nil {
|
||||
Logf(0, "failed to detect host supported syscalls: %v", err)
|
||||
calls = make(map[*sys.Syscall]bool)
|
||||
for _, c := range sys.Syscalls {
|
||||
calls = make(map[*prog.Syscall]bool)
|
||||
for _, c := range prog.Syscalls {
|
||||
calls[c] = true
|
||||
}
|
||||
}
|
||||
for _, c := range sys.Syscalls {
|
||||
for _, c := range prog.Syscalls {
|
||||
if !calls[c] {
|
||||
Logf(0, "disabling unsupported syscall: %v", c.Name)
|
||||
}
|
||||
}
|
||||
trans := sys.TransitivelyEnabledCalls(calls)
|
||||
trans := prog.TransitivelyEnabledCalls(calls)
|
||||
for c := range calls {
|
||||
if !trans[c] {
|
||||
Logf(0, "disabling transitively unsupported syscall: %v", c.Name)
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/google/syzkaller/pkg/osutil"
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
Loading…
Reference in New Issue
Block a user