[R2R] Align composite ManifestMetadata and ComponentAssemblies sections to 4 bytes#130564
Open
simonrozsival wants to merge 1 commit into
Open
Conversation
…ns to 4 bytes Follow-up to dotnet#129017. That PR fixed a 32-bit ARM SIGBUS (BUS_ADRALN) in composite Ready-to-Run images caused by emitting the manifest MVID table with alignment: 1. The adjacent ManifestMetadataTableNode (metadata root) and AssemblyTableNode (ComponentAssemblies) have the identical latent bug: both are packed arrays of DWORD-typed fields the runtime reads in place, but are emitted with alignment: 1, so they can land on a non-4-aligned RVA and fault on ARM32 (unaligned multi-word load) during coreclr_initialize. x64/arm64 tolerate the unaligned access. In the failing android-arm MAUI R2R crash (dotnet/android#12026) the MVID table was already aligned (thanks to dotnet#129017), but the metadata root landed on an odd RVA and faulted in PEDecoder::CheckCorHeader, so dotnet#129017 alone did not cover this case. Align both sections to 4 bytes (their contents' natural alignment) and add a regression test mirroring the MVID-table tests (a plain composite case plus a Windows-only --pdb variant that deterministically exposes the misalignment). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 77c12619-9a25-4209-9469-b44bd280f2bc
Contributor
|
Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates crossgen2 composite ReadyToRun emission to ensure manifest-related sections that contain 32-bit fields are emitted on 4-byte boundaries, avoiding potential unaligned in-place reads on targets that require alignment (notably ARM32). It also adds regression checks in the ReadyToRun test suite to validate the resulting section RVAs are properly aligned.
Changes:
- Align
ManifestMetadataTableNodeoutput to 4 bytes (including therelocsOnlypath) since it contains DWORD-based metadata stream headers. - Require 4-byte initial alignment for the
ComponentAssembliestable (AssemblyTableNode). - Add a new test helper plus composite test cases that assert
ManifestMetadataandComponentAssembliessection RVAs are 4-byte aligned (with a Windows-only--pdbvariant).
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs | Changes manifest metadata node alignment from 1 to 4 to ensure safe in-place parsing of DWORD fields. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AssemblyTableNode.cs | Requires 4-byte alignment for the component assemblies table emission. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs | Adds alignment-check helpers for composite manifest sections (metadata + component assemblies). |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs | Adds regression tests validating the new alignment constraints (including a --pdb padding trigger on Windows). |
Copilot's findings
- Files reviewed: 4/4 changed files
- Comments generated: 0
This was referenced Jul 12, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #129017.
Summary
That PR fixed a 32-bit ARM
SIGBUS(BUS_ADRALN) in composite Ready-to-Run images caused by emitting the manifest MVID table withalignment: 1. The adjacentManifestMetadataTableNode(the metadata root) andAssemblyTableNode(ComponentAssemblies) have the identical latent bug: both are packed arrays ofDWORD-typed fields that the CoreCLR runtime reads in place, but both are emitted withalignment: 1, so they can land on a non-4-aligned RVA. On ARM32 that faults withBUS_ADRALN(unaligned multi-word load); x64/arm64 tolerate it, so it stayed latent until android-arm composite R2R was exercised.In the failing android-arm MAUI R2R crash (dotnet/android#12026) the MVID table was already aligned (thanks to #129017), but the metadata root landed on an odd RVA and faulted in
PEDecoder::CheckCorHeaderduringcoreclr_initialize. So #129017 was necessary but not sufficient for this configuration; this change completes it by aligning the remaining manifest-region sections.Root cause
Loading a composite image parses the metadata root via
PEDecoder::CheckCorHeader, which walksSTORAGESTREAMheaders (ULONG iOffset; ULONG iSize; char rcName[]). The compiler coalesces the two adjacentDWORDreads (iOffset/iSize) into a singleLDRD, which requires 4-byte alignment on ARM32:ComponentAssemblies(READYTORUN_COMPONENT_ASSEMBLIES_ENTRY) is likewise a packedDWORDarray read in place, and the regression test shows it landing unaligned without the fix.Provenance
alignment: 1onManifestMetadataTableNodedates back to the initial population of crossgen2 from the CoreRT sources (ac857a2e, 2019) and was never a deliberate choice — no commit or discussion in the file's history addressed alignment; the value was carried verbatim through later refactors (e.g. #71271 only switched to named arguments). The siblingManifestAssemblyMvidHeaderNodeshared the same default and was corrected in #129017.Why 4, and why not configurable / a size concern
DWORDfields whose natural alignment is 4; ECMA-335 already pads the metadata version string so stream headers are 4-aligned within the blob. 4-byte section-start alignment is the correct requirement (same rationale as Align manifest assembly MVID table to 4 bytes in composite R2R images #129017's "GUID has a natural alignment of 4").Testing
Mirrors #129017's test approach: a
CompositeManifestSectionsAreAligned(...)checker inR2RResultChecker, driven by a plain[Fact]and a Windows-only[ConditionalFact(IsWindows)]--pdbvariant that uses the same composite inputs.Validation
Mirrors #129017: the
--pdbvariant emits an odd-sizedNativeDebugDirectoryEntryNodethat, without the fix, shifts the manifest sections off a 4-byte boundary; with the fix they are padded to a 4-byte RVA. Verified end-to-end by building an android-arm CoreCLR composite R2R APK with the fixed crossgen2 — R2RDump confirmsManifestMetadata,ComponentAssemblies, andManifestAssemblyMvidsall start on 4-byte-aligned RVAs — resolving the crash reported in dotnet/android#12026.cc @jtschuster (author of the sibling fix #129017)