Commit b4efd0d8 authored by Orgad Shaneh's avatar Orgad Shaneh Committed by hjk
Browse files

Valgrind: Support vgdb



Change-Id: Id9f653a81d329494017653b8fc7ec9960e20dbcd
Reviewed-by: default avatarhjk <hjk@theqtcompany.com>
parent 4db12d43
...@@ -80,8 +80,8 @@ RunControl *AndroidRunControlFactory::create(RunConfiguration *runConfig, ...@@ -80,8 +80,8 @@ RunControl *AndroidRunControlFactory::create(RunConfiguration *runConfig,
case DebugRunModeWithBreakOnMain: case DebugRunModeWithBreakOnMain:
case CallgrindRunMode: case CallgrindRunMode:
case MemcheckRunMode: case MemcheckRunMode:
case MemcheckWithGdbRunMode:
case ClangStaticAnalyzerMode: case ClangStaticAnalyzerMode:
default:
QTC_CHECK(false); // The other run modes are not supported QTC_CHECK(false); // The other run modes are not supported
} }
return 0; return 0;
......
...@@ -274,6 +274,7 @@ enum RunMode { ...@@ -274,6 +274,7 @@ enum RunMode {
QmlProfilerRunMode, QmlProfilerRunMode,
CallgrindRunMode, CallgrindRunMode,
MemcheckRunMode, MemcheckRunMode,
MemcheckWithGdbRunMode,
ClangStaticAnalyzerMode ClangStaticAnalyzerMode
}; };
......
...@@ -198,6 +198,7 @@ RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, RunMode mo ...@@ -198,6 +198,7 @@ RunControl *QnxRunControlFactory::create(RunConfiguration *runConfig, RunMode mo
case NoRunMode: case NoRunMode:
case CallgrindRunMode: case CallgrindRunMode:
case MemcheckRunMode: case MemcheckRunMode:
case MemcheckWithGdbRunMode:
case ClangStaticAnalyzerMode: case ClangStaticAnalyzerMode:
case DebugRunModeWithBreakOnMain: case DebugRunModeWithBreakOnMain:
QTC_ASSERT(false, return 0); QTC_ASSERT(false, return 0);
......
...@@ -126,6 +126,7 @@ RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Ru ...@@ -126,6 +126,7 @@ RunControl *RemoteLinuxRunControlFactory::create(RunConfiguration *runConfig, Ru
case NoRunMode: case NoRunMode:
case CallgrindRunMode: case CallgrindRunMode:
case MemcheckRunMode: case MemcheckRunMode:
case MemcheckWithGdbRunMode:
case ClangStaticAnalyzerMode: case ClangStaticAnalyzerMode:
QTC_ASSERT(false, return 0); QTC_ASSERT(false, return 0);
} }
......
...@@ -57,7 +57,8 @@ class MemcheckRunner::Private ...@@ -57,7 +57,8 @@ class MemcheckRunner::Private
public: public:
explicit Private() explicit Private()
: parser(0), : parser(0),
logSocket(0) logSocket(0),
disableXml(false)
{ {
} }
...@@ -65,6 +66,7 @@ public: ...@@ -65,6 +66,7 @@ public:
XmlProtocol::ThreadedParser *parser; XmlProtocol::ThreadedParser *parser;
QTcpServer logServer; QTcpServer logServer;
QTcpSocket *logSocket; QTcpSocket *logSocket;
bool disableXml;
}; };
MemcheckRunner::MemcheckRunner(QObject *parent) MemcheckRunner::MemcheckRunner(QObject *parent)
...@@ -106,6 +108,13 @@ bool MemcheckRunner::start() ...@@ -106,6 +108,13 @@ bool MemcheckRunner::start()
return ValgrindRunner::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() void MemcheckRunner::xmlSocketConnected()
{ {
QTcpSocket *socket = d->xmlServer.nextPendingConnection(); QTcpSocket *socket = d->xmlServer.nextPendingConnection();
...@@ -157,13 +166,15 @@ bool MemcheckRunner::startServers(const QHostAddress &localHostAddress) ...@@ -157,13 +166,15 @@ bool MemcheckRunner::startServers(const QHostAddress &localHostAddress)
QStringList MemcheckRunner::memcheckLogArguments() const QStringList MemcheckRunner::memcheckLogArguments() const
{ {
return QStringList() QStringList arguments;
<< QLatin1String("--xml=yes") if (!d->disableXml)
<< QString::fromLatin1("--xml-socket=%1:%2") arguments << QLatin1String("--xml=yes");
.arg(d->xmlServer.serverAddress().toString()).arg(d->xmlServer.serverPort()) arguments << QString::fromLatin1("--xml-socket=%1:%2")
<< QLatin1String("--child-silent-after-fork=yes") .arg(d->xmlServer.serverAddress().toString()).arg(d->xmlServer.serverPort())
<< QString::fromLatin1("--log-socket=%1:%2") << QLatin1String("--child-silent-after-fork=yes")
.arg(d->logServer.serverAddress().toString()).arg(d->logServer.serverPort()); << QString::fromLatin1("--log-socket=%1:%2")
.arg(d->logServer.serverAddress().toString()).arg(d->logServer.serverPort());
return arguments;
} }
void MemcheckRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress) void MemcheckRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress)
......
...@@ -52,6 +52,7 @@ public: ...@@ -52,6 +52,7 @@ public:
void setParser(XmlProtocol::ThreadedParser *parser); void setParser(XmlProtocol::ThreadedParser *parser);
bool start(); bool start();
void disableXml();
signals: signals:
void logMessageReceived(const QByteArray &); void logMessageReceived(const QByteArray &);
......
...@@ -30,14 +30,22 @@ ...@@ -30,14 +30,22 @@
****************************************************************************/ ****************************************************************************/
#include "memcheckengine.h" #include "memcheckengine.h"
#include "valgrindprocess.h"
#include "valgrindsettings.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/projectexplorer.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h> #include <projectexplorer/taskhub.h>
#include <projectexplorer/toolchain.h>
#include <valgrind/xmlprotocol/error.h>
#include <valgrind/xmlprotocol/status.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
...@@ -65,7 +73,7 @@ QString MemcheckRunControl::progressTitle() const ...@@ -65,7 +73,7 @@ QString MemcheckRunControl::progressTitle() const
return tr("Analyzing Memory"); return tr("Analyzing Memory");
} }
Valgrind::ValgrindRunner *MemcheckRunControl::runner() ValgrindRunner *MemcheckRunControl::runner()
{ {
return &m_runner; return &m_runner;
} }
...@@ -129,5 +137,70 @@ QStringList MemcheckRunControl::suppressionFiles() const ...@@ -129,5 +137,70 @@ QStringList MemcheckRunControl::suppressionFiles() const
return m_settings->suppressionFiles(); 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 Internal
} // namespace Valgrind } // namespace Valgrind
...@@ -59,15 +59,29 @@ signals: ...@@ -59,15 +59,29 @@ signals:
void suppressionCount(const QString &name, qint64 count); void suppressionCount(const QString &name, qint64 count);
protected: protected:
virtual QString progressTitle() const; QString progressTitle() const Q_DECL_OVERRIDE;
virtual QStringList toolArguments() const; QStringList toolArguments() const Q_DECL_OVERRIDE;
virtual ValgrindRunner *runner(); ValgrindRunner *runner() Q_DECL_OVERRIDE;
private: protected:
XmlProtocol::ThreadedParser m_parser; XmlProtocol::ThreadedParser m_parser;
Memcheck::MemcheckRunner m_runner; 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 Internal
} // namespace Valgrind } // namespace Valgrind
......
...@@ -438,7 +438,7 @@ AnalyzerRunControl *MemcheckTool::createRunControl(const AnalyzerStartParameters ...@@ -438,7 +438,7 @@ AnalyzerRunControl *MemcheckTool::createRunControl(const AnalyzerStartParameters
m_frameFinder->setFiles(runConfiguration ? runConfiguration->target() m_frameFinder->setFiles(runConfiguration ? runConfiguration->target()
->project()->files(Project::AllFiles) : QStringList()); ->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::starting, this, &MemcheckTool::engineStarting);
connect(engine, &MemcheckRunControl::parserError, this, &MemcheckTool::parserError); connect(engine, &MemcheckRunControl::parserError, this, &MemcheckTool::parserError);
...@@ -571,6 +571,12 @@ int MemcheckTool::updateUiAfterFinishedHelper() ...@@ -571,6 +571,12 @@ int MemcheckTool::updateUiAfterFinishedHelper()
return issuesFound; return issuesFound;
} }
MemcheckRunControl *MemcheckTool::createMemcheckRunControl(const AnalyzerStartParameters &sp,
RunConfiguration *runConfiguration)
{
return new MemcheckRunControl(sp, runConfiguration);
}
void MemcheckTool::engineFinished() void MemcheckTool::engineFinished()
{ {
const int issuesFound = updateUiAfterFinishedHelper(); const int issuesFound = updateUiAfterFinishedHelper();
...@@ -593,5 +599,18 @@ void MemcheckTool::setBusyCursor(bool busy) ...@@ -593,5 +599,18 @@ void MemcheckTool::setBusyCursor(bool busy)
m_errorView->setCursor(cursor); 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 Internal
} // namespace Valgrind } // namespace Valgrind
...@@ -54,6 +54,7 @@ namespace Internal { ...@@ -54,6 +54,7 @@ namespace Internal {
class FrameFinder; class FrameFinder;
class MemcheckErrorView; class MemcheckErrorView;
class MemcheckRunControl;
class ValgrindBaseSettings; class ValgrindBaseSettings;
class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel class MemcheckErrorFilterProxyModel : public QSortFilterProxyModel
...@@ -108,6 +109,11 @@ private: ...@@ -108,6 +109,11 @@ private:
void updateFromSettings(); void updateFromSettings();
int updateUiAfterFinishedHelper(); int updateUiAfterFinishedHelper();
protected:
virtual MemcheckRunControl *createMemcheckRunControl(
const Analyzer::AnalyzerStartParameters &sp,
ProjectExplorer::RunConfiguration *runConfiguration);
private: private:
ValgrindBaseSettings *m_settings; ValgrindBaseSettings *m_settings;
QMenu *m_filterMenu; QMenu *m_filterMenu;
...@@ -126,6 +132,17 @@ private: ...@@ -126,6 +132,17 @@ private:
QAction *m_goNext; 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 Internal
} // namespace Valgrind } // namespace Valgrind
......
...@@ -7,6 +7,7 @@ QTC_LIB_DEPENDS += \ ...@@ -7,6 +7,7 @@ QTC_LIB_DEPENDS += \
QTC_PLUGIN_DEPENDS += \ QTC_PLUGIN_DEPENDS += \
analyzerbase \ analyzerbase \
coreplugin \ coreplugin \
debugger \
projectexplorer \ projectexplorer \
texteditor \ texteditor \
remotelinux remotelinux
...@@ -116,6 +116,7 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *) ...@@ -116,6 +116,7 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
addAutoReleasedObject(new ValgrindOptionsPage()); addAutoReleasedObject(new ValgrindOptionsPage());
m_memcheckTool = new MemcheckTool(this); m_memcheckTool = new MemcheckTool(this);
m_memcheckWithGdbTool = new MemcheckWithGdbTool(this);
m_callgrindTool = new CallgrindTool(this); m_callgrindTool = new CallgrindTool(this);
ValgrindAction *action = 0; ValgrindAction *action = 0;
...@@ -126,6 +127,10 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *) ...@@ -126,6 +127,10 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
QString memcheckToolTip = tr("Valgrind Analyze Memory uses the " QString memcheckToolTip = tr("Valgrind Analyze Memory uses the "
"\"memcheck\" tool to find memory leaks."); "\"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()) { if (!Utils::HostOsInfo::isWindowsHost()) {
action = new ValgrindAction(this); action = new ValgrindAction(this);
action->setId("Memcheck.Local"); action->setId("Memcheck.Local");
...@@ -137,6 +142,16 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *) ...@@ -137,6 +142,16 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
action->setEnabled(false); action->setEnabled(false);
AnalyzerManager::addAction(action); 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 = new ValgrindAction(this);
action->setId("Callgrind.Local"); action->setId("Callgrind.Local");
action->setTool(m_callgrindTool); action->setTool(m_callgrindTool);
......
...@@ -40,6 +40,7 @@ namespace Internal { ...@@ -40,6 +40,7 @@ namespace Internal {
class ValgrindGlobalSettings; class ValgrindGlobalSettings;
class MemcheckTool; class MemcheckTool;
class MemcheckWithGdbTool;
class CallgrindTool; class CallgrindTool;
class ValgrindPlugin : public ExtensionSystem::IPlugin class ValgrindPlugin : public ExtensionSystem::IPlugin
...@@ -58,6 +59,7 @@ public: ...@@ -58,6 +59,7 @@ public:
private: private:
MemcheckTool *m_memcheckTool; MemcheckTool *m_memcheckTool;
MemcheckWithGdbTool *m_memcheckWithGdbTool;
CallgrindTool *m_callgrindTool; CallgrindTool *m_callgrindTool;
}; };
......
...@@ -65,7 +65,7 @@ ValgrindRunControlFactory::ValgrindRunControlFactory(QObject *parent) : ...@@ -65,7 +65,7 @@ ValgrindRunControlFactory::ValgrindRunControlFactory(QObject *parent) :
bool ValgrindRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const bool ValgrindRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const
{ {
Q_UNUSED(runConfiguration); Q_UNUSED(runConfiguration);
return mode == CallgrindRunMode || mode == MemcheckRunMode; return mode == CallgrindRunMode || mode == MemcheckRunMode || mode == MemcheckWithGdbRunMode;
} }
RunControl *ValgrindRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage) RunControl *ValgrindRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage)
......
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