diff options
author | David Schulz <david.schulz@digia.com> | 2013-06-10 15:45:00 +0200 |
---|---|---|
committer | David Schulz <david.schulz@digia.com> | 2013-06-17 11:20:42 +0200 |
commit | 2bc24b7a25ba7faf523166bbb75e36a9e7528124 (patch) | |
tree | b39a285d63b2e1cfd50230520b5da3a715a7f57e | |
parent | 94dd4e740a3b6acf28cd3df4015af6f612aae6d5 (diff) | |
download | qt-creator-2bc24b7a25ba7faf523166bbb75e36a9e7528124.tar.gz |
Debugger: Fix interrupting 32bit process from a 64bit creator...
... on windows.
Change-Id: I93f5299ab7f90ed64a6369176107d7596f3b36e4
Reviewed-by: hjk <hjk121@nokiamail.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
-rw-r--r-- | src/plugins/debugger/procinterrupt.cpp | 93 | ||||
-rw-r--r-- | src/tools/tools.pro | 11 | ||||
-rw-r--r-- | src/tools/wininterrupt/wininterrupt.c (renamed from src/tools/win64interrupt/win64interrupt.c) | 0 | ||||
-rw-r--r-- | src/tools/wininterrupt/wininterrupt.pro (renamed from src/tools/win64interrupt/win64interrupt.pro) | 12 |
4 files changed, 69 insertions, 47 deletions
diff --git a/src/plugins/debugger/procinterrupt.cpp b/src/plugins/debugger/procinterrupt.cpp index 0ad32373af..178f6a823e 100644 --- a/src/plugins/debugger/procinterrupt.cpp +++ b/src/plugins/debugger/procinterrupt.cpp @@ -93,51 +93,70 @@ bool Debugger::Internal::interruptProcess(int pID, int engineType, QString *erro arg(pID).arg(Utils::winErrorMessage(GetLastError())); break; } - // Try DebugBreakProcess if either Qt Creator is compiled 64 bit or - // both Qt Creator and application are 32 bit. -#ifdef Q_OS_WIN64 - // Qt-Creator compiled 64 bit - // Windows must be 64 bit - // CDB 64 bit: use DebugBreakProcess for 32 an 64 bit processes. - // TODO: CDB 32 bit: inferior 32 bit can not use DebugBreakProcess, we need a win32interrupt.exe - // GDB: not supported - const bool useDebugBreakApi= true; - Q_UNUSED(engineExecutableIs64Bit) - Q_UNUSED(engineType) + enum DebugBreakApi { + UseDebugBreakApi, + UseWin64Interrupt, + UseWin32Interrupt + }; +/* + Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a + 32 bit application inside a 64 bit environment. + When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running + the inferior. If CDB is used we could in theory break wow64 processes, + but the break is actually a wow64 breakpoint. CDB is configured to ignore these + breakpoints, because they also appear on module loading. + Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling + DebugBreakProcess from the correct system. + + DebugBreak matrix for windows + + Api = UseDebugBreakApi + Win64 = UseWin64Interrupt + Win32 = UseWin32Interrupt + N/A = This configuration is not possible + + | Windows 32bit | Windows 64bit + | QtCreator 32bit | QtCreator 32bit | QtCreator 64bit + | Inferior 32bit | Inferior 32bit | Inferior 64bit | Inferior 32bit | Inferior 64bit | +----------|-----------------|-----------------|-----------------|-----------------|----------------| +CDB 32bit | Api | Api | NA | Win32 | NA | + 64bit | NA | Win64 | Win64 | Api | Api | +----------|-----------------|-----------------|-----------------|-----------------|----------------| +GDB 32bit | Api | Api | NA | Win32 | NA | + 64bit | NA | Api | Win64 | Win32 | Api | +----------|-----------------|-----------------|-----------------|-----------------|----------------| + +*/ + + DebugBreakApi breakApi = UseDebugBreakApi; +#ifdef Q_OS_WIN64 + if ((engineType == GdbEngineType && isWow64Process(inferior)) + || (engineType == CdbEngineType && !engineExecutableIs64Bit)) { + breakApi = UseWin32Interrupt; + } #else - // Qt-Creator compiled 32 bit: - - bool useDebugBreakApi; - if (isWow64Process(GetCurrentProcess())) { - // Windows is 64 bit - if (engineType == CdbEngineType) { - // CDB 64 bit: If Qt-Creator is a WOW64 process (meaning a 32bit process - // running in emulation), always use win64interrupt.exe for native - // 64 bit processes and WOW64 processes. While DebugBreakProcess() - // works in theory for other WOW64 processes, the break appears - // as a WOW64 breakpoint, which CDB is configured to ignore since - // it also triggers on module loading. - // CDB 32 bit: 32 bit applications can not be interrupted using the win64interrupt.exe - // So we need to find out which bitness the currently used cdb has. - useDebugBreakApi = !engineExecutableIs64Bit; - } else { - // GDB: Use win64interrupt for native 64bit processes only (it fails - // for WOW64 processes. - useDebugBreakApi = isWow64Process(inferior); - } - } else { - // Windows is 32 bit - // All processes are 32 bit, so DebugBreakProcess can be used in all cases. - useDebugBreakApi = true; + if (isWow64Process(GetCurrentProcess()) + && ((engineType == CdbEngineType && engineExecutableIs64Bit) + || (engineType == GdbEngineType && !isWow64Process(inferior)))) { + breakApi = UseWin64Interrupt; } #endif - if (useDebugBreakApi) { + if (breakApi == UseDebugBreakApi) { ok = DebugBreakProcess(inferior); if (!ok) *errorMessage = QLatin1String("DebugBreakProcess failed: ") + Utils::winErrorMessage(GetLastError()); } else { - const QString executable = QCoreApplication::applicationDirPath() + QLatin1String("/win64interrupt.exe"); + const QString executable = breakApi == UseWin32Interrupt + ? QCoreApplication::applicationDirPath() + QLatin1String("/win32interrupt.exe") + : QCoreApplication::applicationDirPath() + QLatin1String("/win64interrupt.exe"); + if (!QFile::exists(executable)) { + *errorMessage = QString::fromLatin1("%1 does not exist. If you have built QtCreator " + "on your own ,checkout " + "http://qt.gitorious.org/qt-creator/binary-artifacts."). + arg(QDir::toNativeSeparators(executable)); + break; + } switch (QProcess::execute(executable, QStringList(QString::number(pID)))) { case -2: *errorMessage = QString::fromLatin1("Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c for more information."). diff --git a/src/tools/tools.pro b/src/tools/tools.pro index 240a42ee3f..ce4530ca8c 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -7,14 +7,7 @@ SUBDIRS = qtpromaker \ win32 { SUBDIRS += qtcdebugger - # win64interrupt only make sense for 64bit builds - ENV_CPU=$$(CPU) - ENV_LIBPATH=$$(LIBPATH) - contains(ENV_CPU, ^AMD64$) { - SUBDIRS += win64interrupt - } else:isEmpty(ENV_CPU):contains(ENV_LIBPATH, ^.*amd64.*$) { - SUBDIRS += win64interrupt - } + SUBDIRS += wininterrupt } else { SUBDIRS += valgrindfake } @@ -36,4 +29,4 @@ greaterThan(QT_MAJOR_VERSION, 4) { } else { SUBDIRS += qml2puppet } -}
\ No newline at end of file +} diff --git a/src/tools/win64interrupt/win64interrupt.c b/src/tools/wininterrupt/wininterrupt.c index f2327f8a1c..f2327f8a1c 100644 --- a/src/tools/win64interrupt/win64interrupt.c +++ b/src/tools/wininterrupt/wininterrupt.c diff --git a/src/tools/win64interrupt/win64interrupt.pro b/src/tools/wininterrupt/wininterrupt.pro index 282514c54c..b306db179f 100644 --- a/src/tools/win64interrupt/win64interrupt.pro +++ b/src/tools/wininterrupt/wininterrupt.pro @@ -16,7 +16,7 @@ win32-msvc* { QMAKE_CXXFLAGS += -static } -SOURCES = win64interrupt.c +SOURCES = wininterrupt.c TEMPLATE = app DESTDIR = $$IDE_LIBEXEC_PATH @@ -26,5 +26,15 @@ build_all:!build_pass { CONFIG += release } +ENV_CPU=$$(CPU) +ENV_LIBPATH=$$(LIBPATH) +contains(ENV_CPU, ^AMD64$) { + TARGET = win64interrupt +} else:isEmpty(ENV_CPU):contains(ENV_LIBPATH, ^.*amd64.*$) { + TARGET = win64interrupt +} else { + TARGET = win32interrupt +} + target.path = $$QTC_PREFIX/bin # FIXME: libexec, more or less INSTALLS += target |