this should make quassel compile on vs2005 again
[quassel.git] / src / common / logbacktrace_win.cpp
old mode 100755 (executable)
new mode 100644 (file)
index abcab48..779e5cb
-/***************************************************************************\r
- *   Copyright (C) 2005-08 by the Quassel IRC Team                         *\r
- *   devel@quassel-irc.org                                                 *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) version 3.                                           *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-\r
-#include "quassel.h"\r
-\r
-#include <windows.h>\r
-#include <dbghelp.h>\r
-#include <stdio.h>\r
-\r
-// #include <QDebug>\r
-#include <QFile>\r
-#include <QTextStream>\r
-\r
-void loadHelpStackFrame(IMAGEHLP_STACK_FRAME &ihsf, const STACKFRAME64 &stackFrame) {\r
-  ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));\r
-  ihsf.InstructionOffset = stackFrame.AddrPC.Offset;\r
-  ihsf.FrameOffset = stackFrame.AddrFrame.Offset;\r
-}\r
-\r
-BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) { \r
-  QStringList *params = (QStringList *)user;\r
-  if(symInfo->Flags & SYMFLAG_PARAMETER) {\r
-    params->append(symInfo->Name);\r
-  }\r
-  return TRUE;\r
-}\r
-\r
-\r
-struct EnumModulesContext {\r
-  HANDLE hProcess;\r
-  QTextStream &stream;\r
-  EnumModulesContext(HANDLE hProcess, QTextStream &stream) : hProcess(hProcess), stream(stream) {}\r
-};\r
-\r
-BOOL CALLBACK EnumModulesCB(PCTSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) {\r
-  IMAGEHLP_MODULE64 mod;\r
-  EnumModulesContext *context = (EnumModulesContext *)UserContext;\r
-  mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);\r
-  if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) {\r
-    QString line = QString("%1 0x%2 Image: %3").arg(mod.ModuleName, -14)\r
-      .arg(BaseOfDll, 8, 16, QLatin1Char('0'))\r
-      .arg(mod.LoadedImageName);\r
-    // qDebug() << qPrintable(line);\r
-    context->stream  << line << '\n';\r
-    \r
-    QString pdbName(mod.LoadedPdbName);\r
-    if(!pdbName.isEmpty()) {\r
-      QString line2 = QString("%1 %2").arg("", 32).arg(pdbName);\r
-      // qDebug() << qPrintable(line2);\r
-      context->stream  << line2 << '\n';\r
-    }\r
-  }\r
-  return TRUE;\r
-}\r
-\r
-#ifdef _M_IX86\r
-  // Disable global optimization and ignore /GS waning caused by\r
-  // inline assembly.\r
-  #pragma optimize("g", off)\r
-  #pragma warning(push)\r
-  #pragma warning(disable : 4748)\r
-#endif\r
-void Quassel::logBacktrace(const QString &filename) {\r
-  DWORD MachineType;\r
-  CONTEXT Context;\r
-  STACKFRAME64 StackFrame;\r
-\r
-#ifdef _M_IX86\r
-    ZeroMemory(&Context, sizeof(CONTEXT));\r
-    Context.ContextFlags = CONTEXT_CONTROL;\r
-    __asm {\r
-    Label:\r
-      mov [Context.Ebp], ebp;\r
-      mov [Context.Esp], esp;\r
-      mov eax, [Label];\r
-      mov [Context.Eip], eax;\r
-    }\r
-#else\r
-    RtlCaptureContext(&Context);\r
-#endif\r
-\r
-  ZeroMemory(&StackFrame, sizeof(STACKFRAME64));\r
-#ifdef _M_IX86\r
-  MachineType                 = IMAGE_FILE_MACHINE_I386;\r
-  StackFrame.AddrPC.Offset    = Context.Eip;\r
-  StackFrame.AddrPC.Mode      = AddrModeFlat;\r
-  StackFrame.AddrFrame.Offset = Context.Ebp;\r
-  StackFrame.AddrFrame.Mode   = AddrModeFlat;\r
-  StackFrame.AddrStack.Offset = Context.Esp;\r
-  StackFrame.AddrStack.Mode   = AddrModeFlat;\r
-#elif _M_X64\r
-  MachineType                 = IMAGE_FILE_MACHINE_AMD64;\r
-  StackFrame.AddrPC.Offset    = Context.Rip;\r
-  StackFrame.AddrPC.Mode      = AddrModeFlat;\r
-  StackFrame.AddrFrame.Offset = Context.Rsp;\r
-  StackFrame.AddrFrame.Mode   = AddrModeFlat;\r
-  StackFrame.AddrStack.Offset = Context.Rsp;\r
-  StackFrame.AddrStack.Mode   = AddrModeFlat;\r
-#elif _M_IA64\r
-  MachineType                 = IMAGE_FILE_MACHINE_IA64;\r
-  StackFrame.AddrPC.Offset    = Context.StIIP;\r
-  StackFrame.AddrPC.Mode      = AddrModeFlat;\r
-  StackFrame.AddrFrame.Offset = Context.IntSp;\r
-  StackFrame.AddrFrame.Mode   = AddrModeFlat;\r
-  StackFrame.AddrBStore.Offset= Context.RsBSP;\r
-  StackFrame.AddrBStore.Mode  = AddrModeFlat;\r
-  StackFrame.AddrStack.Offset = Context.IntSp;\r
-  StackFrame.AddrStack.Mode   = AddrModeFlat;\r
-#else\r
-  #error "Unsupported platform"\r
-#endif\r
-\r
-  //EnterCriticalSection(&DbgHelpLock);\r
-\r
-  QFile logFile(filename);\r
-  logFile.open(QIODevice::Append);\r
-  QTextStream logStream(&logFile);\r
-\r
-  HANDLE hProcess = GetCurrentProcess();\r
-  HANDLE hThread = GetCurrentThread();\r
-  SymInitialize(hProcess, NULL, TRUE);\r
-\r
-  DWORD64 dwDisplacement;\r
-\r
-  ULONG64 buffer[(sizeof(SYMBOL_INFO) +\r
-                 MAX_SYM_NAME*sizeof(TCHAR) +\r
-                 sizeof(ULONG64) - 1) /  sizeof(ULONG64)];\r
-  PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;\r
-  pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);\r
-  pSymbol->MaxNameLen = MAX_SYM_NAME;\r
-  \r
-  IMAGEHLP_MODULE64 mod;\r
-  mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);\r
-\r
-  IMAGEHLP_STACK_FRAME ihsf;\r
-  ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));\r
-\r
-  int i = 0;\r
-  while(StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) {\r
-    if(i == 128)\r
-      break;\r
-\r
-    loadHelpStackFrame(ihsf, StackFrame);\r
-    if(StackFrame.AddrPC.Offset != 0) { // Valid frame.\r
-      \r
-      QString fileName("???");\r
-      if(SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) {\r
-       fileName = QString(mod.ImageName);\r
-       int slashPos = fileName.lastIndexOf('\\');\r
-       if(slashPos != -1)\r
-         fileName = fileName.mid(slashPos + 1);\r
-      }\r
-      QString funcName;\r
-      if(SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) {\r
-       funcName = QString(pSymbol->Name);\r
-      } else {\r
-       funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'));\r
-      }\r
-      QStringList params;\r
-      SymSetContext(hProcess, &ihsf, NULL);\r
-      SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)&params);\r
-      \r
-      QString debugLine = QString("#%1 %2 0x%3 %4(%5)").arg(i, 3, 10)\r
-       .arg(fileName, -20)\r
-       .arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'))\r
-       .arg(funcName)\r
-       .arg(params.join(", "));\r
-      // qDebug() << qPrintable(debugLine);\r
-      logStream << debugLine << '\n';\r
-      i++;\r
-    } else {\r
-      break; // we're at the end.\r
-    }\r
-  }\r
-\r
-  // qDebug() << "List of linked Modules:";\r
-  logStream << "\n\nList of linked Modules:\n";\r
-  EnumModulesContext modulesContext(hProcess, logStream);\r
-  SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext);\r
-\r
-  logFile.close();\r
-}\r
-#ifdef _M_IX86\r
-  #pragma warning(pop)\r
-  #pragma optimize("g", on)\r
-#endif\r
+/***************************************************************************
+ *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#include "quassel.h"
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <stdio.h>
+
+// #include <QDebug>
+#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;
+}
+
+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) {}
+};
+
+#if _MSC_VER >= 1500
+BOOL CALLBACK EnumModulesCB(PCTSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) {
+#else
+BOOL CALLBACK EnumModulesCB(PSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) {
+#endif
+  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;
+}
+
+#ifdef _M_IX86
+  // Disable global optimization and ignore /GS waning caused by
+  // inline assembly.
+  #pragma optimize("g", off)
+  #pragma warning(push)
+  #pragma warning(disable : 4748)
+#endif
+void Quassel::logBacktrace(const QString &filename) {
+  DWORD MachineType;
+  CONTEXT Context;
+  STACKFRAME64 StackFrame;
+
+#ifdef _M_IX86
+    ZeroMemory(&Context, sizeof(CONTEXT));
+    Context.ContextFlags = CONTEXT_CONTROL;
+    __asm {
+    Label:
+      mov [Context.Ebp], ebp;
+      mov [Context.Esp], esp;
+      mov eax, [Label];
+      mov [Context.Eip], eax;
+    }
+#else
+    RtlCaptureContext(&Context);
+#endif
+
+  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;
+#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;
+#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;
+#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)&params);
+
+      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);
+
+  logFile.close();
+}
+#ifdef _M_IX86
+  #pragma warning(pop)
+  #pragma optimize("g", on)
+#endif