Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ILLink: argument exception in Cecil when writing assembly #93797

Closed
vitek-karas opened this issue Oct 20, 2023 · 8 comments · Fixed by #103844
Closed

ILLink: argument exception in Cecil when writing assembly #93797

vitek-karas opened this issue Oct 20, 2023 · 8 comments · Fixed by #103844
Assignees
Labels
area-Tools-ILLink .NET linker development as well as trimming analyzers in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@vitek-karas
Copy link
Member

Repro:

dotnet new console

app.csproj:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PublishTrimmed>true</PublishTrimmed>
        <WarningsAsErrors>false</WarningsAsErrors>
        <NoWarn>NU1605;NU1603;NU1701</NoWarn>
    </PropertyGroup>

    <ItemGroup>
        <TrimmerRootAssembly Include="Syncfusion.Maui.Gauges" />

        <PackageReference Include="Syncfusion.Maui.Gauges" Version="20.4.40" />
    </ItemGroup>
</Project>

dotnet publish

Stack trace from the output:

   ---> System.ArgumentException: Member 'Syncfusion.Maui.Graphics.Internals.IDrawableView' is declared in another modu
  le and needs to be imported
     at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
     at Mono.Cecil.SignatureWriter.MakeTypeDefOrRefCodedRID(TypeReference type)
     at Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
     at Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
     at Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
     at Mono.Cecil.MetadataBuilder.GetTypeSpecSignature(TypeReference type)
     at Mono.Cecil.MetadataBuilder.GetTypeSpecToken(TypeReference type)
     at Mono.Cecil.MetadataBuilder.GetTypeToken(TypeReference type)
     at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
     at Mono.Cecil.MetadataBuilder.AddTypes()
     at Mono.Cecil.MetadataBuilder.BuildTypes()
     at Mono.Cecil.MetadataBuilder.BuildModule()
     at Mono.Cecil.MetadataBuilder.BuildMetadata()
     at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__2_0(MetadataBuilder builder, MetadataReader _)
     at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
     at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
     at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
     at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
     at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writ
  erParameters)

/cc @LakshanF

@vitek-karas vitek-karas added the area-Tools-ILLink .NET linker development as well as trimming analyzers label Oct 20, 2023
@ghost
Copy link

ghost commented Oct 20, 2023

Tagging subscribers to this area: @agocke, @sbomer, @vitek-karas
See info in area-owners.md if you want to be subscribed.

Issue Details

Repro:

dotnet new console

app.csproj:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PublishTrimmed>true</PublishTrimmed>
        <WarningsAsErrors>false</WarningsAsErrors>
        <NoWarn>NU1605;NU1603;NU1701</NoWarn>
    </PropertyGroup>

    <ItemGroup>
        <TrimmerRootAssembly Include="Syncfusion.Maui.Gauges" />

        <PackageReference Include="Syncfusion.Maui.Gauges" Version="20.4.40" />
    </ItemGroup>
</Project>

dotnet publish

Stack trace from the output:

   ---> System.ArgumentException: Member 'Syncfusion.Maui.Graphics.Internals.IDrawableView' is declared in another modu
  le and needs to be imported
     at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
     at Mono.Cecil.SignatureWriter.MakeTypeDefOrRefCodedRID(TypeReference type)
     at Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
     at Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
     at Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
     at Mono.Cecil.MetadataBuilder.GetTypeSpecSignature(TypeReference type)
     at Mono.Cecil.MetadataBuilder.GetTypeSpecToken(TypeReference type)
     at Mono.Cecil.MetadataBuilder.GetTypeToken(TypeReference type)
     at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
     at Mono.Cecil.MetadataBuilder.AddTypes()
     at Mono.Cecil.MetadataBuilder.BuildTypes()
     at Mono.Cecil.MetadataBuilder.BuildModule()
     at Mono.Cecil.MetadataBuilder.BuildMetadata()
     at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__2_0(MetadataBuilder builder, MetadataReader _)
     at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
     at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
     at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
     at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
     at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writ
  erParameters)

/cc @LakshanF

Author: vitek-karas
Assignees: -
Labels:

area-Tools-ILLink

