/***************************************************************************
- * Copyright (C) 2005-09 by the Quassel Project *
+ * Copyright (C) 2005-2014 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "quassel.h"
#include <QFile>
#include <QTextStream>
-void loadHelpStackFrame(IMAGEHLP_STACK_FRAME &ihsf, const STACKFRAME64 &stackFrame) {
- ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));
- ihsf.InstructionOffset = stackFrame.AddrPC.Offset;
- ihsf.FrameOffset = stackFrame.AddrFrame.Offset;
+void 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 EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) {
- QStringList *params = (QStringList *)user;
- if(symInfo->Flags & SYMFLAG_PARAMETER) {
- params->append(symInfo->Name);
- }
- return TRUE;
+
+BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user)
+{
+ QStringList *params = (QStringList *)user;
+ if (symInfo->Flags & SYMFLAG_PARAMETER) {
+ params->append(symInfo->Name);
+ }
+ return TRUE;
}
struct EnumModulesContext {
- HANDLE hProcess;
- QTextStream &stream;
- EnumModulesContext(HANDLE hProcess, QTextStream &stream) : hProcess(hProcess), stream(stream) {}
+ HANDLE hProcess;
+ QTextStream &stream;
+ EnumModulesContext(HANDLE hProcess, QTextStream &stream) : hProcess(hProcess), stream(stream) {}
};
-BOOL CALLBACK EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) {
- IMAGEHLP_MODULE64 mod;
- EnumModulesContext *context = (EnumModulesContext *)UserContext;
- mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
- if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) {
- QString line = QString("%1 0x%2 Image: %3").arg(mod.ModuleName, -14)
- .arg(BaseOfDll, 8, 16, QLatin1Char('0'))
- .arg(mod.LoadedImageName);
- // qDebug() << qPrintable(line);
- context->stream << line << '\n';
-
- QString pdbName(mod.LoadedPdbName);
- if(!pdbName.isEmpty()) {
- QString line2 = QString("%1 %2").arg("", 32).arg(pdbName);
- // qDebug() << qPrintable(line2);
- context->stream << line2 << '\n';
+BOOL CALLBACK EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext)
+{
+ IMAGEHLP_MODULE64 mod;
+ EnumModulesContext *context = (EnumModulesContext *)UserContext;
+ mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
+ if (SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) {
+ QString line = QString("%1 0x%2 Image: %3").arg(mod.ModuleName, -14)
+ .arg(BaseOfDll, 8, 16, QLatin1Char('0'))
+ .arg(mod.LoadedImageName);
+ // qDebug() << qPrintable(line);
+ context->stream << line << '\n';
+
+ QString pdbName(mod.LoadedPdbName);
+ if (!pdbName.isEmpty()) {
+ QString line2 = QString("%1 %2").arg("", 32).arg(pdbName);
+ // qDebug() << qPrintable(line2);
+ context->stream << line2 << '\n';
+ }
}
- }
- return TRUE;
+ return TRUE;
}
-
-#if defined( _M_IX86 ) && defined(Q_CC_MSVC)
- // Disable global optimization and ignore /GS waning caused by
- // inline assembly.
- // not needed with mingw cause we can tell mingw which registers we use
+#if defined(_M_IX86) && defined(Q_CC_MSVC)
+// Disable global optimization and ignore /GS waning caused by
+// inline assembly.
+// not needed with mingw cause we can tell mingw which registers we use
#pragma optimize("g", off)
#pragma warning(push)
#pragma warning(disable : 4748)
#endif
-void Quassel::logBacktrace(const QString &filename) {
- DWORD MachineType;
- CONTEXT Context;
- STACKFRAME64 StackFrame;
+void Quassel::logBacktrace(const QString &filename)
+{
+ DWORD MachineType;
+ CONTEXT Context;
+ STACKFRAME64 StackFrame;
#ifdef _M_IX86
ZeroMemory(&Context, sizeof(CONTEXT));
Context.ContextFlags = CONTEXT_CONTROL;
-// TODO: port asssembler to mingw32
#ifdef __MINGW32__
-// asm("Label:\n\t"
-// "movl %%ebp,%0;\n\t"
-// "movl %%esp,%1;\n\t"
-// "movl $Label,%%eax;\n\t"
-// "movl %%eax,;\n\t"
-// :"=r"(Content.Epb),"=r"(Context.Esp),"=r"(Context.Eip)
-// ://no input
-// :"ebp","esp","eax");
+ asm ("Label:\n\t"
+ "movl %%ebp,%0;\n\t"
+ "movl %%esp,%1;\n\t"
+ "movl $Label,%%eax;\n\t"
+ "movl %%eax,%2;\n\t"
+ : "=r" (Context.Ebp), "=r" (Context.Esp), "=r" (Context.Eip)
+ : //no input
+ : "eax");
#else
_asm {
- Label:
- mov [Context.Ebp], ebp;
- mov [Context.Esp], esp;
- mov eax, [Label];
- mov [Context.Eip], eax;
+Label:
+ mov[Context.Ebp], ebp;
+ mov[Context.Esp], esp;
+ mov eax, [Label];
+ mov[Context.Eip], eax;
}
#endif
#else
RtlCaptureContext(&Context);
#endif
- ZeroMemory(&StackFrame, sizeof(STACKFRAME64));
+ ZeroMemory(&StackFrame, sizeof(STACKFRAME64));
#ifdef _M_IX86
- MachineType = IMAGE_FILE_MACHINE_I386;
- StackFrame.AddrPC.Offset = Context.Eip;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = Context.Ebp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = Context.Esp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
+ MachineType = IMAGE_FILE_MACHINE_I386;
+ StackFrame.AddrPC.Offset = Context.Eip;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = Context.Ebp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = Context.Esp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
- MachineType = IMAGE_FILE_MACHINE_AMD64;
- StackFrame.AddrPC.Offset = Context.Rip;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = Context.Rsp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = Context.Rsp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
+ MachineType = IMAGE_FILE_MACHINE_AMD64;
+ StackFrame.AddrPC.Offset = Context.Rip;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = Context.Rsp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = Context.Rsp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
- MachineType = IMAGE_FILE_MACHINE_IA64;
- StackFrame.AddrPC.Offset = Context.StIIP;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = Context.IntSp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
- StackFrame.AddrBStore.Offset= Context.RsBSP;
- StackFrame.AddrBStore.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = Context.IntSp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
+ MachineType = IMAGE_FILE_MACHINE_IA64;
+ StackFrame.AddrPC.Offset = Context.StIIP;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = Context.IntSp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ StackFrame.AddrBStore.Offset = Context.RsBSP;
+ StackFrame.AddrBStore.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = Context.IntSp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
#else
#error "Unsupported platform"
#endif
- //EnterCriticalSection(&DbgHelpLock);
-
- QFile logFile(filename);
- logFile.open(QIODevice::Append);
- QTextStream logStream(&logFile);
-
- HANDLE hProcess = GetCurrentProcess();
- HANDLE hThread = GetCurrentThread();
- SymInitialize(hProcess, NULL, TRUE);
-
- DWORD64 dwDisplacement;
-
- ULONG64 buffer[(sizeof(SYMBOL_INFO) +
- MAX_SYM_NAME*sizeof(TCHAR) +
- sizeof(ULONG64) - 1) / sizeof(ULONG64)];
- PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
- pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- pSymbol->MaxNameLen = MAX_SYM_NAME;
-
- IMAGEHLP_MODULE64 mod;
- mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
-
- IMAGEHLP_STACK_FRAME ihsf;
- ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));
-
- int i = 0;
- while(StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) {
- if(i == 128)
- break;
-
- loadHelpStackFrame(ihsf, StackFrame);
- if(StackFrame.AddrPC.Offset != 0) { // Valid frame.
-
- QString fileName("???");
- if(SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) {
- fileName = QString(mod.ImageName);
- int slashPos = fileName.lastIndexOf('\\');
- if(slashPos != -1)
- fileName = fileName.mid(slashPos + 1);
- }
- QString funcName;
- if(SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) {
- funcName = QString(pSymbol->Name);
- } else {
- funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'));
- }
- QStringList params;
- SymSetContext(hProcess, &ihsf, NULL);
- SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms);
-
- QString debugLine = QString("#%1 %2 0x%3 %4(%5)").arg(i, 3, 10)
- .arg(fileName, -20)
- .arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'))
- .arg(funcName)
- .arg(params.join(", "));
- // qDebug() << qPrintable(debugLine);
- logStream << debugLine << '\n';
- i++;
- } else {
- break; // we're at the end.
+ //EnterCriticalSection(&DbgHelpLock);
+
+ QFile logFile(filename);
+ logFile.open(QIODevice::Append);
+ QTextStream logStream(&logFile);
+
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hThread = GetCurrentThread();
+ SymInitialize(hProcess, NULL, TRUE);
+
+ DWORD64 dwDisplacement;
+
+ ULONG64 buffer[(sizeof(SYMBOL_INFO) +
+ MAX_SYM_NAME*sizeof(TCHAR) +
+ sizeof(ULONG64) - 1) / sizeof(ULONG64)];
+ PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
+ pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ pSymbol->MaxNameLen = MAX_SYM_NAME;
+
+ IMAGEHLP_MODULE64 mod;
+ mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
+
+ IMAGEHLP_STACK_FRAME ihsf;
+ ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));
+
+ int i = 0;
+ while (StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) {
+ if (i == 128)
+ break;
+
+ loadHelpStackFrame(ihsf, StackFrame);
+ if (StackFrame.AddrPC.Offset != 0) { // Valid frame.
+ QString fileName("???");
+ if (SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) {
+ fileName = QString(mod.ImageName);
+ int slashPos = fileName.lastIndexOf('\\');
+ if (slashPos != -1)
+ fileName = fileName.mid(slashPos + 1);
+ }
+ QString funcName;
+ if (SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) {
+ funcName = QString(pSymbol->Name);
+ }
+ else {
+ funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'));
+ }
+ QStringList params;
+ SymSetContext(hProcess, &ihsf, NULL);
+ SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms);
+
+ QString debugLine = QString("#%1 %2 0x%3 %4(%5)").arg(i, 3, 10)
+ .arg(fileName, -20)
+ .arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'))
+ .arg(funcName)
+ .arg(params.join(", "));
+ // qDebug() << qPrintable(debugLine);
+ logStream << debugLine << '\n';
+ i++;
+ }
+ else {
+ break; // we're at the end.
+ }
}
- }
- // qDebug() << "List of linked Modules:";
- logStream << "\n\nList of linked Modules:\n";
- EnumModulesContext modulesContext(hProcess, logStream);
- SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext);
+ // qDebug() << "List of linked Modules:";
+ logStream << "\n\nList of linked Modules:\n";
+ EnumModulesContext modulesContext(hProcess, logStream);
+ SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext);
- logFile.close();
+ logFile.close();
}
+
+
#if defined(_M_IX86) && defined(Q_CC_MSVC)
#pragma warning(pop)
#pragma optimize("g", on)