2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
|
|
|
|
** Contact: http://www.qt-project.org/legal
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 15:08:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "breakhandler.h"
|
2011-04-21 15:52:51 +02:00
|
|
|
#include "debuggerinternalconstants.h"
|
2010-10-25 14:00:19 +02:00
|
|
|
#include "breakpointmarker.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-09-23 16:11:25 +02:00
|
|
|
#include "debuggeractions.h"
|
2010-11-10 11:39:01 +01:00
|
|
|
#include "debuggercore.h"
|
2010-11-15 14:27:06 +01:00
|
|
|
#include "debuggerengine.h"
|
2010-05-07 15:16:31 +02:00
|
|
|
#include "debuggerstringutils.h"
|
2010-11-24 11:44:43 +01:00
|
|
|
#include "stackframe.h"
|
2009-08-14 13:04:05 +02:00
|
|
|
|
2012-10-09 22:34:36 +02:00
|
|
|
#include <extensionsystem/invoker.h>
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2010-03-26 08:52:49 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
#if USE_BREAK_MODEL_TEST
|
|
|
|
|
#include "modeltest.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QTimerEvent>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-04-14 16:10:18 +02:00
|
|
|
#define BREAK_ASSERT(cond, action) if (cond) {} else { action; }
|
|
|
|
|
//#define BREAK_ASSERT(cond, action) QTC_ASSERT(cond, action)
|
2010-11-05 13:35:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// BreakHandler
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2011-02-17 13:49:47 +01:00
|
|
|
static QString stateToString(BreakpointState state)
|
|
|
|
|
{
|
|
|
|
|
switch (state) {
|
|
|
|
|
case BreakpointNew:
|
|
|
|
|
return BreakHandler::tr("New");
|
|
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
return BreakHandler::tr("Insertion requested");
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
return BreakHandler::tr("Insertion proceeding");
|
|
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
return BreakHandler::tr("Change requested");
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
return BreakHandler::tr("Change proceeding");
|
|
|
|
|
case BreakpointInserted:
|
|
|
|
|
return BreakHandler::tr("Breakpoint inserted");
|
|
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
return BreakHandler::tr("Removal requested");
|
|
|
|
|
case BreakpointRemoveProceeding:
|
|
|
|
|
return BreakHandler::tr("Removal proceeding");
|
|
|
|
|
case BreakpointDead:
|
|
|
|
|
return BreakHandler::tr("Dead");
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
//: Invalid breakpoint state.
|
|
|
|
|
return BreakHandler::tr("<invalid state>");
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 17:20:10 +01:00
|
|
|
static QString msgBreakpointAtSpecialFunc(const char *func)
|
|
|
|
|
{
|
2012-02-16 09:55:47 +02:00
|
|
|
return BreakHandler::tr("Breakpoint at \"%1\"").arg(QString::fromLatin1(func));
|
2011-03-07 17:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
2011-03-04 19:38:58 +01:00
|
|
|
static QString typeToString(BreakpointType type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case BreakpointByFileAndLine:
|
|
|
|
|
return BreakHandler::tr("Breakpoint by File and Line");
|
|
|
|
|
case BreakpointByFunction:
|
|
|
|
|
return BreakHandler::tr("Breakpoint by Function");
|
|
|
|
|
case BreakpointByAddress:
|
|
|
|
|
return BreakHandler::tr("Breakpoint by Address");
|
|
|
|
|
case BreakpointAtThrow:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("throw");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtCatch:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("catch");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtFork:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("fork");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtExec:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("exec");
|
2011-03-29 09:58:21 +02:00
|
|
|
//case BreakpointAtVFork:
|
|
|
|
|
// return msgBreakpointAtSpecialFunc("vfork");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtSysCall:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("syscall");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtMain:
|
|
|
|
|
return BreakHandler::tr("Breakpoint at Function \"main()\"");
|
2011-05-09 08:35:58 +02:00
|
|
|
case WatchpointAtAddress:
|
|
|
|
|
return BreakHandler::tr("Watchpoint at Address");
|
|
|
|
|
case WatchpointAtExpression:
|
|
|
|
|
return BreakHandler::tr("Watchpoint at Expression");
|
2012-04-16 12:00:23 +02:00
|
|
|
case BreakpointOnQmlSignalEmit:
|
|
|
|
|
return BreakHandler::tr("Breakpoint on QML Signal Emit");
|
2011-10-10 15:25:18 +02:00
|
|
|
case BreakpointAtJavaScriptThrow:
|
|
|
|
|
return BreakHandler::tr("Breakpoint at JavaScript throw");
|
2011-03-04 19:38:58 +01:00
|
|
|
case UnknownType:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return BreakHandler::tr("Unknown Breakpoint Type");
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-04 09:54:23 +01:00
|
|
|
BreakHandler::BreakHandler()
|
2010-11-18 14:57:00 +01:00
|
|
|
: m_syncTimerId(-1)
|
2011-06-15 14:02:26 +02:00
|
|
|
{
|
|
|
|
|
#if USE_BREAK_MODEL_TEST
|
|
|
|
|
new ModelTest(this, 0);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2008-12-04 11:37:43 +01:00
|
|
|
BreakHandler::~BreakHandler()
|
2010-11-10 16:33:11 +01:00
|
|
|
{}
|
2008-12-04 11:37:43 +01:00
|
|
|
|
2010-11-18 14:57:00 +01:00
|
|
|
QIcon BreakHandler::breakpointIcon()
|
|
|
|
|
{
|
|
|
|
|
static QIcon icon(_(":/debugger/images/breakpoint_16.png"));
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QIcon BreakHandler::disabledBreakpointIcon()
|
|
|
|
|
{
|
|
|
|
|
static QIcon icon(_(":/debugger/images/breakpoint_disabled_16.png"));
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-26 12:30:05 +01:00
|
|
|
QIcon BreakHandler::pendingBreakpointIcon()
|
2010-11-18 14:57:00 +01:00
|
|
|
{
|
|
|
|
|
static QIcon icon(_(":/debugger/images/breakpoint_pending_16.png"));
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-26 12:30:05 +01:00
|
|
|
QIcon BreakHandler::watchpointIcon()
|
|
|
|
|
{
|
|
|
|
|
static QIcon icon(_(":/debugger/images/watchpoint.png"));
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-16 13:02:59 +01:00
|
|
|
QIcon BreakHandler::tracepointIcon()
|
|
|
|
|
{
|
|
|
|
|
static QIcon icon(_(":/debugger/images/tracepoint.png"));
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-18 14:57:00 +01:00
|
|
|
QIcon BreakHandler::emptyIcon()
|
|
|
|
|
{
|
|
|
|
|
static QIcon icon(_(":/debugger/images/breakpoint_pending_16.png"));
|
|
|
|
|
//static QIcon icon(_(":/debugger/images/watchpoint.png"));
|
|
|
|
|
//static QIcon icon(_(":/debugger/images/debugger_empty_14.png"));
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
static inline bool fileNameMatch(const QString &f1, const QString &f2)
|
2010-03-26 08:52:49 +01:00
|
|
|
{
|
2012-08-23 15:53:58 +02:00
|
|
|
if (Utils::HostOsInfo::isWindowsHost())
|
|
|
|
|
return f1.compare(f2, Qt::CaseInsensitive) == 0;
|
2010-11-10 16:33:11 +01:00
|
|
|
return f1 == f2;
|
2010-03-26 08:52:49 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-16 11:48:17 +01:00
|
|
|
static bool isSimilarTo(const BreakpointParameters &data, const BreakpointResponse &needle)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-11-10 16:33:11 +01:00
|
|
|
// Clear hit.
|
|
|
|
|
// Clear miss.
|
2010-11-16 11:48:17 +01:00
|
|
|
if (needle.type != UnknownType && data.type != UnknownType
|
|
|
|
|
&& data.type != needle.type)
|
2010-11-10 16:33:11 +01:00
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
// Clear hit.
|
2010-11-16 11:48:17 +01:00
|
|
|
if (data.address && data.address == needle.address)
|
2010-11-10 16:33:11 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// At least at a position we were looking for.
|
|
|
|
|
// FIXME: breaks multiple breakpoints at the same location
|
2010-11-16 11:48:17 +01:00
|
|
|
if (!data.fileName.isEmpty()
|
|
|
|
|
&& fileNameMatch(data.fileName, needle.fileName)
|
|
|
|
|
&& data.lineNumber == needle.lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// At least at a position we were looking for.
|
|
|
|
|
// FIXME: breaks multiple breakpoints at the same location
|
2010-11-16 11:48:17 +01:00
|
|
|
if (!data.fileName.isEmpty()
|
|
|
|
|
&& fileNameMatch(data.fileName, needle.fileName)
|
|
|
|
|
&& data.lineNumber == needle.lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-02-11 17:29:10 +01:00
|
|
|
// Search a breakpoint we might refer to.
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it) {
|
2011-06-24 16:25:30 +02:00
|
|
|
const BreakpointModelId id = it.key();
|
2010-11-16 11:48:17 +01:00
|
|
|
const BreakpointParameters &data = it->data;
|
2010-11-15 14:12:05 +01:00
|
|
|
const BreakpointResponse &response = it->response;
|
2010-11-24 11:44:43 +01:00
|
|
|
//qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
|
2011-06-21 16:45:23 +02:00
|
|
|
if (response.id.isValid() && response.id.majorPart() == needle.id.majorPart())
|
2010-11-10 16:33:11 +01:00
|
|
|
return id;
|
|
|
|
|
|
|
|
|
|
if (isSimilarTo(data, needle))
|
|
|
|
|
return id;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findBreakpointByResponseId(const BreakpointResponseId &id) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2011-06-24 16:25:30 +02:00
|
|
|
if (it->response.id.majorPart() == id.majorPart())
|
2010-11-10 16:33:11 +01:00
|
|
|
return it.key();
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findBreakpointByFunction(const QString &functionName) const
|
2010-05-19 17:34:47 +02:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2010-11-16 11:48:17 +01:00
|
|
|
if (it->data.functionName == functionName)
|
2010-11-10 16:33:11 +01:00
|
|
|
return it.key();
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findBreakpointByAddress(quint64 address) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2011-02-02 17:28:24 +01:00
|
|
|
if (it->data.address == address || it->response.address == address)
|
2010-11-10 16:33:11 +01:00
|
|
|
return it.key();
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findBreakpointByFileAndLine(const QString &fileName,
|
2010-11-10 16:33:11 +01:00
|
|
|
int lineNumber, bool useMarkerPosition)
|
|
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2010-11-15 19:05:31 +01:00
|
|
|
if (it->isLocatedAt(fileName, lineNumber, useMarkerPosition))
|
2010-11-10 16:33:11 +01:00
|
|
|
return it.key();
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
const BreakpointParameters &BreakHandler::breakpointData(BreakpointModelId id) const
|
2010-11-15 15:24:27 +01:00
|
|
|
{
|
2010-11-16 11:06:09 +01:00
|
|
|
static BreakpointParameters dummy;
|
2010-11-15 15:24:27 +01:00
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return dummy);
|
2010-11-16 11:48:17 +01:00
|
|
|
return it->data;
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findWatchpoint(const BreakpointParameters &data) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2011-03-01 19:16:24 +01:00
|
|
|
if (it->data.isWatchpoint()
|
|
|
|
|
&& it->data.address == data.address
|
|
|
|
|
&& it->data.size == data.size
|
2011-05-10 15:57:33 +02:00
|
|
|
&& it->data.expression == data.expression
|
2011-03-01 19:16:24 +01:00
|
|
|
&& it->data.bitpos == data.bitpos)
|
2010-11-10 16:33:11 +01:00
|
|
|
return it.key();
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void BreakHandler::saveBreakpoints()
|
|
|
|
|
{
|
2011-02-02 14:41:14 +01:00
|
|
|
const QString one = _("1");
|
2010-06-16 11:08:54 +02:00
|
|
|
//qDebug() << "SAVING BREAKPOINTS...";
|
2010-11-10 11:39:01 +01:00
|
|
|
QTC_ASSERT(debuggerCore(), return);
|
2008-12-02 12:01:29 +01:00
|
|
|
QList<QVariant> list;
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it) {
|
2010-11-16 11:48:17 +01:00
|
|
|
const BreakpointParameters &data = it->data;
|
2008-12-02 12:01:29 +01:00
|
|
|
QMap<QString, QVariant> map;
|
2010-11-16 11:48:17 +01:00
|
|
|
if (data.type != BreakpointByFileAndLine)
|
|
|
|
|
map.insert(_("type"), data.type);
|
|
|
|
|
if (!data.fileName.isEmpty())
|
|
|
|
|
map.insert(_("filename"), data.fileName);
|
|
|
|
|
if (data.lineNumber)
|
|
|
|
|
map.insert(_("linenumber"), data.lineNumber);
|
|
|
|
|
if (!data.functionName.isEmpty())
|
|
|
|
|
map.insert(_("funcname"), data.functionName);
|
|
|
|
|
if (data.address)
|
|
|
|
|
map.insert(_("address"), data.address);
|
|
|
|
|
if (!data.condition.isEmpty())
|
|
|
|
|
map.insert(_("condition"), data.condition);
|
|
|
|
|
if (data.ignoreCount)
|
|
|
|
|
map.insert(_("ignorecount"), data.ignoreCount);
|
2011-01-05 19:10:33 +01:00
|
|
|
if (data.threadSpec >= 0)
|
2010-11-16 11:48:17 +01:00
|
|
|
map.insert(_("threadspec"), data.threadSpec);
|
|
|
|
|
if (!data.enabled)
|
2011-02-02 14:41:14 +01:00
|
|
|
map.insert(_("disabled"), one);
|
2012-08-21 14:16:07 +02:00
|
|
|
if (data.oneShot)
|
|
|
|
|
map.insert(_("oneshot"), one);
|
2011-02-17 13:00:11 +01:00
|
|
|
if (data.pathUsage != BreakpointPathUsageEngineDefault)
|
|
|
|
|
map.insert(_("usefullpath"), QString::number(data.pathUsage));
|
2010-12-16 17:58:43 +01:00
|
|
|
if (data.tracepoint)
|
2011-02-02 14:41:14 +01:00
|
|
|
map.insert(_("tracepoint"), one);
|
|
|
|
|
if (!data.module.isEmpty())
|
|
|
|
|
map.insert(_("module"), data.module);
|
2011-02-04 11:33:45 +01:00
|
|
|
if (!data.command.isEmpty())
|
|
|
|
|
map.insert(_("command"), data.command);
|
2011-05-11 15:24:50 +02:00
|
|
|
if (!data.expression.isEmpty())
|
|
|
|
|
map.insert(_("expression"), data.expression);
|
2011-06-27 10:37:57 +02:00
|
|
|
if (!data.message.isEmpty())
|
|
|
|
|
map.insert(_("message"), data.message);
|
2008-12-02 12:01:29 +01:00
|
|
|
list.append(map);
|
|
|
|
|
}
|
2011-12-21 14:02:52 +01:00
|
|
|
debuggerCore()->setSessionValue(QLatin1String("Breakpoints"), list);
|
2010-06-16 11:08:54 +02:00
|
|
|
//qDebug() << "SAVED BREAKPOINTS" << this << list.size();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::loadBreakpoints()
|
|
|
|
|
{
|
2010-11-10 11:39:01 +01:00
|
|
|
QTC_ASSERT(debuggerCore(), return);
|
2010-06-16 11:08:54 +02:00
|
|
|
//qDebug() << "LOADING BREAKPOINTS...";
|
2011-12-21 14:02:52 +01:00
|
|
|
QVariant value = debuggerCore()->sessionValue(QLatin1String("Breakpoints"));
|
2008-12-02 12:01:29 +01:00
|
|
|
QList<QVariant> list = value.toList();
|
2010-11-10 16:33:11 +01:00
|
|
|
//clear();
|
2008-12-02 12:01:29 +01:00
|
|
|
foreach (const QVariant &var, list) {
|
|
|
|
|
const QMap<QString, QVariant> map = var.toMap();
|
2010-11-16 10:50:11 +01:00
|
|
|
BreakpointParameters data(BreakpointByFileAndLine);
|
2010-05-07 15:16:31 +02:00
|
|
|
QVariant v = map.value(_("filename"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.fileName = v.toString();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("linenumber"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.lineNumber = v.toString().toInt();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("condition"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.condition = v.toString().toLatin1();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("address"));
|
|
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.address = v.toString().toULongLong();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("ignorecount"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.ignoreCount = v.toString().toInt();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("threadspec"));
|
2010-04-29 18:36:18 +02:00
|
|
|
if (v.isValid())
|
2010-11-30 13:39:01 +01:00
|
|
|
data.threadSpec = v.toString().toInt();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("funcname"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.functionName = v.toString();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("disabled"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2010-11-16 10:50:11 +01:00
|
|
|
data.enabled = !v.toInt();
|
2012-08-21 14:16:07 +02:00
|
|
|
v = map.value(_("oneshot"));
|
|
|
|
|
if (v.isValid())
|
|
|
|
|
data.oneShot = v.toInt();
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("usefullpath"));
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2011-02-17 13:00:11 +01:00
|
|
|
data.pathUsage = static_cast<BreakpointPathUsage>(v.toInt());
|
2010-12-16 17:58:43 +01:00
|
|
|
v = map.value(_("tracepoint"));
|
|
|
|
|
if (v.isValid())
|
|
|
|
|
data.tracepoint = bool(v.toInt());
|
2010-05-07 15:16:31 +02:00
|
|
|
v = map.value(_("type"));
|
2010-11-15 17:25:42 +01:00
|
|
|
if (v.isValid() && v.toInt() != UnknownType)
|
2010-11-16 10:50:11 +01:00
|
|
|
data.type = BreakpointType(v.toInt());
|
2011-02-02 14:41:14 +01:00
|
|
|
v = map.value(_("module"));
|
|
|
|
|
if (v.isValid())
|
|
|
|
|
data.module = v.toString();
|
2011-02-04 11:33:45 +01:00
|
|
|
v = map.value(_("command"));
|
|
|
|
|
if (v.isValid())
|
|
|
|
|
data.command = v.toString();
|
2011-05-11 15:24:50 +02:00
|
|
|
v = map.value(_("expression"));
|
|
|
|
|
if (v.isValid())
|
|
|
|
|
data.expression = v.toString();
|
2011-06-27 10:37:57 +02:00
|
|
|
v = map.value(_("message"));
|
|
|
|
|
if (v.isValid())
|
|
|
|
|
data.message = v.toString();
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (data.isValid())
|
2011-10-20 10:45:59 +02:00
|
|
|
appendBreakpoint(data);
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
else
|
2011-10-20 10:45:59 +02:00
|
|
|
qWarning("Not restoring invalid breakpoint: %s", qPrintable(data.toString()));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
//qDebug() << "LOADED BREAKPOINTS" << this << list.size();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::updateMarkers()
|
|
|
|
|
{
|
2011-06-24 19:44:49 +02:00
|
|
|
Iterator it = m_storage.begin(), et = m_storage.end();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2011-06-24 19:44:49 +02:00
|
|
|
it->updateMarker(it.key());
|
2010-10-25 14:00:19 +02:00
|
|
|
}
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QVariant BreakHandler::headerData(int section,
|
|
|
|
|
Qt::Orientation orientation, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
|
|
|
static QString headers[] = {
|
|
|
|
|
tr("Number"), tr("Function"), tr("File"), tr("Line"),
|
2010-11-26 12:30:05 +01:00
|
|
|
tr("Address"), tr("Condition"), tr("Ignore"), tr("Threads")
|
2008-12-02 12:01:29 +01:00
|
|
|
};
|
|
|
|
|
return headers[section];
|
|
|
|
|
}
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2011-06-15 14:02:26 +02:00
|
|
|
//qDebug() << "FIND: " << index <<
|
|
|
|
|
// BreakpointId::fromInternalId(index.internalId());
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId::fromInternalId(index.internalId());
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
|
2010-11-15 15:30:39 +01:00
|
|
|
{
|
2011-06-24 16:25:30 +02:00
|
|
|
QSet<BreakpointModelId> ids;
|
2010-11-15 15:30:39 +01:00
|
|
|
foreach (const QModelIndex &index, list)
|
2010-11-24 11:44:43 +01:00
|
|
|
ids.insert(findBreakpointByIndex(index));
|
|
|
|
|
return ids.toList();
|
2010-11-15 15:30:39 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-16 13:52:21 +01:00
|
|
|
Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
// switch (index.column()) {
|
|
|
|
|
// //case 0:
|
|
|
|
|
// // return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
|
|
|
|
|
// default:
|
2011-05-11 16:24:04 +02:00
|
|
|
return QAbstractItemModel::flags(index);
|
2010-11-16 13:52:21 +01:00
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-14 13:00:02 +01:00
|
|
|
QString BreakHandler::displayFromThreadSpec(int spec)
|
2010-11-30 13:39:01 +01:00
|
|
|
{
|
2010-12-14 13:00:02 +01:00
|
|
|
return spec == -1 ? BreakHandler::tr("(all)") : QString::number(spec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BreakHandler::threadSpecFromDisplay(const QString &str)
|
|
|
|
|
{
|
|
|
|
|
bool ok = false;
|
|
|
|
|
int result = str.toInt(&ok);
|
|
|
|
|
return ok ? result : -1;
|
2010-11-30 13:39:01 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
QModelIndex BreakHandler::createIndex(int row, int column, quint32 id) const
|
|
|
|
|
{
|
|
|
|
|
return QAbstractItemModel::createIndex(row, column, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QModelIndex BreakHandler::createIndex(int row, int column, void *ptr) const
|
|
|
|
|
{
|
2011-07-29 12:00:11 +02:00
|
|
|
QTC_CHECK(false); // This function is not used.
|
2011-06-15 14:02:26 +02:00
|
|
|
return QAbstractItemModel::createIndex(row, column, ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BreakHandler::columnCount(const QModelIndex &idx) const
|
|
|
|
|
{
|
|
|
|
|
if (idx.column() > 0)
|
|
|
|
|
return 0;
|
2011-06-24 16:25:30 +02:00
|
|
|
const BreakpointModelId id = findBreakpointByIndex(idx);
|
2011-06-15 14:02:26 +02:00
|
|
|
return id.isMinor() ? 0 : 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BreakHandler::rowCount(const QModelIndex &idx) const
|
|
|
|
|
{
|
|
|
|
|
if (idx.column() > 0)
|
|
|
|
|
return 0;
|
|
|
|
|
if (!idx.isValid())
|
|
|
|
|
return m_storage.size();
|
2011-06-24 16:25:30 +02:00
|
|
|
const BreakpointModelId id = findBreakpointByIndex(idx);
|
2011-06-15 14:02:26 +02:00
|
|
|
if (id.isMajor())
|
|
|
|
|
return m_storage.value(id).subItems.size();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-11 16:24:04 +02:00
|
|
|
QModelIndex BreakHandler::index(int row, int col, const QModelIndex &parent) const
|
|
|
|
|
{
|
2011-06-15 14:02:26 +02:00
|
|
|
if (row < 0 || col < 0)
|
|
|
|
|
return QModelIndex();
|
|
|
|
|
if (parent.column() > 0)
|
|
|
|
|
return QModelIndex();
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = findBreakpointByIndex(parent);
|
2011-06-15 14:02:26 +02:00
|
|
|
if (id.isMajor()) {
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
|
|
|
|
if (row >= it->subItems.size())
|
|
|
|
|
return QModelIndex();
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId sub = id.child(row);
|
2011-06-15 14:02:26 +02:00
|
|
|
return createIndex(row, col, sub.toInternalId());
|
|
|
|
|
}
|
|
|
|
|
if (id.isMinor())
|
|
|
|
|
return QModelIndex();
|
|
|
|
|
QTC_ASSERT(!id.isValid(), return QModelIndex());
|
|
|
|
|
if (row >= m_storage.size())
|
|
|
|
|
return QModelIndex();
|
|
|
|
|
id = at(row);
|
|
|
|
|
return createIndex(row, col, id.toInternalId());
|
2011-05-11 16:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
QModelIndex BreakHandler::parent(const QModelIndex &idx) const
|
2011-05-11 16:24:04 +02:00
|
|
|
{
|
2011-06-15 14:02:26 +02:00
|
|
|
if (!idx.isValid())
|
|
|
|
|
return QModelIndex();
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = findBreakpointByIndex(idx);
|
2011-06-15 14:02:26 +02:00
|
|
|
if (id.isMajor())
|
|
|
|
|
return QModelIndex();
|
|
|
|
|
if (id.isMinor()) {
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId pid = id.parent();
|
2011-06-15 14:02:26 +02:00
|
|
|
int row = indexOf(pid);
|
|
|
|
|
return createIndex(row, 0, pid.toInternalId());
|
|
|
|
|
}
|
2011-05-11 16:24:04 +02:00
|
|
|
return QModelIndex();
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
|
|
|
|
{
|
|
|
|
|
static const QString empty = QString(QLatin1Char('-'));
|
|
|
|
|
|
2010-11-15 14:12:05 +01:00
|
|
|
if (!mi.isValid())
|
|
|
|
|
return QVariant();
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id = findBreakpointByIndex(mi);
|
2011-06-15 14:02:26 +02:00
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId pid = id;
|
2011-06-15 14:02:26 +02:00
|
|
|
if (id.isMinor())
|
|
|
|
|
pid = id.parent();
|
|
|
|
|
|
|
|
|
|
ConstIterator it = m_storage.find(pid);
|
|
|
|
|
QTC_ASSERT(it != m_storage.end(), return QVariant());
|
2010-11-16 11:48:17 +01:00
|
|
|
const BreakpointParameters &data = it->data;
|
2010-11-15 14:12:05 +01:00
|
|
|
const BreakpointResponse &response = it->response;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-25 15:01:51 +01:00
|
|
|
bool orig = false;
|
|
|
|
|
switch (it->state) {
|
|
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
case BreakpointInserted:
|
|
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
case BreakpointRemoveProceeding:
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointNew:
|
|
|
|
|
case BreakpointDead:
|
|
|
|
|
orig = true;
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
if (id.isMinor()) {
|
|
|
|
|
QTC_ASSERT(id.minorPart() <= it->subItems.size(), return QVariant());
|
|
|
|
|
const BreakpointResponse &res = it->subItems.at(id.minorPart() - 1);
|
|
|
|
|
switch (mi.column()) {
|
|
|
|
|
case 0:
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return id.toString();
|
|
|
|
|
case 1:
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return res.functionName;
|
2011-06-21 16:45:23 +02:00
|
|
|
case 4:
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
if (res.address)
|
2012-02-16 09:55:47 +02:00
|
|
|
return QString::fromLatin1("0x%1").arg(res.address, 0, 16);
|
2011-06-15 14:02:26 +02:00
|
|
|
}
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
switch (mi.column()) {
|
|
|
|
|
case 0:
|
2011-06-21 16:45:23 +02:00
|
|
|
if (role == Qt::DisplayRole)
|
2011-06-15 14:02:26 +02:00
|
|
|
return id.toString();
|
2010-11-18 14:57:00 +01:00
|
|
|
if (role == Qt::DecorationRole)
|
|
|
|
|
return it->icon();
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
2010-11-18 14:57:00 +01:00
|
|
|
if (!response.functionName.isEmpty())
|
|
|
|
|
return response.functionName;
|
|
|
|
|
if (!data.functionName.isEmpty())
|
|
|
|
|
return data.functionName;
|
2011-03-04 19:38:58 +01:00
|
|
|
if (data.type == BreakpointAtMain
|
|
|
|
|
|| data.type == BreakpointAtThrow
|
|
|
|
|
|| data.type == BreakpointAtCatch
|
|
|
|
|
|| data.type == BreakpointAtFork
|
|
|
|
|
|| data.type == BreakpointAtExec
|
2011-03-29 09:58:21 +02:00
|
|
|
//|| data.type == BreakpointAtVFork
|
2011-03-04 19:38:58 +01:00
|
|
|
|| data.type == BreakpointAtSysCall)
|
|
|
|
|
return typeToString(data.type);
|
2012-03-19 14:12:29 +01:00
|
|
|
if (data.type == WatchpointAtAddress) {
|
|
|
|
|
quint64 address = response.address ? response.address : data.address;
|
|
|
|
|
return tr("Data at 0x%1").arg(address, 0, 16);
|
|
|
|
|
}
|
|
|
|
|
if (data.type == WatchpointAtExpression) {
|
|
|
|
|
QString expression = !response.expression.isEmpty()
|
|
|
|
|
? response.expression : data.expression;
|
|
|
|
|
return tr("Data at %1").arg(expression);
|
|
|
|
|
}
|
2010-11-18 14:57:00 +01:00
|
|
|
return empty;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
2010-11-18 14:57:00 +01:00
|
|
|
QString str;
|
|
|
|
|
if (!response.fileName.isEmpty())
|
|
|
|
|
str = response.fileName;
|
|
|
|
|
if (str.isEmpty() && !data.fileName.isEmpty())
|
2010-11-18 15:47:50 +01:00
|
|
|
str = data.fileName;
|
2010-11-18 14:57:00 +01:00
|
|
|
if (str.isEmpty()) {
|
|
|
|
|
QString s = QFileInfo(str).fileName();
|
|
|
|
|
if (!s.isEmpty())
|
|
|
|
|
str = s;
|
|
|
|
|
}
|
2010-02-10 11:45:40 +01:00
|
|
|
// FIXME: better?
|
2010-11-18 13:38:58 +01:00
|
|
|
//if (data.multiple && str.isEmpty() && !response.fileName.isEmpty())
|
|
|
|
|
// str = response.fileName;
|
2010-11-18 14:57:00 +01:00
|
|
|
if (!str.isEmpty())
|
2010-12-14 09:57:14 +01:00
|
|
|
return QDir::toNativeSeparators(str);
|
2010-11-18 14:57:00 +01:00
|
|
|
return empty;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
2010-11-18 14:57:00 +01:00
|
|
|
if (response.lineNumber > 0)
|
|
|
|
|
return response.lineNumber;
|
|
|
|
|
if (data.lineNumber > 0)
|
|
|
|
|
return data.lineNumber;
|
|
|
|
|
return empty;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2010-11-16 11:48:17 +01:00
|
|
|
return data.lineNumber;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
case 4:
|
2010-11-26 12:30:05 +01:00
|
|
|
if (role == Qt::DisplayRole) {
|
|
|
|
|
const quint64 address = orig ? data.address : response.address;
|
|
|
|
|
if (address)
|
2012-02-16 09:55:47 +02:00
|
|
|
return QString::fromLatin1("0x%1").arg(address, 0, 16);
|
2011-06-21 16:45:23 +02:00
|
|
|
return QVariant();
|
2010-11-26 12:30:05 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::DisplayRole)
|
2010-11-25 15:01:51 +01:00
|
|
|
return orig ? data.condition : response.condition;
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return tr("Breakpoint will only be hit if this condition is met.");
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2010-11-16 11:48:17 +01:00
|
|
|
return data.condition;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2010-11-26 12:30:05 +01:00
|
|
|
case 6:
|
2010-09-21 14:26:45 +02:00
|
|
|
if (role == Qt::DisplayRole) {
|
2010-11-10 16:33:11 +01:00
|
|
|
const int ignoreCount =
|
2010-11-25 15:01:51 +01:00
|
|
|
orig ? data.ignoreCount : response.ignoreCount;
|
2010-09-21 14:26:45 +02:00
|
|
|
return ignoreCount ? QVariant(ignoreCount) : QVariant(QString());
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return tr("Breakpoint will only be hit after being ignored so many times.");
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2010-11-16 11:48:17 +01:00
|
|
|
return data.ignoreCount;
|
2010-06-11 13:39:47 +10:00
|
|
|
break;
|
2010-11-26 12:30:05 +01:00
|
|
|
case 7:
|
2010-11-30 13:39:01 +01:00
|
|
|
if (role == Qt::DisplayRole)
|
2010-12-14 13:00:02 +01:00
|
|
|
return displayFromThreadSpec(orig ? data.threadSpec : response.threadSpec);
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return tr("Breakpoint will only be hit in the specified thread(s).");
|
|
|
|
|
if (role == Qt::UserRole + 1)
|
2010-12-14 13:00:02 +01:00
|
|
|
return displayFromThreadSpec(data.threadSpec);
|
2010-06-11 13:39:47 +10:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2011-02-07 11:04:31 +01:00
|
|
|
switch (role) {
|
|
|
|
|
case Qt::ToolTipRole:
|
|
|
|
|
if (debuggerCore()->boolSetting(UseToolTipsInBreakpointsView))
|
|
|
|
|
return QVariant(it->toToolTip());
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
#define GETTER(type, getter) \
|
2011-06-24 16:25:30 +02:00
|
|
|
type BreakHandler::getter(BreakpointModelId id) const \
|
2010-11-10 16:33:11 +01:00
|
|
|
{ \
|
2010-11-15 14:12:05 +01:00
|
|
|
ConstIterator it = m_storage.find(id); \
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), \
|
2010-11-15 15:05:39 +01:00
|
|
|
qDebug() << "ID" << id << "NOT KNOWN"; \
|
|
|
|
|
return type()); \
|
2010-11-16 11:48:17 +01:00
|
|
|
return it->data.getter; \
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-16 11:48:17 +01:00
|
|
|
#define SETTER(type, getter, setter) \
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setter(BreakpointModelId id, const type &value) \
|
2010-11-10 16:33:11 +01:00
|
|
|
{ \
|
2010-11-15 14:12:05 +01:00
|
|
|
Iterator it = m_storage.find(id); \
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), \
|
2010-11-15 15:05:39 +01:00
|
|
|
qDebug() << "ID" << id << "NOT KNOWN"; return); \
|
2010-11-16 11:48:17 +01:00
|
|
|
if (it->data.getter == value) \
|
2010-11-15 16:22:51 +01:00
|
|
|
return; \
|
2010-11-16 11:48:17 +01:00
|
|
|
it->data.getter = value; \
|
2010-12-14 13:35:42 +01:00
|
|
|
if (it->state != BreakpointNew) { \
|
|
|
|
|
it->state = BreakpointChangeRequested; \
|
|
|
|
|
scheduleSynchronization(); \
|
|
|
|
|
} \
|
2010-09-28 13:14:14 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
#define PROPERTY(type, getter, setter) \
|
|
|
|
|
GETTER(type, getter) \
|
2010-11-16 11:48:17 +01:00
|
|
|
SETTER(type, getter, setter)
|
2009-05-12 14:28:27 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-02-17 13:00:11 +01:00
|
|
|
PROPERTY(BreakpointPathUsage, pathUsage, setPathUsage)
|
2010-11-10 16:33:11 +01:00
|
|
|
PROPERTY(QString, fileName, setFileName)
|
|
|
|
|
PROPERTY(QString, functionName, setFunctionName)
|
|
|
|
|
PROPERTY(BreakpointType, type, setType)
|
2010-11-30 13:39:01 +01:00
|
|
|
PROPERTY(int, threadSpec, setThreadSpec)
|
2010-11-10 16:33:11 +01:00
|
|
|
PROPERTY(QByteArray, condition, setCondition)
|
2010-11-18 17:53:42 +01:00
|
|
|
GETTER(int, lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
PROPERTY(quint64, address, setAddress)
|
2011-05-10 15:57:33 +02:00
|
|
|
PROPERTY(QString, expression, setExpression)
|
2011-06-27 10:37:57 +02:00
|
|
|
PROPERTY(QString, message, setMessage)
|
2010-11-15 12:32:51 +01:00
|
|
|
PROPERTY(int, ignoreCount, setIgnoreCount)
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
bool BreakHandler::isEnabled(BreakpointModelId id) const
|
2010-11-15 15:05:39 +01:00
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
2010-11-16 11:48:17 +01:00
|
|
|
return it->data.enabled;
|
2010-11-15 15:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setEnabled(BreakpointModelId id, bool on)
|
2010-11-15 15:05:39 +01:00
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-15 15:05:39 +01:00
|
|
|
//qDebug() << "SET ENABLED: " << id << it->data.isEnabled() << on;
|
2010-11-16 11:48:17 +01:00
|
|
|
if (it->data.enabled == on)
|
|
|
|
|
return;
|
|
|
|
|
it->data.enabled = on;
|
2012-03-08 14:00:26 +01:00
|
|
|
it->updateMarkerIcon();
|
2011-02-17 13:49:47 +01:00
|
|
|
if (it->engine) {
|
|
|
|
|
it->state = BreakpointChangeRequested;
|
|
|
|
|
scheduleSynchronization();
|
|
|
|
|
}
|
2010-11-15 15:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
bool BreakHandler::isWatchpoint(BreakpointModelId id) const
|
2011-05-09 08:35:58 +02:00
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
|
|
|
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
|
|
|
|
return it->data.isWatchpoint();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
bool BreakHandler::isTracepoint(BreakpointModelId id) const
|
2010-12-16 17:58:43 +01:00
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
2010-12-16 17:58:43 +01:00
|
|
|
return it->data.tracepoint;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-21 14:16:07 +02:00
|
|
|
bool BreakHandler::isOneShot(BreakpointModelId id) const
|
|
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
|
|
|
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
|
|
|
|
return it->data.oneShot;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 19:02:12 +02:00
|
|
|
bool BreakHandler::needsChildren(BreakpointModelId id) const
|
|
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
|
|
|
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
|
|
|
|
return it->response.multiple && it->subItems.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setTracepoint(BreakpointModelId id, bool on)
|
2010-12-16 17:58:43 +01:00
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-12-16 17:58:43 +01:00
|
|
|
if (it->data.tracepoint == on)
|
|
|
|
|
return;
|
|
|
|
|
it->data.tracepoint = on;
|
2012-03-08 14:00:26 +01:00
|
|
|
it->updateMarkerIcon();
|
2011-02-17 13:49:47 +01:00
|
|
|
|
|
|
|
|
if (it->engine) {
|
|
|
|
|
it->state = BreakpointChangeRequested;
|
|
|
|
|
scheduleSynchronization();
|
|
|
|
|
}
|
2010-12-16 17:58:43 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setMarkerFileAndLine(BreakpointModelId id,
|
2010-11-15 19:05:31 +01:00
|
|
|
const QString &fileName, int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
2011-06-24 16:25:30 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(),
|
|
|
|
|
qDebug() << "MARKER_FILE_AND_LINE: " << id; return);
|
2010-11-18 13:38:58 +01:00
|
|
|
if (it->response.fileName == fileName && it->response.lineNumber == lineNumber)
|
2010-11-18 12:30:56 +01:00
|
|
|
return;
|
|
|
|
|
it->response.fileName = fileName;
|
|
|
|
|
it->response.lineNumber = lineNumber;
|
2010-11-18 14:57:00 +01:00
|
|
|
it->destroyMarker();
|
2011-06-24 19:44:49 +02:00
|
|
|
it->updateMarker(id);
|
2010-11-18 14:57:00 +01:00
|
|
|
emit layoutChanged();
|
2010-11-15 19:05:31 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointState BreakHandler::state(BreakpointModelId id) const
|
2010-11-15 14:12:05 +01:00
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-06-24 16:25:30 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(),
|
|
|
|
|
qDebug() << "STATE: " << id; return BreakpointDead);
|
2010-11-15 14:12:05 +01:00
|
|
|
return it->state;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
DebuggerEngine *BreakHandler::engine(BreakpointModelId id) const
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), qDebug() << id; return 0);
|
2010-11-16 13:52:21 +01:00
|
|
|
return it->engine;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setEngine(BreakpointModelId id, DebuggerEngine *value)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
2011-05-11 16:24:04 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), qDebug() << "SET ENGINE" << id; return);
|
|
|
|
|
QTC_ASSERT(it->state == BreakpointNew, qDebug() << "STATE: " << it->state <<id);
|
|
|
|
|
QTC_ASSERT(!it->engine, qDebug() << "NO ENGINE" << id; return);
|
2010-11-16 13:52:21 +01:00
|
|
|
it->engine = value;
|
|
|
|
|
it->state = BreakpointInsertRequested;
|
2010-11-18 14:57:00 +01:00
|
|
|
it->response = BreakpointResponse();
|
2011-06-24 19:44:49 +02:00
|
|
|
it->updateMarker(id);
|
2010-11-16 13:52:21 +01:00
|
|
|
scheduleSynchronization();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isAllowedTransition(BreakpointState from, BreakpointState to)
|
|
|
|
|
{
|
|
|
|
|
switch (from) {
|
|
|
|
|
case BreakpointNew:
|
|
|
|
|
return to == BreakpointInsertRequested;
|
|
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
return to == BreakpointInsertProceeding;
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
return to == BreakpointInserted
|
2010-11-18 12:30:56 +01:00
|
|
|
|| to == BreakpointDead
|
2011-10-01 16:21:59 +02:00
|
|
|
|| to == BreakpointChangeRequested
|
|
|
|
|
|| to == BreakpointRemoveRequested;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
return to == BreakpointChangeProceeding;
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
return to == BreakpointInserted
|
|
|
|
|
|| to == BreakpointDead;
|
|
|
|
|
case BreakpointInserted:
|
2010-11-16 16:10:55 +01:00
|
|
|
return to == BreakpointChangeRequested
|
|
|
|
|
|| to == BreakpointRemoveRequested;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointRemoveRequested:
|
2010-11-16 16:10:55 +01:00
|
|
|
return to == BreakpointRemoveProceeding;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointRemoveProceeding:
|
2010-11-16 16:10:55 +01:00
|
|
|
return to == BreakpointDead;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointDead:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
qDebug() << "UNKNOWN BREAKPOINT STATE:" << from;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
bool BreakHandler::isEngineRunning(BreakpointModelId id) const
|
2011-05-11 12:18:32 +02:00
|
|
|
{
|
|
|
|
|
if (const DebuggerEngine *e = engine(id)) {
|
|
|
|
|
const DebuggerState state = e->state();
|
|
|
|
|
return state != DebuggerFinished && state != DebuggerNotReady;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setState(BreakpointModelId id, BreakpointState state)
|
2010-11-15 14:12:05 +01:00
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
2011-06-24 19:36:13 +02:00
|
|
|
//qDebug() << "BREAKPOINT STATE TRANSITION, ID: " << id
|
|
|
|
|
// << " FROM: " << it->state << " TO: " << state;
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), qDebug() << id; return);
|
2010-11-16 13:52:21 +01:00
|
|
|
QTC_ASSERT(isAllowedTransition(it->state, state),
|
|
|
|
|
qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION"
|
|
|
|
|
<< it->state << state);
|
|
|
|
|
|
2010-11-15 16:58:23 +01:00
|
|
|
if (it->state == state) {
|
|
|
|
|
qDebug() << "STATE UNCHANGED: " << id << state;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-11-16 13:52:21 +01:00
|
|
|
|
2010-11-15 14:12:05 +01:00
|
|
|
it->state = state;
|
2011-06-24 19:36:13 +02:00
|
|
|
|
|
|
|
|
// FIXME: updateMarker() should recognize the need for icon changes.
|
|
|
|
|
if (state == BreakpointInserted) {
|
|
|
|
|
it->destroyMarker();
|
2011-06-24 19:44:49 +02:00
|
|
|
it->updateMarker(id);
|
2011-06-24 19:36:13 +02:00
|
|
|
}
|
2011-03-04 18:08:56 +01:00
|
|
|
layoutChanged();
|
2010-11-15 14:12:05 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointChangeAfterInsertNeeded(BreakpointModelId id)
|
2010-11-30 12:47:53 +01:00
|
|
|
{
|
|
|
|
|
QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id));
|
|
|
|
|
setState(id, BreakpointChangeRequested);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointInsertProceeding(BreakpointModelId id)
|
2009-04-28 15:08:52 +02:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointInsertRequested, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointInsertProceeding);
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointInsertOk(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointInserted);
|
2010-11-16 17:53:08 +01:00
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointInsertFailed(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointDead);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointRemoveProceeding(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointRemoveRequested, qDebug() << state(id));
|
2010-11-16 17:29:38 +01:00
|
|
|
setState(id, BreakpointRemoveProceeding);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointRemoveOk(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointRemoveProceeding, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointDead);
|
|
|
|
|
cleanupBreakpoint(id);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointRemoveFailed(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointRemoveProceeding, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointDead);
|
|
|
|
|
cleanupBreakpoint(id);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointChangeProceeding(BreakpointModelId id)
|
2010-11-18 16:16:23 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointChangeRequested, qDebug() << state(id));
|
2010-11-18 16:16:23 +01:00
|
|
|
setState(id, BreakpointChangeProceeding);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointChangeOk(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointInserted);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointChangeFailed(BreakpointModelId id)
|
2009-04-28 15:08:52 +02:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
|
2010-11-16 13:52:21 +01:00
|
|
|
setState(id, BreakpointDead);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointReleased(BreakpointModelId id)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
//QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
|
2010-11-15 14:12:05 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-16 13:52:21 +01:00
|
|
|
it->state = BreakpointNew;
|
|
|
|
|
it->engine = 0;
|
|
|
|
|
it->response = BreakpointResponse();
|
2011-06-15 14:02:26 +02:00
|
|
|
it->subItems.clear();
|
2011-06-24 19:44:49 +02:00
|
|
|
it->destroyMarker();
|
|
|
|
|
it->updateMarker(id);
|
2011-05-11 15:24:50 +02:00
|
|
|
if (it->data.type == WatchpointAtAddress
|
|
|
|
|
|| it->data.type == WatchpointAtExpression
|
|
|
|
|
|| it->data.type == BreakpointByAddress)
|
|
|
|
|
it->data.enabled = false;
|
2010-11-16 13:52:21 +01:00
|
|
|
layoutChanged();
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointAdjusted(BreakpointModelId id,
|
2010-11-16 18:20:52 +01:00
|
|
|
const BreakpointParameters &data)
|
|
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointInserted, qDebug() << state(id));
|
2010-11-16 18:20:52 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-16 18:20:52 +01:00
|
|
|
it->data = data;
|
2010-11-30 12:47:53 +01:00
|
|
|
//if (it->needsChange())
|
|
|
|
|
// setState(id, BreakpointChangeRequested);
|
2010-11-16 18:20:52 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::notifyBreakpointNeedsReinsertion(BreakpointModelId id)
|
2010-11-30 12:47:53 +01:00
|
|
|
{
|
2010-11-30 13:39:01 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id));
|
2010-11-30 12:47:53 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-30 13:39:01 +01:00
|
|
|
it->state = BreakpointInsertRequested;
|
2010-11-30 12:47:53 +01:00
|
|
|
}
|
2010-11-16 18:20:52 +01:00
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::removeAlienBreakpoint(BreakpointModelId id)
|
2011-06-24 14:17:16 +02:00
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
|
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
|
|
|
|
it->state = BreakpointDead;
|
|
|
|
|
cleanupBreakpoint(id);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::removeBreakpoint(BreakpointModelId id)
|
2009-04-28 15:08:52 +02:00
|
|
|
{
|
2010-11-15 14:12:05 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2011-02-17 13:49:47 +01:00
|
|
|
switch (it->state) {
|
2011-10-28 12:26:00 +02:00
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
break;
|
2011-02-17 13:49:47 +01:00
|
|
|
case BreakpointInserted:
|
2011-10-01 16:21:59 +02:00
|
|
|
case BreakpointInsertProceeding:
|
2010-11-15 16:58:23 +01:00
|
|
|
setState(id, BreakpointRemoveRequested);
|
2010-11-18 14:57:00 +01:00
|
|
|
scheduleSynchronization();
|
2011-02-17 13:49:47 +01:00
|
|
|
break;
|
|
|
|
|
case BreakpointNew:
|
2010-11-15 14:12:05 +01:00
|
|
|
it->state = BreakpointDead;
|
2010-11-10 16:33:11 +01:00
|
|
|
cleanupBreakpoint(id);
|
2011-02-17 13:49:47 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2011-06-15 14:02:26 +02:00
|
|
|
qWarning("Warning: Cannot remove breakpoint %s in state '%s'.",
|
|
|
|
|
qPrintable(id.toString()), qPrintable(stateToString(it->state)));
|
2010-11-15 16:58:23 +01:00
|
|
|
it->state = BreakpointRemoveRequested;
|
2011-02-17 13:49:47 +01:00
|
|
|
break;
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-06-24 14:17:16 +02:00
|
|
|
// Ok to be not thread-safe. The order does not matter and only the gui
|
|
|
|
|
// produces authoritative ids.
|
|
|
|
|
static int currentId = 0;
|
|
|
|
|
|
2010-11-16 10:50:11 +01:00
|
|
|
void BreakHandler::appendBreakpoint(const BreakpointParameters &data)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2011-10-20 10:45:59 +02:00
|
|
|
if (!data.isValid()) {
|
|
|
|
|
qWarning("Not adding invalid breakpoint: %s", qPrintable(data.toString()));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id(++currentId);
|
2011-02-04 09:11:24 +01:00
|
|
|
const int row = m_storage.size();
|
|
|
|
|
beginInsertRows(QModelIndex(), row, row);
|
2011-06-27 18:04:39 +02:00
|
|
|
Iterator it = m_storage.insert(id, BreakpointItem());
|
2011-02-04 09:11:24 +01:00
|
|
|
endInsertRows();
|
|
|
|
|
|
2011-06-27 18:04:39 +02:00
|
|
|
// Create marker after copy is inserted into hash.
|
|
|
|
|
it->data = data;
|
|
|
|
|
it->updateMarker(id);
|
2011-06-15 14:02:26 +02:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
scheduleSynchronization();
|
2011-06-15 14:02:26 +02:00
|
|
|
}
|
2011-02-04 09:11:24 +01:00
|
|
|
|
2012-03-19 14:12:29 +01:00
|
|
|
void BreakHandler::handleAlienBreakpoint(const BreakpointResponse &response, DebuggerEngine *engine)
|
2011-06-24 14:17:16 +02:00
|
|
|
{
|
2012-03-19 14:12:29 +01:00
|
|
|
BreakpointModelId id = findSimilarBreakpoint(response);
|
|
|
|
|
if (id.isValid()) {
|
|
|
|
|
if (response.id.isMinor())
|
|
|
|
|
insertSubBreakpoint(id, response);
|
|
|
|
|
else
|
|
|
|
|
setResponse(id, response);
|
2011-06-24 14:17:16 +02:00
|
|
|
} else {
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId id(++currentId);
|
2011-06-24 14:17:16 +02:00
|
|
|
const int row = m_storage.size();
|
2011-06-27 18:04:39 +02:00
|
|
|
|
2011-06-24 14:17:16 +02:00
|
|
|
beginInsertRows(QModelIndex(), row, row);
|
2011-06-27 18:04:39 +02:00
|
|
|
Iterator it = m_storage.insert(id, BreakpointItem());
|
2011-06-24 14:17:16 +02:00
|
|
|
endInsertRows();
|
|
|
|
|
|
2011-06-27 18:04:39 +02:00
|
|
|
it->data = response;
|
|
|
|
|
it->response = response;
|
|
|
|
|
it->state = BreakpointInserted;
|
|
|
|
|
it->engine = engine;
|
|
|
|
|
it->updateMarker(id);
|
|
|
|
|
|
2011-06-24 14:17:16 +02:00
|
|
|
layoutChanged();
|
|
|
|
|
scheduleSynchronization();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelId BreakHandler::at(int n) const
|
2011-06-15 14:02:26 +02:00
|
|
|
{
|
|
|
|
|
if (n < 0 || n >= m_storage.size())
|
2011-06-24 16:25:30 +02:00
|
|
|
return BreakpointModelId();
|
2011-06-27 11:29:15 +02:00
|
|
|
ConstIterator it = m_storage.constBegin();
|
2011-06-15 14:02:26 +02:00
|
|
|
for ( ; --n >= 0; ++it)
|
|
|
|
|
;
|
|
|
|
|
return it.key();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
int BreakHandler::indexOf(BreakpointModelId id) const
|
2011-06-15 14:02:26 +02:00
|
|
|
{
|
|
|
|
|
int row = 0;
|
|
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
|
|
|
|
for ( ; it != et; ++it, ++row)
|
|
|
|
|
if (it.key() == id)
|
|
|
|
|
return row;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 19:02:12 +02:00
|
|
|
void BreakHandler::insertSubBreakpoint(BreakpointModelId id,
|
|
|
|
|
const BreakpointResponse &data)
|
2011-06-15 14:02:26 +02:00
|
|
|
{
|
2011-06-24 19:02:12 +02:00
|
|
|
QTC_ASSERT(data.id.isMinor(), return);
|
|
|
|
|
QTC_ASSERT(id.isMajor(), return);
|
|
|
|
|
Iterator it = m_storage.find(id);
|
2011-06-24 14:17:16 +02:00
|
|
|
|
|
|
|
|
if (it == m_storage.end()) {
|
2011-06-24 19:02:12 +02:00
|
|
|
qDebug() << "FAILED: " << id.toString();
|
2011-06-24 14:17:16 +02:00
|
|
|
for (ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
|
|
|
|
it != et; ++it) {
|
|
|
|
|
qDebug() << " ID: " << it->response.id.toString();
|
|
|
|
|
qDebug() << " DATA: " << it->data.toString();
|
|
|
|
|
qDebug() << " RESP: " << it->response.toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
QTC_ASSERT(it != m_storage.end(), return);
|
2011-06-24 19:02:12 +02:00
|
|
|
int minorPart = data.id.minorPart();
|
2011-06-21 16:45:23 +02:00
|
|
|
int pos = -1;
|
|
|
|
|
for (int i = 0; i != it->subItems.size(); ++i) {
|
|
|
|
|
if (it->subItems.at(i).id.minorPart() == minorPart) {
|
|
|
|
|
pos = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pos == -1) {
|
|
|
|
|
// This is a new sub-breakpoint.
|
2011-06-24 19:02:12 +02:00
|
|
|
//qDebug() << "NEW ID" << id;
|
|
|
|
|
int row = indexOf(id);
|
2011-06-24 16:25:30 +02:00
|
|
|
QTC_ASSERT(row != -1, return);
|
2011-06-21 16:45:23 +02:00
|
|
|
QModelIndex idx = createIndex(row, 0, id.toInternalId());
|
|
|
|
|
beginInsertRows(idx, it->subItems.size(), it->subItems.size());
|
|
|
|
|
it->subItems.append(data);
|
|
|
|
|
endInsertRows();
|
|
|
|
|
} else {
|
|
|
|
|
// This modifies an existing sub-breakpoint.
|
2011-06-24 19:02:12 +02:00
|
|
|
//qDebug() << "EXISTING ID" << id;
|
2011-06-21 16:45:23 +02:00
|
|
|
it->subItems[pos] = data;
|
|
|
|
|
layoutChanged();
|
|
|
|
|
}
|
2010-06-25 16:06:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void BreakHandler::saveSessionData()
|
|
|
|
|
{
|
|
|
|
|
saveBreakpoints();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::loadSessionData()
|
|
|
|
|
{
|
2012-09-20 10:31:34 +02:00
|
|
|
beginResetModel();
|
2010-11-15 13:12:13 +01:00
|
|
|
m_storage.clear();
|
2012-09-20 10:31:34 +02:00
|
|
|
endResetModel();
|
2008-12-02 12:01:29 +01:00
|
|
|
loadBreakpoints();
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-25 16:32:07 +01:00
|
|
|
void BreakHandler::removeSessionData()
|
|
|
|
|
{
|
2012-09-20 10:31:34 +02:00
|
|
|
beginResetModel();
|
2010-11-25 16:32:07 +01:00
|
|
|
Iterator it = m_storage.begin(), et = m_storage.end();
|
|
|
|
|
for ( ; it != et; ++it)
|
|
|
|
|
it->destroyMarker();
|
|
|
|
|
m_storage.clear();
|
2012-09-20 10:31:34 +02:00
|
|
|
endResetModel();
|
2010-11-25 16:32:07 +01:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void BreakHandler::breakByFunction(const QString &functionName)
|
|
|
|
|
{
|
2010-03-26 08:52:49 +01:00
|
|
|
// One breakpoint per function is enough for now. This does not handle
|
|
|
|
|
// combinations of multiple conditions and ignore counts, though.
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it) {
|
2010-11-16 11:48:17 +01:00
|
|
|
const BreakpointParameters &data = it->data;
|
|
|
|
|
if (data.functionName == functionName
|
|
|
|
|
&& data.condition.isEmpty()
|
|
|
|
|
&& data.ignoreCount == 0)
|
2008-12-02 12:01:29 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2010-11-16 10:50:11 +01:00
|
|
|
BreakpointParameters data(BreakpointByFunction);
|
|
|
|
|
data.functionName = functionName;
|
2010-11-10 16:33:11 +01:00
|
|
|
appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
QIcon BreakHandler::icon(BreakpointModelId id) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 14:12:05 +01:00
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), qDebug() << "NO ICON FOR ID" << id;
|
2010-11-26 12:30:05 +01:00
|
|
|
return pendingBreakpointIcon());
|
2010-11-18 14:57:00 +01:00
|
|
|
return it->icon();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::scheduleSynchronization()
|
|
|
|
|
{
|
|
|
|
|
if (m_syncTimerId == -1)
|
|
|
|
|
m_syncTimerId = startTimer(10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::timerEvent(QTimerEvent *event)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(event->timerId() == m_syncTimerId, return);
|
|
|
|
|
killTimer(m_syncTimerId);
|
|
|
|
|
m_syncTimerId = -1;
|
|
|
|
|
saveBreakpoints(); // FIXME: remove?
|
2010-11-30 12:47:53 +01:00
|
|
|
debuggerCore()->synchronizeBreakpoints();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::gotoLocation(BreakpointModelId id) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-12-14 12:21:29 +01:00
|
|
|
DebuggerEngine *engine = debuggerCore()->currentEngine();
|
2010-11-24 11:44:43 +01:00
|
|
|
if (it->data.type == BreakpointByAddress) {
|
|
|
|
|
if (engine)
|
2010-12-16 19:06:33 +01:00
|
|
|
engine->gotoLocation(it->data.address);
|
2010-11-24 11:44:43 +01:00
|
|
|
} else {
|
2010-12-14 12:21:29 +01:00
|
|
|
if (engine)
|
2010-12-16 19:06:33 +01:00
|
|
|
engine->gotoLocation(
|
2010-12-21 15:53:49 +01:00
|
|
|
Location(it->markerFileName(), it->markerLineNumber(), false));
|
2010-11-24 11:44:43 +01:00
|
|
|
}
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2012-03-12 16:56:25 +01:00
|
|
|
void BreakHandler::updateFileNameFromMarker(BreakpointModelId id, const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
Iterator it = m_storage.find(id);
|
|
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
|
|
|
|
it->data.fileName = fileName;
|
|
|
|
|
emit layoutChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::updateLineNumberFromMarker(BreakpointModelId id, int lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-10 16:33:11 +01:00
|
|
|
// Ignore updates to the "real" line number while the debugger is
|
|
|
|
|
// running, as this can be triggered by moving the breakpoint to
|
|
|
|
|
// the next line that generated code.
|
2011-06-07 17:21:45 +02:00
|
|
|
if (it->data.lineNumber == lineNumber)
|
|
|
|
|
; // Nothing
|
|
|
|
|
else if (isEngineRunning(id))
|
2011-06-01 13:24:29 +02:00
|
|
|
it->data.lineNumber += lineNumber - it->response.lineNumber;
|
|
|
|
|
else
|
2010-11-16 11:48:17 +01:00
|
|
|
it->data.lineNumber = lineNumber;
|
2011-06-24 19:44:49 +02:00
|
|
|
it->updateMarker(id);
|
2010-11-18 14:57:00 +01:00
|
|
|
emit layoutChanged();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2012-10-09 22:34:36 +02:00
|
|
|
void BreakHandler::changeLineNumberFromMarker(BreakpointModelId id, int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
// We need to delay this as it is called from a marker which will be destroyed.
|
|
|
|
|
ExtensionSystem::InvokerBase invoker;
|
|
|
|
|
invoker.addArgument(id);
|
|
|
|
|
invoker.addArgument(lineNumber);
|
|
|
|
|
invoker.setConnectionType(Qt::QueuedConnection);
|
|
|
|
|
invoker.invoke(this, "changeLineNumberFromMarkerHelper");
|
|
|
|
|
QTC_CHECK(invoker.wasSuccessful());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::changeLineNumberFromMarkerHelper(BreakpointModelId id, int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
BreakpointParameters data = breakpointData(id);
|
|
|
|
|
data.lineNumber = lineNumber;
|
|
|
|
|
removeBreakpoint(id);
|
|
|
|
|
appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelIds BreakHandler::allBreakpointIds() const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelIds ids;
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
|
|
|
|
ids.append(it.key());
|
|
|
|
|
return ids;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelIds BreakHandler::unclaimedBreakpointIds() const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
|
|
|
|
return engineBreakpointIds(0);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelIds BreakHandler::engineBreakpointIds(DebuggerEngine *engine) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2011-06-24 16:25:30 +02:00
|
|
|
BreakpointModelIds ids;
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
2010-11-10 16:33:11 +01:00
|
|
|
for ( ; it != et; ++it)
|
2010-11-15 14:12:05 +01:00
|
|
|
if (it->engine == engine)
|
2010-11-10 16:33:11 +01:00
|
|
|
ids.append(it.key());
|
|
|
|
|
return ids;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 14:46:59 +02:00
|
|
|
QStringList BreakHandler::engineBreakpointPaths(DebuggerEngine *engine) const
|
|
|
|
|
{
|
|
|
|
|
QSet<QString> set;
|
|
|
|
|
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
|
|
|
|
for ( ; it != et; ++it) {
|
|
|
|
|
if (it->engine == engine) {
|
|
|
|
|
if (it->data.type == BreakpointByFileAndLine)
|
|
|
|
|
set.insert(QFileInfo(it->data.fileName).dir().path());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return set.toList();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::cleanupBreakpoint(BreakpointModelId id)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-30 12:47:53 +01:00
|
|
|
QTC_ASSERT(state(id) == BreakpointDead, qDebug() << state(id));
|
2010-11-15 13:12:13 +01:00
|
|
|
BreakpointItem item = m_storage.take(id);
|
2010-11-15 14:27:06 +01:00
|
|
|
item.destroyMarker();
|
2010-11-15 15:15:09 +01:00
|
|
|
layoutChanged();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
const BreakpointResponse &BreakHandler::response(BreakpointModelId id) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 16:22:51 +01:00
|
|
|
static BreakpointResponse dummy;
|
2010-11-15 13:12:13 +01:00
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-07-04 13:37:01 +02:00
|
|
|
if (it == m_storage.end()) {
|
|
|
|
|
qDebug() << "NO RESPONSE FOR " << id;
|
2011-03-23 12:24:35 +01:00
|
|
|
return dummy;
|
2011-07-04 13:37:01 +02:00
|
|
|
}
|
2010-11-15 14:12:05 +01:00
|
|
|
return it->response;
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
bool BreakHandler::needsChange(BreakpointModelId id) const
|
2010-11-30 12:47:53 +01:00
|
|
|
{
|
|
|
|
|
ConstIterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
2010-11-30 12:47:53 +01:00
|
|
|
return it->needsChange();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::setResponse(BreakpointModelId id,
|
2011-05-11 15:24:50 +02:00
|
|
|
const BreakpointResponse &response)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2010-11-15 13:12:13 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2011-06-24 19:44:49 +02:00
|
|
|
it->response = response;
|
|
|
|
|
it->destroyMarker();
|
|
|
|
|
it->updateMarker(id);
|
2011-03-04 19:26:11 +01:00
|
|
|
// Take over corrected values from response.
|
2011-06-24 19:44:49 +02:00
|
|
|
if ((it->data.type == BreakpointByFileAndLine
|
|
|
|
|
|| it->data.type == BreakpointByFunction)
|
2011-05-11 15:24:50 +02:00
|
|
|
&& !response.module.isEmpty())
|
2011-06-24 19:44:49 +02:00
|
|
|
it->data.module = response.module;
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
2010-11-04 09:54:23 +01:00
|
|
|
|
2011-06-24 16:25:30 +02:00
|
|
|
void BreakHandler::changeBreakpointData(BreakpointModelId id,
|
2011-03-29 12:55:36 +02:00
|
|
|
const BreakpointParameters &data, BreakpointParts parts)
|
2010-11-16 10:50:11 +01:00
|
|
|
{
|
2011-11-23 16:46:16 +00:00
|
|
|
Q_UNUSED(parts);
|
2010-11-16 10:50:11 +01:00
|
|
|
Iterator it = m_storage.find(id);
|
2011-04-14 16:10:18 +02:00
|
|
|
BREAK_ASSERT(it != m_storage.end(), return);
|
2010-11-16 11:48:17 +01:00
|
|
|
if (data == it->data)
|
2010-11-16 10:50:11 +01:00
|
|
|
return;
|
2010-11-16 11:48:17 +01:00
|
|
|
it->data = data;
|
2011-11-04 14:03:48 +01:00
|
|
|
it->destroyMarker();
|
|
|
|
|
it->updateMarker(id);
|
|
|
|
|
layoutChanged();
|
|
|
|
|
if (it->needsChange() && it->engine && it->state != BreakpointNew) {
|
2011-03-29 12:55:36 +02:00
|
|
|
setState(id, BreakpointChangeRequested);
|
|
|
|
|
scheduleSynchronization();
|
2010-11-30 12:47:53 +01:00
|
|
|
}
|
2010-11-16 10:50:11 +01:00
|
|
|
}
|
2010-11-15 19:05:31 +01:00
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Storage
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
BreakHandler::BreakpointItem::BreakpointItem()
|
2010-11-18 13:38:58 +01:00
|
|
|
: state(BreakpointNew), engine(0), marker(0)
|
2010-11-15 19:05:31 +01:00
|
|
|
{}
|
|
|
|
|
|
2010-11-15 14:27:06 +01:00
|
|
|
void BreakHandler::BreakpointItem::destroyMarker()
|
2010-11-15 13:12:13 +01:00
|
|
|
{
|
2010-11-15 14:27:06 +01:00
|
|
|
BreakpointMarker *m = marker;
|
2010-11-15 13:12:13 +01:00
|
|
|
marker = 0;
|
2010-11-15 14:27:06 +01:00
|
|
|
delete m;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-18 13:38:58 +01:00
|
|
|
QString BreakHandler::BreakpointItem::markerFileName() const
|
|
|
|
|
{
|
2010-11-18 16:00:56 +01:00
|
|
|
// Some heuristics to find a "good" file name.
|
|
|
|
|
if (!data.fileName.isEmpty()) {
|
|
|
|
|
QFileInfo fi(data.fileName);
|
|
|
|
|
if (fi.exists())
|
|
|
|
|
return fi.absoluteFilePath();
|
|
|
|
|
}
|
|
|
|
|
if (!response.fileName.isEmpty()) {
|
|
|
|
|
QFileInfo fi(response.fileName);
|
|
|
|
|
if (fi.exists())
|
|
|
|
|
return fi.absoluteFilePath();
|
|
|
|
|
}
|
|
|
|
|
if (response.fileName.endsWith(data.fileName))
|
|
|
|
|
return response.fileName;
|
|
|
|
|
if (data.fileName.endsWith(response.fileName))
|
|
|
|
|
return data.fileName;
|
|
|
|
|
return response.fileName.size() > data.fileName.size()
|
|
|
|
|
? response.fileName : data.fileName;
|
2010-11-18 13:38:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int BreakHandler::BreakpointItem::markerLineNumber() const
|
|
|
|
|
{
|
|
|
|
|
return response.lineNumber ? response.lineNumber : data.lineNumber;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-15 14:27:06 +01:00
|
|
|
static void formatAddress(QTextStream &str, quint64 address)
|
|
|
|
|
{
|
|
|
|
|
if (address) {
|
|
|
|
|
str << "0x";
|
|
|
|
|
str.setIntegerBase(16);
|
|
|
|
|
str << address;
|
|
|
|
|
str.setIntegerBase(10);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 18:14:00 +01:00
|
|
|
bool BreakHandler::BreakpointItem::needsChange() const
|
|
|
|
|
{
|
|
|
|
|
if (!data.conditionsMatch(response.condition))
|
|
|
|
|
return true;
|
|
|
|
|
if (data.ignoreCount != response.ignoreCount)
|
|
|
|
|
return true;
|
|
|
|
|
if (data.enabled != response.enabled)
|
|
|
|
|
return true;
|
2010-11-30 12:47:53 +01:00
|
|
|
if (data.threadSpec != response.threadSpec)
|
|
|
|
|
return true;
|
2011-02-04 11:33:45 +01:00
|
|
|
if (data.command != response.command)
|
|
|
|
|
return true;
|
2011-11-04 14:03:48 +01:00
|
|
|
if (data.lineNumber != response.lineNumber)
|
|
|
|
|
return true;
|
2010-11-16 18:14:00 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-15 19:05:31 +01:00
|
|
|
bool BreakHandler::BreakpointItem::isLocatedAt
|
|
|
|
|
(const QString &fileName, int lineNumber, bool useMarkerPosition) const
|
|
|
|
|
{
|
2010-11-18 13:38:58 +01:00
|
|
|
int line = useMarkerPosition ? response.lineNumber : data.lineNumber;
|
2010-11-18 16:31:18 +01:00
|
|
|
return lineNumber == line
|
|
|
|
|
&& (fileNameMatch(fileName, response.fileName)
|
|
|
|
|
|| fileNameMatch(fileName, markerFileName()));
|
2010-11-15 19:05:31 +01:00
|
|
|
}
|
|
|
|
|
|
2012-03-08 14:00:26 +01:00
|
|
|
void BreakHandler::BreakpointItem::updateMarkerIcon()
|
|
|
|
|
{
|
2012-04-26 19:21:28 +02:00
|
|
|
if (marker) {
|
|
|
|
|
marker->setIcon(icon());
|
|
|
|
|
marker->updateMarker();
|
|
|
|
|
}
|
2012-03-08 14:00:26 +01:00
|
|
|
}
|
|
|
|
|
|
2011-06-24 19:44:49 +02:00
|
|
|
void BreakHandler::BreakpointItem::updateMarker(BreakpointModelId id)
|
|
|
|
|
{
|
|
|
|
|
QString file = markerFileName();
|
|
|
|
|
int line = markerLineNumber();
|
|
|
|
|
if (marker && (file != marker->fileName() || line != marker->lineNumber()))
|
|
|
|
|
destroyMarker();
|
|
|
|
|
|
2012-05-02 14:33:28 +02:00
|
|
|
if (!marker && !file.isEmpty() && line > 0) {
|
2011-06-24 19:44:49 +02:00
|
|
|
marker = new BreakpointMarker(id, file, line);
|
2012-05-02 14:33:28 +02:00
|
|
|
marker->init();
|
|
|
|
|
}
|
2011-06-24 19:44:49 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-18 14:57:00 +01:00
|
|
|
QIcon BreakHandler::BreakpointItem::icon() const
|
|
|
|
|
{
|
|
|
|
|
// FIXME: This seems to be called on each cursor blink as soon as the
|
|
|
|
|
// cursor is near a line with a breakpoint marker (+/- 2 lines or so).
|
2010-12-16 13:02:59 +01:00
|
|
|
if (data.isTracepoint())
|
|
|
|
|
return BreakHandler::tracepointIcon();
|
2011-05-09 08:35:58 +02:00
|
|
|
if (data.type == WatchpointAtAddress)
|
2010-11-26 12:30:05 +01:00
|
|
|
return BreakHandler::watchpointIcon();
|
2011-05-10 15:57:33 +02:00
|
|
|
if (data.type == WatchpointAtExpression)
|
|
|
|
|
return BreakHandler::watchpointIcon();
|
2010-11-18 14:57:00 +01:00
|
|
|
if (!data.enabled)
|
|
|
|
|
return BreakHandler::disabledBreakpointIcon();
|
|
|
|
|
if (state == BreakpointInserted)
|
|
|
|
|
return BreakHandler::breakpointIcon();
|
2010-11-26 12:30:05 +01:00
|
|
|
return BreakHandler::pendingBreakpointIcon();
|
2010-11-18 14:57:00 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-15 14:27:06 +01:00
|
|
|
QString BreakHandler::BreakpointItem::toToolTip() const
|
|
|
|
|
{
|
|
|
|
|
QString rc;
|
|
|
|
|
QTextStream str(&rc);
|
|
|
|
|
str << "<html><body><table>"
|
2011-09-26 16:48:54 +02:00
|
|
|
//<< "<tr><td>" << tr("ID:") << "</td><td>" << m_id << "</td></tr>"
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "<tr><td>" << tr("State:")
|
2011-02-03 16:26:23 +01:00
|
|
|
<< "</td><td>" << (data.enabled ? tr("Enabled") : tr("Disabled"));
|
|
|
|
|
if (response.pending)
|
|
|
|
|
str << tr(", pending");
|
|
|
|
|
str << ", " << state << " (" << stateToString(state) << ")</td></tr>";
|
|
|
|
|
if (engine) {
|
|
|
|
|
str << "<tr><td>" << tr("Engine:")
|
|
|
|
|
<< "</td><td>" << engine->objectName() << "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
if (!response.pending) {
|
|
|
|
|
str << "<tr><td>" << tr("Breakpoint Number:")
|
2011-06-21 16:45:23 +02:00
|
|
|
<< "</td><td>" << response.id.toString() << "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
|
|
|
|
str << "<tr><td>" << tr("Breakpoint Type:")
|
2011-06-24 16:25:30 +02:00
|
|
|
<< "</td><td>" << typeToString(data.type) << "</td></tr>"
|
|
|
|
|
<< "<tr><td>" << tr("Marker File:")
|
2011-02-03 16:26:23 +01:00
|
|
|
<< "</td><td>" << QDir::toNativeSeparators(markerFileName()) << "</td></tr>"
|
2010-11-18 16:00:56 +01:00
|
|
|
<< "<tr><td>" << tr("Marker Line:")
|
|
|
|
|
<< "</td><td>" << markerLineNumber() << "</td></tr>"
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "</table><br><hr><table>"
|
|
|
|
|
<< "<tr><th>" << tr("Property")
|
|
|
|
|
<< "</th><th>" << tr("Requested")
|
|
|
|
|
<< "</th><th>" << tr("Obtained") << "</th></tr>"
|
|
|
|
|
<< "<tr><td>" << tr("Internal Number:")
|
2011-06-21 16:45:23 +02:00
|
|
|
<< "</td><td>—</td><td>" << response.id.toString() << "</td></tr>";
|
2011-02-02 14:41:14 +01:00
|
|
|
if (data.type == BreakpointByFunction) {
|
|
|
|
|
str << "<tr><td>" << tr("Function Name:")
|
2010-11-18 13:38:58 +01:00
|
|
|
<< "</td><td>" << data.functionName
|
|
|
|
|
<< "</td><td>" << response.functionName
|
2011-02-02 14:41:14 +01:00
|
|
|
<< "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
if (data.type == BreakpointByFileAndLine) {
|
|
|
|
|
str << "<tr><td>" << tr("File Name:")
|
2010-11-16 11:48:17 +01:00
|
|
|
<< "</td><td>" << QDir::toNativeSeparators(data.fileName)
|
2010-11-15 17:04:29 +01:00
|
|
|
<< "</td><td>" << QDir::toNativeSeparators(response.fileName)
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "</td></tr>"
|
2010-11-18 13:38:58 +01:00
|
|
|
<< "<tr><td>" << tr("Line Number:")
|
|
|
|
|
<< "</td><td>" << data.lineNumber
|
|
|
|
|
<< "</td><td>" << response.lineNumber << "</td></tr>"
|
2011-01-05 19:30:24 +01:00
|
|
|
<< "<tr><td>" << tr("Corrected Line Number:")
|
|
|
|
|
<< "</td><td>-"
|
2011-02-02 14:41:14 +01:00
|
|
|
<< "</td><td>" << response.correctedLineNumber << "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
if (data.type == BreakpointByFunction || data.type == BreakpointByFileAndLine) {
|
|
|
|
|
str << "<tr><td>" << tr("Module:")
|
|
|
|
|
<< "</td><td>" << data.module
|
|
|
|
|
<< "</td><td>" << response.module
|
|
|
|
|
<< "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
str << "<tr><td>" << tr("Breakpoint Address:")
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "</td><td>";
|
2010-11-16 11:48:17 +01:00
|
|
|
formatAddress(str, data.address);
|
2010-11-15 14:27:06 +01:00
|
|
|
str << "</td><td>";
|
2010-11-15 17:04:29 +01:00
|
|
|
formatAddress(str, response.address);
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "</td></tr>";
|
|
|
|
|
if (response.multiple) {
|
|
|
|
|
str << "<tr><td>" << tr("Multiple Addresses:")
|
2011-06-21 16:45:23 +02:00
|
|
|
<< "</td><td>"
|
|
|
|
|
<< "</td></tr>";
|
2011-03-02 13:37:29 +01:00
|
|
|
}
|
2011-02-04 11:33:45 +01:00
|
|
|
if (!data.command.isEmpty() || !response.command.isEmpty()) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Command:")
|
2011-02-04 11:33:45 +01:00
|
|
|
<< "</td><td>" << data.command
|
2011-03-02 13:37:29 +01:00
|
|
|
<< "</td><td>" << response.command
|
|
|
|
|
<< "</td></tr>";
|
2011-02-04 11:33:45 +01:00
|
|
|
}
|
2011-06-27 10:37:57 +02:00
|
|
|
if (!data.message.isEmpty() || !response.message.isEmpty()) {
|
|
|
|
|
str << "<tr><td>" << tr("Message:")
|
|
|
|
|
<< "</td><td>" << data.message
|
|
|
|
|
<< "</td><td>" << response.message
|
|
|
|
|
<< "</td></tr>";
|
|
|
|
|
}
|
2011-02-03 16:26:23 +01:00
|
|
|
if (!data.condition.isEmpty() || !response.condition.isEmpty()) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Condition:")
|
2011-02-03 16:26:23 +01:00
|
|
|
<< "</td><td>" << data.condition
|
2011-03-02 13:37:29 +01:00
|
|
|
<< "</td><td>" << response.condition
|
|
|
|
|
<< "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
|
|
|
|
if (data.ignoreCount || response.ignoreCount) {
|
|
|
|
|
str << "<tr><td>" << tr("Ignore Count:") << "</td><td>";
|
|
|
|
|
if (data.ignoreCount)
|
|
|
|
|
str << data.ignoreCount;
|
|
|
|
|
str << "</td><td>";
|
|
|
|
|
if (response.ignoreCount)
|
|
|
|
|
str << response.ignoreCount;
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
|
|
|
|
if (data.threadSpec >= 0 || response.threadSpec >= 0) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Thread Specification:")
|
2011-02-03 16:26:23 +01:00
|
|
|
<< "</td><td>";
|
|
|
|
|
if (data.threadSpec >= 0)
|
|
|
|
|
str << data.threadSpec;
|
|
|
|
|
str << "</td><td>";
|
|
|
|
|
if (response.threadSpec >= 0)
|
|
|
|
|
str << response.threadSpec;
|
|
|
|
|
str << "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
str << "</table></body></html>";
|
2010-11-15 14:27:06 +01:00
|
|
|
return rc;
|
2010-11-15 13:12:13 +01:00
|
|
|
}
|
|
|
|
|
|
2012-06-03 21:59:21 +02:00
|
|
|
void BreakHandler::setWatchpointAtAddress(quint64 address, unsigned size)
|
|
|
|
|
{
|
|
|
|
|
BreakpointParameters data(WatchpointAtAddress);
|
|
|
|
|
data.address = address;
|
|
|
|
|
data.size = size;
|
|
|
|
|
BreakpointModelId id = findWatchpoint(data);
|
|
|
|
|
if (id) {
|
|
|
|
|
qDebug() << "WATCHPOINT EXISTS";
|
|
|
|
|
// removeBreakpoint(index);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::setWatchpointAtExpression(const QString &exp)
|
|
|
|
|
{
|
|
|
|
|
BreakpointParameters data(WatchpointAtExpression);
|
|
|
|
|
data.expression = exp;
|
|
|
|
|
BreakpointModelId id = findWatchpoint(data);
|
|
|
|
|
if (id) {
|
|
|
|
|
qDebug() << "WATCHPOINT EXISTS";
|
|
|
|
|
// removeBreakpoint(index);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Debugger
|