aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2017-01-23 15:02:47 +0100
committerAndrey Konovalov <andreyknvl@google.com>2017-01-23 18:13:06 +0100
commitb323c5aaa9b926ba43a9c5435b62b4fce992ff94 (patch)
tree2620c3928f0b1b27f401565eb3d162dd2f254b11
parentcd23722cf2dabd28d83fa321c3cbf50a956d3fb7 (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.go4
-rw-r--r--prog/encoding.go4
-rw-r--r--prog/mutation.go10
-rw-r--r--prog/validation.go3
-rw-r--r--sys/decl.go6
-rw-r--r--sysgen/sysgen.go10
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().