Skip to content
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

Merged
merged 7 commits into from
Feb 15, 2025

Conversation

steveharter
Copy link
Member

@steveharter steveharter commented Dec 23, 2024

Fix alignment Assert and add tests for #110686.

@steveharter steveharter added area-System.Reflection.Emit test-enhancement Improvements of test source code labels Dec 23, 2024
@steveharter steveharter self-assigned this Dec 23, 2024
private static void SamplePrivateMethod ()
{
}
private static void SamplePrivateMethod()
Copy link
Member Author

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

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection-emit
See info in area-owners.md if you want to be subscribed.

@jkotas
Copy link
Member

jkotas commented Dec 23, 2024

What was the alignment issue that you have mentioned in #110686 (comment) originally?

@steveharter steveharter removed the test-enhancement Improvements of test source code label Dec 23, 2024
@steveharter steveharter changed the title Add test for saving and reading managed resources Fix alignment and add test for saving resources using PersistedAssemblyBuilder Dec 23, 2024
@steveharter
Copy link
Member Author

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.

@steveharter steveharter changed the title Fix alignment and add test for saving resources using PersistedAssemblyBuilder Fix alignment padding and add test for saving managed resources Dec 24, 2024
@steveharter steveharter requested a review from ericstj December 24, 2024 16:10
@@ -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).
Copy link
Member

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping @tmat

Copy link
Member

@tmat tmat Jan 13, 2025

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.

Copy link
Member Author

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:

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.

Copy link
Member Author

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.

Copy link
Member

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?

Copy link
Member Author

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.

@ericstj ericstj requested review from jkotas and tmat January 7, 2025 00:14
@steveharter
Copy link
Member Author

@jkotas @tmat any final comments or asks?

I don't think we need to port this to v9, as the alignment added here appears optional.

@steveharter
Copy link
Member Author

ping @tmat @jkotas - any additional comments here?

@jkotas
Copy link
Member

jkotas commented Feb 10, 2025

I think we should:

  • Delete the asserts that check alignment of mapped fields and resources sizes. They can be trivially hit by user code passing in misaligned blobs:

Debug.Assert(MappedFieldDataSize % MappedFieldDataAlignment == 0);

  • Optionally, if we believe that the alignment of the resource blob is important (there is no evidence in any spec that it is the case), add the padding before the resource blob similarly how it is added before the field data blob. It may be best to wait and see whether this shows up anywhere.

@steveharter
Copy link
Member Author

I do not think that the prosed fix that tries to add the padding after the resource section is good. It does not seem to follow what we do in the other places wrt. alignment of user provided blobs.

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.

@jkotas
Copy link
Member

jkotas commented Feb 12, 2025

the next section in the CorHeader (StrongNameSignature) is also aligned

StrongNameSignature is a byte array without any structure. These is no reason for it to require any sort of alignment.

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:

if (mappedFieldDataBuilderOpt.Count != 0)
builder.Align(MappedFieldDataAlignment);

@steveharter
Copy link
Member Author

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.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@jkotas jkotas merged commit 16f2675 into dotnet:main Feb 15, 2025
82 of 86 checks passed
grendello added a commit to grendello/runtime that referenced this pull request Feb 18, 2025
* 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)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants