Bug 29679 - Mono crashes with "Assertion at class.c:5748" when getting custom attributes from corefx contract assembly
Summary: Mono crashes with "Assertion at class.c:5748" when getting custom attributes ...
Alias: None
Product: Runtime
Classification: Mono
Component: JIT ()
Version: unspecified
Hardware: PC Windows
: Normal normal
Target Milestone: ---
Assignee: Zoltan Varga
Depends on:
Reported: 2015-05-02 22:11 UTC by Alexander Köplinger
Modified: 2015-07-28 23:07 UTC (History)
5 users (show)

Is this bug a regression?: ---
Last known good build:

Repro code (51.19 KB, application/x-zip-compressed)
2015-05-02 22:11 UTC, Alexander Köplinger

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Alexander Köplinger 2015-05-02 22:11:52 UTC
Created attachment 11033 [details]
Repro code

Unpack the attached zip and cd into the directory, then do "mcs test.cs" and run it with "mono test.exe".

On Mono, this results in the following crash:

> $ mono test.exe 
> System.Console, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
> ReflectionOnlyAssemblyResolve: System.Runtime, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
> Can't find custom attr constructor image: /home/alexander/Desktop/System.Console.dll mtoken: 0x0a000003
> * Assertion at class.c:5748, condition `!mono_loader_get_last_error ()' not met
> Stacktrace:
> * Assertion at class.c:5748, condition `!mono_loader_get_last_error ()' not met
> Aborted (core dumped)

Expected output from MS.NET

> System.Console, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
> ReflectionOnlyAssemblyResolve: System.Runtime, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
> attr:[System.Reflection.AssemblyInformationalVersionAttribute("4.6.22809.00 built by: PROJECTK")]

This is currently blocking the corefx build with the open-sourced MSBuild on Unix.
Comment 1 Zoltan Varga 2015-05-26 18:04:06 UTC
This happens because the 'DebuggingModes' type is encoded in IL as:
class System.Diagnostics.DebuggableAttribute/DebuggingModes modes
in the System.Runtime assembly, even through its an enum. It should be encoded as:
valuetype System.Diagnostics.DebuggableAttribute/DebuggingModes modes
The System.Console assembly encodes it correctly.
Comment 2 Alexander Köplinger 2015-05-26 18:37:41 UTC
@Zoltan: there's something scary going on here. I checked with ikdasm on Linux and it indeed confirms what you say:

>   .method public hidebysig specialname rtspecialname 
>          instance void  .ctor(class >System.Diagnostics.DebuggableAttribute/DebuggingModes modes) cil managed

However, opening the assembly in ilasm, ILSpy and dotpeek on Windows results in this:

> .method public hidebysig specialname rtspecialname 
>        instance void  .ctor(valuetype System.Diagnostics.DebuggableAttribute/DebuggingModes modes) cil managed

Note that it reports **valuetype** as expected.

So whom do we trust now?
Comment 3 Zoltan Varga 2015-05-26 18:41:03 UTC
ikdasm returns the actual metadata encoding, no idea what the windows tool return.
Comment 4 Alexander Köplinger 2015-05-26 19:33:33 UTC
I think ikdasm is wrong here, or at least it doesn't really reflect what is happening under the hood.

This commit to ikvm looks related: https://github.com/gluck/ikvm/commit/842a86fb686640338d3c765adf1da56e5b8044c1
Comment 5 Alexander Köplinger 2015-05-26 19:43:20 UTC
monodis seems to just crash:

>$ monodis System.Runtime.dll 
>.assembly 'System.Runtime'
>Could not load signature of System.Diagnostics.DebuggableAttribute:.ctor due to: Could not parse type argument 0 on method signature
>Segmentation fault (core dumped)

