Skip to content

[tools] Support current and legacy assembly stores - #12104

Merged
jonathanpeppers merged 6 commits into
mainfrom
dev/simonrozsival/update-assembly-store-tools
Jul 20, 2026
Merged

[tools] Support current and legacy assembly stores#12104
jonathanpeppers merged 6 commits into
mainfrom
dev/simonrozsival/update-assembly-store-tools

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

  • locate CoreCLR assembly stores through the exported _assembly_store ELF symbol while retaining the MonoVM payload section fallback
  • preserve compatibility with legacy v1 multi-file store sets, manifests, and architecture-agnostic assemblies
  • read both v2 and v3 RID-specific stores under their historical and current APK/AAB names
  • decode both XALZ/LZ4 and XAZS/Zstd compressed assemblies
  • use the unified reader from decompress-assemblies without dropping direct DLL or individual-entry handling

This follows up on #12033 (comment).

Compatibility

The reader now detects the archive layout, ELF wrapper, store format, and compression format independently:

Layer Supported formats
Store set legacy v1 blobs + manifest; RID-specific v2/v3 stores
APK/AAB entry assemblies/assemblies.blob; libassemblies.{abi}.blob.so; libassembly-store.so
Wrapper raw blob; ELF payload section; exported _assembly_store symbol
Compression uncompressed; XALZ/LZ4; XAZS/Zstd

Legacy common assemblies are included in each ABI-specific view, matching the original store-set behavior.

Follow-up

A separate stacked PR will simplify the standalone tool projects into .NET file-based apps and introduce skills that invoke them for customer APK inspection and extraction. The shared compatibility parser remains in the repository because build/device tests and external projects consume or track it.

Validation

  • 10 standalone compatibility tests covering:
    • v1 filesystem, manifest, base-name, APK, common-store, LZ4, and Zstd cases
    • v2 historical archive names and index layout
    • v3 current archive names and index layout
  • builds for the modern reader, legacy reader, decompressor, and tmt
  • compatibility tests added to Windows CI

Teach the assembly store reader to locate CoreCLR stores through the exported _assembly_store symbol while retaining the MonoVM payload-section fallback. Reuse the modern reader from decompress-assemblies without dropping legacy store support.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 55493571-86e2-4326-850e-ea55883aa5d8
Copilot AI review requested due to automatic review settings July 14, 2026 15:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the inspection/decompression tooling to support the current CoreCLR assembly-store layout by locating the store via the exported _assembly_store ELF symbol (with a fallback to the legacy payload section), and wires that into decompress-assemblies so it can correctly extract assemblies from modern APK/AAB layouts under lib/{ABI}/libassembly-store.so. It also factors the v2 reader into a reusable library and ensures decompression failures propagate via the tool exit code.

Changes:

  • Add ELF _assembly_store symbol lookup (with payload section fallback) to the mk2 assembly-store reader.
  • Split the mk2 reader into a reusable AssemblyStore library and consume it from both the mk2 CLI and decompress-assemblies.
  • Update decompress-assemblies to handle both legacy assemblies/assemblies.blob and current lib/{ABI}/libassembly-store.so stores, and to return non-zero on failures.
Show a summary per file
File Description
tools/decompress-assemblies/main.cs Adds support for extracting from current lib/{ABI}/libassembly-store.so stores (plus better failure propagation), while keeping legacy store and individual-entry paths.
tools/decompress-assemblies/decompress-assemblies.csproj Adds a project reference (with alias) to the mk2 AssemblyStore library and the Android SDK tools dependency needed for ABI/arch handling.
tools/assembly-store-reader-mk2/Main.cs Removes redundant file-format/existence checks now handled by AssemblyStoreExplorer.Open.
tools/assembly-store-reader-mk2/Directory.Build.targets Copies the launch script only for executable builds and makes the script path resolution robust via $(MSBuildThisFileDirectory).
tools/assembly-store-reader-mk2/AssemblyStore/Utils.cs Implements _assembly_store dynamic symbol-based payload discovery with fallback to payload section scanning.
tools/assembly-store-reader-mk2/AssemblyStore/StoreReader_V2.cs Uses the new ELF payload discovery API and improves the error message for invalid _assembly_store symbols.
tools/assembly-store-reader-mk2/AssemblyStore/ELFPayloadError.cs Adds an error value for invalid payload symbols.
tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStoreItem.cs Makes AssemblyStoreItem public to support external consumers.
tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStoreExplorer.cs Makes AssemblyStoreExplorer public and updates the “no entries found” error message.
tools/assembly-store-reader-mk2/AssemblyStore/AssemblyStore.csproj Introduces a dedicated reusable library project for the mk2 reader implementation.
tools/assembly-store-reader-mk2/assembly-store-reader.csproj Switches the CLI to consume the new library project instead of compiling the sources directly.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0

@jonathanpeppers

Copy link
Copy Markdown
Member

/review

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Needs Changes

Nice, well-structured follow-up that revives decompress-assemblies for symbol-based (libassembly-store.so) stores while preserving the legacy assemblies.blob and individual-entry paths, plus threading failures through the exit code. The ELF _assembly_store symbol resolution with a payload-section fallback is clean, and the 32/64-bit bounds checks are careful.

Issues (see inline comments):

  • ⚠️ 1 error-handling: GetAndroidAbi can throw NotSupportedException for None/Mips/Other archs (which pass the HasValue guard), crashing the tool instead of propagating a non-zero exit code — the opposite of one of this PR's goals.
  • 💡 2 suggestions: arch→ABI mapping duplicates MonoAndroidHelper; and a diagnostic log for the zero-size symbol fallback.

