|
|
|
@ -23,44 +23,72 @@
@@ -23,44 +23,72 @@
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
#include <QTextStream> |
|
|
|
|
#ifdef __MINGW32__ |
|
|
|
|
#include <cxxabi.h> |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
namespace straceWin{ |
|
|
|
|
namespace straceWin |
|
|
|
|
{ |
|
|
|
|
void loadHelpStackFrame(IMAGEHLP_STACK_FRAME&, const STACKFRAME64&); |
|
|
|
|
BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO, ULONG, PVOID); |
|
|
|
|
BOOL CALLBACK EnumModulesCB(LPCSTR, DWORD64, PVOID); |
|
|
|
|
const QString getBacktrace(); |
|
|
|
|
struct EnumModulesContext; |
|
|
|
|
// Also works for MinGW64
|
|
|
|
|
#ifdef __MINGW32__ |
|
|
|
|
void demangle(QString& str); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void straceWin::loadHelpStackFrame(IMAGEHLP_STACK_FRAME &ihsf, const STACKFRAME64 &stackFrame) { |
|
|
|
|
#ifdef __MINGW32__ |
|
|
|
|
void straceWin::demangle(QString& str) |
|
|
|
|
{ |
|
|
|
|
char const* inStr = qPrintable("_" + str); // Really need that underline or demangling will fail
|
|
|
|
|
int status = 0; |
|
|
|
|
size_t outSz = 0; |
|
|
|
|
char* demangled_name = abi::__cxa_demangle(inStr, 0, &outSz, &status); |
|
|
|
|
if (status == 0) { |
|
|
|
|
str = QString::fromLocal8Bit(demangled_name); |
|
|
|
|
if (outSz > 0) |
|
|
|
|
free(demangled_name); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
void straceWin::loadHelpStackFrame(IMAGEHLP_STACK_FRAME& ihsf, const STACKFRAME64& stackFrame) |
|
|
|
|
{ |
|
|
|
|
ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); |
|
|
|
|
ihsf.InstructionOffset = stackFrame.AddrPC.Offset; |
|
|
|
|
ihsf.FrameOffset = stackFrame.AddrFrame.Offset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
BOOL CALLBACK straceWin::EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) { |
|
|
|
|
BOOL CALLBACK straceWin::EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) |
|
|
|
|
{ |
|
|
|
|
Q_UNUSED(size) |
|
|
|
|
QStringList* params = (QStringList*)user; |
|
|
|
|
if(symInfo->Flags & SYMFLAG_PARAMETER) { |
|
|
|
|
if (symInfo->Flags & SYMFLAG_PARAMETER) |
|
|
|
|
params->append(symInfo->Name); |
|
|
|
|
} |
|
|
|
|
return TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct straceWin::EnumModulesContext { |
|
|
|
|
struct straceWin::EnumModulesContext |
|
|
|
|
{ |
|
|
|
|
HANDLE hProcess; |
|
|
|
|
QTextStream& stream; |
|
|
|
|
EnumModulesContext(HANDLE hProcess, QTextStream& stream): hProcess(hProcess), stream(stream) {} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
BOOL CALLBACK straceWin::EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) { |
|
|
|
|
BOOL CALLBACK straceWin::EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) |
|
|
|
|
{ |
|
|
|
|
Q_UNUSED(ModuleName) |
|
|
|
|
IMAGEHLP_MODULE64 mod; |
|
|
|
|
EnumModulesContext* context = (EnumModulesContext*)UserContext; |
|
|
|
|
mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); |
|
|
|
|
if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) { |
|
|
|
|
QString moduleBase = QString("0x%1").arg(BaseOfDll, 8, 16, QLatin1Char('0')); |
|
|
|
|
QString moduleBase = QString("0x%1").arg(BaseOfDll, 16, 16, QLatin1Char('0')); |
|
|
|
|
QString line = QString("%1 %2 Image: %3") |
|
|
|
|
.arg(mod.ModuleName, -14) |
|
|
|
|
.arg(mod.ModuleName, -25) |
|
|
|
|
.arg(moduleBase, -13) |
|
|
|
|
.arg(mod.LoadedImageName); |
|
|
|
|
context->stream << line << '\n'; |
|
|
|
@ -86,7 +114,8 @@ BOOL CALLBACK straceWin::EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVO
@@ -86,7 +114,8 @@ BOOL CALLBACK straceWin::EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVO
|
|
|
|
|
#pragma warning(push) |
|
|
|
|
#pragma warning(disable : 4748) |
|
|
|
|
#endif |
|
|
|
|
const QString straceWin::getBacktrace() { |
|
|
|
|
const QString straceWin::getBacktrace() |
|
|
|
|
{ |
|
|
|
|
DWORD MachineType; |
|
|
|
|
CONTEXT Context; |
|
|
|
|
STACKFRAME64 StackFrame; |
|
|
|
@ -173,6 +202,7 @@ const QString straceWin::getBacktrace() {
@@ -173,6 +202,7 @@ const QString straceWin::getBacktrace() {
|
|
|
|
|
ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); |
|
|
|
|
|
|
|
|
|
int i = 0; |
|
|
|
|
|
|
|
|
|
while(StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) { |
|
|
|
|
if(i == 128) |
|
|
|
|
break; |
|
|
|
@ -190,23 +220,38 @@ const QString straceWin::getBacktrace() {
@@ -190,23 +220,38 @@ const QString straceWin::getBacktrace() {
|
|
|
|
|
QString funcName; |
|
|
|
|
if(SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) { |
|
|
|
|
funcName = QString(pSymbol->Name); |
|
|
|
|
} else { |
|
|
|
|
#ifdef __MINGW32__ |
|
|
|
|
demangle(funcName); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')); |
|
|
|
|
} |
|
|
|
|
QStringList params; |
|
|
|
|
SymSetContext(hProcess, &ihsf, NULL); |
|
|
|
|
#ifndef __MINGW32__ |
|
|
|
|
QStringList params; |
|
|
|
|
SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
QString insOffset = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')); |
|
|
|
|
QString debugLine = QString("#%1 %2 %3 %4(%5)") |
|
|
|
|
QString insOffset = QString("0x%1").arg(ihsf.InstructionOffset, 16, 16, QLatin1Char('0')); |
|
|
|
|
QString formatLine = "#%1 %2 %3 %4"; |
|
|
|
|
#ifndef __MINGW32__ |
|
|
|
|
formatLine += "(%5)"; |
|
|
|
|
#endif |
|
|
|
|
QString debugLine = formatLine |
|
|
|
|
.arg(i, 3, 10) |
|
|
|
|
.arg(fileName, -20) |
|
|
|
|
.arg(insOffset, -11) |
|
|
|
|
.arg(funcName) |
|
|
|
|
#ifndef __MINGW32__ |
|
|
|
|
.arg(params.join(", ")); |
|
|
|
|
#else |
|
|
|
|
; |
|
|
|
|
#endif |
|
|
|
|
logStream << debugLine << '\n'; |
|
|
|
|
i++; |
|
|
|
|
} else { |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
break; // we're at the end.
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|