Debugger: Use Utils::CommandLine handling in CDB

Change-Id: I124f7eeee5eb5028fb3316f69144fdcdfe63bc4d
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2019-06-12 12:33:46 +02:00
parent a38c3ac08e
commit 2942ae876c
2 changed files with 44 additions and 76 deletions

View File

@@ -295,35 +295,6 @@ QString CdbEngine::extensionLibraryName(bool is64Bit)
return rc; return rc;
} }
// Determine environment for CDB.exe, start out with run config and
// add CDB extension path merged with system value should there be one.
static QStringList mergeEnvironment(QStringList runConfigEnvironment,
QString cdbExtensionPath)
{
// Determine CDB extension path from Qt Creator
static const char cdbExtensionPathVariableC[] = "_NT_DEBUGGER_EXTENSION_PATH";
const QByteArray oldCdbExtensionPath = qgetenv(cdbExtensionPathVariableC);
if (!oldCdbExtensionPath.isEmpty()) {
cdbExtensionPath.append(';');
cdbExtensionPath.append(QString::fromLocal8Bit(oldCdbExtensionPath));
}
// We do not assume someone sets _NT_DEBUGGER_EXTENSION_PATH in the run
// config, just to make sure, delete any existing entries
const QString cdbExtensionPathVariableAssign =
QLatin1String(cdbExtensionPathVariableC) + '=';
for (QStringList::iterator it = runConfigEnvironment.begin(); it != runConfigEnvironment.end() ; ) {
if (it->startsWith(cdbExtensionPathVariableAssign)) {
it = runConfigEnvironment.erase(it);
break;
} else {
++it;
}
}
runConfigEnvironment.append(cdbExtensionPathVariableAssign +
QDir::toNativeSeparators(cdbExtensionPath));
return runConfigEnvironment;
}
int CdbEngine::elapsedLogTime() const int CdbEngine::elapsedLogTime() const
{ {
const int elapsed = m_logTime.elapsed(); const int elapsed = m_logTime.elapsed();
@@ -372,18 +343,16 @@ void CdbEngine::setupEngine()
m_effectiveStartMode = sp.startMode; m_effectiveStartMode = sp.startMode;
} }
const QChar blank(' ');
// Start engine which will run until initial breakpoint: // Start engine which will run until initial breakpoint:
// Determine binary (force MSVC), extension lib name and path to use // Determine binary (force MSVC), extension lib name and path to use
// The extension is passed as relative name with the path variable set // The extension is passed as relative name with the path variable set
//(does not work with absolute path names) //(does not work with absolute path names)
const QString executable = sp.debugger.executable; if (sp.debugger.executable.isEmpty()) {
if (executable.isEmpty()) {
handleSetupFailure(tr("There is no CDB executable specified.")); handleSetupFailure(tr("There is no CDB executable specified."));
return; return;
} }
bool cdbIs64Bit = Utils::is64BitWindowsBinary(executable); bool cdbIs64Bit = Utils::is64BitWindowsBinary(sp.debugger.executable);
if (!cdbIs64Bit) if (!cdbIs64Bit)
m_wow64State = noWow64Stack; m_wow64State = noWow64Stack;
const QFileInfo extensionFi(CdbEngine::extensionLibraryName(cdbIs64Bit)); const QFileInfo extensionFi(CdbEngine::extensionLibraryName(cdbIs64Bit));
@@ -401,28 +370,32 @@ void CdbEngine::setupEngine()
Core::Constants::IDE_DISPLAY_NAME)); Core::Constants::IDE_DISPLAY_NAME));
return; return;
} }
// Prepare command line.
CommandLine debugger{FilePath::fromString(sp.debugger.executable)};
const QString extensionFileName = extensionFi.fileName(); const QString extensionFileName = extensionFi.fileName();
// Prepare arguments
QStringList arguments;
const bool isRemote = sp.startMode == AttachToRemoteServer; const bool isRemote = sp.startMode == AttachToRemoteServer;
if (isRemote) { // Must be first if (isRemote) { // Must be first
arguments << "-remote" << sp.remoteChannel; debugger.addArgs({"-remote", sp.remoteChannel});
} else { } else {
arguments << ("-a" + extensionFileName); debugger.addArg("-a" + extensionFileName);
} }
// Source line info/No terminal breakpoint / Pull extension // Source line info/No terminal breakpoint / Pull extension
arguments << "-lines" << "-G" debugger.addArgs({"-lines", "-G",
// register idle (debuggee stop) notification // register idle (debuggee stop) notification
<< "-c" "-c", ".idle_cmd " + m_extensionCommandPrefix + "idle"});
<< ".idle_cmd " + m_extensionCommandPrefix + "idle";
if (sp.useTerminal) // Separate console if (sp.useTerminal) // Separate console
arguments << "-2"; debugger.addArg("-2");
if (boolSetting(IgnoreFirstChanceAccessViolation)) if (boolSetting(IgnoreFirstChanceAccessViolation))
arguments << "-x"; debugger.addArg("-x");
const QStringList &sourcePaths = stringListSetting(CdbSourcePaths); const QStringList &sourcePaths = stringListSetting(CdbSourcePaths);
if (!sourcePaths.isEmpty()) if (!sourcePaths.isEmpty())
arguments << "-srcpath" << sourcePaths.join(';'); debugger.addArgs({"-srcpath", sourcePaths.join(';')});
QStringList symbolPaths = stringListSetting(CdbSymbolPaths); QStringList symbolPaths = stringListSetting(CdbSymbolPaths);
QString symbolPath = sp.inferior.environment.value("_NT_ALT_SYMBOL_PATH"); QString symbolPath = sp.inferior.environment.value("_NT_ALT_SYMBOL_PATH");
@@ -431,48 +404,39 @@ void CdbEngine::setupEngine()
symbolPath = sp.inferior.environment.value("_NT_SYMBOL_PATH"); symbolPath = sp.inferior.environment.value("_NT_SYMBOL_PATH");
if (!symbolPath.isEmpty()) if (!symbolPath.isEmpty())
symbolPaths += symbolPath; symbolPaths += symbolPath;
arguments << "-y" << (symbolPaths.isEmpty() ? "\"\"" : symbolPaths.join(';')); debugger.addArgs({"-y", symbolPaths.join(';')});
// Compile argument string preserving quotes
QString nativeArguments = expand(stringSetting(CdbAdditionalArguments));
switch (sp.startMode) { switch (sp.startMode) {
case StartInternal: case StartInternal:
case StartExternal: case StartExternal:
if (!nativeArguments.isEmpty()) debugger.addArg(QDir::toNativeSeparators(sp.inferior.executable));
nativeArguments.push_back(blank); // Complete native argument string.
QtcProcess::addArgs(&nativeArguments, debugger.addArgs(sp.inferior.commandLineArguments, CommandLine::Raw);
QStringList(QDir::toNativeSeparators(sp.inferior.executable)));
if (!sp.inferior.commandLineArguments.isEmpty()) { // Complete native argument string.
if (!nativeArguments.isEmpty())
nativeArguments.push_back(blank);
nativeArguments += sp.inferior.commandLineArguments;
}
break; break;
case AttachToRemoteServer: case AttachToRemoteServer:
break; break;
case AttachExternal: case AttachExternal:
case AttachCrashedExternal: case AttachCrashedExternal:
arguments << "-p" << QString::number(sp.attachPID.pid()); debugger.addArgs({"-p", QString::number(sp.attachPID.pid())});
if (sp.startMode == AttachCrashedExternal) { if (sp.startMode == AttachCrashedExternal) {
arguments << "-e" << sp.crashParameter << "-g"; debugger.addArgs({"-e", sp.crashParameter, "-g"});
} else { } else {
if (terminal()) if (terminal())
arguments << "-pr" << "-pb"; debugger.addArgs({"-pr", "-pb"});
} }
break; break;
case AttachCore: case AttachCore:
arguments << "-z" << sp.coreFile; debugger.addArgs({"-z", sp.coreFile});
break; break;
default: default:
handleSetupFailure(QString("Internal error: Unsupported start mode %1.").arg(sp.startMode)); handleSetupFailure(QString("Internal error: Unsupported start mode %1.").arg(sp.startMode));
return; return;
} }
const QString msg = QString("Launching %1 %2\nusing %3 of %4."). const QString msg = QString("Launching %1\nusing %2 of %3.")
arg(QDir::toNativeSeparators(executable), .arg(debugger.toUserOutput(),
arguments.join(blank) + blank + nativeArguments, QDir::toNativeSeparators(extensionFi.absoluteFilePath()),
QDir::toNativeSeparators(extensionFi.absoluteFilePath()), extensionFi.lastModified().toString(Qt::SystemLocaleShortDate));
extensionFi.lastModified().toString(Qt::SystemLocaleShortDate));
showMessage(msg, LogMisc); showMessage(msg, LogMisc);
m_outputBuffer.clear(); m_outputBuffer.clear();
@@ -486,25 +450,29 @@ void CdbEngine::setupEngine()
if (!sp.useTerminal && !inferiorEnvironment.hasKey(qtLoggingToConsoleKey)) if (!sp.useTerminal && !inferiorEnvironment.hasKey(qtLoggingToConsoleKey))
inferiorEnvironment.set(qtLoggingToConsoleKey, "0"); inferiorEnvironment.set(qtLoggingToConsoleKey, "0");
m_process.setEnvironment(mergeEnvironment(inferiorEnvironment.toStringList(), static const char cdbExtensionPathVariableC[] = "_NT_DEBUGGER_EXTENSION_PATH";
extensionFi.absolutePath())); inferiorEnvironment.prependOrSet(cdbExtensionPathVariableC, extensionFi.absolutePath());
const QByteArray oldCdbExtensionPath = qgetenv(cdbExtensionPathVariableC);
if (!oldCdbExtensionPath.isEmpty()) {
inferiorEnvironment.appendOrSet(cdbExtensionPathVariableC,
QString::fromLocal8Bit(oldCdbExtensionPath));
}
m_process.setEnvironment(inferiorEnvironment);
if (!sp.inferior.workingDirectory.isEmpty()) if (!sp.inferior.workingDirectory.isEmpty())
m_process.setWorkingDirectory(sp.inferior.workingDirectory); m_process.setWorkingDirectory(sp.inferior.workingDirectory);
#ifdef Q_OS_WIN m_process.setCommand(debugger);
if (!nativeArguments.isEmpty()) // Appends m_process.start();
m_process.setNativeArguments(nativeArguments);
#endif
m_process.start(executable, arguments);
if (!m_process.waitForStarted()) { if (!m_process.waitForStarted()) {
handleSetupFailure(QString("Internal error: Cannot start process %1: %2"). handleSetupFailure(QString("Internal error: Cannot start process %1: %2").
arg(QDir::toNativeSeparators(executable), m_process.errorString())); arg(debugger.toUserOutput(), m_process.errorString()));
return; return;
} }
const qint64 pid = m_process.processId(); const qint64 pid = m_process.processId();
showMessage(QString("%1 running as %2"). showMessage(QString("%1 running as %2").arg(debugger.executable().toUserOutput()).arg(pid),
arg(QDir::toNativeSeparators(executable)).arg(pid), LogMisc); LogMisc);
m_hasDebuggee = true; m_hasDebuggee = true;
m_initialSessionIdleHandled = false; m_initialSessionIdleHandled = false;
if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible

View File

@@ -202,7 +202,7 @@ private:
const QString m_tokenPrefix; const QString m_tokenPrefix;
void handleSetupFailure(const QString &errorMessage); void handleSetupFailure(const QString &errorMessage);
QProcess m_process; Utils::QtcProcess m_process;
DebuggerStartMode m_effectiveStartMode = NoStartMode; DebuggerStartMode m_effectiveStartMode = NoStartMode;
QByteArray m_outputBuffer; QByteArray m_outputBuffer;
//! Debugger accessible (expecting commands) //! Debugger accessible (expecting commands)