Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167/* * PROJECT: ReactOS API tests * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Test for RtlQueryProcessBackTraceInformation & RtlLogStackBackTrace * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org) */
#include "loadconfig.h"
// This test serves 2 purposes:// 1. It tests RtlQueryProcessBackTraceInformation & RtlLogStackBackTrace// 2. It tests the correct activation of IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (see also common.c)
NTSTATUS NTAPI RtlQueryProcessBackTraceInformation(IN OUT PRTL_DEBUG_INFORMATION Buffer);
// Seems that this struct is wrong in our sdk?typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION_32{ PVOID SymbolicBackTrace; ULONG TraceCount; USHORT Index; USHORT Depth; PVOID BackTrace[32];} RTL_PROCESS_BACKTRACE_INFORMATION_32, *PRTL_PROCESS_BACKTRACE_INFORMATION_32;
static PVOID g_Call_Address;static PVOID g_PreviousReturnAddress;
__declspec(noinline)PVOID GetFunctionAddress(){ return _ReturnAddress();}
__declspec(noinline)USHORT Call_Backtrace_2(){ USHORT Index; Index = RtlLogStackBackTrace(); ok(Index != 0, "RtlLogStackBackTrace failed\n"); return Index;}
__declspec(noinline)USHORT Call_Backtrace_1(){ USHORT Index; // It seems that the function calling RtlLogStackBackTrace is skipped, // so we wrap it in a deeper nested function to be able to check it g_Call_Address = GetFunctionAddress(); g_PreviousReturnAddress = _ReturnAddress(); Index = Call_Backtrace_2(); return Index;}
static void Check_Stacktrace(PVOID* BackTrace, USHORT Depth){ ok(Depth > 2, "Unexpected Depth: %lu\n", (ULONG)Depth); if (Depth > 2) { ULONG_PTR EndAddress = ((ULONG_PTR)g_Call_Address + 0x20); ok(BackTrace[0] >= g_Call_Address && (ULONG_PTR)BackTrace[0] < EndAddress, "Unexpected return: %p, expected between %p and %p\n", BackTrace[0], g_Call_Address, (PVOID)EndAddress); ok(BackTrace[1] == g_PreviousReturnAddress, "Unexpected return: %p, expected: %p\n", BackTrace[1], g_PreviousReturnAddress); }}
static void test_QueryBacktrace(PRTL_DEBUG_INFORMATION Buffer1, PRTL_DEBUG_INFORMATION Buffer2){ NTSTATUS Status; USHORT StackTrace; PRTL_PROCESS_BACKTRACES Backtraces; ULONG OldNumberOfBackTraces, n; PRTL_PROCESS_BACKTRACE_INFORMATION_32 FirstBacktrace; int found = 0;
Status = RtlQueryProcessBackTraceInformation(Buffer1); ok_hex(Status, STATUS_SUCCESS); if (Status != STATUS_SUCCESS) return;
Backtraces = Buffer1->BackTraces; ok(Backtraces != NULL, "No BackTraces\n"); if (!Backtraces) return;
OldNumberOfBackTraces = Backtraces->NumberOfBackTraces; // Capture a stacktrace StackTrace = Call_Backtrace_1();
// Show that the old debugbuffer is not changed ok(OldNumberOfBackTraces == Backtraces->NumberOfBackTraces, "Debug buffer changed! (%lu => %lu)\n", OldNumberOfBackTraces, Backtraces->NumberOfBackTraces);
// Ask for a new snapshot Status = RtlQueryProcessBackTraceInformation(Buffer2); ok_hex(Status, STATUS_SUCCESS); if (Status != STATUS_SUCCESS) return;
Backtraces = Buffer2->BackTraces; ok(Backtraces != NULL, "No BackTraces\n"); if (!Backtraces) return;
ok(OldNumberOfBackTraces+1 == Backtraces->NumberOfBackTraces, "Stacktrace not added! (%lu => %lu)\n", OldNumberOfBackTraces, Backtraces->NumberOfBackTraces);
FirstBacktrace = (PRTL_PROCESS_BACKTRACE_INFORMATION_32)&Backtraces->BackTraces[0]; trace("NumberOfBackTraces=%lu\n", Backtraces->NumberOfBackTraces); for (n = 0; n < Backtraces->NumberOfBackTraces; ++n) { PRTL_PROCESS_BACKTRACE_INFORMATION_32 Info = FirstBacktrace + n;#if 0 USHORT j;
trace("BackTraces[%02lu]->SymbolicBackTrace = %p\n", n, Info->SymbolicBackTrace); trace("BackTraces[%02lu]->TraceCount = %lu\n", n, Info->TraceCount); trace("BackTraces[%02lu]->Index = %lu\n", n, (ULONG)Info->Index); trace("BackTraces[%02lu]->Depth = %lu\n", n, (ULONG)Info->Depth); for (j = 0; j < Info->Depth; ++j) { trace("BackTraces[%02lu]->BackTrace[%02u] = %p\n", n, j, Info->BackTrace[j]); } trace("\n");#endif if (Info->Index == StackTrace) { found = 1; Check_Stacktrace(Info->BackTrace, Info->Depth); } } ok(found, "Stacktrace not found :(\n");}
START_TEST(stacktrace){ PRTL_DEBUG_INFORMATION Buffer1, Buffer2;
if (!check_loadconfig()) return;
skip("QueryBacktrace not implemented yet\n"); return;
Buffer1 = RtlCreateQueryDebugBuffer(0, FALSE); ok(Buffer1 != NULL, "Failed!\n"); if (Buffer1) { Buffer2 = RtlCreateQueryDebugBuffer(0, FALSE); ok(Buffer2 != NULL, "Failed!\n"); if (Buffer2) { test_QueryBacktrace(Buffer1, Buffer2); RtlDestroyQueryDebugBuffer(Buffer2); }
RtlDestroyQueryDebugBuffer(Buffer1); }}