From ac106e87e1224bc81f28d82f1f1507dfd65ad975 Mon Sep 17 00:00:00 2001 From: Anton Lapounov Date: Tue, 22 Jun 2021 15:45:36 -0700 Subject: [PATCH] Set DLL flag on R2R binaries (#54533) This is required for R2R relocations to be processed by the OS loader on Windows 7. --- .../CodeGen/ReadyToRunObjectWriter.cs | 8 +--- .../ObjectWriter/R2RPEBuilder.cs | 48 +++++-------------- 2 files changed, 13 insertions(+), 43 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index e54207ff00fb1..74da51246b620 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -198,11 +198,7 @@ public void EmitPortableExecutable() if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode && _componentModule == null) { - headerBuilder = PEHeaderProvider.Create( - imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll, - dllCharacteristics: default(DllCharacteristics), - Subsystem.Unknown, - _nodeFactory.Target); + headerBuilder = PEHeaderProvider.Create(Subsystem.Unknown, _nodeFactory.Target); peIdProvider = new Func, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSourceHash(content))); timeDateStamp = null; r2rHeaderExportSymbol = _nodeFactory.Header; @@ -210,7 +206,7 @@ public void EmitPortableExecutable() else { PEReader inputPeReader = (_componentModule != null ? _componentModule.PEReader : _nodeFactory.CompilationModuleGroup.CompilationModuleSet.First().PEReader); - headerBuilder = PEHeaderProvider.Copy(inputPeReader.PEHeaders, _nodeFactory.Target); + headerBuilder = PEHeaderProvider.Create(inputPeReader.PEHeaders.PEHeader.Subsystem, _nodeFactory.Target); timeDateStamp = inputPeReader.PEHeaders.CoffHeader.TimeDateStamp; r2rHeaderExportSymbol = null; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs index 3f6764b0e804b..c7212368ace07 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs @@ -489,7 +489,7 @@ private void SetPEHeaderTimeStamp(Stream outputStream, int timeDateStamp) DosHeaderSize + PESignatureSize + sizeof(short) + // Machine - sizeof(short); //NumberOfSections + sizeof(short); // NumberOfSections outputStream.Seek(seekSize, SeekOrigin.Begin); outputStream.Write(patchedTimestamp, 0, patchedTimestamp.Length); @@ -664,52 +664,28 @@ protected override BlobBuilder SerializeSection(string name, SectionLocation loc } /// - /// Simple helper for filling in PE header information by either copying over - /// data from a pre-existing input PE header (used for single-assembly R2R files) - /// or by explicitly specifying the image characteristics (for composite R2R). + /// Simple helper for filling in PE header information. /// static class PEHeaderProvider { - /// - /// Copy PE headers into a PEHeaderBuilder used by PEBuilder. - /// - /// Headers to copy - /// Target architecture to set in the header - public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target) - { - return Create( - peHeaders.CoffHeader.Characteristics, - peHeaders.PEHeader.DllCharacteristics, - peHeaders.PEHeader.Subsystem, - target); - } - /// /// Fill in PE header information into a PEHeaderBuilder used by PEBuilder. /// - /// Relocs are not present in the PE executable - /// Extra DLL characteristics to apply /// Targeting subsystem /// Target architecture to set in the header - public static PEHeaderBuilder Create(Characteristics imageCharacteristics, DllCharacteristics dllCharacteristics, Subsystem subsystem, TargetDetails target) + public static PEHeaderBuilder Create(Subsystem subsystem, TargetDetails target) { bool is64BitTarget = target.PointerSize == sizeof(long); - imageCharacteristics &= ~(Characteristics.Bit32Machine | Characteristics.LargeAddressAware); - imageCharacteristics |= (is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine); + Characteristics imageCharacteristics = Characteristics.ExecutableImage | Characteristics.Dll; + imageCharacteristics |= is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine; - ulong imageBase = PE32HeaderConstants.ImageBase; - if (target.IsWindows && is64BitTarget && (imageBase <= uint.MaxValue)) - { - // Base addresses below 4 GiB are reserved for WoW on x64 and disallowed on ARM64. - // If the input assembly was compiled for anycpu, its base address is 32-bit and we need to fix it. - imageBase = (imageCharacteristics & Characteristics.Dll) != 0 ? PE64HeaderConstants.DllImageBase : PE64HeaderConstants.ExeImageBase; - } + ulong imageBase = is64BitTarget ? PE64HeaderConstants.DllImageBase : PE32HeaderConstants.ImageBase; int fileAlignment = 0x200; if (!target.IsWindows && !is64BitTarget) { - // To minimize wasted VA space on 32 bit systems align file to page bounaries (presumed to be 4K). + // To minimize wasted VA space on 32-bit systems, align file to page boundaries (presumed to be 4K) fileAlignment = 0x1000; } @@ -721,13 +697,11 @@ public static PEHeaderBuilder Create(Characteristics imageCharacteristics, DllCh sectionAlignment = fileAlignment; } - dllCharacteristics &= DllCharacteristics.AppContainer; - - // In Crossgen1, this is under a debug-specific condition 'if (0 == CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NoASLRForNgen))' - dllCharacteristics |= DllCharacteristics.DynamicBase; - // Without NxCompatible the PE executable cannot execute on Windows ARM64 - dllCharacteristics |= DllCharacteristics.NxCompatible | DllCharacteristics.TerminalServerAware; + DllCharacteristics dllCharacteristics = + DllCharacteristics.DynamicBase | + DllCharacteristics.NxCompatible | + DllCharacteristics.TerminalServerAware; if (is64BitTarget) {