16 #include "qgsstacktrace.h"
30 QVector<QgsStackTrace::StackLine> QgsStackTrace::trace( _EXCEPTION_POINTERS *ExceptionInfo )
37 HANDLE process = GetCurrentProcess();
38 SymSetOptions( SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME );
41 if ( QgsStackTrace::mSymbolPaths.isEmpty() )
47 paths = QgsStackTrace::mSymbolPaths.toStdString().c_str();
50 SymInitialize( process, paths, TRUE );
54 CONTEXT context_record;
56 context_record = *ExceptionInfo->ContextRecord;
58 RtlCaptureContext( &context_record );
61 STACKFRAME64 stack_frame;
62 memset( &stack_frame, 0,
sizeof( stack_frame ) );
64 int machine_type = IMAGE_FILE_MACHINE_AMD64;
65 stack_frame.AddrPC.Offset = context_record.Rip;
66 stack_frame.AddrFrame.Offset = context_record.Rbp;
67 stack_frame.AddrStack.Offset = context_record.Rsp;
69 int machine_type = IMAGE_FILE_MACHINE_I386;
70 stack_frame.AddrPC.Offset = context_record.Eip;
71 stack_frame.AddrFrame.Offset = context_record.Ebp;
72 stack_frame.AddrStack.Offset = context_record.Esp;
74 stack_frame.AddrPC.Mode = AddrModeFlat;
75 stack_frame.AddrFrame.Mode = AddrModeFlat;
76 stack_frame.AddrStack.Mode = AddrModeFlat;
78 SYMBOL_INFO *symbol = ( SYMBOL_INFO * )
qgsMalloc(
sizeof( SYMBOL_INFO ) + MAX_SYM_NAME );
79 symbol->SizeOfStruct =
sizeof( SYMBOL_INFO );
80 symbol->MaxNameLen = MAX_SYM_NAME;
82 IMAGEHLP_LINE *line = ( IMAGEHLP_LINE * )
qgsMalloc(
sizeof( IMAGEHLP_LINE ) );
83 line->SizeOfStruct =
sizeof( IMAGEHLP_LINE );
85 IMAGEHLP_MODULE *module = ( IMAGEHLP_MODULE * )
qgsMalloc(
sizeof( IMAGEHLP_MODULE ) );
86 module->SizeOfStruct =
sizeof( IMAGEHLP_MODULE );
88 while ( StackWalk64( machine_type,
94 &SymFunctionTableAccess64,
99 DWORD64 displacement = 0;
101 if ( SymFromAddr( process, ( DWORD64 )stack_frame.AddrPC.Offset, &displacement, symbol ) )
103 DWORD dwDisplacement;
105 QgsStackTrace::StackLine stackline;
106 stackline.symbolName = QString( symbol->Name );
108 if ( SymGetLineFromAddr( process, ( DWORD64 ) stack_frame.AddrPC.Offset, &dwDisplacement, line ) )
110 stackline.fileName = QString( line->FileName );
111 stackline.lineNumber = QString::number( line->LineNumber );
115 stackline.fileName =
"(unknown file)";
116 stackline.lineNumber =
"(unknown line)";
119 if ( SymGetModuleInfo( process, ( DWORD64 ) stack_frame.AddrPC.Offset, module ) )
121 stackline.moduleName = module->ModuleName;
125 stackline.moduleName =
"(unknown module)";
128 stack.append( stackline );
135 SymCleanup( process );
139 QString QgsStackTrace::mSymbolPaths;
141 void QgsStackTrace::setSymbolPath( QString symbolPaths )
143 mSymbolPaths = symbolPaths;
149 QVector<QgsStackTrace::StackLine> QgsStackTrace::trace(
unsigned int maxFrames )
151 Q_UNUSED( maxFrames )
162 bool QgsStackTrace::StackLine::isQgisModule()
const
164 return moduleName.contains( QLatin1String(
"qgis" ), Qt::CaseInsensitive );
167 bool QgsStackTrace::StackLine::isValid()
const
169 return !( fileName.contains( QLatin1String(
"exe_common" ), Qt::CaseInsensitive ) ||
170 fileName.contains( QLatin1String(
"unknown" ), Qt::CaseInsensitive ) ||
171 lineNumber.contains( QLatin1String(
"unknown" ), Qt::CaseInsensitive ) );
void qgsFree(void *ptr)
Frees the memory space pointed to by ptr.
void * qgsMalloc(size_t size)
Allocates size bytes and returns a pointer to the allocated memory.