Commit 14d59059 authored by Friedemann Kleint's avatar Friedemann Kleint

Debugger: Use Startparameters.debuggerCommand for command.

Use in both engines preferred over ABI if it is compatible.
Report start parameters. Introduce gdb configuration check.
parent a49972e7
......@@ -333,6 +333,18 @@ static inline QString msgNoCdbBinaryForToolChain(const ProjectExplorer::Abi &tc)
return CdbEngine::tr("There is no CDB binary available for binaries in format '%1'").arg(tc.toString());
}
static QString cdbBinary(const DebuggerStartParameters &sp)
{
if (!sp.debuggerCommand.isEmpty()) {
// Do not use a GDB binary if we got started for a project with MinGW runtime.
const bool abiMatch = sp.toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS
&& sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvcFlavor;
if (abiMatch)
return sp.debuggerCommand;
}
return debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType);
}
bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check)
{
#ifdef Q_OS_WIN
......@@ -344,13 +356,6 @@ bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck
return false;
}
if (debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType).isEmpty()) {
check->errorDetails.push_back(msgNoCdbBinaryForToolChain(sp.toolChainAbi));
check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
if (!validMode(sp.startMode)) {
check->errorDetails.push_back(CdbEngine::tr("The CDB engine does not support start mode %1.").arg(sp.startMode));
return false;
......@@ -361,6 +366,14 @@ bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck
arg(sp.toolChainAbi.toString()));
return false;
}
if (cdbBinary(sp).isEmpty()) {
check->errorDetails.push_back(msgNoCdbBinaryForToolChain(sp.toolChainAbi));
check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
return true;
#else
Q_UNUSED(sp);
......@@ -652,7 +665,7 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa
// Determine binary (force MSVC), extension lib name and path to use
// The extension is passed as relative name with the path variable set
//(does not work with absolute path names)
const QString executable = debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType);
const QString executable = cdbBinary(sp);
if (executable.isEmpty()) {
*errorMessage = tr("There is no CDB executable specified.");
return false;
......
......@@ -2349,6 +2349,66 @@ void DebuggerPluginPrivate::createNewDock(QWidget *widget)
dockWidget->show();
}
static QString formatStartParameters(DebuggerStartParameters &sp)
{
QString rc;
QTextStream str(&rc);
str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode
<< "\nABI: " << sp.toolChainAbi.toString() << '\n';
if (!sp.executable.isEmpty()) {
str << "Executable: " << QDir::toNativeSeparators(sp.executable) << ' ' << sp.processArgs;
if (sp.useTerminal)
str << " [terminal]";
str << '\n';
if (!sp.workingDirectory.isEmpty())
str << "Directory: " << QDir::toNativeSeparators(sp.workingDirectory) << '\n';
if (sp.executableUid) {
str << "UID: 0x";
str.setIntegerBase(16);
str << sp.executableUid << '\n';
str.setIntegerBase(10);
}
}
if (!sp.debuggerCommand.isEmpty())
str << "Debugger: " << QDir::toNativeSeparators(sp.debuggerCommand) << '\n';
if (!sp.coreFile.isEmpty())
str << "Core: " << QDir::toNativeSeparators(sp.coreFile) << '\n';
if (sp.attachPID > 0)
str << "PID: " << sp.attachPID << ' ' << sp.crashParameter << '\n';
if (!sp.projectDir.isEmpty()) {
str << "Project: " << QDir::toNativeSeparators(sp.projectDir);
if (!sp.projectBuildDir.isEmpty())
str << " (built: " << QDir::toNativeSeparators(sp.projectBuildDir);
str << '\n';
}
if (!sp.qmlServerAddress.isEmpty())
str << "QML server: " << sp.qmlServerAddress << ':' << sp.qmlServerPort << '\n';
if (!sp.remoteChannel.isEmpty()) {
str << "Remote: " << sp.remoteChannel << ", " << sp.remoteArchitecture << '\n';
if (!sp.remoteDumperLib.isEmpty())
str << "Remote dumpers: " << sp.remoteDumperLib << '\n';
if (!sp.remoteSourcesDir.isEmpty())
str << "Remote sources: " << sp.remoteSourcesDir << '\n';
if (!sp.remoteMountPoint.isEmpty())
str << "Remote mount point: " << sp.remoteMountPoint << " Local: " << sp.localMountDir << '\n';
}
if (!sp.gnuTarget.isEmpty())
str << "Gnu target: " << sp.gnuTarget << '\n';
if (!sp.sysRoot.isEmpty())
str << "Sysroot: " << sp.sysRoot << '\n';
if (!sp.symbolFileName.isEmpty())
str << "Symbol file: " << sp.symbolFileName << '\n';
if (sp.useServerStartScript)
str << "Using server start script: " << sp.serverStartScript;
if (!sp.dumperLibrary.isEmpty()) {
str << "Dumper libraries: " << QDir::toNativeSeparators(sp.dumperLibrary);
foreach (const QString &dl, sp.dumperLibraryLocations)
str << ' ' << QDir::toNativeSeparators(dl);
str << '\n';
}
return rc;
}
void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
{
activateDebugMode();
......@@ -2356,6 +2416,7 @@ void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
.arg(engine->objectName())
.arg(engine->startParameters().toolChainAbi.toString());
showMessage(message, StatusBar);
showMessage(formatStartParameters(engine->startParameters()), LogDebug);
showMessage(m_debuggerSettings->dump(), LogDebug);
m_snapshotHandler->appendSnapshot(engine);
connectEngine(engine);
......
......@@ -78,11 +78,13 @@ namespace Internal {
bool isCdbEngineEnabled(); // Check the configuration page
bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check);
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp,
DebuggerEngine *masterEngine, QString *error);
bool checkGdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check);
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &sp,
DebuggerEngine *masterEngine);
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp);
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp);
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &sp);
......@@ -476,34 +478,6 @@ static QList<DebuggerEngineType> engineTypes(const DebuggerStartParameters &sp)
return result;
}
// Engine detection logic: Configuration checks.
QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &tc, DebuggerEngineType et)
{
return DebuggerPlugin::tr("There is no binary available for debugging binaries of type '%1' using the engine '%2'").
arg(tc.toString(), QLatin1String(engineTypeName(et)));
}
static inline bool engineConfigurationCheck(const DebuggerStartParameters &sp,
DebuggerEngineType et,
ConfigurationCheck *check)
{
switch (et) {
case Debugger::CdbEngineType:
return checkCdbConfiguration(sp, check);
case Debugger::GdbEngineType:
if (debuggerCore()->debuggerForAbi(sp.toolChainAbi, et).isEmpty()) {
check->errorDetails.push_back(msgNoBinaryForToolChain(sp.toolChainAbi, et));
check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
default:
break;
}
return true;
}
// Engine detection logic: ConfigurationCheck.
ConfigurationCheck::ConfigurationCheck() :
masterSlaveEngineTypes(NoEngineType, NoEngineType)
......@@ -575,9 +549,25 @@ DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartPa
}
if (debug)
qDebug() << " Usable engines: " << engineTypeNames(usableTypes);
// Configuration check: Strip off non-configured engines.
while (!usableTypes.isEmpty() && !engineConfigurationCheck(sp, usableTypes.front(), &result))
usableTypes.pop_front();
// Configuration check: Strip off non-configured engines, find first one to use.
while (!usableTypes.isEmpty()) {
bool configurationOk = true;
switch (usableTypes.front()) {
case Debugger::CdbEngineType:
configurationOk = checkCdbConfiguration(sp, &result);
break;
case Debugger::GdbEngineType:
configurationOk = checkGdbConfiguration(sp, &result);
break;
default:
break;
}
if (configurationOk) {
break;
} else {
usableTypes.pop_front();
}
}
if (debug)
qDebug() << "Configured engines: " << engineTypeNames(usableTypes);
if (usableTypes.isEmpty()) {
......@@ -585,6 +575,8 @@ DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartPa
return result;
}
// Anything left: Happy.
result.errorMessage.clear();
result.errorDetails.clear();
if (qmlLanguage && cppLanguage) {
result.masterSlaveEngineTypes.first = QmlCppEngineType;
result.masterSlaveEngineTypes.second = usableTypes.front();
......
......@@ -96,9 +96,6 @@ public:
QString projectBuildDir;
QString projectDir;
// Used by combined cpp+qml debugging.
DebuggerEngineType cppEngineType;
// Used by remote debugging.
QString remoteChannel;
QString remoteArchitecture;
......
......@@ -54,10 +54,11 @@ void DebuggerToolChainComboBox::init(bool hostAbiOnly)
{
const ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi();
foreach (const ProjectExplorer::ToolChain *tc, ProjectExplorer::ToolChainManager::instance()->toolChains()) {
if (!hostAbiOnly || hostAbi.isCompatibleWith(tc->targetAbi())) {
if (!hostAbiOnly || hostAbi.os() == hostAbi.os()) { // Offer MSVC and Mingw, etc.
const QString debuggerCommand = tc->debuggerCommand();
if (!debuggerCommand.isEmpty()) {
const QString name = tr("%1 (%2)").arg(tc->displayName(), QFileInfo(debuggerCommand).baseName());
const QString completeBase = QFileInfo(debuggerCommand).completeBaseName();
const QString name = tr("%1 (%2)").arg(tc->displayName(), completeBase);
addItem(name, qVariantFromValue(tc->targetAbi()));
}
}
......
......@@ -59,7 +59,6 @@ protected:
virtual bool event(QEvent *event);
private:
ProjectExplorer::Abi abiAt(int index) const;
};
......
......@@ -377,7 +377,7 @@ void CodaGdbAdapter::startGdb()
{
QStringList gdbArgs;
gdbArgs.append(_("--nx")); // Do not read .gdbinit file
if (!m_engine->startGdb(gdbArgs, QString(), QString())) {
if (!m_engine->startGdb(gdbArgs)) {
cleanup();
return;
}
......
......@@ -79,7 +79,7 @@ void CoreGdbAdapter::startAdapter()
QStringList args;
args.append(_("-ex"));
args.append(_("set auto-solib-add off"));
if (!m_engine->startGdb(args))
if (!m_engine->startGdb(args, QString()))
return;
//if (m_executable.isEmpty()) {
......
......@@ -76,6 +76,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/ifile.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <texteditor/itexteditor.h>
#include <utils/qtcassert.h>
......@@ -4203,23 +4204,62 @@ void GdbEngine::handleFetchDisassemblerByCliRangePlain(const GdbResponse &respon
.arg(QString::fromLocal8Bit(msg)), 5000);
}
// Binary/configuration check logic.
static QString gdbBinary(const DebuggerStartParameters &sp)
{
// 1) Environment.
const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
if (!envBinary.isEmpty())
return QString::fromLocal8Bit(envBinary);
// 2) Command explicitly specified.
if (!sp.debuggerCommand.isEmpty()) {
#ifdef Q_OS_WIN
// Do not use a CDB binary if we got started for a project with MSVC runtime.
const bool abiMatch = sp.toolChainAbi.os() != ProjectExplorer::Abi::WindowsOS
|| sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor;
#else
const bool abiMatch = true;
#endif
if (abiMatch)
return sp.debuggerCommand;
}
// 3) Find one from toolchains.
return debuggerCore()->debuggerForAbi(sp.toolChainAbi, GdbEngineType);
}
bool checkGdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check)
{
const QString binary = gdbBinary(sp);
if (gdbBinary(sp).isEmpty()) {
check->errorDetails.push_back(msgNoGdbBinaryForToolChain(sp.toolChainAbi));
check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
#ifdef Q_OS_WIN
// See initialization below, we need an absolute path to be able to locate Python on Windows.
if (!QFileInfo(binary).isAbsolute()) {
check->errorDetails.push_back(GdbEngine::tr("The gdb location must be given as an "
"absolute path in the debugger settings (%1).").arg(binary));
check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
return false;
}
#endif
return true;
}
//
// Starting up & shutting down
//
bool GdbEngine::startGdb(const QStringList &args, const QString &gdb,
const QString &settingsIdHint)
bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint)
{
gdbProc()->disconnect(); // From any previous runs
const DebuggerStartParameters &sp = startParameters();
m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH"));
if (m_gdb.isEmpty() && sp.startMode != StartRemoteGdb) {
m_gdb = debuggerCore()->debuggerForAbi(startParameters().toolChainAbi, GdbEngineType);
}
if (m_gdb.isEmpty())
m_gdb = gdb;
m_gdb = gdbBinary(sp);
if (m_gdb.isEmpty()) {
handleAdapterStartFailed(
msgNoGdbBinaryForToolChain(sp.toolChainAbi),
......@@ -4237,13 +4277,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb,
// Set python path. By convention, python is located below gdb executable.
// Extend the environment set on the process in startAdapter().
const QFileInfo fi(m_gdb);
if (!fi.isAbsolute()) {
showMessage(_("GDB %1 DOES NOT HAVE ABSOLUTE LOCATION.").arg(m_gdb));
const QString msg = tr("The gdb location must be given as an "
"absolute path in the debugger settings.");
handleAdapterStartFailed(msg, settingsIdHint);
return false;
}
QTC_ASSERT(fi.isAbsolute(), return false; )
const QString winPythonVersion = _(winPythonVersionC);
const QDir dir = fi.absoluteDir();
......
......@@ -132,7 +132,6 @@ private: ////////// Gdb Process Management //////////
AbstractGdbAdapter *createAdapter();
bool startGdb(const QStringList &args = QStringList(),
const QString &gdb = QString(),
const QString &settingsIdHint = QString());
void handleInferiorShutdown(const GdbResponse &response);
void handleGdbExit(const GdbResponse &response);
......
......@@ -317,7 +317,7 @@ void RemoteGdbServerAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPor
void RemoteGdbServerAdapter::handleSetupDone()
{
if (m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
if (m_engine->startGdb())
m_engine->handleAdapterStarted();
}
......
......@@ -123,8 +123,7 @@ void RemotePlainGdbAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort
void RemotePlainGdbAdapter::handleGdbStarted()
{
if (m_engine->startGdb(QStringList(),
m_engine->startParameters().debuggerCommand))
if (m_engine->startGdb())
m_engine->handleAdapterStarted();
}
......
......@@ -1475,7 +1475,7 @@ void TrkGdbAdapter::slotStartGdb()
{
QStringList gdbArgs;
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
if (!m_engine->startGdb(gdbArgs, QString(), QString())) {
if (!m_engine->startGdb(gdbArgs)) {
cleanup();
return;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment