sys: add packed/aligned struct attributes

This commit is contained in:
Dmitry Vyukov 2015-12-30 13:53:09 +01:00
parent 28b3d1e1ab
commit 777beb5076
5 changed files with 133 additions and 94 deletions

87
sys/align.go Normal file
View File

@ -0,0 +1,87 @@
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package sys
func initAlign() {
var rec func(t Type) Type
rec = func(t Type) Type {
switch t1 := t.(type) {
case PtrType:
t1.Type = rec(t1.Type)
t = t1
case ArrayType:
t1.Type = rec(t1.Type)
t = t1
case StructType:
for i, f := range t1.Fields {
t1.Fields[i] = rec(f)
}
t = addAlignment(t1)
case UnionType:
opts := make(map[string]bool)
for i, opt := range t1.Options {
if opts[opt.Name()] {
panic("duplicate option in union")
}
opts[opt.Name()] = true
t1.Options[i] = rec(opt)
}
}
return t
}
for _, c := range Calls {
for i, t := range c.Args {
c.Args[i] = rec(t)
}
if c.Ret != nil {
c.Ret = rec(c.Ret)
}
}
}
func addAlignment(t StructType) Type {
if t.packed {
t.padded = true
return t
}
var fields []Type
var off, align uintptr
varLen := false
for i, f := range t.Fields {
a := f.Align()
if align < a {
align = a
}
if off%a != 0 {
pad := a - off%a
off += pad
fields = append(fields, makePad(pad))
}
off += f.Size()
fields = append(fields, f)
if at, ok := f.(ArrayType); ok && at.Len == 0 {
varLen = true
}
if varLen && i != len(t.Fields)-1 {
panic("embed array in middle of a struct")
}
}
if align != 0 && off%align != 0 && !varLen {
pad := align - off%align
off += pad
fields = append(fields, makePad(pad))
}
t.Fields = fields
t.padded = true
return t
}
func makePad(sz uintptr) Type {
return ConstType{
TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false},
TypeSize: sz,
Val: 0,
IsPad: true,
}
}

View File

