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

commit 3cf2bea0def78939382f0aa4045c6d7cef2b3ef2
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Wed Mar 7 15:38:24 2018 +0100
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Sat Jun 5 13:52:42 2021 +0200

    [RTL] Fix RtlWalkFrameChain and wrap it in SEH
---
 sdk/lib/rtl/amd64/unwind.c | 100 +++++++++++++++++++++++++++------------------
 1 file changed, 61 insertions(+), 39 deletions(-)

diff --git a/sdk/lib/rtl/amd64/unwind.c b/sdk/lib/rtl/amd64/unwind.c
index 859ef783043..87e370ed89f 100644
--- a/sdk/lib/rtl/amd64/unwind.c
+++ b/sdk/lib/rtl/amd64/unwind.c
@@ -956,53 +956,75 @@ RtlWalkFrameChain(OUT PVOID *Callers,
     {
     }
 
-    /* Loop the frames */
-    for (i = 0; i < FramesToSkip + Count; i++)
+    _SEH2_TRY
     {
-        /* Lookup the FunctionEntry for the current ControlPc */
-        FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
-
-        /* Is this a leaf function? */
-        if (!FunctionEntry)
+        /* Loop the frames */
+        for (i = 0; i < FramesToSkip + Count; i++)
         {
-            Context.Rip = *(DWORD64*)Context.Rsp;
-            Context.Rsp += sizeof(DWORD64);
-            DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", 
(PVOID)Context.Rip, (PVOID)Context.Rsp);
-        }
-        else
-        {
-            RtlVirtualUnwind(0,
-                             ImageBase,
-                             ControlPc,
-                             FunctionEntry,
-                             &Context,
-                             &HandlerData,
-                             &EstablisherFrame,
-                             NULL);
-            DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", 
(PVOID)Context.Rip, (PVOID)Context.Rsp);
-        }
+            /* Lookup the FunctionEntry for the current ControlPc */
+            FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, 
NULL);
 
-        /* Check if new Rip is valid */
-        if (!Context.Rip)
-        {
-            break;
-        }
+            /* Is this a leaf function? */
+            if (!FunctionEntry)
+            {
+                Context.Rip = *(DWORD64*)Context.Rsp;
+                Context.Rsp += sizeof(DWORD64);
+                DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", 
(PVOID)Context.Rip, (PVOID)Context.Rsp);
+            }
+            else
+            {
+                RtlVirtualUnwind(UNW_FLAG_NHANDLER,
+                                 ImageBase,
+                                 ControlPc,
+                                 FunctionEntry,
+                                 &Context,
+                                 &HandlerData,
+                                 &EstablisherFrame,
+                                 NULL);
+                DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", 
(PVOID)Context.Rip, (PVOID)Context.Rsp);
+            }
 
-        /* Check, if we have left our stack */
-        if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh))
-        {
-            break;
-        }
+            /* Check if we are in kernel mode */
+            if (RtlpGetMode() == KernelMode)
+            {
+                /* Check if we left the kernel range */
+                if (!(Flags & 1) && (Context.Rip < 0xFFFF800000000000ULL))
+                {
+                    break;
+                }
+            }
+            else
+            {
+                /* Check if we left the user range */
+                if ((Context.Rip < 0x10000) ||
+                    (Context.Rip > 0x000007FFFFFEFFFFULL))
+                {
+                    break;
+                }
+            }
 
-        /* Continue with new Rip */
-        ControlPc = Context.Rip;
+            /* Check, if we have left our stack */
+            if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh))
+            {
+                break;
+            }
 
-        /* Save value, if we are past the frames to skip */
-        if (i >= FramesToSkip)
-        {
-            Callers[i - FramesToSkip] = (PVOID)ControlPc;
+            /* Continue with new Rip */
+            ControlPc = Context.Rip;
+
+            /* Save value, if we are past the frames to skip */
+            if (i >= FramesToSkip)
+            {
+                Callers[i - FramesToSkip] = (PVOID)ControlPc;
+            }
         }
     }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        DPRINT1("Exception while getting callers!\n");
+        i = 0;
+    }
+    _SEH2_END;
 
     DPRINT("RtlWalkFrameChain returns %ld\n", i);
     return i;

Reply via email to