aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/align.go43
-rw-r--r--sys/decl.go13
-rw-r--r--sys/test.txt120
3 files changed, 145 insertions, 31 deletions
diff --git a/sys/align.go b/sys/align.go
index 8b9e1a3c2..3c672b83e 100644
--- a/sys/align.go
+++ b/sys/align.go
@@ -22,6 +22,7 @@ func initAlign() {
rec(f)
}
markBitfields(t1)
+ markVarlen(t1)
addAlignment(t1)
}
case *UnionType:
@@ -76,13 +77,38 @@ func markBitfields(t *StructType) {
}
}
+func markVarlen(t *StructType) {
+ for i, f := range t.Fields {
+ if at, ok := f.(*StructType); ok && at.Varlen {
+ t.Varlen = true
+ }
+ if at, ok := f.(*UnionType); ok && at.Varlen {
+ t.Varlen = true
+ }
+ if at, ok := f.(*ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) {
+ t.Varlen = true
+ }
+ if at, ok := f.(*BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) {
+ t.Varlen = true
+ }
+ if !t.packed && t.Varlen && i != len(t.Fields)-1 {
+ panic(fmt.Sprintf("variable length field %+v in the middle of a struct %+v", f, t))
+ }
+ }
+}
+
func addAlignment(t *StructType) {
if t.packed {
+ // If a struct is packed, statically sized and has explicitly set alignment, add a padding.
+ if !t.Varlen && t.align != 0 && t.Size()%t.align != 0 {
+ pad := t.align - t.Size()%t.align
+ t.Fields = append(t.Fields, makePad(pad))
+ }
return
}
var fields []Type
- var off, align uintptr
- varLen := false
+ var off uintptr
+ align := t.align
for i, f := range t.Fields {
a := f.Align()
if align < a {
@@ -97,21 +123,12 @@ func addAlignment(t *StructType) {
}
}
fields = append(fields, f)
- if at, ok := f.(*ArrayType); ok && (at.Kind == ArrayRandLen || (at.Kind == ArrayRangeLen && at.RangeBegin != at.RangeEnd)) {
- varLen = true
- }
- if at, ok := f.(*BufferType); ok && (at.Kind == BufferBlobRand || (at.Kind == BufferBlobRange && at.RangeBegin != at.RangeEnd)) {
- varLen = true
- }
- if varLen && i != len(t.Fields)-1 {
- panic("embed array in middle of a struct")
- }
- if (f.BitfieldLength() == 0 || f.BitfieldLast()) && !varLen {
+ if (f.BitfieldLength() == 0 || f.BitfieldLast()) && !t.Varlen {
// Increase offset if the current field is not a bitfield or it's the last bitfield in a set.
off += f.Size()
}
}
- if align != 0 && off%align != 0 && !varLen {
+ if align != 0 && off%align != 0 && !t.Varlen {
pad := align - off%align
off += pad
fields = append(fields, makePad(pad))
diff --git a/sys/decl.go b/sys/decl.go
index 9c7887f99..08df93dd2 100644
--- a/sys/decl.go
+++ b/sys/decl.go
@@ -222,6 +222,7 @@ type BufferType struct {
Text TextKind // for BufferText
SubKind string
Values []string // possible values for BufferString kind
+ Length uintptr // max string length for BufferString kind
}
func (t *BufferType) Size() uintptr {
@@ -292,6 +293,7 @@ func (t *PtrType) Align() uintptr {
type StructType struct {
TypeCommon
Fields []Type
+ Varlen bool
padded bool
packed bool
align uintptr
@@ -303,7 +305,9 @@ func (t *StructType) Size() uintptr {
}
var size uintptr
for _, f := range t.Fields {
- size += f.Size()
+ if f.BitfieldLength() == 0 || f.BitfieldLast() {
+ size += f.Size()
+ }
}
return size
}
@@ -312,6 +316,9 @@ func (t *StructType) Align() uintptr {
if t.align != 0 {
return t.align // overrided by user attribute
}
+ if t.packed {
+ return 1
+ }
var align uintptr
for _, f := range t.Fields {
if a1 := f.Align(); align < a1 {
@@ -324,11 +331,11 @@ func (t *StructType) Align() uintptr {
type UnionType struct {
TypeCommon
Options []Type
- varlen bool
+ Varlen bool
}
func (t *UnionType) Size() uintptr {
- if t.varlen {
+ if t.Varlen {
panic("union size is not statically known")
}
size := t.Options[0].Size()
diff --git a/sys/test.txt b/sys/test.txt
index aa9ea1ab0..68ca85db8 100644
--- a/sys/test.txt
+++ b/sys/test.txt
@@ -6,16 +6,23 @@
syz_test()
# Integer types.
+
syz_test$int(a0 intptr, a1 int8, a2 int16, a3 int32, a4 int64)
# Opt arguments
+
syz_test$opt0(a0 intptr[opt])
syz_test$opt1(a0 ptr[in, intptr, opt])
syz_test$opt2(a0 vma[opt])
-# Struct alignment.
+# Alignment and padding
+
syz_test$align0(a0 ptr[in, syz_align0])
syz_test$align1(a0 ptr[in, syz_align1])
+syz_test$align2(a0 ptr[in, syz_align2])
+syz_test$align3(a0 ptr[in, syz_align3])
+syz_test$align4(a0 ptr[in, syz_align4])
+syz_test$align5(a0 ptr[in, syz_align5])
syz_align0 {
f0 int16
@@ -33,22 +40,93 @@ syz_align1 {
f4 int64
} [packed]
-# Unions.
+syz_align2_packed {
+ f0 array[int16, 1]
+} [packed]
-syz_test$union0(a0 ptr[in, syz_union_struct])
+syz_align2_not_packed {
+ f0 array[int16, 1]
+}
-syz_union_struct {
- f int64
- u syz_union0
+syz_align2 {
+ f0 int8
+ f1 syz_align2_packed
+ f2 syz_align2_not_packed
+}
+
+syz_align3_noalign {
+ f0 int8
+}
+
+syz_align3_align4 {
+ f0 int8
+} [align_4]
+
+syz_align3 {
+ f0 int8
+ f1 syz_align3_noalign
+ f2 syz_align3_align4
+}
+
+syz_align4_internal {
+ f0 int8
+ f1 int16
+} [packed, align_4]
+
+syz_align4 {
+ f0 syz_align4_internal
+ f1 int8
+}
+
+syz_align5_internal {
+ f0 int64
+ f1 array[int16, 0:3]
}
+syz_align5 {
+ f0 syz_align5_internal
+ f1 syz_align5_internal
+ f2 int8
+} [packed]
+
+# Unions
+
+syz_test$union0(a0 ptr[in, syz_union0_struct])
+syz_test$union1(a0 ptr[in, syz_union1_struct])
+syz_test$union2(a0 ptr[in, syz_union2_struct])
+
syz_union0 [
f0 int64
f1 array[int64, 10]
f2 int8
]
-# Arrays.
+syz_union0_struct {
+ f int64
+ u syz_union0
+}
+
+syz_union1 [
+ f0 int64
+ f1 int32
+]
+
+syz_union1_struct {
+ f0 syz_union1
+ f1 int8
+} [packed]
+
+syz_union2 [
+ f0 int64
+ f1 int32
+] [varlen]
+
+syz_union2_struct {
+ f0 syz_union2
+ f1 int8
+} [packed]
+
+# Arrays
syz_test$array0(a0 ptr[in, syz_array_struct])
syz_test$array1(a0 ptr[in, syz_array_trailing])
@@ -77,7 +155,7 @@ syz_array_blob {
f2 int16
}
-# Length.
+# Length
syz_test$length0(a0 ptr[in, syz_length_int_struct])
syz_test$length1(a0 ptr[in, syz_length_const_struct])
@@ -178,7 +256,7 @@ syz_length_bytesize_struct {
f5 bytesize8[f0, int8]
}
-# Big endian.
+# Big endian
syz_test$end0(a0 ptr[in, syz_end_int_struct])
syz_test$end1(a0 ptr[in, syz_end_var_struct])
@@ -199,18 +277,18 @@ syz_end_var_struct {
f2 flags[syz_end_flags, int64be]
} [packed]
-# Vma type.
+# Vma type
syz_test$vma0(v0 vma, l0 len[v0], v1 vma[5], l1 len[v1], v2 vma[7:9], l2 len[v2])
-# Text type.
+# Text type
syz_test$text_x86_real(a0 ptr[in, text[x86_real]], a1 len[a0])
syz_test$text_x86_16(a0 ptr[in, text[x86_16]], a1 len[a0])
syz_test$text_x86_32(a0 ptr[in, text[x86_32]], a1 len[a0])
syz_test$text_x86_64(a0 ptr[in, text[x86_64]], a1 len[a0])
-# Regression tests.
+# Regression tests
syz_test$regression0(a0 ptr[inout, syz_regression0_struct])
@@ -218,11 +296,11 @@ syz_regression0_struct {
f0 buffer[out]
}
-# Bitfields.
+# Bitfields
syz_bf_flags = 0, 1, 2
-syz_bf_struct {
+syz_bf_struct0 {
f0 flags[syz_bf_flags, int16:10]
f1 int64
f2 const[0x42, int16:5]
@@ -233,4 +311,16 @@ syz_bf_struct {
f7 int8
}
-syz_test$bf(a0 ptr[in, syz_bf_struct])
+syz_bf_struct1_internal {
+ f0 int32:10
+ f1 int32:10
+ f2 int32:10
+}
+
+syz_bf_struct1 {
+ f0 syz_bf_struct1_internal
+ f1 int8
+}
+
+syz_test$bf0(a0 ptr[in, syz_bf_struct0])
+syz_test$bf1(a0 ptr[in, syz_bf_struct1])