1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite Runtime library stack trace test
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #define KMT_EMULATE_KERNEL
9 #include <kmt_test.h>
10 
11 static PVOID ReturnAddresses[4];
12 
13 static
14 VOID
15 TestStackWalk3(VOID);
16 
17 DECLSPEC_NOINLINE
18 static
19 VOID
20 TestStackWalk4(VOID)
21 {
22     PVOID Frames[5];
23     ULONG Ret;
24     ULONG Hash;
25     ULONG ExpectedHash;
26     ULONG i;
27     const ULONG FunctionSizeGuess = 0x1000;
28 
29     ReturnAddresses[3] = _ReturnAddress();
30 
31     Ret = RtlWalkFrameChain(NULL, 5, 0);
32     ok_eq_ulong(Ret, 0);
33 
34     RtlFillMemory(Frames, sizeof(Frames), 0x55);
35     Ret = RtlWalkFrameChain(Frames, 0, 0);
36     ok_eq_ulong(Ret, 0);
37     ok_eq_pointer(Frames[0], (PVOID)(ULONG_PTR)0x5555555555555555);
38 
39     RtlFillMemory(Frames, sizeof(Frames), 0x55);
40     Ret = RtlWalkFrameChain(Frames, 5, 0);
41     ok_eq_ulong(Ret, 5);
42     ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
43     ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
44     ok_eq_pointer(Frames[1], ReturnAddresses[3]);
45     ok_eq_pointer(Frames[2], ReturnAddresses[2]);
46     ok_eq_pointer(Frames[3], ReturnAddresses[1]);
47     ok_eq_pointer(Frames[4], ReturnAddresses[0]);
48 
49     RtlFillMemory(Frames, sizeof(Frames), 0x55);
50     Ret = RtlWalkFrameChain(Frames, 4, 0);
51     ok_eq_ulong(Ret, 4);
52     ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
53     ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
54     ok_eq_pointer(Frames[1], ReturnAddresses[3]);
55     ok_eq_pointer(Frames[2], ReturnAddresses[2]);
56     ok_eq_pointer(Frames[3], ReturnAddresses[1]);
57     ok_eq_pointer(Frames[4], (PVOID)(ULONG_PTR)0x5555555555555555);
58 
59     KmtStartSeh()
60         RtlCaptureStackBackTrace(0, 5, NULL, NULL);
61     KmtEndSeh(STATUS_ACCESS_VIOLATION);
62 
63     RtlFillMemory(Frames, sizeof(Frames), 0x55);
64     Hash = 0x55555555;
65     Ret = RtlCaptureStackBackTrace(0, 0, Frames, &Hash);
66     ok_eq_ulong(Ret, 0);
67     ok_eq_hex(Hash, 0x55555555);
68     ok_eq_pointer(Frames[0], (PVOID)(ULONG_PTR)0x5555555555555555);
69 
70     RtlFillMemory(Frames, sizeof(Frames), 0x55);
71     Hash = 0x55555555;
72     Ret = RtlCaptureStackBackTrace(0, 1, Frames, NULL);
73     ok_eq_ulong(Ret, 1);
74     ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
75     ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
76     ok_eq_pointer(Frames[1], (PVOID)(ULONG_PTR)0x5555555555555555);
77 
78     RtlFillMemory(Frames, sizeof(Frames), 0x55);
79     Ret = RtlCaptureStackBackTrace(0, 5, Frames, &Hash);
80     ok_eq_ulong(Ret, 5);
81     ExpectedHash = 0;
82     for (i = 0; i < 5; i++)
83         ExpectedHash += (ULONG)(ULONG_PTR)Frames[i];
84     ok_eq_hex(Hash, ExpectedHash);
85     ok((ULONG_PTR)Frames[0] > (ULONG_PTR)TestStackWalk4, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
86     ok((ULONG_PTR)Frames[0] < (ULONG_PTR)TestStackWalk4 + FunctionSizeGuess, "Frame is %p, function is %p\n", Frames[0], TestStackWalk4);
87     ok_eq_pointer(Frames[1], ReturnAddresses[3]);
88     ok_eq_pointer(Frames[2], ReturnAddresses[2]);
89     ok_eq_pointer(Frames[3], ReturnAddresses[1]);
90     ok_eq_pointer(Frames[4], ReturnAddresses[0]);
91 
92     RtlFillMemory(Frames, sizeof(Frames), 0x55);
93     Ret = RtlCaptureStackBackTrace(1, 4, Frames, &Hash);
94     ok_eq_ulong(Ret, 4);
95     ExpectedHash = 0;
96     for (i = 0; i < 4; i++)
97         ExpectedHash += (ULONG)(ULONG_PTR)Frames[i];
98     ok_eq_hex(Hash, ExpectedHash);
99     ok_eq_pointer(Frames[0], ReturnAddresses[3]);
100     ok_eq_pointer(Frames[1], ReturnAddresses[2]);
101     ok_eq_pointer(Frames[2], ReturnAddresses[1]);
102     ok_eq_pointer(Frames[3], ReturnAddresses[0]);
103     ok_eq_pointer(Frames[4], (PVOID)(ULONG_PTR)0x5555555555555555);
104 }
105 
106 DECLSPEC_NOINLINE
107 static
108 VOID
109 TestStackWalk3(VOID)
110 {
111     ReturnAddresses[2] = _ReturnAddress();
112     TestStackWalk4();
113 }
114 
115 DECLSPEC_NOINLINE
116 static
117 VOID
118 TestStackWalk2(VOID)
119 {
120     ReturnAddresses[1] = _ReturnAddress();
121     TestStackWalk3();
122 }
123 
124 DECLSPEC_NOINLINE
125 static
126 VOID
127 TestStackWalk1(VOID)
128 {
129     ReturnAddresses[0] = _ReturnAddress();
130     TestStackWalk2();
131 }
132 
133 START_TEST(RtlStack)
134 {
135     TestStackWalk1();
136 }
137