Better managed stack traces with IL2CPP

Starting with 5.0.3p1 (today), 4.6.6p2, and 5.1.0p1 (both yet to be released), we have improved managed stack traces reported by IL2CPP. They should be correct now in a all cases, so if you see a problem, please let us know, as it might be a bug.

We’re creating better managed stack traces by parsing the linker map file and generating a binary file with information about method sizes and offsets that we ship with the application. You’ll see a native executable named MapFileParser in the Unity editor build directory for your project. We use a Run Shell Script build phase in Xcode to run this utility and generate the data we need at runtime.

We know that some customers use a build configuration where the Unity Editor on Windows generates an Xcode project that is then copied to an OSX machine to actually build for the device. In this case, the MapFileParser utility won’t get into the Xcode project correctly, and the runtime will fall back to the previous stack trace code (which is sometimes incorrect). You should see a message in the Xcode build output indicating that the linker map file could not be used if this happens.

I’m interested to know how many users are using this Windows → OSX build process for iOS builds. For those that do use it, do you have a Unity installation on the OSX machine? This will help us determine how to better support this build configuration. Thanks!

We use the Windows → OSX build process you describe. We do not use Unity on the OSX machine at all.

I tried 5.0.3p1 and tried to publish our project with IL2CPP from windows, but got a failure error that it couldn’t find a MapFilterParser executable “C:\Program Files\Unity503p1\Editor\Data\Tools\MapFileParser\MapFileParser”. When I went to the “C:\Program Files\Unity503p1\Editor\Data\Tools\MapFileParser” directory, I saw a MapFileParser.exe file in there, but no MapFileParser file. So I made a copy of the MapFileParser.exe called MapFileParser (without extension) in that directory and the publish worked.

However, once I tried to build inside of XCode, I got yet another error that “MapFileParser” wasn’t a valid executable. This makes sense, since it’s trying to execute a windows binary on OS X. To fix this, I replaced the MapFileParser file with a shell script that does nothing.

That worked.

Long story short, I don’t think the fallback logic you describe is working correctly right now, because Unity is still trying to do stuff with the MapFileParser exe when the project is published from Windows – Both on the Unity side and the XCode side.

I’m glad I was able to work around it for now, since we’ve already been waiting on this latest patch to fix another critical ByteCodeStripper error that was preventing us from publishing using IL2CPP for the last couple of months.

@ajohnson223

Thanks for letting me know. Can you send me the full Xcode log from the project when the error happens in Xcode due to a missing MapFileParser executable? We should be able to correct both issues for the next patch release.

@ajohnson223

Another work around is to copy the MapFileParser utility from an OSX editor installation into that directory (Editor\Data\Tools\MapFileParser) in the Windows editor installation. Meanwhile, we have a fix for this bug that should make it into the next patch release.

Hello. I just stumbled upon the same problem with MapFileParser on 5.1.0p on Windows 8.1 (I like to build from windows to a remote location and then run on iOS from X-Code). I am going to try to apply the above workaround for now.

@Uber6

Thanks for letting me know. This should be corrected in 5.1.1p1, which will be available in the next few days.

I am building from an OSX machine and there are still some minor bugs concerning stacktrace in 5.0.3p2.

p.s OSX editor sometimes cannot load assemblies without influence on compilation.

Still the same for me on 5.1.1f1

1 Like

@Uber6

The fix did not make it into 5.1.1f1, but it is in the next patch release, 5.1.1p1, which should be out today or tomorrow.

@John-Chen350

Thanks for letting me know. Can you submit a bug report with a project that demonstrates this problem? We would like to have a look at it. Thanks.

I am working only on OSX for both the creation of the xcode project and app/ipa. I am running 4.6.6p3 and the file is present in my build output, but I don’t think it’s valid. I get a Permission Denied error:

…/IntermediateBuildFilesPath/Unity-iPhone.build/Release-iphoneos/Unity-iPhone.build/Script-033966F41B18B03000ECD701.sh: line 12: …/MapFileParser: Permission denied and it fails my build.

I trimmed the paths down a bit to remove my environment specific information. Is this a known issue? I am building using batch mode.

@davisben85

This is not a know issue. Maybe the MapFileParser is ending up with the wrong permissions after it is copied into the output directory. Can you take a look to see if it has the execute permission? If not we may have a bug where we need to set it correctly.

I cannot reproduce it all the time. Mostly speaking it works fine. I’ve noticed that once due to my previous VB problem: it shows that some code in Standard Assets (shall be Effects right?) wronged but I have never referenced to it.

@John-Chen350

Thanks, let me know if you find something that happens at least somewhat regularly. I suspect the issues is related to how the linker lays out the native code in the binary, so it may be difficult to reproduce in many cases.

Now I’m confused. When I build with IL2CPP I don’t get any stack traces. This is an example of what I get:

*** loading to inventory: LXMXFCgLAlggQGMId210MhQDKB0FVCcHKht/Gi1zDxA3HUkNbCU2VSFjenMFFCkbGV4+FjBWK2Nsc0NdeBEfUiMrPRt/YzE+DRUFGx5FPAc3WjxjenMCHTsL

