mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +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
|
||||
RtlpTryToUnwindEpilog(
|
||||
_Inout_ PCONTEXT Context,
|
||||
_In_ ULONG64 ControlPc,
|
||||
_Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
|
||||
_In_ ULONG64 ImageBase,
|
||||
_In_ PRUNTIME_FUNCTION FunctionEntry)
|
||||
|
@ -316,7 +317,7 @@ RtlpTryToUnwindEpilog(
|
|||
/* Make a local copy of the context */
|
||||
LocalContext = *Context;
|
||||
|
||||
InstrPtr = (BYTE*)LocalContext.Rip;
|
||||
InstrPtr = (BYTE*)ControlPc;
|
||||
|
||||
/* Check if first instruction of epilog is "add rsp, x" */
|
||||
Instr = *(DWORD*)InstrPtr;
|
||||
|
@ -339,7 +340,10 @@ RtlpTryToUnwindEpilog(
|
|||
else if ( (Instr & 0x38fffe) == 0x208d48 )
|
||||
{
|
||||
/* Get the register */
|
||||
Reg = ((Instr << 8) | (Instr >> 16)) & 0x7;
|
||||
Reg = (Instr >> 16) & 0x7;
|
||||
|
||||
/* REX.R */
|
||||
Reg += (Instr & 1) * 8;
|
||||
|
||||
LocalContext.Rsp = GetReg(&LocalContext, Reg);
|
||||
|
||||
|
@ -353,13 +357,13 @@ RtlpTryToUnwindEpilog(
|
|||
else if (Mod == 1)
|
||||
{
|
||||
/* 1 byte displacement */
|
||||
LocalContext.Rsp += Instr >> 24;
|
||||
LocalContext.Rsp += (LONG)(CHAR)(Instr >> 24);
|
||||
InstrPtr += 4;
|
||||
}
|
||||
else if (Mod == 2)
|
||||
{
|
||||
/* 4 bytes displacement */
|
||||
LocalContext.Rsp += *(DWORD*)(InstrPtr + 3);
|
||||
LocalContext.Rsp += *(LONG*)(InstrPtr + 3);
|
||||
InstrPtr += 7;
|
||||
}
|
||||
}
|
||||
|
@ -453,11 +457,17 @@ GetEstablisherFrame(
|
|||
i < UnwindInfo->CountOfCodes;
|
||||
i += UnwindOpSlots(UnwindInfo->UnwindCode[i]))
|
||||
{
|
||||
/* Skip codes past our code offset */
|
||||
if (UnwindInfo->UnwindCode[i].CodeOffset > CodeOffset)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for SET_FPREG */
|
||||
if (UnwindInfo->UnwindCode[i].UnwindOp == UWOP_SET_FPREG)
|
||||
{
|
||||
return GetReg(Context, UnwindInfo->FrameRegister) -
|
||||
UnwindInfo->FrameOffset * 16;
|
||||
UnwindInfo->FrameOffset * 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,18 +487,18 @@ RtlVirtualUnwind(
|
|||
_Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers)
|
||||
{
|
||||
PUNWIND_INFO UnwindInfo;
|
||||
ULONG_PTR CodeOffset;
|
||||
ULONG_PTR ControlRva, CodeOffset;
|
||||
ULONG i, Offset;
|
||||
UNWIND_CODE UnwindCode;
|
||||
BYTE Reg;
|
||||
PULONG LanguageHandler;
|
||||
|
||||
/* Use relative virtual address */
|
||||
ControlPc -= ImageBase;
|
||||
/* Get relative virtual address */
|
||||
ControlRva = ControlPc - ImageBase;
|
||||
|
||||
/* Sanity checks */
|
||||
if ( (ControlPc < FunctionEntry->BeginAddress) ||
|
||||
(ControlPc >= FunctionEntry->EndAddress) )
|
||||
if ( (ControlRva < FunctionEntry->BeginAddress) ||
|
||||
(ControlRva >= FunctionEntry->EndAddress) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -498,17 +508,16 @@ RtlVirtualUnwind(
|
|||
|
||||
/* The language specific handler data follows the unwind info */
|
||||
LanguageHandler = ALIGN_UP_POINTER_BY(&UnwindInfo->UnwindCode[UnwindInfo->CountOfCodes], sizeof(ULONG));
|
||||
*HandlerData = (LanguageHandler + 1);
|
||||
|
||||
/* Calculate relative offset to function start */
|
||||
CodeOffset = ControlPc - FunctionEntry->BeginAddress;
|
||||
CodeOffset = ControlRva - FunctionEntry->BeginAddress;
|
||||
|
||||
*EstablisherFrame = GetEstablisherFrame(Context, UnwindInfo, CodeOffset);
|
||||
|
||||
/* 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 */
|
||||
return NULL;
|
||||
|
@ -565,7 +574,7 @@ RepeatChainedInfo:
|
|||
|
||||
case UWOP_SAVE_NONVOL:
|
||||
Reg = UnwindCode.OpInfo;
|
||||
Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
|
||||
Offset = UnwindInfo->UnwindCode[i + 1].FrameOffset;
|
||||
SetRegFromStackValue(Context, ContextPointers, Reg, (DWORD64*)Context->Rsp + Offset);
|
||||
i += 2;
|
||||
break;
|
||||
|
@ -588,15 +597,15 @@ RepeatChainedInfo:
|
|||
|
||||
case UWOP_SAVE_XMM128:
|
||||
Reg = UnwindCode.OpInfo;
|
||||
Offset = *(USHORT*)(&UnwindInfo->UnwindCode[i + 1]);
|
||||
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
|
||||
Offset = UnwindInfo->UnwindCode[i + 1].FrameOffset;
|
||||
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)Context->Rsp + Offset);
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case UWOP_SAVE_XMM128_FAR:
|
||||
Reg = UnwindCode.OpInfo;
|
||||
Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i + 1]);
|
||||
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)(Context->Rsp + Offset));
|
||||
SetXmmRegFromStackValue(Context, ContextPointers, Reg, (M128A*)Context->Rsp + Offset);
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
|
@ -604,11 +613,8 @@ RepeatChainedInfo:
|
|||
/* OpInfo is 1, when an error code was pushed, otherwise 0. */
|
||||
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->SegCs = *(PDWORD64)(Context->Rsp + 0x08);
|
||||
Context->EFlags = *(PDWORD64)(Context->Rsp + 0x10);
|
||||
Context->SegSs = *(PDWORD64)(Context->Rsp + 0x20);
|
||||
Context->Rsp = *(PDWORD64)(Context->Rsp + 0x18);
|
||||
ASSERT((i + 1) == UnwindInfo->CountOfCodes);
|
||||
goto Exit;
|
||||
|
@ -635,8 +641,9 @@ RepeatChainedInfo:
|
|||
Exit:
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue