I found some compatibility issues between performance profiler and Unity3d or mono


In my project, there is a very special requirement. We integrated Unity3d (a 3d game engine: https://unity.com/) into a winforms-based reference program. When I tried to use Ants Performance Profiler to perform During performance analysis, initialization exceptions or failures may be caused. After my analysis, I found that this should be caused by some compatibility issues. But fortunately, this should have nothing to do with the ANTS tool, just a pure compatibility issue, and I also circumvented these issues through some special measures. This is just to provide you with relevant information for reference.

first issues is compatible with mono, this version of mono is the old version of mono. please check this stacktrace:
> mono.dll!MONO_GET_RUNTIME_FUNCTION_CALLBACK(unsigned __int64 ControlPc, void * Context) 行 1594 C
  ntdll.dll!RtlpLookupDynamicFunctionEntry() 未知
  ntdll.dll!RtlLookupFunctionEntry() 未知
  RedGate.Profiler.Core.dll!000000018007c950() 未知
  RedGate.Profiler.Core.dll!0000000180065f7a() 未知
  RedGate.Profiler.Core.dll!0000000180066325() 未知
  RedGate.Profiler.Core.dll!0000000180094ed5() 未知
  RedGate.Profiler.Core.dll!0000000180094cde() 未知
  kernel32.dll!BaseThreadInitThunk() 未知
  ntdll.dll!RtlUserThreadStart() 未知

this is the code of mono C-function:
PRUNTIME_FUNCTION
MONO_GET_RUNTIME_FUNCTION_CALLBACK ( DWORD64 ControlPc, IN PVOID Context )
{
MonoJitInfo *ji;
guint64 pos;
PMonoUnwindInfo targetinfo;
MonoDomain *domain = mono_domain_get ();

ji = mini_jit_info_table_find (domain, (char*)ControlPc, NULL);
if (!ji)
return 0;

pos = (guint64)(((char*)ji->code_start) + ji->code_size);
targetinfo = (PMonoUnwindInfo)ALIGN_TO (pos, 8);

targetinfo->runtimeFunction.BeginAddress = ((DWORD64)ji->code_start) - ((DWORD64)Context);
targetinfo->runtimeFunction.EndAddress = pos - ((DWORD64)Context);
targetinfo->runtimeFunction.UnwindData = ((DWORD64)&targetinfo->unwindInfo) - ((DWORD64)Context);

return &targetinfo->runtimeFunction;
}
    I think this thread is created by your modules. But this thread is not properly initialized by mono, so the MonoMomain should be NULL. it will cause crash.
When I do not start from the Profiler, this function will not be triggered, so it will not cause a crash.

 I added a protection code to solve this problem. here:
PRUNTIME_FUNCTION
MONO_GET_RUNTIME_FUNCTION_CALLBACK ( DWORD64 ControlPc, IN PVOID Context )
{
MonoJitInfo *ji;
guint64 pos;
PMonoUnwindInfo targetinfo;
MonoDomain *domain = mono_domain_get ();

if (domain == NULL)
{
return 0;
}

ji = mini_jit_info_table_find (domain, (char*)ControlPc, NULL);
if (!ji)
return 0;

pos = (guint64)(((char*)ji->code_start) + ji->code_size);
targetinfo = (PMonoUnwindInfo)ALIGN_TO (pos, 8);

targetinfo->runtimeFunction.BeginAddress = ((DWORD64)ji->code_start) - ((DWORD64)Context);
targetinfo->runtimeFunction.EndAddress = pos - ((DWORD64)Context);
targetinfo->runtimeFunction.UnwindData = ((DWORD64)&targetinfo->unwindInfo) - ((DWORD64)Context);

return &targetinfo->runtimeFunction;
}

Sign In or Register to comment.