From 72f310a6c3dccbabf9edc29677b51ed78c87cc67 Mon Sep 17 00:00:00 2001 From: Sanjam Panda Date: Tue, 19 Sep 2023 15:16:02 +0200 Subject: [PATCH 1/3] [wasm] Endian fix for Webcil 'dotnet new blazorwasm' command failed on s390x and was throwing a not implemented exception The issue was with with the WebCil writer and reader, specific endianness conversions relating to the webcil payload were not implemented for big endian machines. We considered fixing the generic implementation, but there were only two structures in use: WebcilHeader and WebcilSectionHeader, so it was easier to handle them explicitly. --- .../Microsoft.NET.WebAssembly.Webcil.csproj | 1 + .../WebcilConverter.cs | 35 +++++++++++++----- .../WebcilReader.cs | 37 +++++++++++++++---- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj index c35eb57e80686..d09ae4a569a59 100644 --- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj +++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj @@ -16,6 +16,7 @@ + diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs index a38af7270a2da..7b882c42d579e 100644 --- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs +++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Buffers.Binary; using System.IO; using System.Collections.Immutable; using System.Reflection.PortableExecutable; @@ -181,9 +182,6 @@ private static void WriteHeader(Stream s, WebcilHeader header) private static void WriteSectionHeaders(Stream s, ImmutableArray sectionsHeaders) { - // FIXME: fixup endianness - if (!BitConverter.IsLittleEndian) - throw new NotImplementedException(); foreach (var sectionHeader in sectionsHeaders) { WriteSectionHeader(s, sectionHeader); @@ -192,16 +190,38 @@ private static void WriteSectionHeaders(Stream s, ImmutableArray(Stream s, T structure) where T : unmanaged { - // FIXME: fixup endianness - if (!BitConverter.IsLittleEndian) - throw new NotImplementedException(); unsafe { byte* p = (byte*)&structure; @@ -212,9 +232,6 @@ private static void WriteStructure(Stream s, T structure) private static void WriteStructure(Stream s, T structure) where T : unmanaged { - // FIXME: fixup endianness - if (!BitConverter.IsLittleEndian) - throw new NotImplementedException(); int size = Marshal.SizeOf(); byte[] buffer = new byte[size]; IntPtr ptr = IntPtr.Zero; diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs index 4f42f82798664..ac4f9d86095a9 100644 --- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs +++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs @@ -6,7 +6,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; - +using System.Buffers.Binary; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; @@ -63,14 +63,20 @@ private unsafe bool ReadHeader() { return false; } - if (!BitConverter.IsLittleEndian) - { - throw new NotImplementedException("TODO: implement big endian support"); - } fixed (byte* p = buffer) { header = *(WebcilHeader*)p; } + if (!BitConverter.IsLittleEndian) + { + header.version_major = BinaryPrimitives.ReverseEndianness(header.version_major); + header.version_minor = BinaryPrimitives.ReverseEndianness(header.version_minor); + header.coff_sections = BinaryPrimitives.ReverseEndianness(header.coff_sections); + header.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_rva); + header.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_size); + header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_rva); + header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_size); + } if (header.id[0] != 'W' || header.id[1] != 'b' || header.id[2] != 'I' || header.id[3] != 'L' || header.version_major != Internal.Constants.WC_VERSION_MAJOR @@ -346,6 +352,7 @@ private long TranslateRVA(uint rva) private unsafe ImmutableArray ReadSections() { + WebcilSectionHeader secheader; var sections = ImmutableArray.CreateBuilder(_header.coff_sections); var buffer = new byte[Marshal.SizeOf()]; _stream.Seek(SectionDirectoryOffset + _webcilInWasmOffset, SeekOrigin.Begin); @@ -357,8 +364,24 @@ private unsafe ImmutableArray ReadSections() } fixed (byte* p = buffer) { - // FIXME endianness - sections.Add(*(WebcilSectionHeader*)p); + secheader = (*(WebcilSectionHeader*)p); + } + if (!BitConverter.IsLittleEndian) + { + sections.Add + ( + new WebcilSectionHeader + ( + virtualSize: BinaryPrimitives.ReverseEndianness(secheader.VirtualSize), + virtualAddress: BinaryPrimitives.ReverseEndianness(secheader.VirtualAddress), + sizeOfRawData: BinaryPrimitives.ReverseEndianness(secheader.SizeOfRawData), + pointerToRawData: BinaryPrimitives.ReverseEndianness(secheader.PointerToRawData) + ) + ); + } + else + { + sections.Add(secheader); } } return sections.MoveToImmutable(); From 0c78184347335db183a38cf6bd26e2fe69160931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Thu, 21 Sep 2023 14:31:12 -0400 Subject: [PATCH 2/3] Fix infinite recursion --- .../WebcilConverter.cs | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs index 7b882c42d579e..fc95eded5bc33 100644 --- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs +++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs @@ -177,6 +177,16 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi private static void WriteHeader(Stream s, WebcilHeader header) { + if (!BitConverter.IsLittleEndian) + { + webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major); + webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor); + webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections); + webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva); + webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size); + webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva); + webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size); + } WriteStructure(s, header); } @@ -203,21 +213,6 @@ private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHead WriteStructure(s, sectionHeader); } - private static void WriteStructure(Stream s, WebcilHeader webcilHeader) - { - if (!BitConverter.IsLittleEndian) - { - webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major); - webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor); - webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections); - webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva); - webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size); - webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva); - webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size); - } - WriteStructure(s, webcilHeader); - } - #if NETCOREAPP2_1_OR_GREATER private static void WriteStructure(Stream s, T structure) where T : unmanaged From cecf4f09f0c52340c753811098f0f2d9593049aa Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Thu, 21 Sep 2023 14:36:20 -0400 Subject: [PATCH 3/3] rename var --- src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs index fc95eded5bc33..13c34bde4b8ea 100644 --- a/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs +++ b/src/runtime/src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs @@ -175,7 +175,7 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi SectionStart: firstWCSection); } - private static void WriteHeader(Stream s, WebcilHeader header) + private static void WriteHeader(Stream s, WebcilHeader webcilHeader) { if (!BitConverter.IsLittleEndian) { @@ -187,7 +187,7 @@ private static void WriteHeader(Stream s, WebcilHeader header) webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva); webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size); } - WriteStructure(s, header); + WriteStructure(s, webcilHeader); } private static void WriteSectionHeaders(Stream s, ImmutableArray sectionsHeaders)