https://git.reactos.org/?p=reactos.git;a=commitdiff;h=aade1ab01beedac84af6712e8cf02128b34021b3

commit aade1ab01beedac84af6712e8cf02128b34021b3
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Fri Aug 19 13:03:22 2022 +0200
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Thu Nov 24 21:17:58 2022 +0200

    [RTL] Fix RtlVirtualUnwind
---
 sdk/lib/rtl/amd64/unwind.c | 53 ++++++++++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 23 deletions(-)

diff --git a/sdk/lib/rtl/amd64/unwind.c b/sdk/lib/rtl/amd64/unwind.c
index 33a7e71c857..2b596341eb0 100644
--- a/sdk/lib/rtl/amd64/unwind.c
+++ b/sdk/lib/rtl/amd64/unwind.c
@@ -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);
     }
 

Reply via email to