OSDN Git Service

Removed unused function
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / shared / dbgwinutils.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #include "winutils.h"
34 #include "dbgwinutils.h"
35 #include "debuggerdialogs.h"
36 #include "breakpoint.h"
37
38 #include <QtCore/QDebug>
39 #include <QtCore/QString>
40 #include <QtCore/QTextStream>
41
42 // Enable Win API of XP SP1 and later
43 #ifdef Q_OS_WIN
44 #    define _WIN32_WINNT 0x0502
45 #    include <windows.h>
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
50 #endif // Q_OS_WIN
51
52 #include <tlhelp32.h>
53 #include <psapi.h>
54 #include <QtCore/QLibrary>
55
56 namespace Debugger {
57 namespace Internal {
58
59 // Resolve QueryFullProcessImageNameW out of kernel32.dll due
60 // to incomplete MinGW import libs and it not being present
61 // on Windows XP.
62 static inline BOOL queryFullProcessImageName(HANDLE h,
63                                                    DWORD flags,
64                                                    LPWSTR buffer,
65                                                    DWORD *size)
66 {
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");
75     }
76     if (!queryFullProcessImageNameW)
77         return FALSE;
78     // Read out process
79     return (*queryFullProcessImageNameW)(h, flags, buffer, size);
80 }
81
82 static inline QString imageName(DWORD processId)
83 {
84     QString  rc;
85     HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, processId);
86     if (handle == INVALID_HANDLE_VALUE)
87         return rc;
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));
92     CloseHandle(handle);
93     return rc;
94 }
95
96 QList<ProcData> winProcessList()
97 {
98     QList<ProcData> rc;
99
100     PROCESSENTRY32 pe;
101     pe.dwSize = sizeof(PROCESSENTRY32);
102     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
103     if (snapshot == INVALID_HANDLE_VALUE)
104         return rc;
105
106     for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
107         ProcData procData;
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);
112     }
113     CloseHandle(snapshot);
114     return rc;
115 }
116
117 bool winResumeThread(unsigned long dwThreadId, QString *errorMessage)
118 {
119     bool ok = false;
120     HANDLE handle = NULL;
121     do {
122         if (!dwThreadId)
123             break;
124
125         handle = OpenThread(SYNCHRONIZE |THREAD_QUERY_INFORMATION |THREAD_SUSPEND_RESUME,
126                             FALSE, dwThreadId);
127         if (handle==NULL) {
128             *errorMessage = QString::fromLatin1("Unable to open thread %1: %2").
129                             arg(dwThreadId).arg(Utils::winErrorMessage(GetLastError()));
130             break;
131         }
132         if (ResumeThread(handle) == DWORD(-1)) {
133             *errorMessage = QString::fromLatin1("Unable to resume thread %1: %2").
134                             arg(dwThreadId).arg(Utils::winErrorMessage(GetLastError()));
135             break;
136         }
137         ok = true;
138     } while (false);
139     if (handle != NULL)
140         CloseHandle(handle);
141     return ok;
142 }
143
144 // Open the process and break into it
145 bool winDebugBreakProcess(unsigned long  pid, QString *errorMessage)
146 {
147     bool ok = false;
148     HANDLE inferior = NULL;
149     do {
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()));
157             break;
158         }
159         if (!DebugBreakProcess(inferior)) {
160             *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError()));
161             break;
162         }
163         ok = true;
164     } while (false);
165     if (inferior != NULL)
166         CloseHandle(inferior);
167     return ok;
168 }
169
170 unsigned long winGetCurrentProcessId()
171 {
172     return GetCurrentProcessId();
173 }
174
175 bool isWinProcessBeingDebugged(unsigned long pid)
176 {
177     HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
178     if (processHandle == NULL)
179         return false;
180     BOOL debugged = FALSE;
181     CheckRemoteDebuggerPresent(processHandle, &debugged);
182     CloseHandle(processHandle);
183     return debugged != FALSE;
184 }
185
186 // Simple exception formatting
187 void formatWindowsException(unsigned long code, quint64 address,
188                             unsigned long flags, quint64 info1, quint64 info2,
189                             QTextStream &str)
190 {
191     str.setIntegerBase(16);
192     str << "\nException at 0x"  << address
193             <<  ", code: 0x" << code << ": ";
194     switch (code) {
195     case winExceptionCppException:
196         str << "C++ exception";
197         break;
198     case winExceptionStartupCompleteTrap:
199         str << "Startup complete";
200         break;
201     case winExceptionDllNotFound:
202         str << "DLL not found";
203         break;
204     case winExceptionDllEntryPointNoFound:
205         str << "DLL entry point not found";
206         break;
207     case winExceptionDllInitFailed:
208         str << "DLL failed to initialize";
209         break;
210     case winExceptionMissingSystemFile:
211         str << "System file is missing";
212         break;
213     case winExceptionRpcServerUnavailable:
214         str << "RPC server unavailable";
215         break;
216     case winExceptionRpcServerInvalid:
217         str << "Invalid RPC server";
218         break;
219     case winExceptionWX86Breakpoint:
220         str << "Win32 x86 emulation subsystem breakpoint hit";
221         break;
222     case EXCEPTION_ACCESS_VIOLATION: {
223             const bool writeOperation = info1;
224             str << (writeOperation ? "write" : "read")
225                 << " access violation at: 0x" << info2;
226     }
227         break;
228     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
229         str << "arrary bounds exceeded";
230         break;
231     case EXCEPTION_BREAKPOINT:
232         str << "breakpoint";
233         break;
234     case EXCEPTION_DATATYPE_MISALIGNMENT:
235         str << "datatype misalignment";
236         break;
237     case EXCEPTION_FLT_DENORMAL_OPERAND:
238         str << "floating point exception";
239         break;
240     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
241         str << "division by zero";
242         break;
243     case EXCEPTION_FLT_INEXACT_RESULT:
244         str << " floating-point operation cannot be represented exactly as a decimal fraction";
245         break;
246     case EXCEPTION_FLT_INVALID_OPERATION:
247         str << "invalid floating-point operation";
248         break;
249     case EXCEPTION_FLT_OVERFLOW:
250         str << "floating-point overflow";
251         break;
252     case EXCEPTION_FLT_STACK_CHECK:
253         str << "floating-point operation stack over/underflow";
254         break;
255     case  EXCEPTION_FLT_UNDERFLOW:
256         str << "floating-point UNDERFLOW";
257         break;
258     case  EXCEPTION_ILLEGAL_INSTRUCTION:
259         str << "invalid instruction";
260         break;
261     case EXCEPTION_IN_PAGE_ERROR:
262         str << "page in error";
263         break;
264     case EXCEPTION_INT_DIVIDE_BY_ZERO:
265         str << "integer division by zero";
266         break;
267     case EXCEPTION_INT_OVERFLOW:
268         str << "integer overflow";
269         break;
270     case EXCEPTION_INVALID_DISPOSITION:
271         str << "invalid disposition to exception dispatcher";
272         break;
273     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
274         str << "attempt to continue execution after noncontinuable exception";
275         break;
276     case EXCEPTION_PRIV_INSTRUCTION:
277         str << "privileged instruction";
278         break;
279     case EXCEPTION_SINGLE_STEP:
280         str << "single step";
281         break;
282     case EXCEPTION_STACK_OVERFLOW:
283         str << "stack_overflow";
284         break;
285     }
286     str << ", flags=0x" << flags;
287     if (flags == EXCEPTION_NONCONTINUABLE) {
288         str << " (execution cannot be continued)";
289     }
290     str.setIntegerBase(10);
291 }
292
293 bool isDebuggerWinException(long code)
294 {
295     return code ==EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
296 }
297
298 bool isFatalWinException(long code)
299 {
300     switch (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:
309         return false;
310     default:
311         break;
312     }
313     return true;
314 }
315
316 } // namespace Internal
317 } // namespace Debugger