]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.23] 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 21:57:44 +0000 (21:57 +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 #69219

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/+/611296
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Commit-Queue: 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 6c23e59adf19eb6e49d789de6b6ef722747187f7..be93c4a24bb5663e49684cd360750fd2da90c0f0 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 374689631d77ab191544a7feadd9d1474ca35041..362be79a737bee412129cbc0c4f90622cfd14f77 100644 (file)
@@ -940,6 +940,19 @@ typedef struct {
 } issue67517struct;
 static void issue67517(issue67517struct* p) {}
 
+// 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"
 
@@ -2349,3 +2362,24 @@ func issue67517() {
                b: nil,
        })
 }
+
+// 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)
+       }
+}