File indexing completed on 2024-04-28 16:44:10
0001 /****************************************************************** 0002 * 0003 * kdbgwin - Helper application for DrKonqi 0004 * 0005 * This file is part of the KDE project 0006 * 0007 * SPDX-FileCopyrightText: 2010 Ilie Halip <lupuroshu@gmail.com> 0008 * 0009 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0010 *****************************************************************/ 0011 0012 #include "abstract_generator.h" 0013 #include "callbacks.h" 0014 0015 #include <QStringList> 0016 0017 AbstractBTGenerator::AbstractBTGenerator(const Process &process) 0018 : m_process(process) 0019 { 0020 assert(process.IsValid()); 0021 } 0022 0023 AbstractBTGenerator::~AbstractBTGenerator() 0024 { 0025 } 0026 0027 QString AbstractBTGenerator::GetModuleName() 0028 { 0029 IMAGEHLP_MODULE64 module; 0030 ZeroMemory(&module, sizeof(module)); 0031 module.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); 0032 0033 if (!SymGetModuleInfo64(m_process.GetHandle(), m_currentFrame.AddrPC.Offset, &module)) { 0034 qCCritical(DRKONQI_LOG) << "SymGetModuleInfo64 failed: " << GetLastError(); 0035 return QLatin1String(DEFAULT_MODULE); 0036 } 0037 0038 QStringList list = QString(QLatin1String(module.ImageName)).split(QStringLiteral("\\")); 0039 return list[list.size() - 1]; 0040 } 0041 0042 QString AbstractBTGenerator::GetModulePath() 0043 { 0044 IMAGEHLP_MODULE64 module; 0045 ZeroMemory(&module, sizeof(module)); 0046 module.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); 0047 0048 if (!SymGetModuleInfo64(m_process.GetHandle(), m_currentFrame.AddrPC.Offset, &module)) { 0049 qCCritical(DRKONQI_LOG) << "SymGetModuleInfo64 failed: " << GetLastError(); 0050 return QLatin1String(DEFAULT_MODULE); 0051 } 0052 0053 return QString(QLatin1String(module.ImageName)); 0054 } 0055 0056 void AbstractBTGenerator::Run(HANDLE hThread, bool bFaultingThread) 0057 { 0058 assert(m_process.IsValid()); 0059 assert(hThread); 0060 0061 if (!Init()) { 0062 assert(false); 0063 return; 0064 } 0065 0066 // HANDLE hFile = CreateFile(L"C:\\test\\test.dmp", FILE_ALL_ACCESS, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); 0067 // if (!MiniDumpWriteDump(m_process.GetHandle(), m_process.GetId(), hFile, 0068 // MiniDumpNormal, NULL, NULL, NULL)) 0069 //{ 0070 // HRESULT hres = (HRESULT) GetLastError(); 0071 // printf("%08X\n\n", hres); 0072 //} 0073 // SafeCloseHandle(hFile); 0074 0075 DWORD dw = SuspendThread(hThread); 0076 assert(dw != DWORD(-1)); 0077 if (dw == DWORD(-1)) { 0078 qCCritical(DRKONQI_LOG) << "SuspendThread() failed: " << GetLastError(); 0079 return; 0080 } 0081 0082 CONTEXT context; 0083 ZeroMemory(&context, sizeof(context)); 0084 if (!bFaultingThread) { 0085 // if it's not the faulting thread, get its context 0086 context.ContextFlags = CONTEXT_FULL; 0087 if (!GetThreadContext(hThread, &context)) { 0088 ResumeThread(hThread); 0089 assert(false); 0090 qCCritical(DRKONQI_LOG) << "GetThreadContext() failed: " << GetLastError(); 0091 return; 0092 } 0093 } else { 0094 // if it is, get it from KCrash 0095 HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"Local\\KCrashShared"); 0096 if (hMapFile == NULL) { 0097 qCCritical(DRKONQI_LOG) << "OpenFileMapping() failed: " << GetLastError(); 0098 return; 0099 } 0100 CONTEXT *othercontext = (CONTEXT *)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CONTEXT)); 0101 if (othercontext == NULL) { 0102 qCCritical(DRKONQI_LOG) << "MapViewOfFile() failed: " << GetLastError(); 0103 SafeCloseHandle(hMapFile); 0104 return; 0105 } 0106 CopyMemory(&context, othercontext, sizeof(CONTEXT)); 0107 UnmapViewOfFile(othercontext); // continue even if it fails 0108 SafeCloseHandle(hMapFile); 0109 } 0110 0111 // some of this stuff is taken from StackWalker 0112 ZeroMemory(&m_currentFrame, sizeof(m_currentFrame)); 0113 DWORD machineType = IMAGE_FILE_MACHINE_UNKNOWN; 0114 #if defined(_M_IX86) 0115 machineType = IMAGE_FILE_MACHINE_I386; 0116 m_currentFrame.AddrPC.Offset = context.Eip; 0117 m_currentFrame.AddrFrame.Offset = context.Ebp; 0118 m_currentFrame.AddrStack.Offset = context.Esp; 0119 #elif defined(_M_X64) 0120 machineType = IMAGE_FILE_MACHINE_AMD64; 0121 m_currentFrame.AddrPC.Offset = context.Rip; 0122 m_currentFrame.AddrFrame.Offset = context.Rbp; 0123 m_currentFrame.AddrStack.Offset = context.Rsp; 0124 #else 0125 #error This architecture is not supported. 0126 #endif 0127 m_currentFrame.AddrPC.Mode = AddrModeFlat; 0128 m_currentFrame.AddrFrame.Mode = AddrModeFlat; 0129 m_currentFrame.AddrStack.Mode = AddrModeFlat; 0130 0131 SymSetOptions(SymGetOptions() | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES); 0132 SymInitialize(m_process.GetHandle(), NULL, FALSE); 0133 0134 LoadSymbols(); 0135 0136 for (int i = 0; /*nothing*/; i++) { 0137 SetLastError(0); 0138 0139 if (!StackWalk64(machineType, 0140 m_process.GetHandle(), 0141 hThread, 0142 &m_currentFrame, 0143 &context, 0144 &Callbacks::ReadProcessMemory, 0145 &Callbacks::SymFunctionTableAccess64, 0146 &Callbacks::SymGetModuleBase64, 0147 NULL)) { 0148 Q_EMIT Finished(); 0149 qCDebug(DRKONQI_LOG) << "Stackwalk finished; GetLastError=" << GetLastError(); 0150 break; 0151 } 0152 0153 FrameChanged(); 0154 0155 QString modulename = GetModuleName(); 0156 QString functionname = GetFunctionName(); 0157 QString file = GetFile(); 0158 int line = GetLine(); 0159 QString address = QString::number(m_currentFrame.AddrPC.Offset, 16); 0160 0161 QString debugLine = QString::fromLatin1(BACKTRACE_FORMAT).arg(modulename).arg(functionname).arg(file).arg(line).arg(address); 0162 0163 Q_EMIT DebugLine(debugLine); 0164 } 0165 0166 // Resume the target thread now, or else the crashing process will not 0167 // be terminated 0168 ResumeThread(hThread); 0169 0170 SymCleanup(m_process.GetHandle()); 0171 } 0172 0173 bool AbstractBTGenerator::IsSymbolLoaded(const QString &module) 0174 { 0175 if (m_symbolsMap.contains(module)) { 0176 return m_symbolsMap[module]; 0177 } 0178 return false; 0179 } 0180 0181 void AbstractBTGenerator::LoadSymbols() 0182 { 0183 TModulesMap modules = m_process.GetModules(); 0184 for (TModulesMap::iterator i = modules.begin(); i != modules.end(); i++) { 0185 MODULEINFO modInfo; 0186 ZeroMemory(&modInfo, sizeof(modInfo)); 0187 0188 QString strModule = i.key(); 0189 0190 GetModuleInformation(m_process.GetHandle(), i.value(), &modInfo, sizeof(modInfo)); 0191 SymLoadModuleEx(m_process.GetHandle(), 0192 NULL, 0193 (CHAR *)i.key().toLatin1().constData(), 0194 (CHAR *)i.key().toLatin1().constData(), 0195 (DWORD64)modInfo.lpBaseOfDll, 0196 modInfo.SizeOfImage, 0197 NULL, 0198 0); 0199 0200 LoadSymbol(strModule, (DWORD64)modInfo.lpBaseOfDll); 0201 0202 if (!IsSymbolLoaded(strModule)) { 0203 Q_EMIT MissingSymbol(strModule); 0204 } 0205 } 0206 Q_EMIT DebugLine(QString()); 0207 Q_EMIT DebugLine(QString()); 0208 }