forked from qt-creator/qt-creator
Valgrind: Support vgdb
Change-Id: Id9f653a81d329494017653b8fc7ec9960e20dbcd Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
@@ -80,8 +80,8 @@ RunControl *AndroidRunControlFactory::create(RunConfiguration *runConfig,
|
||||
case DebugRunModeWithBreakOnMain:
|
||||
case CallgrindRunMode:
|
||||
case MemcheckRunMode:
|
||||
case MemcheckWithGdbRunMode:
|
||||
case ClangStaticAnalyzerMode:
|
||||
default:
|
||||
QTC_CHECK(false); // The other run modes are not supported
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -274,6 +274,7 @@ enum RunMode {
|
||||
QmlProfilerRunMode,
|
||||
CallgrindRunMode,
|
||||
MemcheckRunMode,
|
||||
MemcheckWithGdbRunMode,
|
||||
ClangStaticAnalyzerMode
|
||||
};
|
||||
|
||||
|
||||
@@ -198,6 +198,7 @@ RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, RunMode mo
|
||||
case NoRunMode:
|
||||
case CallgrindRunMode:
|
||||
case MemcheckRunMode:
|
||||
case MemcheckWithGdbRunMode:
|
||||
case ClangStaticAnalyzerMode:
|
||||
case DebugRunModeWithBreakOnMain:
|
||||
QTC_ASSERT(false, return 0);
|
||||
|
||||
@@ -126,6 +126,7 @@ RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Ru
|
||||
case NoRunMode:
|
||||
case CallgrindRunMode:
|
||||
case MemcheckRunMode:
|
||||
case MemcheckWithGdbRunMode:
|
||||
case ClangStaticAnalyzerMode:
|
||||
QTC_ASSERT(false, return 0);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,8 @@ class MemcheckRunner::Private
|
||||
public:
|
||||
explicit Private()
|
||||
: parser(0),
|
||||
logSocket(0)
|
||||
logSocket(0),
|
||||
disableXml(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,6 +66,7 @@ public:
|
||||
XmlProtocol::ThreadedParser *parser;
|
||||
QTcpServer logServer;
|
||||
QTcpSocket *logSocket;
|
||||
bool disableXml;
|
||||
};
|
||||
|
||||
MemcheckRunner::MemcheckRunner(QObject *parent)
|
||||
@@ -106,6 +108,13 @@ bool MemcheckRunner::start()
|
||||
return ValgrindRunner::start();
|
||||
}
|
||||
|
||||
// Workaround for valgrind bug when running vgdb with xml output
|
||||
// https://bugs.kde.org/show_bug.cgi?id=343902
|
||||
void MemcheckRunner::disableXml()
|
||||
{
|
||||
d->disableXml = true;
|
||||
}
|
||||
|
||||
void MemcheckRunner::xmlSocketConnected()
|
||||
{
|
||||
QTcpSocket *socket = d->xmlServer.nextPendingConnection();
|
||||
@@ -157,13 +166,15 @@ bool MemcheckRunner::startServers(const QHostAddress &localHostAddress)
|
||||
|
||||
QStringList MemcheckRunner::memcheckLogArguments() const
|
||||
{
|
||||
return QStringList()
|
||||
<< QLatin1String("--xml=yes")
|
||||
<< QString::fromLatin1("--xml-socket=%1:%2")
|
||||
QStringList arguments;
|
||||
if (!d->disableXml)
|
||||
arguments << QLatin1String("--xml=yes");
|
||||
arguments << QString::fromLatin1("--xml-socket=%1:%2")
|
||||
.arg(d->xmlServer.serverAddress().toString()).arg(d->xmlServer.serverPort())
|
||||
<< QLatin1String("--child-silent-after-fork=yes")
|
||||
<< QString::fromLatin1("--log-socket=%1:%2")
|
||||
.arg(d->logServer.serverAddress().toString()).arg(d->logServer.serverPort());
|
||||
return arguments;
|
||||
}
|
||||
|
||||
void MemcheckRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress)
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
|
||||
void setParser(XmlProtocol::ThreadedParser *parser);
|
||||
bool start();
|
||||
void disableXml();
|
||||
|
||||
signals:
|
||||
void logMessageReceived(const QByteArray &);
|
||||
|
||||
@@ -30,14 +30,22 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "memcheckengine.h"
|
||||
|
||||
#include "valgrindprocess.h"
|
||||
#include "valgrindsettings.h"
|
||||
#include "xmlprotocol/error.h"
|
||||
#include "xmlprotocol/status.h"
|
||||
|
||||
#include <debugger/debuggerkitinformation.h>
|
||||
#include <debugger/debuggerstartparameters.h>
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
#include <valgrind/xmlprotocol/status.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -65,7 +73,7 @@ QString MemcheckRunControl::progressTitle() const
|
||||
return tr("Analyzing Memory");
|
||||
}
|
||||
|
||||
Valgrind::ValgrindRunner *MemcheckRunControl::runner()
|
||||
ValgrindRunner *MemcheckRunControl::runner()
|
||||
{
|
||||
return &m_runner;
|
||||
}
|
||||
@@ -129,5 +137,70 @@ QStringList MemcheckRunControl::suppressionFiles() const
|
||||
return m_settings->suppressionFiles();
|
||||
}
|
||||
|
||||
MemcheckWithGdbRunControl::MemcheckWithGdbRunControl(const AnalyzerStartParameters &sp,
|
||||
RunConfiguration *runConfiguration)
|
||||
: MemcheckRunControl(sp, runConfiguration)
|
||||
{
|
||||
connect(&m_runner, &Memcheck::MemcheckRunner::started,
|
||||
this, &MemcheckWithGdbRunControl::startDebugger);
|
||||
connect(&m_runner, &Memcheck::MemcheckRunner::logMessageReceived,
|
||||
this, &MemcheckWithGdbRunControl::appendLog);
|
||||
disconnect(&m_parser, &ThreadedParser::internalError,
|
||||
this, &MemcheckRunControl::internalParserError);
|
||||
m_runner.disableXml();
|
||||
}
|
||||
|
||||
QStringList MemcheckWithGdbRunControl::toolArguments() const
|
||||
{
|
||||
return MemcheckRunControl::toolArguments()
|
||||
<< QLatin1String("--vgdb=yes") << QLatin1String("--vgdb-error=0");
|
||||
}
|
||||
|
||||
void MemcheckWithGdbRunControl::startDebugger()
|
||||
{
|
||||
const qint64 valgrindPid = runner()->valgrindProcess()->pid();
|
||||
const AnalyzerStartParameters &mySp = startParameters();
|
||||
Debugger::DebuggerStartParameters sp;
|
||||
|
||||
RunConfiguration *rc = runConfiguration();
|
||||
const Target *target = rc->target();
|
||||
QTC_ASSERT(target, return);
|
||||
|
||||
const Kit *kit = target->kit();
|
||||
QTC_ASSERT(kit, return);
|
||||
|
||||
if (const ToolChain *tc = ToolChainKitInformation::toolChain(kit))
|
||||
sp.toolChainAbi = tc->targetAbi();
|
||||
|
||||
if (const Project *project = target->project()) {
|
||||
sp.projectSourceDirectory = project->projectDirectory().toString();
|
||||
sp.projectSourceFiles = project->files(Project::ExcludeGeneratedFiles);
|
||||
|
||||
if (const BuildConfiguration *bc = target->activeBuildConfiguration())
|
||||
sp.projectBuildDirectory = bc->buildDirectory().toString();
|
||||
}
|
||||
|
||||
sp.executable = mySp.debuggee;
|
||||
sp.sysRoot = SysRootKitInformation::sysRoot(kit).toString();
|
||||
sp.debuggerCommand = Debugger::DebuggerKitInformation::debuggerCommand(kit).toString();
|
||||
sp.languages |= Debugger::CppLanguage;
|
||||
sp.startMode = Debugger::AttachToRemoteServer;
|
||||
sp.displayName = QString::fromLatin1("VGdb %1").arg(valgrindPid);
|
||||
sp.remoteChannel = QString::fromLatin1("| vgdb --pid=%1").arg(valgrindPid);
|
||||
sp.useContinueInsteadOfRun = true;
|
||||
|
||||
QString errorMessage;
|
||||
RunControl *gdbRunControl = Debugger::DebuggerRunControlFactory::doCreate(sp, rc, &errorMessage);
|
||||
QTC_ASSERT(gdbRunControl, return);
|
||||
connect(gdbRunControl, &RunControl::finished,
|
||||
gdbRunControl, &RunControl::deleteLater);
|
||||
gdbRunControl->start();
|
||||
}
|
||||
|
||||
void MemcheckWithGdbRunControl::appendLog(const QByteArray &data)
|
||||
{
|
||||
appendMessage(QString::fromUtf8(data), Utils::StdOutFormat);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
@@ -59,15 +59,29 @@ signals:
|
||||
void suppressionCount(const QString &name, qint64 count);
|
||||
|
||||
protected:
|
||||
virtual QString progressTitle() const;
|
||||
virtual QStringList toolArguments() const;
|
||||
virtual ValgrindRunner *runner();
|
||||
QString progressTitle() const Q_DECL_OVERRIDE;
|
||||
QStringList toolArguments() const Q_DECL_OVERRIDE;
|
||||
ValgrindRunner *runner() Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
protected:
|
||||
XmlProtocol::ThreadedParser m_parser;
|
||||
Memcheck::MemcheckRunner m_runner;
|
||||
};
|
||||
|
||||
class MemcheckWithGdbRunControl : public MemcheckRunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MemcheckWithGdbRunControl(const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration);
|
||||
|
||||
protected:
|
||||
QStringList toolArguments() const Q_DECL_OVERRIDE;
|
||||
void startDebugger();
|
||||
void appendLog(const QByteArray &data);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
|
||||
@@ -438,7 +438,7 @@ AnalyzerRunControl *MemcheckTool::createRunControl(const AnalyzerStartParameters
|
||||
m_frameFinder->setFiles(runConfiguration ? runConfiguration->target()
|
||||
->project()->files(Project::AllFiles) : QStringList());
|
||||
|
||||
MemcheckRunControl *engine = new MemcheckRunControl(sp, runConfiguration);
|
||||
MemcheckRunControl *engine = createMemcheckRunControl(sp, runConfiguration);
|
||||
|
||||
connect(engine, &MemcheckRunControl::starting, this, &MemcheckTool::engineStarting);
|
||||
connect(engine, &MemcheckRunControl::parserError, this, &MemcheckTool::parserError);
|
||||
@@ -571,6 +571,12 @@ int MemcheckTool::updateUiAfterFinishedHelper()
|
||||
return issuesFound;
|
||||
}
|
||||
|
||||
MemcheckRunControl *MemcheckTool::createMemcheckRunControl(const AnalyzerStartParameters &sp,
|
||||
RunConfiguration *runConfiguration)
|
||||
{
|
||||
return new MemcheckRunControl(sp, runConfiguration);
|
||||
}
|
||||
|
||||
void MemcheckTool::engineFinished()
|
||||
{
|
||||
const int issuesFound = updateUiAfterFinishedHelper();
|
||||
@@ -593,5 +599,18 @@ void MemcheckTool::setBusyCursor(bool busy)
|
||||
m_errorView->setCursor(cursor);
|
||||
}
|
||||
|
||||
MemcheckWithGdbTool::MemcheckWithGdbTool(QObject *parent) :
|
||||
MemcheckTool(parent)
|
||||
{
|
||||
setRunMode(MemcheckWithGdbRunMode);
|
||||
setObjectName(QLatin1String("MemcheckWithGdbTool"));
|
||||
}
|
||||
|
||||
MemcheckRunControl *MemcheckWithGdbTool::createMemcheckRunControl(const AnalyzerStartParameters &sp,
|
||||
RunConfiguration *runConfiguration)
|
||||
{
|
||||
return new MemcheckWithGdbRunControl(sp, runConfiguration);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Internal {
|
||||
|
||||
class FrameFinder;
|
||||
class MemcheckErrorView;
|
||||
class MemcheckRunControl;
|
||||
class ValgrindBaseSettings;
|
||||
|
||||
class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel
|
||||
@@ -108,6 +109,11 @@ private:
|
||||
void updateFromSettings();
|
||||
int updateUiAfterFinishedHelper();
|
||||
|
||||
protected:
|
||||
virtual MemcheckRunControl *createMemcheckRunControl(
|
||||
const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration);
|
||||
|
||||
private:
|
||||
ValgrindBaseSettings *m_settings;
|
||||
QMenu *m_filterMenu;
|
||||
@@ -126,6 +132,17 @@ private:
|
||||
QAction *m_goNext;
|
||||
};
|
||||
|
||||
class MemcheckWithGdbTool : public MemcheckTool
|
||||
{
|
||||
public:
|
||||
MemcheckWithGdbTool(QObject *parent);
|
||||
|
||||
protected:
|
||||
MemcheckRunControl *createMemcheckRunControl(
|
||||
const Analyzer::AnalyzerStartParameters &sp,
|
||||
ProjectExplorer::RunConfiguration *runConfiguration) Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ QTC_LIB_DEPENDS += \
|
||||
QTC_PLUGIN_DEPENDS += \
|
||||
analyzerbase \
|
||||
coreplugin \
|
||||
debugger \
|
||||
projectexplorer \
|
||||
texteditor \
|
||||
remotelinux
|
||||
|
||||
@@ -116,6 +116,7 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
|
||||
addAutoReleasedObject(new ValgrindOptionsPage());
|
||||
|
||||
m_memcheckTool = new MemcheckTool(this);
|
||||
m_memcheckWithGdbTool = new MemcheckWithGdbTool(this);
|
||||
m_callgrindTool = new CallgrindTool(this);
|
||||
|
||||
ValgrindAction *action = 0;
|
||||
@@ -126,6 +127,10 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
|
||||
QString memcheckToolTip = tr("Valgrind Analyze Memory uses the "
|
||||
"\"memcheck\" tool to find memory leaks.");
|
||||
|
||||
QString memcheckWithGdbToolTip = tr(
|
||||
"Valgrind Analyze Memory with GDB uses the \"memcheck\" tool to find memory leaks.\n"
|
||||
"When a problem is detected, the application is interrupted and can be debugged");
|
||||
|
||||
if (!Utils::HostOsInfo::isWindowsHost()) {
|
||||
action = new ValgrindAction(this);
|
||||
action->setId("Memcheck.Local");
|
||||
@@ -137,6 +142,16 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
|
||||
action->setEnabled(false);
|
||||
AnalyzerManager::addAction(action);
|
||||
|
||||
action = new ValgrindAction(this);
|
||||
action->setId("MemcheckWithGdb.Local");
|
||||
action->setTool(m_memcheckWithGdbTool);
|
||||
action->setText(tr("Valgrind Memory Analyzer with GDB"));
|
||||
action->setToolTip(memcheckWithGdbToolTip);
|
||||
action->setMenuGroup(Constants::G_ANALYZER_TOOLS);
|
||||
action->setStartMode(StartLocal);
|
||||
action->setEnabled(false);
|
||||
AnalyzerManager::addAction(action);
|
||||
|
||||
action = new ValgrindAction(this);
|
||||
action->setId("Callgrind.Local");
|
||||
action->setTool(m_callgrindTool);
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Internal {
|
||||
|
||||
class ValgrindGlobalSettings;
|
||||
class MemcheckTool;
|
||||
class MemcheckWithGdbTool;
|
||||
class CallgrindTool;
|
||||
|
||||
class ValgrindPlugin : public ExtensionSystem::IPlugin
|
||||
@@ -58,6 +59,7 @@ public:
|
||||
|
||||
private:
|
||||
MemcheckTool *m_memcheckTool;
|
||||
MemcheckWithGdbTool *m_memcheckWithGdbTool;
|
||||
CallgrindTool *m_callgrindTool;
|
||||
};
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ ValgrindRunControlFactory::ValgrindRunControlFactory(QObject *parent) :
|
||||
bool ValgrindRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const
|
||||
{
|
||||
Q_UNUSED(runConfiguration);
|
||||
return mode == CallgrindRunMode || mode == MemcheckRunMode;
|
||||
return mode == CallgrindRunMode || mode == MemcheckRunMode || mode == MemcheckWithGdbRunMode;
|
||||
}
|
||||
|
||||
RunControl *ValgrindRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage)
|
||||
|
||||
Reference in New Issue
Block a user