summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>2018-04-16 18:11:41 (GMT)
committerGleb Balykov <g.balykov@samsung.com>2018-09-18 12:49:14 (GMT)
commitd424bb734ce61bc98d1cfab815c48c5ad1d01d5e (patch)
tree5bde5d7331409e274ef179620376910b3b337c27
parente15bd6545ad4d917eeafaf91a725b12f84c20ec2 (diff)
downloadcoreclr-d424bb734ce61bc98d1cfab815c48c5ad1d01d5e.zip
coreclr-d424bb734ce61bc98d1cfab815c48c5ad1d01d5e.tar.gz
coreclr-d424bb734ce61bc98d1cfab815c48c5ad1d01d5e.tar.bz2
[x86/Linux] Fix marshalling struct with 64-bit types (#17455)
* [x86/Linux] Fix marshalling struct with 64-bit types The System V ABI for i386 defines 4-byte alignment for 64-bit types. * [Linux/x86] Fix marshalling tests in the case of System V i386 ABI
-rw-r--r--src/vm/fieldmarshaler.cpp20
-rw-r--r--src/vm/fieldmarshaler.h6
-rw-r--r--tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof1.cs12
-rw-r--r--tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof2.cs12
-rw-r--r--tests/src/Interop/MarshalAPI/OffsetOf/OffsetOf.cs69
-rw-r--r--tests/src/Interop/StructPacking/StructPacking.cs36
6 files changed, 120 insertions, 35 deletions
diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp
index 1e24399..dfbbb9a 100644
--- a/src/vm/fieldmarshaler.cpp
+++ b/src/vm/fieldmarshaler.cpp
@@ -285,7 +285,27 @@ do \
if (CorTypeInfo::IsPrimitiveType(corElemType))
{
pfwalk->m_managedSize = ((UINT32)CorTypeInfo::Size(corElemType)); // Safe cast - no primitive type is larger than 4gb!
+#if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
+ switch (corElemType)
+ {
+ // The System V ABI for i386 defines different packing for these types.
+ case ELEMENT_TYPE_I8:
+ case ELEMENT_TYPE_U8:
+ case ELEMENT_TYPE_R8:
+ {
+ pfwalk->m_managedAlignmentReq = 4;
+ break;
+ }
+
+ default:
+ {
+ pfwalk->m_managedAlignmentReq = pfwalk->m_managedSize;
+ break;
+ }
+ }
+#else // _TARGET_X86_ && UNIX_X86_ABI
pfwalk->m_managedAlignmentReq = pfwalk->m_managedSize;
+#endif
}
else if (corElemType == ELEMENT_TYPE_PTR)
{
diff --git a/src/vm/fieldmarshaler.h b/src/vm/fieldmarshaler.h
index 8c1f8fe..934f058 100644
--- a/src/vm/fieldmarshaler.h
+++ b/src/vm/fieldmarshaler.h
@@ -1626,7 +1626,13 @@ public:
UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
+#if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
+ // The System V ABI for i386 defines 4-byte alignment for 64-bit types.
+ SCALAR_MARSHALER_IMPL(8, 4)
+#else
SCALAR_MARSHALER_IMPL(8, 8)
+#endif // _TARGET_X86_
+
COPY_TO_IMPL_BASE_STRUCT_ONLY()
VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
diff --git a/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof1.cs b/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof1.cs
index 030e767..c0d16b8 100644
--- a/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof1.cs
+++ b/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof1.cs
@@ -225,7 +225,17 @@ public class MarshalSizeOf1
TestMultiMemberStruct1 obj = new TestMultiMemberStruct1();
obj.TestInt = TestLibrary.Generator.GetInt32(-55);
obj.TestDouble = TestLibrary.Generator.GetDouble(-55);
- int expectedSize = 16; // sizeof(double) + sizeof(int) + padding
+ int expectedSize;
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ expectedSize = 16; // sizeof(double) + sizeof(int) + padding
+ }
+ else
+ {
+ // The System V ABI for i386 defines double as having 4-byte alignment
+ expectedSize = 12; // sizeof(double) + sizeof(int)
+ }
int actualSize = Marshal.SizeOf(obj);
diff --git a/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof2.cs b/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof2.cs
index eac0ab6..6882ad0 100644
--- a/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof2.cs
+++ b/tests/src/CoreMangLib/cti/system/runtime/interopservices/marshal/marshalsizeof2.cs
@@ -210,7 +210,17 @@ public class MarshalSizeOf2
try
{
Type obj = typeof(TestMultiMemberStruct1);
- int expectedSize = 16; // sizeof(double) + sizeof(int) + padding
+ int expectedSize;
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ expectedSize = 16; // sizeof(double) + sizeof(int) + padding
+ }
+ else
+ {
+ // The System V ABI for i386 defines double as having 4-byte alignment
+ expectedSize = 12; // sizeof(double) + sizeof(int)
+ }
int actualSize = Marshal.SizeOf(obj);
diff --git a/tests/src/Interop/MarshalAPI/OffsetOf/OffsetOf.cs b/tests/src/Interop/MarshalAPI/OffsetOf/OffsetOf.cs
index 5bb4715..6b28401 100644
--- a/tests/src/Interop/MarshalAPI/OffsetOf/OffsetOf.cs
+++ b/tests/src/Interop/MarshalAPI/OffsetOf/OffsetOf.cs
@@ -109,13 +109,13 @@ internal struct FieldAlignementTest
// 3 bytes of padding
public Int32 m_int2; // 4 bytes
- // 4 bytes of padding
+ // 4 bytes of padding (0 bytes on x86/Unix according System V ABI as double 4-byte aligned)
public double m_double1; // 8 bytes
public char m_char1; // 1 byte
public char m_char2; // 1 byte
public char m_char3; // 1 byte
- // 5 bytes of padding
+ // 5 bytes of padding (1 byte on x86/Unix according System V ABI as double 4-byte aligned)
public double m_double2; // 8 bytes
public byte m_byte3; // 1 byte
@@ -137,7 +137,7 @@ struct FieldAlignementTest_Decimal
// This is because unlike fields of other types well known to mcg (like long, char etc.)
// which need to be aligned according to their byte size, decimal is really a struct
// with 8 byte alignment requirement.
- public FieldAlignementTest p; // 80 bytes
+ public FieldAlignementTest p; // 80 bytes (72 bytes on x86/Unix)
public short s; // 2 bytes
// 6 bytes of padding
@@ -251,7 +251,14 @@ public class OffsetTest
public static void TestFieldAlignment()
{
var t = typeof(FieldAlignementTest);
- Assert.AreEqual(80, Marshal.SizeOf(t));
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.AreEqual(80, Marshal.SizeOf(t));
+ }
+ else
+ {
+ Assert.AreEqual(72, Marshal.SizeOf(t));
+ }
Assert.AreEqual(new IntPtr(0), Marshal.OffsetOf(t, "m_byte1"));
Assert.AreEqual(new IntPtr(2), Marshal.OffsetOf(t, "m_short1"));
@@ -259,26 +266,58 @@ public class OffsetTest
Assert.AreEqual(new IntPtr(8), Marshal.OffsetOf(t, "m_int1"));
Assert.AreEqual(new IntPtr(12), Marshal.OffsetOf(t, "m_byte2"));
Assert.AreEqual(new IntPtr(16), Marshal.OffsetOf(t, "m_int2"));
- Assert.AreEqual(new IntPtr(24), Marshal.OffsetOf(t, "m_double1"));
- Assert.AreEqual(new IntPtr(32), Marshal.OffsetOf(t, "m_char1"));
- Assert.AreEqual(new IntPtr(33), Marshal.OffsetOf(t, "m_char2"));
- Assert.AreEqual(new IntPtr(34), Marshal.OffsetOf(t, "m_char3"));
- Assert.AreEqual(new IntPtr(40), Marshal.OffsetOf(t, "m_double2"));
- Assert.AreEqual(new IntPtr(48), Marshal.OffsetOf(t, "m_byte3"));
- Assert.AreEqual(new IntPtr(49), Marshal.OffsetOf(t, "m_byte4"));
- Assert.AreEqual(new IntPtr(56), Marshal.OffsetOf(t, "m_decimal1"));
- Assert.AreEqual(new IntPtr(72), Marshal.OffsetOf(t, "m_char4"));
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.AreEqual(new IntPtr(24), Marshal.OffsetOf(t, "m_double1"));
+ Assert.AreEqual(new IntPtr(32), Marshal.OffsetOf(t, "m_char1"));
+ Assert.AreEqual(new IntPtr(33), Marshal.OffsetOf(t, "m_char2"));
+ Assert.AreEqual(new IntPtr(34), Marshal.OffsetOf(t, "m_char3"));
+ Assert.AreEqual(new IntPtr(40), Marshal.OffsetOf(t, "m_double2"));
+ Assert.AreEqual(new IntPtr(48), Marshal.OffsetOf(t, "m_byte3"));
+ Assert.AreEqual(new IntPtr(49), Marshal.OffsetOf(t, "m_byte4"));
+ Assert.AreEqual(new IntPtr(56), Marshal.OffsetOf(t, "m_decimal1"));
+ Assert.AreEqual(new IntPtr(72), Marshal.OffsetOf(t, "m_char4"));
+ }
+ else
+ {
+ Assert.AreEqual(new IntPtr(20), Marshal.OffsetOf(t, "m_double1"));
+ Assert.AreEqual(new IntPtr(28), Marshal.OffsetOf(t, "m_char1"));
+ Assert.AreEqual(new IntPtr(29), Marshal.OffsetOf(t, "m_char2"));
+ Assert.AreEqual(new IntPtr(30), Marshal.OffsetOf(t, "m_char3"));
+ Assert.AreEqual(new IntPtr(32), Marshal.OffsetOf(t, "m_double2"));
+ Assert.AreEqual(new IntPtr(40), Marshal.OffsetOf(t, "m_byte3"));
+ Assert.AreEqual(new IntPtr(41), Marshal.OffsetOf(t, "m_byte4"));
+ Assert.AreEqual(new IntPtr(48), Marshal.OffsetOf(t, "m_decimal1"));
+ Assert.AreEqual(new IntPtr(64), Marshal.OffsetOf(t, "m_char4"));
+ }
}
public static void TestFieldAlignment_Decimal()
{
var t = typeof(FieldAlignementTest_Decimal);
- Assert.AreEqual(96, Marshal.SizeOf(t));
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.AreEqual(96, Marshal.SizeOf(t));
+ }
+ else
+ {
+ Assert.AreEqual(88, Marshal.SizeOf(t));
+ }
Assert.AreEqual(new IntPtr(0), Marshal.OffsetOf(t, "b"));
Assert.AreEqual(new IntPtr(8), Marshal.OffsetOf(t, "p"));
- Assert.AreEqual(new IntPtr(88), Marshal.OffsetOf(t, "s"));
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+ {
+ Assert.AreEqual(new IntPtr(88), Marshal.OffsetOf(t, "s"));
+ }
+ else
+ {
+ Assert.AreEqual(new IntPtr(80), Marshal.OffsetOf(t, "s"));
+ }
}
diff --git a/tests/src/Interop/StructPacking/StructPacking.cs b/tests/src/Interop/StructPacking/StructPacking.cs
index ad27ef6..704552d 100644
--- a/tests/src/Interop/StructPacking/StructPacking.cs
+++ b/tests/src/Interop/StructPacking/StructPacking.cs
@@ -384,20 +384,20 @@ unsafe class Program
succeeded &= Test<AutoLayoutDefaultPacking<double>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
succeeded &= Test<AutoLayoutMinPacking<double>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
succeeded &= Test<AutoLayoutMaxPacking<double>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
}
@@ -603,20 +603,20 @@ unsafe class Program
succeeded &= Test<AutoLayoutDefaultPacking<long>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
succeeded &= Test<AutoLayoutMinPacking<long>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
succeeded &= Test<AutoLayoutMaxPacking<long>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
}
@@ -1016,20 +1016,20 @@ unsafe class Program
succeeded &= Test<AutoLayoutDefaultPacking<ulong>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
succeeded &= Test<AutoLayoutMinPacking<ulong>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
succeeded &= Test<AutoLayoutMaxPacking<ulong>>(
expectedSize: 12,
- expectedOffsetByte: 0,
- expectedOffsetValue: 4
+ expectedOffsetByte: 8,
+ expectedOffsetValue: 0
);
}