Skip to content

Commit c209892

Browse files
ianlancetaylorgopherbot
authored andcommitted
cmd/cgo: correct padding required by alignment
If the aligned offset isn't sufficient for the field offset, we were padding based on the aligned offset. We need to pad based on the original offset instead. Also set the Go alignment correctly for int128. We were defaulting to the maximum alignment, but since we translate int128 into an array of uint8 the correct Go alignment is 1. Fixes #69086 Change-Id: I23ce583335c81beac2ac51f7f9336ac97ccebf09 Reviewed-on: https://go-review.googlesource.com/c/go/+/608815 Reviewed-by: Damien Neil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent 6781ff2 commit c209892

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

src/cmd/cgo/gcc.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
25772577
if dt.BitSize > 0 {
25782578
fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
25792579
}
2580+
2581+
if t.Align = t.Size; t.Align >= c.ptrSize {
2582+
t.Align = c.ptrSize
2583+
}
2584+
25802585
switch t.Size {
25812586
default:
25822587
fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
@@ -2593,9 +2598,8 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
25932598
Len: c.intExpr(t.Size),
25942599
Elt: c.uint8,
25952600
}
2596-
}
2597-
if t.Align = t.Size; t.Align >= c.ptrSize {
2598-
t.Align = c.ptrSize
2601+
// t.Align is the alignment of the Go type.
2602+
t.Align = 1
25992603
}
26002604

26012605
case *dwarf.PtrType:
@@ -2824,6 +2828,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
28242828
if dt.BitSize > 0 {
28252829
fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
28262830
}
2831+
2832+
if t.Align = t.Size; t.Align >= c.ptrSize {
2833+
t.Align = c.ptrSize
2834+
}
2835+
28272836
switch t.Size {
28282837
default:
28292838
fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
@@ -2840,9 +2849,8 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
28402849
Len: c.intExpr(t.Size),
28412850
Elt: c.uint8,
28422851
}
2843-
}
2844-
if t.Align = t.Size; t.Align >= c.ptrSize {
2845-
t.Align = c.ptrSize
2852+
// t.Align is the alignment of the Go type.
2853+
t.Align = 1
28462854
}
28472855

28482856
case *dwarf.VoidType:
@@ -3108,10 +3116,11 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
31083116
}
31093117

31103118
// Round off up to talign, assumed to be a power of 2.
3119+
origOff := off
31113120
off = (off + talign - 1) &^ (talign - 1)
31123121

31133122
if f.ByteOffset > off {
3114-
fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
3123+
fld, sizes = c.pad(fld, sizes, f.ByteOffset-origOff)
31153124
off = f.ByteOffset
31163125
}
31173126
if f.ByteOffset < off {

src/cmd/cgo/internal/test/cgo_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func Test31891(t *testing.T) { test31891(t) }
7070
func Test42018(t *testing.T) { test42018(t) }
7171
func Test45451(t *testing.T) { test45451(t) }
7272
func Test49633(t *testing.T) { test49633(t) }
73+
func Test69086(t *testing.T) { test69086(t) }
7374
func TestAlign(t *testing.T) { testAlign(t) }
7475
func TestAtol(t *testing.T) { testAtol(t) }
7576
func TestBlocking(t *testing.T) { testBlocking(t) }

src/cmd/cgo/internal/test/test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,19 @@ typedef struct {
940940
} issue67517struct;
941941
static void issue67517(issue67517struct* p) {}
942942
943+
// Issue 69086.
944+
// GCC added the __int128 type in GCC 4.6, released in 2011.
945+
typedef struct {
946+
int a;
947+
#ifdef __SIZEOF_INT128__
948+
unsigned __int128 b;
949+
#else
950+
uint64_t b;
951+
#endif
952+
unsigned char c;
953+
} issue69086struct;
954+
static int issue690861(issue69086struct* p) { p->b = 1234; return p->c; }
955+
static int issue690862(unsigned long ul1, unsigned long ul2, unsigned int u, issue69086struct s) { return (int)(s.b); }
943956
*/
944957
import "C"
945958

@@ -2349,3 +2362,24 @@ func issue67517() {
23492362
b: nil,
23502363
})
23512364
}
2365+
2366+
// Issue 69086.
2367+
func test69086(t *testing.T) {
2368+
var s C.issue69086struct
2369+
2370+
typ := reflect.TypeOf(s)
2371+
for i := 0; i < typ.NumField(); i++ {
2372+
f := typ.Field(i)
2373+
t.Logf("field %d: name %s size %d align %d offset %d", i, f.Name, f.Type.Size(), f.Type.Align(), f.Offset)
2374+
}
2375+
2376+
s.c = 1
2377+
got := C.issue690861(&s)
2378+
if got != 1 {
2379+
t.Errorf("field: got %d, want 1", got)
2380+
}
2381+
got = C.issue690862(1, 2, 3, s)
2382+
if got != 1234 {
2383+
t.Errorf("call: got %d, want 1234", got)
2384+
}
2385+
}

0 commit comments

Comments
 (0)