Verification notes:

  • CI is still pending on the head commit — not green yet, so not mergeable until checks pass.
  • The retained FindELFPayloadSectionOffsetAndSize wrapper is correctly kept for its build-task/test caller (ArchiveAssemblyHelper.cs), which now transparently gains symbol-based resolution.
  • Re: the PR's open question about deleting decompress-assemblies — that's a reasonable call for maintainers; nothing in this diff blocks either decision.

No blocking correctness issues beyond the unhandled-exception path above.

Generated by Android PR Reviewer for #12104 · 112.5 AIC · ⌖ 18.8 AIC · ⊞ 6.8K
Comment /review to run again

Comment thread tools/assembly-store-reader-mk2/AssemblyStore/Utils.cs Outdated
Comment thread tools/decompress-assemblies/main.cs Outdated
Comment thread tools/decompress-assemblies/main.cs Outdated
Unify the legacy v1 parser with the modern reader, recognize v2 and v3 store layouts and archive names, and decode both XALZ/LZ4 and XAZS/Zstd assemblies. Add a standalone compatibility matrix and run it in CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 55493571-86e2-4326-850e-ea55883aa5d8
@simonrozsival simonrozsival changed the title [tools] Support current assembly stores in inspection tools [tools] Support current and legacy assembly stores Jul 14, 2026
Use MonoAndroidHelper as the ABI source of truth, report unsupported store architectures without throwing, and log when zero-sized ELF symbols fall back to the containing section size.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 55493571-86e2-4326-850e-ea55883aa5d8
simonrozsival added a commit that referenced this pull request Jul 14, 2026
Keep the file-app project removals while incorporating the shared ELF symbol diagnostic changes from the compatibility branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 55493571-86e2-4326-850e-ea55883aa5d8
@simonrozsival

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved in 3bd1dc82e.

@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@simonrozsival simonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label Jul 16, 2026
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 Code review — ⚠️ minor suggestions

Reviewed the assembly-store tooling changes that add current/legacy store support, _assembly_store ELF-symbol detection, unified LZ4/Zstd decompression (AssemblyCompression), and per-arch v1 store reconstruction.

Assessment

Overall this is a solid, well-structured refactor. Highlights:

  • ReadEntryImageData now guards against short reads (nread == 0EndOfStreamException) and returns pooled buffers in finally — a real robustness improvement over the previous unbounded loop.
  • V2 index parsing correctly distinguishes v2 (no ignore byte) from v3/v4 entry sizes, avoiding a mis-parse of the trailing byte.
  • Decompression logic is consolidated into AssemblyCompression and reused by tmt, decompress-assemblies, and the mk2 reader, eliminating three near-identical Zstd copies.
  • Good test coverage: both compression formats, v1 store sets/manifests/APK, and v2/v3 archive names & index layouts.

Comments (all 💡 suggestions, none blocking)

  1. UncompressIfNeeded throws NotSupportedException for all uncompress requests on the stable (non-net11) TFM, even for uncompressed entries — consider passing uncompressed data through instead.
  2. OpenV1 fallback runs while the ZipArchive handle is still open on the same file — possible Windows sharing violation; scope the using narrower.
  3. uncompressedLength from an untrusted header drives a pool Rent up to ~2 GB before validation.

CI

No pipeline checks are reported yet on the head commit (status: pending). Not a blocker for this review — please confirm the Windows compatibility-test leg (added in build-windows-steps.yaml) goes green before merge.

Nice work overall.

Generated by Android PR Reviewer for #12104 · 156.2 AIC · ⌖ 12 AIC · ⊞ 6.8K
Comment /review to run again

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: fe34b69d-7bab-4dd6-904d-dab51648046a
Allow stable-target consumers to request decompression for uncompressed entries, cap decompressed assembly allocations, and release modern archive handles before falling back to the legacy reader. Add stable-target and malformed-header coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: fe34b69d-7bab-4dd6-904d-dab51648046a
@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) July 20, 2026 16:46
@jonathanpeppers
jonathanpeppers merged commit 3065ab6 into main Jul 20, 2026
45 checks passed
@jonathanpeppers
jonathanpeppers deleted the dev/simonrozsival/update-assembly-store-tools branch July 20, 2026 19:51
jonathanpeppers added a commit that referenced this pull request Jul 23, 2026
## Summary

- replace the standalone assembly-store reader and decompressor executable projects with .NET file-based apps owned by repository skills
- expand `read-assembly-store` to invoke its bundled app directly
- add an `extract-android-assemblies` skill for customer APK/AAB investigation and decompilation preparation
- remove the obsolete legacy reader project, launch wrappers, and solution entries while retaining the shared compatibility parser
- build both file apps in CI

## Stack

This PR is stacked on #12104, which provides the shared v1/v2/v3 and LZ4/Zstd compatibility layer. Review this PR as the single commit on top of that branch. It can be retargeted to `main` after #12104 merges.

## File apps

```text
dotnet run --file .github/skills/read-assembly-store/scripts/read-assembly-store.cs -- <input>

dotnet run --file .github/skills/extract-android-assemblies/scripts/extract-android-assemblies.cs -- --output <directory> <input>
```

The extractor handles:

- APK, AAB, raw store, manifest, store base-name, and DLL inputs
- legacy and current assembly stores
- raw, ELF `payload`, and `_assembly_store` wrappers
- historical and current individually packaged assemblies
- LZ4 and Zstd compression
- multiple ABIs and satellite assemblies

Customer inputs remain local. Extraction rejects path traversal, output-name collisions, and overwrites.

## Validation

- both skills pass `skill-creator` validation and package successfully
- both file apps build and run through their CI commands
- shared parser builds for .NET 10 and .NET 11
- 10 assembly-store compatibility tests pass
- byte-for-byte extraction exercised for:
  - current store APKs
  - standalone stores
  - ELF-wrapped individual assemblies
  - current and historical satellite names
  - modern loose individual assemblies

Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants