Add backported patches for additional s390x issues

Related: RHEL-4074
This commit is contained in:
Omair Majid 2023-09-27 11:09:44 -04:00
parent 63573e2cc8
commit 9db4f80a3f
4 changed files with 594 additions and 1 deletions

View File

@ -54,7 +54,7 @@
Name: dotnet%{dotnetver}
Version: %{sdk_rpm_version}
Release: 0.2%{?dist}
Release: 0.3%{?dist}
Summary: .NET Runtime and SDK
License: 0BSD AND Apache-2.0 AND (Apache-2.0 WITH LLVM-exception) AND APSL-2.0 AND BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND BSL-1.0 AND bzip2-1.0.6 AND CC0-1.0 AND CC-BY-3.0 AND CC-BY-4.0 AND CC-PDDC AND CNRI-Python AND EPL-1.0 AND GPL-2.0-only AND (GPL-2.0-only WITH GCC-exception-2.0) AND GPL-2.0-or-later AND GPL-3.0-only AND ICU AND ISC AND LGPL-2.1-only AND LGPL-2.1-or-later AND LicenseRef-Fedora-Public-Domain AND LicenseRef-ISO-8879 AND MIT AND MIT-Wu AND MS-PL AND MS-RL AND NCSA AND OFL-1.1 AND OpenSSL AND Unicode-DFS-2015 AND Unicode-DFS-2016 AND W3C-19980720 AND X11 AND Zlib
@ -96,6 +96,13 @@ Patch3: fix-mono-typeloadexception.patch
Patch4: runtime-91008-mono-var-opcode-OP_REGOFFSET.patch
# https://github.com/dotnet/runtime/pull/91865
Patch5: runtime-91865-arm64-page-size.patch
# https://github.com/dotnet/runtime/pull/92274
Patch6: runtime-92274-webcil-s390x.patch
# https://github.com/dotnet/runtime/pull/92441
Patch7: runtime-92441-s390x-host-le.patch
# https://github.com/dotnet/sdk/pull/35600
Patch8: sdk-35600-skip-windows-gui.patch
%if 0%{?fedora} || 0%{?rhel} >= 8
ExclusiveArch: aarch64 ppc64le s390x x86_64
@ -664,6 +671,10 @@ export COMPlus_LTTng=0
%changelog
* Wed Sep 27 2023 Omair Majid <omajid@redhat.com> - 8.0.100~rc.1-0.3
- Add backported patches for additional s390x issues
- Related: RHEL-4074
* Mon Sep 18 2023 Omair Majid <omajid@redhat.com> - 8.0.100~rc.1-0.2
- Add patches to fix mono and arm64 issues
- Include libmono-*.a files in the SDK

View File