(Filename: /Users/builduser/buildslave/unity/build/artifacts/iPhonePlayer-armv7-il2cppGenerated/UnityEngineDebug.cpp Line: 56)

Should I be getting a full stack trace on Debug.Log statements? (That would be great)

I’m using 4.6.7. Is there a flag or something that I missed?

@bigdaddy

Yes, you should get a stack trace. If I use this script code:

using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour {
    void Start () {
        First();
    }

    void First() {
        Second();
    }

    void Second() {
        Debug.Log("Here Josh");
    }
}

I get the following output in the Xcode console:

Here Josh
UnityEngine.Debug:Internal_Log(Int32, String, Object)
UnityEngine.Debug:Log(Object)
NewBehaviourScript:Second()
NewBehaviourScript:First()
NewBehaviourScript:Start()

@JoshPeterson - Now this is interesting… Two iPhones connected to MacBook Pro. Game built and run on iPhone 6+ and Xcode console displays this:

*** loading to inventory: LXMXFCgLAlggQGMId210MhQDKB0FVCcHKht/Gi1zDxA3HUkNbCU2VSFjenMFFCkbGV4+FjBWK2Nsc0NdeBEfUiMrPRt/YzE+DRUFGx5FPAc3WjxjenMCHTsL
UnityEngine.Debug:Internal_Log(Int32, String, Object)
UnityEngine.Debug:Log(Object)
Game.InventoryDBFactory:Load(String)
System.Action1:Invoke(GcLeaderboard)** **AIS.MessageKit.Messenger1:Broadcast(MessageTypes, VirtualItemReward)
GameVarsLoader:InventoryGameVarLoaded(AISGameVar, PResponse)
System.Action2:Invoke(AISGameVar, PResponse)** **<SendRequest>c__Iterator181:MoveNext()

(Filename: /Users/builduser/buildslave/unity/build/artifacts/iPhonePlayer-armv7-il2cppGenerated/UnityEngineDebug.cpp Line: 56)

Click the Stop button, change drop down to point to the iPhone 5 and running it, the XCode console displays this:
*** loading to inventory: LXMXFCgLAlggQGMId210MhQDKB0FVCcHKht/Gi1zDxA3HUkNbCU2VSFjenMFFCkbGV4+FjBWK2Nsc0NdeBEfUiMrPRt/YzE+DRUFGx5FPAc3WjxjenMCHTsL

(Filename: /Users/builduser/buildslave/unity/build/artifacts/iPhonePlayer-armv7-il2cppGenerated/UnityEngineDebug.cpp Line: 56)

@bigdaddy

Is the iPhone 5 a 32-bit device (i.e. and iPhone 5 or 5c, not a 5s)? If so, that might explain the difference. This really looks like something we should investigate here. Can you file a bug report?

Hi, Josh.

Is it possible to have line numbers in stack traces in projects compiled with il2cpp?

UnityEngine.Debug:Internal_Log(Int32, String, Object)
UnityEngine.Debug:Log(Object)
NewBehaviourScript:Second()
NewBehaviourScript:First()
NewBehaviourScript:Start()

Is nice, but it was a lot better with mono. Line numbers are very useful, especially when you’re trying to debug using crash reports from HockeyApp.

NullReferenceException
  at UnityEngine.EventSystems.UIBehaviour.IsActive ()
  at UnityEngine.UI.Graphic.SetVerticesDirty ()
  at UnityEngine.UI.Text.set_text (System.String value)
  at LedLifeUnit.HandleLevelChanged (Int32 newLevel) (at Unit/LedLifeUnit.cs:71)
  at EntityExperience.set_CurrentLevel (Int32 value) (at Common/EntityExperience.cs:24)
  at UnitsRaceExperience.SetUnitsLevel (.UnitData unitData, Int32 level) (at Player/UnitsRaceExperience.cs:225)
  at UnitsRaceExperience+Race.LevelUpNow () (at Player/UnitsRaceExperience.cs:129)
  at TrainingRoomController.OnHurryConfirm (Boolean perform, .Race raceExp, System.Func`1 showPredicate) (at Building/Training Room/TrainingRoomController.cs:509)
  at TrainingRoomController+<FinishTraining>c__AnonStorey125.<>m__D2 (Boolean peform) (at Building/Training Room/TrainingRoomController.cs:483)
  at PayConfirmationDialog.OnOk () (at NGUI/PayConfirmationDialog.cs:150)
  at UnityEngine.Events.InvokableCall.Invoke (System.Object[] args)
  at UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters)
  at UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters)
  at UnityEngine.Events.UnityEvent.Invoke ()
  at UnityEngine.UI.Button.Press ()
  at UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData)
  at UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData)
  at UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor)
  at UnityEngine.EventSystems.EventSystem:Update()

(I’ve removed most of environment specific parts of file paths)

Is this possible with il2cpp? Am I missing something? Thanks.

@begray

I think that this should be possible, but it is not something we’ve implemented yet for IL2CPP. Since the behavior differs from Mono, I would classify this as a bug. Can you submit a bug report? We an look at implementing it then. Thanks!