Skip to content

Commit 72f310a

Browse files
committed
[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.
1 parent 963954a commit 72f310a

File tree

3 files changed

+57
-16
lines changed

3 files changed

+57
-16
lines changed

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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 26 additions & 9 deletions
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;
@@ -181,9 +182,6 @@ private static void WriteHeader(Stream s, WebcilHeader header)
181182

182183
private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHeader> sectionsHeaders)
183184
{
184-
// FIXME: fixup endianness
185-
if (!BitConverter.IsLittleEndian)
186-
throw new NotImplementedException();
187185
foreach (var sectionHeader in sectionsHeaders)
188186
{
189187
WriteSectionHeader(s, sectionHeader);
@@ -192,16 +190,38 @@ private static void WriteSectionHeaders(Stream s, ImmutableArray<WebcilSectionHe
192190

193191
private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHeader)
194192
{
193+
if (!BitConverter.IsLittleEndian)
194+
{
195+
sectionHeader = new WebcilSectionHeader
196+
(
197+
virtualSize: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualSize),
198+
virtualAddress: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualAddress),
199+
sizeOfRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.SizeOfRawData),
200+
pointerToRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.PointerToRawData)
201+
);
202+
}
195203
WriteStructure(s, sectionHeader);
196204
}
197205

206+
private static void WriteStructure(Stream s, WebcilHeader webcilHeader)
207+
{
208+
if (!BitConverter.IsLittleEndian)
209+
{
210+
webcilHeader.version_major = BinaryPrimitives.ReverseEndianness(webcilHeader.version_major);
211+
webcilHeader.version_minor = BinaryPrimitives.ReverseEndianness(webcilHeader.version_minor);
212+
webcilHeader.coff_sections = BinaryPrimitives.ReverseEndianness(webcilHeader.coff_sections);
213+
webcilHeader.pe_cli_header_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_rva);
214+
webcilHeader.pe_cli_header_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_cli_header_size);
215+
webcilHeader.pe_debug_rva = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_rva);
216+
webcilHeader.pe_debug_size = BinaryPrimitives.ReverseEndianness(webcilHeader.pe_debug_size);
217+
}
218+
WriteStructure(s, webcilHeader);
219+
}
220+
198221
#if NETCOREAPP2_1_OR_GREATER
199222
private static void WriteStructure<T>(Stream s, T structure)
200223
where T : unmanaged
201224
{
202-
// FIXME: fixup endianness
203-
if (!BitConverter.IsLittleEndian)
204-
throw new NotImplementedException();
205225
unsafe
206226
{
207227
byte* p = (byte*)&structure;
@@ -212,9 +232,6 @@ private static void WriteStructure<T>(Stream s, T structure)
212232
private static void WriteStructure<T>(Stream s, T structure)
213233
where T : unmanaged
214234
{
215-
// FIXME: fixup endianness
216-
if (!BitConverter.IsLittleEndian)
217-
throw new NotImplementedException();
218235
int size = Marshal.SizeOf<T>();
219236
byte[] buffer = new byte[size];
220237
IntPtr ptr = IntPtr.Zero;

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

Lines changed: 30 additions & 7 deletions
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)