diff options
author | Konstantin Baladurin <k.baladurin@partner.samsung.com> | 2018-04-16 21:11:41 +0300 |
---|---|---|
committer | 이형주/Tizen Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com> | 2018-07-06 09:22:08 +0900 |
commit | b192de29e9035467716c59187d774f2105c89521 (patch) | |
tree | dfe836ddc7d16f33d5a0060524fc87c16b5f9020 | |
parent | 085dc2aec408c22e48ec5fff46b42429accf8a6f (diff) | |
download | coreclr-b192de29e9035467716c59187d774f2105c89521.tar.gz coreclr-b192de29e9035467716c59187d774f2105c89521.tar.bz2 coreclr-b192de29e9035467716c59187d774f2105c89521.zip |
[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
6 files changed, 120 insertions, 35 deletions
diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp index 1e24399e30..dfbbb9aebb 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 8c1f8fe1ac..934f058f99 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 030e767bac..c0d16b8623 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 eac0ab60d7..6882ad0489 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 5bb4715f4d..6b284012c5 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 ad27ef64a9..704552d85e 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 ); } |