From 8f9a03bfb481e383ecc0e6d3bbcfa484b3448235 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 4 Mar 2011 12:15:18 +0100 Subject: [PATCH] Add libvalgrind. Merge-request: 260 Reviewed-by: hjk --- src/libs/libs.pro | 5 + src/libs/valgrind/memcheck/memcheckrunner.cpp | 140 +++++ src/libs/valgrind/memcheck/memcheckrunner.h | 88 +++ src/libs/valgrind/valgrind.pri | 1 + src/libs/valgrind/valgrind.pro | 42 ++ src/libs/valgrind/valgrind_global.h | 47 ++ src/libs/valgrind/valgrindprocess.cpp | 146 +++++ src/libs/valgrind/valgrindprocess.h | 114 ++++ src/libs/valgrind/valgrindrunner.cpp | 253 ++++++++ src/libs/valgrind/valgrindrunner.h | 108 ++++ src/libs/valgrind/xmlprotocol/announcethread.cpp | 109 ++++ src/libs/valgrind/xmlprotocol/announcethread.h | 75 +++ src/libs/valgrind/xmlprotocol/error.cpp | 263 ++++++++ src/libs/valgrind/xmlprotocol/error.h | 150 +++++ src/libs/valgrind/xmlprotocol/errorlistmodel.cpp | 303 +++++++++ src/libs/valgrind/xmlprotocol/errorlistmodel.h | 113 ++++ src/libs/valgrind/xmlprotocol/frame.cpp | 162 +++++ src/libs/valgrind/xmlprotocol/frame.h | 85 +++ src/libs/valgrind/xmlprotocol/modelhelpers.cpp | 82 +++ src/libs/valgrind/xmlprotocol/modelhelpers.h | 57 ++ src/libs/valgrind/xmlprotocol/parser.cpp | 749 +++++++++++++++++++++++ src/libs/valgrind/xmlprotocol/parser.h | 95 +++ src/libs/valgrind/xmlprotocol/stack.cpp | 159 +++++ src/libs/valgrind/xmlprotocol/stack.h | 89 +++ src/libs/valgrind/xmlprotocol/stackmodel.cpp | 237 +++++++ src/libs/valgrind/xmlprotocol/stackmodel.h | 94 +++ src/libs/valgrind/xmlprotocol/status.cpp | 105 ++++ src/libs/valgrind/xmlprotocol/status.h | 82 +++ src/libs/valgrind/xmlprotocol/suppression.cpp | 245 ++++++++ src/libs/valgrind/xmlprotocol/suppression.h | 113 ++++ src/libs/valgrind/xmlprotocol/threadedparser.cpp | 153 +++++ src/libs/valgrind/xmlprotocol/threadedparser.h | 94 +++ 32 files changed, 4558 insertions(+) create mode 100644 src/libs/valgrind/memcheck/memcheckrunner.cpp create mode 100644 src/libs/valgrind/memcheck/memcheckrunner.h create mode 100644 src/libs/valgrind/valgrind.pri create mode 100644 src/libs/valgrind/valgrind.pro create mode 100644 src/libs/valgrind/valgrind_global.h create mode 100644 src/libs/valgrind/valgrindprocess.cpp create mode 100644 src/libs/valgrind/valgrindprocess.h create mode 100644 src/libs/valgrind/valgrindrunner.cpp create mode 100644 src/libs/valgrind/valgrindrunner.h create mode 100644 src/libs/valgrind/xmlprotocol/announcethread.cpp create mode 100644 src/libs/valgrind/xmlprotocol/announcethread.h create mode 100644 src/libs/valgrind/xmlprotocol/error.cpp create mode 100644 src/libs/valgrind/xmlprotocol/error.h create mode 100644 src/libs/valgrind/xmlprotocol/errorlistmodel.cpp create mode 100644 src/libs/valgrind/xmlprotocol/errorlistmodel.h create mode 100644 src/libs/valgrind/xmlprotocol/frame.cpp create mode 100644 src/libs/valgrind/xmlprotocol/frame.h create mode 100644 src/libs/valgrind/xmlprotocol/modelhelpers.cpp create mode 100644 src/libs/valgrind/xmlprotocol/modelhelpers.h create mode 100644 src/libs/valgrind/xmlprotocol/parser.cpp create mode 100644 src/libs/valgrind/xmlprotocol/parser.h create mode 100644 src/libs/valgrind/xmlprotocol/stack.cpp create mode 100644 src/libs/valgrind/xmlprotocol/stack.h create mode 100644 src/libs/valgrind/xmlprotocol/stackmodel.cpp create mode 100644 src/libs/valgrind/xmlprotocol/stackmodel.h create mode 100644 src/libs/valgrind/xmlprotocol/status.cpp create mode 100644 src/libs/valgrind/xmlprotocol/status.h create mode 100644 src/libs/valgrind/xmlprotocol/suppression.cpp create mode 100644 src/libs/valgrind/xmlprotocol/suppression.h create mode 100644 src/libs/valgrind/xmlprotocol/threadedparser.cpp create mode 100644 src/libs/valgrind/xmlprotocol/threadedparser.h diff --git a/src/libs/libs.pro b/src/libs/libs.pro index f33e687774..3e34c766e5 100644 --- a/src/libs/libs.pro +++ b/src/libs/libs.pro @@ -16,6 +16,11 @@ SUBDIRS = \ qmleditorwidgets \ symbianutils + +!win32 { + SUBDIRS += valgrind +} + # Windows: Compile Qt Creator CDB extension if Debugging tools can be detected. win32 { include(qtcreatorcdbext/cdb_detect.pri) diff --git a/src/libs/valgrind/memcheck/memcheckrunner.cpp b/src/libs/valgrind/memcheck/memcheckrunner.cpp new file mode 100644 index 0000000000..00fefe9413 --- /dev/null +++ b/src/libs/valgrind/memcheck/memcheckrunner.cpp @@ -0,0 +1,140 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "memcheckrunner.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace Valgrind::Memcheck; + +class MemcheckRunner::Private +{ +public: + explicit Private() + : parser(0), + logSocket(0) + { + } + + QTcpServer xmlServer; + XmlProtocol::ThreadedParser *parser; + QTcpServer logServer; + QTcpSocket *logSocket; +}; + +MemcheckRunner::MemcheckRunner(QObject *parent) + : ValgrindRunner(parent), + d(new Private) +{ +} + +MemcheckRunner::~MemcheckRunner() +{ + if (d->parser->isRunning()) { + // make sure we don't delete the thread while it's still running + waitForFinished(); + } + delete d; + d = 0; +} + +QString MemcheckRunner::tool() const +{ + return QString("memcheck"); +} + +void MemcheckRunner::setParser(XmlProtocol::ThreadedParser *parser) +{ + QTC_ASSERT(!d->parser, qt_noop()); + d->parser = parser; +} + +void MemcheckRunner::start() +{ + QTC_ASSERT(d->parser, return); + + bool check = d->xmlServer.listen(QHostAddress(QHostAddress::LocalHost)); + QTC_ASSERT(check, return); + d->xmlServer.setMaxPendingConnections(1); + const quint16 xmlPortNumber = d->xmlServer.serverPort(); + connect(&d->xmlServer, SIGNAL(newConnection()), SLOT(xmlSocketConnected())); + + check = d->logServer.listen(QHostAddress(QHostAddress::LocalHost)); + QTC_ASSERT(check, return); + d->logServer.setMaxPendingConnections(1); + const quint16 logPortNumber = d->logServer.serverPort(); + connect(&d->logServer, SIGNAL(newConnection()), SLOT(logSocketConnected())); + + QStringList memcheckArguments; + memcheckArguments << QString("--xml=yes") + << QString("--xml-socket=127.0.0.1:%1").arg(QString::number(xmlPortNumber)) + << QString("--child-silent-after-fork=yes") + << QString("--log-socket=127.0.0.1:%1").arg(QString::number(logPortNumber)) + << valgrindArguments(); + setValgrindArguments(memcheckArguments); + + ValgrindRunner::start(); +} + +void MemcheckRunner::xmlSocketConnected() +{ + QTcpSocket *socket = d->xmlServer.nextPendingConnection(); + QTC_ASSERT(socket, return); + d->xmlServer.close(); + d->parser->parse(socket); +} + +void MemcheckRunner::logSocketConnected() +{ + d->logSocket = d->logServer.nextPendingConnection(); + QTC_ASSERT(d->logSocket, return); + connect(d->logSocket, SIGNAL(readyRead()), + this, SLOT(readLogSocket())); + d->logServer.close(); +} + +void MemcheckRunner::readLogSocket() +{ + emit logMessageReceived(d->logSocket->readAll()); +} diff --git a/src/libs/valgrind/memcheck/memcheckrunner.h b/src/libs/valgrind/memcheck/memcheckrunner.h new file mode 100644 index 0000000000..5884f6d11b --- /dev/null +++ b/src/libs/valgrind/memcheck/memcheckrunner.h @@ -0,0 +1,88 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef VALGRIND_PROTOCOL_MEMCHECKRUNNER_H +#define VALGRIND_PROTOCOL_MEMCHECKRUNNER_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QProcessEnvironment; +QT_END_NAMESPACE + +namespace Utils { +class Environment; +} + +namespace Valgrind { +namespace XmlProtocol{ +class ThreadedParser; +} + +namespace Memcheck { + +class VALGRINDSHARED_EXPORT MemcheckRunner : public ValgrindRunner +{ + Q_OBJECT + +public: + explicit MemcheckRunner(QObject *parent = 0); + ~MemcheckRunner(); + + void setParser(XmlProtocol::ThreadedParser *parser); + + void start(); + +signals: + void logMessageReceived(const QByteArray &); + +private slots: + void xmlSocketConnected(); + void logSocketConnected(); + void readLogSocket(); +private: + QString tool() const; + + Q_DISABLE_COPY(MemcheckRunner); + class Private; + Private *d; +}; + +} + +} + +#endif // VALGRIND_PROTOCOL_MEMCHECKRUNNER_H diff --git a/src/libs/valgrind/valgrind.pri b/src/libs/valgrind/valgrind.pri new file mode 100644 index 0000000000..7647eeacb0 --- /dev/null +++ b/src/libs/valgrind/valgrind.pri @@ -0,0 +1 @@ +LIBS *= -l$$qtLibraryName(Valgrind) diff --git a/src/libs/valgrind/valgrind.pro b/src/libs/valgrind/valgrind.pro new file mode 100644 index 0000000000..cc795b2ba3 --- /dev/null +++ b/src/libs/valgrind/valgrind.pro @@ -0,0 +1,42 @@ +TEMPLATE = lib +TARGET = Valgrind + +include(../../qtcreatorlibrary.pri) +include(../utils/utils.pri) + +TEMPLATE = lib + +DEFINES += VALGRIND_LIBRARY + +QT += network + +HEADERS += valgrind_global.h \ + xmlprotocol/frame.h \ + xmlprotocol/parser.h \ + xmlprotocol/error.h \ + xmlprotocol/status.h \ + xmlprotocol/suppression.h \ + xmlprotocol/threadedparser.h \ + xmlprotocol/announcethread.h \ + xmlprotocol/stack.h \ + xmlprotocol/errorlistmodel.h \ + xmlprotocol/stackmodel.h \ + xmlprotocol/modelhelpers.h \ + memcheck/memcheckrunner.h \ + valgrindrunner.h \ + valgrindprocess.h + +SOURCES += xmlprotocol/error.cpp \ + xmlprotocol/frame.cpp \ + xmlprotocol/parser.cpp \ + xmlprotocol/status.cpp \ + xmlprotocol/suppression.cpp \ + xmlprotocol/threadedparser.cpp \ + xmlprotocol/announcethread.cpp \ + xmlprotocol/stack.cpp \ + xmlprotocol/errorlistmodel.cpp \ + xmlprotocol/stackmodel.cpp \ + xmlprotocol/modelhelpers.cpp \ + memcheck/memcheckrunner.cpp \ + valgrindrunner.cpp \ + valgrindprocess.cpp diff --git a/src/libs/valgrind/valgrind_global.h b/src/libs/valgrind/valgrind_global.h new file mode 100644 index 0000000000..1c0ec531e5 --- /dev/null +++ b/src/libs/valgrind/valgrind_global.h @@ -0,0 +1,47 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef VALGRIND_GLOBAL_H +#define VALGRIND_GLOBAL_H + +#include + +#if defined(VALGRIND_LIBRARY) +# define VALGRINDSHARED_EXPORT Q_DECL_EXPORT +#else +# define VALGRINDSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // VALGRIND_GLOBAL_H diff --git a/src/libs/valgrind/valgrindprocess.cpp b/src/libs/valgrind/valgrindprocess.cpp new file mode 100644 index 0000000000..1731c80d30 --- /dev/null +++ b/src/libs/valgrind/valgrindprocess.cpp @@ -0,0 +1,146 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "valgrindprocess.h" + +#include +#include +#include + +namespace Valgrind { +namespace Internal { + +ValgrindProcess::ValgrindProcess(QObject *parent) +: QObject(parent) +{ + +} + +ValgrindProcess::~ValgrindProcess() +{ + +} + +//////////////////////// + +LocalValgrindProcess::LocalValgrindProcess(QObject *parent) +: ValgrindProcess(parent) +{ + connect(&m_process, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SIGNAL(finished(int, QProcess::ExitStatus))); + connect(&m_process, SIGNAL(started()), + this, SIGNAL(started())); + connect(&m_process, SIGNAL(error(QProcess::ProcessError)), + this, SIGNAL(error(QProcess::ProcessError))); + connect(&m_process, SIGNAL(readyReadStandardError()), + this, SLOT(readyReadStandardError())); + connect(&m_process, SIGNAL(readyReadStandardOutput()), + this, SLOT(readyReadStandardOutput())); +} + +LocalValgrindProcess::~LocalValgrindProcess() +{ + +} + +void LocalValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) +{ + m_process.setProcessChannelMode(mode); +} + +void LocalValgrindProcess::setWorkingDirectory(const QString &path) +{ + m_process.setWorkingDirectory(path); +} + +bool LocalValgrindProcess::isRunning() const +{ + return m_process.state() != QProcess::NotRunning; +} + +void LocalValgrindProcess::setEnvironment(const Utils::Environment &environment) +{ + m_process.setEnvironment(environment); +} + +void LocalValgrindProcess::close() +{ + m_process.close(); + m_process.waitForFinished(-1); +} + +void LocalValgrindProcess::run(const QString &valgrindExecutable, const QStringList &valgrindArguments, + const QString &debuggeeExecutable, const QString &debuggeeArguments) +{ + QString arguments; + Utils::QtcProcess::addArgs(&arguments, valgrindArguments); + Utils::QtcProcess::addArg(&arguments, debuggeeExecutable); + Utils::QtcProcess::addArgs(&arguments, debuggeeArguments); + m_process.setCommand(valgrindExecutable, arguments); + m_process.start(); + m_process.waitForStarted(); +} + +QString LocalValgrindProcess::errorString() const +{ + return m_process.errorString(); +} + +QProcess::ProcessError LocalValgrindProcess::error() const +{ + return m_process.error(); +} + +Q_PID LocalValgrindProcess::pid() const +{ + return m_process.pid(); +} + +void LocalValgrindProcess::readyReadStandardError() +{ + const QByteArray b = m_process.readAllStandardError(); + if (!b.isEmpty()) + emit standardErrorReceived(b); +} + +void LocalValgrindProcess::readyReadStandardOutput() +{ + const QByteArray b = m_process.readAllStandardOutput(); + if (!b.isEmpty()) + emit standardOutputReceived(b); +} + +} +} diff --git a/src/libs/valgrind/valgrindprocess.h b/src/libs/valgrind/valgrindprocess.h new file mode 100644 index 0000000000..496753bc25 --- /dev/null +++ b/src/libs/valgrind/valgrindprocess.h @@ -0,0 +1,114 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef VALGRIND_RUNNER_P_H +#define VALGRIND_RUNNER_P_H + +#include + +namespace Valgrind { +namespace Internal { + +/** + * Abstract process that can be subclassed to supply local and remote valgrind runs + */ +class ValgrindProcess : public QObject +{ + Q_OBJECT +public: + explicit ValgrindProcess(QObject *parent = 0); + virtual ~ValgrindProcess(); + + virtual bool isRunning() const = 0; + + virtual void run(const QString &valgrindExecutable, const QStringList &valgrindArguments, + const QString &debuggeeExecutable, const QString &debuggeeArguments) = 0; + virtual void close() = 0; + + virtual QString errorString() const = 0; + virtual QProcess::ProcessError error() const = 0; + + virtual void setProcessChannelMode(QProcess::ProcessChannelMode mode) = 0; + virtual void setWorkingDirectory(const QString &path) = 0; + virtual void setEnvironment(const Utils::Environment &environment) = 0; + +signals: + void started(); + void finished(int, QProcess::ExitStatus); + void error(QProcess::ProcessError); + void standardOutputReceived(const QByteArray &); + void standardErrorReceived(const QByteArray &); +}; + +/** + * Run valgrind on the local machine + */ +class LocalValgrindProcess : public ValgrindProcess +{ + Q_OBJECT + +public: + explicit LocalValgrindProcess(QObject *parent = 0); + virtual ~LocalValgrindProcess(); + + virtual bool isRunning() const; + + virtual void run(const QString &valgrindExecutable, const QStringList &valgrindArguments, + const QString &debuggeeExecutable, const QString &debuggeeArguments); + virtual void close(); + + virtual QString errorString() const; + QProcess::ProcessError error() const; + + virtual void setProcessChannelMode(QProcess::ProcessChannelMode mode); + virtual void setWorkingDirectory(const QString &path); + virtual void setEnvironment(const Utils::Environment &environment); + + Q_PID pid() const; + +private slots: + void readyReadStandardError(); + void readyReadStandardOutput(); + +private: + Utils::QtcProcess m_process; +}; + +// remote support will be supplied later + +} +} + +#endif // VALGRIND_RUNNER_P_H diff --git a/src/libs/valgrind/valgrindrunner.cpp b/src/libs/valgrind/valgrindrunner.cpp new file mode 100644 index 0000000000..12bacc4de3 --- /dev/null +++ b/src/libs/valgrind/valgrindrunner.cpp @@ -0,0 +1,253 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "valgrindrunner.h" +#include "valgrindprocess.h" + +#include + +#include + +#include + +using namespace Valgrind; + +class ValgrindRunner::Private +{ +public: + explicit Private(ValgrindRunner *qq) + : q(qq), + process(0), + channelMode(QProcess::SeparateChannels), + finished(false), + lastPid(0) + { + } + + void run(Internal::ValgrindProcess *process); + + ValgrindRunner *q; + Internal::ValgrindProcess *process; + Utils::Environment environment; + QProcess::ProcessChannelMode channelMode; + bool finished; + Q_PID lastPid; + QString valgrindExecutable; + QStringList valgrindArguments; + QString debuggeeExecutable; + QString debuggeeArguments; + QString workingdir; +}; + +void ValgrindRunner::Private::run(Internal::ValgrindProcess *_process) +{ + if (process && process->isRunning()) { + process->close(); + process->disconnect(q); + process->deleteLater(); + } + + lastPid = 0; + QTC_ASSERT(_process, return); + + process = _process; + + if (environment.size() > 0) + process->setEnvironment(environment); + + process->setWorkingDirectory(workingdir); + process->setProcessChannelMode(channelMode); + // consider appending our options last so they override any interfering user-supplied options + // -q as suggested by valgrind manual + QStringList valgrindArgs = valgrindArguments; + valgrindArgs << QString("--tool=%1").arg(q->tool()); + + QObject::connect(process, SIGNAL(standardOutputReceived(QByteArray)), + q, SIGNAL(standardOutputReceived(QByteArray))); + QObject::connect(process, SIGNAL(standardErrorReceived(QByteArray)), + q, SIGNAL(standardErrorReceived(QByteArray))); + QObject::connect(process, SIGNAL(started()), + q, SLOT(processStarted())); + QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), + q, SLOT(processFinished(int, QProcess::ExitStatus))); + QObject::connect(process, SIGNAL(error(QProcess::ProcessError)), + q, SLOT(processError(QProcess::ProcessError))); + + process->run(valgrindExecutable, valgrindArgs, debuggeeExecutable, debuggeeArguments); +} + +ValgrindRunner::ValgrindRunner(QObject *parent) + : QObject(parent), + d(new Private(this)) +{ +} + +ValgrindRunner::~ValgrindRunner() +{ + if (d->process && d->process->isRunning()) { + // make sure we don't delete the thread while it's still running + waitForFinished(); + } + delete d; + d = 0; +} + +void ValgrindRunner::setValgrindExecutable(const QString &executable) +{ + d->valgrindExecutable = executable; +} + +QString ValgrindRunner::valgrindExecutable() const +{ + return d->valgrindExecutable; +} + +void ValgrindRunner::setValgrindArguments(const QStringList &toolArguments) +{ + d->valgrindArguments = toolArguments; +} + +QStringList ValgrindRunner::valgrindArguments() const +{ + return d->valgrindArguments; +} + +QString ValgrindRunner::debuggeeExecutable() const +{ + return d->debuggeeExecutable; +} + +void ValgrindRunner::setDebuggeeExecutable(const QString &executable) +{ + d->debuggeeExecutable = executable; +} + +QString ValgrindRunner::debuggeArguments() const +{ + return d->debuggeeArguments; +} + +void ValgrindRunner::setDebuggeeArguments(const QString &arguments) +{ + d->debuggeeArguments = arguments; +} + +void ValgrindRunner::setWorkingDirectory(const QString &path) +{ + d->workingdir = path; +} + +QString ValgrindRunner::workingDirectory() const +{ + return d->workingdir; +} + +void ValgrindRunner::setEnvironment(const Utils::Environment &environment) +{ + d->environment = environment; +} + +void ValgrindRunner::setProcessChannelMode(QProcess::ProcessChannelMode mode) +{ + d->channelMode = mode; +} + +void ValgrindRunner::waitForFinished() const +{ + if (d->finished || !d->process) + return; + + QEventLoop loop; + connect(this, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(); +} + +void ValgrindRunner::start() +{ + d->run(new Internal::LocalValgrindProcess(this)); +} + +void ValgrindRunner::processError(QProcess::ProcessError e) +{ + if (d->finished) + return; + + d->finished = true; + + // make sure we don't wait for the connection anymore + emit processErrorReceived(errorString(), e); + emit finished(); +} + +void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status) +{ + if (d->finished) + return; + + d->finished = true; + + // make sure we don't wait for the connection anymore + emit finished(); + + if (ret != 0 || status == QProcess::CrashExit) + emit processErrorReceived(errorString(), d->process->error()); +} + +void ValgrindRunner::processStarted() +{ + if (Internal::LocalValgrindProcess *process = dynamic_cast(d->process)) + d->lastPid = process->pid(); + + emit started(); +} + +Q_PID ValgrindRunner::lastPid() const +{ + return d->lastPid; +} + +QString ValgrindRunner::errorString() const +{ + if (d->process) + return d->process->errorString(); + else + return QString(); +} + +void ValgrindRunner::stop() +{ + if (d->process) + d->process->close(); +} \ No newline at end of file diff --git a/src/libs/valgrind/valgrindrunner.h b/src/libs/valgrind/valgrindrunner.h new file mode 100644 index 0000000000..9d7a1eb74a --- /dev/null +++ b/src/libs/valgrind/valgrindrunner.h @@ -0,0 +1,108 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef VALGRIND_RUNNER_H +#define VALGRIND_RUNNER_H + +#include + +#include "valgrind_global.h" + +QT_BEGIN_NAMESPACE +class QProcessEnvironment; +QT_END_NAMESPACE + +namespace Utils { +class Environment; +} + +namespace Valgrind { + +class VALGRINDSHARED_EXPORT ValgrindRunner : public QObject +{ + Q_OBJECT + +public: + explicit ValgrindRunner(QObject *parent = 0); + ~ValgrindRunner(); + + QString valgrindExecutable() const; + void setValgrindExecutable(const QString &executable); + QStringList valgrindArguments() const; + void setValgrindArguments(const QStringList &toolArguments); + QString debuggeeExecutable() const; + void setDebuggeeExecutable(const QString &executable); + QString debuggeArguments() const; + void setDebuggeeArguments(const QString &arguments); + + void setWorkingDirectory(const QString &path); + QString workingDirectory() const; + void setEnvironment(const Utils::Environment &environment); + void setProcessChannelMode(QProcess::ProcessChannelMode mode); + + void waitForFinished() const; + + QString errorString() const; + + virtual void start(); + + virtual void stop(); + +protected: + virtual QString tool() const = 0; + + Q_PID lastPid() const; + +signals: + void standardOutputReceived(const QByteArray &); + void standardErrorReceived(const QByteArray &); + void processErrorReceived(const QString &, QProcess::ProcessError); + void started(); + void finished(); + +protected slots: + virtual void processError(QProcess::ProcessError); + virtual void processStarted(); + virtual void processFinished(int, QProcess::ExitStatus); + +private: + Q_DISABLE_COPY(ValgrindRunner); + class Private; + Private *d; +}; + +} + +#endif // VALGRIND_RUNNER_H diff --git a/src/libs/valgrind/xmlprotocol/announcethread.cpp b/src/libs/valgrind/xmlprotocol/announcethread.cpp new file mode 100644 index 0000000000..2b96f348b7 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/announcethread.cpp @@ -0,0 +1,109 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "announcethread.h" +#include "frame.h" + +#include +#include + +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class AnnounceThread::Private : public QSharedData +{ +public: + Private() + : hThreadId( -1 ) + { + } + + qint64 hThreadId; + QVector stack; +}; + +AnnounceThread::AnnounceThread() + : d(new Private) +{ +} + +AnnounceThread::AnnounceThread(const AnnounceThread &other) + : d(other.d) +{ +} + +AnnounceThread::~AnnounceThread() +{ +} + +void AnnounceThread::swap(AnnounceThread &other) +{ + qSwap(d, other.d); +} + +AnnounceThread &AnnounceThread::operator=(const AnnounceThread &other) +{ + AnnounceThread tmp(other); + swap(tmp); + return *this; +} + +bool AnnounceThread::operator==(const AnnounceThread &other) const +{ + return d->stack == other.d->stack + && d->hThreadId == other.d->hThreadId; +} + +qint64 AnnounceThread::helgrindThreadId() const +{ + return d->hThreadId; +} + +void AnnounceThread::setHelgrindThreadId(qint64 id) +{ + d->hThreadId = id; +} + +QVector AnnounceThread::stack() const +{ + return d->stack; +} + +void AnnounceThread::setStack(const QVector &stack) +{ + d->stack = stack; +} diff --git a/src/libs/valgrind/xmlprotocol/announcethread.h b/src/libs/valgrind/xmlprotocol/announcethread.h new file mode 100644 index 0000000000..8c170efc45 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/announcethread.h @@ -0,0 +1,75 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_ANNOUNCETHREAD_H +#define LIBVALGRIND_PROTOCOL_ANNOUNCETHREAD_H + +#include "../valgrind_global.h" + +#include + +QT_BEGIN_NAMESPACE +template class QVector; +QT_END_NAMESPACE + +namespace Valgrind { +namespace XmlProtocol { + +class Frame; + +class VALGRINDSHARED_EXPORT AnnounceThread { +public: + AnnounceThread(); + AnnounceThread(const AnnounceThread &other); + ~AnnounceThread(); + AnnounceThread &operator=(const AnnounceThread &other); + void swap(AnnounceThread &other); + bool operator==(const AnnounceThread &other) const; + + qint64 helgrindThreadId() const; + void setHelgrindThreadId(qint64 id); + + QVector stack() const; + void setStack(const QVector &stack); + +private: + class Private; + QSharedDataPointer d; +}; + +} +} + +#endif // LIBVALGRIND_PROTOCOL_ANNOUNCETHREAD_H diff --git a/src/libs/valgrind/xmlprotocol/error.cpp b/src/libs/valgrind/xmlprotocol/error.cpp new file mode 100644 index 0000000000..c05869c932 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/error.cpp @@ -0,0 +1,263 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "error.h" +#include "frame.h" +#include "stack.h" +#include "suppression.h" + +#include +#include +#include +#include + +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class Error::Private : public QSharedData { +public: + explicit Private() : + unique(0), + tid(0), + kind(0), + leakedBytes(0), + leakedBlocks(0), + hThreadId(-1) + {} + + qint64 unique; + qint64 tid; + QString what; + int kind; + QVector stacks; + Suppression suppression; + quint64 leakedBytes; + qint64 leakedBlocks; + qint64 hThreadId; + + bool operator==(const Private &other) const + { + return unique == other.unique + && tid == other.tid + && what == other.what + && kind == other.kind + && stacks == other.stacks + && suppression == other.suppression + && leakedBytes == other.leakedBytes + && leakedBlocks == other.leakedBlocks + && hThreadId == other.hThreadId; + } +}; + +Error::Error() : + d(new Private) +{ +} + +Error::~Error() +{ +} + +Error::Error(const Error &other) : + d( other.d ) +{ +} + +void Error::swap(Error &other) +{ + qSwap(d, other.d); +} + +Error &Error::operator=(const Error &other) +{ + Error tmp(other); + swap(tmp); + return *this; +} + +bool Error::operator ==(const Error &other) const +{ + return *d == *other.d; +} + +bool Error::operator !=(const Error &other) const +{ + return !(*d == *other.d); +} + +Suppression Error::suppression() const +{ + return d->suppression; +} + +void Error::setSuppression(const Suppression &supp) +{ + d->suppression = supp; +} + +qint64 Error::unique() const +{ + return d->unique; +} + +void Error::setUnique(qint64 unique) +{ + d->unique = unique; +} + +qint64 Error::tid() const +{ + return d->tid; +} + +void Error::setTid(qint64 tid) +{ + d->tid = tid; +} + +quint64 Error::leakedBytes() const +{ + return d->leakedBytes; +} + +void Error::setLeakedBytes(quint64 l) +{ + d->leakedBytes = l; +} + +qint64 Error::leakedBlocks() const +{ + return d->leakedBlocks; +} + +void Error::setLeakedBlocks(qint64 b) +{ + d->leakedBlocks = b; +} + +QString Error::what() const +{ + return d->what; +} + +void Error::setWhat(const QString &what) +{ + d->what = what; +} + +int Error::kind() const +{ + return d->kind; +} + +void Error::setKind(int k) +{ + d->kind = k; +} + +QVector Error::stacks() const +{ + return d->stacks; +} + +void Error::setStacks(const QVector &stacks) +{ + d->stacks = stacks; +} + +void Error::setHelgrindThreadId(qint64 id) +{ + d->hThreadId = id; +} + +qint64 Error::helgrindThreadId() const +{ + return d->hThreadId; +} + +QString Error::toXml() const +{ + QString xml; + QTextStream stream(&xml); + stream << "\n"; + stream << " " << d->unique << "\n"; + stream << " " << d->tid << "\n"; + stream << " " << d->kind << "\n"; + if (d->leakedBlocks > 0 && d->leakedBytes > 0) { + stream << " \n" + << " " << d->what << "\n" + << " " << d->leakedBytes << "\n" + << " " << d->leakedBlocks << "\n" + << " \n"; + } else { + stream << " " << d->what << "\n"; + } + + foreach(const Stack &stack, d->stacks) { + if (!stack.auxWhat().isEmpty()) { + stream << " " << stack.auxWhat() << "\n"; + } + stream << " \n"; + + foreach(const Frame &frame, stack.frames()) { + stream << " \n"; + stream << " 0x" << QString::number(frame.instructionPointer(), 16) << "\n"; + if (!frame.object().isEmpty()) { + stream << " " << frame.object() << "\n"; + } + if (!frame.functionName().isEmpty()) { + stream << " " << frame.functionName() << "\n"; + } + if (!frame.directory().isEmpty()) { + stream << " " << frame.directory() << "\n"; + } + if (!frame.file().isEmpty()) { + stream << " " << frame.file() << "\n"; + } + if (!frame.line() == -1) { + stream << " " << frame.line() << ""; + } + stream << " \n"; + } + + stream << " \n"; + } + + stream << "\n"; + + return xml; +} diff --git a/src/libs/valgrind/xmlprotocol/error.h b/src/libs/valgrind/xmlprotocol/error.h new file mode 100644 index 0000000000..eabe1c75fa --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/error.h @@ -0,0 +1,150 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_ERROR_H +#define LIBVALGRIND_PROTOCOL_ERROR_H + +#include "../valgrind_global.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QString; +template class QVector; +QT_END_NAMESPACE + +namespace Valgrind { +namespace XmlProtocol { + +class Frame; +class Stack; +class Suppression; + +/** + * Error kinds, specific to memcheck + */ +enum MemcheckErrorKind { + InvalidFree, + MismatchedFree, + InvalidRead, + InvalidWrite, + InvalidJump, + Overlap, + InvalidMemPool, + UninitCondition, + UninitValue, + SyscallParam, + ClientCheck, + Leak_DefinitelyLost, + Leak_PossiblyLost, + Leak_StillReachable, + Leak_IndirectlyLost, + MemcheckErrorKindCount +}; + +enum PtrcheckErrorKind { + SorG, + Heap, + Arith, + SysParam +}; + +enum HelgrindErrorKind { + Race, + UnlockUnlocked, + UnlockForeign, + UnlockBogus, + PthAPIerror, + LockOrder, + Misc +}; + +class VALGRINDSHARED_EXPORT Error { +public: + + Error(); + ~Error(); + + Error(const Error &other); + + Error &operator=(const Error &other); + void swap(Error &other); + + bool operator==(const Error &other) const; + bool operator!=(const Error &other) const; + + qint64 unique() const; + void setUnique(qint64 unique); + + qint64 tid() const; + void setTid(qint64); + + QString what() const; + void setWhat(const QString &what); + + int kind() const; + void setKind(int kind); + + QVector stacks() const; + void setStacks(const QVector &stacks); + + Suppression suppression() const; + void setSuppression(const Suppression &suppression); + + //memcheck + quint64 leakedBytes() const; + void setLeakedBytes(quint64); + + qint64 leakedBlocks() const; + void setLeakedBlocks(qint64 blocks); + + //helgrind + qint64 helgrindThreadId() const; + void setHelgrindThreadId( qint64 threadId ); + + QString toXml() const; + +private: + class Private; + QSharedDataPointer d; +}; + +} // namespace XmlProtocol +} // namespace Valgrind + +Q_DECLARE_METATYPE(Valgrind::XmlProtocol::Error) + +#endif diff --git a/src/libs/valgrind/xmlprotocol/errorlistmodel.cpp b/src/libs/valgrind/xmlprotocol/errorlistmodel.cpp new file mode 100644 index 0000000000..599d52f083 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/errorlistmodel.cpp @@ -0,0 +1,303 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "errorlistmodel.h" +#include "error.h" +#include "frame.h" +#include "stack.h" +#include "modelhelpers.h" +#include + +#include +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class ErrorListModel::Private +{ +public: + QVector errors; + QVariant errorData(int row, int column, int role) const; + QSharedPointer relevantFrameFinder; + Frame findRelevantFrame(const Error &error) const; + QString formatAbsoluteFilePath(const Error &error) const; + QString formatLocation(const Error &error) const; + +}; + +ErrorListModel::ErrorListModel(QObject *parent) + : QAbstractItemModel(parent) + , d(new Private) +{ +} + +ErrorListModel::~ErrorListModel() +{ + delete d; +} + +QSharedPointer ErrorListModel::relevantFrameFinder() const +{ + return d->relevantFrameFinder; +} + +void ErrorListModel::setRelevantFrameFinder(const QSharedPointer &finder) +{ + d->relevantFrameFinder = finder; +} + +Frame ErrorListModel::findRelevantFrame(const Error &error) const +{ + return d->findRelevantFrame(error); +} + +QModelIndex ErrorListModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) { + QTC_ASSERT(parent.model() == this, qt_noop()); + return QModelIndex(); + } + return createIndex(row, column, 0); +} + +QModelIndex ErrorListModel::parent(const QModelIndex &child) const +{ + QTC_ASSERT(!child.isValid() || child.model() == this, return QModelIndex()); + return QModelIndex(); + +} + +Frame ErrorListModel::Private::findRelevantFrame(const Error &error) const +{ + if (relevantFrameFinder) + return relevantFrameFinder->findRelevant(error); + const QVector stacks = error.stacks(); + if (stacks.isEmpty()) + return Frame(); + const Stack &stack = stacks[0]; + const QVector frames = stack.frames(); + if (!frames.isEmpty()) + return frames.first(); + else + return Frame(); +} + +QString ErrorListModel::Private::formatAbsoluteFilePath(const Error &error) const +{ + const Frame f = findRelevantFrame(error); + if (!f.directory().isEmpty() && !f.file().isEmpty()) + return QString(f.directory() + QDir::separator() + f.file()); + else + return QString(); +} + +QString ErrorListModel::Private::formatLocation(const Error &error) const +{ + const Frame frame = findRelevantFrame(error); + const QString file = frame.file(); + if (!frame.functionName().isEmpty()) + return frame.functionName(); + if (!file.isEmpty()) { + const qint64 line = frame.line(); + if (line > 0) + return QString::fromLatin1("%1:%2").arg(file, QString::number(frame.line())); + else + return file; + } + return frame.object(); +} + +QVariant ErrorListModel::Private::errorData(int row, int column, int role) const +{ + if (row < 0 || row >= errors.size()) + return QVariant(); + const Error &error = errors[row]; + + const QVector stacks = error.stacks(); + const Stack stack = !stacks.isEmpty() ? stacks.first() : Stack(); + + if (error.stacks().count()) + switch(role) { + case Qt::DisplayRole: + { + switch (column) { + case WhatColumn: + return error.what(); + case LocationColumn: + return formatLocation(error); + case AbsoluteFilePathColumn: + return formatAbsoluteFilePath(error); + case LineColumn: + { + const qint64 line = findRelevantFrame(error).line(); + return line > 0 ? line : QVariant(); + } + case UniqueColumn: + return error.unique(); + case TidColumn: + return error.tid(); + case KindColumn: + return error.kind(); + case LeakedBlocksColumn: + return error.leakedBlocks(); + case LeakedBytesColumn: + return error.leakedBytes(); + case HelgrindThreadIdColumn: + return error.helgrindThreadId(); + default: + break; + } + } + case Qt::ToolTipRole: + { + return toolTipForFrame(findRelevantFrame(error)); + } + case ErrorRole: + return QVariant::fromValue(error); + case AbsoluteFilePathRole: + return formatAbsoluteFilePath(error); + case FileRole: + return findRelevantFrame(error).file(); + case LineRole: + { + const qint64 line = findRelevantFrame(error).line(); + return line > 0 ? line : QVariant(); + } + } + return QVariant(); +} + +QVariant ErrorListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + QTC_ASSERT(index.model() == this, return QVariant()); + + if (!index.parent().isValid()) + return d->errorData(index.row(), index.column(), role); + + return QVariant(); +} + +QVariant ErrorListModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || role != Qt::DisplayRole) + return QVariant(); + + switch (section) { + case WhatColumn: + return tr("What"); + case LocationColumn: + return tr("Location"); + case AbsoluteFilePathColumn: + return tr("File"); + case LineColumn: + return tr("Line"); + case UniqueColumn: + return tr("Unique"); + case TidColumn: + return tr("Thread ID"); + case KindColumn: + return tr("Kind"); + case LeakedBlocksColumn: + return tr("Leaked Blocks"); + case LeakedBytesColumn: + return tr("Leaked Bytes"); + case HelgrindThreadIdColumn: + return tr("Helgrind Thread ID"); + } + + return QVariant(); +} + +int ErrorListModel::rowCount(const QModelIndex &parent) const +{ + //root + if (!parent.isValid()) + return d->errors.count(); + + QTC_ASSERT(parent.model() == this, return 0); + + return 0; +} + +int ErrorListModel::columnCount(const QModelIndex &parent) const +{ + QTC_ASSERT(!parent.isValid() || parent.model() == this, return 0); + return ColumnCount; +} + +bool ErrorListModel::removeRows(int row, int count, const QModelIndex &parent) +{ + QTC_ASSERT(!parent.isValid() || parent.model() == this, return false); + + if (row < 0 || row + count > d->errors.size() || parent.isValid()) + return false; + + beginRemoveRows(parent, row, row + count); + d->errors.remove(row, count); + endRemoveRows(); + return true; +} + +void ErrorListModel::addError(const Error &error) +{ + beginInsertRows(QModelIndex(), d->errors.size(), d->errors.size()); + d->errors.push_back(error); + endInsertRows(); +} + +Error ErrorListModel::error(const QModelIndex &index) const +{ + if (!index.isValid()) + return Error(); + + QTC_ASSERT(index.model() == this, return Error()); + + const int r = index.row(); + if (r < 0 || r >= d->errors.size()) + return Error(); + else + return d->errors[r]; +} + +void ErrorListModel::clear() +{ + beginResetModel(); + d->errors.clear(); + endResetModel(); +} diff --git a/src/libs/valgrind/xmlprotocol/errorlistmodel.h b/src/libs/valgrind/xmlprotocol/errorlistmodel.h new file mode 100644 index 0000000000..ddf5296c76 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/errorlistmodel.h @@ -0,0 +1,113 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_ERRORLISTMODEL_H +#define LIBVALGRIND_PROTOCOL_ERRORLISTMODEL_H + +#include "../valgrind_global.h" + +#include +#include + +namespace Valgrind { +namespace XmlProtocol { + +class Error; +class Frame; + +class VALGRINDSHARED_EXPORT ErrorListModel : public QAbstractItemModel +{ + Q_OBJECT +public: + enum Column { + WhatColumn=0, + LocationColumn, + AbsoluteFilePathColumn, + LineColumn, + UniqueColumn, + TidColumn, + KindColumn, + LeakedBlocksColumn, + LeakedBytesColumn, + HelgrindThreadIdColumn, + ColumnCount + }; + + enum Role { + ErrorRole=Qt::UserRole, + AbsoluteFilePathRole, + FileRole, + LineRole + }; + + class RelevantFrameFinder + { + public: + virtual ~RelevantFrameFinder() {} + virtual Frame findRelevant(const Error &error) const = 0; + }; + + explicit ErrorListModel(QObject *parent=0); + ~ErrorListModel(); + + QSharedPointer relevantFrameFinder() const; + void setRelevantFrameFinder(const QSharedPointer &finder); + + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + + Error error(const QModelIndex &index) const; + + Frame findRelevantFrame(const Error &error) const; + + void clear(); + +public Q_SLOTS: + void addError(const Valgrind::XmlProtocol::Error &error); + +private: + class Private; + Private *const d; +}; + +} +} + +#endif // LIBVALGRIND_PROTOCOL_ERRORLISTMODEL_H diff --git a/src/libs/valgrind/xmlprotocol/frame.cpp b/src/libs/valgrind/xmlprotocol/frame.cpp new file mode 100644 index 0000000000..da2e5c40df --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/frame.cpp @@ -0,0 +1,162 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "frame.h" + +#include + +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class Frame::Private : public QSharedData { +public: + explicit Private() : + ip(0), line( -1 ) + {} + + bool operator==(const Private &other) const + { + return ip == other.ip + && object == other.object + && functionName == other.functionName + && file == other.file + && directory == other.directory + && line == other.line; + } + + quint64 ip; + QString object; + QString functionName; + QString file; + QString directory; + int line; +}; + +Frame::Frame() : d(new Private) +{ +} + +Frame::~Frame() +{ +} + +Frame::Frame(const Frame &other) : + d( other.d ) +{ +} + +Frame &Frame::operator=(const Frame &other) +{ + Frame tmp(other); + swap(tmp); + return *this; +} + +bool Frame::operator==( const Frame &other ) const +{ + return *d == *other.d; +} + +bool Frame::operator!=(const Frame &other) const +{ + return !(*this == other); +} + +void Frame::swap(Frame &other) +{ + qSwap(d, other.d); +} + +quint64 Frame::instructionPointer() const +{ + return d->ip; +} + +void Frame::setInstructionPointer(quint64 ip) +{ + d->ip = ip; +} + +QString Frame::object() const +{ + return d->object; +} + +void Frame::setObject(const QString &obj) +{ + d->object = obj; +} + +QString Frame::functionName() const +{ + return d->functionName; +} + +void Frame::setFunctionName(const QString &functionName) +{ + d->functionName = functionName; +} + +QString Frame::file() const +{ + return d->file; +} + +void Frame::setFile(const QString &file) +{ + d->file = file; +} + +QString Frame::directory() const +{ + return d->directory; +} + +void Frame::setDirectory(const QString &directory) +{ + d->directory = directory; +} + +int Frame::line() const +{ + return d->line; +} + +void Frame::setLine(int line) +{ + d->line = line; +} diff --git a/src/libs/valgrind/xmlprotocol/frame.h b/src/libs/valgrind/xmlprotocol/frame.h new file mode 100644 index 0000000000..2dd36cc336 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/frame.h @@ -0,0 +1,85 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_FRAME_H +#define LIBVALGRIND_PROTOCOL_FRAME_H + +#include "../valgrind_global.h" + +#include + +namespace Valgrind { +namespace XmlProtocol { + +class VALGRINDSHARED_EXPORT Frame +{ +public: + Frame(); + ~Frame(); + Frame(const Frame &other); + + Frame &operator=(const Frame &other); + void swap(Frame &other); + + bool operator==(const Frame &other) const; + bool operator!=(const Frame &other) const; + + quint64 instructionPointer() const; + void setInstructionPointer(quint64); + + QString object() const; + void setObject(const QString &obj); + + QString functionName() const; + void setFunctionName(const QString &functionName); + + QString file() const; + void setFile(const QString &file); + + QString directory() const; + void setDirectory(const QString &directory); + + int line() const; + void setLine(int line); + +private: + class Private; + QSharedDataPointer d; +}; + +} // namespace XmlProtocol +} // namespace Valgrind + +#endif diff --git a/src/libs/valgrind/xmlprotocol/modelhelpers.cpp b/src/libs/valgrind/xmlprotocol/modelhelpers.cpp new file mode 100644 index 0000000000..8e7ec3370b --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/modelhelpers.cpp @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "modelhelpers.h" + +#include +#include +#include + +#include "frame.h" + +namespace Valgrind { +namespace XmlProtocol { + +QString toolTipForFrame(const Frame &frame) +{ + QString location; + if (!frame.file().isEmpty()) { + location = frame.directory() + QDir::separator() + frame.file(); + if (frame.line() > 0) + location += ':' + QString::number(frame.line()); + } + + typedef QPair StringPair; + QList lines; + + if (!frame.functionName().isEmpty()) + lines << qMakePair(QObject::tr("Function:"), frame.functionName()); + if (!location.isEmpty()) + lines << qMakePair(QObject::tr("Location:"), location); + if (frame.instructionPointer()) + lines << qMakePair(QObject::tr("Instruction pointer:"), + QString("0x%1").arg(frame.instructionPointer(), 0, 16)); + if (!frame.object().isEmpty()) + lines << qMakePair(QObject::tr("Object:"), frame.object()); + + QString html = "" + "" + "\n" + "
"; + + foreach(const StringPair &pair, lines) + html += "
" + pair.first + "
" + pair.second + "
\n"; + + html += "
"; + return html; +} + +} +} \ No newline at end of file diff --git a/src/libs/valgrind/xmlprotocol/modelhelpers.h b/src/libs/valgrind/xmlprotocol/modelhelpers.h new file mode 100644 index 0000000000..f22dba2543 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/modelhelpers.h @@ -0,0 +1,57 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_MODELHELPERS_H +#define LIBVALGRIND_PROTOCOL_MODELHELPERS_H + +#include + +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE + +#include "../valgrind_global.h" + +namespace Valgrind { +namespace XmlProtocol { + +class Frame; + +VALGRINDSHARED_EXPORT QString toolTipForFrame(const Frame &frame); + +} +} + +#endif // LIBVALGRIND_PROTOCOL_MODELHELPERS_H diff --git a/src/libs/valgrind/xmlprotocol/parser.cpp b/src/libs/valgrind/xmlprotocol/parser.cpp new file mode 100644 index 0000000000..d7b994c460 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/parser.cpp @@ -0,0 +1,749 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "parser.h" +#include "announcethread.h" +#include "error.h" +#include "frame.h" +#include "stack.h" +#include "status.h" +#include "suppression.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +namespace { + class Exception { + public: + explicit Exception(const QString &msg) + : m_message(msg) + { + } + + ~Exception() throw() {} + + QString message() const + { + return m_message; + } + + private: + QString m_message; + }; + + class ParserException : public Exception { + public: + explicit ParserException(const QString &message) + : Exception(message) + { + } + + ~ParserException() throw() {} + }; + + struct XWhat { + XWhat() : leakedblocks(0), leakedbytes(0), hthreadid(-1) {} + QString text; + qint64 leakedblocks; + qint64 leakedbytes; + qint64 hthreadid; + }; + + struct XauxWhat { + XauxWhat() : line(-1), hthreadid(-1) {} + void clear() + { + *this = XauxWhat(); + } + + QString text; + QString file; + QString dir; + qint64 line; + qint64 hthreadid; + }; +} + +class Parser::Private { + Parser *const q; +public: + + explicit Private(Parser *qq); + + void parse(QIODevice *device); + + void parse_error(); + QVector parse_stack(); + Suppression parse_suppression(); + SuppressionFrame parse_suppFrame(); + Frame parse_frame(); + void parse_status(); + void parse_errorcounts(); + void parse_suppcounts(); + void parse_announcethread(); + void checkProtocolVersion(const QString &versionStr); + void checkTool(const QString &tool); + XWhat parseXWhat(); + XauxWhat parseXauxWhat(); + MemcheckErrorKind parseMemcheckErrorKind(const QString &kind); + HelgrindErrorKind parseHelgrindErrorKind(const QString &kind); + PtrcheckErrorKind parsePtrcheckErrorKind(const QString &kind); + int parseErrorKind(const QString &kind); + + void reportInternalError(const QString &errorString); + QXmlStreamReader::TokenType blockingReadNext(); + bool notAtEnd() const; + QString blockingReadElementText(); + + Tool tool; + QString errorString; + QXmlStreamReader reader; + QHash errorKindsByName_memcheck; + QHash errorKindsByName_helgrind; + QHash errorKindsByName_ptrcheck; + QHash toolsByName; +}; + +#undef ADD_ENUM +#define ADD_ENUM(tool,enumV) { errorKindsByName_##tool.insert(QLatin1String(#enumV), enumV); } + + +Parser::Private::Private(Parser *qq) + : q(qq), + tool(Parser::Unknown) +{ + toolsByName.insert(QLatin1String("memcheck"), Parser::Memcheck); + toolsByName.insert(QLatin1String("ptrcheck"), Parser::Ptrcheck); + toolsByName.insert(QLatin1String("exp-ptrcheck"), Parser::Ptrcheck); + toolsByName.insert(QLatin1String("helgrind"), Parser::Helgrind); + + ADD_ENUM(memcheck, ClientCheck) + ADD_ENUM(memcheck, InvalidFree) + ADD_ENUM(memcheck, InvalidJump) + ADD_ENUM(memcheck, InvalidRead) + ADD_ENUM(memcheck, InvalidWrite) + ADD_ENUM(memcheck, Leak_DefinitelyLost) + ADD_ENUM(memcheck, Leak_PossiblyLost) + ADD_ENUM(memcheck, Leak_StillReachable) + ADD_ENUM(memcheck, Leak_IndirectlyLost) + ADD_ENUM(memcheck, MismatchedFree) + ADD_ENUM(memcheck, Overlap) + ADD_ENUM(memcheck, SyscallParam) + ADD_ENUM(memcheck, UninitCondition) + ADD_ENUM(memcheck, UninitValue) + + ADD_ENUM(helgrind, Race) + ADD_ENUM(helgrind, UnlockUnlocked) + ADD_ENUM(helgrind, UnlockForeign) + ADD_ENUM(helgrind, UnlockBogus) + ADD_ENUM(helgrind, PthAPIerror) + ADD_ENUM(helgrind, LockOrder) + ADD_ENUM(helgrind, Misc) + + ADD_ENUM(ptrcheck, SorG) + ADD_ENUM(ptrcheck, Heap) + ADD_ENUM(ptrcheck, Arith) + ADD_ENUM(ptrcheck, SysParam) +} + +#undef ADD_ENUM + +static quint64 parseHex(const QString &str, const QString &context) +{ + bool ok; + const quint64 v = str.toULongLong(&ok, 16); + if (!ok) + throw ParserException(QObject::tr("Could not parse hex number from \"%1\" (%2)").arg(str, context)); + return v; +} + +static qint64 parseInt64(const QString &str, const QString &context) +{ + bool ok; + const quint64 v = str.toLongLong(&ok); + if (!ok) + throw ParserException(QObject::tr("Could not parse hex number from \"%1\" (%2)").arg(str, context)); + return v; +} + +QXmlStreamReader::TokenType Parser::Private::blockingReadNext() +{ + QXmlStreamReader::TokenType token = QXmlStreamReader::Invalid; + + forever { + token = reader.readNext(); + + if (reader.error() == QXmlStreamReader::PrematureEndOfDocumentError) { + if (reader.device()->waitForReadyRead(1000)) { + // let's try again + continue; + } else { + // device error, e.g. remote host closed connection, or timeout + // ### we have no way to know if waitForReadyRead() timed out or failed with a real + // error, and sensible heuristics based on QIODevice fail. + // - error strings are translated and in any case not guaranteed to stay the same, + // so we can't use them. + // - errorString().isEmpty() does not work because errorString() is + // "network timeout error" if the waitFor... timed out. + // - isSequential() [for socket] && isOpen() doesn't work because isOpen() + // returns true if the remote host closed the connection. + // ...so we fall back to knowing it might be a QAbstractSocket. + + QIODevice *dev = reader.device(); + QAbstractSocket *sock = qobject_cast(dev); + + if (!sock || sock->state() != QAbstractSocket::ConnectedState) { + throw ParserException(dev->errorString()); + } + } + } else if (reader.hasError()) { + throw ParserException(reader.errorString()); //TODO add line, column? + break; + } else { + // read a valid next token + break; + } + } + + return token; +} + +bool Parser::Private::notAtEnd() const +{ + return !reader.atEnd() + || reader.error() == QXmlStreamReader::PrematureEndOfDocumentError; +} + +QString Parser::Private::blockingReadElementText() +{ + //analogous to QXmlStreamReader::readElementText(), but blocking. readElementText() doesn't recover from PrematureEndOfData, + //but always returns a null string if isStartElement() is false (which is the case if it already parts of the text) + //affects at least Qt <= 4.7.1. Reported as QTBUG-14661. + + if (!reader.isStartElement()) + throw ParserException(QObject::tr("trying to read element text although current position is not start of element")); + + QString result; + + forever { + const QXmlStreamReader::TokenType type = blockingReadNext(); + switch (type) { + case QXmlStreamReader::Characters: + case QXmlStreamReader::EntityReference: + result += reader.text(); + break; + case QXmlStreamReader::EndElement: + return result; + case QXmlStreamReader::ProcessingInstruction: + case QXmlStreamReader::Comment: + break; + case QXmlStreamReader::StartElement: + throw ParserException(QObject::tr("Unexpected child element while reading element text")); + default: + //TODO handle + throw ParserException(QObject::tr("Unexpected token type %1").arg(type)); + break; + } + } + return QString(); +} + +void Parser::Private::checkProtocolVersion(const QString &versionStr) +{ + bool ok; + const int version = versionStr.toInt(&ok); + if (!ok) + throw ParserException(QObject::tr("Could not parse protocol version from \"%1\"").arg(versionStr)); + if (version != 4) + throw ParserException(QObject::tr("XmlProtocol version %1 not supported (supported version: 4)").arg(version)); +} + +void Parser::Private::checkTool(const QString &reportedStr) +{ + const QHash::ConstIterator reported = toolsByName.find(reportedStr); + + if (reported == toolsByName.constEnd()) + throw ParserException(QObject::tr("Valgrind tool \"%1\" not supported").arg(reportedStr)); + + tool = reported.value(); +} + +XWhat Parser::Private::parseXWhat() +{ + XWhat what; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.name() == QLatin1String("text")) + what.text = blockingReadElementText(); + else if (reader.name() == QLatin1String("leakedbytes")) + what.leakedbytes = parseInt64(blockingReadElementText(), QLatin1String("error/xwhat[memcheck]/leakedbytes")); + else if (reader.name() == QLatin1String("leakedblocks")) + what.leakedblocks = parseInt64(blockingReadElementText(), QLatin1String("error/xwhat[memcheck]/leakedblocks")); + else if (reader.name() == QLatin1String("hthreadid")) + what.hthreadid = parseInt64(blockingReadElementText(), QLatin1String("error/xwhat[memcheck]/hthreadid")); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + return what; +} + +XauxWhat Parser::Private::parseXauxWhat() +{ + XauxWhat what; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.name() == QLatin1String("text")) + what.text = blockingReadElementText(); + else if (reader.name() == QLatin1String("file")) + what.file = blockingReadElementText(); + else if (reader.name() == QLatin1String("dir")) + what.dir = blockingReadElementText(); + else if (reader.name() == QLatin1String("line")) + what.line = parseInt64(blockingReadElementText(), QLatin1String("error/xauxwhat/line")); + else if (reader.name() == QLatin1String("hthreadid")) + what.hthreadid = parseInt64(blockingReadElementText(), QLatin1String("error/xauxwhat/hthreadid")); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + return what; +} + + + +MemcheckErrorKind Parser::Private::parseMemcheckErrorKind(const QString &kind) +{ + const QHash::ConstIterator it = errorKindsByName_memcheck.find(kind); + if (it != errorKindsByName_memcheck.constEnd()) + return *it; + else + throw ParserException(QObject::tr("Unknown memcheck error kind \"%1\"").arg(kind)); +} + +HelgrindErrorKind Parser::Private::parseHelgrindErrorKind(const QString &kind) +{ + const QHash::ConstIterator it = errorKindsByName_helgrind.find(kind); + if (it != errorKindsByName_helgrind.constEnd()) + return *it; + else + throw ParserException(QObject::tr("Unknown helgrind error kind \"%1\"").arg(kind)); +} + +PtrcheckErrorKind Parser::Private::parsePtrcheckErrorKind(const QString &kind) +{ + const QHash::ConstIterator it = errorKindsByName_ptrcheck.find(kind); + if (it != errorKindsByName_ptrcheck.constEnd()) + return *it; + else + throw ParserException(QObject::tr("Unknown ptrcheck error kind \"%1\"").arg(kind)); +} + +int Parser::Private::parseErrorKind(const QString &kind) +{ + switch (tool) { + case Memcheck: + return parseMemcheckErrorKind(kind); + case Ptrcheck: + return parsePtrcheckErrorKind(kind); + case Helgrind: + return parseHelgrindErrorKind(kind); + case Unknown: + default: + break; + } + throw ParserException(QObject::tr("Could not parse error kind, tool not yet set.")); +} + +static Status::State parseState(const QString &state) +{ + if (state == QLatin1String("RUNNING")) + return Status::Running; + if (state == QLatin1String("FINISHED")) + return Status::Finished; + throw ParserException(QObject::tr("Unknown state \"%1\"").arg(state)); +} + +void Parser::Private::reportInternalError(const QString &e) +{ + errorString = e; + emit q->internalError(e); +} + +static Stack makeStack( const XauxWhat &xauxwhat, const QVector &frames) +{ + Stack s; + s.setFrames(frames); + s.setFile(xauxwhat.file); + s.setDirectory(xauxwhat.dir); + s.setLine(xauxwhat.line); + s.setHelgrindThreadId(xauxwhat.hthreadid); + s.setAuxWhat(xauxwhat.text); + return s; +} + +void Parser::Private::parse_error() +{ + Error e; + QVector > frames; + XauxWhat currentAux; + QVector auxs; + + int lastAuxWhat = -1; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) + lastAuxWhat++; + if (reader.name() == QLatin1String("unique")) + e.setUnique(parseHex(blockingReadElementText(), QLatin1String("unique"))); + else if ( reader.name() == QLatin1String("tid")) + e.setTid(parseInt64(blockingReadElementText(), QLatin1String("error/tid"))); + else if (reader.name() == QLatin1String("kind")) //TODO this is memcheck-specific: + e.setKind(parseErrorKind(blockingReadElementText())); + else if (reader.name() == QLatin1String("suppression")) + e.setSuppression(parse_suppression()); + else if (reader.name() == QLatin1String("xwhat")) { + const XWhat xw = parseXWhat(); + e.setWhat(xw.text); + e.setLeakedBlocks(xw.leakedblocks); + e.setLeakedBytes(xw.leakedbytes); + e.setHelgrindThreadId(xw.hthreadid); + } + else if (reader.name() == QLatin1String("what")) + e.setWhat(blockingReadElementText()); + else if (reader.name() == QLatin1String("xauxwhat")) { + if (!currentAux.text.isEmpty()) + auxs.push_back(currentAux); + currentAux = parseXauxWhat(); + } + else if (reader.name() == QLatin1String("auxwhat")) { + const QString aux = blockingReadElementText(); + //concatenate multiple consecutive tags + if (lastAuxWhat > 1) { + if (!currentAux.text.isEmpty()) + auxs.push_back(currentAux); + currentAux.clear(); + currentAux.text = aux; + } else { + if (!currentAux.text.isEmpty()) + currentAux.text.append(QLatin1Char(' ')); + currentAux.text.append(aux); + } + lastAuxWhat = 0; + } + else if (reader.name() == QLatin1String("stack")) { + frames.push_back(parse_stack()); + } + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + + if (!currentAux.text.isEmpty()) + auxs.push_back(currentAux); + + //if we have less xaux/auxwhats than stacks, prepend empty xauxwhats + //(the first frame usually has not xauxwhat in helgrind and memcheck) + while (auxs.size() < frames.size()) + auxs.prepend(XauxWhat()); + + QVector stacks; + for (int i = 0; i < auxs.size(); ++i) + stacks.append(makeStack(auxs[i], frames[i])); + e.setStacks(stacks); + + emit q->error(e); +} + +Frame Parser::Private::parse_frame() +{ + Frame frame; + + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("ip")) + frame.setInstructionPointer(parseHex(blockingReadElementText(), QLatin1String("error/frame/ip"))); + else if (reader.name() == QLatin1String("obj")) + frame.setObject(blockingReadElementText()); + else if (reader.name() == QLatin1String("fn")) + frame.setFunctionName( blockingReadElementText()); + else if (reader.name() == QLatin1String("dir")) + frame.setDirectory(blockingReadElementText()); + else if (reader.name() == QLatin1String("file")) + frame.setFile( blockingReadElementText()); + else if (reader.name() == QLatin1String("line")) + frame.setLine(parseInt64(blockingReadElementText(), QLatin1String("error/frame/line"))); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } + + return frame; +} + +void Parser::Private::parse_announcethread() +{ + AnnounceThread at; + + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("hthreadid")) + at.setHelgrindThreadId(parseInt64(blockingReadElementText(), QLatin1String("announcethread/hthreadid"))); + else if (reader.name() == QLatin1String("stack")) + at.setStack(parse_stack()); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } + + emit q->announceThread(at); +} + +void Parser::Private::parse_errorcounts() +{ + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("pair")) { + qint64 unique = 0; + qint64 count = 0; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("unique")) + unique = parseHex(blockingReadElementText(), QLatin1String("errorcounts/pair/unique")); + else if (reader.name() == QLatin1String("count")) + count = parseInt64(blockingReadElementText(), QLatin1String("errorcounts/pair/count")); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } + emit q->errorCount(unique, count); + } + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } +} + + +void Parser::Private::parse_suppcounts() +{ + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("pair")) { + QString name; + qint64 count = 0; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("name")) + name = blockingReadElementText(); + else if (reader.name() == QLatin1String("count")) + count = parseInt64(blockingReadElementText(), QLatin1String("suppcounts/pair/count")); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } + emit q->suppressionCount(name, count); + } + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } +} + +void Parser::Private::parse_status() +{ + Status s; + + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("state")) + s.setState(parseState(blockingReadElementText())); + else if (reader.name() == QLatin1String("time")) + s.setTime(blockingReadElementText()); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } + + emit q->status(s); +} + +QVector Parser::Private::parse_stack() +{ + QVector frames; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("frame")) + frames.append(parse_frame()); + } + } + + return frames; +} + +SuppressionFrame Parser::Private::parse_suppFrame() +{ + SuppressionFrame frame; + + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("obj")) + frame.setObject(blockingReadElementText()); + else if (reader.name() == QLatin1String("fun")) + frame.setFunction( blockingReadElementText()); + else if (reader.isStartElement()) + reader.skipCurrentElement(); + } + } + + return frame; +} + +Suppression Parser::Private::parse_suppression() +{ + Suppression supp; + QVector frames; + while (notAtEnd()) { + blockingReadNext(); + if (reader.isEndElement()) + break; + if (reader.isStartElement()) { + if (reader.name() == QLatin1String("sname")) + supp.setName(blockingReadElementText()); + else if (reader.name() == QLatin1String("skind")) + supp.setKind(blockingReadElementText()); + else if (reader.name() == QLatin1String("skaux")) + supp.setAuxKind(blockingReadElementText()); + else if (reader.name() == QLatin1String("rawtext")) + supp.setRawText(blockingReadElementText()); + else if (reader.name() == QLatin1String("sframe")) + frames.push_back(parse_suppFrame()); + } + } + + supp.setFrames(frames); + return supp; +} + +void Parser::Private::parse(QIODevice *device) +{ + QTC_ASSERT(device, return); + reader.setDevice(device); + + try { + while (notAtEnd()) { + blockingReadNext(); + if (reader.name() == QLatin1String("error")) + parse_error(); + else if (reader.name() == QLatin1String("announcethread")) + parse_announcethread(); + else if (reader.name() == QLatin1String("status")) + parse_status(); + else if (reader.name() == QLatin1String("errorcounts")) + parse_errorcounts(); + else if (reader.name() == QLatin1String("suppcounts")) + parse_suppcounts(); + else if (reader.name() == QLatin1String("protocolversion")) + checkProtocolVersion(blockingReadElementText()); + else if (reader.name() == QLatin1String("protocoltool")) + checkTool(blockingReadElementText()); + } + } catch (const ParserException &e) { + reportInternalError(e.message()); + } catch (...) { + reportInternalError(QObject::tr("Unexpected exception caught during parsing.")); + } + emit q->finished(); +} + +Parser::Parser(QObject *parent) + : QObject(parent) + , d(new Private(this)) +{ +} + +Parser::~Parser() +{ + delete d; +} + +QString Parser::errorString() const +{ + return d->errorString; +} + +void Parser::parse(QIODevice *device) +{ + d->parse(device); +} diff --git a/src/libs/valgrind/xmlprotocol/parser.h b/src/libs/valgrind/xmlprotocol/parser.h new file mode 100644 index 0000000000..108763f10c --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/parser.h @@ -0,0 +1,95 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_PARSER_H +#define LIBVALGRIND_PROTOCOL_PARSER_H + +#include "../valgrind_global.h" + +#include + +QT_BEGIN_NAMESPACE +class QIODevice; +QT_END_NAMESPACE + +namespace Valgrind { + +namespace XmlProtocol { + +class AnnounceThread; +class Error; +class Status; + +/** + * Parser for the Valgrind Output XML Protocol 4 + */ +class VALGRINDSHARED_EXPORT Parser : public QObject { + Q_OBJECT +public: + enum Tool { + Unknown, + Memcheck, + Ptrcheck, + Helgrind + }; + + explicit Parser(QObject *parent=0); + ~Parser(); + + QString errorString() const; + +public Q_SLOTS: + void parse(QIODevice *stream); + +Q_SIGNALS: + void status(const Valgrind::XmlProtocol::Status &status); + void error(const Valgrind::XmlProtocol::Error &error); + void internalError(const QString &errorString); + void errorCount(qint64 unique, qint64 count); + void suppressionCount(const QString &name, qint64 count); + void announceThread(const Valgrind::XmlProtocol::AnnounceThread &announceThread); + void finished(); + +private: + Q_DISABLE_COPY(Parser) + + class Private; + Private *const d; +}; + +} // XmlProtocol +} // Valgrind + +#endif //LIBVALGRIND_PROTOCOL_PARSER_H diff --git a/src/libs/valgrind/xmlprotocol/stack.cpp b/src/libs/valgrind/xmlprotocol/stack.cpp new file mode 100644 index 0000000000..55141b9208 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/stack.cpp @@ -0,0 +1,159 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "stack.h" +#include "frame.h" + +#include +#include +#include + +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class Stack::Private : public QSharedData +{ +public: + Private() + : line(-1) + , hthreadid(-1) + { + } + + QString auxwhat; + QString file; + QString dir; + qint64 line; + qint64 hthreadid; + QVector frames; +}; + +Stack::Stack() + : d(new Private) +{ +} + +Stack::Stack(const Stack &other) + : d(other.d) +{ +} + +Stack::~Stack() +{ +} + +void Stack::swap(Stack &other) +{ + qSwap(d, other.d); +} + +Stack &Stack::operator=(const Stack &other) +{ + Stack tmp(other); + swap(tmp); + return *this; +} + +bool Stack::operator==(const Stack &other) const +{ + return d->frames == other.d->frames + && d->auxwhat == other.d->auxwhat + && d->file == other.d->file + && d->dir == other.d->dir + && d->line == other.d->line + && d->hthreadid == other.d->hthreadid; +} + +QString Stack::auxWhat() const +{ + return d->auxwhat; +} + +void Stack::setAuxWhat(const QString &auxwhat) +{ + d->auxwhat = auxwhat; +} + +QVector Stack::frames() const +{ + return d->frames; +} + +void Stack::setFrames(const QVector &frames) +{ + d->frames = frames; +} + +QString Stack::file() const +{ + return d->file; +} + +void Stack::setFile(const QString &file) +{ + d->file = file; +} + +QString Stack::directory() const +{ + return d->dir; +} + +void Stack::setDirectory(const QString &directory) +{ + d->dir = directory; +} + +qint64 Stack::line() const +{ + return d->line; +} + +void Stack::setLine(qint64 line) +{ + d->line = line; +} + +qint64 Stack::helgrindThreadId() const +{ + return d->hthreadid; +} + +void Stack::setHelgrindThreadId(qint64 id) +{ + d->hthreadid = id; +} diff --git a/src/libs/valgrind/xmlprotocol/stack.h b/src/libs/valgrind/xmlprotocol/stack.h new file mode 100644 index 0000000000..f428191916 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/stack.h @@ -0,0 +1,89 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_STACK_H +#define LIBVALGRIND_PROTOCOL_STACK_H + +#include "../valgrind_global.h" + +#include + +QT_BEGIN_NAMESPACE +template class QVector; +QT_END_NAMESPACE + +namespace Valgrind { +namespace XmlProtocol { + +class Frame; + +class VALGRINDSHARED_EXPORT Stack { +public: + Stack(); + Stack(const Stack &other); + ~Stack(); + Stack &operator=(const Stack &other); + void swap(Stack &other); + bool operator==(const Stack &other) const; + + QString auxWhat() const; + void setAuxWhat(const QString &auxwhat); + + QVector frames() const; + void setFrames(const QVector &frames); + + //memcheck, ptrcheck, helgrind: + QString file() const; + void setFile(const QString &file); + + QString directory() const; + void setDirectory(const QString &directory); + + qint64 line() const; + void setLine(qint64 line); + + //helgrind: + qint64 helgrindThreadId() const; + void setHelgrindThreadId(qint64 threadId ); + +private: + class Private; + QSharedDataPointer d; +}; + +} +} + +#endif // LIBVALGRIND_PROTOCOL_STACK_H diff --git a/src/libs/valgrind/xmlprotocol/stackmodel.cpp b/src/libs/valgrind/xmlprotocol/stackmodel.cpp new file mode 100644 index 0000000000..0404b513c4 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/stackmodel.cpp @@ -0,0 +1,237 @@ +/************************************************************************** +** +** This file is part of Qt Creator Instrumentation Tools +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "stackmodel.h" +#include "error.h" +#include "frame.h" +#include "stack.h" +#include + +#include +#include +#include "modelhelpers.h" + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class StackModel::Private +{ +public: + Error error; + + Stack stack(int i) const + { + if (i < 0 || i >= error.stacks().size()) + return Stack(); + else + return error.stacks().at(i); + } +}; + +static QString makeName(const Frame &frame) +{ + const QString d = frame.directory(); + const QString f = frame.file(); + const QString fn = frame.functionName(); + if (!fn.isEmpty()) + return fn; + if (!d.isEmpty() && !f.isEmpty()) + return frame.line() > 0 ? QString::fromLatin1("%1%2%3:%4").arg(d, QDir::separator(), f, QString::number(frame.line())) + : QString::fromLatin1("%1%2%3").arg(d, QDir::separator(), f); + else + return frame.object(); +} + +StackModel::StackModel(QObject *parent) + : QAbstractItemModel(parent) + , d(new Private) +{ +} + +StackModel::~StackModel() +{ + delete d; +} + +QVariant StackModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + QTC_ASSERT(index.model() == this, return QVariant()); + + if (!index.parent().isValid()) { + const Stack stack = d->stack(index.row()); + if (role == Qt::DisplayRole) { + switch (index.column()) { + case NameColumn: + if (!stack.auxWhat().isEmpty()) + return stack.auxWhat(); + else + return d->error.what(); + default: + return QVariant(); + } + } + } else { + const Stack stack = d->stack(index.parent().row()); + const QVector frames = stack.frames(); + const int fidx = index.row(); + if (fidx < 0 || fidx >= frames.size()) + return QVariant(); + const Frame &frame = frames[fidx]; + switch(role) { + case Qt::DisplayRole: + { + switch (index.column()) { + case NameColumn: + return makeName(frame); + case InstructionPointerColumn: + return QString::fromLatin1("0x%1").arg(frame.instructionPointer(), 0, 16); + case ObjectColumn: + return frame.object(); + case FunctionNameColumn: + return frame.functionName(); + case DirectoryColumn: + return frame.directory(); + case FileColumn: + return frame.file(); + case LineColumn: + if (frame.line() > 0) + return frame.line(); + else + return QVariant(); + } + break; + } + case Qt::ToolTipRole: + return toolTipForFrame(frame); + case ObjectRole: + return frame.object(); + case FunctionNameRole: + return frame.functionName(); + case FileRole: + return frame.file(); + case DirectoryRole: + return frame.directory(); + case LineRole: + if (frame.line() > 0) + return frame.line(); + else + return QVariant(); + } + } + + return QVariant(); +} + +QVariant StackModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || role != Qt::DisplayRole) + return QVariant(); + + switch (section) { + case NameColumn: + return tr("Description"); + case InstructionPointerColumn: + return tr("Instruction Pointer"); + case ObjectColumn: + return tr("Object"); + case FunctionNameColumn: + return tr("Function"); + case DirectoryColumn: + return tr("Directory"); + case FileColumn: + return tr("File"); + case LineColumn: + return tr("Line"); + } + + return QVariant(); +} + +QModelIndex StackModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) { + QTC_ASSERT(parent.model() == this, return QModelIndex()); + return createIndex(row, column, parent.row()); + } else + return createIndex(row, column, -1); +} + +QModelIndex StackModel::parent(const QModelIndex &child) const +{ + QTC_ASSERT(!child.isValid() || child.model() == this, return QModelIndex()); + + if (child.internalId() == -1) + return QModelIndex(); + else + return createIndex(child.internalId(), 0, -1); +} + +int StackModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return d->error.stacks().size(); + + QTC_ASSERT(parent.model() == this, return 0); + + const QModelIndex gp = parent.parent(); + + if (!gp.isValid()) + return d->stack(parent.row()).frames().size(); + else + return 0; +} + +int StackModel::columnCount(const QModelIndex &parent) const { + QTC_ASSERT(!parent.isValid() || parent.model() == this, return 0); + return ColumnCount; +} + +void StackModel::setError(const Error &error) +{ + if (d->error == error) + return; + d->error = error; + reset(); +} + +void StackModel::clear() +{ + beginResetModel(); + d->error = Error(); + endResetModel(); +} diff --git a/src/libs/valgrind/xmlprotocol/stackmodel.h b/src/libs/valgrind/xmlprotocol/stackmodel.h new file mode 100644 index 0000000000..b04ad972ba --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/stackmodel.h @@ -0,0 +1,94 @@ +/************************************************************************** +** +** This file is part of Qt Creator Instrumentation Tools +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_STACKMODEL_H +#define LIBVALGRIND_PROTOCOL_STACKMODEL_H + +#include "../valgrind_global.h" + +#include + +namespace Valgrind { +namespace XmlProtocol { + +class Error; + +class VALGRINDSHARED_EXPORT StackModel : public QAbstractItemModel +{ + Q_OBJECT +public: + enum Column { + NameColumn=0, + FunctionNameColumn, + DirectoryColumn, + FileColumn, + LineColumn, + InstructionPointerColumn, + ObjectColumn, + ColumnCount + }; + + enum Role { + ObjectRole=Qt::UserRole, + FunctionNameRole, + DirectoryRole, + FileRole, + LineRole + }; + + explicit StackModel(QObject *parent=0); + ~StackModel(); + + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + void clear(); + +public Q_SLOTS: + void setError(const Valgrind::XmlProtocol::Error &error); + +private: + class Private; + Private *const d; +}; + +} +} + +#endif // LIBVALGRIND_PROTOCOL_STACKMODEL_H diff --git a/src/libs/valgrind/xmlprotocol/status.cpp b/src/libs/valgrind/xmlprotocol/status.cpp new file mode 100644 index 0000000000..8dfe205e6b --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/status.cpp @@ -0,0 +1,105 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "status.h" + +#include +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class Status::Private : public QSharedData +{ +public: + Private() + : state(Running) + { + } + + State state; + QString time; +}; + +Status::Status() + : d(new Private) +{ +} + +Status::Status(const Status &other) + : d(other.d) +{ +} + +Status::~Status() +{ +} + +void Status::swap(Status &other) +{ + qSwap(d, other.d); +} + +Status &Status::operator=(const Status &other) +{ + Status tmp(other); + swap(tmp); + return *this; +} + +bool Status::operator==(const Status &other) const +{ + return d->state == other.d->state && d->time == other.d->time; +} + +void Status::setState(State state) +{ + d->state = state; +} + +Status::State Status::state() const +{ + return d->state; +} + +void Status::setTime(const QString &time) +{ + d->time = time; +} + +QString Status::time() const +{ + return d->time; +} diff --git a/src/libs/valgrind/xmlprotocol/status.h b/src/libs/valgrind/xmlprotocol/status.h new file mode 100644 index 0000000000..fb88aa53e6 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/status.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_STATUS_H +#define LIBVALGRIND_PROTOCOL_STATUS_H + +#include "../valgrind_global.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE + +namespace Valgrind { +namespace XmlProtocol { + +class VALGRINDSHARED_EXPORT Status +{ +public: + enum State { + Running, + Finished + }; + + Status(); + Status(const Status &other); + ~Status(); + Status &operator=(const Status &other); + void swap(Status &other); + bool operator==(const Status &other) const; + + State state() const; + void setState(State state); + + QString time() const; + void setTime(const QString &time); + +private: + class Private; + QSharedDataPointer d; +}; + +} // namespace XmlProtocol +} // namespace Valgrind + +Q_DECLARE_METATYPE(Valgrind::XmlProtocol::Status) + +#endif // LIBVALGRIND_PROTOCOL_STATUS_H diff --git a/src/libs/valgrind/xmlprotocol/suppression.cpp b/src/libs/valgrind/xmlprotocol/suppression.cpp new file mode 100644 index 0000000000..17306a97e8 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/suppression.cpp @@ -0,0 +1,245 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "suppression.h" + +#include +#include +#include +#include + +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +class SuppressionFrame::Private : public QSharedData +{ +public: + Private() + { + } + + QString obj; + QString fun; +}; + +SuppressionFrame::SuppressionFrame() + : d(new Private) +{ +} + +SuppressionFrame::SuppressionFrame(const SuppressionFrame &other) + : d(other.d) +{ +} + +SuppressionFrame::~SuppressionFrame() +{ +} + +void SuppressionFrame::swap(SuppressionFrame &other) +{ + qSwap(d, other.d); +} + +SuppressionFrame &SuppressionFrame::operator=(const SuppressionFrame &other) +{ + SuppressionFrame tmp(other); + swap(tmp); + return *this; +} + +bool SuppressionFrame::operator==(const SuppressionFrame &other) const +{ + return d->fun == other.d->fun + && d->obj == other.d->obj; +} + +QString SuppressionFrame::function() const +{ + return d->fun; +} + +void SuppressionFrame::setFunction(const QString &fun) +{ + d->fun = fun; +} + +QString SuppressionFrame::object() const +{ + return d->obj; +} + +void SuppressionFrame::setObject(const QString &obj) +{ + d->obj = obj; +} + +QString SuppressionFrame::toString() const +{ + if (!d->fun.isEmpty()) { + return QLatin1String("fun:") + d->fun; + } else { + return QLatin1String("obj:") + d->obj; + } +} + +class Suppression::Private : public QSharedData +{ +public: + Private() + : isNull(true) + { + } + + bool isNull; + QString name; + QString kind; + QString auxkind; + QString rawText; + QVector frames; +}; + +Suppression::Suppression() + : d(new Private) +{ +} + +Suppression::Suppression(const Suppression &other) + : d(other.d) +{ +} + +Suppression::~Suppression() +{ +} + +void Suppression::swap(Suppression &other) +{ + qSwap(d, other.d); +} + +Suppression &Suppression::operator=(const Suppression &other) +{ + Suppression tmp(other); + swap(tmp); + return *this; +} + +bool Suppression::operator==(const Suppression &other) const +{ + return d->isNull == other.d->isNull + && d->name == other.d->name + && d->kind == other.d->kind + && d->auxkind == other.d->auxkind + && d->rawText == other.d->rawText + && d->frames == other.d->frames; +} + +bool Suppression::isNull() const +{ + return d->isNull; +} +void Suppression::setName(const QString &name) +{ + d->isNull = false; + d->name = name; +} + +QString Suppression::name() const +{ + return d->name; +} + +void Suppression::setKind(const QString &kind) +{ + d->isNull = false; + d->kind = kind; +} + +QString Suppression::kind() const +{ + return d->kind; +} + +void Suppression::setAuxKind(const QString &auxkind) +{ + d->isNull = false; + d->auxkind = auxkind; +} + +QString Suppression::auxKind() const +{ + return d->auxkind; +} + +void Suppression::setRawText(const QString &text) +{ + d->isNull = false; + d->rawText = text; +} + +QString Suppression::rawText() const +{ + return d->rawText; +} + +void Suppression::setFrames(const QVector &frames) +{ + d->isNull = false; + d->frames = frames; +} + +QVector Suppression::frames() const +{ + return d->frames; +} + +QString Suppression::toString() const +{ + QString ret; + QTextStream stream(&ret); + const QLatin1String indent(" "); + + stream << "{\n"; + stream << indent << d->name << '\n'; + stream << indent << d->kind << '\n'; + foreach(const SuppressionFrame &frame, d->frames) { + stream << indent << frame.toString() << '\n'; + } + stream << "}\n"; + return ret; +} diff --git a/src/libs/valgrind/xmlprotocol/suppression.h b/src/libs/valgrind/xmlprotocol/suppression.h new file mode 100644 index 0000000000..ab896a4ab4 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/suppression.h @@ -0,0 +1,113 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_SUPPRESSION_H +#define LIBVALGRIND_PROTOCOL_SUPPRESSION_H + +#include "../valgrind_global.h" + +#include + +QT_BEGIN_NAMESPACE +class QString; +template class QVector; +QT_END_NAMESPACE + +namespace Valgrind { +namespace XmlProtocol { + +class VALGRINDSHARED_EXPORT SuppressionFrame { +public: + SuppressionFrame(); + SuppressionFrame(const SuppressionFrame &other); + ~SuppressionFrame(); + SuppressionFrame &operator=(const SuppressionFrame &other); + void swap(SuppressionFrame &other); + bool operator==(const SuppressionFrame &other) const; + bool operator!=(const SuppressionFrame &other) const + { + return !operator==(other); + } + + QString object() const; + void setObject(const QString &object); + + QString function() const; + void setFunction(const QString &function); + + QString toString() const; + +private: + class Private; + QSharedDataPointer d; +}; + +class VALGRINDSHARED_EXPORT Suppression { +public: + Suppression(); + Suppression(const Suppression &other); + ~Suppression(); + Suppression &operator=(const Suppression &other); + void swap(Suppression &other); + bool operator==(const Suppression &other) const; + + bool isNull() const; + + QString name() const; + void setName(const QString &name); + + QString kind() const; + void setKind(const QString &kind); + + QString auxKind() const; + void setAuxKind(const QString &kind); + + QString rawText() const; + void setRawText(const QString &text); + + QVector frames() const; + void setFrames(const QVector &frames); + + QString toString() const; + +private: + class Private; + QSharedDataPointer d; +}; + +} // namespace XmlProtocol +} // namespace Valgrind + +#endif // LIBVALGRIND_PROTOCOL_SUPPRESSION_H diff --git a/src/libs/valgrind/xmlprotocol/threadedparser.cpp b/src/libs/valgrind/xmlprotocol/threadedparser.cpp new file mode 100644 index 0000000000..a303d54cb8 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/threadedparser.cpp @@ -0,0 +1,153 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Andreas Hartmetz, KDAB (andreas.hartmetz@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "threadedparser.h" +#include "parser.h" +#include "error.h" +#include "frame.h" +#include "status.h" +#include "suppression.h" +#include + +#include +#include +#include + +using namespace Valgrind; +using namespace Valgrind::XmlProtocol; + +namespace { + +class Thread : public QThread { +public: + Thread() + : QThread() + , parser(0) + , device(0) + { + } + + void run() { + QTC_ASSERT(QThread::currentThread() == this, return); + parser->parse(device); + delete parser; + parser = 0; + delete device; + device = 0; + } + + XmlProtocol::Parser *parser; + QIODevice *device; +}; +} +class ThreadedParser::Private +{ +public: + Private() + {} + + QWeakPointer parserThread; + QString errorString; +}; + + +ThreadedParser::ThreadedParser(QObject *parent) + : QObject(parent), + d(new Private) +{ +} + +ThreadedParser::~ThreadedParser() +{ + delete d; +} + +QString ThreadedParser::errorString() const +{ + return d->errorString; +} + +bool ThreadedParser::isRunning() const +{ + return d->parserThread ? d->parserThread.data()->isRunning() : 0; +} + +void ThreadedParser::parse(QIODevice *device) +{ + QTC_ASSERT(!d->parserThread, return); + + Parser *parser = new Parser; + qRegisterMetaType(); + qRegisterMetaType(); + connect(parser, SIGNAL(status(Valgrind::XmlProtocol::Status)), + SIGNAL(status(Valgrind::XmlProtocol::Status)), + Qt::QueuedConnection); + connect(parser, SIGNAL(error(Valgrind::XmlProtocol::Error)), + SIGNAL(error(Valgrind::XmlProtocol::Error)), + Qt::QueuedConnection); + connect(parser, SIGNAL(internalError(QString)), + SLOT(slotInternalError(QString)), + Qt::QueuedConnection); + connect(parser, SIGNAL(errorCount(qint64, qint64)), + SIGNAL(errorCount(qint64, qint64)), + Qt::QueuedConnection); + connect(parser, SIGNAL(suppressionCount(QString, qint64)), + SIGNAL(suppressionCount(QString, qint64)), + Qt::QueuedConnection); + connect(parser, SIGNAL(finished()), SIGNAL(finished()), + Qt::QueuedConnection); + + + Thread* thread = new Thread; + d->parserThread = thread; + connect(thread, SIGNAL(finished()), + thread, SLOT(deleteLater())); + device->setParent(0); + device->moveToThread(thread); + parser->moveToThread(thread); + thread->device = device; + thread->parser = parser; + thread->start(); +} + +void ThreadedParser::slotInternalError(const QString &errorString) +{ + d->errorString = errorString; + emit internalError(errorString); +} +bool ThreadedParser::waitForFinished() +{ + return d->parserThread ? d->parserThread.data()->wait() : true; +} diff --git a/src/libs/valgrind/xmlprotocol/threadedparser.h b/src/libs/valgrind/xmlprotocol/threadedparser.h new file mode 100644 index 0000000000..ea06c729e8 --- /dev/null +++ b/src/libs/valgrind/xmlprotocol/threadedparser.h @@ -0,0 +1,94 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Author: Andreas Hartmetz, KDAB (andreas.hartmetz@kdab.com) +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef LIBVALGRIND_PROTOCOL_THREADEDPARSER_H +#define LIBVALGRIND_PROTOCOL_THREADEDPARSER_H + +#include "../valgrind_global.h" + +#include + +QT_BEGIN_NAMESPACE +class QIODevice; +QT_END_NAMESPACE + +namespace Valgrind { +namespace XmlProtocol { + +class Error; +class Status; + +/** + * ThreadedParser for the Valgrind Output XmlProtocol 4 + */ +class VALGRINDSHARED_EXPORT ThreadedParser : public QObject { + Q_OBJECT +public: + explicit ThreadedParser(QObject *parent=0); + ~ThreadedParser(); + + QString errorString() const; + + /// interface additions relative to Parser because Parser is synchronous and this + /// class parses asynchronously in a non-public secondary thread. + bool waitForFinished(); + bool isRunning() const; + +public Q_SLOTS: + ///@warning will move @p stream to a different thread and take ownership of it + void parse(QIODevice *stream); + +private Q_SLOTS: + void slotInternalError(const QString &errorString); + +Q_SIGNALS: + void status(const Valgrind::XmlProtocol::Status &status); + void error(const Valgrind::XmlProtocol::Error &error); + void internalError(const QString &errorString); + void errorCount(qint64 unique, qint64 count); + void suppressionCount(const QString &name, qint64 count); + void finished(); + +private: + Q_DISABLE_COPY(ThreadedParser) + + class Private; + Private *const d; +}; + +} // XmlProtocol +} // Valgrind + +#endif //LIBVALGRIND_PROTOCOL_THREADEDPARSER_H -- 2.11.0