Skip to content

Crossplatform ResourceUpdater #89303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 79 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
ad7e0e2
add Mono.Cecil.Binary from mono repository
anatawa12 Jul 18, 2023
36e12c8
port Mono.Cecil.Binary onto netstandard2.0
anatawa12 Jul 18, 2023
379d8a8
reformat Mono.Cecil.Binary
anatawa12 Jul 18, 2023
a6d09c6
make Mono.Cecil.Binary.Image and Mono.Cecil.Binary.ImageReader public
anatawa12 Jul 18, 2023
a53eb03
rewrite ResourceUpdater.AddResource with Mono.Cecil.Binary
anatawa12 Jul 19, 2023
cf8effd
reimplement AddResourcesFromPEImage with Mono.Cecil.Binary
anatawa12 Jul 19, 2023
11e2c45
reimplement ResourceUpdater with Mono.Cecil.Binary.ImageWriter
anatawa12 Jul 19, 2023
2d5d598
fix: remove unused csproj
anatawa12 Jul 19, 2023
a06aeef
publish mono cecil binary
anatawa12 Jul 19, 2023
7778151
chore: remove unnecessary mappings
anatawa12 Jul 20, 2023
bff5f19
leave open FileStream
anatawa12 Jul 20, 2023
027cf55
update binary with our own code instead of ImageWriter
anatawa12 Jul 21, 2023
2ccadd8
remove unused files from Mono.Cecil.Binary
anatawa12 Jul 21, 2023
6022cfd
flatten Mono.Cecil.Binary
anatawa12 Jul 21, 2023
455eab7
fix
anatawa12 Jul 24, 2023
dde91d4
clear padding
anatawa12 Jul 25, 2023
a4de95c
fix ResourceWriter
anatawa12 Jul 25, 2023
df8b502
reimplement ResourceUpdater with System.Reflection.Metadata and ILCom…
anatawa12 Jul 26, 2023
832629f
make ResourceData.WriteResources working
anatawa12 Jul 26, 2023
4a7c516
remove Mono.Cecil.Binary
anatawa12 Jul 26, 2023
99d0f3d
add unit test for ResourceUpdater
anatawa12 Jul 26, 2023
8dd9c0a
fix bad image file if resource delta is small
anatawa12 Jul 26, 2023
9542736
ResourceUpdaterAddResource is WindowsOnlyFact
anatawa12 Jul 26, 2023
55631c2
Use CoreClrProjectRoot instead of long relative path
anatawa12 Jul 27, 2023
8059a5c
make ResourceUpdaterAddResource test simple
anatawa12 Jul 27, 2023
49e1130
use int instead of uint
anatawa12 Jul 27, 2023
033ad24
fix ResourceUpdaterAddResource test
anatawa12 Jul 27, 2023
08b4cd1
support adding section in ResourceUpdater
anatawa12 Jul 27, 2023
5e6f581
add more unit tests
anatawa12 Jul 27, 2023
e5fc1e6
use GetExecutingAssembly for PE with .rsrc section
anatawa12 Jul 27, 2023
5abe05d
Merge branch 'main' into crossplatform-resource-updater
anatawa12 Jul 28, 2023
efe5b1c
fix: ResourceUpdater is not disposed in HostWriter
anatawa12 Jul 28, 2023
3a60147
extract ObjectDataBuilder for HostModel to an separated file
anatawa12 Jul 28, 2023
5c2bf12
move Win32Resources for host model to Microsoft.NET.HostModel.Win32Re…
anatawa12 Aug 2, 2023
e630a0e
move files for Win32Resources
anatawa12 Aug 2, 2023
6bf8b25
improve readability with #if
anatawa12 Aug 2, 2023
42c5798
move ResourceUpdaterTests to Microsoft.NET.HostModel.AppHost.Tests
anatawa12 Aug 2, 2023
20b384e
fix duplicated code in ResourceUpdaterTests
anatawa12 Aug 2, 2023
4ae6177
fix pe32InitializedDataSizeOffset
anatawa12 Aug 2, 2023
1a64d91
rename offsets
anatawa12 Aug 2, 2023
5878ecb
move offsets constants to into Offsets class
anatawa12 Aug 2, 2023
b893113
throw InvalidOperationException if Update is already called.
anatawa12 Aug 2, 2023
dce2f4c
use RetryUtil.RetryOnIOError
anatawa12 Aug 2, 2023
3703177
addd more tests for AddResource
anatawa12 Aug 2, 2023
5241c08
add test for AddResourcesFromPEImage
anatawa12 Aug 2, 2023
75340cf
use GetAllResources in CopyResourcesFrom
anatawa12 Aug 2, 2023
0788ea5
set fileshare
anatawa12 Aug 2, 2023
1e6f4d8
use memory mapped file in ResourceUpdater
anatawa12 Aug 2, 2023
0a27042
remove outdated comment
anatawa12 Aug 2, 2023
81a05fb
DosStab -> DosStub
anatawa12 Aug 4, 2023
7aabeef
fix styling
anatawa12 Aug 4, 2023
bd3bab8
use using block instead of using var
anatawa12 Aug 4, 2023
36c8579
buffer -> accessor
anatawa12 Aug 4, 2023
ac45717
CopyRes(Name|Type) -> SelectRes(Name|Type)
anatawa12 Aug 4, 2023
d6d390a
use Assert.Fail instead of InvalidOperationException
anatawa12 Aug 4, 2023
30b3943
use CreateTestPEFileWithoutRsrc in AddResourcesFromPEImage
anatawa12 Aug 4, 2023
a9e975c
PE(32|64)(InitializedDataSize|SizeOfImage) -> (InitializedDataSize|Si…
anatawa12 Aug 4, 2023
eef78a2
add dataDirectoriesOffset and pull the updating of data directories o…
anatawa12 Aug 4, 2023
34ca149
add offsets around DataDirectory
anatawa12 Aug 4, 2023
9288922
throw exception in ThrowExceptionForInvalidUpdate
anatawa12 Aug 4, 2023
33abdc8
fix parameter names of AddResource
anatawa12 Aug 4, 2023
647b250
reorder parameters of AddResource and AddResourceInternal to match wi…
anatawa12 Aug 4, 2023
a224eda
add test ResourceUpdaterAddResourceTwoSameUShortTypeWithDifferName
anatawa12 Aug 4, 2023
d174ece
move calling ResourceUpdater and open appHostDestinationFilePath once
anatawa12 Aug 4, 2023
545965b
use single code to modify InitializedDataSize and SizeOfImage
anatawa12 Aug 4, 2023
5a1cfd0
seek to head in ResourceUpdater constructor
anatawa12 Aug 4, 2023
8a8ca68
insert blank line
anatawa12 Aug 5, 2023
b2bbd1b
Update comment
anatawa12 Aug 5, 2023
92defd3
improve test name
anatawa12 Aug 5, 2023
ab5d5e0
remove throw from ThrowExceptionForInvalidUpdate caller
anatawa12 Aug 5, 2023
30c3451
strip ResourceData constructor with PEReader from ilc/crossgen
anatawa12 Aug 5, 2023
de8455f
update doc comments in ResourceUpdater
anatawa12 Aug 5, 2023
7ec110e
add test for app with unknown language resource
anatawa12 Aug 5, 2023
ed3f32a
fix CreateAppHost failure from old SDK
anatawa12 Aug 5, 2023
6e8120b
share offsets constants of PE between PEUtils and ResourceUpdater
anatawa12 Aug 6, 2023
b829782
DosStubSignature -> DosImageSignature
anatawa12 Aug 8, 2023
fe92cc3
move AppWithUnknownLanguageResource to Microsoft.NET.HostModel.AppHos…
anatawa12 Aug 8, 2023
1470480
Merge branch 'dotnet:main' into crossplatform-resource-updater
anatawa12 Aug 8, 2023
65f23d4
Merge branch 'dotnet:main' into crossplatform-resource-updater
anatawa12 Aug 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace ILCompiler.DependencyAnalysis
{
// There is small set of ObjectDataBuilder in at src/installer/managed/Microsoft.NET.HostModel/ObjectDataBuilder.cs
// only for ResourceData.WriteResources
public struct ObjectDataBuilder
#if !READYTORUN
: Internal.Runtime.ITargetBinaryWriter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.Win32Resources
#else
namespace ILCompiler.Win32Resources
#endif
{
public unsafe partial class ResourceData
{
Expand Down Expand Up @@ -51,7 +55,7 @@ void ProcessLanguageList(object languageName, uint offsetOfLanguageListEntry, bo
if (!resourceFilter(typeName, name, (ushort)languageName))
return;
}
AddResource(typeName, name, (ushort)languageName, data);
AddResourceInternal(name, typeName, (ushort)languageName, data);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
using System;
using System.Collections.Generic;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.Win32Resources
#else
namespace ILCompiler.Win32Resources
#endif
{
public unsafe partial class ResourceData
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
using System;
using System.Collections;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.Win32Resources
#else
namespace ILCompiler.Win32Resources
#endif
{
public unsafe partial class ResourceData
{
private void AddResource(object type, object name, ushort language, byte[] data)
private void AddResourceInternal(object name, object type, ushort language, byte[] data)
{
ResType resType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
using System.Runtime.InteropServices;
using System.Reflection.Metadata;

#if !HOST_MODEL
using ILCompiler.DependencyAnalysis;
#endif

#if HOST_MODEL
namespace Microsoft.NET.HostModel.Win32Resources
#else
namespace ILCompiler.Win32Resources
#endif
{
public unsafe partial class ResourceData
{
Expand Down Expand Up @@ -81,16 +87,23 @@ public IMAGE_RESOURCE_DATA_ENTRY(ref BlobReader blobReader)
CodePage = blobReader.ReadUInt32();
Reserved = blobReader.ReadUInt32();
}

#if HOST_MODEL
public static void Write(ref ObjectDataBuilder dataBuilder, int sectionBase, int offsetFromSymbol, int sizeOfData)
#else
public static void Write(ref ObjectDataBuilder dataBuilder, ISymbolNode node, int offsetFromSymbol, int sizeOfData)
#endif
{
#if HOST_MODEL
dataBuilder.EmitInt(sectionBase + offsetFromSymbol);
#else
dataBuilder.EmitReloc(node,
#if READYTORUN
RelocType.IMAGE_REL_BASED_ADDR32NB,
#else
RelocType.IMAGE_REL_BASED_ABSOLUTE,
#endif
offsetFromSymbol);
#endif
dataBuilder.EmitInt(sizeOfData);
dataBuilder.EmitInt(1252); // CODEPAGE = DEFAULT_CODEPAGE
dataBuilder.EmitInt(0); // RESERVED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,46 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;

#if !HOST_MODEL
using ILCompiler.DependencyAnalysis;
using Internal.TypeSystem.Ecma;
#endif

#if HOST_MODEL
namespace Microsoft.NET.HostModel.Win32Resources
#else
namespace ILCompiler.Win32Resources
#endif
{
/// <summary>
/// Resource abstraction to allow examination
/// of a PE file that contains resources.
/// </summary>
public unsafe partial class ResourceData
{
#if HOST_MODEL
/// <summary>
/// Initialize a ResourceData instance from a PE file
/// </summary>
/// <param name="peFile"></param>
public ResourceData(PEReader peFile)
{
DirectoryEntry resourceDirectory = peFile.PEHeaders.PEHeader!.ResourceTableDirectory;
if (resourceDirectory.Size != 0)
{
BlobReader resourceDataBlob = peFile.GetSectionData(resourceDirectory.RelativeVirtualAddress).GetReader(0, resourceDirectory.Size);
ReadResourceData(resourceDataBlob, peFile, null);
}
}
#else
/// <summary>
/// Initialize a ResourceData instance from a PE file
/// </summary>
/// <param name="ecmaModule"></param>
public ResourceData(EcmaModule ecmaModule, Func<object, object, ushort, bool> resourceFilter = null)
public ResourceData(Internal.TypeSystem.Ecma.EcmaModule ecmaModule, Func<object, object, ushort, bool> resourceFilter = null)
{
System.Collections.Immutable.ImmutableArray<byte> ecmaData = ecmaModule.PEReader.GetEntireImage().GetContent();
PEReader peFile = ecmaModule.PEReader;
Expand All @@ -34,6 +55,7 @@ public ResourceData(EcmaModule ecmaModule, Func<object, object, ushort, bool> re
ReadResourceData(resourceDataBlob, peFile, resourceFilter);
}
}
#endif

/// <summary>
/// Find a resource in the resource data
Expand Down Expand Up @@ -67,6 +89,44 @@ public byte[] FindResource(ushort name, ushort type, ushort language)
return FindResourceInternal(name, type, language);
}

/// <summary>
/// Add or update resource
/// </summary>
public void AddResource(string name, string type, ushort language, byte[] data) => AddResourceInternal(name, type, language, data);

/// <summary>
/// Add or update resource
/// </summary>
public void AddResource(string name, ushort type, ushort language, byte[] data) => AddResourceInternal(name, type, language, data);

/// <summary>
/// Add or update resource
/// </summary>
public void AddResource(ushort name, string type, ushort language, byte[] data) => AddResourceInternal(name, type, language, data);

/// <summary>
/// Add or update resource
/// </summary>
public void AddResource(ushort name, ushort type, ushort language, byte[] data) => AddResourceInternal(name, type, language, data);

public IEnumerable<(object name, object type, ushort language, byte[] data)> GetAllResources()
{
return _resTypeHeadID.SelectMany(typeIdPair => SelectResType(typeIdPair.Key, typeIdPair.Value))
.Concat(_resTypeHeadName.SelectMany(typeNamePair => SelectResType(typeNamePair.Key, typeNamePair.Value)));

IEnumerable<(object name, object type, ushort language, byte[] data)> SelectResType(object type, ResType resType)
{
return resType.NameHeadID.SelectMany(nameIdPair => SelectResName(type, nameIdPair.Key, nameIdPair.Value))
.Concat(resType.NameHeadName.SelectMany(nameNamePair =>
SelectResName(type, nameNamePair.Key, nameNamePair.Value)));
}

IEnumerable<(object name, object type, ushort language, byte[] data)> SelectResName(object type, object name, ResName resType)
{
return resType.Languages.Select((lang) => (name, type, lang.Key, lang.Value.DataEntry));
}
}

public bool IsEmpty
{
get
Expand All @@ -81,12 +141,32 @@ public bool IsEmpty
}
}

/// <summary>
/// Add all resources in the specified ResourceData struct.
/// </summary>
public void CopyResourcesFrom(ResourceData moduleResources)
{
foreach ((object name, object type, ushort language, byte[] data) in moduleResources.GetAllResources())
AddResourceInternal(name, type, language, data);
}

#if HOST_MODEL
public void WriteResources(int sectionBase, ref ObjectDataBuilder dataBuilder)
{
WriteResources(sectionBase, ref dataBuilder, ref dataBuilder);
}
#else
public void WriteResources(ISymbolNode nodeAssociatedWithDataBuilder, ref ObjectDataBuilder dataBuilder)
{
WriteResources(nodeAssociatedWithDataBuilder, ref dataBuilder, ref dataBuilder);
}
#endif

#if HOST_MODEL
public void WriteResources(int sectionBase, ref ObjectDataBuilder dataBuilder, ref ObjectDataBuilder contentBuilder)
#else
public void WriteResources(ISymbolNode nodeAssociatedWithDataBuilder, ref ObjectDataBuilder dataBuilder, ref ObjectDataBuilder contentBuilder)
#endif
{
Debug.Assert(dataBuilder.CountBytes == 0);

Expand Down Expand Up @@ -159,7 +239,11 @@ public void WriteResources(ISymbolNode nodeAssociatedWithDataBuilder, ref Object
foreach (Tuple<ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages)
{
dataBuilder.EmitInt(language.Item2, dataBuilder.CountBytes);
#if HOST_MODEL
IMAGE_RESOURCE_DATA_ENTRY.Write(ref dataBuilder, sectionBase, dataEntryTable[language.Item1], language.Item1.DataEntry.Length);
#else
IMAGE_RESOURCE_DATA_ENTRY.Write(ref dataBuilder, nodeAssociatedWithDataBuilder, dataEntryTable[language.Item1], language.Item1.DataEntry.Length);
#endif
}
dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,6 @@ void RewriteAppHost(MemoryMappedViewAccessor accessor)
}
}

void UpdateResources()
{
if (assemblyToCopyResourcesFrom != null && appHostIsPEImage)
{
if (ResourceUpdater.IsSupportedOS())
{
// Copy resources from managed dll to the apphost
new ResourceUpdater(appHostDestinationFilePath)
.AddResourcesFromPEImage(assemblyToCopyResourcesFrom)
.Update();
}
else
{
throw new AppHostCustomizationUnsupportedOSException();
}
}
}

try
{
RetryUtil.RetryOnIOError(() =>
Expand Down Expand Up @@ -115,6 +97,13 @@ void UpdateResources()
{
MachOUtils.RemoveSignature(fileStream);
}

if (assemblyToCopyResourcesFrom != null && appHostIsPEImage)
{
using var updater = new ResourceUpdater(fileStream, true);
updater.AddResourcesFromPEImage(assemblyToCopyResourcesFrom);
updater.Update();
}
}
}
finally
Expand All @@ -125,8 +114,6 @@ void UpdateResources()
}
});

RetryUtil.RetryOnWin32Error(UpdateResources);

if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var filePermissionOctal = Convert.ToInt32("755", 8); // -rwxr-xr-x
Expand Down
Loading