// -------------------------------------------------------------------------- int ctkBackTracePrivate::trace(void** array, size_t n) const { if(n>=63) n=62; if (s_pfnCaptureStackBackTrace == 0) { const HMODULE hNtDll = ::GetModuleHandleW(L"ntdll.dll"); reinterpret_cast<void*&>(s_pfnCaptureStackBackTrace) = ::GetProcAddress(hNtDll, "RtlCaptureStackBackTrace"); } if (s_pfnCaptureStackBackTrace != 0) { return s_pfnCaptureStackBackTrace(0, n, array, 0); } return 0; }
// getStackTrace - Traces the stack as far back as possible, or until 'maxdepth' // frames have been traced. Populates the CallStack with one entry for each // stack frame traced. // // Note: This function uses a very efficient method to walk the stack from // frame to frame, so it is quite fast. However, unconventional stack frames // (such as those created when frame pointer omission optimization is used) // will not be successfully walked by this function and will cause the // stack trace to terminate prematurely. // // - maxdepth (IN): Maximum number of frames to trace back. // // - framepointer (IN): Frame (base) pointer at which to begin the stack trace. // If NULL, then the stack trace will begin at this function. // // Return Value: // // None. // VOID FastCallStack::getStackTrace (UINT32 maxdepth, const context_t& context) { UINT32 count = 0; UINT_PTR* framePointer = context.fp; #if defined(_M_IX86) while (count < maxdepth) { if (*framePointer < (UINT_PTR)framePointer) { if (*framePointer == NULL) { // Looks like we reached the end of the stack. break; } else { // Invalid frame pointer. Frame pointer addresses should always // increase as we move up the stack. m_status |= CALLSTACK_STATUS_INCOMPLETE; break; } } if (*framePointer & (sizeof(UINT_PTR*) - 1)) { // Invalid frame pointer. Frame pointer addresses should always // be aligned to the size of a pointer. This probably means that // we've encountered a frame that was created by a module built with // frame pointer omission (FPO) optimization turned on. m_status |= CALLSTACK_STATUS_INCOMPLETE; break; } if (IsBadReadPtr((UINT*)*framePointer, sizeof(UINT_PTR*))) { // Bogus frame pointer. Again, this probably means that we've // encountered a frame built with FPO optimization. m_status |= CALLSTACK_STATUS_INCOMPLETE; break; } count++; push_back(*(framePointer + 1)); framePointer = (UINT_PTR*)*framePointer; } #elif defined(_M_X64) UINT32 maxframes = min(62, maxdepth + 10); static USHORT (WINAPI *s_pfnCaptureStackBackTrace)(ULONG FramesToSkip, ULONG FramesToCapture, PVOID* BackTrace, PULONG BackTraceHash) = 0; if (s_pfnCaptureStackBackTrace == 0) { const HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll"); reinterpret_cast<void*&>(s_pfnCaptureStackBackTrace) = ::GetProcAddress(hNtDll, "RtlCaptureStackBackTrace"); if (s_pfnCaptureStackBackTrace == 0) return; } UINT_PTR* myFrames = new UINT_PTR[maxframes]; ZeroMemory(myFrames, sizeof(UINT_PTR) * maxframes); s_pfnCaptureStackBackTrace(0, maxframes, (PVOID*)myFrames, NULL); UINT32 startIndex = 0; while (count < maxframes) { if (myFrames[count] == 0) break; if (myFrames[count] == *(framePointer + 1)) startIndex = count; count++; } count = startIndex; while (count < maxframes) { if (myFrames[count] == 0) break; push_back(myFrames[count]); count++; } delete [] myFrames; #endif }
xgc_void GetStackTrace( StackFrameSequence& FrameSequence ) { UINT_PTR* fp = (UINT_PTR*) _AddressOfReturnAddress(); UINT_PTR* framePointer = (UINT_PTR*) fp - 1; FrameSequence.Count = 0; #if defined(_M_IX86) while ( FrameSequence.Count < MAX_FRAME_SAVE) { if (*framePointer < (UINT_PTR)framePointer) { if (*framePointer == NULL) { // Looks like we reached the end of the stack. break; } else { // Invalid frame pointer. Frame pointer addresses should always // increase as we move up the stack. break; } } if (*framePointer & (sizeof(UINT_PTR*) - 1)) { // Invalid frame pointer. Frame pointer addresses should always // be aligned to the size of a pointer. This probably means that // we've encountered a frame that was created by a module built with // frame pointer omission (FPO) optimization turned on. break; } if (IsBadReadPtr((UINT*)*framePointer, sizeof(UINT_PTR*))) { // Bogus frame pointer. Again, this probably means that we've // encountered a frame built with FPO optimization. break; } //push_back(*(framePointer + 1)); FrameSequence.Frame[ FrameSequence.Count ] = *(framePointer + 1); FrameSequence.Count += 1; framePointer = (UINT_PTR*)*framePointer; } #elif defined(_M_X64) xgc_uint32 maxframes = XGC_MIN( 62, MAX_FRAME_SAVE + 10 ); static USHORT( WINAPI *s_pfnCaptureStackBackTrace )( ULONG FramesToSkip, ULONG FramesToCapture, PVOID* BackTrace, PULONG BackTraceHash ) = 0; if( s_pfnCaptureStackBackTrace == 0 ) { const HMODULE hNtDll = GetModuleHandleW( L"ntdll.dll" ); reinterpret_cast<void*&>( s_pfnCaptureStackBackTrace ) = ::GetProcAddress( hNtDll, "RtlCaptureStackBackTrace" ); if( s_pfnCaptureStackBackTrace == 0 ) return; } UINT_PTR* myFrames = XGC_NEW UINT_PTR[maxframes]; ZeroMemory( myFrames, sizeof( UINT_PTR ) * maxframes ); s_pfnCaptureStackBackTrace( 0, maxframes, (PVOID*) myFrames, NULL ); xgc_uint32 startIndex = 0; xgc_uint32 count = 0; while( count < maxframes ) { if( myFrames[count] == 0 ) break; if( myFrames[count] == *( framePointer + 1 ) ) startIndex = count; count++; } FrameSequence.Count = 0; while( FrameSequence.Count < maxframes && FrameSequence.Count < XGC_COUNTOF( FrameSequence.Frame ) ) { if( myFrames[FrameSequence.Count] == 0 ) break; //push_back(myFrames[count]); FrameSequence.Frame[FrameSequence.Count] = (void*)myFrames[startIndex + FrameSequence.Count]; FrameSequence.Count += 1; } delete[] myFrames; #endif }