aboutsummaryrefslogtreecommitdiffstats
path: root/prog/size.go
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2017-07-11 16:49:08 +0200
committerAndrey Konovalov <andreyknvl@google.com>2017-07-17 14:34:09 +0200
commitcfc46d9d0bea72865ba75e0e4063a1a558262df8 (patch)
tree80455a77ab10d09154bb1ae66a12de002b7cd030 /prog/size.go
parent8d1e7095528712971312a83e067cdd803aaccc47 (diff)
prog: split Arg into smaller structs
Right now Arg is a huge struct (160 bytes), which has many different fields used for different arg kinds. Since most of the args we see in a typical corpus are ArgConst, this results in a significant memory overuse. This change: - makes Arg an interface instead of a struct - adds a SomethingArg struct for each arg kind we have - converts all *Arg pointers into just Arg, since interface variable by itself contains a pointer to the actual data - removes ArgPageSize, now ConstArg is used instead - consolidates correspondence between arg kinds and types, see comments before each SomethingArg struct definition - now LenType args that denote the length of VmaType args are serialized as "0x1000" instead of "(0x1000)"; to preserve backwards compatibility syzkaller is able to parse the old format for now - multiple small changes all over to make the above work After this change syzkaller uses twice less memory after deserializing a typical corpus.
Diffstat (limited to 'prog/size.go')
-rw-r--r--prog/size.go58
1 files changed, 31 insertions, 27 deletions
diff --git a/prog/size.go b/prog/size.go
index 60cc7bd57..f00fd56b1 100644
--- a/prog/size.go
+++ b/prog/size.go
@@ -9,20 +9,22 @@ import (
"github.com/google/syzkaller/sys"
)
-func generateSize(arg *Arg, lenType *sys.LenType) *Arg {
+func generateSize(arg Arg, lenType *sys.LenType) Arg {
if arg == nil {
// Arg is an optional pointer, set size to 0.
return constArg(lenType, 0)
}
- switch arg.Type.(type) {
+ switch arg.Type().(type) {
case *sys.VmaType:
- return pageSizeArg(lenType, arg.AddrPagesNum, 0)
+ a := arg.(*PointerArg)
+ return constArg(lenType, a.PagesNum*pageSize)
case *sys.ArrayType:
+ a := arg.(*GroupArg)
if lenType.ByteSize != 0 {
- return constArg(lenType, arg.Size()/lenType.ByteSize)
+ return constArg(lenType, a.Size()/lenType.ByteSize)
} else {
- return constArg(lenType, uintptr(len(arg.Inner)))
+ return constArg(lenType, uintptr(len(a.Inner)))
}
default:
if lenType.ByteSize != 0 {
@@ -33,42 +35,44 @@ func generateSize(arg *Arg, lenType *sys.LenType) *Arg {
}
}
-func assignSizes(args []*Arg, parentsMap map[*Arg]*Arg) {
- // Create a map of args and calculate size of the whole struct.
- argsMap := make(map[string]*Arg)
+func assignSizes(args []Arg, parentsMap map[Arg]Arg) {
+ // Create a map from field names to args.
+ argsMap := make(map[string]Arg)
for _, arg := range args {
- if sys.IsPad(arg.Type) {
+ if sys.IsPad(arg.Type()) {
continue
}
- argsMap[arg.Type.FieldName()] = arg
+ argsMap[arg.Type().FieldName()] = arg
}
// Fill in size arguments.
for _, arg := range args {
- if arg = arg.InnerArg(); arg == nil {
+ if arg = InnerArg(arg); arg == nil {
continue // Pointer to optional len field, no need to fill in value.
}
- if typ, ok := arg.Type.(*sys.LenType); ok {
+ if typ, ok := arg.Type().(*sys.LenType); ok {
+ a := arg.(*ConstArg)
+
buf, ok := argsMap[typ.Buf]
if ok {
- *arg = *generateSize(buf.InnerArg(), typ)
+ *a = *generateSize(InnerArg(buf), typ).(*ConstArg)
continue
}
if typ.Buf == "parent" {
- arg.Val = parentsMap[arg].Size()
+ a.Val = parentsMap[arg].Size()
if typ.ByteSize != 0 {
- arg.Val /= typ.ByteSize
+ a.Val /= typ.ByteSize
}
continue
}
sizeAssigned := false
for parent := parentsMap[arg]; parent != nil; parent = parentsMap[parent] {
- if typ.Buf == parent.Type.Name() {
- arg.Val = parent.Size()
+ if typ.Buf == parent.Type().Name() {
+ a.Val = parent.Size()
if typ.ByteSize != 0 {
- arg.Val /= typ.ByteSize
+ a.Val /= typ.ByteSize
}
sizeAssigned = true
break
@@ -84,19 +88,19 @@ func assignSizes(args []*Arg, parentsMap map[*Arg]*Arg) {
}
}
-func assignSizesArray(args []*Arg) {
- parentsMap := make(map[*Arg]*Arg)
- foreachArgArray(&args, nil, func(arg, base *Arg, _ *[]*Arg) {
- if _, ok := arg.Type.(*sys.StructType); ok {
- for _, field := range arg.Inner {
- parentsMap[field.InnerArg()] = arg
+func assignSizesArray(args []Arg) {
+ parentsMap := make(map[Arg]Arg)
+ foreachArgArray(&args, nil, func(arg, base Arg, _ *[]Arg) {
+ if _, ok := arg.Type().(*sys.StructType); ok {
+ for _, field := range arg.(*GroupArg).Inner {
+ parentsMap[InnerArg(field)] = arg
}
}
})
assignSizes(args, parentsMap)
- foreachArgArray(&args, nil, func(arg, base *Arg, _ *[]*Arg) {
- if _, ok := arg.Type.(*sys.StructType); ok {
- assignSizes(arg.Inner, parentsMap)
+ foreachArgArray(&args, nil, func(arg, base Arg, _ *[]Arg) {
+ if _, ok := arg.Type().(*sys.StructType); ok {
+ assignSizes(arg.(*GroupArg).Inner, parentsMap)
}
})
}