1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
// 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)
rec = func(t Type) {
switch t1 := t.(type) {
case *PtrType:
rec(t1.Type)
case *ArrayType:
rec(t1.Type)
case *StructType:
if !t1.padded {
t1.padded = true
for _, f := range t1.Fields {
rec(f)
}
addAlignment(t1)
}
case *UnionType:
for _, opt := range t1.Options {
rec(opt)
}
}
}
for _, s := range Structs {
rec(s)
}
}
func addAlignment(t *StructType) {
if t.packed {
return
}
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))
}
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 !varLen {
off += f.Size()
}
}
if align != 0 && off%align != 0 && !varLen {
pad := align - off%align
off += pad
fields = append(fields, makePad(pad))
}
t.Fields = fields
}
func makePad(sz uintptr) Type {
return &ConstType{
TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false},
TypeSize: sz,
Val: 0,
IsPad: true,
}
}
|