Milestone: -

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Oct 20, 2023
@vitek-karas
Copy link
Member Author

Similar failure on a different package - worth validating on the same fix:

app.csproj:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PublishTrimmed>true</PublishTrimmed>
        <WarningsAsErrors>false</WarningsAsErrors>
        <NoWarn>NU1605;NU1603;NU1701</NoWarn>

        <TargetPackageName>NewPlatform.Flexberry.ORM.ODataService</TargetPackageName>
        <TargetPackageVersion>7.0.0</TargetPackageVersion>
        <TargetAssemblyName></TargetAssemblyName>

        <TargetAssemblyName Condition="'$(TargetAssemblyName)' == ''">$(TargetPackageName)</TargetAssemblyName>
    </PropertyGroup>

    <ItemGroup>
        <TrimmerRootAssembly Include="$(TargetAssemblyName)" />

        <PackageReference Include="$(TargetPackageName)" Version="$(TargetPackageVersion)" />
    </ItemGroup>

    <Target Name="ConfigureTrimming"
            BeforeTargets="PrepareForILLink">
        <ItemGroup>
          <ManagedAssemblyToLink Condition="'%(Filename)' == '$(TargetAssemblyName)'">
              <TrimmerSingleWarn>false</TrimmerSingleWarn>
          </ManagedAssemblyToLink>
        </ItemGroup>
    </Target>
</Project>

Stack trace:

  Fatal error in IL Linker
  Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1011: Failed to write 'obj\Release\net8.0
  \win-x64\linked\Microsoft.AspNetCore.OData.dll'.
   ---> System.ArgumentException: Member 'Microsoft.AspNet.OData.Batch.ODataBatchMiddleware' is declared in another mod
  ule and needs to be imported
     at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider provider)
     at Mono.Cecil.SignatureWriter.MakeTypeDefOrRefCodedRID(TypeReference type)
     at Mono.Cecil.SignatureWriter.WriteTypeSignature(TypeReference type)
     at Mono.Cecil.SignatureWriter.WriteGenericInstanceSignature(IGenericInstance instance)
     at Mono.Cecil.MetadataBuilder.GetMethodSpecSignature(MethodSpecification method_spec)
     at Mono.Cecil.MetadataBuilder.CreateMethodSpecRow(MethodSpecification method_spec)
   ...
     at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writ
  erParameters)

@agocke agocke added this to AppModel Nov 28, 2023
@agocke agocke added this to the Future milestone Feb 12, 2024
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Feb 12, 2024
@danmoseley
Copy link
Member

is the bug here that it should not be dumping stack? or that it should not be failing? I was going to open a bug for the former, perhaps this covers it. dumping stack when it's not a bug on us is ugly.

ILLink : error IL1011: Failed to write 'obj\Debug\net8.0\linked\System.Private.CoreLib.dll'. [D:\a\aspire-samples\aspire-samples\samples\Metrics\MetricsApp.Client\MetricsApp.Client.csproj]
  Fatal error in IL Linker
  Unhandled exception. Mono.Linker.LinkerFatalErrorException: ILLink: error IL1011: Failed to write 'obj\Debug\net8.0\linked\System.Private.CoreLib.dll'.
   ---> System.IO.IOException: The process cannot access the file 'D:\a\aspire-samples\aspire-samples\samples\Metrics\MetricsApp.Client\obj\Debug\net8.0\linked\System.Private.CoreLib.dll' because it is being used by another process.
     at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
     at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
     at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
     at System.IO.Strategies.FileStreamHelpers.ChooseStrategyCore(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
     at Mono.Cecil.ModuleDefinition.GetFileStream(String fileName, FileMode mode, FileAccess access, FileShare share)
     at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters parameters)
     at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writerParameters)
     --- End of inner exception stack trace ---
     at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory, WriterParameters writerParameters)
     at Mono.Linker.Steps.OutputStep.WriteAssembly(AssemblyDefinition assembly, String directory)
     at Mono.Linker.Steps.OutputStep.OutputAssembly(AssemblyDefinition assembly)
     at Mono.Linker.Steps.OutputStep.ProcessAssembly(AssemblyDefinition assembly)
     at Mono.Linker.Steps.BaseStep.Process(LinkContext context)
     at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
     at Mono.Linker.Pipeline.Process(LinkContext context)
     at Mono.Linker.Driver.Run(ILogger customLogger)
     at Mono.Linker.Driver.Main(String[] args)

