From c99cbdbe58f7817a2ee6064e72db25fc1d067b41 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 21 Sep 2016 16:52:55 +0200 Subject: Emit BufferBlob for array[int8] --- prog/mutation.go | 20 ++++++++++++++++---- prog/prio.go | 2 +- prog/rand.go | 12 +++++++----- sys/align.go | 7 ++++++- sys/decl.go | 12 ++++++++++-- sysgen/sysgen.go | 34 +++++++++++++++++++++++----------- 6 files changed, 63 insertions(+), 24 deletions(-) diff --git a/prog/mutation.go b/prog/mutation.go index f50f60e06..068ebb849 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -67,7 +67,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { size = size1 case sys.BufferType: switch a.Kind { - case sys.BufferBlob: + case sys.BufferBlobRand, sys.BufferBlobRange: var data []byte switch arg.Kind { case ArgData: @@ -80,10 +80,16 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable) { default: panic(fmt.Sprintf("bad arg kind for BufferType: %v", arg.Kind)) } - arg.Data = mutateData(r, data) + minLen := int(0) + maxLen := ^int(0) + if a.Kind == sys.BufferBlobRange { + minLen = int(a.RangeBegin) + maxLen = int(a.RangeEnd) + } + arg.Data = mutateData(r, data, minLen, maxLen) case sys.BufferString: if r.bin() { - arg.Data = mutateData(r, append([]byte{}, arg.Data...)) + arg.Data = mutateData(r, append([]byte{}, arg.Data...), int(0), ^int(0)) } else { arg.Data = r.randString(s) } @@ -424,16 +430,22 @@ func swap64(v uint64) uint64 { return v } -func mutateData(r *randGen, data []byte) []byte { +func mutateData(r *randGen, data []byte, minLen, maxLen int) []byte { const maxInc = 35 for stop := false; !stop; stop = r.bin() { r.choose( 100, func() { // Append byte. + if len(data) == maxLen { + return + } data = append(data, byte(r.rand(256))) }, 100, func() { // Remove byte. + if len(data) == minLen { + return + } if len(data) == 0 { return } diff --git a/prog/prio.go b/prog/prio.go index 9291b3d09..8983c1c92 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -80,7 +80,7 @@ func calcStaticPriorities() [][]float32 { } case sys.BufferType: switch a.Kind { - case sys.BufferBlob, sys.BufferFilesystem, sys.BufferAlgType, sys.BufferAlgName: + case sys.BufferBlobRand, sys.BufferBlobRange, sys.BufferFilesystem, sys.BufferAlgType, sys.BufferAlgName: case sys.BufferString: noteUsage(0.2, "str") case sys.BufferSockaddr: diff --git a/prog/rand.go b/prog/rand.go index 26063b626..b96ecbe9a 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -706,14 +706,16 @@ func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir, sizes map[stri return arg, nil, nil case sys.BufferType: switch a.Kind { - case sys.BufferBlob: + case sys.BufferBlobRand, sys.BufferBlobRange: sz := r.randBufLen() - if dir == DirOut { - return nil, constArg(sz), nil + if a.Kind == sys.BufferBlobRange { + sz = r.randRange(int(a.RangeBegin), int(a.RangeEnd)) } data := make([]byte, sz) - for i := range data { - data[i] = byte(r.Intn(256)) + if dir != DirOut { + for i := range data { + data[i] = byte(r.Intn(256)) + } } return dataArg(data), constArg(sz), nil case sys.BufferString: diff --git a/sys/align.go b/sys/align.go index 6e8563da4..055a433f8 100644 --- a/sys/align.go +++ b/sys/align.go @@ -48,14 +48,19 @@ func addAlignment(t *StructType) { off += pad fields = append(fields, makePad(pad)) } - off += f.Size() fields = append(fields, f) if at, ok := f.(ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) { varLen = true } + if at, ok := f.(BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) { + varLen = true + } if varLen && i != len(t.Fields)-1 { panic("embed array in middle of a struct") } + if !varLen { + off += f.Size() + } } if align != 0 && off%align != 0 && !varLen { pad := align - off%align diff --git a/sys/decl.go b/sys/decl.go index f792f541c..275bbb380 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -100,7 +100,8 @@ func (t FileoffType) Align() uintptr { type BufferKind int const ( - BufferBlob BufferKind = iota + BufferBlobRand BufferKind = iota + BufferBlobRange BufferString BufferSockaddr BufferFilesystem @@ -110,7 +111,9 @@ const ( type BufferType struct { TypeCommon - Kind BufferKind + Kind BufferKind + RangeBegin uintptr // for BufferBlobRange kind + RangeEnd uintptr // for BufferBlobRange kind } func (t BufferType) Size() uintptr { @@ -119,6 +122,11 @@ func (t BufferType) Size() uintptr { return 14 case BufferAlgName: return 64 + case BufferBlobRange: + if t.RangeBegin == t.RangeEnd { + return t.RangeBegin + } + fallthrough default: panic(fmt.Sprintf("buffer size is not statically known: %v", t.Name())) } diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index c27e413c3..c09a7cd7e 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -345,7 +345,7 @@ func generateArg( } commonHdr := common() opt = false - fmt.Fprintf(out, "PtrType{%v, Dir: %v, Type: BufferType{%v, Kind: BufferBlob}}", commonHdr, fmtDir(a[0]), common()) + fmt.Fprintf(out, "PtrType{%v, Dir: %v, Type: BufferType{%v, Kind: BufferBlobRand}}", commonHdr, fmtDir(a[0]), common()) case "string": canBeArg = true if want := 0; len(a) != want { @@ -490,22 +490,34 @@ func generateArg( opt = false fmt.Fprintf(out, "PtrType{%v, Dir: DirIn, Type: FilenameType{%v}}", commonHdr, common()) case "array": - switch len(a) { - case 1: - fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], desc, consts)) - case 2: + if len(a) != 1 && len(a) != 2 { + failf("wrong number of arguments for %v arg %v, want 1 or 2, got %v", typ, name, len(a)) + } + if len(a) == 1 { + if a[0] == "int8" { + fmt.Fprintf(out, "BufferType{%v, Kind: BufferBlobRand}", common()) + } else { + fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], desc, consts)) + } + } else { var begin, end uintptr - sz := a[1] - if _, err := fmt.Sscanf(sz, "%d:%d", &begin, &end); err != nil { + var beginStr, endStr string + if _, err := fmt.Sscanf(a[1], "%d:%d", &begin, &end); err == nil { + beginStr = fmt.Sprint(begin) + endStr = fmt.Sprint(end) + } else { + sz := a[1] if v, ok := consts[sz]; ok { sz = fmt.Sprint(v) } - fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], desc, consts), sz, sz) + beginStr = sz + endStr = sz + } + if a[0] == "int8" { + fmt.Fprintf(out, "BufferType{%v, Kind: BufferBlobRange, RangeBegin: %v, RangeEnd: %v}", common(), beginStr, endStr) } else { - fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], desc, consts), begin, end) + fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], desc, consts), beginStr, endStr) } - default: - failf("wrong number of arguments for %v arg %v, want 1 or 2, got %v", typ, name, len(a)) } case "ptr": canBeArg = true -- cgit mrf-deployment