NTSTATUS CfixkrpCaptureStackTrace( __in_opt CONST PCONTEXT Context, __in PCFIX_STACKTRACE StackTrace, __in ULONG MaxFrames ) { #ifdef _WIN32 ULONG Index; PVOID FramesBuffer[ 64 ]; #endif if ( Context != NULL ) { // // Unfortunately, RtlWalkFrameChain cannot be passed // a CONTEXT. // return STATUS_NOT_IMPLEMENTED; } StackTrace->GetInformationStackFrame = NULL; // // N.B. CFIX_STACKTRACE uses ULONGLONGs, RtlWalkFrameChain // uses PVOIDs, so conversion is necessary on i386. // #ifdef _WIN32 StackTrace->FrameCount = RtlWalkFrameChain( FramesBuffer, min( MaxFrames, _countof( FramesBuffer ) ), 0 ); for ( Index = 0; Index < StackTrace->FrameCount; Index++ ) { StackTrace->Frames[ Index ] = ( ULONG_PTR ) FramesBuffer[ Index ]; } #else StackTrace->FrameCount = RtlWalkFrameChain( StackTrace->Frames, MaxFrames, 0 ); #endif return STATUS_SUCCESS; }
ULONG NTAPI DbgCaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture) { ULONG nFrameCount; memset(pFrames, 0x00, (nFramesToCapture + 1) * sizeof(PVOID)); nFrameCount = RtlWalkFrameChain(pFrames, nFramesToCapture, 0); if (nFrameCount < nFramesToCapture) { nFrameCount += RtlWalkFrameChain(pFrames + nFrameCount, nFramesToCapture - nFrameCount, 1); } return nFrameCount; }
static tracy_force_inline void* Callstack( int depth ) { assert( depth >= 1 && depth < 63 ); auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) ); const auto num = RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 ); *trace = num; return trace; }
USHORT NTAPI KeRosCaptureUserStackBackTrace(IN ULONG FramesToSkip, IN ULONG FramesToCapture, OUT PVOID *BackTrace, OUT PULONG BackTraceHash OPTIONAL) { PVOID Frames[2 * 64]; ULONG FrameCount; ULONG Hash = 0, i; /* Skip a frame for the caller */ FramesToSkip++; /* Don't go past the limit */ if ((FramesToCapture + FramesToSkip) >= 128) return 0; /* Do the back trace */ FrameCount = RtlWalkFrameChain(Frames, FramesToCapture + FramesToSkip, 1); /* Make sure we're not skipping all of them */ if (FrameCount <= FramesToSkip) return 0; /* Loop all the frames */ for (i = 0; i < FramesToCapture; i++) { /* Don't go past the limit */ if ((FramesToSkip + i) >= FrameCount) break; /* Save this entry and hash it */ BackTrace[i] = Frames[FramesToSkip + i]; Hash += PtrToUlong(BackTrace[i]); } /* Write the hash */ if (BackTraceHash) *BackTraceHash = Hash; /* Clear the other entries and return count */ RtlFillMemoryUlong(Frames, 128, 0); return (USHORT)i; }
USHORT RtlCaptureStackBackTrace( IN ULONG FramesToSkip, IN ULONG FramesToCapture, OUT PVOID *BackTrace, OUT PULONG BackTraceHash ) /*++ Routine Description: This routine walks up the stack frames, capturing the return address from each frame requested. This used to be implemented in assembly language and used to be unsafe in special contexts (DPC level). Right now it uses RtlWalkFrameChain that validates the chain of pointers and it guarantees not to take exceptions. Arguments: FramesToSkip - frames detected but not included in the stack trace FramesToCapture - frames to be captured in the stack trace buffer. One of the frames will be for RtlCaptureStackBackTrace. BackTrace - stack trace buffer BackTraceHash - very simple hash value that can be used to organize hash tables. It is just an arithmetic sum of the pointers in the stack trace buffer. Return Value: Number of return addresses returned in the stack trace buffer. --*/ { PVOID Trace [2 * MAX_STACK_DEPTH]; ULONG FramesFound; ULONG HashValue; ULONG Index; // // One more frame to skip for the "capture" function (WalkFrameChain). // FramesToSkip++; // // Sanity checks. // if (FramesToCapture + FramesToSkip >= 2 * MAX_STACK_DEPTH) { return 0; } FramesFound = RtlWalkFrameChain ( Trace, FramesToCapture + FramesToSkip, 0); if (FramesFound <= FramesToSkip) { return 0; } for (HashValue = 0, Index = 0; Index < FramesToCapture; Index++) { if (FramesToSkip + Index >= FramesFound) { break; } BackTrace[Index] = Trace[FramesToSkip + Index]; HashValue += PtrToUlong(BackTrace[Index]); } *BackTraceHash = HashValue; return (USHORT)Index; }