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.
This commit is contained in:
Andrey Konovalov 2017-01-23 15:02:47 +01:00
parent cd23722cf2
commit b323c5aaa9
6 changed files with 23 additions and 14 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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
}

View File

@ -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().