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

Unresolved assembly references error when decompiling a netstandard2 dll included with .NET Framework 4.6.1 dll #2054

Open
mmusu3 opened this issue Jul 4, 2020 · 6 comments
Assignees
Labels
Bug C# Decompiler The decompiler engine itself

Comments

@mmusu3
Copy link

mmusu3 commented Jul 4, 2020

Input code

UnresolvedRefsTest.zip
Open NetStandard2Lib.dll Class1 in ILSpy

Erroneous output

ILSpy displays a warning that says some assembly references could not be resolved automatically (I can't seem to copy the text).
The decompiler does not produce the correct output in these circumstances.

private void Test(IEnumerable<string> strings)
{
	Console.Write(Enumerable.Sum<string>(strings, (Func<string, int>)((string s) => s.Length)));
}

Expected output

This is the source code for the test method.

void Test(IEnumerable<string> strings)
{
    int length = strings.Sum(s => s.Length);
    Console.Write(length);
}

Details

  • Product in use: ILSpy VS extension. I have also had the issue decompiling another whole project using the decompiler library.
  • Version in use: 6.0.0.5830-rc1
  • Other info: Does not occur when decompiling the NetStandard2Lib.dll when isolated from the other dlls.
@siegfriedpammer siegfriedpammer added this to the v6.0 milestone Jul 4, 2020
@siegfriedpammer siegfriedpammer added Bug C# Decompiler The decompiler engine itself labels Jul 4, 2020
@siegfriedpammer siegfriedpammer self-assigned this Jul 4, 2020
@siegfriedpammer
Copy link
Member

The reason is that the netstandard.dll included with the project seems to be broken, so ILSpy gets confused.

@mmusu3
Copy link
Author

mmusu3 commented Jul 4, 2020

This issue started happening after commit 5f27fd9
The issue seems to go away if I comment out the lines at:

foreach (var directory in directories) {
dotNetCorePathFinder.AddSearchDirectory(directory);
}

and
packageBasePaths.Add(basePath);

but I'm sure you can provide a better fix.

@siegfriedpammer
Copy link
Member

Well... I don't think this is a reasonable fix, because in general it is better to use the assemblies next to the assembly you are trying to decompile. The problem in this case is that some assemblies seem to be missing (so some type forwarders including System.Linq.Enumerable cannot be resolved correctly).

@siegfriedpammer
Copy link
Member

How did you compile the list of assemblies provided in the zip file? When loading all assemblies provided in the zip file in the same assembly list. The extension method System.Linq.Enumerable.Sum cannot be found. From the netstandard.dll found in the zip file, I have to deduce that System.Core.dll is missing. Before implementing a fix I would like to understand how the binaries you sent were generated/collected. Thanks!

@mmusu3
Copy link
Author

mmusu3 commented Jul 5, 2020

UnresolvedRefsProj.zip
Build the solution and open the bin folder in the NetFx461Lib project. .NET 4.6.1 is listed as usable with netstandard2 but is not recommended for use with it due to issues as described in the table footnote here https://docs.microsoft.com/en-us/dotnet/standard/net-standard
However some projects use it anyway like one that I am decompiling. The projects and binaries provided here though are just a minimal reproduction of the issue.

@siegfriedpammer siegfriedpammer removed this from the v6.0 milestone Jul 6, 2020
@siegfriedpammer
Copy link
Member

Summarizing my findings, so they don't get lost:

Everything works when decompiling NetFx461Lib.dll, because there we fall back to the GAC and load the correct System.Core.dll.
However, when decompiling the NetStandard2Lib.dll we end up doing the following:

In general, we prefer assemblies located in the same folder as the assembly being decompiled over other locations, this is what 5f27fd9 implements.
We now want to decompile a .NET Standard 2.0 assembly next to .NET 4.6.x assemblies:

  1. We load NetStandard2Lib.dll and look at its references: netstandard, Version=2.0
  2. We load netstandard.dll: We use the version located in the current directory as stated above, because we trust the user. (Note: it belongs to .NET 4.6.1 and not .NET Standard 2.0)
  3. We then try to resolve all the type forwarders defined: Most of the assemblies are found in the current directory, so everything seems fine.
  4. However: the loaded netstandard.dll (compatible with .NET 4.6.1) tells us System.Linq.Enumerable is located in System.Core.dll, however there is no System.Core.dll in the current directory. ILSpy then tries to load the assembly from the .NET Core framework directories, most of the time this is the correct choice.
  5. So we load System.Core.dll from C:\Program Files\dotnet\sdk\<some 2.x version>, however it again only contains type forwarder that tell us System.Linq.Enumerable is defined in netstandard.dll (this time it refers to the one located in C:\Program Files\dotnet\sdk\<some 2.x version>, unfortunately we already resolved netstandard.dll so our resolver stops in order to break out of loops in the reference graph.

The result is that the decompiler type system does not contain a definition of System.Linq.Enumerable although it seems all references were resolved properly.

There is no easy fix for this. A workaround would be isolating NetStandard2Lib.dll in a separate directory so ILSpy does not get confused.
The part about ILSpy not showing a resolver error is recorded in #2036. We would have to implement some more sophisticated algorithm that tries to infer the correct target framework from all immediate references and detects that this .netstandard2.0 DLL should be treated as .NET Framework 4.6.1 assembly (which would then load System.Core.dll from the GAC).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug C# Decompiler The decompiler engine itself
Projects
None yet
Development

No branches or pull requests

2 participants