[Trimming] Fix startup crash when TypeMapAssemblyTarget attribute survives but target assembly is fully trimmed#130589
[Trimming] Fix startup crash when TypeMapAssemblyTarget attribute survives but target assembly is fully trimmed#130589AaronRobinsonMSFT with Copilot wants to merge 7 commits into
Conversation
…no surviving entries Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
….cs and assemblynative.cpp Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
|
@copilot No changes should be done to CoreCLR itself. This is entirely a trimming issue. When the trimmer decides to remove a type based on the typemap reference algorithm, it should also remove the typemap attributes that reference it. |
Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
Reverted all changes to
Reverted all changes to |
|
Tagging subscribers to this area: @agocke, @dotnet/illink |
There was a problem hiding this comment.
Pull request overview
This PR updates ILLink’s type map handling to avoid keeping TypeMapAssemblyTargetAttribute<TGroup> metadata that can reference assemblies which end up not being present after trimming, and adds a new regression test case in the linker test suite.
Changes:
- Update
TypeMapHandlerto defer markingTypeMapAssemblyTargetattributes until the referenced target assembly is known to be kept (or drop the attribute if the assembly can’t be resolved in linker input). - Add a new linker test plus two dependency assemblies to cover the “all TypeMap entries trimmed away” scenario.
Show a summary per file
| File | Description |
|---|---|
| src/tools/illink/src/linker/Linker/TypeMapHandler.cs | Adds deferral/flush mechanism for TypeMapAssemblyTarget marking, keyed by resolved target assembly. |
| src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMapAssemblyTargetRemovedWhenAllEntriesTrimmed.cs | New test case intended to validate removal of a dangling TypeMapAssemblyTarget attribute. |
| src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/TypeMapAllConditionalGroupDep.cs | New dependency assembly containing a group marker type for the test. |
| src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/TypeMapAllConditionalEntriesDep.cs | New dependency assembly containing only conditional TypeMap entries. |
Copilot's findings
- Files reviewed: 4/4 changed files
- Comments generated: 1
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| if (_context.Annotations.IsMarked(targetAssembly)) | ||
| { | ||
| // Target assembly is already in the output because it has surviving TypeMap entries. | ||
| MarkTypeMapAttribute(entry, new DependencyInfo(DependencyKind.TypeMapAssemblyTarget, callingMethod)); | ||
| } |
… MarkStep Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
Updated. The current PR description now reflects the actual changes: Fix — ILLink
Test
(No CoreCLR changes — the previous |
…ttribute, update comment Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com>
In trimmed CoreCLR apps, a
TypeMapAssemblyTargetattribute could survive trimming even when its named assembly was fully trimmed (all its TypeMap entries were conditional on trim targets that were never marked). At runtime,TypeMapLazyDictionaryunconditionally callsAssembly.Loadfor every surviving attribute, crashing withFileNotFoundException.Changes
Fix — ILLink
TypeMapHandler.csTypeMapAssemblyTargetattributes are now only marked when their target assembly is also marked (has surviving entries or is otherwise kept)._pendingAssemblyTargetsByAssembly: when a group is seen but the target assembly is not yet marked, the attribute is deferred here rather than immediately marked.TriggerPendingAssemblyTargets()isinternaland called only fromMarkStep.MarkAssemblywhenever an assembly is first marked — ensuring deferred attributes are flushed regardless of assembly visitation order.TypeMapAttribute, but the added complexity is not justified for a narrow case.Fix —
MarkStep.csMarkAssemblycalls_typeMapHandler.TriggerPendingAssemblyTargets(assembly)to flush any pendingTypeMapAssemblyTargetattributes for the assembly being marked, regardless of the order in which TypeMap entries are visited.Test
TypeMapAssemblyTargetRemovedWhenAllEntriesTrimmedwith two dependency assemblies: a shared group-type assembly, and aconditional.dllwith only conditional TypeMap entries (trim target never marked). Verifies via[RemovedAttributeInAssembly]and[RemovedAssembly]that theTypeMapAssemblyTargetattribute and the conditional assembly are both removed from the linked output.