-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix missing assemblyref for typeref only kept for debug info in illink (
#87575) Fixes #86462 by walking debug info to discover typerefs in the assembly that are only preserved due to debug info. In this case the assembly has the 'save' action, so the reference to the typeref in the debug info is not swept. This means that the presence of the typeref in the final output depends on whether we are linking the PDB. Walking the typeref will preserve the assemblyref that it refers to, fixing the issue. The fix also needs to walk up the parent import scopes, discovered by reproducing the issue in our test infra. The behavior needs to depend on whether we are linking debug symbols, otherwise we will keep the assemblyref (but not the typeref that uses it) when PDBs are present, and the output should not depend on the presence of PDBs. `AssemblyOnlyUsedByUsingSaveAction` tests this case - see comments in there for more detail. This includes some unrelated test infra changes (supporting multiple additional compiler arguments) which were useful for iterating on this, even though they aren't necessary in the final version of the testcases.
- Loading branch information
Showing
36 changed files
with
241 additions
and
82 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
42 changes: 42 additions & 0 deletions
42
...tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveAction.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using Mono.Linker.Tests.Cases.Expectations.Assertions; | ||
using Mono.Linker.Tests.Cases.Expectations.Helpers; | ||
using Mono.Linker.Tests.Cases.Expectations.Metadata; | ||
using Mono.Linker.Tests.Cases.References.Dependencies; | ||
|
||
namespace Mono.Linker.Tests.Cases.References | ||
{ | ||
/// <summary> | ||
/// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted. | ||
/// With the assembly action of `save`, we remove unused assembly references from the assembly and rewrite it. | ||
/// When cecil writes the assembly, the unused typeref is not written out. | ||
/// </summary> | ||
|
||
// Add a custom step which sets the assembly action of the test to "save" | ||
[SetupCompileBefore ("SetSaveAction.dll", new[] { "Dependencies/CustomMarkHandlerSaveAssembly.cs" }, | ||
new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] | ||
[SetupLinkerArgument ("--custom-step", "CustomMarkHandlerSaveAssembly,SetSaveAction.dll")] | ||
|
||
// When csc is used, `saved.dll` will have a reference to `library.dll` | ||
[SetupCompileBefore ("library.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Lib.cs" })] | ||
[SetupCompileBefore ("saved.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs" }, | ||
// Even though this testcase doesn't link symbols, tell the compiler to produce symbols to confirm that the behavior | ||
// isn't affected by the presence of symbols when not passing '-b'. | ||
new[] { "library.dll" }, additionalArguments: new string[] { "/debug:portable" }, compilerToUse: "csc")] | ||
|
||
// Here to assert that the test is setup correctly to preserve unused code in the saved assembly. This is an important aspect of the bug | ||
[KeptMemberInAssembly ("saved.dll", typeof (AssemblyOnlyUsedByUsing_UnusedUsing), "Unused()")] | ||
|
||
// The library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked | ||
[RemovedAssembly ("library.dll")] | ||
// The `save` action results in the reference to System.Runtime being resolved into a reference directly to System.Private.CoreLib. | ||
// The reference to `library` is removed. | ||
[KeptReferencesInAssembly ("saved.dll", new[] { "System.Private.CoreLib" })] | ||
public class AssemblyOnlyUsedByUsingSaveAction | ||
{ | ||
public static void Main () | ||
{ | ||
// Use something to keep the reference at compile time | ||
AssemblyOnlyUsedByUsing_UnusedUsing.UsedToKeepReference (); | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...k/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveActionWithSymbols.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using Mono.Linker.Tests.Cases.Expectations.Assertions; | ||
using Mono.Linker.Tests.Cases.Expectations.Helpers; | ||
using Mono.Linker.Tests.Cases.Expectations.Metadata; | ||
using Mono.Linker.Tests.Cases.References.Dependencies; | ||
|
||
namespace Mono.Linker.Tests.Cases.References | ||
{ | ||
/// <summary> | ||
/// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted. | ||
/// With the assembly action of `save`, we remove unused assembly references from the assembly and rewrite it, preserving all methods. | ||
/// When debug symbols are present for the `save` assembly, we do not trim debug symbols, so cecil keeps all type references in the | ||
/// save assembly that are referenced by the debug info. This includes the unused typeref, so the assemblyref referenced by the typeref | ||
/// must also be preserved. | ||
/// </summary> | ||
|
||
// Add a custom step which sets the assembly action of the test to "save" | ||
[SetupCompileBefore ("SetSaveAction_Symbols.dll", new[] { "Dependencies/CustomMarkHandlerSaveAssembly.cs" }, | ||
new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] | ||
[SetupLinkerArgument ("--custom-step", "CustomMarkHandlerSaveAssembly,SetSaveAction_Symbols.dll")] | ||
|
||
// When csc is used, `saved.dll` will have a reference to `library.dll` | ||
[SetupCompileBefore ("library.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Lib.cs" })] | ||
[SetupCompileBefore ("saved.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs" }, | ||
new[] { "library.dll" }, additionalArguments: new string[] { "/debug:portable" }, compilerToUse: "csc")] | ||
|
||
// Here to assert that the test is setup correctly to preserve unused code in the saved assembly. This is an important aspect of the bug | ||
[KeptMemberInAssembly ("saved.dll", typeof (AssemblyOnlyUsedByUsing_UnusedUsing), "Unused()")] | ||
|
||
// The library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked | ||
[RemovedAssembly ("library.dll")] | ||
// The `save` action results in the reference to System.Runtime being resolved into a reference directly to System.Private.CoreLib. | ||
// The reference to `library` is kept, because it is referenced from a typeref that is referenced from the debug info. | ||
[KeptReferencesInAssembly ("saved.dll", new[] { "System.Private.CoreLib", "library" })] | ||
|
||
// Linking debug symbols is required for cecil not to remove the typeref from the assembly, because it is only referenced from the debug info. | ||
[SetupLinkerLinkSymbols ("true")] | ||
public class AssemblyOnlyUsedByUsingSaveActionWithSymbols | ||
{ | ||
public static void Main () | ||
{ | ||
// Use something to keep the reference at compile time | ||
AssemblyOnlyUsedByUsing_UnusedUsing.UsedToKeepReference (); | ||
} | ||
} | ||
} |
This file contains 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
This file contains 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
15 changes: 15 additions & 0 deletions
15
...ink/test/Mono.Linker.Tests.Cases/References/Dependencies/CustomMarkHandlerSaveAssembly.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
using Mono.Cecil; | ||
using Mono.Linker; | ||
using Mono.Linker.Steps; | ||
|
||
public class CustomMarkHandlerSaveAssembly : IMarkHandler | ||
{ | ||
public void Initialize (LinkContext context, MarkContext markContext) | ||
{ | ||
markContext.RegisterMarkAssemblyAction (assembly => { | ||
if (assembly.Name.Name == "saved") | ||
context.Annotations.SetAction (assembly, AssemblyAction.Save); | ||
}); | ||
} | ||
} |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Oops, something went wrong.