166 lines
5.1 KiB
C++
166 lines
5.1 KiB
C++
#include "Engine.h"
|
|||
|
|
|
||
|
|
#include "codegen/il2cpp-codegen.h"
|
||
|
|
|
||
|
|
#include "Interpreter.h"
|
||
|
|
#include "MemoryUtil.h"
|
||
|
|
#include "../metadata/InterpreterImage.h"
|
||
|
|
#include "../metadata/MetadataModule.h"
|
||
|
|
|
||
|
|
namespace hybridclr
|
||
|
|
{
|
||
|
|
namespace interpreter
|
||
|
|
{
|
||
|
|
|
||
|
|
#if HYBRIDCLR_ENABLE_STRACKTRACE
|
||
|
|
|
||
|
|
#define PUSH_STACK_FRAME(method, rawIp) do { \
|
||
|
|
Il2CppStackFrameInfo stackFrameInfo = { method, rawIp }; \
|
||
|
|
il2cpp::vm::StackTrace::PushFrame(stackFrameInfo); \
|
||
|
|
} while(0)
|
||
|
|
|
||
|
|
#define POP_STACK_FRAME() do { il2cpp::vm::StackTrace::PopFrame(); } while(0)
|
||
|
|
|
||
|
|
#else
|
||
|
|
#define PUSH_STACK_FRAME(method, rawIp)
|
||
|
|
#define POP_STACK_FRAME()
|
||
|
|
#endif
|
||
|
|
|
||
|
|
InterpFrame* InterpFrameGroup::EnterFrameFromInterpreter(const MethodInfo* method, StackObject* argBase)
|
||
|
|
{
|
||
|
|
#if HYBRIDCLR_ENABLE_PROFILER
|
||
|
|
il2cpp_codegen_profiler_method_enter(method);
|
||
|
|
#endif
|
||
|
|
const InterpMethodInfo* imi = (const InterpMethodInfo*)method->interpData;
|
||
|
|
int32_t oldStackTop = _machineState.GetStackTop();
|
||
|
|
StackObject* stackBasePtr = _machineState.AllocStackSlot(imi->maxStackSize - imi->argStackObjectSize);
|
||
|
|
InterpFrame* newFrame = _machineState.PushFrame();
|
||
|
|
*newFrame = { method, argBase, oldStackTop, nullptr, nullptr, nullptr, 0, 0, _machineState.GetLocalPoolBottomIdx() };
|
||
|
|
PUSH_STACK_FRAME(method, (uintptr_t)newFrame);
|
||
|
|
return newFrame;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
InterpFrame* InterpFrameGroup::EnterFrameFromNative(const MethodInfo* method, StackObject* argBase)
|
||
|
|
{
|
||
|
|
#if HYBRIDCLR_ENABLE_PROFILER
|
||
|
|
il2cpp_codegen_profiler_method_enter(method);
|
||
|
|
#endif
|
||
|
|
const InterpMethodInfo* imi = (const InterpMethodInfo*)method->interpData;
|
||
|
|
int32_t oldStackTop = _machineState.GetStackTop();
|
||
|
|
StackObject* stackBasePtr = _machineState.AllocStackSlot(imi->maxStackSize);
|
||
|
|
InterpFrame* newFrame = _machineState.PushFrame();
|
||
|
|
*newFrame = { method, stackBasePtr, oldStackTop, nullptr, nullptr, nullptr, 0, 0, _machineState.GetLocalPoolBottomIdx() };
|
||
|
|
|
||
|
|
// if not prepare arg stack. copy from args
|
||
|
|
if (imi->args)
|
||
|
|
{
|
||
|
|
IL2CPP_ASSERT(imi->argCount == metadata::GetActualArgumentNum(method));
|
||
|
|
CopyStackObject(stackBasePtr, argBase, imi->argStackObjectSize);
|
||
|
|
}
|
||
|
|
PUSH_STACK_FRAME(method, (uintptr_t)newFrame);
|
||
|
|
return newFrame;
|
||
|
|
}
|
||
|
|
|
||
|
|
InterpFrame* InterpFrameGroup::LeaveFrame()
|
||
|
|
{
|
||
|
|
IL2CPP_ASSERT(_machineState.GetFrameTopIdx() > _frameBaseIdx);
|
||
|
|
POP_STACK_FRAME();
|
||
|
|
InterpFrame* frame = _machineState.GetTopFrame();
|
||
|
|
#if HYBRIDCLR_ENABLE_PROFILER
|
||
|
|
il2cpp_codegen_profiler_method_exit(frame->method);
|
||
|
|
#endif
|
||
|
|
if (frame->exFlowBase)
|
||
|
|
{
|
||
|
|
_machineState.SetExceptionFlowTop(frame->exFlowBase);
|
||
|
|
}
|
||
|
|
_machineState.PopFrame();
|
||
|
|
_machineState.SetStackTop(frame->oldStackTop);
|
||
|
|
_machineState.SetLocalPoolBottomIdx(frame->oldLocalPoolBottomIdx);
|
||
|
|
return _machineState.GetFrameTopIdx() > _frameBaseIdx ? _machineState.GetTopFrame() : nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
static bool FrameNeedsSkipped(const Il2CppStackFrameInfo& frame)
|
||
|
|
{
|
||
|
|
const MethodInfo* method = frame.method;
|
||
|
|
const Il2CppClass* klass = method->klass;
|
||
|
|
return (strcmp(klass->namespaze, "System.Diagnostics") == 0 &&
|
||
|
|
(strcmp(klass->name, "StackFrame") == 0 || strcmp(klass->name, "StackTrace") == 0))
|
||
|
|
|| (strcmp(klass->namespaze, "UnityEngine") == 0
|
||
|
|
&& (strcmp(klass->name, "StackTraceUtility") == 0
|
||
|
|
|| strcmp(klass->name, "Debug") == 0
|
||
|
|
|| strcmp(klass->name, "Logger") == 0
|
||
|
|
|| strcmp(klass->name, "DebugLogHandler") == 0));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void SetupStackFrameInfo(const InterpFrame* frame, Il2CppStackFrameInfo& stackFrame)
|
||
|
|
{
|
||
|
|
const MethodInfo* method = frame->method;
|
||
|
|
const InterpMethodInfo* imi = (const InterpMethodInfo*)method->interpData;
|
||
|
|
const byte* actualIp = (const byte*)frame->ip;
|
||
|
|
|
||
|
|
stackFrame.method = method;
|
||
|
|
stackFrame.raw_ip = (uintptr_t)frame;
|
||
|
|
|
||
|
|
if (!hybridclr::metadata::IsInterpreterMethod(method))
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
hybridclr::metadata::InterpreterImage* interpImage = hybridclr::metadata::MetadataModule::GetImage(method);
|
||
|
|
if (!interpImage)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
hybridclr::metadata::PDBImage* pdbImage = interpImage->GetPDBImage();
|
||
|
|
if (!pdbImage)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
pdbImage->SetupStackFrameInfo(method, actualIp, stackFrame);
|
||
|
|
}
|
||
|
|
|
||
|
|
void MachineState::CollectFrames(il2cpp::vm::StackFrames* stackFrames)
|
||
|
|
{
|
||
|
|
if (_frameTopIdx <= 0)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
size_t insertIndex = 0;
|
||
|
|
for (; insertIndex < stackFrames->size(); insertIndex++)
|
||
|
|
{
|
||
|
|
if (FrameNeedsSkipped((*stackFrames)[insertIndex]))
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
stackFrames->insert(stackFrames->begin() + insertIndex, _frameTopIdx, Il2CppStackFrameInfo());
|
||
|
|
for (int32_t i = 0; i < _frameTopIdx; i++)
|
||
|
|
{
|
||
|
|
SetupStackFrameInfo(_frameBase + i, (*stackFrames)[insertIndex + i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void MachineState::SetupFramesDebugInfo(il2cpp::vm::StackFrames* stackFrames)
|
||
|
|
{
|
||
|
|
for (Il2CppStackFrameInfo& frame : *stackFrames)
|
||
|
|
{
|
||
|
|
if (frame.method && hybridclr::metadata::IsInterpreterImplement(frame.method))
|
||
|
|
{
|
||
|
|
hybridclr::metadata::InterpreterImage* interpImage = hybridclr::metadata::MetadataModule::GetImage(frame.method);
|
||
|
|
if (interpImage)
|
||
|
|
{
|
||
|
|
hybridclr::metadata::PDBImage* pdbImage = interpImage->GetPDBImage();
|
||
|
|
if (pdbImage)
|
||
|
|
{
|
||
|
|
pdbImage->SetupStackFrameInfo(frame.method, (const byte*)(((InterpFrame*)frame.raw_ip)->ip), frame);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|