forked from qt-creator/qt-creator
Debugger: Use LD_PRELOAD to load debugging helper.
on UNIX. Either set the LD_PRELOAD environment variable using a gdb command or have the TermGdbAdapter set the variable for the debuggee. For the remote adapter, switch on toolchain. dlopen() is a fallback for platforms where it is not supported and attaching to running processes. Fixes a crash with gdb 7.0 (and spurious gdb 6.8 crashes with dlopen()). Reviewed-by: hjk <qtc-committer@nokia.com>
This commit is contained in:
@@ -48,6 +48,11 @@ class AbstractGdbAdapter : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum DumperHandling { DumperNotAvailable,
|
||||||
|
DumperLoadedByAdapter,
|
||||||
|
DumperLoadedByGdbPreload,
|
||||||
|
DumperLoadedByGdb };
|
||||||
|
|
||||||
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||||
virtual ~AbstractGdbAdapter();
|
virtual ~AbstractGdbAdapter();
|
||||||
|
|
||||||
@@ -61,7 +66,7 @@ public:
|
|||||||
virtual void shutdown();
|
virtual void shutdown();
|
||||||
virtual const char *inferiorShutdownCommand() const;
|
virtual const char *inferiorShutdownCommand() const;
|
||||||
|
|
||||||
virtual bool dumpersAvailable() const = 0;
|
virtual DumperHandling dumperHandling() const = 0;
|
||||||
|
|
||||||
static QString msgGdbStopFailed(const QString &why);
|
static QString msgGdbStopFailed(const QString &why);
|
||||||
static QString msgInferiorStopFailed(const QString &why);
|
static QString msgInferiorStopFailed(const QString &why);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class AttachGdbAdapter : public AbstractGdbAdapter
|
|||||||
public:
|
public:
|
||||||
AttachGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
AttachGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||||
|
|
||||||
bool dumpersAvailable() const { return true; }
|
virtual DumperHandling dumperHandling() const { return DumperLoadedByGdb; }
|
||||||
|
|
||||||
void startAdapter();
|
void startAdapter();
|
||||||
void startInferior();
|
void startInferior();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class CoreGdbAdapter : public AbstractGdbAdapter
|
|||||||
public:
|
public:
|
||||||
CoreGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
CoreGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||||
|
|
||||||
bool dumpersAvailable() const { return false; }
|
virtual DumperHandling dumperHandling() const { return DumperNotAvailable; }
|
||||||
|
|
||||||
void startAdapter();
|
void startAdapter();
|
||||||
void startInferior();
|
void startInferior();
|
||||||
|
|||||||
@@ -1197,7 +1197,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool initHelpers = (m_debuggingHelperState == DebuggingHelperUninitialized);
|
bool initHelpers = m_debuggingHelperState == DebuggingHelperUninitialized
|
||||||
|
|| m_debuggingHelperState == DebuggingHelperLoadTried;
|
||||||
// Don't load helpers on stops triggered by signals unless it's
|
// Don't load helpers on stops triggered by signals unless it's
|
||||||
// an intentional trap.
|
// an intentional trap.
|
||||||
if (initHelpers && reason == "signal-received"
|
if (initHelpers && reason == "signal-received"
|
||||||
@@ -1529,7 +1530,7 @@ AbstractGdbAdapter *GdbEngine::createAdapter(const DebuggerStartParametersPtr &s
|
|||||||
case AttachCore:
|
case AttachCore:
|
||||||
return new CoreGdbAdapter(this);
|
return new CoreGdbAdapter(this);
|
||||||
case StartRemote:
|
case StartRemote:
|
||||||
return new RemoteGdbAdapter(this);
|
return new RemoteGdbAdapter(this, sp->toolChainType);
|
||||||
case AttachExternal:
|
case AttachExternal:
|
||||||
return new AttachGdbAdapter(this);
|
return new AttachGdbAdapter(this);
|
||||||
default:
|
default:
|
||||||
@@ -1556,7 +1557,7 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
|||||||
m_gdbAdapter = createAdapter(sp);
|
m_gdbAdapter = createAdapter(sp);
|
||||||
connectAdapter();
|
connectAdapter();
|
||||||
|
|
||||||
if (startModeAllowsDumpers())
|
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable)
|
||||||
connectDebuggingHelperActions();
|
connectDebuggingHelperActions();
|
||||||
|
|
||||||
m_gdbAdapter->startAdapter();
|
m_gdbAdapter->startAdapter();
|
||||||
@@ -2769,7 +2770,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QString &type) const
|
|||||||
if (!theDebuggerBoolSetting(UseDebuggingHelpers))
|
if (!theDebuggerBoolSetting(UseDebuggingHelpers))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!startModeAllowsDumpers()) {
|
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
||||||
// "call" is not possible in gdb when looking at core files
|
// "call" is not possible in gdb when looking at core files
|
||||||
return type == __("QString") || type.endsWith(__("::QString"))
|
return type == __("QString") || type.endsWith(__("::QString"))
|
||||||
|| type == __("QStringList") || type.endsWith(__("::QStringList"));
|
|| type == __("QStringList") || type.endsWith(__("::QStringList"));
|
||||||
@@ -2811,7 +2812,7 @@ void GdbEngine::runDirectDebuggingHelper(const WatchData &data, bool dumpChildre
|
|||||||
|
|
||||||
void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
|
void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
|
||||||
{
|
{
|
||||||
if (!startModeAllowsDumpers()) {
|
if (m_debuggingHelperState != DebuggingHelperAvailable) {
|
||||||
runDirectDebuggingHelper(data0, dumpChildren);
|
runDirectDebuggingHelper(data0, dumpChildren);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3847,14 +3848,50 @@ void GdbEngine::assignValueInDebugger(const QString &expression, const QString &
|
|||||||
postCommand(_("-var-assign assign ") + value, Discardable, CB(handleVarAssign));
|
postCommand(_("-var-assign assign ") + value, Discardable, CB(handleVarAssign));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GdbEngine::qtDumperLibraryName() const
|
||||||
|
{
|
||||||
|
return m_manager->qtDumperLibraryName();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GdbEngine::checkDebuggingHelpers()
|
||||||
|
{
|
||||||
|
if (!manager()->qtDumperLibraryEnabled())
|
||||||
|
return false;
|
||||||
|
const QString lib = qtDumperLibraryName();
|
||||||
|
//qDebug() << "DUMPERLIB:" << lib;
|
||||||
|
const QFileInfo fi(lib);
|
||||||
|
if (!fi.exists()) {
|
||||||
|
const QStringList &locations = manager()->qtDumperLibraryLocations();
|
||||||
|
const QString loc = locations.join(QLatin1String(", "));
|
||||||
|
const QString msg = tr("The debugging helper library was not found at %1.").arg(loc);
|
||||||
|
debugMessage(msg);
|
||||||
|
manager()->showQtDumperLibraryWarning(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::setDebuggingHelperState(DebuggingHelperState s)
|
||||||
|
{
|
||||||
|
m_debuggingHelperState = s;
|
||||||
|
}
|
||||||
|
|
||||||
void GdbEngine::tryLoadDebuggingHelpers()
|
void GdbEngine::tryLoadDebuggingHelpers()
|
||||||
{
|
{
|
||||||
if (isSynchroneous())
|
if (isSynchroneous())
|
||||||
return;
|
return;
|
||||||
|
switch (m_debuggingHelperState) {
|
||||||
if (m_debuggingHelperState != DebuggingHelperUninitialized)
|
case DebuggingHelperUninitialized:
|
||||||
|
break;
|
||||||
|
case DebuggingHelperLoadTried:
|
||||||
|
tryQueryDebuggingHelpers();
|
||||||
return;
|
return;
|
||||||
if (!startModeAllowsDumpers()) {
|
case DebuggingHelperAvailable:
|
||||||
|
case DebuggingHelperUnavailable:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
||||||
// Load at least gdb macro based dumpers.
|
// Load at least gdb macro based dumpers.
|
||||||
QFile file(_(":/gdb/gdbmacros.txt"));
|
QFile file(_(":/gdb/gdbmacros.txt"));
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
@@ -3868,22 +3905,11 @@ void GdbEngine::tryLoadDebuggingHelpers()
|
|||||||
|
|
||||||
PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS");
|
PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS");
|
||||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
m_debuggingHelperState = DebuggingHelperUnavailable;
|
||||||
if (!manager()->qtDumperLibraryEnabled())
|
if (!checkDebuggingHelpers())
|
||||||
return;
|
return;
|
||||||
const QString lib = manager()->qtDumperLibraryName();
|
|
||||||
const QStringList &locations = manager()->qtDumperLibraryLocations();
|
|
||||||
//qDebug() << "DUMPERLIB:" << lib;
|
|
||||||
// @TODO: same in CDB engine...
|
|
||||||
const QFileInfo fi(lib);
|
|
||||||
if (!fi.exists()) {
|
|
||||||
const QString loc = locations.join(QLatin1String(", "));
|
|
||||||
const QString msg = tr("The debugging helper library was not found at %1.").arg(loc);
|
|
||||||
debugMessage(msg);
|
|
||||||
manager()->showQtDumperLibraryWarning(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_debuggingHelperState = DebuggingHelperLoadTried;
|
m_debuggingHelperState = DebuggingHelperLoadTried;
|
||||||
|
const QString lib = manager()->qtDumperLibraryName();
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
if (m_dumperInjectionLoad) {
|
if (m_dumperInjectionLoad) {
|
||||||
/// Launch asynchronous remote thread to load.
|
/// Launch asynchronous remote thread to load.
|
||||||
@@ -3929,29 +3955,20 @@ void GdbEngine::tryLoadDebuggingHelpers()
|
|||||||
|
|
||||||
void GdbEngine::tryQueryDebuggingHelpers()
|
void GdbEngine::tryQueryDebuggingHelpers()
|
||||||
{
|
{
|
||||||
#if !X
|
|
||||||
// retrieve list of dumpable classes
|
// retrieve list of dumpable classes
|
||||||
postCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"), EmbedToken);
|
postCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"), EmbedToken);
|
||||||
postCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
postCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
||||||
#else
|
|
||||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::recheckDebuggingHelperAvailability()
|
void GdbEngine::recheckDebuggingHelperAvailability()
|
||||||
{
|
{
|
||||||
if (startModeAllowsDumpers()) {
|
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
|
||||||
// retreive list of dumpable classes
|
// retreive list of dumpable classes
|
||||||
postCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"), EmbedToken);
|
postCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"), EmbedToken);
|
||||||
postCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
postCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GdbEngine::startModeAllowsDumpers() const
|
|
||||||
{
|
|
||||||
return m_gdbAdapter->dumpersAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::watchPoint(const QPoint &pnt)
|
void GdbEngine::watchPoint(const QPoint &pnt)
|
||||||
{
|
{
|
||||||
//qDebug() << "WATCH " << pnt;
|
//qDebug() << "WATCH " << pnt;
|
||||||
@@ -4309,7 +4326,12 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
|
|||||||
).arg(scriptFileName));
|
).arg(scriptFileName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperLoadedByGdbPreload
|
||||||
|
&& checkDebuggingHelpers()) {
|
||||||
|
const QString cmd = QLatin1String("set environment LD_PRELOAD ") + manager()->qtDumperLibraryName();
|
||||||
|
postCommand(cmd);
|
||||||
|
m_debuggingHelperState = DebuggingHelperLoadTried;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -449,8 +449,9 @@ private: ////////// View & Data Stuff //////////
|
|||||||
QMap<QString, QString> m_varToType;
|
QMap<QString, QString> m_varToType;
|
||||||
|
|
||||||
private: ////////// Dumper Management //////////
|
private: ////////// Dumper Management //////////
|
||||||
|
QString qtDumperLibraryName() const;
|
||||||
bool startModeAllowsDumpers() const;
|
bool checkDebuggingHelpers();
|
||||||
|
void setDebuggingHelperState(DebuggingHelperState);
|
||||||
void tryLoadDebuggingHelpers();
|
void tryLoadDebuggingHelpers();
|
||||||
void tryQueryDebuggingHelpers();
|
void tryQueryDebuggingHelpers();
|
||||||
Q_SLOT void recheckDebuggingHelperAvailability();
|
Q_SLOT void recheckDebuggingHelperAvailability();
|
||||||
|
|||||||
@@ -58,6 +58,15 @@ PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
|
|||||||
engine, SLOT(readDebugeeOutput(QByteArray)));
|
engine, SLOT(readDebugeeOutput(QByteArray)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractGdbAdapter::DumperHandling PlainGdbAdapter::dumperHandling() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
return DumperLoadedByGdb;
|
||||||
|
#else
|
||||||
|
return DumperLoadedByGdbPreload;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void PlainGdbAdapter::startAdapter()
|
void PlainGdbAdapter::startAdapter()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class PlainGdbAdapter : public AbstractGdbAdapter
|
|||||||
public:
|
public:
|
||||||
PlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
PlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||||
|
|
||||||
bool dumpersAvailable() const { return true; }
|
virtual DumperHandling dumperHandling() const;
|
||||||
|
|
||||||
void startAdapter();
|
void startAdapter();
|
||||||
void startInferior();
|
void startInferior();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/fancymainwindow.h>
|
#include <utils/fancymainwindow.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
#include <QtGui/QMessageBox>
|
#include <QtGui/QMessageBox>
|
||||||
@@ -51,8 +52,9 @@ namespace Internal {
|
|||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
|
RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, int toolChainType, QObject *parent) :
|
||||||
: AbstractGdbAdapter(engine, parent)
|
AbstractGdbAdapter(engine, parent),
|
||||||
|
m_toolChainType(toolChainType)
|
||||||
{
|
{
|
||||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||||
this, SLOT(uploadProcError(QProcess::ProcessError)));
|
this, SLOT(uploadProcError(QProcess::ProcessError)));
|
||||||
@@ -62,6 +64,23 @@ RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
|
|||||||
this, SLOT(readUploadStandardError()));
|
this, SLOT(readUploadStandardError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractGdbAdapter::DumperHandling RemoteGdbAdapter::dumperHandling() const
|
||||||
|
{
|
||||||
|
switch (m_toolChainType) {
|
||||||
|
case ProjectExplorer::ToolChain::MinGW:
|
||||||
|
case ProjectExplorer::ToolChain::MSVC:
|
||||||
|
case ProjectExplorer::ToolChain::WINCE:
|
||||||
|
case ProjectExplorer::ToolChain::WINSCW:
|
||||||
|
case ProjectExplorer::ToolChain::GCCE:
|
||||||
|
case ProjectExplorer::ToolChain::RVCT_ARMV5:
|
||||||
|
case ProjectExplorer::ToolChain::RVCT_ARMV6:
|
||||||
|
return DumperLoadedByGdb;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return DumperLoadedByGdbPreload;
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteGdbAdapter::startAdapter()
|
void RemoteGdbAdapter::startAdapter()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ class RemoteGdbAdapter : public AbstractGdbAdapter
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoteGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
RemoteGdbAdapter(GdbEngine *engine, int toolChainType, QObject *parent = 0);
|
||||||
|
|
||||||
bool dumpersAvailable() const { return true; }
|
virtual DumperHandling dumperHandling() const;
|
||||||
|
|
||||||
void startAdapter();
|
void startAdapter();
|
||||||
void startInferior();
|
void startInferior();
|
||||||
@@ -67,6 +67,8 @@ private:
|
|||||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||||
void handleTargetRemote(const GdbResponse &response);
|
void handleTargetRemote(const GdbResponse &response);
|
||||||
|
|
||||||
|
const int m_toolChainType;
|
||||||
|
|
||||||
QProcess m_uploadProc;
|
QProcess m_uploadProc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,15 @@ TermGdbAdapter::~TermGdbAdapter()
|
|||||||
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
|
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractGdbAdapter::DumperHandling TermGdbAdapter::dumperHandling() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
return DumperLoadedByGdb;
|
||||||
|
#else
|
||||||
|
return DumperLoadedByAdapter; // Handles loading itself via LD_PRELOAD
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void TermGdbAdapter::startAdapter()
|
void TermGdbAdapter::startAdapter()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
||||||
@@ -82,7 +91,14 @@ void TermGdbAdapter::startAdapter()
|
|||||||
// m_stubProc.blockSignals(false);
|
// m_stubProc.blockSignals(false);
|
||||||
|
|
||||||
m_stubProc.setWorkingDirectory(startParameters().workingDir);
|
m_stubProc.setWorkingDirectory(startParameters().workingDir);
|
||||||
m_stubProc.setEnvironment(startParameters().environment);
|
// Set environment + dumper preload.
|
||||||
|
QStringList environment = startParameters().environment;
|
||||||
|
if (dumperHandling() == DumperLoadedByGdbPreload
|
||||||
|
&& m_engine->checkDebuggingHelpers()) {
|
||||||
|
environment.push_back(QLatin1String("LD_PRELOAD=") + m_engine->qtDumperLibraryName());
|
||||||
|
m_engine->setDebuggingHelperState(DebuggingHelperLoadTried);
|
||||||
|
}
|
||||||
|
m_stubProc.setEnvironment(environment);
|
||||||
// FIXME: Starting the stub implies starting the inferior. This is
|
// FIXME: Starting the stub implies starting the inferior. This is
|
||||||
// fairly unclean as far as the state machine and error reporting go.
|
// fairly unclean as far as the state machine and error reporting go.
|
||||||
if (!m_stubProc.start(startParameters().executable,
|
if (!m_stubProc.start(startParameters().executable,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
TermGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
TermGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||||
~TermGdbAdapter();
|
~TermGdbAdapter();
|
||||||
|
|
||||||
bool dumpersAvailable() const { return true; }
|
virtual DumperHandling dumperHandling() const;
|
||||||
|
|
||||||
void startAdapter();
|
void startAdapter();
|
||||||
void startInferior();
|
void startInferior();
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ public:
|
|||||||
QIODevice::OpenMode mode = QIODevice::ReadWrite);
|
QIODevice::OpenMode mode = QIODevice::ReadWrite);
|
||||||
void write(const QByteArray &data);
|
void write(const QByteArray &data);
|
||||||
bool isTrkAdapter() const { return true; }
|
bool isTrkAdapter() const { return true; }
|
||||||
bool dumpersAvailable() const { return false; }
|
|
||||||
|
virtual DumperHandling dumperHandling() const { return DumperNotAvailable; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startAdapter();
|
void startAdapter();
|
||||||
|
|||||||
Reference in New Issue
Block a user