5#include <QtTest/private/qtestcrashhandler_p.h>
7#include <QtCore/qbytearray.h>
8#include <QtCore/qstring.h>
10#include <QtTest/qtestcase.h>
11#include <QtTest/private/qtestlog_p.h>
16#if !defined(Q_CC_MINGW) || (defined(Q_CC_MINGW) && defined(__MINGW64_VERSION_MAJOR))
19#include <qt_windows.h>
23using namespace Qt::StringLiterals;
29 return IsDebuggerPresent();
41 const int disableStackDump = qEnvironmentVariableIntValue(
"QTEST_DISABLE_STACK_DUMP", &ok);
42 if (ok && disableStackDump)
50 const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
51 const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
52 const char *
const name = QTest::currentTestFunction();
56 fprintf(stderr,
"\n %s function time: %dms, total time: %dms\n",
57 name ? name :
"[Non-test]", msecsFunctionTime, msecsTotalTime);
62 if (debugger == None || alreadyDebugging())
77class DebugSymbolResolver
79 Q_DISABLE_COPY_MOVE(DebugSymbolResolver)
83 Symbol() : name(
nullptr), address(0) {}
89 explicit DebugSymbolResolver(HANDLE process);
90 ~DebugSymbolResolver() { cleanup(); }
92 bool isValid()
const {
return m_symFromAddr; }
94 Symbol resolveSymbol(DWORD64 address)
const;
98 struct DBGHELP_SYMBOL_INFO {
116 typedef BOOL (
__stdcall *SymInitializeType)(HANDLE, PCSTR, BOOL);
117 typedef BOOL (
__stdcall *SymFromAddrType)(HANDLE, DWORD64, PDWORD64, DBGHELP_SYMBOL_INFO *);
121 const HANDLE m_process;
122 HMODULE m_dbgHelpLib;
123 SymFromAddrType m_symFromAddr;
126void DebugSymbolResolver::cleanup()
129 FreeLibrary(m_dbgHelpLib);
131 m_symFromAddr =
nullptr;
134DebugSymbolResolver::DebugSymbolResolver(HANDLE process)
135 : m_process(process), m_dbgHelpLib(0), m_symFromAddr(
nullptr)
137 bool success =
false;
138 m_dbgHelpLib = LoadLibraryW(L"dbghelp.dll");
140 SymInitializeType symInitialize =
reinterpret_cast<SymInitializeType>(
141 reinterpret_cast<QFunctionPointer>(GetProcAddress(m_dbgHelpLib,
"SymInitialize")));
142 m_symFromAddr =
reinterpret_cast<SymFromAddrType>(
143 reinterpret_cast<QFunctionPointer>(GetProcAddress(m_dbgHelpLib,
"SymFromAddr")));
144 success = symInitialize && m_symFromAddr && symInitialize(process, NULL, TRUE);
150DebugSymbolResolver::Symbol DebugSymbolResolver::resolveSymbol(DWORD64 address)
const
153 struct NamedSymbolInfo :
public DBGHELP_SYMBOL_INFO {
154 enum { symbolNameLength = 255 };
156 char name[symbolNameLength + 1];
162 NamedSymbolInfo symbolBuffer;
163 memset(&symbolBuffer, 0,
sizeof(NamedSymbolInfo));
164 symbolBuffer.MaxNameLen = NamedSymbolInfo::symbolNameLength;
165 symbolBuffer.SizeOfStruct =
sizeof(DBGHELP_SYMBOL_INFO);
166 if (!m_symFromAddr(m_process, address, 0, &symbolBuffer))
168 result.name = qstrdup(symbolBuffer.Name);
169 result.address = symbolBuffer.Address;
178# if !defined(Q_CC_MINGW)
197 fprintf(stderr,
"Function time: %dms Total time: %dms\n\n"
198 "Exception address: 0x%p\n"
199 "Exception code : 0x%lx\n",
211 fputs(
"\nStack:\n", stderr);
219 fprintf(stderr,
"#%3u: Unable to obtain symbol\n",
f + 1);
void maybeDisableCoreDump()
static DebuggerProgram debugger
void generateStackTrace(quintptr ip)