diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 1079fb24eaf..ab173cc0eab 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -124,6 +124,7 @@ const char notCompatibleMessage[] = "is not compatible with target architecture" GdbEngine::GdbEngine() { m_gdbProc.setProcessMode(ProcessMode::Writer); + m_gdbProc.setUseCtrlCStub(true); setObjectName("GdbEngine"); setDebuggerName("GDB"); @@ -673,26 +674,7 @@ void GdbEngine::interruptInferior() } else { showStatusMessage(Tr::tr("Stop requested..."), 5000); showMessage("TRYING TO INTERRUPT INFERIOR"); - if (HostOsInfo::isWindowsHost() && !m_isQnxGdb) { - IDevice::ConstPtr dev = device(); - QTC_ASSERT(dev, notifyInferiorStopFailed(); return); - DeviceProcessSignalOperation::Ptr signalOperation = dev->signalOperation(); - QTC_ASSERT(signalOperation, notifyInferiorStopFailed(); return); - connect(signalOperation.get(), &DeviceProcessSignalOperation::finished, - this, [this, signalOperation](const QString &error) { - if (error.isEmpty()) { - showMessage("Interrupted " + QString::number(inferiorPid())); - notifyInferiorStopOk(); - } else { - showMessage(error, LogError); - notifyInferiorStopFailed(); - } - }); - signalOperation->setDebuggerCommand(runParameters().debugger.command.executable()); - signalOperation->interruptProcess(inferiorPid()); - } else { - interruptInferior2(); - } + interruptInferior2(); } } @@ -1265,9 +1247,11 @@ void GdbEngine::handleStopResponse(const GdbMi &data) handleStop1(data); } -static QString stopSignal(const Abi &abi) +static QStringList stopSignals(const Abi &abi) { - return QLatin1String(abi.os() == Abi::WindowsOS ? "SIGTRAP" : "SIGINT"); + static QStringList winSignals = { "SIGTRAP", "SIGINT" }; + static QStringList unixSignals = { "SIGINT" }; + return abi.os() == Abi::WindowsOS ? winSignals : unixSignals; } void GdbEngine::handleStop1(const GdbMi &data) @@ -1416,7 +1400,7 @@ void GdbEngine::handleStop2(const GdbMi &data) QString meaning = data["signal-meaning"].data(); // Ignore these as they are showing up regularly when // stopping debugging. - if (name == stopSignal(rp.toolChainAbi) || rp.expectedSignals.contains(name)) { + if (stopSignals(rp.toolChainAbi).contains(name) || rp.expectedSignals.contains(name)) { showMessage(name + " CONSIDERED HARMLESS. CONTINUING."); } else if (m_isQnxGdb && name == "0" && meaning == "Signal 0") { showMessage("SIGNAL 0 CONSIDERED BOGUS."); @@ -3817,9 +3801,6 @@ void GdbEngine::setupEngine() CHECK_STATE(EngineSetupRequested); showMessage("TRYING TO START ADAPTER"); - if (isRemoteEngine()) - m_gdbProc.setUseCtrlCStub(runParameters().useCtrlCStub); // This is only set for QNX - const DebuggerRunParameters &rp = runParameters(); CommandLine gdbCommand = rp.debugger.command; @@ -4314,7 +4295,6 @@ void GdbEngine::interruptLocalInferior(qint64 pid) showMessage("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED", LogError); return; } - QString errorMessage; if (runParameters().runAsRoot) { Environment env = Environment::systemEnvironment(); RunControl::provideAskPassEntry(env); @@ -4323,11 +4303,8 @@ void GdbEngine::interruptLocalInferior(qint64 pid) proc.setEnvironment(env); proc.start(); proc.waitForFinished(); - } else if (interruptProcess(pid, GdbEngineType, &errorMessage)) { - showMessage("Interrupted " + QString::number(pid)); } else { - showMessage(errorMessage, LogError); - notifyInferiorStopFailed(); + m_gdbProc.interrupt(); } } diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index e0bfa126f5a..657447f17e0 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -143,7 +143,7 @@ void PdbEngine::handlePdbStarted() void PdbEngine::interruptInferior() { QString error; - interruptProcess(m_proc.processId(), GdbEngineType, &error); + interruptProcess(m_proc.processId(), &error); } void PdbEngine::executeStepIn(bool) diff --git a/src/plugins/debugger/procinterrupt.cpp b/src/plugins/debugger/procinterrupt.cpp index 113fbeefc4f..0f104f3bfc0 100644 --- a/src/plugins/debugger/procinterrupt.cpp +++ b/src/plugins/debugger/procinterrupt.cpp @@ -23,128 +23,23 @@ static inline QString msgCannotInterrupt(qint64 pid, const QString &why) # define PROCESS_SUSPEND_RESUME (0x0800) #endif // PROCESS_SUSPEND_RESUME -static BOOL isWow64Process(HANDLE hproc) -{ - using LPFN_ISWOW64PROCESS = BOOL (WINAPI*)(HANDLE, PBOOL); - - BOOL ret = false; - - static LPFN_ISWOW64PROCESS fnIsWow64Process = NULL; - if (!fnIsWow64Process) { - if (HMODULE hModule = GetModuleHandle(L"kernel32.dll")) - fnIsWow64Process = reinterpret_cast(GetProcAddress(hModule, "IsWow64Process")); - } - - if (!fnIsWow64Process) { - qWarning("Cannot retrieve symbol 'IsWow64Process'."); - return false; - } - - if (!fnIsWow64Process(hproc, &ret)) { - qWarning("IsWow64Process() failed for %p: %s", - hproc, qPrintable(Utils::winErrorMessage(GetLastError()))); - return false; - } - return ret; -} - // Open the process and break into it -bool Debugger::Internal::interruptProcess(qint64 pID, int engineType, QString *errorMessage, const bool engineExecutableIs64Bit) +bool Debugger::Internal::interruptProcess(qint64 pID, QString *errorMessage) { bool ok = false; HANDLE inferior = NULL; - do { - const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION - |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ - |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME; - inferior = OpenProcess(rights, FALSE, DWORD(pID)); - if (inferior == NULL) { - *errorMessage = QString::fromLatin1("Cannot open process %1: %2"). - arg(pID).arg(Utils::winErrorMessage(GetLastError())); - break; - } + const DWORD rights = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_VM_OPERATION + | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_DUP_HANDLE + | PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SUSPEND_RESUME; + inferior = OpenProcess(rights, FALSE, DWORD(pID)); + if (inferior == NULL) { + *errorMessage = QString::fromLatin1("Cannot open process %1: %2") + .arg(pID) + .arg(Utils::winErrorMessage(GetLastError())); + } else if (ok = DebugBreakProcess(inferior); !ok) { + *errorMessage = "DebugBreakProcess failed: " + Utils::winErrorMessage(GetLastError()); + } - 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 - if (isWow64Process(GetCurrentProcess()) - && ((engineType == CdbEngineType && engineExecutableIs64Bit) - || (engineType == GdbEngineType && !isWow64Process(inferior)))) { - breakApi = UseWin64Interrupt; - } -#endif - if (breakApi == UseDebugBreakApi) { - ok = DebugBreakProcess(inferior); - if (!ok) - *errorMessage = "DebugBreakProcess failed: " + Utils::winErrorMessage(GetLastError()); - } else { - const QString executable = breakApi == UseWin32Interrupt - ? QCoreApplication::applicationDirPath() + "/win32interrupt.exe" - : QCoreApplication::applicationDirPath() + "/win64interrupt.exe"; - if (!QFileInfo::exists(executable)) { - *errorMessage = QString::fromLatin1( - "%1 does not exist. If you have built %2 " - "on your own, checkout " - "https://code.qt.io/cgit/qt-creator/binary-artifacts.git/.") - .arg(QDir::toNativeSeparators(executable), - QGuiApplication::applicationDisplayName()); - 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."). - arg(QDir::toNativeSeparators(executable)); - break; - case 0: - ok = true; - break; - default: - *errorMessage = QDir::toNativeSeparators(executable) - + " could not break the process."; - break; - } - break; - } - } while (false); if (inferior != NULL) CloseHandle(inferior); if (!ok) @@ -159,8 +54,7 @@ GDB 32bit | Api | Api | NA | Win32 #include #include -bool Debugger::Internal::interruptProcess(qint64 pID, int /* engineType */, - QString *errorMessage, const bool /*engineExecutableIs64Bit*/) +bool Debugger::Internal::interruptProcess(qint64 pID, QString *errorMessage) { if (pID <= 0) { *errorMessage = msgCannotInterrupt(pID, QString::fromLatin1("Invalid process id.")); diff --git a/src/plugins/debugger/procinterrupt.h b/src/plugins/debugger/procinterrupt.h index c7872ed2e42..ef4d20300db 100644 --- a/src/plugins/debugger/procinterrupt.h +++ b/src/plugins/debugger/procinterrupt.h @@ -7,7 +7,6 @@ namespace Debugger::Internal { -bool interruptProcess(qint64 pID, int engineType, QString *errorMessage, - const bool engineExecutableIs64Bit = false); +bool interruptProcess(qint64 pID, QString *errorMessage); } // Debugger::Internal diff --git a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp index 70412124462..773f4d3bca5 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp @@ -102,90 +102,20 @@ void DesktopProcessSignalOperation::killProcessSilently(qint64 pid) void DesktopProcessSignalOperation::interruptProcessSilently(qint64 pid) { #ifdef Q_OS_WIN - enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt }; - - bool is64BitSystem = is64BitWindowsSystem(); - SpecialInterrupt si = NoSpecialInterrupt; - if (is64BitSystem) - si = is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt; - /* - 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 = UseWin64InterruptHelper - Win32 = UseWin32InterruptHelper - 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 | N/A | Win32 | N/A - 64bit | N/A | Win64 | Win64 | Api | Api -----------|-----------------|-----------------|-----------------|-----------------|---------------- -GDB 32bit | Api | Api | N/A | Win32 | N/A - 64bit | N/A | N/A | Win64 | N/A | Api -----------|-----------------|-----------------|-----------------|-----------------|---------------- - - */ HANDLE inferior = NULL; - do { - const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION - |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ - |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME; - inferior = OpenProcess(rights, FALSE, pid); - if (inferior == NULL) { - appendMsgCannotInterrupt(pid, Tr::tr("Cannot open process: %1") - + winErrorMessage(GetLastError())); - break; - } - bool creatorIs64Bit = is64BitWindowsBinary( - FilePath::fromUserInput(QCoreApplication::applicationFilePath())); - if (!is64BitSystem - || si == NoSpecialInterrupt - || (si == Win64Interrupt && creatorIs64Bit) - || (si == Win32Interrupt && !creatorIs64Bit)) { - if (!DebugBreakProcess(inferior)) { - appendMsgCannotInterrupt(pid, Tr::tr("DebugBreakProcess failed:") - + QLatin1Char(' ') + winErrorMessage(GetLastError())); - } - } else if (si == Win32Interrupt || si == Win64Interrupt) { - QString executable = QCoreApplication::applicationDirPath(); - executable += si == Win32Interrupt - ? QLatin1String("/win32interrupt.exe") - : QLatin1String("/win64interrupt.exe"); - if (!QFileInfo::exists(executable)) { - appendMsgCannotInterrupt(pid, - Tr::tr("%1 does not exist. If you built %2 " - "yourself, check out https://code.qt.io/cgit/" - "qt-creator/binary-artifacts.git/.") - .arg(QDir::toNativeSeparators(executable), - QGuiApplication::applicationDisplayName())); - } - switch (QProcess::execute(executable, QStringList(QString::number(pid)))) { - case -2: - appendMsgCannotInterrupt(pid, Tr::tr( - "Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c " - "for more information.").arg(QDir::toNativeSeparators(executable))); - break; - case 0: - break; - default: - appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable) - + QLatin1Char(' ') + Tr::tr("could not break the process.")); - break; - } - } - } while (false); + const DWORD rights = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_VM_OPERATION + | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_DUP_HANDLE + | PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SUSPEND_RESUME; + inferior = OpenProcess(rights, FALSE, pid); + if (inferior == NULL) { + appendMsgCannotInterrupt( + pid, Tr::tr("Cannot open process: %1") + winErrorMessage(GetLastError())); + } else if (!DebugBreakProcess(inferior)) { + appendMsgCannotInterrupt( + pid, + Tr::tr("DebugBreakProcess failed:") + QLatin1Char(' ') + + winErrorMessage(GetLastError())); + } if (inferior != NULL) CloseHandle(inferior); #else