Uh oh!
There was an error while loading. Please reload this page.
[r8-obfuscation] Add PE metadata rebuild substrate - #12629
Conversation
e83dcaa to
58ac474Comparesimonrozsival
commented
Sep 1, 2026
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
simonrozsival
commented
Sep 2, 2026
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
fdb7393 to
311a3bfComparesimonrozsival
commented
Sep 2, 2026
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use the executing runtime version in metadata fixtures so rebuilt images load across target frameworks. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
311a3bf to
cc7f216CompareThere was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
MetadataEncoding.ReadCompressedInteger does not guard against negative offsets, causing unintended IndexOutOfRangeException instead of a controlled rewrite failure.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 1
New issues introduced by this change (2)
| Severity | Finding |
|---|---|
src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/MetadataEncoding.cs — ❌ error Bug — ReadCompressedInteger allows a negative offset, which will throw… | |
src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/AssemblyRebuilder.cs — 💡 suggestion Formatting / Conventions — Prefer [] over Array.Empty<T>() in this repo to… |
What changed in this PR
Adds the internal PE + ECMA-335 metadata rebuild substrate under Xamarin.Android.Build.Tasks to support later R8/JNI name-rewriting layers, while keeping this layer behaviorally inert (no build integration yet). The new utilities focus on rebuilding managed assemblies without moving metadata tokens, while re-emitting method bodies, resources, debug directory data, native resources, and FieldRVA mapped data, plus adding targeted validation against malformed inputs.
Changes:
- Introduces
AssemblyRebuilderand supporting primitives for token-preserving PE/metadata reconstruction, IL scanning, and selective heap/value rewrites. - Adds low-level helpers for raw metadata column access, compressed integer encoding/decoding,
FieldRVAdecoding/relayout, and Win32 resource section relocation. - Adds focused NUnit coverage with a fixture generator to validate native resources,
FieldRVAbehaviors, IL scanning validation, and strong-name signature handling.
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/AssemblyRebuilder.cs | Core token-preserving managed PE rebuild implementation (IL, resources, debug/native resources, FieldRVA). |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/FieldRvaTable.cs | Reads and interprets FieldRVA rows and mapped data, including typemap-style UTF-8 payload detection. |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/NativeResourceSectionCopier.cs | Copies and relocates .rsrc directory data for rebuilt PEs with validation. |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/MetadataRawColumns.cs | Reads metadata table columns not exposed by MetadataReader (e.g., ImplMap.MemberForwarded). |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/MetadataEncoding.cs | ECMA-335 compressed integer encode/decode helper used for manual blob rewriting. |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/JniRewritePlan.cs | Holds per-use-site rewrite decisions for attributes, ldstr, and UTF-8 FieldRVA data. |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/JniRewriteException.cs | Dedicated exception type for rewrite failures and validation errors. |
| src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/IlOpcodeTable.cs | Minimal operand-size table enabling IL walks without a full IL parser. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/JniRemapping/AssemblyRebuilderTests.cs | End-to-end tests for rebuild invariants (FieldRVA/resources, IL, strong-name space, validation). |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/JniRemapping/NativeResourceSectionCopierTests.cs | Validates .rsrc copying/relocation and malformed directory rejection. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/JniRemapping/JniFixtureBuilder.cs | Produces minimal managed PE fixtures to exercise the rebuilder without external binaries. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Detach rewritten mapped fields from overlapping source storage so shorter replacements cannot corrupt aliased fields. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Validate negative compressed-integer offsets and use the repository empty-array convention when rebuilding method bodies. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Validate malformed resource and strong-name directory values through the rewrite error contract, and emit MethodSemantics rows in HasSemantics coded-index order. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival
commented
Sep 2, 2026
/review |
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
The table-by-table token preservation and malformed-metadata coverage are strong, and all 44 CI checks are green. Before merge, the rebuild needs to reject or preserve non-MethodDef entry points; I also called out two validation gaps that can silently produce altered or inconsistent output for malformed metadata.
Generated by Android PR Reviewer for #12629 · gpt56 · 227.7 AIC · ⌖ 9.02 AIC · ⊞ 25.7K
Comment /review to run again
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Validate colliding synthetic UTF-8 types before reuse and reject half-populated native resource directories. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival
commented
Sep 2, 2026
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
simonrozsival
commented
Sep 2, 2026
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading. Please reload this page.


Summary
This is layer 2 of 6 in the replacement stack for PR #12575. It adds the internal PE and metadata reconstruction substrate required by later JNI name-rewriting layers, without enabling any build behavior.
FieldRVAmapped data, including ranges from different PE sections.FieldRVAbacking data by relocating rewritten fields instead of modifying shared storage.HasSemanticscoded-index order.ImplMaprows instead of silently dropping metadata.FieldRVAreplacements, aliased mapped fields, event/property accessor preservation, per-use#USsplitting, and strong-name signature preservation directly throughAssemblyRebuilder.Scope
This layer intentionally does not add JNI-specific planning or attribute/
ldstrorchestration, the assembly-rewriter facade, theRewriteJniNamesForR8MSBuild task, typemap rewrite behavior, CoreCLR/NativeAOT target integration, or documentation. Those surfaces belong to later stack layers.Validation
./dotnet-local.sh build src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj -c Debug -v:minimal --no-restore./dotnet-local.sh test bin/TestDebug/net10.0/Xamarin.Android.Build.Tests.dll --filter 'FullyQualifiedName~NativeResourceSectionCopierTests|FullyQualifiedName~AssemblyRebuilderTests'RewrittenAssemblyLoadsAndRunsInTheRuntimeresult: 1 passed, 0 failed.Related to #12535
Depends on #12628