From 8550143babb84d1f34eee30c10ad2fb2f204f077 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sat, 6 May 2017 15:29:56 +0000 Subject: [PATCH] [KMTESTS:RTL] - Add a test for RtlWalkFrameChain and RtlCaptureStackBackTrace svn path=/trunk/; revision=74489 --- rostests/kmtests/CMakeLists.txt | 1 + rostests/kmtests/kmtest/testlist.c | 2 + rostests/kmtests/kmtest_drv/testlist.c | 2 + rostests/kmtests/rtl/RtlStack.c | 136 +++++++++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 rostests/kmtests/rtl/RtlStack.c diff --git a/rostests/kmtests/CMakeLists.txt b/rostests/kmtests/CMakeLists.txt index 8fe2101e58a..6291fcdf343 100644 --- a/rostests/kmtests/CMakeLists.txt +++ b/rostests/kmtests/CMakeLists.txt @@ -20,6 +20,7 @@ list(APPEND COMMON_SOURCE rtl/RtlMemory.c rtl/RtlRegistry.c rtl/RtlSplayTree.c + rtl/RtlStack.c rtl/RtlUnicodeString.c) # diff --git a/rostests/kmtests/kmtest/testlist.c b/rostests/kmtests/kmtest/testlist.c index 3778a097078..74e525ce300 100644 --- a/rostests/kmtests/kmtest/testlist.c +++ b/rostests/kmtests/kmtest/testlist.c @@ -21,6 +21,7 @@ KMT_TESTFUNC Test_RtlIntSafe; KMT_TESTFUNC Test_RtlMemory; KMT_TESTFUNC Test_RtlRegistry; KMT_TESTFUNC Test_RtlSplayTree; +KMT_TESTFUNC Test_RtlStack; KMT_TESTFUNC Test_RtlUnicodeString; KMT_TESTFUNC Test_TcpIpIoctl; KMT_TESTFUNC Test_TcpIpTdi; @@ -43,6 +44,7 @@ const KMT_TEST TestList[] = { "RtlMemory", Test_RtlMemory }, { "RtlRegistry", Test_RtlRegistry }, { "RtlSplayTree", Test_RtlSplayTree }, + { "RtlStack", Test_RtlStack }, { "RtlUnicodeString", Test_RtlUnicodeString }, { "TcpIpTdi", Test_TcpIpTdi }, { "TcpIpConnect", Test_TcpIpConnect }, diff --git a/rostests/kmtests/kmtest_drv/testlist.c b/rostests/kmtests/kmtest_drv/testlist.c index 74cb68f0fac..5f2417f0a73 100644 --- a/rostests/kmtests/kmtest_drv/testlist.c +++ b/rostests/kmtests/kmtest_drv/testlist.c @@ -70,6 +70,7 @@ KMT_TESTFUNC Test_RtlIsValidOemCharacter; KMT_TESTFUNC Test_RtlMemory; KMT_TESTFUNC Test_RtlRegistry; KMT_TESTFUNC Test_RtlSplayTree; +KMT_TESTFUNC Test_RtlStack; KMT_TESTFUNC Test_RtlUnicodeString; KMT_TESTFUNC Test_ZwAllocateVirtualMemory; KMT_TESTFUNC Test_ZwCreateSection; @@ -139,6 +140,7 @@ const KMT_TEST TestList[] = { "RtlMemoryKM", Test_RtlMemory }, { "RtlRegistryKM", Test_RtlRegistry }, { "RtlSplayTreeKM", Test_RtlSplayTree }, + { "RtlStackKM", Test_RtlStack }, { "RtlUnicodeStringKM", Test_RtlUnicodeString }, { "SeInheritance", Test_SeInheritance }, { "SeQueryInfoToken", Test_SeQueryInfoToken }, diff --git a/rostests/kmtests/rtl/RtlStack.c b/rostests/kmtests/rtl/RtlStack.c new file mode 100644 index 00000000000..45db416e152 --- /dev/null +++ b/rostests/kmtests/rtl/RtlStack.c @@ -0,0 +1,136 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Kernel-Mode Test Suite Runtime library stack trace test + * PROGRAMMER: Thomas Faber + */ + +#define KMT_EMULATE_KERNEL +#include + +static PVOID ReturnAddresses[4]; + +static +VOID +TestStackWalk3(VOID); + +DECLSPEC_NOINLINE +static +VOID +TestStackWalk4(VOID) +{ + PVOID Frames[5]; + ULONG Ret; + ULONG Hash; + ULONG ExpectedHash; + ULONG i; + const ULONG FunctionSizeGuess = 0x1000; + + ReturnAddresses[3] = _ReturnAddress(); + + Ret = RtlWalkFrameChain(NULL, 5, 0); + ok_eq_ulong(Ret, 0); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Ret = RtlWalkFrameChain(Frames, 0, 0); + ok_eq_ulong(Ret, 0); + ok_eq_pointer(Frames[0], (PVOID)(ULONG_PTR)0x5555555555555555); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Ret = RtlWalkFrameChain(Frames, 5, 0); + ok_eq_ulong(Ret, 5); + ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok_eq_pointer(Frames[1], ReturnAddresses[3]); + ok_eq_pointer(Frames[2], ReturnAddresses[2]); + ok_eq_pointer(Frames[3], ReturnAddresses[1]); + ok_eq_pointer(Frames[4], ReturnAddresses[0]); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Ret = RtlWalkFrameChain(Frames, 4, 0); + ok_eq_ulong(Ret, 4); + ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok_eq_pointer(Frames[1], ReturnAddresses[3]); + ok_eq_pointer(Frames[2], ReturnAddresses[2]); + ok_eq_pointer(Frames[3], ReturnAddresses[1]); + ok_eq_pointer(Frames[4], (PVOID)(ULONG_PTR)0x5555555555555555); + + KmtStartSeh() + RtlCaptureStackBackTrace(0, 5, NULL, NULL); + KmtEndSeh(STATUS_ACCESS_VIOLATION); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Hash = 0x55555555; + Ret = RtlCaptureStackBackTrace(0, 0, Frames, &Hash); + ok_eq_ulong(Ret, 0); + ok_eq_hex(Hash, 0x55555555); + ok_eq_pointer(Frames[0], (PVOID)(ULONG_PTR)0x5555555555555555); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Hash = 0x55555555; + Ret = RtlCaptureStackBackTrace(0, 1, Frames, NULL); + ok_eq_ulong(Ret, 1); + ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok_eq_pointer(Frames[1], (PVOID)(ULONG_PTR)0x5555555555555555); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Ret = RtlCaptureStackBackTrace(0, 5, Frames, &Hash); + ok_eq_ulong(Ret, 5); + ExpectedHash = 0; + for (i = 0; i < 5; i++) + ExpectedHash += (ULONG)(ULONG_PTR)Frames[i]; + ok_eq_hex(Hash, ExpectedHash); + ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4); + ok_eq_pointer(Frames[1], ReturnAddresses[3]); + ok_eq_pointer(Frames[2], ReturnAddresses[2]); + ok_eq_pointer(Frames[3], ReturnAddresses[1]); + ok_eq_pointer(Frames[4], ReturnAddresses[0]); + + RtlFillMemory(Frames, sizeof(Frames), 0x55); + Ret = RtlCaptureStackBackTrace(1, 4, Frames, &Hash); + ok_eq_ulong(Ret, 4); + ExpectedHash = 0; + for (i = 0; i < 4; i++) + ExpectedHash += (ULONG)(ULONG_PTR)Frames[i]; + ok_eq_hex(Hash, ExpectedHash); + ok_eq_pointer(Frames[0], ReturnAddresses[3]); + ok_eq_pointer(Frames[1], ReturnAddresses[2]); + ok_eq_pointer(Frames[2], ReturnAddresses[1]); + ok_eq_pointer(Frames[3], ReturnAddresses[0]); + ok_eq_pointer(Frames[4], (PVOID)(ULONG_PTR)0x5555555555555555); +} + +DECLSPEC_NOINLINE +static +VOID +TestStackWalk3(VOID) +{ + ReturnAddresses[2] = _ReturnAddress(); + TestStackWalk4(); +} + +DECLSPEC_NOINLINE +static +VOID +TestStackWalk2(VOID) +{ + ReturnAddresses[1] = _ReturnAddress(); + TestStackWalk3(); +} + +DECLSPEC_NOINLINE +static +VOID +TestStackWalk1(VOID) +{ + ReturnAddresses[0] = _ReturnAddress(); + TestStackWalk2(); +} + +START_TEST(RtlStack) +{ + TestStackWalk1(); +}