Commit f7a8adbd authored by Matthew Dempsky's avatar Matthew Dempsky Committed by Ian Lance Taylor

cmd/cgo: fix handling of defs_linux.go

Instead of including <sys/types.h> to get size_t, instead include
the ISO C standard <stddef.h> header, which defines fewer additional
types at risk of colliding with the user code.  In particular, this
prevents collisions between <sys/types.h>'s userspace definitions with
the kernel definitions needed by defs_linux.go.

Also, -cdefs mode uses #pragma pack, so we can keep misaligned fields.

Fixes #8477.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/120610043
parent 48e75337
...@@ -6,3 +6,4 @@ ...@@ -6,3 +6,4 @@
#include "cdefstest.h" #include "cdefstest.h"
struct CdefsTest test; struct CdefsTest test;
struct PackedTest packed;
...@@ -35,7 +35,25 @@ struct cdefsTest { ...@@ -35,7 +35,25 @@ struct cdefsTest {
// Correct: -> Array [20][20]**int8 -> int8 **array[20][20] // Correct: -> Array [20][20]**int8 -> int8 **array[20][20]
char **array5[20][20]; char **array5[20][20];
}; };
// Test that packed structures can be translated to C correctly too.
// See issue 8477.
struct packedTest {
char first;
int second;
long long third;
} __attribute__((packed));
// Test that conflicting type definitions don't cause problems with cgo.
// See issue 8477.
typedef struct timespec {
double bogus;
} pid_t;
*/ */
import "C" import "C"
type CdefsTest C.struct_cdefsTest type CdefsTest C.struct_cdefsTest
type PackedTest C.struct_packedTest
...@@ -17,11 +17,22 @@ struct CdefsOrig { ...@@ -17,11 +17,22 @@ struct CdefsOrig {
int8 **array5[20][20]; int8 **array5[20][20];
}; };
typedef struct PackedOrig PackedOrig;
#pragma pack on
struct PackedOrig {
int8 first;
int32 second;
int64 third;
};
#pragma pack off
void void
main·test(int32 ret) main·test(int32 ret)
{ {
CdefsOrig o; CdefsOrig o;
CdefsTest t; CdefsTest t;
PackedOrig po;
PackedTest pt;
ret = 0; ret = 0;
if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) { if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) {
...@@ -44,5 +55,17 @@ main·test(int32 ret) ...@@ -44,5 +55,17 @@ main·test(int32 ret)
runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0])); runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0]));
ret = 1; ret = 1;
} }
if(sizeof(pt.first) != sizeof(po.first) || offsetof(PackedTest, first) != offsetof(PackedOrig, first)) {
runtime·printf("first: size, offset = %d, %d, want %d, %d\n", sizeof(pt.first), offsetof(PackedTest, first), sizeof(po.first), offsetof(PackedOrig, first));
ret = 1;
}
if(sizeof(pt.second) != sizeof(po.second) || offsetof(PackedTest, second) != offsetof(PackedOrig, second)) {
runtime·printf("second: size, offset = %d, %d, want %d, %d\n", sizeof(pt.second), offsetof(PackedTest, second), sizeof(po.second), offsetof(PackedOrig, second));
ret = 1;
}
if(sizeof(pt.third) != sizeof(po.third) || offsetof(PackedTest, third) != offsetof(PackedOrig, third)) {
runtime·printf("third: size, offset = %d, %d, want %d, %d\n", sizeof(pt.third), offsetof(PackedTest, third), sizeof(po.third), offsetof(PackedOrig, third));
ret = 1;
}
FLUSH(&ret); // flush return value FLUSH(&ret); // flush return value
} }
...@@ -1587,12 +1587,14 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct ...@@ -1587,12 +1587,14 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
talign = size talign = size
} }
if talign > 0 && f.ByteOffset%talign != 0 { if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs {
// Drop misaligned fields, the same way we drop integer bit fields. // Drop misaligned fields, the same way we drop integer bit fields.
// The goal is to make available what can be made available. // The goal is to make available what can be made available.
// Otherwise one bad and unneeded field in an otherwise okay struct // Otherwise one bad and unneeded field in an otherwise okay struct
// makes the whole program not compile. Much of the time these // makes the whole program not compile. Much of the time these
// structs are in system headers that cannot be corrected. // structs are in system headers that cannot be corrected.
// Exception: In -cdefs mode, we use #pragma pack, so misaligned
// fields should still work.
continue continue
} }
n := len(fld) n := len(fld)
......
...@@ -1148,16 +1148,10 @@ __cgo_size_assert(double, 8) ...@@ -1148,16 +1148,10 @@ __cgo_size_assert(double, 8)
` `
const builtinProlog = ` const builtinProlog = `
#include <sys/types.h> /* for size_t below */ #include <stddef.h> /* for ptrdiff_t and size_t below */
/* Define intgo when compiling with GCC. */ /* Define intgo when compiling with GCC. */
#ifdef __PTRDIFF_TYPE__ typedef ptrdiff_t intgo;
typedef __PTRDIFF_TYPE__ intgo;
#elif defined(_LP64)
typedef long long intgo;
#else
typedef int intgo;
#endif
typedef struct { char *p; intgo n; } _GoString_; typedef struct { char *p; intgo n; } _GoString_;
typedef struct { char *p; intgo n; intgo c; } _GoBytes_; typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
......
...@@ -28,6 +28,7 @@ package runtime ...@@ -28,6 +28,7 @@ package runtime
#include <asm-generic/errno.h> #include <asm-generic/errno.h>
#include <asm-generic/poll.h> #include <asm-generic/poll.h>
#include <linux/eventpoll.h> #include <linux/eventpoll.h>
#undef size_t
*/ */
import "C" import "C"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment