Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion src/inc/eetwain.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,35 @@ HRESULT FixContextForEnC(PCONTEXT pCtx,
};

#ifdef _TARGET_X86_
bool UnwindStackFrame(PREGDISPLAY pContext,
struct IUnwindFrameReader
{
IUnwindFrameReader() = default;
virtual ~IUnwindFrameReader() = default;

virtual DWORD GetSP(void) = 0;
virtual DWORD GetFP(void) = 0;
virtual DWORD GetPC(void) = 0;
};

struct IUnwindFrameListener
{
IUnwindFrameListener() = default;
virtual ~IUnwindFrameListener() = default;

virtual void NotifyEaxLocation(PDWORD loc) = 0;
virtual void NotifyEbxLocation(PDWORD loc) = 0;
virtual void NotifyEcxLocation(PDWORD loc) = 0;
virtual void NotifyEdxLocation(PDWORD loc) = 0;
virtual void NotifyEsiLocation(PDWORD loc) = 0;
virtual void NotifyEdiLocation(PDWORD loc) = 0;
virtual void NotifyEbpLocation(PDWORD loc) = 0;

virtual void NotifySP(DWORD SP, DWORD stackArgumentSize) = 0;
virtual void NotifyPCLocation(PDWORD loc) = 0;
};

bool UnwindStackFrame(IUnwindFrameReader *pUnwindFrameReader,
IUnwindFrameListener *pUnwindFrameListener,
EECodeInfo *pCodeInfo,
unsigned flags,
CodeManState *pState,
Expand Down
87 changes: 65 additions & 22 deletions src/unwinder/i386/unwinder_i386.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,68 @@
#include "unwinder_i386.h"

#ifdef WIN64EXCEPTIONS
class UnwindFrameReader : public IUnwindFrameReader
{
private:
PCONTEXT pContextRecord;

public:
UnwindFrameReader(PCONTEXT pContextRecord)
{
this->pContextRecord = pContextRecord;
}

public:
virtual DWORD GetSP(void) { return pContextRecord->Esp; }
virtual DWORD GetFP(void) { return pContextRecord->Ebp; }
virtual DWORD GetPC(void) { return pContextRecord->Eip; }
};

struct UnwindFrameListener : public IUnwindFrameListener
{
private:
PCONTEXT pContextRecord;
PKNONVOLATILE_CONTEXT_POINTERS pContextPointers;

T_KNONVOLATILE_CONTEXT_POINTERS ctxPtrs;

public:
UnwindFrameListener(PCONTEXT pContextRecord, PKNONVOLATILE_CONTEXT_POINTERS pContextPointers)
{
this->pContextRecord = pContextRecord;
this->pContextPointers = (pContextPointers) ? pContextPointers : &ctxPtrs;
}

virtual ~UnwindFrameListener() = default;

#define NOTIFY_METHOD(reg) \
virtual void Notify##reg##Location(PDWORD loc) \
{ \
pContextRecord->reg = *loc; \
pContextPointers->reg = loc; \
}

NOTIFY_METHOD(Eax);
NOTIFY_METHOD(Ebx);
NOTIFY_METHOD(Ecx);
NOTIFY_METHOD(Edx);
NOTIFY_METHOD(Esi);
NOTIFY_METHOD(Edi);
NOTIFY_METHOD(Ebp);

#undef NOTIFY_METHOD

virtual void NotifySP(DWORD SP, DWORD stackArgumentSize)
{
pContextRecord->Esp = SP + stackArgumentSize;
}

virtual void NotifyPCLocation(PDWORD loc)
{
pContextRecord->Eip = *loc;
}
};

/*++

Routine Description:
Expand Down Expand Up @@ -72,41 +134,22 @@ OOPStackUnwinderX86::VirtualUnwind(
*HandlerRoutine = NULL;
}

REGDISPLAY rd;

FillRegDisplay(&rd, ContextRecord);

rd.PCTAddr = (UINT_PTR)&(ContextRecord->Eip);

if (ContextPointers)
{
rd.pCurrentContextPointers = ContextPointers;
}
UnwindFrameReader unwindFrameReader(ContextRecord);
UnwindFrameListener unwindFrameListener(ContextRecord, ContextPointers);

CodeManState codeManState;
codeManState.dwIsSet = 0;

EECodeInfo codeInfo;
codeInfo.Init((PCODE) ControlPc);

if (!UnwindStackFrame(&rd, &codeInfo, UpdateAllRegs, &codeManState, NULL))
if (!UnwindStackFrame(&unwindFrameReader, &unwindFrameListener, &codeInfo, UpdateAllRegs, &codeManState, NULL))
{
return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
}

ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;

#define ARGUMENT_AND_SCRATCH_REGISTER(reg) if (rd.pCurrentContextPointers->reg) ContextRecord->reg = *rd.pCurrentContextPointers->reg;
ENUM_ARGUMENT_AND_SCRATCH_REGISTERS();
#undef ARGUMENT_AND_SCRATCH_REGISTER

#define CALLEE_SAVED_REGISTER(reg) if (rd.pCurrentContextPointers->reg) ContextRecord->reg = *rd.pCurrentContextPointers->reg;
ENUM_CALLEE_SAVED_REGISTERS();
#undef CALLEE_SAVED_REGISTER

ContextRecord->Esp = rd.SP;
ContextRecord->Eip = rd.ControlPC;

// For x86, the value of Establisher Frame Pointer is Caller SP
//
// (Please refers to CLR ABI for details)
Expand Down
Loading