void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) { TCHAR symInfo[BUFFERSIZE] = _T("?"); TCHAR srcInfo[BUFFERSIZE] = _T("?"); GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n"); }
void FunctionParameterInfo() { STACKFRAME callStack; BOOL bResult = FALSE; CONTEXT context; TCHAR lpszFnInfo[BUFFERSIZE]; HANDLE hProcess = GetCurrentProcess(); HANDLE hThread = GetCurrentThread(); ::ZeroMemory( &context, sizeof(context) ); context.ContextFlags = CONTEXT_FULL; if ( !GetThreadContext( hThread, &context ) ) { OutputDebugStringFormat( _T("Function info(thread=0x%X) failed.\n") ); return; } ::ZeroMemory( &callStack, sizeof(callStack) ); callStack.AddrPC.Offset = context.Eip; callStack.AddrStack.Offset = context.Esp; callStack.AddrFrame.Offset = context.Ebp; callStack.AddrPC.Mode = AddrModeFlat; callStack.AddrStack.Mode = AddrModeFlat; callStack.AddrFrame.Mode = AddrModeFlat; for( ULONG index = 0; index < 2; index++ ) { bResult = StackWalk( IMAGE_FILE_MACHINE_I386, hProcess, hThread, &callStack, NULL, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL); } if ( bResult && callStack.AddrFrame.Offset != 0) { GetFunctionInfoFromAddresses( callStack.AddrPC.Offset, callStack.AddrFrame.Offset, lpszFnInfo ); OutputDebugStringFormat( _T("Function info(thread=0x%X) : %s\n"), GetCurrentThreadId(), lpszFnInfo ); } else OutputDebugStringFormat( _T("Function info(thread=0x%X) failed.\n") ); }
void StackTrace( HANDLE hThread, LPCTSTR lpszMessage ) { STACKFRAME callStack; BOOL bResult; CONTEXT context; TCHAR symInfo[BUFFERSIZE] = _T("?"); TCHAR srcInfo[BUFFERSIZE] = _T("?"); HANDLE hProcess = GetCurrentProcess(); // If it's not this thread, let's suspend it, and resume it at the end if ( hThread != GetCurrentThread() ) if ( SuspendThread( hThread ) == -1 ) { // whaaat ?! OutputDebugStringFormat( _T("Call stack info(thread=0x%X) failed.\n") ); return; } ::ZeroMemory( &context, sizeof(context) ); context.ContextFlags = CONTEXT_FULL; if ( !GetThreadContext( hThread, &context ) ) { OutputDebugStringFormat( _T("Call stack info(thread=0x%X) failed.\n") ); return; } ::ZeroMemory( &callStack, sizeof(callStack) ); callStack.AddrPC.Offset = context.Eip; callStack.AddrStack.Offset = context.Esp; callStack.AddrFrame.Offset = context.Ebp; callStack.AddrPC.Mode = AddrModeFlat; callStack.AddrStack.Mode = AddrModeFlat; callStack.AddrFrame.Mode = AddrModeFlat; for( ULONG index = 0; ; index++ ) { bResult = StackWalk( IMAGE_FILE_MACHINE_I386, hProcess, hThread, &callStack, NULL, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL); if ( index == 0 ) continue; if( !bResult || callStack.AddrFrame.Offset == 0 ) break; GetFunctionInfoFromAddresses( callStack.AddrPC.Offset, callStack.AddrFrame.Offset, symInfo ); GetSourceInfoFromAddress( callStack.AddrPC.Offset, srcInfo ); OutputDebugStringFormat( _T(" %s : %s\n"), srcInfo, symInfo ); } if ( hThread != GetCurrentThread() ) ResumeThread( hThread ); }