I'm curious if there's really something wrong in the IL (in which case I'll open a bug at corefx) or if Mono just isn't handling this edge case?
Comment 6 Zoltan Varga 2015-05-26 19:53:41 UTC
So the problem seems to be that the mono runtime special cases corlib in a few places so it doesn't think that types inheriting System.Runtime's ValueType type are valuetypes.
Comment 7 Zoltan Varga 2015-05-29 10:06:17 UTC
So the problem is that System.Console.dll is linked against System.Runtime, and the runtime loads the System.Runtime.dll in the current directory, instead of the System.Runtime.dll from the mono installation. Where is that System.Runtime.dll coming from ?
Comment 8 Zoltan Varga 2015-05-29 10:09:21 UTC
So moving System.Runtime.dll into another dir, and using mono master 4183c9cbc51a869711f709b1cfef832e14ab4943 works.
Comment 9 Marcin Cieślak 2015-06-13 14:52:24 UTC
Where is this System.Runtime.dll coming from? When I use System.Runtime.dll from my mono master or from CoreCLR it works.
Comment 10 Alexander Köplinger 2015-06-13 14:58:17 UTC
@Marcin it's coming from the corefx packages, i.e. D:\Dev\corefx\packages\System.Runtime\4.0.20-beta-22927\ref\any\System.Runtime.dll on my machine.

Note that I'm investigating another fix so that MSBuild uses Cecil to read the custom attribute instead of using reflection which would make this issue not being hit.
Comment 11 Zoltan Varga 2015-06-13 15:38:26 UTC
System.Runtime.dll should contain type forwarders to mscorlib etc, this version contain dummy type/method definitions instead.
Comment 12 Miguel de Icaza [MSFT] 2015-06-13 21:16:38 UTC
IKVM.Reflection is probably better than Mono.Cecil.

If all you want is to read metadata, the API is almost identical (except for the initialization) to Reflection.Emit and is very light weight.
Comment 13 Marcin Cieślak 2015-06-14 19:58:53 UTC
https://github.com/mono/mono/pull/1874 should fix that problem.
Comment 14 Marcin Cieślak 2015-06-14 20:05:39 UTC
Constructor signature is encoded as:

0x06  0x20  0x01  0x01  0x11  0x84  0x50

              `-------------  one parameter
                    `--------------- return is void
                          `--------------- valuetype of                   
                                 `-------- 0x114 DebuggingModes type

But because valuetypes are kind of sub-classes, it might be possible
that disassemblers treat them as classes. Actually the problem here
is that DebuggingModes says it's a "class" and Mono is strict enough
not to allow to put "class" where "valuetype" is required.
Comment 15 Alexander Köplinger 2015-06-14 20:28:54 UTC
@Marcin: Thanks for looking into it! I can confirm it fixes the runtime assert, though it doesn't fully work yet.

The if clause for "a.AttributeType.Equals (typeof (AssemblyInformationalVersionAttribute)" doesn't appear to be hit. If I change it to "a.AttributeType.Name == "AssemblyInformationalVersionAttribute"" then it crashes with the following exception:

>Unhandled Exception:
>System.TypeLoadException: Could not load type 'System.Reflection.AssemblyInformationalVersionAttribute' from assembly 'System.Runtime, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
>  at (wrapper managed-to-native) System.Reflection.CustomAttributeData:ResolveArgumentsInternal (System.Reflection.ConstructorInfo,System.Reflection.Assembly,intptr,uint,object[]&,object[]&)
>  at System.Reflection.CustomAttributeData.ResolveArguments () [0x0000c] in /home/alexander/dev/mono/mcs/class/corlib/System.Reflection/CustomAttributeData.cs:76 
>  at System.Reflection.CustomAttributeData.ToString () [0x00000] in /home/alexander/dev/mono/mcs/class/corlib/System.Reflection/CustomAttributeData.cs:140 
> ...
Comment 16 Marcin Cieślak 2015-06-14 21:03:24 UTC
It seems to work if you move the CoreFX dlls out of the way.


> var asm = Assembly.ReflectionOnlyLoadFrom (Path.GetFullPath ("../System.Console.dll"));

This gives the output (for the "a.AttributeType.Equals (typeof
(AssemblyInformationalVersionAttribute)" variant):

System.Console, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
ReflectionOnlyAssemblyResolve: System.Runtime, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
ReflectionOnlyAssemblyResolve: System.Resources.ResourceManager, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
attr:[System.Reflection.AssemblyInformationalVersionAttribute(" built by: DCI-WIN-FBLD-13-dotnet-bot")]

if (a.AttributeType.Name == "AssemblyInformationalVersionAttribute") variant
gives the same output.
Comment 17 Marcin Cieślak 2015-06-22 14:40:43 UTC
Zoltan: do you think my fix in https://github.com/mono/mono/pull/1874 is correct?
Comment 18 Zoltan Varga 2015-06-22 15:27:33 UTC
So the problem is that the assembly is linked against System.Runtime.dll, which should contain type forwarders to the real types in mscorlib. Instead, there is a System.Runtime.dll in the current directory, which contains dummy types. Mono loads this local version, so the types in the assembly will inherit from the dummy ValueType class, not the real ValueType class in mscorlib, so they are not treated as valuetypes as mono, which leads to the loading error. I think this is the correct behavior.
Comment 19 Marcin Cieślak 2015-06-22 15:43:09 UTC
Without the patch, you will end up with an assertion error - I've had the same when just using 'monodis' on mscorelib.dll. The original problem (not the later one stated by Alexander) was the assertion error, because Mono runtime could not accept something defined as class (token 0x12) to be used as valuetype (0x11).

I'd love to have this patch merged, working on the next step will be to improve generics support - because Mono is unable to understand many methods with generic which are contained in the CoreCLR mscorlib.dll - this is https://bugzilla.xamarin.com/show_bug.cgi?id=31244.
Comment 20 Alexander Köplinger 2015-06-23 05:40:51 UTC
Thanks for applying the patch, it seems to solve the problem if I move System.Runtime.dll out of the folder (which isn't required on MS.NET, but I'm happy to ignore this for now as it's sufficient for the msbuild/corefx on Mono work)
Comment 21 Alexander Köplinger 2015-06-23 06:06:07 UTC
Zoltan: can this be ported to the Mono 4.2 branch?
Comment 22 Zoltan Varga 2015-06-23 10:34:02 UTC
Comment 23 Hin-Tak Leung 2015-07-28 22:40:52 UTC
I also have monodis crashing (comment 5) with mono - judging from comment 21 the fix is in master and 4.2 but not in any of the other branches?
Comment 24 Zoltan Varga 2015-07-28 23:07:14 UTC