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,
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)
......
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