+ // Get the name of the function for this stack frame entry
+ BYTE symbolBuffer[ sizeof( SYMBOL_INFO ) + max_sym_name ];
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
+ pSymbol->SizeOfStruct = sizeof( SYMBOL_INFO );
+ pSymbol->MaxNameLen = max_sym_name;
+
+ DWORD64 symDisplacement = 0; // Displacement of the input address,
+ // relative to the start of the symbol
+
+ IMAGEHLP_MODULE64 module = { sizeof( IMAGEHLP_MODULE64 ) };
+ if ( SymGetModuleInfo64( m_hProcess, sf.AddrPC.Offset, &module ) ) {
+ outputStream << module.ModuleName << "!";
+
+ if ( SymFromAddr( m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol ) ) {
+ char undecoratedName[max_sym_name];
+ UnDecorateSymbolName( pSymbol->Name, undecoratedName, max_sym_name, UNDNAME_COMPLETE );
+
+ outputStream << undecoratedName;
+
+ outputStream << "(";
+ // Use SymSetContext to get just the locals/params for this frame
+ IMAGEHLP_STACK_FRAME imagehlpStackFrame;
+ imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset;
+ SymSetContext( m_hProcess, &imagehlpStackFrame, 0 );
+
+ // Enumerate the locals/parameters
+ EnumerateSymbolsContext context( sf, outputStream );
+ SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context );
+ outputStream << ")";
+
+ outputStream << " + " << Offset( reinterpret_cast<void*>( symDisplacement ) );
+
+ // Get the source line for this stack frame entry
+ IMAGEHLP_LINE64 lineInfo = { sizeof( IMAGEHLP_LINE64 ) };
+ DWORD dwLineDisplacement;
+ if ( SymGetLineFromAddr64( m_hProcess, sf.AddrPC.Offset,
+ &dwLineDisplacement, &lineInfo ) ) {
+ outputStream << " " << lineInfo.FileName << " line " << Unsigned( lineInfo.LineNumber );
+ }
+ }
+ else
+ {
+ outputStream << Address( reinterpret_cast<void*>( sf.AddrPC.Offset ) );
+ }
+ }