Reactos
at master 166 lines 5.1 kB view raw
1/* 2 * PROJECT: ReactOS API tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Test for RtlQueryProcessBackTraceInformation & RtlLogStackBackTrace 5 * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8#include "loadconfig.h" 9 10 11// This test serves 2 purposes: 12// 1. It tests RtlQueryProcessBackTraceInformation & RtlLogStackBackTrace 13// 2. It tests the correct activation of IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (see also common.c) 14 15NTSTATUS NTAPI RtlQueryProcessBackTraceInformation(IN OUT PRTL_DEBUG_INFORMATION Buffer); 16 17 18// Seems that this struct is wrong in our sdk? 19typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION_32 20{ 21 PVOID SymbolicBackTrace; 22 ULONG TraceCount; 23 USHORT Index; 24 USHORT Depth; 25 PVOID BackTrace[32]; 26} RTL_PROCESS_BACKTRACE_INFORMATION_32, *PRTL_PROCESS_BACKTRACE_INFORMATION_32; 27 28 29static PVOID g_Call_Address; 30static PVOID g_PreviousReturnAddress; 31 32__declspec(noinline) 33PVOID GetFunctionAddress() 34{ 35 return _ReturnAddress(); 36} 37 38__declspec(noinline) 39USHORT Call_Backtrace_2() 40{ 41 USHORT Index; 42 Index = RtlLogStackBackTrace(); 43 ok(Index != 0, "RtlLogStackBackTrace failed\n"); 44 return Index; 45} 46 47 48__declspec(noinline) 49USHORT Call_Backtrace_1() 50{ 51 USHORT Index; 52 // It seems that the function calling RtlLogStackBackTrace is skipped, 53 // so we wrap it in a deeper nested function to be able to check it 54 g_Call_Address = GetFunctionAddress(); 55 g_PreviousReturnAddress = _ReturnAddress(); 56 Index = Call_Backtrace_2(); 57 return Index; 58} 59 60static void Check_Stacktrace(PVOID* BackTrace, USHORT Depth) 61{ 62 ok(Depth > 2, "Unexpected Depth: %lu\n", (ULONG)Depth); 63 if (Depth > 2) 64 { 65 ULONG_PTR EndAddress = ((ULONG_PTR)g_Call_Address + 0x20); 66 ok(BackTrace[0] >= g_Call_Address && (ULONG_PTR)BackTrace[0] < EndAddress, 67 "Unexpected return: %p, expected between %p and %p\n", BackTrace[0], g_Call_Address, (PVOID)EndAddress); 68 ok(BackTrace[1] == g_PreviousReturnAddress, "Unexpected return: %p, expected: %p\n", 69 BackTrace[1], g_PreviousReturnAddress); 70 } 71} 72 73static void test_QueryBacktrace(PRTL_DEBUG_INFORMATION Buffer1, PRTL_DEBUG_INFORMATION Buffer2) 74{ 75 NTSTATUS Status; 76 USHORT StackTrace; 77 PRTL_PROCESS_BACKTRACES Backtraces; 78 ULONG OldNumberOfBackTraces, n; 79 PRTL_PROCESS_BACKTRACE_INFORMATION_32 FirstBacktrace; 80 int found = 0; 81 82 Status = RtlQueryProcessBackTraceInformation(Buffer1); 83 ok_hex(Status, STATUS_SUCCESS); 84 if (Status != STATUS_SUCCESS) 85 return; 86 87 Backtraces = Buffer1->BackTraces; 88 ok(Backtraces != NULL, "No BackTraces\n"); 89 if (!Backtraces) 90 return; 91 92 OldNumberOfBackTraces = Backtraces->NumberOfBackTraces; 93 // Capture a stacktrace 94 StackTrace = Call_Backtrace_1(); 95 96 // Show that the old debugbuffer is not changed 97 ok(OldNumberOfBackTraces == Backtraces->NumberOfBackTraces, "Debug buffer changed! (%lu => %lu)\n", 98 OldNumberOfBackTraces, Backtraces->NumberOfBackTraces); 99 100 // Ask for a new snapshot 101 Status = RtlQueryProcessBackTraceInformation(Buffer2); 102 ok_hex(Status, STATUS_SUCCESS); 103 if (Status != STATUS_SUCCESS) 104 return; 105 106 Backtraces = Buffer2->BackTraces; 107 ok(Backtraces != NULL, "No BackTraces\n"); 108 if (!Backtraces) 109 return; 110 111 ok(OldNumberOfBackTraces+1 == Backtraces->NumberOfBackTraces, "Stacktrace not added! (%lu => %lu)\n", 112 OldNumberOfBackTraces, Backtraces->NumberOfBackTraces); 113 114 FirstBacktrace = (PRTL_PROCESS_BACKTRACE_INFORMATION_32)&Backtraces->BackTraces[0]; 115 trace("NumberOfBackTraces=%lu\n", Backtraces->NumberOfBackTraces); 116 for (n = 0; n < Backtraces->NumberOfBackTraces; ++n) 117 { 118 PRTL_PROCESS_BACKTRACE_INFORMATION_32 Info = FirstBacktrace + n; 119#if 0 120 USHORT j; 121 122 trace("BackTraces[%02lu]->SymbolicBackTrace = %p\n", n, Info->SymbolicBackTrace); 123 trace("BackTraces[%02lu]->TraceCount = %lu\n", n, Info->TraceCount); 124 trace("BackTraces[%02lu]->Index = %lu\n", n, (ULONG)Info->Index); 125 trace("BackTraces[%02lu]->Depth = %lu\n", n, (ULONG)Info->Depth); 126 for (j = 0; j < Info->Depth; ++j) 127 { 128 trace("BackTraces[%02lu]->BackTrace[%02u] = %p\n", n, j, Info->BackTrace[j]); 129 } 130 trace("\n"); 131#endif 132 if (Info->Index == StackTrace) 133 { 134 found = 1; 135 Check_Stacktrace(Info->BackTrace, Info->Depth); 136 } 137 } 138 ok(found, "Stacktrace not found :(\n"); 139} 140 141 142START_TEST(stacktrace) 143{ 144 PRTL_DEBUG_INFORMATION Buffer1, Buffer2; 145 146 if (!check_loadconfig()) 147 return; 148 149 skip("QueryBacktrace not implemented yet\n"); 150 return; 151 152 Buffer1 = RtlCreateQueryDebugBuffer(0, FALSE); 153 ok(Buffer1 != NULL, "Failed!\n"); 154 if (Buffer1) 155 { 156 Buffer2 = RtlCreateQueryDebugBuffer(0, FALSE); 157 ok(Buffer2 != NULL, "Failed!\n"); 158 if (Buffer2) 159 { 160 test_QueryBacktrace(Buffer1, Buffer2); 161 RtlDestroyQueryDebugBuffer(Buffer2); 162 } 163 164 RtlDestroyQueryDebugBuffer(Buffer1); 165 } 166}