[PATCH 2/5] ntdll: Implement RtlWalkFrameChain() for x86 and x86_64.
Paul Gofman
pgofman at codeweavers.com
Thu Oct 21 11:03:37 CDT 2021
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/ntdll/ntdll.spec | 2 +-
dlls/ntdll/signal_arm.c | 11 +++++++
dlls/ntdll/signal_arm64.c | 11 +++++++
dlls/ntdll/signal_i386.c | 24 ++++++++++++++
dlls/ntdll/signal_x86_64.c | 24 ++++++++++++++
dlls/ntdll/tests/exception.c | 51 +++++++++++++++++++++++++++++
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +-
include/ddk/ntddk.h | 3 ++
include/winnt.h | 2 ++
9 files changed, 128 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 13e65f65139..c54b2e205aa 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1073,7 +1073,7 @@
@ stdcall RtlWakeAddressSingle(ptr)
@ stdcall RtlWakeAllConditionVariable(ptr)
@ stdcall RtlWakeConditionVariable(ptr)
-@ stub RtlWalkFrameChain
+@ stdcall RtlWalkFrameChain(ptr long long)
@ stdcall RtlWalkHeap(long ptr)
@ stdcall RtlWow64EnableFsRedirection(long)
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
index 0ef210a0331..1ab4aa032c0 100644
--- a/dlls/ntdll/signal_arm.c
+++ b/dlls/ntdll/signal_arm.c
@@ -308,6 +308,17 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
return 0;
}
+/**********************************************************************
+ * RtlWalkFrameChain (NTDLL.@)
+ */
+ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags)
+{
+
+ FIXME( "callers %p, count %u, flags %#x stub.\n", callers, count, flags );
+
+ return 0;
+}
+
/***********************************************************************
* signal_start_thread
*/
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index 290639b676b..401db35d405 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -1481,6 +1481,17 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
return 0;
}
+/**********************************************************************
+ * RtlWalkFrameChain (NTDLL.@)
+ */
+ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags)
+{
+
+ FIXME( "callers %p, count %u, flags %#x stub.\n", callers, count, flags );
+
+ return 0;
+}
+
/***********************************************************************
* signal_start_thread
*/
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 0245aa602a1..9390ffa3df3 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -520,6 +520,30 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
}
+/**********************************************************************
+ * RtlWalkFrameChain (NTDLL.@)
+ */
+ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags)
+{
+ CONTEXT context;
+ ULONG skip;
+ ULONG ret;
+
+ TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags );
+
+ RtlCaptureContext( &context );
+
+ skip = (flags >> 8) & 0xff;
+ flags &= ~0xff00;
+
+ if (flags)
+ FIXME( "flags %#x are not supported.\n", flags );
+
+ ret = capture_stack_back_trace( &context, skip, count, callers, NULL );
+ return ret ? ret + skip : 0;
+}
+
+
/***********************************************************************
* signal_start_thread
*/
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index dbf622392b7..e57b538d17c 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1545,6 +1545,30 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
}
+/**********************************************************************
+ * RtlWalkFrameChain (NTDLL.@)
+ */
+ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags)
+{
+ CONTEXT context;
+ ULONG skip;
+ ULONG ret;
+
+ TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags );
+
+ RtlCaptureContext( &context );
+
+ skip = (flags >> 8) & 0xff;
+ flags &= ~0xff00;
+
+ if (flags)
+ FIXME( "flags %#x are not supported.\n", flags );
+
+ ret = capture_stack_back_trace( &context, skip, count, callers, NULL );
+ return ret ? ret + skip : 0;
+}
+
+
/***********************************************************************
* signal_start_thread
*/
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 6af68317732..63b1edeebc9 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -28,6 +28,7 @@
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
+#include "ddk/ntddk.h"
#include "ddk/wdm.h"
#include "excpt.h"
#include "wine/test.h"
@@ -9113,6 +9114,55 @@ static void test_copy_context(void)
}
#endif
+static void test_walk_stack(void)
+{
+ ULONG frame_count, frame_count2;
+ void *addrs[256], *addrs2[256];
+ void *start, *end;
+ unsigned int i;
+
+ memset(addrs, 0xcc, sizeof(addrs));
+ memset(addrs2, 0xcc, sizeof(addrs2));
+
+ frame_count = RtlCaptureStackBackTrace(0, ARRAY_SIZE(addrs), addrs, NULL);
+ frame_count2 = RtlWalkFrameChain(addrs2, ARRAY_SIZE(addrs2), 0);
+
+ trace("frame_count %u.\n", frame_count);
+
+ ok(frame_count > 1, "Got zero frame_count.\n");
+ ok(frame_count == frame_count2, "Got unexpected frame_count %u, frame_count2 %u.\n", frame_count, frame_count2);
+
+ start = test_walk_stack;
+ end = (BYTE *)start + 0x1000;
+ todo_wine_if(sizeof(void *) == 4)
+ ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
+ start, end, addrs[0]);
+ todo_wine_if(sizeof(void *) == 4)
+ ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n",
+ start, end, addrs2[0]);
+
+ for (i = 1; i < frame_count; ++i)
+ {
+ ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]);
+ }
+ todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n");
+
+ memset(addrs, 0xcc, sizeof(addrs));
+ memset(addrs2, 0xcc, sizeof(addrs2));
+
+ frame_count = RtlCaptureStackBackTrace(1, ARRAY_SIZE(addrs), addrs, NULL);
+ ok(frame_count == frame_count2 - 1, "Got unexpected frame_count %u.\n", frame_count);
+
+ frame_count2 = RtlWalkFrameChain(addrs2, frame_count2, 1 << RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT) - 1;
+ ok(frame_count == frame_count2, "Got unexpected frame_count %u, frame_count2 %u.\n", frame_count, frame_count2);
+
+ for (i = 0; i < frame_count; ++i)
+ {
+ ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]);
+ }
+ todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n");
+}
+
START_TEST(exception)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -9339,5 +9389,6 @@ START_TEST(exception)
test_suspend_thread();
test_suspend_process();
test_unload_trace();
+ test_walk_stack();
VirtualFree(code_mem, 0, MEM_RELEASE);
}
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 0208e2f633f..b94e58ccb26 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1300,7 +1300,7 @@
@ stdcall RtlVerifyVersionInfo(ptr long int64)
@ stdcall -arch=arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr)
@ stub RtlVolumeDeviceToDosName
-@ stub RtlWalkFrameChain
+@ stdcall RtlWalkFrameChain(ptr long long)
@ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
@ stub RtlZeroHeap
@ stdcall RtlZeroMemory(ptr long)
diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h
index 41ad3d721bd..ce558139aa6 100644
--- a/include/ddk/ntddk.h
+++ b/include/ddk/ntddk.h
@@ -245,6 +245,8 @@ typedef EXPAND_STACK_CALLOUT *PEXPAND_STACK_CALLOUT;
typedef GUID UUID;
#endif
+#define RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT 8
+
NTSTATUS WINAPI ExUuidCreate(UUID*);
NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE,PULONG,PCONFIGURATION_TYPE,PULONG,
PCONFIGURATION_TYPE,PULONG,PIO_QUERY_DEVICE_ROUTINE,PVOID);
@@ -267,5 +269,6 @@ NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine(PCREATE_THREAD_NOTIFY_ROUTINE);
NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE);
void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE,PRTL_AVL_COMPARE_ROUTINE,PRTL_AVL_ALLOCATE_ROUTINE, PRTL_AVL_FREE_ROUTINE,void *);
void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE,void *,ULONG,BOOL*);
+ULONG WINAPI RtlWalkFrameChain(void **,ULONG,ULONG);
#endif
diff --git a/include/winnt.h b/include/winnt.h
index ef731e29c52..eb1bd165720 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -1840,6 +1840,8 @@ NTSYSAPI PVOID WINAPI RtlVirtualUnwind(DWORD,ULONG_PTR,ULONG_PTR,RUNTIME_FUNCT
#endif
+NTSYSAPI USHORT WINAPI RtlCaptureStackBackTrace(ULONG,ULONG,void **,ULONG *);
+
/*
* Product types
*/
--
2.31.1
More information about the wine-devel
mailing list