Repository navigation
[CoreCLR] Load bootstrap configuration from binary blobs - #13034
Open
simonrozsival wants to merge 17 commits into
Open
simonrozsival wants to merge 17 commits into
simonrozsival wants to merge 17 commits into
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved bootstrap validation and build-incrementality issues block approval.
2 open findings
What changed in this PR
Moves CoreCLR startup configuration from app-specific native globals into per-ABI binary blobs alongside JNI remapping. The assembly store remains separate, and NativeAOT remains remapping-only.
Changes:
- Generate, validate, and package CoreCLR bootstrap data.
- Load configuration during
JNI_OnLoadand reuse the library handle for managed remapping. - Add serialization, packaging, cleanup, and large-configuration startup tests.
| File | Description |
|---|---|
| tests/MSBuildDeviceIntegration/Tests/R8RuntimeRemappingTests.cs | Tests startup with 5,000 runtime properties. |
| tests/MSBuildDeviceIntegration/Tests/R8RuntimeRemappingBuildTests.cs | Tests bootstrap packaging, recovery, and cleanup. |
| src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | Integrates bootstrap generation and output tracking. |
| src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj | Includes the shared bootstrap serializer. |
| src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs | Builds bootstrap data and generic native placeholders. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/EnvironmentHelper.cs | Reads bootstrap configuration in tests. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateNativeApplicationConfigSourcesTests.cs | Tests binary configuration generation. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest3.cs | Reads preload expectations from bootstrap data. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs | Reads assembly counts from bootstrap data. |
| src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs | Writes the bootstrap intermediate. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.R8JniRemapping.targets | Passes bootstrap data into blob packaging. |
| src/native/clr/runtime-base/android-system.cc | Reads environment and system properties from bootstrap data. |
| src/native/clr/libnet-android.map.txt | Exports the shared-handle accessor. |
| src/native/clr/include/runtime-base/monodroid-dl.hh | Uses the bootstrap-backed native-library cache. |
| src/native/clr/include/runtime-base/coreclr-bootstrap.hh | Declares bootstrap state and accessors. |
| src/native/clr/host/host.cc | Initializes and consumes bootstrap configuration. |
| src/native/clr/host/host-jni.cc | Exposes the retained blob-library handle. |
| src/native/clr/host/coreclr-bootstrap.cc | Loads, bounds-checks, and decompresses bootstrap data. |
| src/native/clr/host/CMakeLists.txt | Compiles the bootstrap loader. |
| src/Mono.Android/Microsoft.Android.Runtime/BinaryJniRemappingLookup.cs | Reuses CoreCLR’s native library handle. |
| src/Microsoft.Android.Build.Tasks/Utilities/JniRemappingBinaryBlob.cs | Shares envelope generation between payload types. |
| src/Microsoft.Android.Build.Tasks/Utilities/CoreClrBootstrapBlob.cs | Serializes and validates bootstrap data. |
| src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateJniRemappingBinaryBlobsTests.cs | Tests multi-ABI packaging, compression, and malformed input. |
| src/Microsoft.Android.Build.Tasks/Tasks/GenerateJniRemappingBinaryBlobs.cs | Packages bootstrap and remapping symbols together. |
| Documentation/docs-mobile/messages/xa4325.md | Documents bootstrap-related build failures. |
🧠 Review effort: Balanced
simonrozsival
force-pushed
the
simonrozsival-coreclr-elf-bootstrap-blobs
branch
13 times, most recently
from
October 8, 2026 14:40
8568b14 to
f8eae88
Compare
Keep per-app CoreCLR startup data out of the generated native app configuration. Emit a validated bootstrap intermediate and assemble it with JNI remapping as separate symbols in the same read-only ELF. Load and bound the bootstrap payload during JNI_OnLoad, retaining its DSO handle for managed remapping. Preserve NativeAOT remapping and validate packaging, preload aliases, incremental builds, and startup. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move DSO cache ordering into the producer validator and avoid redundant eager bootstrap scans in JNI_OnLoad. Keep bounded mapped reads and allocation safeguards for native consumers. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copy the fixed-size, build-validated header once into a typed layout and use named fields while leaving the mapped tables in place. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move the mapped-property search into CoreClrBootstrap while preserving AndroidSystem debug bundled-property precedence and value-length behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move the mapped environment and system-property setup together into CoreClrBootstrap, leaving AndroidSystem to apply Debug override files afterward. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify the bootstrap-only ELF and presence stamp, and update packaging and startup tests for the required CoreCLR library while NativeAOT omits empty remapping. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the bootstrap-only library in CoreCLR packages while NativeAOT removes its remapping-only library when obfuscation is disabled. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Share DSO hash/sort logic, use the XCFG intermediate for direct-task assertions, remove obsolete LLVM-config assertions and redundant CoreCLR empty-remap cases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove the fallback that emitted app-specific LLVM configuration when the CoreCLR bootstrap path was absent. Validate the required output before generating anything and update direct task tests to exercise XCFG instead of legacy globals. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use the generation stamp as the incremental output when bootstrap bytes retain their timestamp. Invalidate the stamp if the CoreCLR bootstrap intermediate is deleted, and exercise edit/no-op and missing-file recovery. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove the prior package-manager completion stamp before any generation task mutates outputs. Recreate the stamp only after Java, XCFG and native source generation finish successfully. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival
force-pushed
the
simonrozsival-coreclr-elf-bootstrap-blobs
branch
from
October 8, 2026 17:43
f8eae88 to
ac5810c
Compare
This branch has not been deployed
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.


