From: Russ Cox Date: Tue, 13 May 2014 03:48:20 +0000 (-0400) Subject: cmd/cgo: omit misaligned struct fields, like we omit bitfields X-Git-Tag: go1.3beta2~79 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2d1a9510edc59cad463029fdc8ac93e62247baad;p=gostls13.git cmd/cgo: omit misaligned struct fields, like we omit bitfields Fixes #7560. LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/96300045 --- diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index f015ec9fa3..eb237725a4 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -52,5 +52,6 @@ func Test6390(t *testing.T) { test6390(t) } func Test5986(t *testing.T) { test5986(t) } func Test7665(t *testing.T) { test7665(t) } func TestNaming(t *testing.T) { testNaming(t) } +func Test7560(t *testing.T) { test7560(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } diff --git a/misc/cgo/test/issue7560.go b/misc/cgo/test/issue7560.go new file mode 100644 index 0000000000..4bea6e3573 --- /dev/null +++ b/misc/cgo/test/issue7560.go @@ -0,0 +1,44 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgotest + +/* +#include + +typedef struct { + char x; + long y; +} __attribute__((__packed__)) misaligned; + +int +offset7560(void) +{ + return (uintptr_t)&((misaligned*)0)->y; +} +*/ +import "C" + +import ( + "reflect" + "testing" +) + +func test7560(t *testing.T) { + // some mingw don't implement __packed__ correctly. + if C.offset7560() != 1 { + t.Skip("C compiler did not pack struct") + } + + // C.misaligned should have x but then a padding field to get to the end of the struct. + // There should not be a field named 'y'. + var v C.misaligned + rt := reflect.TypeOf(&v).Elem() + if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" { + t.Errorf("unexpected fields in C.misaligned:\n") + for i := 0; i < rt.NumField(); i++ { + t.Logf("%+v\n", rt.Field(i)) + } + } +} diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 605bab6d2e..057d25f5b4 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -68,6 +68,9 @@ Go references to C Within the Go file, C's struct field names that are keywords in Go can be accessed by prefixing them with an underscore: if x points at a C struct with a field named "type", x._type accesses the field. +C struct fields that cannot be expressed in Go, such as bit fields +or misaligned data, are omitted in the Go struct, replaced by +appropriate padding to reach the next field or the end of the struct. The standard C numeric types are available under the names C.char, C.schar (signed char), C.uchar (unsigned char), diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index b8b783051d..c5fcdfc3df 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -1499,7 +1499,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct t := c.Type(f.Type, pos) tgo := t.Go size := t.Size - + talign := t.Align if f.BitSize > 0 { if f.BitSize%8 != 0 { continue @@ -1512,8 +1512,17 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct name = "uint" } tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize)) + talign = size } + if talign > 0 && f.ByteOffset%talign != 0 { + // Drop misaligned fields, the same way we drop integer bit fields. + // The goal is to make available what can be made available. + // Otherwise one bad and unneeded field in an otherwise okay struct + // makes the whole program not compile. Much of the time these + // structs are in system headers that cannot be corrected. + continue + } n := len(fld) fld = fld[0 : n+1] name := f.Name @@ -1528,8 +1537,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct buf.WriteString(" ") buf.WriteString(name) buf.WriteString("; ") - if t.Align > align { - align = t.Align + if talign > align { + align = talign } } if off < dt.ByteSize {