Bug 13488 - Could not AOT the assembly - mono_loader_get_last_error
Summary: Could not AOT the assembly - mono_loader_get_last_error
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: 6.3.x
Hardware: PC Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
Depends on:
Reported: 2013-07-25 17:38 UTC by Allie Miller
Modified: 2013-08-13 14:22 UTC (History)
5 users (show)

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

Error Log from Case #42140 (44.24 KB, application/octet-stream)
2013-07-25 17:38 UTC, Allie Miller

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 Developer Community or GitHub 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 Allie Miller 2013-07-25 17:38:44 UTC
Created attachment 4442 [details]
Error Log from Case #42140

=== Xamarin Studio ===

Version 4.0.10 (build 7)
Installation UUID: c1fa1bb5-2305-4273-8a26-9ded2092801a
Mono 3.2.0 ((no/7c7fcc7)
GTK 2.24.20
GTK# (
Package version: 302000000

=== Apple Developer Tools ===

Xcode 4.6.2 (2067.2)
Build 4H1003

=== Xamarin.Mac ===

Xamarin.Mac: Not Installed

When attempting to compile for an iOS device, the following issue occurs: 

* Assertion at ../../../../../mono/mono/metadata/class.c:5545, condition `!mono_loader_get_last_error ()' not met

error MT3001: Could not AOT the assembly '/Users/ed/build/ProxyCompanionApps/MobileMaster/MobileMasterAppIOS/obj/iPhone/Debug/mtouch-cache/Build/WebSocket4Net.MonoTouch.dll'
at MonoTouch.AOTTask.Build () [0x00000] in <filename unknown>:0
at MonoTouch.BuildTask.Execute () [0x00000] in <filename unknown>:0
at MonoTouch.Application.<Compile>m__14 (MonoTouch.BuildTask v) [0x00000] in <filename unknown>:0
at System.Threading.Tasks.Parallel+<ForEach>c__AnonStorey56`1[MonoTouch.BuildTask].<>m__55 (MonoTouch.BuildTask e, System.Threading.Tasks.ParallelLoopState s, System.Object l) [0x00000] in <filename unknown>:0
at System.Threading.Tasks.Parallel+<ForEach>c__AnonStorey55`2[MonoTouch.BuildTask,System.Object].<>m__53 () [0x00000] in <filename unknown>:0
at System.Threading.Tasks.TaskActionInvoker+ActionInvoke.Invoke (System.Threading.Tasks.Task owner, System.Object state, System.Threading.Tasks.Task context) [0x00000] in <filename unknown>:0
at System.Threading.Tasks.Task.InnerInvoke () [0x00000] in <filename unknown>:0
at System.Threading.Tasks.Task.ThreadStart () [0x00000] in <filename unknown>:0

Command line as generated by Xamarin Studio is:
/Developer/MonoTouch/usr/bin/mtouch -sdkroot "/Applications/Xcode.app/Contents/Developer" --cache "/Users/ed/build/ProxyCompanionApps/MobileMaster/MobileMasterAppIOS/obj/iPhone/Debug/mtouch-cache" --nomanifest --nosign -dev "/Users/ed/build/ProxyCompanionApps/MobileMaster/MobileMasterAppIOS/bin/iPhone/Debug/MobileMasterAppIOS.app" -r "/Users/ed/build/ProxyCompanionApps/MobileMaster/PrxRC/bin/Debug/PrxRC.dll" -r "/Users/ed/build/ProxyCompanionApps/MobileMaster/ProxyException/bin/Debug/ProxyException.dll" -r "/Users/ed/build/ProxyCompanionApps/MobileMaster/ProxyInterface/bin/Debug/ProxyInterface.dll" -r "/Users/ed/build/ProxyCompanionApps/MobileMaster/ProxyLog/bin/Debug/ProxyLog.dll" -r "/Users/ed/build/ProxyCompanionApps/MobileMaster/PrxNetClient/bin/Debug/PrxNetClient.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/System.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/System.Xml.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/System.Core.dll" -r "/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll" -debug -linksdkonly -sdk "6.1" -targetver "3.2" --abi=armv7 "/Users/ed/build/ProxyCompanionApps/MobileMaster/MobileMasterAppIOS/bin/iPhone/Debug/MobileMasterAppIOS.exe" -v -v -v >&err.log

Deploys to the iOS simulator successfully. 

Version Information:
=== Xamarin Studio ===

Version 4.0.10 (build 7)
Installation UUID: c1fa1bb5-2305-4273-8a26-9ded2092801a
Mono 3.2.0 ((no/7c7fcc7)
GTK 2.24.20
GTK# (
Package version: 302000000

=== Apple Developer Tools ===

Xcode 4.6.2 (2067.2)
Build 4H1003

=== Xamarin.Mac ===

Xamarin.Mac: Not Installed

=== Xamarin.Android ===

Not Installed

=== Xamarin.iOS ===

Version: (Business Edition)
Hash: 6aff00f
Build date: 2013-24-07 06:25:59-0400

=== Build Information ===

Release ID: 400100007
Git revision: f324e2154ee86ae1b6b8483392eddbf418e6381b
Build date: 2013-07-20 06:23:58+0000
Xamarin addins: fe4f180e2386eafc00087ef68c3a580cff4a2592

=== Operating System ===

Mac OS X 10.8.3
Darwin mac-mini.proxynetworks.com 12.3.0 Darwin Kernel Version 12.3.0
Sun Jan 6 22:37:10 PST 2013
root:xnu-2050.22.13~1/RELEASE_X86_64 x86_64
Comment 3 Zoltan Varga 2013-07-25 18:15:41 UTC
So the problem here is that the project uses the binary dll WebSocket4Net.MonoTouch.dll, which depends on System.ServiceModel.Web, but the project doesn't include a reference to that assembly (and it shouldn't have to).
A workaround is to add a reference to this assembly to both the project, and to the source, but it would be better if mt could figure it out by itself.

Another problem is that the aot compiler crashes instead of emitting a useful error message.
Comment 4 Marek Safar 2013-07-26 03:05:32 UTC
Zoltan, if the assembly was really used by any code without reference he would get compiler error but it's not. Perhaps we are AOT-ing too much, unused code in this case.
Comment 5 Zoltan Varga 2013-07-26 06:28:16 UTC
Only the binary dll used by project depends on that assembly, the project itself does not.
The symptom is that mtouch doesn't copy the System.ServiceModel.Web assembly into the build directory, despite the fact that another dll in the project has a clr reference to it.
Comment 6 Marek Safar 2013-07-26 06:47:44 UTC
That's exactly what I said. System.ServiceModel.Web is not needed by the project therefore there is no need to aot System.ServiceModel.Web. The fact that some of reference assembly  has System.ServiceModel.Web does not mean it's needed.
Comment 7 Rolf Bjarne Kvinge [MSFT] 2013-07-29 18:28:48 UTC
So the problem is that mtouch removes the System.ServiceModel.Web reference from WebSocket4Net.MonoTouch.dll, but since it's linking only SDK assemblies the modified WebSocket4Net.MonoTouch.dll assembly isn't actually written to disk.

Linking all assemblies works around this issue.

Assigning to Sebastien for now, but it will take a few weeks until he can look at it (since he's on vacation right now).

If this turns out to be a more widespread problem and a quicker fix is required, I'll try to come up with a fix instead.
Comment 8 Sebastien Pouliot 2013-08-08 14:32:16 UTC
I can reproduce it with monotouch-6.4-series. However there were many more AOT crashes (several assemblies) when I used master. 

Zoltan, you might want to look at this (unlikely to be related, it's not an assert and happens on with link sdk or link all (did not try without linking).
Comment 9 Sebastien Pouliot 2013-08-08 17:05:14 UTC
Yuck. That seems to be a PCL related issue.

DataContractJsonSerializer was in System.ServiceModel.Web.dll in Silverlight [1], 6.2.x (and previous versions) and in the PCL profile. It is now located in System.Runtime.Serialization.dll in 6.4 and .NET 4.0+ [2].

So what happening is:

a. because of PCL there's a reference, from user code, to System.ServiceModel.Web.dll. User code has calls inside the System.ServiceModel.Web assembly;

b. but in reality nothing really comes from System.ServiceModel.Web.dll. Once resolved the type from System.Runtime.Serialization.dll is marked (because it's the only one that exists);

c. so the linker does not mark anything inside System.ServiceModel.Web.dll and schedule it for removal (unused);

d. the AOT compiler is not happy about it's absence (even if there would be nothing to compile in it) and crash

What we can do:

1. Add logic to the linker to create an (almost) empty assembly stub for System.ServiceModel.Web.dll; or

2. Fix the AOT compiler not to crash (but ignore missing assembly references);

I prefer the 2nd option because it means:

* faster build times (we don't need spawning a new AOT compiler process);

* smaller applications (no metadata .dll to include in the app);

* the linker fix needs to be in the base (shared) mono linker code - so it would produce the extra stubs for Mac and Android products (which do not fail because the JIT does not crash for missing references).

[1] http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer(v=vs.95).aspx

[2] http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer(v=vs.100).aspx
Comment 10 Rolf Bjarne Kvinge [MSFT] 2013-08-08 18:03:15 UTC
Isn't there a third option?

3. Remove references to linked-away assemblies from assemblies that aren't linked.
Comment 11 Sebastien Pouliot 2013-08-08 18:42:19 UTC
Right. OTOH that would require modifying and re-writting user assemblies _and_ debugging symbols. All easy but it would be quite slower than the existing file copy operation presently are.

Also I'm not 100% sure that the assembly state is safe to save back. Some (but not all) processing is done when things gets marked. That was never an issue before because we knew the in-memory representation was not saved. I remember fixing some cases where that happened - but that was mostly to save time, I never really checked for this (i.e. fix whenever found).

The above can be easily fixed by reloading, first the assembly - but that's even slower.
Comment 12 Zoltan Varga 2013-08-08 21:21:33 UTC
The AOT compiler crashes because it can't find an assembly it needs, i.e. code/metadata depends on it.
Comment 13 Sebastien Pouliot 2013-08-08 22:32:20 UTC
hmm... yeah it's missing the hint, i.e.

[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.Json.DataContractJsonSerializer))]

since that's not saved back (in user code) by the linker - which is one of the (good this time) thing that would be saved differently (and option #3 would not work if it did not).
Comment 14 Sebastien Pouliot 2013-08-09 10:30:41 UTC
The way the linker resolver works makes it hard to implement #1, i.e. keep the [TypeForwardedTo] attributes.

So I went with Rolf's #3. To minimize the issues (comment #11) I added a new AssemblyAction.Save enum value (instead of re-using the .Link value). That should ensure "well behaved steps" are not modifying* the memory image (that will now be saved). It's also simple to fix "badly behaved steps" if we hit some. 

The XI steps after the SweepStep (where we'll change from Copy to Save) are ok. That's "good enough" for this test case but I still need to check the previous step (in case there's a rogue step modifying assemblies with a Copy action).

* beside what we want, i.e. removing the assembly reference and getting the resolved member references (pointing to System.Runtime.Serialization instead of System.ServiceModel.Web) in the assembly.
Comment 15 Sebastien Pouliot 2013-08-13 14:22:28 UTC
Fixed in master/2ab52ceae23e345b28069bbec37e537f82ef47ac