]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.22] cmd/cgo: correct padding required by alignment
authorIan Lance Taylor <iant@golang.org>
Tue, 27 Aug 2024 17:19:17 +0000 (10:19 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 5 Sep 2024 22:14:37 +0000 (22:14 +0000)
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.

For #69086
Fixes #69218

Change-Id: I23ce583335c81beac2ac51f7f9336ac97ccebf09
Reviewed-on: https://go-review.googlesource.com/c/go/+/608815
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit c2098929056481d0dc09f5f42b8959f4db8878f2)
Reviewed-on: https://go-review.googlesource.com/c/go/+/611297
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/cmd/cgo/gcc.go
src/cmd/cgo/internal/test/cgo_test.go
src/cmd/cgo/internal/test/test.go

index 6e7556de9606281571b1955bfa400d0fb6ca5c86..2cf77d87e8a29250d43a36b7b2a45642b4d91f31 100644 (file)
@@ -2579,6 +2579,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
                if dt.BitSize > 0 {
                        fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
                }
+
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+
                switch t.Size {
                default:
                        fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
@@ -2595,9 +2600,8 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
                                Len: c.intExpr(t.Size),
                                Elt: c.uint8,
                        }
-               }
-               if t.Align = t.Size; t.Align >= c.ptrSize {
-                       t.Align = c.ptrSize
+                       // t.Align is the alignment of the Go type.
+                       t.Align = 1
                }
 
        case *dwarf.PtrType:
@@ -2826,6 +2830,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
                if dt.BitSize > 0 {
                        fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
                }
+
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+
                switch t.Size {
                default:
                        fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
@@ -2842,9 +2851,8 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
                                Len: c.intExpr(t.Size),
                                Elt: c.uint8,
                        }
-               }
-               if t.Align = t.Size; t.Align >= c.ptrSize {
-                       t.Align = c.ptrSize
+                       // t.Align is the alignment of the Go type.
+                       t.Align = 1
                }
 
        case *dwarf.VoidType:
@@ -3110,10 +3118,11 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
                }
 
                // Round off up to talign, assumed to be a power of 2.
+               origOff := off
                off = (off + talign - 1) &^ (talign - 1)
 
                if f.ByteOffset > off {
-                       fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
+                       fld, sizes = c.pad(fld, sizes, f.ByteOffset-origOff)
                        off = f.ByteOffset
                }
                if f.ByteOffset < off {
index 5e02888b3dddd9cb185998ed61ca6ea2c28b445c..5393552e07a4d1130267f1bdc19627a51060cb3f 100644 (file)
@@ -70,6 +70,7 @@ func Test31891(t *testing.T)                 { test31891(t) }
 func Test42018(t *testing.T)                 { test42018(t) }
 func Test45451(t *testing.T)                 { test45451(t) }
 func Test49633(t *testing.T)                 { test49633(t) }
+func Test69086(t *testing.T)                 { test69086(t) }
 func TestAlign(t *testing.T)                 { testAlign(t) }
 func TestAtol(t *testing.T)                  { testAtol(t) }
 func TestBlocking(t *testing.T)              { testBlocking(t) }
index 9b3790eb11e2d85dde3c4f23cf06f42210969fa3..bffe7f9aeeb5cbf0cb7008d963c17eb7b41d1b58 100644 (file)
@@ -933,6 +933,19 @@ typedef struct issue45451Undefined issue45451;
 extern void GoFunc49633(void*);
 void cfunc49633(void *context) { GoFunc49633(context); }
 
+// Issue 69086.
+// GCC added the __int128 type in GCC 4.6, released in 2011.
+typedef struct {
+       int a;
+#ifdef __SIZEOF_INT128__
+       unsigned __int128 b;
+#else
+       uint64_t b;
+#endif
+       unsigned char c;
+} issue69086struct;
+static int issue690861(issue69086struct* p) { p->b = 1234; return p->c; }
+static int issue690862(unsigned long ul1, unsigned long ul2, unsigned int u, issue69086struct s) { return (int)(s.b); }
 */
 import "C"
 
@@ -2321,3 +2334,24 @@ func test45451(t *testing.T) {
 func func52542[T ~[]C.int]() {}
 
 type type52542[T ~*C.float] struct{}
+
+// Issue 69086.
+func test69086(t *testing.T) {
+       var s C.issue69086struct
+
+       typ := reflect.TypeOf(s)
+       for i := 0; i < typ.NumField(); i++ {
+               f := typ.Field(i)
+               t.Logf("field %d: name %s size %d align %d offset %d", i, f.Name, f.Type.Size(), f.Type.Align(), f.Offset)
+       }
+
+       s.c = 1
+       got := C.issue690861(&s)
+       if got != 1 {
+               t.Errorf("field: got %d, want 1", got)
+       }
+       got = C.issue690862(1, 2, 3, s)
+       if got != 1234 {
+               t.Errorf("call: got %d, want 1234", got)
+       }
+}