@sbomer
Copy link
Member

sbomer commented Jun 17, 2024

Confirmed the first repro provided. Here's what happens:

  • Syncfusion.Maui.Core.dll defines a type SfDrawableViewHandler derived from ViewHandler<IDrawableView, object>.
  • ViewHandler is defined in Microsoft.Maui, which is not referenced in the console app.
  • When marking SfDrawableViewHandler we fail to resolve the base type so we don't mark IDrawableView (which is also defined in Syncfusion.Maui.Core.dll).
  • SweepStep detaches all types from their modules, then never adds back IDrawableView because it wasn't marked.
  • When writing the assembly, we try to write a typespec for ViewHandler<IDrawableView, object>, but at this point it fails because IDrawableView's Module is null.

For comparison, Native AOT fails on the same input with:

EXEC : error : Failed to load assembly 'Microsoft.Maui.Controls'
    Internal.TypeSystem.TypeSystemException+FileNotFoundException: Failed to load assembly 'Microsoft.Maui.Controls'
       at Internal.TypeSystem.ThrowHelper.ThrowFileNotFoundException(ExceptionStringID, String) + 0x30
       at Internal.TypeSystem.ResolutionFailure.Throw() + 0xfd
       at Internal.TypeSystem.Ecma.EcmaType.InitializeBaseType() + 0x1da
       at ILCompiler.DependencyAnalysis.TypeMetadataNode.GetStaticDependencies(NodeFactory) + 0x186
       at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependenciesImpl(DependencyNodeCore`1) + 0x3f
       at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependencies(DependencyNodeCore`1) + 0x33
       at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ProcessMarkStack() + 0xff
       at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ComputeMarkedNodes() + 0x4f
       at ILCompiler.ILScanner.ILCompiler.IILScanner.Scan() + 0x19
       at ILCompiler.Program.<Run>g__RunScanner|4_0(Program.<>c__DisplayClass4_0&) + 0x1fa
       at ILCompiler.Program.Run() + 0x29cc
       at ILCompiler.ILCompilerRootCommand.<>c__DisplayClass240_0.<.ctor>b__0(ParseResult result) + 0x35a

@sbomer
Copy link
Member

sbomer commented Jun 21, 2024

The fundamental problem is that the input was missing a referenced assembly. This caused some inconsistent marking for generics, leading to downstream failures. I can see two solutions to this:

  1. Make a best-effort attempt to be resilient to the missing reference. In this particular case that means marking the generic arguments even if we couldn't resolve the generic type definition.
  2. Fail earlier and more predictably, like how Native AOT does it. (Whether it prints a stacktrace or logs an error is a separate question).

I opened #103831 for 2, but I don't think we should do that in .NET 9 so I am leaning towards 1 for a .NET 9 fix.

@jkotas
Copy link
Member

jkotas commented Jun 21, 2024

Fail earlier and more predictably, like how Native AOT does it.

NativeAOT tries to be resilient against missing assemblies where possible. It is not 100% resilient, but it covers a lot of the common situations. We have actually done work to make native AOT more resilient based on customer reports. There are a lot of assemblies and packages with dangling references in the wild.

cc @MichalStrehovsky

@sbomer
Copy link
Member

sbomer commented Jun 21, 2024

Good to know, thanks for the context. Would the Native AOT error in #93797 (comment) be considered a bug?

@jkotas
Copy link
Member

jkotas commented Jun 21, 2024

I think so. (It would not be must-fix bug - we would be ok with won't fixing it if the fix is too complicated or invasive.)

@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Jun 21, 2024
@sbomer sbomer closed this as completed in 3a5a7da Jun 24, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Jul 25, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Tools-ILLink .NET linker development as well as trimming analyzers in-pr There is an active PR which will close this issue when it is merged
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants