1 /***************************************************************************
2 * Copyright (C) 2005-2019 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
27 #include <QTextStream>
31 void loadHelpStackFrame(IMAGEHLP_STACK_FRAME& ihsf, const STACKFRAME64& stackFrame)
33 ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));
34 ihsf.InstructionOffset = stackFrame.AddrPC.Offset;
35 ihsf.FrameOffset = stackFrame.AddrFrame.Offset;
38 BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user)
41 QStringList* params = (QStringList*)user;
42 if (symInfo->Flags & SYMFLAG_PARAMETER) {
43 params->append(symInfo->Name);
48 struct EnumModulesContext
52 EnumModulesContext(HANDLE hProcess, QTextStream& stream)
58 BOOL CALLBACK EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext)
61 IMAGEHLP_MODULE64 mod;
62 EnumModulesContext* context = (EnumModulesContext*)UserContext;
63 mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
64 if (SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) {
65 QString line = QString("%1 0x%2 Image: %3").arg(mod.ModuleName, -14).arg(BaseOfDll, 8, 16, QLatin1Char('0')).arg(mod.LoadedImageName);
66 // qDebug() << qPrintable(line);
67 context->stream << line << '\n';
69 QString pdbName(mod.LoadedPdbName);
70 if (!pdbName.isEmpty()) {
71 QString line2 = QString("%1 %2").arg("", 32).arg(pdbName);
72 // qDebug() << qPrintable(line2);
73 context->stream << line2 << '\n';
79 #if defined(_M_IX86) && defined(Q_CC_MSVC)
80 // Disable global optimization and ignore /GS waning caused by
82 // not needed with mingw cause we can tell mingw which registers we use
83 # pragma optimize("g", off)
84 # pragma warning(push)
85 # pragma warning(disable : 4748)
87 void Quassel::logBacktrace(const QString& filename)
91 STACKFRAME64 StackFrame;
94 ZeroMemory(&Context, sizeof(CONTEXT));
95 Context.ContextFlags = CONTEXT_CONTROL;
101 "movl $Label,%%eax;\n\t"
103 : "=r"(Context.Ebp), "=r"(Context.Esp), "=r"(Context.Eip)
109 mov[Context.Ebp], ebp;
110 mov[Context.Esp], esp;
112 mov[Context.Eip], eax;
116 RtlCaptureContext(&Context);
119 ZeroMemory(&StackFrame, sizeof(STACKFRAME64));
121 MachineType = IMAGE_FILE_MACHINE_I386;
122 StackFrame.AddrPC.Offset = Context.Eip;
123 StackFrame.AddrPC.Mode = AddrModeFlat;
124 StackFrame.AddrFrame.Offset = Context.Ebp;
125 StackFrame.AddrFrame.Mode = AddrModeFlat;
126 StackFrame.AddrStack.Offset = Context.Esp;
127 StackFrame.AddrStack.Mode = AddrModeFlat;
128 #elif defined(_M_X64)
129 MachineType = IMAGE_FILE_MACHINE_AMD64;
130 StackFrame.AddrPC.Offset = Context.Rip;
131 StackFrame.AddrPC.Mode = AddrModeFlat;
132 StackFrame.AddrFrame.Offset = Context.Rsp;
133 StackFrame.AddrFrame.Mode = AddrModeFlat;
134 StackFrame.AddrStack.Offset = Context.Rsp;
135 StackFrame.AddrStack.Mode = AddrModeFlat;
136 #elif defined(_M_IA64)
137 MachineType = IMAGE_FILE_MACHINE_IA64;
138 StackFrame.AddrPC.Offset = Context.StIIP;
139 StackFrame.AddrPC.Mode = AddrModeFlat;
140 StackFrame.AddrFrame.Offset = Context.IntSp;
141 StackFrame.AddrFrame.Mode = AddrModeFlat;
142 StackFrame.AddrBStore.Offset = Context.RsBSP;
143 StackFrame.AddrBStore.Mode = AddrModeFlat;
144 StackFrame.AddrStack.Offset = Context.IntSp;
145 StackFrame.AddrStack.Mode = AddrModeFlat;
147 # error "Unsupported platform"
150 // EnterCriticalSection(&DbgHelpLock);
152 QFile logFile(filename);
153 logFile.open(QIODevice::Append);
154 QTextStream logStream(&logFile);
156 HANDLE hProcess = GetCurrentProcess();
157 HANDLE hThread = GetCurrentThread();
158 SymInitialize(hProcess, NULL, TRUE);
160 DWORD64 dwDisplacement;
162 ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
163 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
164 pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
165 pSymbol->MaxNameLen = MAX_SYM_NAME;
167 IMAGEHLP_MODULE64 mod;
168 mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
170 IMAGEHLP_STACK_FRAME ihsf;
171 ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME));
174 while (StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) {
178 loadHelpStackFrame(ihsf, StackFrame);
179 if (StackFrame.AddrPC.Offset != 0) { // Valid frame.
180 QString fileName("???");
181 if (SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) {
182 fileName = QString(mod.ImageName);
183 int slashPos = fileName.lastIndexOf('\\');
185 fileName = fileName.mid(slashPos + 1);
188 if (SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) {
189 funcName = QString(pSymbol->Name);
192 funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'));
195 SymSetContext(hProcess, &ihsf, NULL);
196 SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms);
198 QString debugLine = QString("#%1 %2 0x%3 %4(%5)")
201 .arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0'))
203 .arg(params.join(", "));
204 // qDebug() << qPrintable(debugLine);
205 logStream << debugLine << '\n';
209 break; // we're at the end.
213 // qDebug() << "List of linked Modules:";
214 logStream << "\n\nList of linked Modules:\n";
215 EnumModulesContext modulesContext(hProcess, logStream);
216 SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext);
221 #if defined(_M_IX86) && defined(Q_CC_MSVC)
222 # pragma warning(pop)
223 # pragma optimize("g", on)