-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Fix alignment padding and add test for saving managed resources #110915
Conversation
private static void SamplePrivateMethod () | ||
{ | ||
} | ||
private static void SamplePrivateMethod() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whitespace-only changes to this file
Tagging subscribers to this area: @dotnet/area-system-reflection-emit |
...libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveResourceTests.cs
Outdated
Show resolved
Hide resolved
What was the alignment issue that you have mentioned in #110686 (comment) originally? |
I pushed a new commit for that. I assume the best practice here is to not modify the incoming blob directly to add the padding, so the alignment is done when writing. Also, the Assert checked on 4-byte alignment, but the unused const had 8, so I'm assuming 8. I'll also double-check to see what Roslyn does. |
...es/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs
Outdated
Show resolved
Hide resolved
@@ -40,8 +41,8 @@ internal sealed class ManagedTextSection | |||
public int MetadataSize { get; } | |||
|
|||
/// <summary> | |||
/// The size of managed resource data stream. | |||
/// Aligned to <see cref="ManagedResourcesDataAlignment"/>. | |||
/// The size of managed resource data stream (unaligned). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tmat Could you please take a look at the changes in this file? How are the alignment requirements expected to be handled by ManagedPEBuilder
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @tmat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't remember what the expectations were. It's been a while.
To me it looks like we should have checked the alignments in ManagedPEBuilder
constructor and throw if they are off. Can we add that check? It would break someone who emits unaligned data, but if they do the emitted assembly would be bad anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are basically two choices: throw if not aligned or align it for the user.
This PR takes the path of aligning it for the user like we do in other areas:
- MappedFieldDataSize
Line 143 in 07e4c1b
result = BitArithmetic.Align(result, MappedFieldDataAlignment); - ImportTable
Line 131 in 1ce82e7
result = BitArithmetic.Align(result, Is32Bit ? 4 : 8); //optional padding to make startup stub's target address align on word or double word boundary - Startup Stub
Line 185 in 07e4c1b
return OffsetToILStream + BitArithmetic.Align(ILStreamSize, 4);
If we don't align it for the user, the user would need an extra LOC to do the alignment for the somewhat common case of using resources, and that extra LOC that would be needed is not obvious to the caller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but if they do the emitted assembly would be bad anyways.
I don't believe the lack of alignment breaks anything, unless there is some platform-specific alignment limitations that I'm not aware of -- e.g. the test added here worked before the alignment was added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow. If the alignment is not needed then why are we adding it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was an Assert that was failing so we either need to remove it or add the alignment \ padding. Since there was a ManagedResourcesDataAlignment public const I decided to use that (it wasn't used before). Finally, the assert was checking if alignment to 4 while the public const is 8.
I do not know why the const was added, or why the alignment and checks are there in part. Git history shows this existed 8+ years ago as part of large commits. Likely the alignment was added for efficiency when reading the subsequent data. The code may have assumed the caller would align the data, but if so then the code should have thrown and not just asserted.
...es/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs
Outdated
Show resolved
Hide resolved
I think we should:
Line 190 in 1c3b1b5
Line 257 in 1c3b1b5
|
My understanding: the resource section has a "ResourcesDirectory" entry (Size + RVA) in the CorHeader so when the actual metadata is written it should aligned so the next section in the CorHeader (StrongNameSignature) is also aligned -- I can verify this, but seems right to me. The other sections like MappedFieldDataSize are in the "MetadataDirectory" CorHeader entry. |
If we believe that there are any sections that need to be aligned, we should emit the alignment before emitting that section, like it is done for field data here: Lines 306 to 307 in 07e4c1b
|
A new commit removes the padding and the original Asserts. Padding is not necessary, and due to padding\alignment inconsistencies (dicussed offline) between Roslyn, Cecil and here (System.Reflection.Metadata) it makes sense to not add padding which may be an unnecessarily optimization. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
* main: (71 commits) Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20250212.3 (dotnet#112626) JIT: Unify struct arg morphing (dotnet#112612) Enable `SA1015`: Closing generic bracket should not be followed by a space (dotnet#112597) Clean up normalizeLocale for mono browser target (dotnet#112575) SPMI: Ensure proper zero extension for isObjectImmutable and friends (dotnet#112617) Quote --version-scripts path (dotnet#112603) Remove incompatible API from PKCS netstandard2.0 lib [main] Update dependencies from dotnet/emsdk (dotnet#112393) Avoid `Unsafe.As` in `RangeCharSearchValues` (dotnet#112606) Fixed the issue of incorrect return value of PalVirtualAlloc (dotnet#112579) Fix size used for vectorization check in BitArray (dotnet#111558) (dotnet#111564) Fix build of windows arm64 crossdac (dotnet#112553) Simplify `ShuffleTakeIterator.GetCount` (dotnet#112593) Fix VS div-by-0 in DacEnumerableHashTable code (dotnet#112542) R2RDump: normalize GC info totalInterruptibleLength (dotnet#112003) Fix alignment padding and add test for saving managed resources (dotnet#110915) Adds `ccmp` logic into emitter backend. (dotnet#112153) Disable AVX10.2 by default (dotnet#112572) Outbox AesGcm in to Microsoft.Bcl.Cryptography Make test `IUnknown` conforming (dotnet#112566) ...
Fix alignment Assert and add tests for #110686.