@ -417,6 +417,8 @@ type StructType struct {
TypeCommon
Fields []Type
padded bool
packed bool
align uintptr
}
func (t StructType) Size() uintptr {
@ -431,6 +433,9 @@ func (t StructType) Size() uintptr {
}
func (t StructType) Align() uintptr {
if t.align != 0 {
return t.align // overrided by user attribute
}
var align uintptr
for _, f := range t.Fields {
if a1 := f.Align(); align < a1 {
@ -614,41 +619,6 @@ func init() {
c.NR = numbers[c.ID]
}
var rec func(t Type) Type
rec = func(t Type) Type {
switch t1 := t.(type) {
case PtrType:
t1.Type = rec(t1.Type)
t = t1
case ArrayType:
t1.Type = rec(t1.Type)
t = t1
case StructType:
for i, f := range t1.Fields {
t1.Fields[i] = rec(f)
}
t = addAlignment(t1)
case UnionType:
opts := make(map[string]bool)
for i, opt := range t1.Options {
if opts[opt.Name()] {
panic("duplicate option in union")
}
opts[opt.Name()] = true
t1.Options[i] = rec(opt)
}
}
return t
}
for _, c := range Calls {
for i, t := range c.Args {
c.Args[i] = rec(t)
}
if c.Ret != nil {
c.Ret = rec(c.Ret)
}
}
for _, c := range Calls {
if CallMap[c.Name] != nil {
println(c.Name)
@ -664,45 +634,3 @@ func init() {
}
CallCount = len(CallID)
}
func addAlignment(t StructType) Type {
var fields []Type
var off, align uintptr
varLen := false
for i, f := range t.Fields {
a := f.Align()
if align < a {
align = a
}
if off%a != 0 {
pad := a - off%a
off += pad
fields = append(fields, makePad(pad))
}
off += f.Size()
fields = append(fields, f)
if at, ok := f.(ArrayType); ok && at.Len == 0 {
varLen = true
}
if varLen && i != len(t.Fields)-1 {
panic("embed array in middle of a struct")
}
}
if align != 0 && off%align != 0 && !varLen {
pad := align - off%align
off += pad
fields = append(fields, makePad(pad))
}
t.Fields = fields
t.padded = true
return t
}
func makePad(sz uintptr) Type {
return ConstType{
TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false},
TypeSize: sz,
Val: 0,
IsPad: true,
}
}

View File

@ -182,7 +182,6 @@ sctp_event_subscribe {
ev9 int8
}
# TODO: this struct is __attribute__((packed, aligned(4)))
sctp_paddrparams {
assoc int32
addr sockaddr_sctp_padded
@ -192,7 +191,7 @@ sctp_paddrparams {
sackdel int32
spp int32
flags flags[sctp_spp_flags, int32]
}
} [packed, align_4]
sctp_authkey {
assoc int32
@ -201,11 +200,10 @@ sctp_authkey {
key array[int8]
}
# TODO: __attribute__((packed, aligned(4)))
sctp_prim {
assoc int32
addr sockaddr_sctp_padded
}
} [packed, align_4]
sctp_rtoinfo {
assoc int32

View File

@ -2020,7 +2020,7 @@ func initCalls() {
Calls = append(Calls, &Call{ID: 672, Name: "setsockopt$SCTP_AUTOCLOSE", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(4)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
}()
func() {
Calls = append(Calls, &Call{ID: 673, Name: "setsockopt$SCTP_PEER_ADDR_PARAMS", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(9)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_paddrparams", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, StructType{TypeCommon: TypeCommon{TypeName: "sockaddr_sctp_padded", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "addr0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr7", IsOptional: false}, TypeSize: 8}}}, IntType{TypeCommon: TypeCommon{TypeName: "interv", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "maxrxt", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pathmtu", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "sackdel", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "spp", IsOptional: false}, TypeSize: 4}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 2, 4, 128, 8, 16, 32, 64}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
Calls = append(Calls, &Call{ID: 673, Name: "setsockopt$SCTP_PEER_ADDR_PARAMS", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(9)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_paddrparams", IsOptional: false}, packed: true, align: 4, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, StructType{TypeCommon: TypeCommon{TypeName: "sockaddr_sctp_padded", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "addr0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr7", IsOptional: false}, TypeSize: 8}}}, IntType{TypeCommon: TypeCommon{TypeName: "interv", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "maxrxt", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pathmtu", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "sackdel", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "spp", IsOptional: false}, TypeSize: 4}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 2, 4, 128, 8, 16, 32, 64}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
}()
func() {
Calls = append(Calls, &Call{ID: 674, Name: "setsockopt$SCTP_DELAYED_SACK", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(16)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: UnionType{TypeCommon: TypeCommon{TypeName: "sctp_delayed_sack", IsOptional: false}, Options: []Type{StructType{TypeCommon: TypeCommon{TypeName: "sctp_sack_info", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "delay", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "freq", IsOptional: false}, TypeSize: 4}}}, StructType{TypeCommon: TypeCommon{TypeName: "sctp_assoc_value", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "value", IsOptional: false}, TypeSize: 4}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
@ -2038,10 +2038,10 @@ func initCalls() {
Calls = append(Calls, &Call{ID: 678, Name: "setsockopt$SCTP_DEFAULT_SNDINFO", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(34)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_sndinfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sid", IsOptional: false}, TypeSize: 2}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 2, Vals: []uintptr{1, 2, 4, 512}}, IntType{TypeCommon: TypeCommon{TypeName: "ppid", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "context", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
}()
func() {
Calls = append(Calls, &Call{ID: 679, Name: "setsockopt$SCTP_PRIMARY_ADDR", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(6)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_prim", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, StructType{TypeCommon: TypeCommon{TypeName: "sockaddr_sctp_padded", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "addr0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr7", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
Calls = append(Calls, &Call{ID: 679, Name: "setsockopt$SCTP_PRIMARY_ADDR", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(6)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_prim", IsOptional: false}, packed: true, align: 4, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, StructType{TypeCommon: TypeCommon{TypeName: "sockaddr_sctp_padded", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "addr0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr7", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
}()
func() {
Calls = append(Calls, &Call{ID: 680, Name: "setsockopt$SCTP_SET_PEER_PRIMARY_ADDR", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(5)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_prim", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, StructType{TypeCommon: TypeCommon{TypeName: "sockaddr_sctp_padded", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "addr0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr7", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
Calls = append(Calls, &Call{ID: 680, Name: "setsockopt$SCTP_SET_PEER_PRIMARY_ADDR", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(5)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sctp_prim", IsOptional: false}, packed: true, align: 4, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "assoc", IsOptional: false}, TypeSize: 4}, StructType{TypeCommon: TypeCommon{TypeName: "sockaddr_sctp_padded", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "addr0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "addr7", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})
}()
func() {
Calls = append(Calls, &Call{ID: 681, Name: "setsockopt$SCTP_NODELAY", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSctp}, ConstType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 0, Val: uintptr(132)}, ConstType{TypeCommon: TypeCommon{TypeName: "opt", IsOptional: false}, TypeSize: 0, Val: uintptr(3)}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "val", TypeSize: 0}}})

View File

@ -68,6 +68,8 @@ type Struct struct {
Name string
Flds [][]string
IsUnion bool
Packed bool
Align int
}
func generate(syscalls []Syscall, structs map[string]Struct, unnamed map[string][]string, flags map[string][]string, flagVals map[string]string, out io.Writer) {
@ -323,7 +325,15 @@ func generateArg(name, typ string, a []string, structs map[string]Struct, unname
typ = "UnionType"
fields = "Options"
}
fmt.Fprintf(out, "%v{TypeCommon: TypeCommon{TypeName: \"%v\", IsOptional: %v}, %v: []Type{", typ, str.Name, false, fields)
packed := ""
if str.Packed {
packed = ", packed: true"
}
align := ""
if str.Align != 0 {
align = fmt.Sprintf(", align: %v", str.Align)
}
fmt.Fprintf(out, "%v{TypeCommon: TypeCommon{TypeName: \"%v\", IsOptional: %v} %v %v, %v: []Type{", typ, str.Name, false, packed, align, fields)
for i, a := range str.Flds {
if i != 0 {
fmt.Fprintf(out, ", ")
@ -554,8 +564,24 @@ func parse(in io.Reader) (includes []string, defines map[string]string, syscalls
// Parsing a struct.
if p.Char() == '}' || p.Char() == ']' {
p.Parse(p.Char())
if _, ok := structs[str.Name]; ok {
failf("%v struct is defined multiple times", str.Name)
for _, attr := range parseType1(p, unnamed, flags, "")[1:] {
if str.IsUnion {
failf("union %v has attribute: %v", str.Name, attr)
}
switch attr {
case "packed":
str.Packed = true
case "align_1":
str.Align = 1
case "align_2":
str.Align = 2
case "align_4":
str.Align = 4
case "align_8":
str.Align = 8
default:
failf("unknown struct %v attribute: %v", str.Name, attr)
}
}
structs[str.Name] = *str
str = nil
@ -593,7 +619,7 @@ func parse(in io.Reader) (includes []string, defines map[string]string, syscalls
}
defines[key] = fmt.Sprintf("(%s)", val)
} else {
switch p.Char() {
switch ch := p.Char(); ch {
case '(':
// syscall
p.Parse('(')
@ -625,12 +651,12 @@ func parse(in io.Reader) (includes []string, defines map[string]string, syscalls
vals = append(vals, p.Ident())
}
flags[name] = vals
case '{':
p.Parse('{')
str = &Struct{Name: name}
case '[':
p.Parse('[')
str = &Struct{Name: name, IsUnion: true}
case '{', '[':
p.Parse(ch)
if _, ok := structs[name]; ok {
failf("%v struct is defined multiple times", name)
}
str = &Struct{Name: name, IsUnion: ch == '['}
default:
failf("bad line (%v)", p.Str())
}