1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
34 #include "dbgwinutils.h"
35 #include "debuggerdialogs.h"
36 #include "breakpoint.h"
38 #include <QtCore/QDebug>
39 #include <QtCore/QString>
40 #include <QtCore/QTextStream>
42 // Enable Win API of XP SP1 and later
44 # define _WIN32_WINNT 0x0502
46 # include <utils/winutils.h>
47 # if !defined(PROCESS_SUSPEND_RESUME) // Check flag for MinGW
48 # define PROCESS_SUSPEND_RESUME (0x0800)
49 # endif // PROCESS_SUSPEND_RESUME
54 #include <QtCore/QLibrary>
59 // Resolve QueryFullProcessImageNameW out of kernel32.dll due
60 // to incomplete MinGW import libs and it not being present
62 static inline BOOL queryFullProcessImageName(HANDLE h,
67 // Resolve required symbols from the kernel32.dll
68 typedef BOOL (WINAPI *QueryFullProcessImageNameWProtoType)
69 (HANDLE, DWORD, LPWSTR, PDWORD);
70 static QueryFullProcessImageNameWProtoType queryFullProcessImageNameW = 0;
71 if (!queryFullProcessImageNameW) {
72 QLibrary kernel32Lib(QLatin1String("kernel32.dll"), 0);
73 if (kernel32Lib.isLoaded() || kernel32Lib.load())
74 queryFullProcessImageNameW = (QueryFullProcessImageNameWProtoType)kernel32Lib.resolve("QueryFullProcessImageNameW");
76 if (!queryFullProcessImageNameW)
79 return (*queryFullProcessImageNameW)(h, flags, buffer, size);
82 static inline QString imageName(DWORD processId)
85 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, processId);
86 if (handle == INVALID_HANDLE_VALUE)
88 WCHAR buffer[MAX_PATH];
89 DWORD bufSize = MAX_PATH;
90 if (queryFullProcessImageName(handle, 0, buffer, &bufSize))
91 rc = QString::fromUtf16(reinterpret_cast<const ushort*>(buffer));
96 QList<ProcData> winProcessList()
101 pe.dwSize = sizeof(PROCESSENTRY32);
102 HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
103 if (snapshot == INVALID_HANDLE_VALUE)
106 for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
108 procData.ppid = QString::number(pe.th32ProcessID);
109 procData.name = QString::fromUtf16(reinterpret_cast<ushort*>(pe.szExeFile));
110 procData.image = imageName(pe.th32ProcessID);
111 rc.push_back(procData);
113 CloseHandle(snapshot);
117 bool winResumeThread(unsigned long dwThreadId, QString *errorMessage)
120 HANDLE handle = NULL;
125 handle = OpenThread(SYNCHRONIZE |THREAD_QUERY_INFORMATION |THREAD_SUSPEND_RESUME,
128 *errorMessage = QString::fromLatin1("Unable to open thread %1: %2").
129 arg(dwThreadId).arg(Utils::winErrorMessage(GetLastError()));
132 if (ResumeThread(handle) == DWORD(-1)) {
133 *errorMessage = QString::fromLatin1("Unable to resume thread %1: %2").
134 arg(dwThreadId).arg(Utils::winErrorMessage(GetLastError()));
144 // Open the process and break into it
145 bool winDebugBreakProcess(unsigned long pid, QString *errorMessage)
148 HANDLE inferior = NULL;
150 const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
151 |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
152 |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME ;
153 inferior = OpenProcess(rights, FALSE, pid);
154 if (inferior == NULL) {
155 *errorMessage = QString::fromLatin1("Cannot open process %1: %2").
156 arg(pid).arg(Utils::winErrorMessage(GetLastError()));
159 if (!DebugBreakProcess(inferior)) {
160 *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError()));
165 if (inferior != NULL)
166 CloseHandle(inferior);
170 unsigned long winGetCurrentProcessId()
172 return GetCurrentProcessId();
175 bool isWinProcessBeingDebugged(unsigned long pid)
177 HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
178 if (processHandle == NULL)
180 BOOL debugged = FALSE;
181 CheckRemoteDebuggerPresent(processHandle, &debugged);
182 CloseHandle(processHandle);
183 return debugged != FALSE;
186 // Simple exception formatting
187 void formatWindowsException(unsigned long code, quint64 address,
188 unsigned long flags, quint64 info1, quint64 info2,
191 str.setIntegerBase(16);
192 str << "\nException at 0x" << address
193 << ", code: 0x" << code << ": ";
195 case winExceptionCppException:
196 str << "C++ exception";
198 case winExceptionStartupCompleteTrap:
199 str << "Startup complete";
201 case winExceptionDllNotFound:
202 str << "DLL not found";
204 case winExceptionDllEntryPointNoFound:
205 str << "DLL entry point not found";
207 case winExceptionDllInitFailed:
208 str << "DLL failed to initialize";
210 case winExceptionMissingSystemFile:
211 str << "System file is missing";
213 case winExceptionRpcServerUnavailable:
214 str << "RPC server unavailable";
216 case winExceptionRpcServerInvalid:
217 str << "Invalid RPC server";
219 case winExceptionWX86Breakpoint:
220 str << "Win32 x86 emulation subsystem breakpoint hit";
222 case EXCEPTION_ACCESS_VIOLATION: {
223 const bool writeOperation = info1;
224 str << (writeOperation ? "write" : "read")
225 << " access violation at: 0x" << info2;
228 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
229 str << "arrary bounds exceeded";
231 case EXCEPTION_BREAKPOINT:
234 case EXCEPTION_DATATYPE_MISALIGNMENT:
235 str << "datatype misalignment";
237 case EXCEPTION_FLT_DENORMAL_OPERAND:
238 str << "floating point exception";
240 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
241 str << "division by zero";
243 case EXCEPTION_FLT_INEXACT_RESULT:
244 str << " floating-point operation cannot be represented exactly as a decimal fraction";
246 case EXCEPTION_FLT_INVALID_OPERATION:
247 str << "invalid floating-point operation";
249 case EXCEPTION_FLT_OVERFLOW:
250 str << "floating-point overflow";
252 case EXCEPTION_FLT_STACK_CHECK:
253 str << "floating-point operation stack over/underflow";
255 case EXCEPTION_FLT_UNDERFLOW:
256 str << "floating-point UNDERFLOW";
258 case EXCEPTION_ILLEGAL_INSTRUCTION:
259 str << "invalid instruction";
261 case EXCEPTION_IN_PAGE_ERROR:
262 str << "page in error";
264 case EXCEPTION_INT_DIVIDE_BY_ZERO:
265 str << "integer division by zero";
267 case EXCEPTION_INT_OVERFLOW:
268 str << "integer overflow";
270 case EXCEPTION_INVALID_DISPOSITION:
271 str << "invalid disposition to exception dispatcher";
273 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
274 str << "attempt to continue execution after noncontinuable exception";
276 case EXCEPTION_PRIV_INSTRUCTION:
277 str << "privileged instruction";
279 case EXCEPTION_SINGLE_STEP:
280 str << "single step";
282 case EXCEPTION_STACK_OVERFLOW:
283 str << "stack_overflow";
286 str << ", flags=0x" << flags;
287 if (flags == EXCEPTION_NONCONTINUABLE) {
288 str << " (execution cannot be continued)";
290 str.setIntegerBase(10);
293 bool isDebuggerWinException(long code)
295 return code ==EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
298 bool isFatalWinException(long code)
301 case EXCEPTION_BREAKPOINT:
302 case EXCEPTION_SINGLE_STEP:
303 case winExceptionStartupCompleteTrap: // Mysterious exception at start of application
304 case winExceptionRpcServerUnavailable:
305 case winExceptionRpcServerInvalid:
306 case winExceptionDllNotFound:
307 case winExceptionDllEntryPointNoFound:
308 case winExceptionCppException:
316 } // namespace Internal
317 } // namespace Debugger