Skip to content

Commit b82b1d9

Browse files
[wasm] Endian fix for Webcil (#92274)
* [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. --------- Co-authored-by: Aleksey Kliger <alklig@microsoft.com>
1 parent 913231a commit b82b1d9

File tree

3 files changed

+54
-18
lines changed

3 files changed

+54
-18
lines changed

src/tasks/Microsoft.NET.WebAssembly.Webcil/Microsoft.NET.WebAssembly.Webcil.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
<ItemGroup>
1818
<!-- we need to keep the version of System.Reflection.Metadata in sync with dotnet/msbuild and dotnet/sdk -->
19+
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
1920
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
2021
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
2122
</ItemGroup>

src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilConverter.cs

+23-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Buffers.Binary;
56
using System.IO;
67
using System.Collections.Immutable;
78
using System.Reflection.PortableExecutable;
@@ -174,16 +175,23 @@ public unsafe void GatherInfo(PEReader peReader, out WCFileInfo wcInfo, out PEFi
174175
SectionStart: firstWCSection);
175176
}
176177

177-
private static void WriteHeader(Stream s, WebcilHeader header)
178+
private static void WriteHeader(Stream s, WebcilHeader webcilHeader)
178179
{
179-
WriteStructure(s, header);
180+
if (!BitConverter.IsLittleEndian)
181+
{
182+
webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
183+
webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
184+
webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
185+
webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
186+
webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
187+
webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
188+
webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
189+
}
190+
WriteStructure(s, webcilHeader);
180191
}
181192

182193
private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHeader> sectionsHeaders)
183194
{
184-
// FIXME: fixup endianness
185-
if (!BitConverter.IsLittleEndian)
186-
throw new NotImplementedException();
187195
foreach (var sectionHeader in sectionsHeaders)
188196
{
189197
WriteSectionHeader(s, sectionHeader);
@@ -192,16 +200,23 @@ private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHe
192200

193201
private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHeader)
194202
{
203+
if (!BitConverter.IsLittleEndian)
204+
{
205+
sectionHeader = new WebcilSectionHeader
206+
(
207+
virtualSize: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualSize),
208+
virtualAddress: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualAddress),
209+
sizeOfRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.SizeOfRawData),
210+
pointerToRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.PointerToRawData)
211+
);
212+
}
195213
WriteStructure(s, sectionHeader);
196214
}
197215

198216
#if NETCOREAPP2_1_OR_GREATER
199217
private static void WriteStructure<T>(Stream s, T structure)
200218
where T : unmanaged
201219
{
202-
// FIXME: fixup endianness
203-
if (!BitConverter.IsLittleEndian)
204-
throw new NotImplementedException();
205220
unsafe
206221
{
207222
byte* p = (byte*)&structure;
@@ -212,9 +227,6 @@ private static void WriteStructure<T>(Stream s, T structure)
212227
private static void WriteStructure<T>(Stream s, T structure)
213228
where T : unmanaged
214229
{
215-
// FIXME: fixup endianness
216-
if (!BitConverter.IsLittleEndian)
217-
throw new NotImplementedException();
218230
int size = Marshal.SizeOf<T>();
219231
byte[] buffer = new byte[size];
220232
IntPtr ptr = IntPtr.Zero;

src/tasks/Microsoft.NET.WebAssembly.Webcil/WebcilReader.cs

+30-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.IO;
77
using System.Reflection;
88
using System.Runtime.InteropServices;
9-
9+
using System.Buffers.Binary;
1010
using System.Reflection.Metadata;
1111
using System.Reflection.PortableExecutable;
1212

@@ -63,14 +63,20 @@ private unsafe bool ReadHeader()
6363
{
6464
return false;
6565
}
66-
if (!BitConverter.IsLittleEndian)
67-
{
68-
throw new NotImplementedException("TODO: implement big endian support");
69-
}
7066
fixed (byte* p = buffer)
7167
{
7268
header = *(WebcilHeader*)p;
7369
}
70+
if (!BitConverter.IsLittleEndian)
71+
{
72+
header.version_major = BinaryPrimitives.ReverseEndianness(header.version_major);
73+
header.version_minor = BinaryPrimitives.ReverseEndianness(header.version_minor);
74+
header.coff_sections = BinaryPrimitives.ReverseEndianness(header.coff_sections);
75+
header.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_rva);
76+
header.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(header.pe_cli_header_size);
77+
header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_rva);
78+
header.pe_debug_rva = BinaryPrimitives.ReverseEndianness(header.pe_debug_size);
79+
}
7480
if (header.id[0] != 'W' || header.id[1] != 'b'
7581
|| header.id[2] != 'I' || header.id[3] != 'L'
7682
|| header.version_major != Internal.Constants.WC_VERSION_MAJOR
@@ -346,6 +352,7 @@ private long TranslateRVA(uint rva)
346352

347353
private unsafe ImmutableArray<WebcilSectionHeader> ReadSections()
348354
{
355+
WebcilSectionHeader secheader;
349356
var sections = ImmutableArray.CreateBuilder<WebcilSectionHeader>(_header.coff_sections);
350357
var buffer = new byte[Marshal.SizeOf<WebcilSectionHeader>()];
351358
_stream.Seek(SectionDirectoryOffset + _webcilInWasmOffset, SeekOrigin.Begin);
@@ -357,8 +364,24 @@ private unsafe ImmutableArray<WebcilSectionHeader> ReadSections()
357364
}
358365
fixed (byte* p = buffer)
359366
{
360-
// FIXME endianness
361-
sections.Add(*(WebcilSectionHeader*)p);
367+
secheader = (*(WebcilSectionHeader*)p);
368+
}
369+
if (!BitConverter.IsLittleEndian)
370+
{
371+
sections.Add
372+
(
373+
new WebcilSectionHeader
374+
(
375+
virtualSize: BinaryPrimitives.ReverseEndianness(secheader.VirtualSize),
376+
virtualAddress: BinaryPrimitives.ReverseEndianness(secheader.VirtualAddress),
377+
sizeOfRawData: BinaryPrimitives.ReverseEndianness(secheader.SizeOfRawData),
378+
pointerToRawData: BinaryPrimitives.ReverseEndianness(secheader.PointerToRawData)
379+
)
380+
);
381+
}
382+
else
383+
{
384+
sections.Add(secheader);
362385
}
363386
}
364387
return sections.MoveToImmutable();

0 commit comments

Comments
 (0)