-void wxCrashReportImpl::OutputStack(const CONTEXT *pCtx, int flags)
-{
- enum
- {
- Output_Stack,
- Output_Locals,
- Output_Max
-#ifndef _M_IX86
- // can't show locals under other architectures
- = Output_Locals
-#endif
- };
-
- for ( int step = 0; step < Output_Max; step++ )
- {
- // don't do things we're not asked for
- if ( (step == Output_Stack) && !(flags & wxCRASH_REPORT_STACK) ||
- (step == Output_Locals) && !(flags & wxCRASH_REPORT_LOCALS) )
- {
- continue;
- }
-
- // the context is going to be modified below so make a copy
- CONTEXT ctx = *pCtx;
-
- Output(_T("\r\n%s\r\n")
- _T(" # Address Frame Function SourceFile\r\n"),
- step == Output_Stack ? _T("Call stack") : _T("Local variables"));
-
- DWORD dwMachineType = 0;
-
- STACKFRAME sf;
- wxZeroMemory(sf);
-
-#ifdef _M_IX86
- // Initialize the STACKFRAME structure for the first call. This is
- // only necessary for Intel CPUs, and isn't mentioned in the
- // documentation.
- sf.AddrPC.Offset = ctx.Eip;
- sf.AddrPC.Mode = AddrModeFlat;
- sf.AddrStack.Offset = ctx.Esp;
- sf.AddrStack.Mode = AddrModeFlat;
- sf.AddrFrame.Offset = ctx.Ebp;
- sf.AddrFrame.Mode = AddrModeFlat;
-
- dwMachineType = IMAGE_FILE_MACHINE_I386;
-#endif // _M_IX86
-
- const HANDLE hProcess = GetCurrentProcess();
- const HANDLE hThread = GetCurrentThread();
-
- // first show just the call stack
- int frame = 0;
- for ( ;; )
- {
- // Get the next stack frame
- if ( !StackWalk(dwMachineType,
- hProcess,
- hThread,
- &sf,
- &ctx,
- 0,
- SymFunctionTableAccess,
- SymGetModuleBase,
- 0) )
- {
- break;
- }
-
- // Basic sanity check to make sure the frame is OK.
- if ( !sf.AddrFrame.Offset )
- break;
-
- Output(_T("%2d %08x %08x "),
- frame++, sf.AddrPC.Offset, sf.AddrFrame.Offset);
-
- // Get the name of the function for this stack frame entry
- BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + 1024 ];
- PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
- pSymbol->SizeOfStruct = sizeof(symbolBuffer);
- pSymbol->MaxNameLen = 1024;
-
- // Displacement of the input address, relative to the start of the
- // symbol
- DWORD64 symDisplacement = 0;
-
- if ( SymFromAddr(hProcess, sf.AddrPC.Offset,
- &symDisplacement,pSymbol) )
- {
- Output(_T("%hs()+%#") wxLongLongFmtSpec _T("x"),
- pSymbol->Name, symDisplacement);
- }
- else // No symbol found. Print out the logical address instead.
- {
- TCHAR szModule[MAX_PATH];
- DWORD section,
- offset;
-
- if ( !GetLogicalAddress((PVOID)sf.AddrPC.Offset,
- szModule, sizeof(szModule),
- section, offset) )
- {
- szModule[0] = _T('\0');
- section =
- offset = 0;
- }
-
- Output(_T("%04x:%08x %s"), section, offset, szModule);
- }
-
- // Get the source line for this stack frame entry
- IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
- DWORD dwLineDisplacement;
- if ( SymGetLineFromAddr(hProcess, sf.AddrPC.Offset,
- &dwLineDisplacement, &lineInfo ))
- {
- Output(_T(" %s line %u"),
- lineInfo.FileName, lineInfo.LineNumber);
- }
-
- OutputEndl();
-
-
-#ifdef _M_IX86
- // on the second iteration also show the local variables and
- // parameters
- if ( step == Output_Locals )
- {
- // Use SymSetContext to get just the locals/params for this
- // frame
- IMAGEHLP_STACK_FRAME imagehlpStackFrame;
- imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset;
- SymSetContext(hProcess, &imagehlpStackFrame, 0);
-
- // Enumerate the locals/parameters
- m_sfCurrent = &sf;
- SymEnumSymbols(hProcess, 0, 0, EnumerateSymbolsCallback, this);
-
- OutputEndl();
- }
-#endif // _M_IX86
- }
- }
-}
-
-void wxCrashReportImpl::OutputGlobals(HANDLE hModule)
-{
-#ifdef _M_IX86
- Output(_T("\r\nGlobal variables:\r\n"));
-
- m_sfCurrent = NULL;
- SymEnumSymbols(::GetCurrentProcess(), (DWORD64)hModule, NULL,
- EnumerateSymbolsCallback, this);
-#endif // _M_IX86
-}
-
-bool wxCrashReportImpl::ResolveSymFunctions(const wxDynamicLibrary& dllDbgHelp)
-{
- #define LOAD_SYM_FUNCTION(name) \
- name = (name ## _t) dllDbgHelp.GetSymbol(#name); \
- if ( !name ) \
- { \
- Output(_T("\r\nFunction ") __XFILE__(#name) \
- _T("() not found.\r\n")); \
- return false; \
- }
-
- LOAD_SYM_FUNCTION(SymSetOptions);
- LOAD_SYM_FUNCTION(SymInitialize);
- LOAD_SYM_FUNCTION(StackWalk);
- LOAD_SYM_FUNCTION(SymFromAddr);
- LOAD_SYM_FUNCTION(SymFunctionTableAccess);
- LOAD_SYM_FUNCTION(SymGetModuleBase);
- LOAD_SYM_FUNCTION(SymGetLineFromAddr);
- LOAD_SYM_FUNCTION(SymSetContext);
- LOAD_SYM_FUNCTION(SymEnumSymbols);
- LOAD_SYM_FUNCTION(SymGetTypeInfo);
-
- #undef LOAD_SYM_FUNCTION
-
- return true;
-}