diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-09-29 13:28:03 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-09-29 13:30:08 +0200 |
| commit | 3ca39dfc4dd8a2dda5b3a9b8c29e295839490af3 (patch) | |
| tree | d3f4161d07c22e4a08eb0d3edfd61b485ef10579 /sys | |
| parent | bf21057e7c36c72c1b46aa71bea8dc48509d4c40 (diff) | |
sys: add padding to structs again
Struct padding was accidentially lost after:
852e3d2eae98a913b7ec91822ba4dc61059a6955
Restore it. Now with tests.
Fixes #78
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/align.go | 50 | ||||
| -rw-r--r-- | sys/decl.go | 47 | ||||
| -rw-r--r-- | sys/test.txt | 25 |
3 files changed, 83 insertions, 39 deletions
diff --git a/sys/align.go b/sys/align.go index 4c91c28be..6e8563da4 100644 --- a/sys/align.go +++ b/sys/align.go @@ -3,51 +3,37 @@ package sys -import ( - "fmt" -) - func initAlign() { - var rec func(t Type) Type - rec = func(t Type) Type { + var rec func(t Type) + rec = func(t Type) { switch t1 := t.(type) { case PtrType: - t1.Type = rec(t1.Type) - t = t1 + rec(t1.Type) case ArrayType: - t1.Type = rec(t1.Type) - t = t1 + rec(t1.Type) case *StructType: - for i, f := range t1.Fields { - t1.Fields[i] = rec(f) + if !t1.padded { + t1.padded = true + for _, f := range t1.Fields { + rec(f) + } + addAlignment(t1) } - t = addAlignment(t1) case *UnionType: - opts := make(map[string]bool) - for i, opt := range t1.Options { - if opts[opt.Name()] { - panic(fmt.Sprintf("duplicate option %v in union %v", opt.Name(), t.Name())) - } - opts[opt.Name()] = true - t1.Options[i] = rec(opt) + for _, opt := range t1.Options { + 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 _, s := range Structs { + rec(s) } } -func addAlignment(t *StructType) Type { +func addAlignment(t *StructType) { if t.packed { - t.padded = true - return t + return } var fields []Type var off, align uintptr @@ -77,8 +63,6 @@ func addAlignment(t *StructType) Type { fields = append(fields, makePad(pad)) } t.Fields = fields - t.padded = true - return t } func makePad(sz uintptr) Type { diff --git a/sys/decl.go b/sys/decl.go index 2cc8f22e5..f792f541c 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -252,11 +252,14 @@ type ArrayType struct { } func (t ArrayType) Size() uintptr { - panic("should not be called") + if t.RangeBegin == t.RangeEnd { + return t.RangeBegin * t.Type.Size() + } + return 0 // for trailing embed arrays } func (t ArrayType) Align() uintptr { - panic("should not be called") + return t.Type.Align() } type PtrType struct { @@ -282,11 +285,27 @@ type StructType struct { } func (t *StructType) Size() uintptr { - panic("not called") + if !t.padded { + panic("struct is not padded yet") + } + var size uintptr + for _, f := range t.Fields { + size += f.Size() + } + return size } func (t *StructType) Align() uintptr { - panic("not called") + 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 { + align = a1 + } + } + return align } type UnionType struct { @@ -296,11 +315,26 @@ type UnionType struct { } func (t *UnionType) Size() uintptr { - panic("not called") + if t.varlen { + panic("union size is not statically known") + } + size := t.Options[0].Size() + for _, opt := range t.Options { + if size < opt.Size() { + size = opt.Size() + } + } + return size } func (t *UnionType) Align() uintptr { - panic("not called") + var align uintptr + for _, opt := range t.Options { + if a1 := opt.Align(); align < a1 { + align = a1 + } + } + return align } type Dir int @@ -503,6 +537,7 @@ var ( func init() { initCalls() + initStructFields() initResources() initAlign() diff --git a/sys/test.txt b/sys/test.txt index 2fc41e677..a01c6b3c2 100644 --- a/sys/test.txt +++ b/sys/test.txt @@ -15,6 +15,7 @@ syz_test$opt2(a0 vma[opt]) # Struct alignment. syz_test$align0(a0 ptr[in, syz_align0]) +syz_test$align1(a0 ptr[in, syz_align1]) syz_align0 { f0 int16 @@ -24,6 +25,14 @@ syz_align0 { f4 int64 } +syz_align1 { + f0 int16 + f1 int32 + f2 int8 + f3 int16 + f4 int64 +} [packed] + # Unions. syz_test$union0(a0 ptr[in, syz_union_struct]) @@ -38,3 +47,19 @@ syz_union0 [ f1 array[int64, 10] f2 int8 ] + +# Arrays. + +syz_test$array0(a0 ptr[in, syz_array_struct]) + +# Struct with a variable-length array or variable-length unions. +syz_array_struct { + f0 int8 + f1 array[syz_array_union, 1:2] + f2 int64 +} [packed] + +syz_array_union [ + f0 int16 + f1 int64 +] [varlen] |