Pull Request
title and
description
should follow the
commit-messages.mdworkflow documentation, and in particular should include:Why: CoreCLR startup configuration was embedded as app-specific native globals, separate from the read-only ELF carrying JNI remapping. This layer generates validated XCFG v1 bootstrap data early and assembles it late with final remapping in the same per-ABI
libbinary_blobs.so. Empty remapping produces a bootstrap-only single-symbol ELF with presence stamptrue; NativeAOT remains remapping-only and emits no library for empty remapping. The assembly-store SO remains separate. App-specific CoreCLR LLVM globals become generic linker placeholders; no app-specific Java configuration bytes are generated. CoreCLR generation requires a nonblank bootstrap output path, with no legacy fallback. Direct-task tests assert XCFG content, and redundant legacy cases were removed. Removing generic LLVM generation is deferred to a follow-up PR.The package-manager generation target uses its completion stamp for freshness, invalidates it when the bootstrap is missing, deletes it before output-producing tasks run, and recreates it only after successful completion. The combined ELF task retains lower-layer stamp invalidation before output mutations. Both packaging paths preserve the lower layer's rejection of external native inputs targeting reserved
libbinary_blobs.so; SDK-generated blob items remain separate and allowed.Stack/ABI handshake: Prerequisite #13033 supplies multi-symbol ELF writing, independent BLBB v1 raw/Zstd-22 envelopes, optional remapping lookup, and required native
BinaryBlobLoader::loadreturning a decoded{data, size}body with process-lifetime backing. CoreCLR callsload("coreclr_bootstrap")at the start ofJNI_OnLoad, before early consumers or CLR creation; its retained loader resolves optionalremapping_dataonce later. XCFG v1 has an 84-byte little-endian header with contiguous environment/system/runtime-property, DSO-cache, preload-index and UTF-8 string-pool sections. The producer validates layout, hash ordering, strings, preload references and required runtime-property slots. ABI metadata is validated upfront and each ELF is validated/written sequentially. Startup trusts build-time invariants rather than rescanning tables or NUL terminators; it copies the fixed header once into a typed struct, retains mapped tables, and bounds on-demand accesses and allocations. Debug override files retain precedence. Default payloads remain raw; compression uses the existing private switch. No issue is closed by this stacked PR.Latest restack: upper
ac5810cda6ea6056eb8f52024f929f69948da5f8is based exactly on lower6e564a248d615d9d4c9cfe2eb751b84bcbf6b3a3, including parent #12844 head31f99c7f06f18cc5cd28c687bb2d35693b6d6279. All 17 upper patches replay unchanged. The parent fixes native test fixture path separators and disposal of the legacy XML input stream; native APIs, wire format, stamp contracts and raw defaults are unchanged.Current-head validation (macOS):
make all— passed, Debug SDK, 0 errors.make all CONFIGURATION=Release MSBUILD_ARGS='-p:RunAnalyzers=false'— passed, Release SDK, 0 errors; the local API-37 preview otherwise triggers unrelated RS0016 analyzer diagnostics. The legacy task assembly also rebuilt successfully in this workspace../dotnet-local.sh test bin/TestDebug/net11.0/Microsoft.Android.Build.Tasks.Tests.dll --arch arm64 --filter 'FullyQualifiedName~CoreClrBootstrapBlobTests|FullyQualifiedName~AssemblyStoreElfWriterTests|FullyQualifiedName~TypeMapProguardTargetsTests' --logger 'console;verbosity=quiet'— 129 passed, 4 skipped../dotnet-local.sh test bin/TestDebug/net10.0/Xamarin.Android.Build.Tests.dll --arch arm64 --filter 'FullyQualifiedName~GenerateJniRemappingNativeCodeTests|Name~UnchangedCoreClrBootstrapDoesNotRegenerateOnNextBuild|FullyQualifiedName~GenerateNativeApplicationConfigSourcesTests|FullyQualifiedName~GeneratePackageManagerJavaTests' --logger 'console;verbosity=quiet'— 18/18 passed, legacy XML generation, XCFG task contract and incremental recovery coverage../dotnet-local.sh test bin/TestDebug/MSBuildDeviceIntegration/net10.0/MSBuildDeviceIntegration.dll --arch arm64 --filter 'Name~BuildWithoutRemappingKeepsOnlyCoreClrBootstrap|Name~MamRemappingTransitionsUpdatePackages|Name~MultiRidUsesOneR8Mapping|Name~ReservedBinaryBlobLibraryNameIsRejected' --logger 'console;verbosity=quiet'— 14/14 passed: APK/AAB, multi-RID, no-map, collision rejection, aliases, no-op, partial-output failure/stamp invalidation/retry, recovery and Clean. These are host-side build tests; no device calls were made. Windows execution was not performed; macOS results are not Windows evidence. No manual CI retry was requested.Prior runtime validation on lower
58c264dc8dcfb90fe29a666db24db98989de951c, upperacf33f4e831497c81249c9aba36f29e238bb1d6f:ADB_TARGET='-s emulator-5594' ANDROID_SERIAL=emulator-5594 ./dotnet-local.sh test bin/TestDebug/MSBuildDeviceIntegration/net10.0/MSBuildDeviceIntegration.dll --arch arm64 --filter 'Name~BuildWithoutRemappingKeepsOnlyCoreClrBootstrap|Name~MamRemappingTransitionsUpdatePackages|Name~MultiRidUsesOneR8Mapping|Name~CoreClrLargeBootstrapStartsInDebug' --logger 'console;verbosity=quiet'— 11/11 passed, including >64 KiB/5,000-property Debug/D8 startup.ADB_TARGET='-s emulator-5594' ANDROID_SERIAL=emulator-5594 ./dotnet-local.sh test bin/TestRelease/MSBuildDeviceIntegration/net10.0/MSBuildDeviceIntegration.dll --arch arm64 --filter 'Name~ObfuscatedMembersRun|Name~NativeAotEmptyExplicitRemappingRuns' --logger 'console;verbosity=quiet'— 5/5 passed: Release/R8 CoreCLR and NativeAOT raw/Zstd startup and explicit-empty NativeAOT startup. These runtime results were not rerun on the latest head.Both existing review threads were replied to and resolved. The removed lower remapping-blob fixture stays removed. Prior runtime validation used only the owned emulator, stopped afterward; no physical device or A16 benchmark was used. Native stack membership and base-branch chain were preserved without metadata recreation.