diff options
| author | Andrey Konovalov <andreyknvl@google.com> | 2017-01-23 15:02:47 +0100 |
|---|---|---|
| committer | Andrey Konovalov <andreyknvl@google.com> | 2017-01-23 18:13:06 +0100 |
| commit | b323c5aaa9b926ba43a9c5435b62b4fce992ff94 (patch) | |
| tree | 2620c3928f0b1b27f401565eb3d162dd2f254b11 | |
| parent | cd23722cf2dabd28d83fa321c3cbf50a956d3fb7 (diff) | |
prog: add FieldName to Type
FieldName() is the name of the struct field or union option with this type.
TypeName() is now always the name of the type.
| -rw-r--r-- | prog/analysis.go | 4 | ||||
| -rw-r--r-- | prog/encoding.go | 4 | ||||
| -rw-r--r-- | prog/mutation.go | 10 | ||||
| -rw-r--r-- | prog/validation.go | 3 | ||||
| -rw-r--r-- | sys/decl.go | 6 | ||||
| -rw-r--r-- | sysgen/sysgen.go | 10 |
6 files changed, 23 insertions, 14 deletions
diff --git a/prog/analysis.go b/prog/analysis.go index a4f399f98..a6ee3885b 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -185,7 +185,7 @@ func assignSizes(args []*Arg) { if sys.IsPad(arg.Type) { continue } - argsMap[arg.Type.Name()] = arg + argsMap[arg.Type.FieldName()] = arg } // Fill in size arguments. @@ -205,7 +205,7 @@ func assignSizes(args []*Arg) { buf, ok := argsMap[typ.Buf] if !ok { panic(fmt.Sprintf("len field '%v' references non existent field '%v', argsMap: %+v", - typ.Name(), typ.Buf, argsMap)) + typ.FieldName(), typ.Buf, argsMap)) } *arg = *generateSize(buf.InnerArg(), typ) diff --git a/prog/encoding.go b/prog/encoding.go index 8c7c1674a..274e94a2d 100644 --- a/prog/encoding.go +++ b/prog/encoding.go @@ -108,7 +108,7 @@ func (a *Arg) serialize(buf io.Writer, vars map[*Arg]int, varSeq *int) { } buf.Write([]byte{delims[1]}) case ArgUnion: - fmt.Fprintf(buf, "@%v=", a.OptionType.Name()) + fmt.Fprintf(buf, "@%v=", a.OptionType.FieldName()) a.Option.serialize(buf, vars, varSeq) default: panic("unknown arg kind") @@ -318,7 +318,7 @@ func parseArg(typ sys.Type, p *parser, vars map[string]*Arg) (*Arg, error) { p.Parse('=') var optType sys.Type for _, t2 := range t1.Options { - if name == t2.Name() { + if name == t2.FieldName() { optType = t2 break } diff --git a/prog/mutation.go b/prog/mutation.go index 2136c86f8..9841d31ca 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -184,8 +184,12 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro } case *sys.UnionType: optType := a.Options[r.Intn(len(a.Options))] - for optType.Name() == arg.OptionType.Name() { + maxIters := 1000 + for i := 0; optType.FieldName() == arg.OptionType.FieldName(); i++ { optType = a.Options[r.Intn(len(a.Options))] + if i >= maxIters { + panic(fmt.Sprintf("couldn't generate a different union option after %v iterations, type: %+v", maxIters, a)) + } } p.removeArg(c, arg.Option) opt, calls := r.generateArg(s, optType) @@ -303,7 +307,7 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool) var rec func(p *Prog, call *Call, arg *Arg, path string) bool rec = func(p *Prog, call *Call, arg *Arg, path string) bool { - path += fmt.Sprintf("-%v", arg.Type.Name()) + path += fmt.Sprintf("-%v", arg.Type.FieldName()) switch typ := arg.Type.(type) { case *sys.StructType: for _, innerArg := range arg.Inner { @@ -438,7 +442,7 @@ func (p *Prog) TrimAfter(idx int) { } func mutationArgs(c *Call) (args, bases []*Arg) { - foreachArg(c, func(arg, base *Arg, parent *[]*Arg) { + foreachArg(c, func(arg, base *Arg, _ *[]*Arg) { switch typ := arg.Type.(type) { case *sys.StructType: if isSpecialStruct(typ) == nil { diff --git a/prog/validation.go b/prog/validation.go index 5eea42e65..f03ec10b8 100644 --- a/prog/validation.go +++ b/prog/validation.go @@ -59,6 +59,9 @@ func (c *Call) validate(ctx *validCtx) error { if arg.Type.Name() != typ.Name() { return fmt.Errorf("syscall %v: type name mismatch: %v vs %v", c.Meta.Name, arg.Type.Name(), typ.Name()) } + if arg.Type.FieldName() != typ.FieldName() { + return fmt.Errorf("syscall %v: field name mismatch: %v vs %v", c.Meta.Name, arg.Type.FieldName(), typ.FieldName()) + } if arg.Type.Dir() == sys.DirOut { if (arg.Val != 0 && arg.Val != arg.Type.Default()) || arg.AddrPage != 0 || arg.AddrOffset != 0 { // We generate output len arguments, which makes sense diff --git a/sys/decl.go b/sys/decl.go index a495ffd4a..3c98d1038 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -29,6 +29,7 @@ const ( type Type interface { Name() string + FieldName() string Dir() Dir Optional() bool Default() uintptr @@ -49,6 +50,7 @@ func IsPad(t Type) bool { type TypeCommon struct { TypeName string + FldName string // for struct fields and named args ArgDir Dir IsOptional bool } @@ -57,6 +59,10 @@ func (t *TypeCommon) Name() string { return t.TypeName } +func (t *TypeCommon) FieldName() string { + return t.FldName +} + func (t *TypeCommon) Optional() bool { return t.IsOptional } diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index 867561ad7..6906c7697 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -265,10 +265,6 @@ func generateStructEntry(str Struct, key structKey, out io.Writer) { if str.IsUnion { typ = "UnionType" } - name := key.field - if name == "" { - name = key.name - } packed := "" if str.Packed { packed = ", packed: true" @@ -281,8 +277,8 @@ func generateStructEntry(str Struct, key structKey, out io.Writer) { if str.Align != 0 { align = fmt.Sprintf(", align: %v", str.Align) } - fmt.Fprintf(out, "\"%v\": &%v{TypeCommon: TypeCommon{TypeName: \"%v\", ArgDir: %v, IsOptional: %v} %v %v %v},\n", - key, typ, name, fmtDir(key.dir), false, packed, align, varlen) + fmt.Fprintf(out, "\"%v\": &%v{TypeCommon: TypeCommon{TypeName: \"%v\", FldName: \"%v\", ArgDir: %v, IsOptional: %v} %v %v %v},\n", + key, typ, key.name, key.field, fmtDir(key.dir), false, packed, align, varlen) } func generateStructFields(str Struct, key structKey, desc *Description, consts map[string]uint64, out io.Writer) { @@ -379,7 +375,7 @@ func generateArg( } } common := func() string { - return fmt.Sprintf("TypeCommon: TypeCommon{TypeName: %v, ArgDir: %v, IsOptional: %v}", name, fmtDir(dir), opt) + return fmt.Sprintf("TypeCommon: TypeCommon{TypeName: \"%v\", FldName: %v, ArgDir: %v, IsOptional: %v}", typ, name, fmtDir(dir), opt) } intCommon := func(typeSize uint64, bigEndian bool, bitfieldLen uint64) string { // BitfieldOff and BitfieldLst will be filled in in initAlign(). |
