mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:53:06 +00:00
[RTL] Fix RtlVirtualUnwind
This commit is contained in:
parent
90d2e12dfa
commit
aade1ab01b
1 changed files with 30 additions and 23 deletions
|
@ -303,6 +303,7 @@ __inline
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
RtlpTryToUnwindEpilog(
|
RtlpTryToUnwindEpilog(
|
||||||
_Inout_ PCONTEXT Context,
|
_Inout_ PCONTEXT Context,
|
||||||
|
_In_ ULONG64 ControlPc,
|
||||||
_Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
|
_Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
|
||||||
_In_ ULONG64 ImageBase,
|
_In_ ULONG64 ImageBase,
|
||||||
_In_ PRUNTIME_FUNCTION FunctionEntry)
|
_In_ PRUNTIME_FUNCTION FunctionEntry)
|
||||||
|
@ -316,7 +317,7 @@ RtlpTryToUnwindEpilog(
|
||||||
/* Make a local copy of the context */
|
/* Make a local copy of the context */
|
||||||
LocalContext = *Context;
|
LocalContext = *Context;
|
||||||
|
|
||||||
InstrPtr = (BYTE*)LocalContext.Rip;
|
InstrPtr = (BYTE*)ControlPc;
|
||||||
|
|
||||||
/* Check if first instruction of epilog is "add rsp, x" */
|
/* Check if first instruction of epilog is "add rsp, x" */
|
||||||
Instr = *(DWORD*)InstrPtr;
|
Instr = *(DWORD*)InstrPtr;
|
||||||
|
@ -339,7 +340,10 @@ RtlpTryToUnwindEpilog(
|
||||||
else if ( (Instr & 0x38fffe) == 0x208d48 )
|
else if ( (Instr & 0x38fffe) == 0x208d48 )
|
||||||
{
|
{
|
||||||
/* Get the register */
|
/* Get the register */
|
||||||
Reg = ((Instr << 8) | (Instr >> 16)) & 0x7;
|
Reg = (Instr >> 16) & 0x7;
|
||||||
|
|
||||||
|
/* REX.R */
|
||||||
|
Reg += (Instr & 1) * 8;
|
||||||
|
|
||||||
LocalContext.Rsp = GetReg(&LocalContext, Reg);
|
LocalContext.Rsp = GetReg(&LocalContext, Reg);
|
||||||
|
|
||||||
|
@ -353,13 +357,13 @@ RtlpTryToUnwindEpilog(
|
||||||
else if (Mod == 1)
|
else if (Mod == 1)
|
||||||
{
|
{
|
||||||
/* 1 byte displacement */
|
/* 1 byte displacement */
|
||||||
LocalContext.Rsp += Instr >> 24;
|
LocalContext.Rsp += (LONG)(CHAR)(Instr >> 24);
|
||||||
InstrPtr += 4;
|
InstrPtr += 4;
|
||||||
}
|
}
|
||||||
else if (Mod == 2)
|
else if (Mod == 2)
|
||||||
{
|
{
|
||||||
/* 4 bytes displacement */
|
/* 4 bytes displacement */
|
||||||
LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
|
LocalContext.Rsp += *(LONG*)(InstrPtr + 3);
|
||||||
InstrPtr += 7;
|
InstrPtr += 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,11 +457,17 @@ GetEstablisherFrame(
|
||||||
i < UnwindInfo->CountOfCodes;
|
i < UnwindInfo->CountOfCodes;
|
||||||
i += UnwindOpSlots(UnwindInfo->UnwindCode[i]))
|
i += UnwindOpSlots(UnwindInfo->UnwindCode[i]))
|
||||||
{
|
{
|
||||||
|
/* Skip codes past our code offset */
|
||||||
|
if (UnwindInfo->UnwindCode[i].CodeOffset > CodeOffset)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for SET_FPREG */
|
/* Check for SET_FPREG */
|
||||||
if (UnwindInfo->UnwindCode[i].UnwindOp == UWOP_SET_FPREG)
|
if (UnwindInfo->UnwindCode[i].UnwindOp == UWOP_SET_FPREG)
|
||||||
{
|
{
|
||||||
return GetReg(Context, UnwindInfo->FrameRegister) -
|
return GetReg(Context, UnwindInfo->FrameRegister) -
|
||||||
UnwindInfo->FrameOffset * 16;
|
UnwindInfo->FrameOffset * 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,18 +487,18 @@ RtlVirtualUnwind(
|
||||||
_Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
|
_Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
|
||||||
{
|
{
|
||||||
PUNWIND_INFO UnwindInfo;
|
PUNWIND_INFO UnwindInfo;
|
||||||
ULONG_PTR CodeOffset;
|
ULONG_PTR ControlRva, CodeOffset;
|
||||||
ULONG i, Offset;
|
ULONG i, Offset;
|
||||||
UNWIND_CODE UnwindCode;
|
UNWIND_CODE UnwindCode;
|
||||||
BYTE Reg;
|
BYTE Reg;
|
||||||
PULONG LanguageHandler;
|
PULONG LanguageHandler;
|
||||||
|
|
||||||
/* Use relative virtual address */
|
/* Get relative virtual address */
|
||||||
ControlPc -= ImageBase;
|
ControlRva = ControlPc - ImageBase;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
if ( (ControlPc < FunctionEntry->BeginAddress) ||
|
if ( (ControlRva < FunctionEntry->BeginAddress) ||
|
||||||
(ControlPc >= FunctionEntry->EndAddress) )
|
(ControlRva >= FunctionEntry->EndAddress) )
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -498,17 +508,16 @@ RtlVirtualUnwind(
|
||||||
|
|
||||||
/* The language specific handler data follows the unwind info */
|
/* The language specific handler data follows the unwind info */
|
||||||
LanguageHandler = ALIGN_UP_POINTER_BY(&UnwindInfo->UnwindCode[UnwindInfo->CountOfCodes], sizeof(ULONG));
|
LanguageHandler = ALIGN_UP_POINTER_BY(&UnwindInfo->UnwindCode[UnwindInfo->CountOfCodes], sizeof(ULONG));
|
||||||
*HandlerData = (LanguageHandler + 1);
|
|
||||||
|
|
||||||
/* Calculate relative offset to function start */
|
/* Calculate relative offset to function start */
|
||||||
CodeOffset = ControlPc - FunctionEntry->BeginAddress;
|
CodeOffset = ControlRva - FunctionEntry->BeginAddress;
|
||||||
|
|
||||||
*EstablisherFrame = GetEstablisherFrame(Context, UnwindInfo, CodeOffset);
|
*EstablisherFrame = GetEstablisherFrame(Context, UnwindInfo, CodeOffset);
|
||||||
|
|
||||||
/* Check if we are in the function epilog and try to finish it */
|
/* Check if we are in the function epilog and try to finish it */
|
||||||
if (CodeOffset > UnwindInfo->SizeOfProlog)
|
if ((CodeOffset > UnwindInfo->SizeOfProlog) && (UnwindInfo->CountOfCodes > 0))
|
||||||
{
|
{
|
||||||
if (RtlpTryToUnwindEpilog(Context, ContextPointers, ImageBase, FunctionEntry))
|
if (RtlpTryToUnwindEpilog(Context, ControlPc, ContextPointers, ImageBase, FunctionEntry))
|
||||||
{
|
{
|
||||||
/* There's no exception routine */
|
/* There's no exception routine */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -565,7 +574,7 @@ RepeatChainedInfo:
|
||||||
|
|
||||||
case UWOP_SAVE_NONVOL:
|
case UWOP_SAVE_NONVOL:
|
||||||
Reg = UnwindCode.OpInfo;
|
Reg = UnwindCode.OpInfo;
|
||||||
Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
|
Offset = UnwindInfo->UnwindCode[i + 1].FrameOffset;
|
||||||
SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
|
SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
|
@ -588,15 +597,15 @@ RepeatChainedInfo:
|
||||||
|
|
||||||
case UWOP_SAVE_XMM128:
|
case UWOP_SAVE_XMM128:
|
||||||
Reg = UnwindCode.OpInfo;
|
Reg = UnwindCode.OpInfo;
|
||||||
Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
|
Offset = UnwindInfo->UnwindCode[i + 1].FrameOffset;
|
||||||
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
|
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)Context->Rsp + Offset);
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UWOP_SAVE_XMM128_FAR:
|
case UWOP_SAVE_XMM128_FAR:
|
||||||
Reg = UnwindCode.OpInfo;
|
Reg = UnwindCode.OpInfo;
|
||||||
Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
|
Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
|
||||||
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
|
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)Context->Rsp + Offset);
|
||||||
i += 3;
|
i += 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -604,11 +613,8 @@ RepeatChainedInfo:
|
||||||
/* OpInfo is 1, when an error code was pushed, otherwise 0. */
|
/* OpInfo is 1, when an error code was pushed, otherwise 0. */
|
||||||
Context->Rsp += UnwindCode.OpInfo * sizeof(DWORD64);
|
Context->Rsp += UnwindCode.OpInfo * sizeof(DWORD64);
|
||||||
|
|
||||||
/* Now pop the MACHINE_FRAME (Yes, "magic numbers", deal with it) */
|
/* Now pop the MACHINE_FRAME (RIP/RSP only. And yes, "magic numbers", deal with it) */
|
||||||
Context->Rip = *(PDWORD64)(Context->Rsp + 0x00);
|
Context->Rip = *(PDWORD64)(Context->Rsp + 0x00);
|
||||||
Context->SegCs = *(PDWORD64)(Context->Rsp + 0x08);
|
|
||||||
Context->EFlags = *(PDWORD64)(Context->Rsp + 0x10);
|
|
||||||
Context->SegSs = *(PDWORD64)(Context->Rsp + 0x20);
|
|
||||||
Context->Rsp = *(PDWORD64)(Context->Rsp + 0x18);
|
Context->Rsp = *(PDWORD64)(Context->Rsp + 0x18);
|
||||||
ASSERT((i + 1) == UnwindInfo->CountOfCodes);
|
ASSERT((i + 1) == UnwindInfo->CountOfCodes);
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -635,8 +641,9 @@ RepeatChainedInfo:
|
||||||
Exit:
|
Exit:
|
||||||
|
|
||||||
/* Check if we have a handler and return it */
|
/* Check if we have a handler and return it */
|
||||||
if (UnwindInfo->Flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
|
if (UnwindInfo->Flags & (HandlerType & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)))
|
||||||
{
|
{
|
||||||
|
*HandlerData = (LanguageHandler + 1);
|
||||||
return RVA(ImageBase, *LanguageHandler);
|
return RVA(ImageBase, *LanguageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue