Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

NullReferenceException in UnityLinker.exe on IL2CPP when Script Debug is enabled

Discussion in 'Experimental Scripting Previews' started by thisisthedave, Sep 21, 2018.

  1. thisisthedave

    thisisthedave

    Joined:
    Dec 2, 2013
    Posts:
    7
    UnityLinker fails with a NullReferenceException in SweepDebugInfo every time I enable "Script Debugging", which seems to be a bug in UnityLinker. Here's how I was able to find a workaround:

    Script debugging was working recently, so I did a binary search through commits in our git repo, building them until I found the bad commit. I enabled diagnostic reporting in UnityLinker (
    set UNITYLINKER_ADDITIONAL_ARGS=--enable-report --enable-snapshot
    ), and then compared input args between the bad commit and the previous good commit. This revealed that a DLL was not being passed to UnityLinker in the bad commit:

    upload_2018-9-21_15-31-22.png

    Note that classes from this DLL are definitely referenced by multiple scripts and prefabs that are navigable from the "roots" as described in the docs about C# code stripping. The guilty commit had purged a bunch of stale SpawnerData .asset files, a ScriptableObject class implemented in this DLL.

    I was able to work around the bug by adding a dummy SpawnerData .asset file to the Resources folder, which convinced Unity to pass the DLL argument to UnityLinker, and fixed the build.

    I pulled the source for mono linker from github to investigate what happens in SweepDebugInfo. SweepDebugInfo has an early exit when debugging is disabled, which explains why builds only fail when script debugging is enabled. Squinting at the code didn't provide much insight. It's checking for null in the obvious places. I'm guessing one of the property getters inside of MethodDebugInformation is stepping on a null because of that missing DLL input argument.

    FWIW, the DLL in question is implemented in F#. What info can I provide to Unity to help track down the issue and get a permanent fix?

    For reference, this is the error message from UnityLinker when it fails to sweep debug info:


    Fatal error in Unity CIL Linker
    System.NullReferenceException: Object reference not set to an instance of an object
    at Mono.Linker.Steps.SweepStep.SweepDebugInfo (Mono.Collections.Generic.Collection`1[T] methods) [0x00098] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Mono.Linker.Steps.SweepStep.SweepMethods (Mono.Collections.Generic.Collection`1[T] methods) [0x00013] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Unity.Linker.Steps.UnitySweepStep.SweepMethods (Mono.Collections.Generic.Collection`1[T] methods) [0x00036] in <04c78ac134f947649b7ee6e8097dfdc1>:0
    at Mono.Linker.Steps.SweepStep.SweepType (Mono.Cecil.TypeDefinition type) [0x0002a] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Mono.Linker.Steps.SweepStep.SweepAssembly (Mono.Cecil.AssemblyDefinition assembly) [0x000ea] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Mono.Linker.Steps.SweepStep.Process () [0x00030] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Unity.Linker.Steps.UnitySweepStep.Process () [0x00007] in <04c78ac134f947649b7ee6e8097dfdc1>:0
    at Mono.Linker.Steps.BaseStep.Process (Mono.Linker.LinkContext context) [0x00018] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Mono.Linker.Pipeline.Process (Mono.Linker.LinkContext context) [0x00021] in <fdb4fc84d9e048eaa2de2ebaa14c8a30>:0
    at Unity.Linker.UnityDriver.Run () [0x00087] in <04c78ac134f947649b7ee6e8097dfdc1>:0
    at Unity.Linker.UnityDriver.RunDriverWithoutErrorHandling () [0x00007] in <04c78ac134f947649b7ee6e8097dfdc1>:0
    at Unity.Linker.UnityDriver.RunDriver () [0x00002] in <04c78ac134f947649b7ee6e8097dfdc1>:0
     
  2. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    4,116
    Thanks for the investigation? Can you provide us with this project via the Unity editor bug repo mechanism? If so, that will help us correct the issue. Thanks!
     
  3. thisisthedave

    thisisthedave

    Joined:
    Dec 2, 2013
    Posts:
    7
    The project is impractically big to submit as a bug. I was hoping you'd have some a priori insight based on your internal understanding of how UnityLinker works and how script debugging changes its behavior. I'll see if I can produce a minimal project that reproduces the issue.

    Alternatively, here's a long shot: what are the chances you could provide me the PDBs for the version of UnityLinker that shipped with 2018.2.8f1 so that I can step through `SweepDebugInfo` and just tell you exactly what is malfunctioning? Most of the project is already open source. It would be easier to debug myself than to provide a working example of the bug.

    Thanks,
    -Dave
     
  4. mike-voorhees

    mike-voorhees

    Unity Technologies

    Joined:
    Aug 9, 2016
    Posts:
    16
    Having access to the PDB's for a better information may give us enough to figure out the root of the problem, or it may just be another clue.

    That said, `SweepDebugInfo` is defined in the upstream monolinker. You could clone our fork for the 2018.2 release, build locally, copy `monolinker.exe` the symbol file into your editor install and you would have the symbols needed to get more information.

    I have not seen this exception from `SweepDebugInfo` before and I'm not sure what could be causing it. I can tell you why you didn't used to see the issue. We recently realized that our documentation about how precompiled assemblies are stripped was not accurate in some places and not clear in other places.

    In the tutorial you linked to it states that

    "If you use types and methods from other assemblies directly in a Scene or in an Asset you include in resources, Unity marks these as roots."

    What that really means is, when you use a type from an assembly directly in the Scene or Asset that entire assembly will not be stripped. On the other hand, if you have code that makes use of types or methods in another assembly that is not directly used in a Scene or Asset, that other assembly will be stripped of unused code.

    Here is what was happening for your case.

    Back at the "good commit" `Wonderstorm.Game.Fs.dll` was not being stripped. By not stripping the assembly it in some way is avoiding/working around whatever is going wrong with `SweepDebugInfo`. Likely because`SweepDebugInfo` will never be called on methods in `Wonderstorm.Game.Fs.dll`.

    The "bad commit" removed the last remaining bits that led to `Wonderstorm.Game.Fs.dll` being flagged as an assembly to not strip. Now `Wonderstorm.Game.Fs.dll` is being stripped. Because of that the bug with `SweepDebugInfo` appears.

    Then you added dummy SpawnerData back, causing `Wonderstorm.Game.Fs.dll` to once again be flagged as an assembly not to strip.

    A bug with a project that can reproduce the issue would be helpful for us. This could be a issue contained in UnityLinker or it could be something where the symbol files were messed up earlier in the build pipeline and an entire project is necessary to reproduce.

    Thanks,
    -Mike
     
  5. thisisthedave

    thisisthedave

    Joined:
    Dec 2, 2013
    Posts:
    7
    Thanks for the thorough analysis, Mike! You tweeted some info to my friend & coworker @danl1240 that was instrumental in getting this far, so I appreciate your help. I'll investigate some things and get back to you.

    Cheers,
    -Dave