@ -0,0 +1,260 @@
From 72f310a6c3dccbabf9edc29677b51ed78c87cc67 Mon Sep 17 00:00:00 2001
From: Sanjam Panda <sanjam.panda@ibm.com>
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 @@
<ItemGroup>
<!-- we need to keep the version of System.Reflection.Metadata in sync with dotnet/msbuild and dotnet/sdk -->
+ <PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
</ItemGroup>
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<WebcilSectionHeader> 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<WebcilSectionHe
private static void WriteSectionHeader(Stream s, WebcilSectionHeader sectionHeader)
{
+ if (!BitConverter.IsLittleEndian)
+ {
+ sectionHeader = new WebcilSectionHeader
+ (
+ virtualSize: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualSize),
+ virtualAddress: BinaryPrimitives.ReverseEndianness(sectionHeader.VirtualAddress),
+ sizeOfRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.SizeOfRawData),
+ pointerToRawData: BinaryPrimitives.ReverseEndianness(sectionHeader.PointerToRawData)
+ );
+ }
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<T>(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<T>(Stream s, T structure)
private static void WriteStructure<T>(Stream s, T structure)
where T : unmanaged
{
- // FIXME: fixup endianness
- if (!BitConverter.IsLittleEndian)
- throw new NotImplementedException();
int size = Marshal.SizeOf<T>();
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<WebcilSectionHeader> ReadSections()
{
+ WebcilSectionHeader secheader;
var sections = ImmutableArray.CreateBuilder<WebcilSectionHeader>(_header.coff_sections);
var buffer = new byte[Marshal.SizeOf<WebcilSectionHeader>()];
_stream.Seek(SectionDirectoryOffset + _webcilInWasmOffset, SeekOrigin.Begin);
@@ -357,8 +364,24 @@ private unsafe ImmutableArray<WebcilSectionHeader> 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?= <alklig@microsoft.com>
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<T>(Stream s, T structure)
where T : unmanaged
From cecf4f09f0c52340c753811098f0f2d9593049aa Mon Sep 17 00:00:00 2001
From: Aleksey Kliger <alklig@microsoft.com>
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<WebcilSectionHeader> sectionsHeaders)

View File

@ -0,0 +1,290 @@
From 0566e7dd9a7a8e5dec119d0ba715623beeba4c90 Mon Sep 17 00:00:00 2001
From: Elinor Fung <elfung@microsoft.com>
Date: Wed, 20 Sep 2023 17:27:40 -0700
Subject: [PATCH 1/2] Make HostModel PEUtils always read/write little endian
---
.../AppHost/PEUtils.cs | 26 ++++++++++++-------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs b/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs
index 0d0b33ed55569..e6142aba26e3e 100644
--- a/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs
+++ b/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+using System.Buffers.Binary;
using System.IO;
using System.IO.MemoryMappedFiles;
@@ -24,7 +26,9 @@ internal static unsafe bool IsPEImage(MemoryMappedViewAccessor accessor)
// https://en.wikipedia.org/wiki/Portable_Executable
// Validate that we're looking at Windows PE file
- if (((ushort*)bytes)[0] != PEOffsets.DosImageSignature
+ ReadOnlySpan<byte> signatureBytes = new(bytes, sizeof(ushort));
+ ushort signature = BinaryPrimitives.ReadUInt16LittleEndian(signatureBytes);
+ if (signature != PEOffsets.DosImageSignature
|| accessor.Capacity < PEOffsets.DosStub.PESignatureOffset + sizeof(uint))
{
return false;
@@ -68,24 +72,26 @@ internal static unsafe void SetWindowsGraphicalUserInterfaceBit(MemoryMappedView
byte* bytes = pointer + accessor.PointerOffset;
// https://en.wikipedia.org/wiki/Portable_Executable
- uint peHeaderOffset = ((uint*)(bytes + PEOffsets.DosStub.PESignatureOffset))[0];
+ ReadOnlySpan<byte> peHeaderOffsetBytes = new(bytes + PEOffsets.DosStub.PESignatureOffset, sizeof(uint));
+ uint peHeaderOffset = BinaryPrimitives.ReadUInt32LittleEndian(peHeaderOffsetBytes);
if (accessor.Capacity < peHeaderOffset + PEOffsets.PEHeader.Subsystem + sizeof(ushort))
{
throw new AppHostNotPEFileException("Subsystem offset out of file range.");
}
- ushort* subsystem = ((ushort*)(bytes + peHeaderOffset + PEOffsets.PEHeader.Subsystem));
+ Span<byte> subsystemBytes = new(bytes + peHeaderOffset + PEOffsets.PEHeader.Subsystem, sizeof(ushort));
+ ushort subsystem = BinaryPrimitives.ReadUInt16LittleEndian(subsystemBytes);
// https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format#windows-subsystem
// The subsystem of the prebuilt apphost should be set to CUI
- if (subsystem[0] != (ushort)PEOffsets.Subsystem.WindowsCui)
+ if (subsystem != (ushort)PEOffsets.Subsystem.WindowsCui)
{
- throw new AppHostNotCUIException(subsystem[0]);
+ throw new AppHostNotCUIException(subsystem);
}
// Set the subsystem to GUI
- subsystem[0] = (ushort)PEOffsets.Subsystem.WindowsGui;
+ BinaryPrimitives.WriteUInt16LittleEndian(subsystemBytes, (ushort)PEOffsets.Subsystem.WindowsGui);
}
finally
{
@@ -121,16 +127,16 @@ internal static unsafe ushort GetWindowsGraphicalUserInterfaceBit(MemoryMappedVi
byte* bytes = pointer + accessor.PointerOffset;
// https://en.wikipedia.org/wiki/Portable_Executable
- uint peHeaderOffset = ((uint*)(bytes + PEOffsets.DosStub.PESignatureOffset))[0];
+ ReadOnlySpan<byte> peHeaderOffsetBytes = new(bytes + PEOffsets.DosStub.PESignatureOffset, sizeof(uint));
+ uint peHeaderOffset = BinaryPrimitives.ReadUInt32LittleEndian(peHeaderOffsetBytes);
if (accessor.Capacity < peHeaderOffset + PEOffsets.PEHeader.Subsystem + sizeof(ushort))
{
throw new AppHostNotPEFileException("Subsystem offset out of file range.");
}
- ushort* subsystem = ((ushort*)(bytes + peHeaderOffset + PEOffsets.PEHeader.Subsystem));
-
- return subsystem[0];
+ ReadOnlySpan<byte> subsystemBytes = new(bytes + peHeaderOffset + PEOffsets.PEHeader.Subsystem, sizeof(ushort));
+ return BinaryPrimitives.ReadUInt16LittleEndian(subsystemBytes);
}
finally
{
From d39f18ecd6671748cc6baf57f141f94668cb5f9e Mon Sep 17 00:00:00 2001
From: Elinor Fung <elfung@microsoft.com>
Date: Thu, 21 Sep 2023 10:45:36 -0700
Subject: [PATCH 2/2] PR feeback - helper methods
---
.../AppHost/PEUtils.cs | 123 ++++++------------
.../AppHostUpdateTests.cs | 6 +-
2 files changed, 42 insertions(+), 87 deletions(-)
diff --git a/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs b/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs
index e6142aba26e3e..1bfc80fcfca49 100644
--- a/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs
+++ b/src/runtime/src/installer/managed/Microsoft.NET.HostModel/AppHost/PEUtils.cs
@@ -5,6 +5,7 @@
using System.Buffers.Binary;
using System.IO;
using System.IO.MemoryMappedFiles;
+using System.Reflection.PortableExecutable;
namespace Microsoft.NET.HostModel.AppHost
{
@@ -17,31 +18,13 @@ public static class PEUtils
/// <returns>true if the accessor represents a PE image, false otherwise.</returns>
internal static unsafe bool IsPEImage(MemoryMappedViewAccessor accessor)
{
- byte* pointer = null;
+ if (accessor.Capacity < PEOffsets.DosStub.PESignatureOffset + sizeof(uint))
+ return false;
- try
- {
- accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
- byte* bytes = pointer + accessor.PointerOffset;
-
- // https://en.wikipedia.org/wiki/Portable_Executable
- // Validate that we're looking at Windows PE file
- ReadOnlySpan<byte> signatureBytes = new(bytes, sizeof(ushort));
- ushort signature = BinaryPrimitives.ReadUInt16LittleEndian(signatureBytes);
- if (signature != PEOffsets.DosImageSignature
- || accessor.Capacity < PEOffsets.DosStub.PESignatureOffset + sizeof(uint))
- {
- return false;
- }
- return true;
- }
- finally
- {
- if (pointer != null)
- {
- accessor.SafeMemoryMappedViewHandle.ReleasePointer();
- }
- }
+ // https://en.wikipedia.org/wiki/Portable_Executable
+ // Validate that we're looking at Windows PE file
+ ushort signature = AsLittleEndian(accessor.ReadUInt16(0));
+ return signature == PEOffsets.DosImageSignature;
}
public static bool IsPEImage(string filePath)
@@ -64,42 +47,15 @@ public static bool IsPEImage(string filePath)
/// <param name="accessor">The memory accessor which has the apphost file opened.</param>
internal static unsafe void SetWindowsGraphicalUserInterfaceBit(MemoryMappedViewAccessor accessor)
{
- byte* pointer = null;
-
- try
- {
- accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
- byte* bytes = pointer + accessor.PointerOffset;
-
- // https://en.wikipedia.org/wiki/Portable_Executable
- ReadOnlySpan<byte> peHeaderOffsetBytes = new(bytes + PEOffsets.DosStub.PESignatureOffset, sizeof(uint));
- uint peHeaderOffset = BinaryPrimitives.ReadUInt32LittleEndian(peHeaderOffsetBytes);
-
- if (accessor.Capacity < peHeaderOffset + PEOffsets.PEHeader.Subsystem + sizeof(ushort))
- {
- throw new AppHostNotPEFileException("Subsystem offset out of file range.");
- }
-
- Span<byte> subsystemBytes = new(bytes + peHeaderOffset + PEOffsets.PEHeader.Subsystem, sizeof(ushort));
- ushort subsystem = BinaryPrimitives.ReadUInt16LittleEndian(subsystemBytes);
-
- // https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format#windows-subsystem
- // The subsystem of the prebuilt apphost should be set to CUI
- if (subsystem != (ushort)PEOffsets.Subsystem.WindowsCui)
- {
- throw new AppHostNotCUIException(subsystem);
- }
-
- // Set the subsystem to GUI
- BinaryPrimitives.WriteUInt16LittleEndian(subsystemBytes, (ushort)PEOffsets.Subsystem.WindowsGui);
- }
- finally
- {
- if (pointer != null)
- {
- accessor.SafeMemoryMappedViewHandle.ReleasePointer();
- }
- }
+ // https://learn.microsoft.com/windows/win32/debug/pe-format#windows-subsystem
+ // The subsystem of the prebuilt apphost should be set to CUI
+ uint peHeaderOffset;
+ ushort subsystem = GetWindowsSubsystem(accessor, out peHeaderOffset);
+ if (subsystem != (ushort)Subsystem.WindowsCui)
+ throw new AppHostNotCUIException(subsystem);
+
+ // Set the subsystem to GUI
+ accessor.Write(peHeaderOffset + PEOffsets.PEHeader.Subsystem, AsLittleEndian((ushort)Subsystem.WindowsGui));
}
public static unsafe void SetWindowsGraphicalUserInterfaceBit(string filePath)
@@ -119,32 +75,7 @@ public static unsafe void SetWindowsGraphicalUserInterfaceBit(string filePath)
/// <param name="accessor">The memory accessor which has the apphost file opened.</param>
internal static unsafe ushort GetWindowsGraphicalUserInterfaceBit(MemoryMappedViewAccessor accessor)
{
- byte* pointer = null;
-
- try
- {
- accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
- byte* bytes = pointer + accessor.PointerOffset;
-
- // https://en.wikipedia.org/wiki/Portable_Executable
- ReadOnlySpan<byte> peHeaderOffsetBytes = new(bytes + PEOffsets.DosStub.PESignatureOffset, sizeof(uint));
- uint peHeaderOffset = BinaryPrimitives.ReadUInt32LittleEndian(peHeaderOffsetBytes);
-
- if (accessor.Capacity < peHeaderOffset + PEOffsets.PEHeader.Subsystem + sizeof(ushort))
- {
- throw new AppHostNotPEFileException("Subsystem offset out of file range.");
- }
-
- ReadOnlySpan<byte> subsystemBytes = new(bytes + peHeaderOffset + PEOffsets.PEHeader.Subsystem, sizeof(ushort));
- return BinaryPrimitives.ReadUInt16LittleEndian(subsystemBytes);
- }
- finally
- {
- if (pointer != null)
- {
- accessor.SafeMemoryMappedViewHandle.ReleasePointer();
- }
- }
+ return GetWindowsSubsystem(accessor, out _);
}
public static unsafe ushort GetWindowsGraphicalUserInterfaceBit(string filePath)
@@ -157,5 +88,25 @@ public static unsafe ushort GetWindowsGraphicalUserInterfaceBit(string filePath)
}
}
}
+
+ private static ushort GetWindowsSubsystem(MemoryMappedViewAccessor accessor, out uint peHeaderOffset)
+ {
+ // https://en.wikipedia.org/wiki/Portable_Executable
+ if (accessor.Capacity < PEOffsets.DosStub.PESignatureOffset + sizeof(uint))
+ throw new AppHostNotPEFileException("PESignature offset out of file range.");
+
+ peHeaderOffset = AsLittleEndian(accessor.ReadUInt32(PEOffsets.DosStub.PESignatureOffset));
+ if (accessor.Capacity < peHeaderOffset + PEOffsets.PEHeader.Subsystem + sizeof(ushort))
+ throw new AppHostNotPEFileException("Subsystem offset out of file range.");
+
+ // https://learn.microsoft.com/windows/win32/debug/pe-format#windows-subsystem
+ return AsLittleEndian(accessor.ReadUInt16(peHeaderOffset + PEOffsets.PEHeader.Subsystem));
+ }
+
+ private static ushort AsLittleEndian(ushort value)
+ => BitConverter.IsLittleEndian ? value : BinaryPrimitives.ReverseEndianness(value);
+
+ private static uint AsLittleEndian(uint value)
+ => BitConverter.IsLittleEndian ? value : BinaryPrimitives.ReverseEndianness(value);
}
}
diff --git a/src/runtime/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUpdateTests.cs b/src/runtime/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUpdateTests.cs
index 232410be8f259..b4d038b99b5ce 100644
--- a/src/runtime/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUpdateTests.cs
+++ b/src/runtime/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUpdateTests.cs
@@ -11,6 +11,7 @@
using Microsoft.NET.HostModel.AppHost;
using Microsoft.DotNet.CoreSetup.Test;
using System.Diagnostics;
+using System.Reflection.PortableExecutable;
namespace Microsoft.NET.HostModel.Tests
{
@@ -111,7 +112,9 @@ public void ItCanSetWindowsGUISubsystem()
BitConverter
.ToUInt16(File.ReadAllBytes(destinationFilePath), SubsystemOffset)
.Should()
- .Be(2);
+ .Be((ushort)Subsystem.WindowsGui);
+
+ Assert.Equal((ushort)Subsystem.WindowsGui, PEUtils.GetWindowsGraphicalUserInterfaceBit(destinationFilePath));
}
}
@@ -153,6 +156,7 @@ public void ItFailsToSetGUISubsystemWithWrongDefault()
string destinationFilePath = Path.Combine(testDirectory.Path, "DestinationAppHost.exe.mock");
string appBinaryFilePath = "Test/App/Binary/Path.dll";
+ Assert.Equal(42, PEUtils.GetWindowsGraphicalUserInterfaceBit(sourceAppHostMock));
Assert.Throws<AppHostNotCUIException>(() =>
HostWriter.CreateAppHost(
sourceAppHostMock,

View File

@ -0,0 +1,32 @@
From eaa9d8ebefb59cb289e147223b242d77e69f0861 Mon Sep 17 00:00:00 2001
From: Elinor Fung <elfung@microsoft.com>
Date: Wed, 20 Sep 2023 15:55:32 -0700
Subject: [PATCH] Skip getting Windows GUI bit on non-Windows in
AppHostShellShimMaker
---
src/Cli/dotnet/ShellShim/AppHostShimMaker.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/sdk/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs b/src/sdk/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs
index eb9a1332299..7240150e06d 100644
--- a/src/sdk/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs
+++ b/src/sdk/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs
@@ -40,14 +40,14 @@ public void CreateApphostShellShim(FilePath entryPoint, FilePath shimPath)
string entryPointFullPath = Path.GetFullPath(entryPoint.Value);
var appBinaryFilePath = Path.GetRelativePath(Path.GetDirectoryName(appHostDestinationFilePath), entryPointFullPath);
-
if (ResourceUpdater.IsSupportedOS())
{
- var windowsGraphicalUserInterfaceBit = PEUtils.GetWindowsGraphicalUserInterfaceBit(entryPointFullPath);
+ bool windowsGraphicalUserInterface = OperatingSystem.IsWindows()
+ && PEUtils.GetWindowsGraphicalUserInterfaceBit(entryPointFullPath) == WindowsGUISubsystem;
HostWriter.CreateAppHost(appHostSourceFilePath: appHostSourcePath,
appHostDestinationFilePath: appHostDestinationFilePath,
appBinaryFilePath: appBinaryFilePath,
- windowsGraphicalUserInterface: (windowsGraphicalUserInterfaceBit == WindowsGUISubsystem) && OperatingSystem.IsWindows(),
+ windowsGraphicalUserInterface: windowsGraphicalUserInterface,
assemblyToCopyResourcesFrom: entryPointFullPath,
enableMacOSCodeSign: OperatingSystem.IsMacOS());
}