https://git.reactos.org/?p=reactos.git;a=commitdiff;h=90d2e12dfab8f6aa8473d…
commit 90d2e12dfab8f6aa8473d2d88a404ba1bb6c1ecd
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Mon Aug 8 09:31:08 2022 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Thu Nov 24 21:17:58 2022 +0200
[RTL] Fix RtlpCaptureNonVolatileContextPointers
---
sdk/lib/rtl/amd64/unwind.c | 46 +++++++++++++++++++++++++++-------------------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/sdk/lib/rtl/amd64/unwind.c b/sdk/lib/rtl/amd64/unwind.c
index 619d31b6bb9..33a7e71c857 100644
--- a/sdk/lib/rtl/amd64/unwind.c
+++ b/sdk/lib/rtl/amd64/unwind.c
@@ -1053,29 +1053,37 @@ RtlpCaptureNonVolatileContextPointers(
do
{
- /* Look up the function entry */
- FunctionEntry = RtlLookupFunctionEntry(Context.Rip, &ImageBase, NULL);
- ASSERT(FunctionEntry != NULL);
-
- /* Do a virtual unwind to the caller and capture saved non-volatiles */
- RtlVirtualUnwind(UNW_FLAG_EHANDLER,
- ImageBase,
- Context.Rip,
- FunctionEntry,
- &Context,
- &HandlerData,
- &EstablisherFrame,
- NonvolatileContextPointers);
-
/* Make sure nothing fishy is going on. Currently this is for kernel mode only. */
- ASSERT(EstablisherFrame != 0);
ASSERT((LONG64)Context.Rip < 0);
+ ASSERT((LONG64)Context.Rsp < 0);
+
+ /* Look up the function entry */
+ FunctionEntry = RtlLookupFunctionEntry(Context.Rip, &ImageBase, NULL);
+ if (FunctionEntry != NULL)
+ {
+ /* Do a virtual unwind to the caller and capture saved non-volatiles */
+ RtlVirtualUnwind(UNW_FLAG_EHANDLER,
+ ImageBase,
+ Context.Rip,
+ FunctionEntry,
+ &Context,
+ &HandlerData,
+ &EstablisherFrame,
+ NonvolatileContextPointers);
+
+ ASSERT(EstablisherFrame != 0);
+ }
+ else
+ {
+ Context.Rip = *(PULONG64)Context.Rsp;
+ Context.Rsp += 8;
+ }
- /* Continue until we reached the target frame or user mode */
- } while (EstablisherFrame < TargetFrame);
+ /* Continue until we reach user mode */
+ } while ((LONG64)Context.Rip < 0);
- /* If the caller did the right thing, we should get exactly the target frame */
- ASSERT(EstablisherFrame == TargetFrame);
+ /* If the caller did the right thing, we should get past the target frame */
+ ASSERT(EstablisherFrame >= TargetFrame);
}
VOID