diff --git a/CMakeLists.txt b/CMakeLists.txt index 95ee1f9..e1b6740 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,153 +1,151 @@ cmake_minimum_required(VERSION 3.0) project(kdevvalgrind) find_package(ECM "5.14.0" REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMAddTests) include(ECMQtDeclareLoggingCategory) include(KDEInstallDirs) include(KDECMakeSettings) include(FeatureSummary) set(QT_MIN_VERSION "5.5.0") find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core Widgets) set(KF5_DEP_VERSION "5.15.0") find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS I18n ItemModels # needed because missing in KDevPlatformConfig.cmake, remove once dep on kdevplatform >=5.2.2 ItemViews ) find_package(KDevPlatform 5.1 CONFIG) set_package_properties(KDevPlatform PROPERTIES TYPE REQUIRED ) include_directories(config core) add_definitions( -DQT_DEPRECATED_WARNINGS -DQT_DISABLE_DEPRECATED_BEFORE=0x050500 -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DQT_NO_URL_CAST_FROM_STRING -DQT_STRICT_ITERATORS -DQT_USE_QSTRINGBUILDER ) add_definitions(-DTRANSLATION_DOMAIN=\"kdevvalgrind\") set(kdevvalgrind_SRCS launchmode.cpp plugin.cpp problemmodel.cpp toolviewfactory.cpp config/globalconfigpage.cpp + core/config.cpp core/configpage.cpp core/job.cpp - core/settings.cpp core/tool.cpp + core/xmlconfig.cpp core/xmljob.cpp - core/xmlsettings.cpp core/utils.cpp + core/widgets/combobox.cpp + core/widgets/menubutton.cpp + core/private/common_config.cpp core/private/common_configpage.cpp - core/private/common_settings.cpp core/private/launcher.cpp core/private/xmlerror.cpp core/private/xmlparser.cpp + tools/cachegrind/cachegrind_config.cpp tools/cachegrind/cachegrind_configpage.cpp tools/cachegrind/cachegrind_job.cpp tools/cachegrind/cachegrind_model.cpp tools/cachegrind/cachegrind_parser.cpp - tools/cachegrind/cachegrind_settings.cpp tools/cachegrind/cachegrind_tool.cpp tools/cachegrind/cachegrind_view.cpp + tools/callgrind/callgrind_config.cpp tools/callgrind/callgrind_configpage.cpp tools/callgrind/callgrind_job.cpp tools/callgrind/callgrind_model.cpp tools/callgrind/callgrind_parser.cpp - tools/callgrind/callgrind_settings.cpp tools/callgrind/callgrind_tool.cpp tools/callgrind/callgrind_view.cpp + tools/drd/drd_config.cpp tools/drd/drd_configpage.cpp - tools/drd/drd_configpage.h tools/drd/drd_configpage.ui tools/drd/drd_job.cpp - tools/drd/drd_job.h - tools/drd/drd_settings.cpp - tools/drd/drd_settings.h tools/drd/drd_tool.cpp - tools/drd/drd_tool.h + tools/helgrind/helgrind_config.cpp tools/helgrind/helgrind_configpage.cpp tools/helgrind/helgrind_job.cpp - tools/helgrind/helgrind_settings.cpp tools/helgrind/helgrind_tool.cpp + tools/massif/massif_config.cpp tools/massif/massif_configpage.cpp tools/massif/massif_job.cpp tools/massif/massif_model.cpp tools/massif/massif_parser.cpp - tools/massif/massif_settings.cpp tools/massif/massif_snapshot.cpp tools/massif/massif_tool.cpp tools/massif/massif_view.cpp + tools/memcheck/memcheck_config.cpp tools/memcheck/memcheck_configpage.cpp tools/memcheck/memcheck_job.cpp - tools/memcheck/memcheck_settings.cpp tools/memcheck/memcheck_tool.cpp ) ki18n_wrap_ui(kdevvalgrind_SRCS config/globalconfigpage.ui core/private/common_configpage.ui tools/cachegrind/cachegrind_configpage.ui tools/cachegrind/cachegrind_view.ui tools/callgrind/callgrind_configpage.ui tools/callgrind/callgrind_view.ui tools/drd/drd_configpage.ui tools/helgrind/helgrind_configpage.ui tools/massif/massif_configpage.ui tools/massif/massif_view.ui tools/memcheck/memcheck_configpage.ui ) kconfig_add_kcfg_files(kdevvalgrind_SRCS config/globalsettings.kcfgc ) ecm_qt_declare_logging_category(kdevvalgrind_SRCS HEADER debug.h IDENTIFIER KDEV_VALGRIND CATEGORY_NAME "kdevelop.analyzers.valgrind" ) qt5_add_resources(kdevvalgrind_SRCS kdevvalgrind.qrc ) kdevplatform_add_plugin(kdevvalgrind JSON kdevvalgrind.json SOURCES ${kdevvalgrind_SRCS} ) target_link_libraries(kdevvalgrind KDev::Language KDev::Project KDev::Shell KF5::ItemViews ) # kdebugsettings file install(FILES kdevvalgrind.categories DESTINATION ${KDE_INSTALL_CONFDIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/core/config.cpp b/core/config.cpp new file mode 100644 index 0000000..37d662f --- /dev/null +++ b/core/config.cpp @@ -0,0 +1,169 @@ +/* This file is part of KDevelop + Copyright 2017 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#include "debug.h" + +#include + +#include + +namespace Valgrind +{ + +class Config::CmdItem +{ +public: + CmdItem(ItemInt* item, const QString& cmdName) + : CmdItem(static_cast(item), cmdName) + { + m_type = Int; + } + + CmdItem(ItemBool* item, const QString& cmdName) + : CmdItem(static_cast(item), cmdName) + { + m_type = Bool; + } + + CmdItem(ItemString* item, const QString& cmdName) + : CmdItem(static_cast(item), cmdName) + { + m_type = String; + } + + ~CmdItem() = default; + + QString cmdArg() + { + QString value; + + switch (m_type) { + case Int: + value = QString::number(m_item->property().toInt()); + break; + + case Bool: + value = m_item->property().toBool() ? QStringLiteral("yes") : QStringLiteral("no"); + break; + + case String: + value = m_item->property().toString(); + break; + } + + return QStringLiteral("--%1=%2").arg(m_cmdName, value); + } + +private: + CmdItem(KConfigSkeletonItem* item, const QString& cmdName) + : m_item(item) + , m_cmdName(cmdName) + { + Q_ASSERT(item); + Q_ASSERT(!cmdName.isEmpty()); + } + + enum Type + { + Int, + Bool, + String + }; + + KConfigSkeletonItem* m_item; + QString m_cmdName; + Type m_type; +}; + +Config::Config(const QString& group) + : m_group(group) +{ + setCurrentGroup(group); + + addItemString(QStringLiteral("extraArgs"), m_extraArgs); +} + +Config::~Config() +{ + qDeleteAll(m_cmdItems); +} + +inline void addParent(QString& fullName, const KConfigGroup& parent) +{ + fullName = parent.name() + QLatin1Char('\x1d') + fullName; +} + +// TODO create patch for KCoreConfigSkeleton::setCurrentGroup(const KConfigGroup& group) overload ? +void Config::setConfigGroup(const KConfigGroup& group) +{ + setSharedConfig(KSharedConfig::openConfig(group.config()->name(), group.config()->openFlags())); + + QString fullName(m_group); + addParent(fullName, group); + + KConfigGroup parentGroup = group.parent(); + while (parentGroup.isValid() && parentGroup.name() != QStringLiteral("")) { + addParent(fullName, parentGroup); + parentGroup = parentGroup.parent(); + } + + setCurrentGroup(fullName); + + const auto allItems = items(); + for (auto item : allItems) { + item->setGroup(fullName); + } +} + +QStringList Config::cmdArgs() +{ + QStringList args; + for (auto cmdItem : qAsConst(m_cmdItems)) { + args += cmdItem->cmdArg(); + } + args += KShell::splitArgs(m_extraArgs); + args.removeAll(QStringLiteral("")); + + return args; +} + +Config::ItemInt* Config::addCmdItemInt(const QString& name, int& reference, int defaultValue, const QString& cmdName) +{ + auto item = addItemInt(name, reference, defaultValue); + m_cmdItems += new CmdItem(item, cmdName); + return item; +} + +Config::ItemBool* Config::addCmdItemBool(const QString& name, bool& reference, bool defaultValue, const QString& cmdName) +{ + auto item = addItemBool(name, reference, defaultValue); + m_cmdItems += new CmdItem(item, cmdName); + return item; +} + +Config::ItemString* Config::addCmdItemString(const QString& name, QString& reference, const QString& defaultValue, const QString& cmdName) +{ + auto item = addItemString(name, reference, defaultValue); + m_cmdItems += new CmdItem(item, cmdName); + return item; +} + +} diff --git a/core/xmlsettings.h b/core/config.h similarity index 56% copy from core/xmlsettings.h copy to core/config.h index eee3f74..4fb86db 100644 --- a/core/xmlsettings.h +++ b/core/config.h @@ -1,38 +1,53 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "settings.h" +#include namespace Valgrind { -class XmlSettings : public Settings +class Config : public KConfigSkeleton { + Q_OBJECT + public: - ~XmlSettings() override = default; + ~Config() override; + + void setConfigGroup(const KConfigGroup& group); + + ItemInt* addCmdItemInt(const QString& name, int& reference, int defaultValue, const QString& cmdName); + ItemBool* addCmdItemBool(const QString& name, bool& reference, bool defaultValue, const QString& cmdName); + ItemString* addCmdItemString(const QString& name, QString& reference, const QString& defaultValue, const QString& cmdName); - BoolValue showInstructionPointer; + QStringList cmdArgs(); protected: - explicit XmlSettings(const QString& configKeyPrefix); + explicit Config(const QString& group); + +private: + QString m_group; + QString m_extraArgs; + + class CmdItem; + QList m_cmdItems; }; } diff --git a/core/configpage.cpp b/core/configpage.cpp index cc43159..7d96da9 100644 --- a/core/configpage.cpp +++ b/core/configpage.cpp @@ -1,57 +1,89 @@ /* This file is part of KDevelop Copyright 2018 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "configpage.h" -#include -#include -#include -#include +#include "config.h" +#include "debug.h" + +#include + +#include namespace Valgrind { -ConfigPage::ConfigPage(QWidget* parent) +ConfigPage::ConfigPage(QString title, QWidget* parent) : LaunchConfigurationPage(parent) + , m_title(title) + , m_config(nullptr) + , m_manager(nullptr) { } -void ConfigPage::connectToChanged(QCheckBox* box) +ConfigPage::~ConfigPage() = default; + +void ConfigPage::init(Config* config) { - connect(box, &QCheckBox::toggled, this, &LaunchConfigurationPage::changed); + Q_ASSERT(config); + + m_config.reset(config); + m_manager.reset(new KConfigDialogManager(this, config)); + + connect(m_manager.data(), &KConfigDialogManager::widgetModified, this, &ConfigPage::changed); + connect(this, &ConfigPage::changed, this, &ConfigPage::check); + + check(); } -void ConfigPage::connectToChanged(QComboBox* box) +void ConfigPage::check() { - connect(box, static_cast(&QComboBox::currentIndexChanged), - this, &LaunchConfigurationPage::changed); } -void ConfigPage::connectToChanged(QLineEdit* edit) +QString ConfigPage::title() const { - connect(edit, &QLineEdit::textChanged, this, &LaunchConfigurationPage::changed); + return m_title; } -void ConfigPage::connectToChanged(QSpinBox* box) +QIcon ConfigPage::icon() const { - connect(box, static_cast(&QSpinBox::valueChanged), - this, &LaunchConfigurationPage::changed); + return QIcon(); +} + +void ConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) +{ + Q_ASSERT(m_config); + Q_ASSERT(m_manager); + + m_config->setConfigGroup(cfg); + m_config->load(); + + m_manager->updateWidgets(); +} + +void ConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const +{ + Q_ASSERT(m_config); + Q_ASSERT(m_manager); + + m_config->setConfigGroup(cfg); + m_manager->updateSettings(); } } diff --git a/core/configpage.h b/core/configpage.h index 5d0d4a2..e269e29 100644 --- a/core/configpage.h +++ b/core/configpage.h @@ -1,48 +1,59 @@ /* This file is part of KDevelop Copyright 2018 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include -class QCheckBox; -class QComboBox; -class QLineEdit; -class QSpinBox; +class KConfigDialogManager; namespace Valgrind { +class Config; + class ConfigPage : public KDevelop::LaunchConfigurationPage { Q_OBJECT public: - ~ConfigPage() override = default; + ~ConfigPage() override; + + QString title() const override final; + QIcon icon() const override final; + + void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override final; + void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override final; protected: - explicit ConfigPage(QWidget* parent = nullptr); + explicit ConfigPage(QString title, QWidget* parent = nullptr); + + void init(Config* config); + + virtual void check(); + +private: + QString m_title; + + QScopedPointer m_config; + QScopedPointer m_manager; - void connectToChanged(QCheckBox* box); - void connectToChanged(QComboBox* box); - void connectToChanged(QLineEdit* edit); - void connectToChanged(QSpinBox* box); }; } diff --git a/core/job.cpp b/core/job.cpp index f1072aa..9540db3 100644 --- a/core/job.cpp +++ b/core/job.cpp @@ -1,311 +1,312 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2011 Lucas Sarie Copyright 2006-2008 Hamish Rodda Copyright 2002 Harald Fernengel Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "job.h" #include "debug.h" #include "globalsettings.h" #include "plugin.h" -#include "private/common_settings.h" #include "tool.h" #include "utils.h" +#include "private/common_config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Valgrind { inline QString valgrindErrorsPrefix() { return QStringLiteral("valgrind: "); } Job::Job(const Tool* tool, KDevelop::ILaunchConfiguration* launchConfig) : KDevelop::OutputExecuteJob(KDevelop::ICore::self()->runController()) , m_tool(tool) - , m_config(launchConfig->config()) + , m_configGroup(launchConfig->config()) , m_tcpServerPort(0) { Q_ASSERT(tool); Q_ASSERT(launchConfig); setProperties(KDevelop::OutputExecuteJob::JobProperty::DisplayStdout); setProperties(KDevelop::OutputExecuteJob::JobProperty::DisplayStderr); setProperties(KDevelop::OutputExecuteJob::JobProperty::PostProcessOutput); setCapabilities(KJob::Killable); setStandardToolView(KDevelop::IOutputView::TestView); setBehaviours(KDevelop::IOutputView::AutoScroll); auto pluginController = KDevelop::ICore::self()->pluginController(); auto iface = pluginController->pluginForExtension(QStringLiteral("org.kdevelop.IExecutePlugin"))->extension(); Q_ASSERT(iface); QString envProfile = iface->environmentProfileName(launchConfig); if (envProfile.isEmpty()) { envProfile = KDevelop::EnvironmentProfileList(KSharedConfig::openConfig()).defaultProfileName(); } setEnvironmentProfile(envProfile); QString errorString; m_analyzedExecutable = iface->executable(launchConfig, errorString).toLocalFile(); if (!errorString.isEmpty()) { setError(-1); setErrorText(errorString); } m_analyzedExecutableArguments = iface->arguments(launchConfig, errorString); if (!errorString.isEmpty()) { setError(-1); setErrorText(errorString); } QUrl workDir = iface->workingDirectory(launchConfig); if (workDir.isEmpty() || !workDir.isValid()) { workDir = QUrl::fromLocalFile(QFileInfo(m_analyzedExecutable).absolutePath()); } setWorkingDirectory(workDir); connect(this, &Job::finished, Plugin::self(), &Plugin::jobFinished); auto tcpServer = new QTcpServer(this); tcpServer->listen(QHostAddress::LocalHost); m_tcpServerPort = tcpServer->serverPort(); connect(tcpServer, &QTcpServer::newConnection, this, [this, tcpServer]() { auto tcpSocket = tcpServer->nextPendingConnection(); connect(tcpSocket, &QTcpSocket::readyRead, this, [this, tcpSocket]() { QStringList lines; while (!tcpSocket->atEnd()) { lines += tcpSocket->readLine().trimmed(); } processValgrindOutput(lines); }); }); connect(this, &Job::finished, this, [this]() { emit hideProgress(this); }); KDevelop::ICore::self()->uiController()->registerStatus(this); } Job::~Job() { } const Tool* Job::tool() const { return m_tool; } QString Job::statusName() const { return i18n("%1 Analysis (%2)", m_tool->name(), QFileInfo(m_analyzedExecutable).fileName()); } void Job::addLoggingArgs(QStringList& args) const { args += QStringLiteral("--log-socket=127.0.0.1:%1").arg(m_tcpServerPort); } QStringList Job::buildCommandLine() const { - CommonSettings settings; - settings.load(m_config); + CommonConfig config; + config.setConfigGroup(m_configGroup); + config.load(); QStringList args; args += QStringLiteral("--tool=%1").arg(m_tool->valgrindToolName()); addLoggingArgs(args); - args += settings.cmdArgs(); + args += config.cmdArgs(); addToolArgs(args); return args; } void Job::start() { - *this << CommonSettings::valgrindExecutablePath(); + *this << KDevelop::Path(GlobalSettings::valgrindExecutablePath()).toLocalFile(); *this << buildCommandLine(); *this << m_analyzedExecutable; *this << m_analyzedExecutableArguments; qCDebug(KDEV_VALGRIND) << "executing:" << commandLine().join(' '); Plugin::self()->jobReadyToStart(this); emit showProgress(this, 0, 0, 0); KDevelop::OutputExecuteJob::start(); } void Job::postProcessStderr(const QStringList& lines) { for (const QString& line : lines) { if (line.startsWith(valgrindErrorsPrefix())) { m_valgrindOutput += line; } } KDevelop::OutputExecuteJob::postProcessStderr(lines); } void Job::processValgrindOutput(const QStringList& lines) { m_valgrindOutput += lines; if (GlobalSettings::showValgrindOutput()) { KDevelop::OutputExecuteJob::postProcessStderr(lines); } } void Job::childProcessExited(int exitCode, QProcess::ExitStatus exitStatus) { qCDebug(KDEV_VALGRIND) << "Process Finished, exitCode" << exitCode << "process exit status" << exitStatus; bool ok = !exitCode; if (ok) { ok = processEnded(); } Plugin::self()->jobReadyToFinish(this, ok); KDevelop::OutputExecuteJob::childProcessExited(exitCode, exitStatus); } void Job::childProcessError(QProcess::ProcessError processError) { QString errorMessage; switch (processError) { case QProcess::FailedToStart: errorMessage = i18n("Failed to start valgrind from \"%1\".", commandLine().at(0)); break; case QProcess::Crashed: // if the process was killed by the user, the crash was expected // don't notify the user if (status() != KDevelop::OutputExecuteJob::JobStatus::JobCanceled) { errorMessage = i18n("Valgrind crashed."); } break; case QProcess::Timedout: errorMessage = i18n("Valgrind process timed out."); break; case QProcess::WriteError: errorMessage = i18n("Write to Valgrind process failed."); break; case QProcess::ReadError: errorMessage = i18n("Read from Valgrind process failed."); break; case QProcess::UnknownError: // Here, check if Valgrind failed (because of bad parameters or whatever). // Because Valgrind always returns 1 on failure, and the profiled application's return // on success, we cannot know for sure which process returned != 0. // // The only way to guess that it is Valgrind which failed is to check stderr and look for // "valgrind: " at the beginning of the first line, even though it can still be the // profiled process that writes it on stderr. It is, however, unlikely enough to be // reliable in most cases. if (!m_valgrindOutput.isEmpty() && m_valgrindOutput.at(0).startsWith(valgrindErrorsPrefix())) { errorMessage = m_valgrindOutput.join('\n').remove(valgrindErrorsPrefix()); errorMessage += QStringLiteral("\n\n"); errorMessage += i18n("Please review your Valgrind launch configuration."); } else { errorMessage = i18n("Unknown Valgrind process error."); } break; } if (!errorMessage.isEmpty()) { KMessageBox::error(activeMainWindow(), errorMessage, i18n("Valgrind Error")); } KDevelop::OutputExecuteJob::childProcessError(processError); } bool Job::processEnded() { return true; } int Job::executeProcess(const QString& executable, const QStringList& args, QByteArray& processOutput) { QString commandLine = executable + QLatin1Char(' ') + args.join(QLatin1Char(' ')); if (GlobalSettings::showValgrindOutput()) { KDevelop::OutputExecuteJob::postProcessStdout({i18n("Executing command: ") + commandLine }); } QProcess process; process.start(executable, args); if (!process.waitForFinished()){ return -1; } processOutput = process.readAllStandardOutput(); QString errOutput(process.readAllStandardError()); if (GlobalSettings::showValgrindOutput()) { KDevelop::OutputExecuteJob::postProcessStdout(QString(processOutput).split('\n')); } KDevelop::OutputExecuteJob::postProcessStderr(errOutput.split('\n')); if (process.exitCode()) { QString message = i18n("Failed to execute the command:"); message += "\n\n"; message += commandLine; message += "\n\n"; message += i18n("Please review your Valgrind launch configuration."); KMessageBox::error(activeMainWindow(), message, i18n("Valgrind Error")); } return process.exitCode(); } } diff --git a/core/job.h b/core/job.h index 7e9e2b5..1b8b5bd 100644 --- a/core/job.h +++ b/core/job.h @@ -1,94 +1,94 @@ /* This file is part of KDevelop Copyright 2006-2008 Hamish Rodda Copyright 2002 Harald Fernengel Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include #include class QWidget; namespace KDevelop { class ILaunchConfiguration; } namespace Valgrind { class Tool; class Job : public KDevelop::OutputExecuteJob, public KDevelop::IStatus { Q_OBJECT Q_INTERFACES(KDevelop::IStatus) public: Job(const Tool* tool, KDevelop::ILaunchConfiguration* launchConfig); ~Job() override; void start() override; using KDevelop::OutputExecuteJob::doKill; const Tool* tool() const; virtual QWidget* createView() = 0; QString statusName() const override; Q_SIGNALS: void clearMessage(KDevelop::IStatus*) override; void hideProgress(KDevelop::IStatus*) override; void showErrorMessage(const QString& message, int timeout = 0) override; void showMessage(KDevelop::IStatus*, const QString& message, int timeout = 0) override; void showProgress(KDevelop::IStatus*, int minimum, int maximum, int value) override; protected: void postProcessStderr(const QStringList& lines) override; virtual void processValgrindOutput(const QStringList& lines); void childProcessExited(int exitCode, QProcess::ExitStatus exitStatus) override; void childProcessError(QProcess::ProcessError processError) override; virtual bool processEnded(); virtual void addLoggingArgs(QStringList& args) const; virtual void addToolArgs(QStringList& args) const = 0; int executeProcess(const QString& executable, const QStringList& args, QByteArray& processOutput); QStringList buildCommandLine() const; const Tool* m_tool; - KConfigGroup m_config; + KConfigGroup m_configGroup; QString m_analyzedExecutable; QStringList m_analyzedExecutableArguments; QStringList m_valgrindOutput; quint16 m_tcpServerPort; }; } diff --git a/core/xmlsettings.cpp b/core/private/common_config.cpp similarity index 66% copy from core/xmlsettings.cpp copy to core/private/common_config.cpp index 6a839eb..055b8da 100644 --- a/core/xmlsettings.cpp +++ b/core/private/common_config.cpp @@ -1,36 +1,35 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "xmlsettings.h" +#include "common_config.h" + +#include "globalsettings.h" namespace Valgrind { -XmlSettings::XmlSettings(const QString& configKeyPrefix) - : Valgrind::Settings(configKeyPrefix) - - , showInstructionPointer( - this, - QStringLiteral("Show Instruction Pointer"), - QStringLiteral(""), - false) +CommonConfig::CommonConfig() + : Config(QStringLiteral("Valgrind")) { + addCmdItemInt(QStringLiteral("numCallers"), m_numCallers, 12, QStringLiteral("num-callers")); + addCmdItemInt(QStringLiteral("maxStackframe"), m_maxStackframe, 2000000, QStringLiteral("max-stackframe")); + addCmdItemBool(QStringLiteral("errorLimit"), m_errorLimit, true, QStringLiteral("error-limit")); } } diff --git a/core/xmlsettings.h b/core/private/common_config.h similarity index 80% rename from core/xmlsettings.h rename to core/private/common_config.h index eee3f74..50fbad9 100644 --- a/core/xmlsettings.h +++ b/core/private/common_config.h @@ -1,38 +1,41 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "settings.h" +#include "config.h" namespace Valgrind { -class XmlSettings : public Settings +class CommonConfig : public Config { -public: - ~XmlSettings() override = default; + Q_OBJECT - BoolValue showInstructionPointer; +public: + CommonConfig(); + ~CommonConfig() override = default; -protected: - explicit XmlSettings(const QString& configKeyPrefix); +private: + int m_numCallers; + int m_maxStackframe; + bool m_errorLimit; }; } diff --git a/core/private/common_configpage.cpp b/core/private/common_configpage.cpp index c1d50ca..e0cdca2 100644 --- a/core/private/common_configpage.cpp +++ b/core/private/common_configpage.cpp @@ -1,91 +1,47 @@ /* This file is part of KDevelop Copyright 2011 Lionel Duc Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "common_configpage.h" #include "ui_common_configpage.h" -#include "common_settings.h" - -#include +#include "common_config.h" namespace Valgrind { CommonConfigPage::CommonConfigPage(QWidget* parent) - : ConfigPage(parent) - , ui(new Ui::CommonConfigPage()) -{ - ui->setupUi(this); - - connectToChanged(ui->extraParameters); - connectToChanged(ui->limitErrors); - connectToChanged(ui->maxStackframe); - connectToChanged(ui->numCallers); - - ui->numCallersLabel->setToolTip(ui->numCallers->toolTip()); - ui->maxStackframeLabel->setToolTip(ui->maxStackframe->toolTip()); -} - -CommonConfigPage::~CommonConfigPage() = default; - -QString CommonConfigPage::title() const -{ - return i18n("Valgrind Generic Settings"); -} - -QIcon CommonConfigPage::icon() const + : ConfigPage(i18n("Valgrind Common Settings"), parent) { - return QIcon(); -} - -void CommonConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) -{ - QSignalBlocker blocker(this); - CommonSettings settings; - settings.load(cfg); - - ui->extraParameters->setText(settings.extraParameters); - ui->numCallers->setValue(settings.numCallers); - ui->maxStackframe->setValue(settings.maxStackframe); - ui->limitErrors->setChecked(settings.limitErrors); -} - -void CommonConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - CommonSettings settings; - - settings.extraParameters = ui->extraParameters->text(); - settings.numCallers = ui->numCallers->value(); - settings.maxStackframe = ui->maxStackframe->value(); - settings.limitErrors = ui->limitErrors->isChecked(); + Ui::CommonConfigPage ui; + ui.setupUi(this); - settings.save(cfg); + init(new CommonConfig); } CommonConfigPageFactory::CommonConfigPageFactory() { } KDevelop::LaunchConfigurationPage* CommonConfigPageFactory::createWidget(QWidget* parent) { return new CommonConfigPage(parent); } } diff --git a/core/private/common_configpage.h b/core/private/common_configpage.h index 60b3320..0731bd0 100644 --- a/core/private/common_configpage.h +++ b/core/private/common_configpage.h @@ -1,58 +1,47 @@ /* This file is part of KDevelop Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" namespace Valgrind { -namespace Ui { class CommonConfigPage; } - class CommonConfigPage : public ConfigPage { Q_OBJECT public: explicit CommonConfigPage(QWidget* parent = nullptr); - ~CommonConfigPage() override; - - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; - -private: - QScopedPointer ui; + ~CommonConfigPage() override = default; }; class CommonConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: CommonConfigPageFactory(); ~CommonConfigPageFactory() override = default; KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; }; } diff --git a/core/private/common_configpage.ui b/core/private/common_configpage.ui index 8d5f389..230944d 100644 --- a/core/private/common_configpage.ui +++ b/core/private/common_configpage.ui @@ -1,133 +1,133 @@ Valgrind::CommonConfigPage 0 0 512 343 Display stac&k to depth: - numCallers + kcfg_numCallers - + <html><head/><body><p>Specifies the maximum number of entries shown in stack traces that identify program locations. Note that errors are commoned up using only the top four function locations (the place in the current function, and that of its three immediate callers). So this doesn't affect the total number of errors reported.</p><p>The maximum value for this is 500. Note that higher settings will make Valgrind run a bit more slowly and take a bit more memory, but can be useful when working with programs with deeply-nested call chains.</p></body></html> 500 12 Maximum size of a stack frame: - maxStackframe + kcfg_maxStackframe - + <html><head/><body><p>The maximum size of a stack frame. If the stack pointer moves by more than this amount then Valgrind will assume that the program is switching to a different stack.</p><p>You may need to use this option if your program has large stack-allocated arrays. Valgrind keeps track of your program's stack pointer. If it changes by more than the threshold amount, Valgrind assumes your program is switching to a different stack, and Memcheck behaves differently than it would for a stack pointer change smaller than the threshold. Usually this heuristic works well. However, if your program allocates large structures on the stack, this heuristic will be fooled, and Memcheck will subsequently report large numbers of invalid stack accesses. This option allows you to change the threshold to a different value.</p><p>You should only consider use of this option if Valgrind's debug output directs you to do so. In that case it will tell you the new threshold you should specify.</p><p>In general, allocating large structures on the stack is a bad idea, because you can easily run out of stack space, especially on systems with limited memory or which expect to support large numbers of threads each with a small stack, and also because the error checking performed by Memcheck is more effective for heap-allocated data than for stack-allocated data. If you have to use this option, you may wish to consider rewriting your code to allocate on the heap rather than on the stack.</p></body></html> 200000000 2000000 - + &Extra parameters: - extraParameters + kcfg_extraArgs - + true Qt::Horizontal - + <html><head/><body><p>When enabled, Valgrind stops reporting errors after 10,000,000 in total, or 1,000 different ones, have been seen. This is to stop the error tracking machinery from becoming a huge performance overhead in programs with many errors.</p></body></html> Limit errors if too many true Qt::Vertical 20 40 - numCallers - maxStackframe - extraParameters - limitErrors + kcfg_numCallers + kcfg_maxStackframe + kcfg_extraArgs + kcfg_errorLimit diff --git a/core/settings.cpp b/core/settings.cpp deleted file mode 100644 index c0288c5..0000000 --- a/core/settings.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "settings.h" - -#include - -#include - -namespace Valgrind -{ - -SettingsBase::SettingsBase(const QString& configKeyPrefix) - : m_configKeyPrefix(configKeyPrefix) -{ -} - -template -SettingsBase::Value::Value( - SettingsBase* settings, - const QString& configKey, - const QString& cmdKey, - const T& defaultValue) - - : m_configKey(configKey) - , m_cmdKey(cmdKey) - , m_value(defaultValue) - , m_defaultValue(defaultValue) -{ - Q_ASSERT(settings); - Q_ASSERT(!configKey.isEmpty()); - - settings->m_values.append(this); -} - -template -SettingsBase::Value::operator const T& () const -{ - return m_value; -} - -template -SettingsBase::Value& SettingsBase::Value::operator=(const T& value) -{ - m_value = value; - return *this; -} - -template -void SettingsBase::Value::load(const KConfigGroup& config, const QString& configKeyPrefix) -{ - m_value = config.readEntry(QStringLiteral("%1 %2").arg(configKeyPrefix).arg(m_configKey), - m_defaultValue); -} - -template -void SettingsBase::Value::save(KConfigGroup& config, const QString& configKeyPrefix) -{ - config.writeEntry(QStringLiteral("%1 %2").arg(configKeyPrefix).arg(m_configKey), - m_value); -} - -inline QString toCmdArg(int value) -{ - return QString::number(value); -} - -inline QString toCmdArg(bool value) -{ - return value ? QStringLiteral("yes") : QStringLiteral("no"); -} - -inline QString toCmdArg(const QString& value) -{ - return value; -} - -template -QString SettingsBase::Value::cmdArg() -{ - if (m_cmdKey.isEmpty()) { - return QStringLiteral(""); - } else { - return QStringLiteral("--%1=%2").arg(m_cmdKey, toCmdArg(m_value)); - } -} - -template class SettingsBase::Value; -template class SettingsBase::Value; -template class SettingsBase::Value; - -Settings::Settings(const QString& configKeyPrefix) - : SettingsBase(configKeyPrefix) - - , extraParameters( - this, - QStringLiteral("Extra Parameters"), - QStringLiteral(""), - QStringLiteral("")) -{ -} - -void Settings::load(const KConfigGroup& config) -{ - for (auto value : qAsConst(m_values)) { - value->load(config, m_configKeyPrefix); - } -} - -void Settings::save(KConfigGroup& config) -{ - for (auto value : qAsConst(m_values)) { - value->save(config, m_configKeyPrefix); - } -} - -QStringList Settings::cmdArgs() -{ - QStringList args; - for (auto value : qAsConst(m_values)) { - args += value->cmdArg(); - } - args += KShell::splitArgs(extraParameters); - args.removeAll(QStringLiteral("")); - - return args; -} - -} diff --git a/core/settings.h b/core/settings.h deleted file mode 100644 index a01ee98..0000000 --- a/core/settings.h +++ /dev/null @@ -1,102 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include - -namespace Valgrind -{ - -class SettingsBase -{ -public: - virtual ~SettingsBase() = default; - -protected: - explicit SettingsBase(const QString& configKeyPrefix); - - class ValueBase; - - template - class Value; - - using IntValue = Value; - using BoolValue = Value; - using StringValue = Value; - - QString m_configKeyPrefix; - QList m_values; -}; - -class SettingsBase::ValueBase -{ - friend class Settings; - -public: - virtual ~ValueBase() = default; - -protected: - virtual void load(const KConfigGroup& config, const QString& configKeyPrefix) = 0; - virtual void save(KConfigGroup& config, const QString& configKeyPrefix) = 0; - virtual QString cmdArg() = 0; -}; - -template -class SettingsBase::Value : public SettingsBase::ValueBase -{ - friend class Settings; - -public: - Value(SettingsBase* settings, const QString& configKey, const QString& cmdKey, const T& defaultValue); - ~Value() override = default; - - operator const T& () const; - Value& operator=(const T& value); - -protected: - void load(const KConfigGroup& config, const QString& configKeyPrefix) override; - void save(KConfigGroup& config, const QString& configKeyPrefix) override; - - QString cmdArg() override; - -private: - QString m_configKey; - QString m_cmdKey; - - T m_value; - T m_defaultValue; -}; - -class Settings : public SettingsBase -{ -public: - StringValue extraParameters; - - void load(const KConfigGroup& config); - void save(KConfigGroup& config); - - QStringList cmdArgs(); - -protected: - explicit Settings(const QString& configKeyPrefix); - ~Settings() override = default; -}; - -} diff --git a/core/tool.cpp b/core/tool.cpp index 934443d..fa68e65 100644 --- a/core/tool.cpp +++ b/core/tool.cpp @@ -1,83 +1,79 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "tool.h" #include "private/launcher.h" namespace Valgrind { Tool::Tool( const QString& id, const QString& name, const QString& fullName, const QString& valgrindToolName, const QString& menuActionName, bool hasView) : m_id(id) , m_name(name) , m_fullName(fullName) , m_valgrindToolName(valgrindToolName) , m_menuActionName(menuActionName) , m_hasView(hasView) { } -Tool::~Tool() -{ -} - QString Tool::name() const { return m_name; } QString Tool::fullName() const { return m_fullName; } QString Tool::valgrindToolName() const { return m_valgrindToolName; } QString Tool::id() const { return m_id; } QString Tool::menuActionName() const { return m_menuActionName; } bool Tool::hasView() const { return m_hasView; } KDevelop::ILauncher* Tool::createLauncher() const { return new Launcher(this); } } diff --git a/core/tool.h b/core/tool.h index fe819c0..afad189 100644 --- a/core/tool.h +++ b/core/tool.h @@ -1,91 +1,91 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include namespace KDevelop { class ILauncher; class ILaunchConfiguration; class LaunchConfigurationPageFactory; } namespace Valgrind { class Job; class Tool { public: - virtual ~Tool(); + virtual ~Tool() = default; /// Short name, used in UI. /// Example: i18n("Memcheck"). QString name() const; /// Full name, used in UI (description). /// Example: i18n("Memcheck: a memory error detector"). QString fullName() const; /// Internal Valgrind tool name, used in jobs. /// Example: "memcheck". QString valgrindToolName() const; - /// Internal id, used as id for launcher and setting names prefix. + /// Internal id, used as id for launcher and config group name. /// Example: "Memcheck". QString id() const; /// "Analyze" menu action name, used when tool action added to action collection. /// Example: "memcheck_tool". QString menuActionName() const; /// True if tool has view bool hasView() const; KDevelop::ILauncher* createLauncher() const; virtual Job* createJob(KDevelop::ILaunchConfiguration* launchConfig) const = 0; virtual KDevelop::LaunchConfigurationPageFactory* createConfigPageFactory() const = 0; protected: Tool( const QString& id, const QString& name, const QString& fullName, const QString& valgrindToolName, const QString& menuActionName, bool hasView ); private: QString m_id; QString m_name; QString m_fullName; QString m_valgrindToolName; QString m_menuActionName; bool m_hasView; }; } diff --git a/core/utils.cpp b/core/utils.cpp index 38bce9e..e83c9e5 100644 --- a/core/utils.cpp +++ b/core/utils.cpp @@ -1,151 +1,150 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "utils.h" #include #include #include #include #include #include #include #include #include #include namespace Valgrind { QString eventFullName(const QString& eventShortName) { static QMap fullNames; static bool initDone = false; if (!initDone) { initDone = true; // full names are from KCachegrind fullNames["Ir" ] = i18n("Instruction Fetch"); fullNames["Dr" ] = i18n("Data Read Access"); fullNames["Dw" ] = i18n("Data Write Access"); fullNames["I1mr"] = i18n("L1 Instr. Fetch Miss"); fullNames["D1mr"] = i18n("L1 Data Read Miss"); fullNames["D1mw"] = i18n("L1 Data Write Miss"); fullNames["ILmr"] = i18n("LL Instr. Fetch Miss"); fullNames["DLmr"] = i18n("LL Data Read Miss"); fullNames["DLmw"] = i18n("LL Data Write Miss"); fullNames["Bc" ] = i18n("Conditional Branch"); fullNames["Bcm" ] = i18n("Mispredicted Cond. Branch"); fullNames["Bi" ] = i18n("Indirect Branch"); fullNames["Bim" ] = i18n("Mispredicted Ind. Branch"); } return fullNames.value(eventShortName, eventShortName); } QString displayValue(int value) { QString result = QString::number(value); int length = result.length(); for (int i = 0; i < (length / 3); ++i) { int pos = result.length() - (4 * i + 3); if (!pos) { break; } result.insert(pos, ' '); } return result; } QString displayValue(double value) { return QString::number(value, 'f', 2); } void emitDataChanged(QAbstractTableModel* model) { Q_ASSERT(model); - emit model->dataChanged(model->index(0,0), model->index(model->rowCount() - 1, model->columnCount() - 1), { Qt::DisplayRole }); } void setupVisualizerProcess( QProcess* visualizerProcess, QPushButton* startButton, std::function startFunction, bool startImmediately) { Q_ASSERT(visualizerProcess); Q_ASSERT(startButton); QObject::connect(startButton, &QPushButton::clicked, startButton, [startFunction]() { startFunction(); }); QObject::connect(visualizerProcess, &QProcess::started, startButton, [startButton]() { startButton->setEnabled(false); }); QObject::connect(visualizerProcess, &QProcess::errorOccurred, startButton, [visualizerProcess, startButton]() { QString errorMessage; if (visualizerProcess->error() == QProcess::FailedToStart) { errorMessage += i18n("Failed to start visualizer from \"%1\".", visualizerProcess->program()); errorMessage += QStringLiteral("\n\n"); errorMessage += i18n("Check your settings and install the visualizer if necessary."); } else { errorMessage += i18n("Error during visualizer execution:"); errorMessage += QStringLiteral("\n\n"); errorMessage += visualizerProcess->errorString(); } KMessageBox::error(activeMainWindow(), errorMessage, i18n("Valgrind Error")); startButton->setEnabled(true); }); QObject::connect(visualizerProcess, static_cast(&QProcess::finished), startButton, [startButton]() { startButton->setEnabled(true); }); if (startImmediately) { startFunction(); } } QWidget* activeMainWindow() { return KDevelop::ICore::self()->uiController()->activeMainWindow(); } QString findExecutable(const QString &executableName) { QString executablePath = QStandardPaths::findExecutable(executableName); return executablePath.isEmpty() ? executableName : executablePath; } } diff --git a/core/utils.h b/core/utils.h index 7d2f7db..719d403 100644 --- a/core/utils.h +++ b/core/utils.h @@ -1,57 +1,58 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include class QAbstractTableModel; class QProcess; class QPushButton; class QWidget; namespace Valgrind { QString eventFullName(const QString& eventShortName); enum ItemDataRole { SortRole = Qt::UserRole + 1 }; static const int rightAlign = int(Qt::AlignRight | Qt::AlignVCenter); QString displayValue(int value); QString displayValue(double value); void emitDataChanged(QAbstractTableModel* model); void setupVisualizerProcess(QProcess* visualizerProcess, QPushButton* startButton, std::function startFunction, bool startImmediately); +// FIXME remove and replace with aApp QWidget* activeMainWindow(); QString findExecutable(const QString &executableName); } diff --git a/core/configpage.h b/core/widgets/combobox.cpp similarity index 63% copy from core/configpage.h copy to core/widgets/combobox.cpp index 5d0d4a2..3e84695 100644 --- a/core/configpage.h +++ b/core/widgets/combobox.cpp @@ -1,48 +1,44 @@ /* This file is part of KDevelop Copyright 2018 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#pragma once - -#include - -class QCheckBox; -class QComboBox; -class QLineEdit; -class QSpinBox; +#include "combobox.h" namespace Valgrind { -class ConfigPage : public KDevelop::LaunchConfigurationPage +ComboBox::ComboBox(QWidget* parent) + : QComboBox(parent) { - Q_OBJECT - -public: - ~ConfigPage() override = default; + connect(this, static_cast(&QComboBox::currentIndexChanged), + this, [this](int index) { + emit valueChanged(itemData(index).toString()); + }); +} -protected: - explicit ConfigPage(QWidget* parent = nullptr); +QString ComboBox::value() const +{ + return currentData().toString(); +} - void connectToChanged(QCheckBox* box); - void connectToChanged(QComboBox* box); - void connectToChanged(QLineEdit* edit); - void connectToChanged(QSpinBox* box); -}; +void ComboBox::setValue(const QString& value) +{ + setCurrentIndex(findData(value)); +} } diff --git a/core/configpage.h b/core/widgets/combobox.h similarity index 66% copy from core/configpage.h copy to core/widgets/combobox.h index 5d0d4a2..d22a431 100644 --- a/core/configpage.h +++ b/core/widgets/combobox.h @@ -1,48 +1,49 @@ /* This file is part of KDevelop Copyright 2018 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include - -class QCheckBox; -class QComboBox; -class QLineEdit; -class QSpinBox; +#include namespace Valgrind { -class ConfigPage : public KDevelop::LaunchConfigurationPage +class ComboBox : public QComboBox { Q_OBJECT + Q_PROPERTY( + QString value + READ value + WRITE setValue + NOTIFY valueChanged + USER true) + public: - ~ConfigPage() override = default; + explicit ComboBox(QWidget* parent = nullptr); + ~ComboBox() override = default; -protected: - explicit ConfigPage(QWidget* parent = nullptr); + QString value() const; + void setValue(const QString& value); - void connectToChanged(QCheckBox* box); - void connectToChanged(QComboBox* box); - void connectToChanged(QLineEdit* edit); - void connectToChanged(QSpinBox* box); +Q_SIGNALS: + void valueChanged(const QString& value); }; } diff --git a/core/widgets/menubutton.cpp b/core/widgets/menubutton.cpp new file mode 100644 index 0000000..47f84b8 --- /dev/null +++ b/core/widgets/menubutton.cpp @@ -0,0 +1,107 @@ +/* This file is part of KDevelop + Copyright 2018 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "menubutton.h" + +#include + +#include + +namespace Valgrind +{ + +MenuButton::MenuButton(QWidget* parent) + : QPushButton(parent) +{ + setMenu(new QMenu(this)); +} + +QAction* MenuButton::addAction(const QString& text, const QString& data) +{ + auto action = new QAction(text, this); + action->setData(data); + action->setCheckable(true); + action->setChecked(false); + + connect(action, &QAction::toggled, this, &MenuButton::updateValue); + + menu()->addAction(action); + updateValue(); + + return action; +} + +QString MenuButton::value() const +{ + return m_value; +} + +void MenuButton::setValue(const QString& value) +{ + if (m_value == value) { + return; + } + + const auto enabled = value.split(QLatin1Char(',')); + const auto actions = menu()->actions(); + + for (auto action : actions) { + QSignalBlocker blocker(action); + + if (value == QStringLiteral("all")) { + action->setChecked(true); + } else if (value == QStringLiteral("none")) { + action->setChecked(false); + } else { + action->setChecked(enabled.contains(action->data().toString())); + } + } + + QSignalBlocker blocker(this); + updateValue(); +} + +void MenuButton::updateValue() +{ + QStringList dataSelected; + QStringList textSelected; + + const auto actions = menu()->actions(); + for (auto action : actions) { + if (action->isChecked()) { + dataSelected += action->data().toString(); + textSelected += action->text(); + } + } + + if (dataSelected.isEmpty()) { + m_value = QStringLiteral("none"); + setText(i18n("none")); + } else if (dataSelected.size() == actions.size()) { + m_value = QStringLiteral("all"); + setText(i18n("all")); + } else { + m_value = dataSelected.join(QLatin1Char(',')); + setText(textSelected.join(QLatin1String(", "))); + } + + emit valueChanged(m_value); +} + +} diff --git a/core/configpage.h b/core/widgets/menubutton.h similarity index 63% copy from core/configpage.h copy to core/widgets/menubutton.h index 5d0d4a2..2c2b5ec 100644 --- a/core/configpage.h +++ b/core/widgets/menubutton.h @@ -1,48 +1,56 @@ /* This file is part of KDevelop Copyright 2018 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include - -class QCheckBox; -class QComboBox; -class QLineEdit; -class QSpinBox; +#include namespace Valgrind { -class ConfigPage : public KDevelop::LaunchConfigurationPage +class MenuButton : public QPushButton { Q_OBJECT + Q_PROPERTY( + QString value + READ value + WRITE setValue + NOTIFY valueChanged + USER true) + public: - ~ConfigPage() override = default; + explicit MenuButton(QWidget* parent = nullptr); + ~MenuButton() override = default; + + QAction* addAction(const QString& text, const QString& data); + + QString value() const; + void setValue(const QString& value); + +Q_SIGNALS: + void valueChanged(const QString& value); -protected: - explicit ConfigPage(QWidget* parent = nullptr); +private: + void updateValue(); - void connectToChanged(QCheckBox* box); - void connectToChanged(QComboBox* box); - void connectToChanged(QLineEdit* edit); - void connectToChanged(QSpinBox* box); + QString m_value; }; } diff --git a/core/xmlsettings.cpp b/core/xmlconfig.cpp similarity index 76% rename from core/xmlsettings.cpp rename to core/xmlconfig.cpp index 6a839eb..f3cd921 100644 --- a/core/xmlsettings.cpp +++ b/core/xmlconfig.cpp @@ -1,36 +1,31 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "xmlsettings.h" +#include "xmlconfig.h" namespace Valgrind { -XmlSettings::XmlSettings(const QString& configKeyPrefix) - : Valgrind::Settings(configKeyPrefix) - - , showInstructionPointer( - this, - QStringLiteral("Show Instruction Pointer"), - QStringLiteral(""), - false) +XmlConfig::XmlConfig(const QString& group) + : Config(group) { + addItemBool(QStringLiteral("showInstructionPointer"), m_showInstructionPointer, false); } } diff --git a/core/private/common_settings.h b/core/xmlconfig.h similarity index 75% rename from core/private/common_settings.h rename to core/xmlconfig.h index 67b8490..6834065 100644 --- a/core/private/common_settings.h +++ b/core/xmlconfig.h @@ -1,41 +1,44 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "settings.h" +#include "config.h" namespace Valgrind { -class CommonSettings : public Settings +class XmlConfig : public Config { public: - CommonSettings(); - ~CommonSettings() override = default; + ~XmlConfig() override = default; - IntValue numCallers; - IntValue maxStackframe; + bool showInstructionPointer() const + { + return m_showInstructionPointer; + } - BoolValue limitErrors; +protected: + explicit XmlConfig(const QString& group); - static QString valgrindExecutablePath(); +private: + bool m_showInstructionPointer; }; } diff --git a/core/xmljob.cpp b/core/xmljob.cpp index 95bdfe3..9d9849c 100644 --- a/core/xmljob.cpp +++ b/core/xmljob.cpp @@ -1,94 +1,94 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "xmljob.h" -#include "xmlsettings.h" +#include "xmlconfig.h" #include "debug.h" #include "tool.h" #include "plugin.h" #include "problemmodel.h" #include "private/xmlparser.h" #include namespace Valgrind { -XmlJob::XmlJob(const Tool* tool, KDevelop::ILaunchConfiguration* launchConfig, XmlSettings* settings) +XmlJob::XmlJob(const Tool* tool, KDevelop::ILaunchConfiguration* launchConfig, XmlConfig* config) : Job(tool, launchConfig) - , m_settings(settings) + , m_config(config) { - Q_ASSERT(m_settings); + Q_ASSERT(m_config); } -XmlJob::~XmlJob() -{ - delete m_settings; -} +XmlJob::~XmlJob() = default; void XmlJob::processValgrindOutput(const QStringList& lines) { static const auto xmlStartRegex = QRegularExpression("\\s*<"); for (const QString& line : lines) { if (line.isEmpty()) { continue; } if (line.indexOf(xmlStartRegex) >= 0) { // the line contains XML m_xmlOutput << line; } } Job::processValgrindOutput(lines); } bool XmlJob::processEnded() { - m_settings->load(m_config); + m_config->setConfigGroup(m_configGroup); + m_config->load(); - auto problems = parseXml(m_tool->name(), m_xmlOutput.join(" "), m_settings->showInstructionPointer); + auto problems = parseXml(m_tool->name(), m_xmlOutput.join(" "), m_config->showInstructionPointer()); Plugin::self()->problemModel()->setProblems(problems); return true; } void XmlJob::addLoggingArgs(QStringList& args) const { args += QStringLiteral("--xml=yes"); args += QStringLiteral("--xml-socket=127.0.0.1:%1").arg(m_tcpServerPort); } void XmlJob::addToolArgs(QStringList& args) const { - m_settings->load(m_config); - args += m_settings->cmdArgs(); + m_config->setConfigGroup(m_configGroup); + m_config->load(); + + args += m_config->cmdArgs(); } QWidget* XmlJob::createView() { return nullptr; } } diff --git a/core/xmljob.h b/core/xmljob.h index ce6a43f..f057fc7 100644 --- a/core/xmljob.h +++ b/core/xmljob.h @@ -1,56 +1,57 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "job.h" namespace Valgrind { -class XmlSettings; +class XmlConfig; class XmlJob : public Job { Q_OBJECT public: ~XmlJob() override; protected: - XmlJob(const Tool* tool, KDevelop::ILaunchConfiguration* launchConfig, XmlSettings* settings); + XmlJob(const Tool* tool, KDevelop::ILaunchConfiguration* launchConfig, XmlConfig* config); QWidget* createView() override final; void processValgrindOutput(const QStringList& lines) override final; bool processEnded() override final; void addLoggingArgs(QStringList& args) const override final; void addToolArgs(QStringList& args) const override final; - XmlSettings* m_settings; +private: + QScopedPointer m_config; QStringList m_xmlOutput; }; } diff --git a/tools/cachegrind/cachegrind_settings.cpp b/tools/cachegrind/cachegrind_config.cpp similarity index 62% rename from tools/cachegrind/cachegrind_settings.cpp rename to tools/cachegrind/cachegrind_config.cpp index fd95109..9c6468d 100644 --- a/tools/cachegrind/cachegrind_settings.cpp +++ b/tools/cachegrind/cachegrind_config.cpp @@ -1,56 +1,42 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "cachegrind_settings.h" +#include "cachegrind_config.h" #include "cachegrind_tool.h" #include "globalsettings.h" namespace Valgrind { -CachegrindSettings::CachegrindSettings() - : Settings(CachegrindTool::self()->id()) - - , cacheSimulation( - this, - QStringLiteral("Cache Simulation"), - QStringLiteral("cache-sim"), - true) - - , branchSimulation( - this, - QStringLiteral("Branch Simulation"), - QStringLiteral("branch-sim"), - false) - - , cgAnnotateParameters( - this, - QStringLiteral("cg_annotate Parameters"), - QStringLiteral(""), - QStringLiteral("")) +CachegrindConfig::CachegrindConfig() + : Config(CachegrindTool::self()->id()) { + addCmdItemBool(QStringLiteral("cacheSim"), m_cacheSim, true, QStringLiteral("cache-sim")); + addCmdItemBool(QStringLiteral("branchSim"), m_branchSim, false, QStringLiteral("branch-sim")); + + addItemString(QStringLiteral("cgAnnotateArgs"), m_cgAnnotateArgs); } -QString CachegrindSettings::cgAnnotateExecutablePath() +QString CachegrindConfig::cgAnnotateExecutablePath() { return KDevelop::Path(GlobalSettings::cg_annotateExecutablePath()).toLocalFile(); } } diff --git a/tools/cachegrind/cachegrind_settings.h b/tools/cachegrind/cachegrind_config.h similarity index 75% rename from tools/cachegrind/cachegrind_settings.h rename to tools/cachegrind/cachegrind_config.h index c7e1ccf..6e9ad1b 100644 --- a/tools/cachegrind/cachegrind_settings.h +++ b/tools/cachegrind/cachegrind_config.h @@ -1,41 +1,48 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "settings.h" +#include "config.h" namespace Valgrind { -class CachegrindSettings : public Settings +class CachegrindConfig : public Config { + Q_OBJECT + public: - CachegrindSettings(); - ~CachegrindSettings() override = default; + CachegrindConfig(); + ~CachegrindConfig() override = default; - BoolValue cacheSimulation; - BoolValue branchSimulation; + static QString cgAnnotateExecutablePath(); - StringValue cgAnnotateParameters; + QString cgAnnotateParameters() const + { + return m_cgAnnotateArgs; + } - static QString cgAnnotateExecutablePath(); +private: + bool m_cacheSim; + bool m_branchSim; + QString m_cgAnnotateArgs; }; } diff --git a/tools/cachegrind/cachegrind_configpage.cpp b/tools/cachegrind/cachegrind_configpage.cpp index 732b37a..1b02167 100644 --- a/tools/cachegrind/cachegrind_configpage.cpp +++ b/tools/cachegrind/cachegrind_configpage.cpp @@ -1,106 +1,49 @@ /* This file is part of KDevelop Copyright 2011 Sebastien Rannou Copyright 2011 Lionel Duc Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "cachegrind_configpage.h" #include "ui_cachegrind_configpage.h" -#include "cachegrind_settings.h" +#include "cachegrind_config.h" #include "cachegrind_tool.h" #include namespace Valgrind { CachegrindConfigPage::CachegrindConfigPage(QWidget* parent) - : ConfigPage(parent) + : ConfigPage(CachegrindTool::self()->name(), parent) , ui(new Ui::CachegrindConfigPage()) { ui->setupUi(this); - connectToChanged(ui->extraParameters); - - connectToChanged(ui->cacheSimulation); - connectToChanged(ui->branchSimulation); - connectToChanged(ui->cgAnnotateParameters); - - connectToChanged(ui->cacheSimulation); - connectToChanged(ui->branchSimulation); + init(new CachegrindConfig); } CachegrindConfigPage::~CachegrindConfigPage() = default; -QString CachegrindConfigPage::title() const -{ - return CachegrindTool::self()->name(); -} - -QIcon CachegrindConfigPage::icon() const -{ - return QIcon(); -} - -void CachegrindConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) -{ - QSignalBlocker blocker(this); - CachegrindSettings settings; - settings.load(cfg); - - ui->extraParameters->setText(settings.extraParameters); - ui->cacheSimulation->setChecked(settings.cacheSimulation); - ui->branchSimulation->setChecked(settings.branchSimulation); - ui->cgAnnotateParameters->setText(settings.cgAnnotateParameters); - - check(); -} - -void CachegrindConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - CachegrindSettings settings; - - settings.extraParameters = ui->extraParameters->text(); - settings.cacheSimulation = ui->cacheSimulation->isChecked(); - settings.branchSimulation = ui->branchSimulation->isChecked(); - settings.cgAnnotateParameters = ui->cgAnnotateParameters->text(); - - settings.save(cfg); -} - void CachegrindConfigPage::check() { - if (!ui->cacheSimulation->isChecked() && !ui->branchSimulation->isChecked()) { - ui->messageWidget->setVisible(true); - return; - } - - ui->messageWidget->setVisible(false); -} - -CachegrindConfigPageFactory::CachegrindConfigPageFactory() -{ -} - -KDevelop::LaunchConfigurationPage* CachegrindConfigPageFactory::createWidget(QWidget* parent) -{ - return new CachegrindConfigPage(parent); + ui->messageWidget->setVisible(!(ui->kcfg_cacheSim->isChecked() || ui->kcfg_branchSim->isChecked())); } } diff --git a/tools/cachegrind/cachegrind_configpage.h b/tools/cachegrind/cachegrind_configpage.h index 28b6b7a..bca67de 100644 --- a/tools/cachegrind/cachegrind_configpage.h +++ b/tools/cachegrind/cachegrind_configpage.h @@ -1,59 +1,59 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" namespace Valgrind { namespace Ui { class CachegrindConfigPage; } class CachegrindConfigPage : public ConfigPage { Q_OBJECT public: explicit CachegrindConfigPage(QWidget* parent = nullptr); ~CachegrindConfigPage() override; - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; - private: - void check(); + void check() override; QScopedPointer ui; }; class CachegrindConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: - CachegrindConfigPageFactory(); + CachegrindConfigPageFactory() + { + } + ~CachegrindConfigPageFactory() override = default; - KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override + { + return new CachegrindConfigPage(parent); + } }; } diff --git a/tools/cachegrind/cachegrind_configpage.ui b/tools/cachegrind/cachegrind_configpage.ui index eadb92f..7f4c4f8 100644 --- a/tools/cachegrind/cachegrind_configpage.ui +++ b/tools/cachegrind/cachegrind_configpage.ui @@ -1,140 +1,140 @@ Valgrind::CachegrindConfigPage 0 0 494 369 - + - + <html><head/><body><p>Enables or disables collection of cache access and miss counts.</p></body></html> Cache simulation false - + <html><head/><body><p>Enables or disables collection of branch instruction and misprediction counts. By default this is disabled as it slows Cachegrind down by approximately 25%. Note that you cannot specify <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--cache-sim=no</span> and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--branch-sim=no</span> together, as that would leave Cachegrind with no information to collect.</p></body></html> Branch simulation false You cannot disable both cache and branch simulation, as that would leave Cachegrind with no information to collect. true false KMessageWidget::Warning Qt::Horizontal - + - + Extra parameters: - extraParameters + kcfg_extraArgs - + true - + cg_annotate parameters: - cgAnnotateParameters + kcfg_cgAnnotateArgs - + true Qt::Vertical 20 40 KMessageWidget QFrame
kmessagewidget.h
- cacheSimulation - branchSimulation - extraParameters - cgAnnotateParameters + kcfg_cacheSim + kcfg_branchSim + kcfg_extraArgs + kcfg_cgAnnotateArgs
diff --git a/tools/cachegrind/cachegrind_job.cpp b/tools/cachegrind/cachegrind_job.cpp index fbab42e..7c7cc26 100644 --- a/tools/cachegrind/cachegrind_job.cpp +++ b/tools/cachegrind/cachegrind_job.cpp @@ -1,91 +1,93 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "cachegrind_job.h" +#include "cachegrind_config.h" #include "cachegrind_model.h" #include "cachegrind_parser.h" -#include "cachegrind_settings.h" #include "cachegrind_tool.h" #include "cachegrind_view.h" #include "plugin.h" #include #include #include #include #include #include namespace Valgrind { CachegrindJob::CachegrindJob(KDevelop::ILaunchConfiguration* launchConfig) : Job(CachegrindTool::self(), launchConfig) , m_model(new CachegrindFunctionsModel) , m_outputFile(new QTemporaryFile(this)) { m_outputFile->open(); } CachegrindJob::~CachegrindJob() { } bool CachegrindJob::processEnded() { - CachegrindSettings settings; - settings.load(m_config); + CachegrindConfig config; + config.setConfigGroup(m_configGroup); + config.load(); QStringList cgArgs; - cgArgs += KShell::splitArgs(settings.cgAnnotateParameters); + cgArgs += KShell::splitArgs(config.cgAnnotateParameters()); cgArgs += m_outputFile->fileName(); QByteArray cgOutput; - if (executeProcess(settings.cgAnnotateExecutablePath(), cgArgs, cgOutput) != 0) { + if (executeProcess(config.cgAnnotateExecutablePath(), cgArgs, cgOutput) != 0) { return false; } cachegrindParse(cgOutput, m_model); return true; } void CachegrindJob::addToolArgs(QStringList& args) const { - CachegrindSettings settings; - settings.load(m_config); + CachegrindConfig config; + config.setConfigGroup(m_configGroup); + config.load(); - args += settings.cmdArgs(); + args += config.cmdArgs(); args += QStringLiteral("--cachegrind-out-file=%1").arg(m_outputFile->fileName()); } QWidget* CachegrindJob::createView() { return new CachegrindView(m_model); } } diff --git a/tools/callgrind/callgrind_settings.cpp b/tools/callgrind/callgrind_config.cpp similarity index 58% rename from tools/callgrind/callgrind_settings.cpp rename to tools/callgrind/callgrind_config.cpp index 4960ad1..95e89fe 100644 --- a/tools/callgrind/callgrind_settings.cpp +++ b/tools/callgrind/callgrind_config.cpp @@ -1,67 +1,48 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "callgrind_settings.h" +#include "callgrind_config.h" #include "globalsettings.h" #include "callgrind_tool.h" namespace Valgrind { -CallgrindSettings::CallgrindSettings() - : Settings(CallgrindTool::self()->id()) - - , cacheSimulation( - this, - QStringLiteral("Cache Simulation"), - QStringLiteral("cache-sim"), - false) - - , branchSimulation( - this, - QStringLiteral("Branch Simulation"), - QStringLiteral("branch-sim"), - false) - - , callgrindAnnotateParameters( - this, - QStringLiteral("callgrind_annotate Parameters"), - QStringLiteral(""), - QStringLiteral("")) - - , launchKCachegrind( - this, - QStringLiteral("Launch KCachegrind"), - QStringLiteral(""), - false) +CallgrindConfig::CallgrindConfig() + : Config(CallgrindTool::self()->id()) { + addCmdItemBool(QStringLiteral("cacheSim"), m_cacheSim, true, QStringLiteral("cache-sim")); + addCmdItemBool(QStringLiteral("branchSim"), m_branchSim, false, QStringLiteral("branch-sim")); + + addItemBool(QStringLiteral("launchKCachegrind"), m_launchKCachegrind); + addItemString(QStringLiteral("callgrindAnnotateArgs"), m_callgrindAnnotateArgs); } -QString CallgrindSettings::callgrindAnnotateExecutablePath() +QString CallgrindConfig::callgrindAnnotateExecutablePath() { return KDevelop::Path(GlobalSettings::callgrind_annotateExecutablePath()).toLocalFile(); } -QString CallgrindSettings::kcachegrindExecutablePath() +QString CallgrindConfig::kcachegrindExecutablePath() { return KDevelop::Path(GlobalSettings::kcachegrindExecutablePath()).toLocalFile(); } } diff --git a/tools/callgrind/callgrind_settings.h b/tools/callgrind/callgrind_config.h similarity index 69% rename from tools/callgrind/callgrind_settings.h rename to tools/callgrind/callgrind_config.h index 7d72c7c..1a536b8 100644 --- a/tools/callgrind/callgrind_settings.h +++ b/tools/callgrind/callgrind_config.h @@ -1,44 +1,55 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "settings.h" +#include "config.h" namespace Valgrind { -class CallgrindSettings : public Settings +class CallgrindConfig : public Config { -public: - CallgrindSettings(); - ~CallgrindSettings() override = default; - - BoolValue cacheSimulation; - BoolValue branchSimulation; - - StringValue callgrindAnnotateParameters; + Q_OBJECT - BoolValue launchKCachegrind; +public: + CallgrindConfig(); + ~CallgrindConfig() override = default; static QString callgrindAnnotateExecutablePath(); static QString kcachegrindExecutablePath(); + + QString callgrindAnnotateArgs() const + { + return m_callgrindAnnotateArgs; + } + + bool launchKCachegrind() const + { + return m_launchKCachegrind; + } + +private: + bool m_cacheSim; + bool m_branchSim; + bool m_launchKCachegrind; + QString m_callgrindAnnotateArgs; }; } diff --git a/tools/callgrind/callgrind_configpage.cpp b/tools/callgrind/callgrind_configpage.cpp index a2b484c..c02ba6b 100644 --- a/tools/callgrind/callgrind_configpage.cpp +++ b/tools/callgrind/callgrind_configpage.cpp @@ -1,92 +1,41 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "callgrind_configpage.h" #include "ui_callgrind_configpage.h" -#include "callgrind_settings.h" +#include "callgrind_config.h" #include "callgrind_tool.h" #include namespace Valgrind { CallgrindConfigPage::CallgrindConfigPage(QWidget* parent) - : ConfigPage(parent) - , ui(new Ui::CallgrindConfigPage()) + : ConfigPage(CallgrindTool::self()->name(), parent) { - ui->setupUi(this); + Ui::CallgrindConfigPage ui; + ui.setupUi(this); - connectToChanged(ui->extraParameters); - connectToChanged(ui->cacheSimulation); - connectToChanged(ui->branchSimulation); - connectToChanged(ui->launchKCachegrind); - connectToChanged(ui->callgrindAnnotateParameters); -} - -CallgrindConfigPage::~CallgrindConfigPage() = default; - -QString CallgrindConfigPage::title() const -{ - return CallgrindTool::self()->name(); -} - -QIcon CallgrindConfigPage::icon() const -{ - return QIcon(); -} - -void CallgrindConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) -{ - QSignalBlocker blocker(this); - CallgrindSettings settings; - settings.load(cfg); - - ui->extraParameters->setText(settings.extraParameters); - ui->cacheSimulation->setChecked(settings.cacheSimulation); - ui->branchSimulation->setChecked(settings.branchSimulation); - ui->launchKCachegrind->setChecked(settings.launchKCachegrind); - ui->callgrindAnnotateParameters->setText(settings.callgrindAnnotateParameters); -} - -void CallgrindConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - CallgrindSettings settings; - - settings.extraParameters = ui->extraParameters->text(); - settings.cacheSimulation = ui->cacheSimulation->isChecked(); - settings.branchSimulation = ui->branchSimulation->isChecked(); - settings.launchKCachegrind = ui->launchKCachegrind->isChecked(); - settings.callgrindAnnotateParameters = ui->callgrindAnnotateParameters->text(); - - settings.save(cfg); -} - -CallgrindConfigPageFactory::CallgrindConfigPageFactory() -{ -} - -KDevelop::LaunchConfigurationPage* CallgrindConfigPageFactory::createWidget(QWidget* parent) -{ - return new CallgrindConfigPage(parent); + init(new CallgrindConfig); } } diff --git a/tools/callgrind/callgrind_configpage.h b/tools/callgrind/callgrind_configpage.h index b534d73..d9991c9 100644 --- a/tools/callgrind/callgrind_configpage.h +++ b/tools/callgrind/callgrind_configpage.h @@ -1,57 +1,52 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" namespace Valgrind { -namespace Ui { class CallgrindConfigPage; } - class CallgrindConfigPage : public ConfigPage { Q_OBJECT public: explicit CallgrindConfigPage(QWidget* parent = nullptr); - ~CallgrindConfigPage() override; - - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; - -private: - QScopedPointer ui; + ~CallgrindConfigPage() override = default; }; class CallgrindConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: - CallgrindConfigPageFactory(); + CallgrindConfigPageFactory() + { + } + ~CallgrindConfigPageFactory() override = default; - KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override + { + return new CallgrindConfigPage(parent); + } }; } diff --git a/tools/callgrind/callgrind_configpage.ui b/tools/callgrind/callgrind_configpage.ui index 16011b7..a6660fa 100644 --- a/tools/callgrind/callgrind_configpage.ui +++ b/tools/callgrind/callgrind_configpage.ui @@ -1,132 +1,132 @@ Valgrind::CallgrindConfigPage 0 0 655 244 - + <html><head/><body><p>Specify if you want to do full cache simulation. By default, only instruction read accesses will be counted (&quot;Ir&quot;). With cache simulation, further event counters are enabled: </p><p>Cache misses on instruction reads (&quot;I1mr&quot;/&quot;ILmr&quot;), </p><p>data read accesses (&quot;Dr&quot;) and related cache misses (&quot;D1mr&quot;/&quot;DLmr&quot;), </p><p>data write accesses (&quot;Dw&quot;) and related cache misses (&quot;D1mw&quot;/&quot;DLmw&quot;).</p></body></html> Cache simulation false - + <html><head/><body><p>Specify if you want to do branch prediction simulation. Further event counters are enabled: Number of executed conditional branches and related predictor misses (&quot;Bc&quot;/&quot;Bcm&quot;), executed indirect jumps and related misses of the jump address predictor (&quot;Bi&quot;/&quot;Bim&quot;).</p></body></html> Branch simulation false Qt::Horizontal - + Extra parameters: - extraParameters + kcfg_extraArgs - + true - + callgrind_annotate parameters: - callgrindAnnotateParameters + kcfg_callgrindAnnotateArgs - + true Qt::Horizontal - + Launch KCachegrind after analysis finish Qt::Vertical 20 40 - cacheSimulation - branchSimulation - extraParameters - callgrindAnnotateParameters - launchKCachegrind + kcfg_cacheSim + kcfg_branchSim + kcfg_extraArgs + kcfg_callgrindAnnotateArgs + kcfg_launchKCachegrind diff --git a/tools/callgrind/callgrind_job.cpp b/tools/callgrind/callgrind_job.cpp index af63e97..5f8cefc 100644 --- a/tools/callgrind/callgrind_job.cpp +++ b/tools/callgrind/callgrind_job.cpp @@ -1,93 +1,95 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2011 Lucas Sarie Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "callgrind_job.h" +#include "callgrind_config.h" #include "callgrind_model.h" #include "callgrind_parser.h" -#include "plugin.h" -#include "callgrind_settings.h" #include "callgrind_tool.h" #include "callgrind_view.h" +#include "plugin.h" #include #include #include #include #include #include namespace Valgrind { CallgrindJob::CallgrindJob(KDevelop::ILaunchConfiguration* launchConfig) : Job(CallgrindTool::self(), launchConfig) , m_model(new CallgrindFunctionsModel) , m_outputFile(new QTemporaryFile(this)) { m_outputFile->open(); } CallgrindJob::~CallgrindJob() { } bool CallgrindJob::processEnded() { - CallgrindSettings settings; - settings.load(m_config); + CallgrindConfig config; + config.setConfigGroup(m_configGroup); + config.load(); QStringList caArgs; - caArgs += KShell::splitArgs(settings.callgrindAnnotateParameters); + caArgs += KShell::splitArgs(config.callgrindAnnotateArgs()); caArgs += QStringLiteral("--tree=calling"); caArgs += QStringLiteral("--threshold=100"); caArgs += m_outputFile->fileName(); QByteArray caOutput; - if (executeProcess(settings.callgrindAnnotateExecutablePath(), caArgs, caOutput)) { + if (executeProcess(config.callgrindAnnotateExecutablePath(), caArgs, caOutput)) { return false; } callgrindParse(caOutput, m_model); return true; } void CallgrindJob::addToolArgs(QStringList& args) const { - CallgrindSettings settings; - settings.load(m_config); + CallgrindConfig config; + config.setConfigGroup(m_configGroup); + config.load(); - args += settings.cmdArgs(); + args += config.cmdArgs(); args += QStringLiteral("--callgrind-out-file=%1").arg(m_outputFile->fileName()); } QWidget* CallgrindJob::createView() { - return new CallgrindView(m_config, m_outputFile, m_model); + return new CallgrindView(m_configGroup, m_outputFile, m_model); } } diff --git a/tools/callgrind/callgrind_view.cpp b/tools/callgrind/callgrind_view.cpp index 0ef1064..0ac0cad 100644 --- a/tools/callgrind/callgrind_view.cpp +++ b/tools/callgrind/callgrind_view.cpp @@ -1,144 +1,145 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2008 Hamish Rodda * Copyright 2011 Lucas Sarie * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "callgrind_view.h" #include "ui_callgrind_view.h" +#include "callgrind_config.h" #include "callgrind_model.h" -#include "callgrind_settings.h" #include "debug.h" #include "utils.h" #include #include #include namespace Valgrind { -CallgrindView::CallgrindView(KConfigGroup config, QTemporaryFile* outputFile, CallgrindFunctionsModel* model, QWidget* parent) +CallgrindView::CallgrindView(KConfigGroup configGroup, QTemporaryFile* outputFile, CallgrindFunctionsModel* model, QWidget* parent) : QWidget(parent) , ui(new Ui::CallgrindView) , m_kcachegrindProcess(new QProcess) { ui->setupUi(this); Q_ASSERT(model); model->setParent(this); Q_ASSERT(outputFile); outputFile->setParent(this); for (const QString& eventType : model->eventTypes()) { ui->eventTypes->addItem(eventFullName(eventType)); } connect(ui->eventTypes, static_cast(&QComboBox::currentIndexChanged), model, &CallgrindFunctionsModel::setCurrentEventType); model->setCurrentEventType(ui->eventTypes->currentIndex()); connect(ui->percenageValues, &QCheckBox::stateChanged, model, &CallgrindFunctionsModel::setPercentageValues); model->setPercentageValues(ui->percenageValues->checkState()); auto functionsProxyModel = new QSortFilterProxyModel(this); functionsProxyModel->setSourceModel(model); functionsProxyModel->setSortRole(SortRole); functionsProxyModel->setFilterKeyColumn(-1); ui->functionsView->setModel(functionsProxyModel); ui->functionsView->setSortingEnabled(true); connect(ui->searchEdit, &QLineEdit::textChanged, functionsProxyModel, &QSortFilterProxyModel::setFilterWildcard); auto eventsModel = new CallgrindFunctionEventsModel(model); ui->eventsView->setModel(eventsModel); ui->eventsView->header()->resizeSections(QHeaderView::ResizeToContents); auto callersModel = new CallgrindFunctionCallersCalleesModel(model, true); auto callersProxyModel = new QSortFilterProxyModel(this); callersProxyModel->setSourceModel(callersModel); callersProxyModel->setSortRole(SortRole); ui->callersView->setModel(callersProxyModel); ui->callersView->setSortingEnabled(true); connect(callersModel, &CallgrindFunctionCallersCalleesModel::headerDataChanged, this, [this](Qt::Orientation, int, int) { ui->callersView->header()->resizeSections(QHeaderView::ResizeToContents); }); auto calleesModel = new CallgrindFunctionCallersCalleesModel(model, false); auto calleesProxyModel = new QSortFilterProxyModel(this); calleesProxyModel->setSourceModel(calleesModel); calleesProxyModel->setSortRole(SortRole); ui->calleesView->setModel(calleesProxyModel); ui->calleesView->setSortingEnabled(true); connect(calleesModel, &CallgrindFunctionCallersCalleesModel::headerDataChanged, this, [this](Qt::Orientation, int, int) { ui->calleesView->header()->resizeSections(QHeaderView::ResizeToContents); }); connect(ui->functionsView->selectionModel(), &QItemSelectionModel::currentChanged, this, [=](const QModelIndex& currentProxyIndex, const QModelIndex&) { auto sourceIndex = functionsProxyModel->mapToSource(currentProxyIndex); auto function = static_cast(sourceIndex.internalPointer()); eventsModel->setFunction(function); callersModel->setFunction(function); calleesModel->setFunction(function); if (function) { ui->binaryLabel->setText(function->binaryFile); ui->sourceLabel->setText(function->sourceFiles.join('\n')); } else { ui->binaryLabel->clear(); ui->sourceLabel->clear(); } }); ui->binaryLabel->clear(); ui->sourceLabel->clear(); if (functionsProxyModel->rowCount()) { ui->functionsView->setCurrentIndex(functionsProxyModel->index(0,0)); } auto startVisualizer = [this, outputFile]() { - m_kcachegrindProcess->start(CallgrindSettings::kcachegrindExecutablePath(), + m_kcachegrindProcess->start(CallgrindConfig::kcachegrindExecutablePath(), { outputFile->fileName() }); }; - CallgrindSettings settings; - settings.load(config); + CallgrindConfig config; + config.setConfigGroup(configGroup); + config.load(); setupVisualizerProcess(m_kcachegrindProcess.data(), ui->launchKCachegrindButton, - startVisualizer, settings.launchKCachegrind); + startVisualizer, config.launchKCachegrind()); } CallgrindView::~CallgrindView() { m_kcachegrindProcess->disconnect(); // FIXME is this really needed ? } } diff --git a/tools/callgrind/callgrind_view.h b/tools/callgrind/callgrind_view.h index ce38dc5..6db6140 100644 --- a/tools/callgrind/callgrind_view.h +++ b/tools/callgrind/callgrind_view.h @@ -1,52 +1,52 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2008 Hamish Rodda * Copyright 2011 Lucas Sarie * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include class QProcess; class QTemporaryFile; namespace Valgrind { namespace Ui { class CallgrindView; } class CallgrindFunctionsModel; class CallgrindView : public QWidget { Q_OBJECT public: - CallgrindView(KConfigGroup config, QTemporaryFile* outputFile, CallgrindFunctionsModel* model, QWidget* parent = nullptr); + CallgrindView(KConfigGroup configGroup, QTemporaryFile* outputFile, CallgrindFunctionsModel* model, QWidget* parent = nullptr); ~CallgrindView() override; private: QScopedPointer ui; QScopedPointer m_kcachegrindProcess; }; } diff --git a/tools/drd/drd_config.cpp b/tools/drd/drd_config.cpp new file mode 100644 index 0000000..b6ac66e --- /dev/null +++ b/tools/drd/drd_config.cpp @@ -0,0 +1,52 @@ +/* This file is part of KDevelop + Copyright 2017 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "drd_config.h" + +#include "drd_tool.h" + +namespace Valgrind +{ + +DrdConfig::DrdConfig() + : XmlConfig(DrdTool::self()->id()) +{ + addCmdItemBool(QStringLiteral("checkStackVar"), m_checkStackVar, false, QStringLiteral("check-stack-var")); + addCmdItemBool(QStringLiteral("firstRaceOnly"), m_firstRaceOnly, false, QStringLiteral("first-race-only")); + addCmdItemBool(QStringLiteral("freeIsWrite"), m_freeIsWrite, false, QStringLiteral("free-is-write")); + addCmdItemBool(QStringLiteral("reportSignalUnlocked"), m_reportSignalUnlocked, true, QStringLiteral("report-signal-unlocked")); + addCmdItemBool(QStringLiteral("segmentMerging"), m_segmentMerging, true, QStringLiteral("segment-merging")); + addCmdItemBool(QStringLiteral("showConflSeg"), m_showConflSeg, true, QStringLiteral("show-confl-seg")); + addCmdItemBool(QStringLiteral("showStackUsage"), m_showStackUsage, false, QStringLiteral("show-stack-usage")); + addCmdItemBool(QStringLiteral("ignoreThreadCreation"), m_ignoreThreadCreation, false, QStringLiteral("ignore-thread-creation")); + + addCmdItemBool(QStringLiteral("traceAlloc"), m_traceAlloc, false, QStringLiteral("trace-alloc")); + addCmdItemBool(QStringLiteral("traceBarrier"), m_traceBarrier, false, QStringLiteral("trace-barrier")); + addCmdItemBool(QStringLiteral("traceCond"), m_traceCond, false, QStringLiteral("trace-cond")); + addCmdItemBool(QStringLiteral("traceForkJoin"), m_traceForkJoin, false, QStringLiteral("trace-fork-join")); + addCmdItemBool(QStringLiteral("traceHb"), m_traceHb, false, QStringLiteral("trace-hb")); + addCmdItemBool(QStringLiteral("traceMutex"), m_traceMutex, false, QStringLiteral("trace-mutex")); + addCmdItemBool(QStringLiteral("traceRwlock"), m_traceRwlock, false, QStringLiteral("trace-rwlock")); + addCmdItemBool(QStringLiteral("traceSemaphore"), m_traceSemaphore, false, QStringLiteral("trace-semaphore")); + + addCmdItemInt(QStringLiteral("joinListVol"), m_joinListVol, 10, QStringLiteral("join-list-vol")); + addCmdItemInt(QStringLiteral("segmentMergingInterval"), m_segmentMergingInterval, 10, QStringLiteral("segment-merging-interval")); +} + +} diff --git a/tools/helgrind/helgrind_settings.h b/tools/drd/drd_config.h similarity index 59% copy from tools/helgrind/helgrind_settings.h copy to tools/drd/drd_config.h index b1025d6..1916132 100644 --- a/tools/helgrind/helgrind_settings.h +++ b/tools/drd/drd_config.h @@ -1,43 +1,57 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "xmlsettings.h" +#include "xmlconfig.h" namespace Valgrind { -class HelgrindSettings : public XmlSettings +class DrdConfig : public XmlConfig { -public: - HelgrindSettings(); - ~HelgrindSettings() override = default; - - StringValue historyLevel; + Q_OBJECT - IntValue conflictCacheSize; - - BoolValue trackLockorders; - BoolValue checkStackRefs; - BoolValue ignoreThreadCreation; - BoolValue freeIsWrite; +public: + DrdConfig(); + ~DrdConfig() override = default; + +private: + bool m_checkStackVar; + bool m_firstRaceOnly; + bool m_freeIsWrite; + bool m_reportSignalUnlocked; + bool m_segmentMerging; + bool m_showConflSeg; + bool m_showStackUsage; + bool m_ignoreThreadCreation; + bool m_traceAlloc; + bool m_traceBarrier; + bool m_traceCond; + bool m_traceForkJoin; + bool m_traceHb; + bool m_traceMutex; + bool m_traceRwlock; + bool m_traceSemaphore; + + int m_joinListVol; + int m_segmentMergingInterval; }; } diff --git a/tools/drd/drd_configpage.cpp b/tools/drd/drd_configpage.cpp index 2f03870..6e87e8c 100644 --- a/tools/drd/drd_configpage.cpp +++ b/tools/drd/drd_configpage.cpp @@ -1,143 +1,39 @@ /* This file is part of KDevelop * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "drd_configpage.h" #include "ui_drd_configpage.h" -#include "drd_settings.h" +#include "drd_config.h" #include "drd_tool.h" -#include - namespace Valgrind { DrdConfigPage::DrdConfigPage(QWidget* parent) - : ConfigPage(parent) - , ui(new Ui::DrdConfigPage()) -{ - ui->setupUi(this); - - connectToChanged(ui->joinListVol); - connectToChanged(ui->segmentMergingInterval); - - connectToChanged(ui->checkStackVar); - connectToChanged(ui->firstRaceOnly); - connectToChanged(ui->freeIsWrite); - connectToChanged(ui->reportSignalUnlocked); - connectToChanged(ui->segmentMerging); - connectToChanged(ui->showConflSeg); - connectToChanged(ui->showStackUsage); - connectToChanged(ui->ignoreThreadCreation); - connectToChanged(ui->showInstructionPointer); - - connectToChanged(ui->traceAlloc); - connectToChanged(ui->traceBarrier); - connectToChanged(ui->traceCond); - connectToChanged(ui->traceForkJoin); - connectToChanged(ui->traceHb); - connectToChanged(ui->traceMutex); - connectToChanged(ui->traceRwlock); - connectToChanged(ui->traceSemaphore); - - ui->joinListVolLabel->setToolTip(ui->joinListVol->toolTip()); - ui->segmentMergingIntervalLabel->setToolTip(ui->segmentMergingInterval->toolTip()); -} - -DrdConfigPage::~DrdConfigPage() = default; - -QString DrdConfigPage::title() const -{ - return DrdTool::self()->name(); -} - -QIcon DrdConfigPage::icon() const -{ - return QIcon(); -} - -void DrdConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) + : ConfigPage(DrdTool::self()->name(), parent) { - QSignalBlocker blocker(this); - DrdSettings settings; - settings.load(cfg); + Ui::DrdConfigPage ui; + ui.setupUi(this); - ui->joinListVol->setValue(settings.joinListVol); - ui->segmentMergingInterval->setValue(settings.segmentMergingInterval); - - ui->checkStackVar->setChecked(settings.checkStackVar); - ui->firstRaceOnly->setChecked(settings.firstRaceOnly); - ui->freeIsWrite->setChecked(settings.freeIsWrite); - ui->reportSignalUnlocked->setChecked(settings.reportSignalUnlocked); - ui->segmentMerging->setChecked(settings.segmentMerging); - ui->showConflSeg->setChecked(settings.showConflSeg); - ui->showStackUsage->setChecked(settings.showStackUsage); - ui->ignoreThreadCreation->setChecked(settings.ignoreThreadCreation); - ui->showInstructionPointer->setChecked(settings.showInstructionPointer); - - ui->traceAlloc->setChecked(settings.traceAlloc); - ui->traceBarrier->setChecked(settings.traceBarrier); - ui->traceCond->setChecked(settings.traceCond); - ui->traceForkJoin->setChecked(settings.traceForkJoin); - ui->traceHb->setChecked(settings.traceHb); - ui->traceMutex->setChecked(settings.traceMutex); - ui->traceRwlock->setChecked(settings.traceRwlock); - ui->traceSemaphore->setChecked(settings.traceSemaphore); -} - -void DrdConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - DrdSettings settings; - - settings.joinListVol = ui->joinListVol->value(); - settings.segmentMergingInterval = ui->segmentMergingInterval->value(); - - settings.checkStackVar = ui->checkStackVar->isChecked(); - settings.firstRaceOnly = ui->firstRaceOnly->isChecked(); - settings.freeIsWrite = ui->freeIsWrite->isChecked(); - settings.reportSignalUnlocked = ui->reportSignalUnlocked->isChecked(); - settings.segmentMerging = ui->segmentMerging->isChecked(); - settings.showConflSeg = ui->showConflSeg->isChecked(); - settings.showStackUsage = ui->showStackUsage->isChecked(); - settings.ignoreThreadCreation = ui->ignoreThreadCreation->isChecked(); - settings.showInstructionPointer = ui->showInstructionPointer->isChecked(); - - settings.traceAlloc = ui->traceAlloc->isChecked(); - settings.traceBarrier = ui->traceBarrier->isChecked(); - settings.traceCond = ui->traceCond->isChecked(); - settings.traceForkJoin = ui->traceForkJoin->isChecked(); - settings.traceHb = ui->traceHb->isChecked(); - settings.traceMutex = ui->traceMutex->isChecked(); - settings.traceRwlock = ui->traceRwlock->isChecked(); - settings.traceSemaphore = ui->traceSemaphore->isChecked(); - - settings.save(cfg); -} - -DrdConfigPageFactory::DrdConfigPageFactory() -{ -} - -KDevelop::LaunchConfigurationPage* DrdConfigPageFactory::createWidget(QWidget* parent) -{ - return new DrdConfigPage(parent); + init(new DrdConfig); } } diff --git a/tools/drd/drd_configpage.h b/tools/drd/drd_configpage.h index db77c2d..e992b5a 100644 --- a/tools/drd/drd_configpage.h +++ b/tools/drd/drd_configpage.h @@ -1,56 +1,51 @@ /* This file is part of KDevelop * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" namespace Valgrind { -namespace Ui { class DrdConfigPage; } - class DrdConfigPage : public ConfigPage { Q_OBJECT public: explicit DrdConfigPage(QWidget* parent = nullptr); - ~DrdConfigPage() override; - - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; - -private: - QScopedPointer ui; + ~DrdConfigPage() override = default; }; class DrdConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: - DrdConfigPageFactory(); + DrdConfigPageFactory() + { + } + ~DrdConfigPageFactory() override = default; - KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override + { + return new DrdConfigPage(parent); + } }; } diff --git a/tools/drd/drd_configpage.ui b/tools/drd/drd_configpage.ui index d900201..62d37f2 100644 --- a/tools/drd/drd_configpage.ui +++ b/tools/drd/drd_configpage.ui @@ -1,350 +1,350 @@ Valgrind::DrdConfigPage 0 0 676 558 Joined threads memory access list volume: - joinListVol + kcfg_joinListVol - + <html><head/><body><p>Data races that occur between a statement at the end of one thread and another thread can be missed if memory access information is discarded immediately after a thread has been joined. This option allows to specify for how many joined threads memory access information should be retained.</p></body></html> 1 1000 10 Segment merging interval: - + <html><head/><body><p>Perform segment merging only after the specified number of new segments have been created. This is an advanced configuration option that allows to choose whether to minimize DRD's memory usage by choosing a low value or to let DRD run faster by choosing a slightly higher value. The optimal value for this parameter depends on the program being analyzed. The default value works well for most programs.</p></body></html> 1000000 10 - + Extra parameters: - extraParameters + kcfg_extraArgs - + true 0 Common options - + <html><head/><body><p>Controls whether DRD detects data races on stack variables. Verifying stack variables is disabled by default because most programs do not share stack variables over threads.</p></body></html> Detect data races on stack variables - + <html><head/><body><p>Whether to report only the first data race that has been detected on a memory location or all data races that have been detected on a memory location.</p></body></html> Report only the first data race - + true <html><head/><body><p>Whether to report races between accessing memory and freeing memory. Enabling this option may cause DRD to run slightly slower. Notes:</p><p>Don't enable this option when using custom memory allocators that use the <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">VG_USERREQ__MALLOCLIKE_BLOCK</span> and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">VG_USERREQ__FREELIKE_BLOCK</span> because that would result in false positives. </p><p>Don't enable this option when using reference-counted objects because that will result in false positives, even when that code has been annotated properly with <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">ANNOTATE_HAPPENS_BEFORE</span> and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">ANNOTATE_HAPPENS_AFTER</span>. See e.g. the output of the following command for an example: <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">valgrind --tool=drd --free-is-write=yes drd/tests/annotate_smart_pointer</span>.</p></body></html> Report races between accessing and freeing memory - + <html><head/><body><p>Whether to report calls to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">pthread_cond_signal</span> and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">pthread_cond_broadcast</span> where the mutex associated with the signal through <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">pthread_cond_wait</span> or <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">pthread_cond_timed_wait</span> is not locked at the time the signal is sent. Sending a signal without holding a lock on the associated mutex is a common programming error which can cause subtle race conditions and unpredictable behavior. There exist some uncommon synchronization patterns however where it is safe to send a signal without holding a lock on the associated mutex.</p></body></html> Report calls to unlocked signals - + <html><head/><body><p>Controls segment merging. Segment merging is an algorithm to limit memory usage of the data race detection algorithm. Disabling segment merging may improve the accuracy of the so-called 'other segments' displayed in race reports but can also trigger an out of memory error.</p></body></html> Segment merging - + <html><head/><body><p>Show conflicting segments in race reports. Since this information can help to find the cause of a data race, this option is enabled by default. Disabling this option makes the output of DRD more compact.</p></body></html> Show conflicting segments - + <html><head/><body><p>Print stack usage at thread exit time. When a program creates a large number of threads it becomes important to limit the amount of virtual memory allocated for thread stacks. This option makes it possible to observe how much stack memory has been used by each thread of the client program.</p><p>Note: the DRD tool itself allocates some temporary data on the client thread stack. The space necessary for this temporary data must be allocated by the client program when it allocates stack memory, but is not included in stack usage reported by DRD.</p></body></html> Show stack usage - + <html><head/><body><p>Controls whether all activities during thread creation should be ignored. By default enabled only on Solaris. Solaris provides higher throughput, parallelism and scalability than other operating systems, at the cost of more fine-grained locking activity. This means for example that when a thread is created under glibc, just one big lock is used for all thread setup. Solaris libc uses several fine-grained locks and the creator thread resumes its activities as soon as possible, leaving for example stack and TLS setup sequence to the created thread. This situation confuses DRD as it assumes there is some false ordering in place between creator and created thread; and therefore many types of race conditions in the application would not be reported. To prevent such false ordering, this command line option is set to <span style=" font-family:'Monospace';">yes</span> by default on Solaris. All activity (loads, stores, client requests) is therefore ignored during:</p><p>* pthread_create() call in the creator thread </p><p>* thread creation phase (stack and TLS setup) in the created thread</p></body></html> Ignore thread creation Qt::Horizontal - + Show stack frame instruction pointer value Qt::Vertical 20 0 Trace options - + <html><head/><body><p>Trace all memory allocations and deallocations. May produce a huge amount of output.</p></body></html> Trace memory allocations/deallocations - + <html><head/><body><p>Trace all barrier activity.</p></body></html> Trace barrier activity - + <html><head/><body><p>Trace all condition variable activity.</p></body></html> Trace condition variable activity - + <html><head/><body><p>Trace all thread creation and all thread termination events.</p></body></html> Trace thread creation/termination events - + <html><head/><body><p>Trace execution of the <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">ANNOTATE_HAPPENS_BEFORE()</span>, <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">ANNOTATE_HAPPENS_AFTER()</span> and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">ANNOTATE_HAPPENS_DONE()</span> client requests.</p></body></html> Trace execution of "ANNOTATE_HAPPENS" requests - + <html><head/><body><p>Trace all mutex activity.</p></body></html> Trace mutex activity - + <html><head/><body><p>Trace all reader-writer lock activity.</p></body></html> Trace reader-writer lock activity - + <html><head/><body><p>Trace all semaphore activity.</p></body></html> Trace semaphore activity Qt::Vertical 20 0 Qt::Vertical 20 52 - joinListVol - segmentMergingInterval - extraParameters + kcfg_joinListVol + kcfg_segmentMergingInterval + kcfg_extraArgs tabWidget - checkStackVar - firstRaceOnly - freeIsWrite - reportSignalUnlocked - segmentMerging - showConflSeg - showStackUsage - ignoreThreadCreation - showInstructionPointer - traceAlloc - traceBarrier - traceCond - traceForkJoin - traceHb - traceMutex - traceRwlock - traceSemaphore + kcfg_checkStackVar + kcfg_firstRaceOnly + kcfg_freeIsWrite + kcfg_reportSignalUnlocked + kcfg_segmentMerging + kcfg_showConflSeg + kcfg_showStackUsage + kcfg_ignoreThreadCreation + kcfg_showInstructionPointer + kcfg_traceAlloc + kcfg_traceBarrier + kcfg_traceCond + kcfg_traceForkJoin + kcfg_traceHb + kcfg_traceMutex + kcfg_traceRwlock + kcfg_traceSemaphore diff --git a/tools/drd/drd_job.cpp b/tools/drd/drd_job.cpp index e0ab2d8..1c0e246 100644 --- a/tools/drd/drd_job.cpp +++ b/tools/drd/drd_job.cpp @@ -1,34 +1,34 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "drd_job.h" #include "debug.h" -#include "drd_settings.h" +#include "drd_config.h" #include "drd_tool.h" namespace Valgrind { DrdJob::DrdJob(KDevelop::ILaunchConfiguration* launchConfig) - : XmlJob(DrdTool::self(), launchConfig, new DrdSettings) + : XmlJob(DrdTool::self(), launchConfig, new DrdConfig) { } } diff --git a/tools/drd/drd_settings.cpp b/tools/drd/drd_settings.cpp deleted file mode 100644 index a6c6534..0000000 --- a/tools/drd/drd_settings.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "drd_settings.h" - -#include "drd_tool.h" - -namespace Valgrind -{ - -DrdSettings::DrdSettings() - : XmlSettings(DrdTool::self()->id()) - - , checkStackVar( - this, - QStringLiteral("Check Stack Variables"), - QStringLiteral("check-stack-var"), - false) - - , firstRaceOnly( - this, - QStringLiteral("First Race Only"), - QStringLiteral("first-race-only"), - false) - - , freeIsWrite( - this, - QStringLiteral("Free is Write"), - QStringLiteral("free-is-write"), - false) - - , reportSignalUnlocked( - this, - QStringLiteral("Report Signal Unlocked"), - QStringLiteral("report-signal-unlocked"), - true) - - , segmentMerging( - this, - QStringLiteral("Segment Merging"), - QStringLiteral("segment-merging"), - true) - - , showConflSeg( - this, - QStringLiteral("Show Conflicting Segments"), - QStringLiteral("show-confl-seg"), - true) - - , showStackUsage( - this, - QStringLiteral("Show Stack Usage"), - QStringLiteral("show-stack-usage"), - false) - - , ignoreThreadCreation( - this, - QStringLiteral("Ignore Thread Creation"), - QStringLiteral("ignore-thread-creation"), - false) - - , traceAlloc( - this, - QStringLiteral("Trace Allocations"), - QStringLiteral("trace-alloc"), - false) - - , traceBarrier( - this, - QStringLiteral("Trace Barrier Activity"), - QStringLiteral("trace-barrier"), - false) - - , traceCond( - this, - QStringLiteral("Trace Condition Variable Activity"), - QStringLiteral("trace-cond"), - false) - - , traceForkJoin( - this, - QStringLiteral("Trace Thread Creation and Termination"), - QStringLiteral("trace-fork-join"), - false) - - , traceHb( - this, - QStringLiteral("Trace HB"), - QStringLiteral("trace-hb"), - false) - - , traceMutex( - this, - QStringLiteral("Trace Mutex Activity"), - QStringLiteral("trace-mutex"), - false) - - , traceRwlock( - this, - QStringLiteral("Trace ReaderWriter Lock Activity"), - QStringLiteral("trace-rwlock"), - false) - - , traceSemaphore( - this, - QStringLiteral("Trace Semaphore Activity"), - QStringLiteral("trace-semaphore"), - false) - - , joinListVol( - this, - QStringLiteral("Joined Threads Memory Access List Volume"), - QStringLiteral("join-list-vol"), - 10) - - , segmentMergingInterval( - this, - QStringLiteral("Segment Merging Interval"), - QStringLiteral("segment-merging-interval"), - 10) -{ -} - -} diff --git a/tools/drd/drd_settings.h b/tools/drd/drd_settings.h deleted file mode 100644 index 82a1e61..0000000 --- a/tools/drd/drd_settings.h +++ /dev/null @@ -1,54 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include "xmlsettings.h" - -namespace Valgrind -{ - -class DrdSettings : public XmlSettings -{ -public: - DrdSettings(); - ~DrdSettings() override = default; - - BoolValue checkStackVar; - BoolValue firstRaceOnly; - BoolValue freeIsWrite; - BoolValue reportSignalUnlocked; - BoolValue segmentMerging; - BoolValue showConflSeg; - BoolValue showStackUsage; - BoolValue ignoreThreadCreation; - BoolValue traceAlloc; - BoolValue traceBarrier; - BoolValue traceCond; - BoolValue traceForkJoin; - BoolValue traceHb; - BoolValue traceMutex; - BoolValue traceRwlock; - BoolValue traceSemaphore; - - IntValue joinListVol; - IntValue segmentMergingInterval; -}; - -} diff --git a/core/private/common_settings.cpp b/tools/helgrind/helgrind_config.cpp similarity index 50% rename from core/private/common_settings.cpp rename to tools/helgrind/helgrind_config.cpp index 915f392..d8a0162 100644 --- a/core/private/common_settings.cpp +++ b/tools/helgrind/helgrind_config.cpp @@ -1,55 +1,40 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "common_settings.h" +#include "helgrind_config.h" -#include "globalsettings.h" +#include "helgrind_tool.h" namespace Valgrind { -CommonSettings::CommonSettings() - : Settings(QStringLiteral("Valgrind")) - - , numCallers( - this, - QStringLiteral("Stackframe Depth"), - QStringLiteral("num-callers"), - 12) - - , maxStackframe( - this, - QStringLiteral("Maximum Stackframe Size"), - QStringLiteral("max-stackframe"), - 2000000) - - , limitErrors( - this, - QStringLiteral("Limit Errors"), - QStringLiteral("error-limit"), - true) +HelgrindConfig::HelgrindConfig() + : XmlConfig(HelgrindTool::self()->id()) { -} + addCmdItemString(QStringLiteral("historyLevel"), m_historyLevel, QStringLiteral("full"), QStringLiteral("history-level")); -QString CommonSettings::valgrindExecutablePath() -{ - return KDevelop::Path(GlobalSettings::valgrindExecutablePath()).toLocalFile(); + addCmdItemInt(QStringLiteral("conflictCacheSize"), m_conflictCacheSize, 1000000, QStringLiteral("conflict-cache-size")); + + addCmdItemBool(QStringLiteral("trackLockorders"), m_trackLockorders, true, QStringLiteral("track-lockorders")); + addCmdItemBool(QStringLiteral("checkStackRefs"), m_checkStackRefs, true, QStringLiteral("check-stack-refs")); + addCmdItemBool(QStringLiteral("ignoreThreadCreation"), m_ignoreThreadCreation, false, QStringLiteral("ignore-thread-creation")); + addCmdItemBool(QStringLiteral("freeIsWrite"), m_freeIsWrite, false, QStringLiteral("free-is-write")); } } diff --git a/tools/helgrind/helgrind_settings.h b/tools/helgrind/helgrind_config.h similarity index 73% copy from tools/helgrind/helgrind_settings.h copy to tools/helgrind/helgrind_config.h index b1025d6..8086298 100644 --- a/tools/helgrind/helgrind_settings.h +++ b/tools/helgrind/helgrind_config.h @@ -1,43 +1,44 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "xmlsettings.h" +#include "xmlconfig.h" namespace Valgrind { -class HelgrindSettings : public XmlSettings +class HelgrindConfig : public XmlConfig { public: - HelgrindSettings(); - ~HelgrindSettings() override = default; + HelgrindConfig(); + ~HelgrindConfig() override = default; - StringValue historyLevel; +private: + QString m_historyLevel; - IntValue conflictCacheSize; + int m_conflictCacheSize; - BoolValue trackLockorders; - BoolValue checkStackRefs; - BoolValue ignoreThreadCreation; - BoolValue freeIsWrite; + bool m_trackLockorders; + bool m_checkStackRefs; + bool m_ignoreThreadCreation; + bool m_freeIsWrite; }; } diff --git a/tools/helgrind/helgrind_configpage.cpp b/tools/helgrind/helgrind_configpage.cpp index 3392d36..7e3ef02 100644 --- a/tools/helgrind/helgrind_configpage.cpp +++ b/tools/helgrind/helgrind_configpage.cpp @@ -1,107 +1,43 @@ /* This file is part of KDevelop * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "helgrind_configpage.h" #include "ui_helgrind_configpage.h" -#include "helgrind_settings.h" +#include "helgrind_config.h" #include "helgrind_tool.h" -#include - namespace Valgrind { HelgrindConfigPage::HelgrindConfigPage(QWidget* parent) - : ConfigPage(parent) - , ui(new Ui::HelgrindConfigPage()) -{ - ui->setupUi(this); - - connectToChanged(ui->extraParameters); - connectToChanged(ui->conflictCacheSize); - connectToChanged(ui->historyLevel); - - connectToChanged(ui->trackLockorders); - connectToChanged(ui->checkStackRefs); - connectToChanged(ui->ignoreThreadCreation); - connectToChanged(ui->freeIsWrite); - connectToChanged(ui->showInstructionPointer); - - ui->historyLevelLabel->setToolTip(ui->historyLevel->toolTip()); - ui->conflictCacheSizeLabel->setToolTip(ui->conflictCacheSize->toolTip()); -} - -HelgrindConfigPage::~HelgrindConfigPage() = default; - -QString HelgrindConfigPage::title() const -{ - return HelgrindTool::self()->name(); -} - -QIcon HelgrindConfigPage::icon() const -{ - return QIcon(); -} - -void HelgrindConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) + : ConfigPage(HelgrindTool::self()->name(), parent) { - QSignalBlocker blocker(this); - HelgrindSettings settings; - settings.load(cfg); - - ui->extraParameters->setText(settings.extraParameters); - ui->conflictCacheSize->setValue(settings.conflictCacheSize); - ui->historyLevel->setCurrentText(settings.historyLevel); - - ui->trackLockorders->setChecked(settings.trackLockorders); - ui->checkStackRefs->setChecked(settings.checkStackRefs); - ui->ignoreThreadCreation->setChecked(settings.ignoreThreadCreation); - ui->freeIsWrite->setChecked(settings.freeIsWrite); - ui->showInstructionPointer->setChecked(settings.showInstructionPointer); -} - -void HelgrindConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - HelgrindSettings settings; - - settings.extraParameters = ui->extraParameters->text(); - settings.conflictCacheSize = ui->conflictCacheSize->value(); - settings.historyLevel = ui->historyLevel->currentText(); + Ui::HelgrindConfigPage ui; + ui.setupUi(this); - settings.trackLockorders = ui->trackLockorders->isChecked(); - settings.checkStackRefs = ui->checkStackRefs->isChecked(); - settings.ignoreThreadCreation = ui->ignoreThreadCreation->isChecked(); - settings.freeIsWrite = ui->freeIsWrite->isChecked(); - settings.showInstructionPointer = ui->showInstructionPointer->isChecked(); + ui.kcfg_historyLevel->addItem(i18n("Full"), QStringLiteral("full")); + ui.kcfg_historyLevel->addItem(i18n("Approx"), QStringLiteral("approx")); + ui.kcfg_historyLevel->addItem(i18n("None"), QStringLiteral("none")); - settings.save(cfg); -} - -HelgrindConfigPageFactory::HelgrindConfigPageFactory() -{ -} - -KDevelop::LaunchConfigurationPage* HelgrindConfigPageFactory::createWidget(QWidget* parent) -{ - return new HelgrindConfigPage(parent); + init(new HelgrindConfig); } } diff --git a/tools/helgrind/helgrind_configpage.h b/tools/helgrind/helgrind_configpage.h index 6774ef3..21a3452 100644 --- a/tools/helgrind/helgrind_configpage.h +++ b/tools/helgrind/helgrind_configpage.h @@ -1,56 +1,51 @@ /* This file is part of KDevelop * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" namespace Valgrind { -namespace Ui { class HelgrindConfigPage; } - class HelgrindConfigPage : public ConfigPage { Q_OBJECT public: explicit HelgrindConfigPage(QWidget* parent = nullptr); - ~HelgrindConfigPage() override; - - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; - -private: - QScopedPointer ui; + ~HelgrindConfigPage() override = default; }; class HelgrindConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: - HelgrindConfigPageFactory(); + HelgrindConfigPageFactory() + { + } + ~HelgrindConfigPageFactory() override = default; - KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override + { + return new HelgrindConfigPage(parent); + } }; } diff --git a/tools/helgrind/helgrind_configpage.ui b/tools/helgrind/helgrind_configpage.ui index c41d0ea..ea64793 100644 --- a/tools/helgrind/helgrind_configpage.ui +++ b/tools/helgrind/helgrind_configpage.ui @@ -1,205 +1,183 @@ Valgrind::HelgrindConfigPage 0 0 469 380 History level: - - historyLevel - - - - - - - <html><head/><body><p><span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=full</span> (the default) causes Helgrind collects enough information about &quot;old&quot; accesses that it can produce two stack traces in a race report -- both the stack trace for the current access, and the trace for the older, conflicting access. To limit memory usage, &quot;old&quot; accesses stack traces are limited to a maximum of 8 entries, even if <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--num-callers</span> value is bigger.</p><p>Collecting such information is expensive in both speed and memory, particularly for programs that do many inter-thread synchronization events (locks, unlocks, etc). Without such information, it is more difficult to track down the root causes of races. Nonetheless, you may not need it in situations where you just want to check for the presence or absence of races, for example, when doing regression testing of a previously race-free program.</p><p><span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=none</span> is the opposite extreme. It causes Helgrind not to collect any information about previous accesses. This can be dramatically faster than <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=full</span>.</p><p><span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=approx</span> provides a compromise between these two extremes. It causes Helgrind to show a full trace for the later access, and approximate information regarding the earlier access. This approximate information consists of two stacks, and the earlier access is guaranteed to have occurred somewhere between program points denoted by the two stacks. This is not as useful as showing the exact stack for the previous access (as <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=full</span> does), but it is better than nothing, and it is almost as fast as <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=none</span>.</p></body></html> - - - - full - - - - - approx - - - - - none - - Conflict cache size: - conflictCacheSize + kcfg_conflictCacheSize - + <html><head/><body><p>This flag only has any effect at <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--history-level=full</span>.</p><p>Information about &quot;old&quot; conflicting accesses is stored in a cache of limited size, with LRU-style management. This is necessary because it isn't practical to store a stack trace for every single memory access made by the program. Historical information on not recently accessed locations is periodically discarded, to free up space in the cache.</p><p>This option controls the size of the cache, in terms of the number of different memory addresses for which conflicting access information is stored. If you find that Helgrind is showing race errors with only one stack instead of the expected two stacks, try increasing this value.</p><p>The minimum value is 10,000 and the maximum is 30,000,000 (thirty times the default value). Increasing the value by 1 increases Helgrind's memory requirement by very roughly 100 bytes, so the maximum value will easily eat up three extra gigabytes or so of memory.</p></body></html> 10000 30000000 1000000 - + Extra parameters: - extraParameters + kcfg_extraArgs - + true + + + Qt::Horizontal - + true <html><head/><body><p>When enabled (the default), Helgrind performs lock order consistency checking. For some buggy programs, the large number of lock order errors reported can become annoying, particularly if you're only interested in race errors. You may therefore find it helpful to disable lock order checking.</p></body></html> Track lock orders - - true - - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:14pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">By default Helgrind checks all data memory accesses made by your program. This flag enables you to skip checking for accesses to thread stacks (local variables). This can improve performance, but comes at the cost of missing races on stack-allocated data.</p></body></html> Check stack refs - - true - - + <html><head/><body><p>Controls whether all activities during thread creation should be ignored. By default enabled only on Solaris. Solaris provides higher throughput, parallelism and scalability than other operating systems, at the cost of more fine-grained locking activity. This means for example that when a thread is created under glibc, just one big lock is used for all thread setup. Solaris libc uses several fine-grained locks and the creator thread resumes its activities as soon as possible, leaving for example stack and TLS setup sequence to the created thread. This situation confuses Helgrind as it assumes there is some false ordering in place between creator and created thread; and therefore many types of race conditions in the application would not be reported. To prevent such false ordering, this command line option is set to yes by default on Solaris. All activity (loads, stores, client requests) is therefore ignored during:</p><p>* pthread_create() call in the creator thread</p><p>* thread creation phase (stack and TLS setup) in the created thread</p><p>Also new memory allocated during thread creation is untracked, that is race reporting is suppressed there. DRD does the same thing implicitly. This is necessary because Solaris libc caches many objects and reuses them for different threads and that confuses Helgrind.</p></body></html> Ignore thread creation - + true <html><head/><body><p>When enabled (not the default), Helgrind treats freeing of heap memory as if the memory was written immediately before the free. This exposes races where memory is referenced by one thread, and freed by another, but there is no observable synchronization event to ensure that the reference happens before the free.</p><p>This functionality is new in Valgrind 3.7.0, and is regarded as experimental. It is not enabled by default because its interaction with custom memory allocators is not well understood at present. User feedback is welcomed.</p></body></html> Free is write (experimental) Qt::Horizontal - + Show stack frame instruction pointer value Qt::Vertical 20 71 + + + Valgrind::ComboBox + QComboBox +
core/widgets/combobox.h
+
+
- historyLevel - conflictCacheSize - extraParameters - trackLockorders - checkStackRefs - ignoreThreadCreation - freeIsWrite + kcfg_conflictCacheSize + kcfg_extraArgs + kcfg_trackLockorders + kcfg_checkStackRefs + kcfg_ignoreThreadCreation + kcfg_freeIsWrite
diff --git a/tools/helgrind/helgrind_job.cpp b/tools/helgrind/helgrind_job.cpp index 7a56fce..9351c52 100644 --- a/tools/helgrind/helgrind_job.cpp +++ b/tools/helgrind/helgrind_job.cpp @@ -1,34 +1,34 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "helgrind_job.h" #include "debug.h" -#include "helgrind_settings.h" +#include "helgrind_config.h" #include "helgrind_tool.h" namespace Valgrind { HelgrindJob::HelgrindJob(KDevelop::ILaunchConfiguration* launchConfig) - : XmlJob(HelgrindTool::self(), launchConfig, new HelgrindSettings) + : XmlJob(HelgrindTool::self(), launchConfig, new HelgrindConfig) { } } diff --git a/tools/helgrind/helgrind_settings.cpp b/tools/helgrind/helgrind_settings.cpp deleted file mode 100644 index 20e7a85..0000000 --- a/tools/helgrind/helgrind_settings.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "helgrind_settings.h" - -#include "helgrind_tool.h" - -namespace Valgrind -{ - -HelgrindSettings::HelgrindSettings() - : XmlSettings(HelgrindTool::self()->id()) - - , historyLevel( - this, - QStringLiteral("History Level"), - QStringLiteral("history-level"), - QStringLiteral("full")) - - , conflictCacheSize( - this, - QStringLiteral("Conflict Cache Size"), - QStringLiteral("conflict-cache-size"), - 1000000) - - , trackLockorders( - this, - QStringLiteral("Track Lock Orders"), - QStringLiteral("track-lockorders"), - true) - - , checkStackRefs( - this, - QStringLiteral("Check Stack Refs"), - QStringLiteral("check-stack-refs"), - true) - - , ignoreThreadCreation( - this, - QStringLiteral("Ignore Thread Creation"), - QStringLiteral("ignore-thread-creation"), - false) - - , freeIsWrite( - this, - QStringLiteral("Free Is Write"), - QStringLiteral("free-is-write"), - false) -{ -} - -} diff --git a/tools/massif/massif_config.cpp b/tools/massif/massif_config.cpp new file mode 100644 index 0000000..5f3a92d --- /dev/null +++ b/tools/massif/massif_config.cpp @@ -0,0 +1,51 @@ +/* This file is part of KDevelop + Copyright 2017 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "massif_config.h" + +#include "globalsettings.h" +#include "massif_tool.h" + +namespace Valgrind +{ + +MassifConfig::MassifConfig() + : Config(MassifTool::self()->id()) +{ + addCmdItemInt(QStringLiteral("snapshotTreeDepth"), m_snapshotTreeDepth, 30, QStringLiteral("depth")); + addCmdItemInt(QStringLiteral("threshold"), m_threshold, 1, QStringLiteral("threshold")); + addCmdItemInt(QStringLiteral("peakInaccuracy"), m_peakInaccuracy, 1, QStringLiteral("peak-inaccuracy")); + addCmdItemInt(QStringLiteral("maximumSnapshots"), m_maximumSnapshots, 100, QStringLiteral("max-snapshots")); + addCmdItemInt(QStringLiteral("detailedSnapshotsFrequency"), m_detailedSnapshotsFrequency, 10, QStringLiteral("detailed-freq")); + + addCmdItemString(QStringLiteral("timeUnit"), m_timeUnit, QStringLiteral("i"), QStringLiteral("time-unit")); + + addCmdItemBool(QStringLiteral("profileHeap"), m_profileHeap, true, QStringLiteral("heap")); + addCmdItemBool(QStringLiteral("profileStack"), m_profileStack, false, QStringLiteral("stacks")); + addCmdItemBool(QStringLiteral("pagesAsHeap"), m_pagesAsHeap, false, QStringLiteral("pages-as-heap")); + + addItemBool(QStringLiteral("launchVisualizer"), m_launchVisualizer, false); +} + +QString MassifConfig::visualizerExecutablePath() +{ + return KDevelop::Path(GlobalSettings::massifVisualizerExecutablePath()).toLocalFile(); +} + +} diff --git a/tools/massif/massif_settings.h b/tools/massif/massif_config.h similarity index 66% rename from tools/massif/massif_settings.h rename to tools/massif/massif_config.h index bdf95f8..80ebfd8 100644 --- a/tools/massif/massif_settings.h +++ b/tools/massif/massif_config.h @@ -1,49 +1,56 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "settings.h" +#include "config.h" namespace Valgrind { -class MassifSettings : public Settings +class MassifConfig : public Config { public: - MassifSettings(); - ~MassifSettings() override = default; + MassifConfig(); + ~MassifConfig() override = default; - IntValue snapshotTreeDepth; - IntValue threshold; - IntValue peakInaccuracy; - IntValue maximumSnapshots; - IntValue detailedSnapshotsFrequency; - IntValue timeUnit; + static QString visualizerExecutablePath(); - BoolValue profileHeap; - BoolValue profileStack; - BoolValue pagesAsHeap; + bool launchVisualizer() const + { + return m_launchVisualizer; + } - BoolValue launchVisualizer; +private: + int m_snapshotTreeDepth; + int m_threshold; + int m_peakInaccuracy; + int m_maximumSnapshots; + int m_detailedSnapshotsFrequency; - static QString visualizerExecutablePath(); + QString m_timeUnit; + + bool m_profileHeap; + bool m_profileStack; + bool m_pagesAsHeap; + + bool m_launchVisualizer; }; } diff --git a/tools/massif/massif_configpage.cpp b/tools/massif/massif_configpage.cpp index d5ada29..8838fb4 100644 --- a/tools/massif/massif_configpage.cpp +++ b/tools/massif/massif_configpage.cpp @@ -1,132 +1,53 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2011 Lionel Duc * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "massif_configpage.h" #include "ui_massif_configpage.h" -#include "massif_settings.h" +#include "massif_config.h" #include "massif_tool.h" -#include +#include namespace Valgrind { MassifConfigPage::MassifConfigPage(QWidget* parent) - : ConfigPage(parent) + : ConfigPage(MassifTool::self()->name(), parent) , ui(new Ui::MassifConfigPage()) { ui->setupUi(this); - connectToChanged(ui->extraParameters); - connectToChanged(ui->launchMassifVisualizer); - connectToChanged(ui->depth); - connectToChanged(ui->threshold); - connectToChanged(ui->peakInaccuracy); - connectToChanged(ui->maxSnapshots); - connectToChanged(ui->snapshotFreq); - connectToChanged(ui->timeUnit); - connectToChanged(ui->profileHeap); - connectToChanged(ui->profileStack); - connectToChanged(ui->pagesAsHeap); + ui->kcfg_timeUnit->addItem(i18n("CPU instructions"), QStringLiteral("i")); + ui->kcfg_timeUnit->addItem(i18n("Milliseconds"), QStringLiteral("ms")); + ui->kcfg_timeUnit->addItem(i18n("Bytes allocated"), QStringLiteral("B")); - connectToChanged(ui->profileStack); - connectToChanged(ui->pagesAsHeap); - check(); - - ui->timeUnitLabel->setToolTip(ui->timeUnit->toolTip()); - ui->depthLabel->setToolTip(ui->depth->toolTip()); - ui->thresholdLabel->setToolTip(ui->threshold->toolTip()); - ui->peakInaccuracyLabel->setToolTip(ui->peakInaccuracy->toolTip()); - ui->maxSnapshotsLabel->setToolTip(ui->maxSnapshots->toolTip()); - ui->snapshotFreqLabel->setToolTip(ui->snapshotFreq->toolTip()); + init(new MassifConfig); } MassifConfigPage::~MassifConfigPage() = default; -QString MassifConfigPage::title() const -{ - return MassifTool::self()->name(); -} - -QIcon MassifConfigPage::icon() const -{ - return QIcon(); -} - -void MassifConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) -{ - QSignalBlocker blocker(this); - MassifSettings settings; - settings.load(cfg); - - ui->extraParameters->setText(settings.extraParameters); - ui->depth->setValue(settings.snapshotTreeDepth); - ui->threshold->setValue(settings.threshold); - ui->peakInaccuracy->setValue(settings.peakInaccuracy); - ui->maxSnapshots->setValue(settings.maximumSnapshots); - ui->snapshotFreq->setValue(settings.detailedSnapshotsFrequency); - ui->timeUnit->setCurrentIndex(settings.timeUnit); - ui->profileHeap->setChecked(settings.profileHeap); - ui->profileStack->setChecked(settings.profileStack); - ui->pagesAsHeap->setChecked(settings.pagesAsHeap); - ui->launchMassifVisualizer->setChecked(settings.launchVisualizer); -} - -void MassifConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - MassifSettings settings; - - settings.extraParameters = ui->extraParameters->text(); - settings.snapshotTreeDepth = ui->depth->value(); - settings.threshold = ui->threshold->value(); - settings.peakInaccuracy = ui->peakInaccuracy->value(); - settings.maximumSnapshots = ui->maxSnapshots->value(); - settings.detailedSnapshotsFrequency = ui->snapshotFreq->value(); - settings.timeUnit = ui->timeUnit->currentIndex(); - settings.profileHeap = ui->profileHeap->isChecked(); - settings.profileStack = ui->profileStack->isChecked(); - settings.pagesAsHeap = ui->pagesAsHeap->isChecked(); - settings.launchVisualizer = ui->launchMassifVisualizer->isChecked(); - - settings.save(cfg); -} - void MassifConfigPage::check() { - if (ui->profileStack->isChecked() && ui->pagesAsHeap->isChecked()) { - ui->messageWidget->setVisible(true); - return; - } - - ui->messageWidget->setVisible(false); -} - -MassifConfigPageFactory::MassifConfigPageFactory() -{ -} - -KDevelop::LaunchConfigurationPage* MassifConfigPageFactory::createWidget(QWidget* parent) -{ - return new MassifConfigPage(parent); + ui->messageWidget->setVisible(ui->kcfg_profileStack->isChecked() && ui->kcfg_pagesAsHeap->isChecked()); } } diff --git a/tools/massif/massif_configpage.h b/tools/massif/massif_configpage.h index 462a65e..47acc97 100644 --- a/tools/massif/massif_configpage.h +++ b/tools/massif/massif_configpage.h @@ -1,59 +1,60 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" namespace Valgrind { namespace Ui { class MassifConfigPage; } class MassifConfigPage : public ConfigPage { Q_OBJECT public: explicit MassifConfigPage(QWidget* parent = nullptr); ~MassifConfigPage() override; - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; +protected: + void check() override; private: - void check(); - QScopedPointer ui; }; class MassifConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: - MassifConfigPageFactory(); + MassifConfigPageFactory() + { + } + ~MassifConfigPageFactory() override = default; - KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override + { + return new MassifConfigPage(parent); + } }; } diff --git a/tools/massif/massif_configpage.ui b/tools/massif/massif_configpage.ui index cdde443..2dd814f 100644 --- a/tools/massif/massif_configpage.ui +++ b/tools/massif/massif_configpage.ui @@ -1,301 +1,283 @@ Valgrind::MassifConfigPage 0 0 465 582 Time unit: - - timeUnit - - - - - - - <html><head/><body><p>The time unit used for the profiling. There are three possibilities: </p><p><span style=" font-weight:600;">instructions</span> executed (i), which is good for most cases; </p><p>real (wallclock) time (ms, i.e. <span style=" font-weight:600;">milliseconds</span>), which is sometimes useful; </p><p>and <span style=" font-weight:600;">bytes</span> allocated/deallocated on the heap and/or stack (B), which is useful for very short-run programs, and for testing purposes, because it is the most reproducible across different machines.</p></body></html> - - - - CPU instructions - - - - - Milliseconds - - - - - Bytes allocated - - - + Snapshot tree depth: - depth + kcfg_snapshotTreeDepth - + <html><head/><body><p>Maximum depth of the allocation trees recorded for detailed snapshots. Increasing it will make Massif run somewhat more slowly, use more memory, and produce bigger output files.</p></body></html> 2000000000 30 Threshold: - threshold + kcfg_threshold - + <html><head/><body><p>The significance threshold for heap allocations, as a percentage of total memory size. Allocation tree entries that account for less than this will be aggregated. Note that this should be specified in tandem with ms_print's option of the same name.</p></body></html> % 1 Peak inaccuracy: - peakInaccuracy + kcfg_peakInaccuracy - + <html><head/><body><p>Massif does not necessarily record the actual global memory allocation peak; by default it records a peak only when the global memory allocation size exceeds the previous peak by at least 1.0%. This is because there can be many local allocation peaks along the way, and doing a detailed snapshot for every one would be expensive and wasteful, as all but one of them will be later discarded. This inaccuracy can be changed (even to 0.0%) via this option, but Massif will run drastically slower as the number approaches zero.</p></body></html> % 100 1 - + Maximum snapshots: - maxSnapshots + kcfg_maximumSnapshots - + <html><head/><body><p>The maximum number of snapshots recorded. If set to N, for all programs except very short-running ones, the final number of snapshots will be between N/2 and N.</p></body></html> 2000000000 100 - + Detailed snapshot frequency: - snapshotFreq + kcfg_detailedSnapshotsFrequency - + <html><head/><body><p>Frequency of detailed snapshots. With <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--detailed-freq=1</span>, every snapshot is detailed.</p></body></html> 2000000000 10 - + E&xtra parameters: - extraParameters + kcfg_extraArgs - + true + + + Qt::Horizontal - + <html><head/><body><p>Specifies whether heap profiling should be done.</p></body></html> Profile heap true - + <html><head/><body><p>Specifies whether stack profiling should be done. This option slows Massif down greatly, and so is off by default. Note that Massif assumes that the main stack has size zero at start-up. This is not true, but doing otherwise accurately is difficult. Furthermore, starting at zero better indicates the size of the part of the main stack that a user program actually has control over.</p></body></html> Profile stack (slows profiling down greatly) - + <html><head/><body><p>Tells Massif to profile memory at the page level rather than at the malloc'd block level.</p></body></html> Pages as heap <html><head/><body><p>&quot;Pages as heap&quot; cannot be used together with &quot;Profile stack&quot;.</p></body></html> true false KMessageWidget::Error Qt::Horizontal - + Launch Massif Visualizer after analysis finish Qt::Vertical 20 40 KMessageWidget QFrame
kmessagewidget.h
+ + Valgrind::ComboBox + QComboBox +
core/widgets/combobox.h
+
- timeUnit - depth - threshold - peakInaccuracy - maxSnapshots - snapshotFreq - extraParameters - profileHeap - profileStack - pagesAsHeap - launchMassifVisualizer + kcfg_snapshotTreeDepth + kcfg_threshold + kcfg_peakInaccuracy + kcfg_maximumSnapshots + kcfg_detailedSnapshotsFrequency + kcfg_extraArgs + kcfg_profileHeap + kcfg_profileStack + kcfg_pagesAsHeap + kcfg_launchVisualizer
diff --git a/tools/massif/massif_job.cpp b/tools/massif/massif_job.cpp index d661b4c..9098123 100644 --- a/tools/massif/massif_job.cpp +++ b/tools/massif/massif_job.cpp @@ -1,89 +1,78 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "massif_job.h" #include "debug.h" +#include "massif_config.h" #include "massif_model.h" #include "massif_parser.h" -#include "massif_settings.h" #include "massif_tool.h" #include "massif_view.h" #include "plugin.h" #include #include #include #include namespace Valgrind { MassifJob::MassifJob(KDevelop::ILaunchConfiguration* launchConfig) : Job(MassifTool::self(), launchConfig) , m_model(new MassifSnapshotsModel) , m_outputFile(new QTemporaryFile(this)) { m_outputFile->open(); } bool MassifJob::processEnded() { - MassifSettings settings; - settings.load(m_config); + MassifConfig config; + config.setConfigGroup(m_configGroup); + config.load(); massifParse(m_outputFile->fileName(), m_model); return true; } void MassifJob::addToolArgs(QStringList& args) const { - MassifSettings settings; - settings.load(m_config); + MassifConfig config; + config.setConfigGroup(m_configGroup); + config.load(); - int tu = settings.timeUnit; - if (tu == 0) { - args += QStringLiteral("--time-unit=i"); - } - - else if (tu == 1) { - args += QStringLiteral("--time-unit=ms"); - } - - else if (tu == 2) { - args += QStringLiteral("--time-unit=B"); - } - - args += settings.cmdArgs(); + args += config.cmdArgs(); args += QStringLiteral("--massif-out-file=%1").arg(m_outputFile->fileName()); } QWidget* MassifJob::createView() { - return new MassifView(m_config, m_outputFile, m_model); + return new MassifView(m_configGroup, m_outputFile, m_model); } } diff --git a/tools/massif/massif_settings.cpp b/tools/massif/massif_settings.cpp deleted file mode 100644 index 8a61cf6..0000000 --- a/tools/massif/massif_settings.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "massif_settings.h" - -#include "globalsettings.h" -#include "massif_tool.h" - -namespace Valgrind -{ - -MassifSettings::MassifSettings() - : Settings(MassifTool::self()->id()) - - , snapshotTreeDepth( - this, - QStringLiteral("Snapshot Tree Depth"), - QStringLiteral("depth"), - 30) - - , threshold( - this, - QStringLiteral("Threshold"), - QStringLiteral("threshold"), - 1) - - , peakInaccuracy( - this, - QStringLiteral("Peak Inaccuracy"), - QStringLiteral("peak-inaccuracy"), - 1) - - , maximumSnapshots( - this, - QStringLiteral("Maximum Snapshots"), - QStringLiteral("max-snapshots"), - 100) - - , detailedSnapshotsFrequency( - this, - QStringLiteral("Detailed Snapshots Frequency"), - QStringLiteral("detailed-freq"), - 10) - - , timeUnit( - this, - QStringLiteral("Time Unit"), - QStringLiteral(""), - 0) - - , profileHeap( - this, - QStringLiteral("Profile Heap"), - QStringLiteral("heap"), - true) - - , profileStack( - this, - QStringLiteral("Profile Stack"), - QStringLiteral("stacks"), - false) - - , pagesAsHeap( - this, - QStringLiteral("Pages As Heap"), - QStringLiteral("pages-as-heap"), - false) - - , launchVisualizer( - this, - QStringLiteral("Launch Visualizer"), - QStringLiteral(""), - false) -{ -} - -QString MassifSettings::visualizerExecutablePath() -{ - return KDevelop::Path(GlobalSettings::massifVisualizerExecutablePath()).toLocalFile(); -} - -} diff --git a/tools/massif/massif_view.cpp b/tools/massif/massif_view.cpp index c61196f..cb61cbd 100644 --- a/tools/massif/massif_view.cpp +++ b/tools/massif/massif_view.cpp @@ -1,81 +1,82 @@ /* This file is part of KDevelop * Copyright 2011 Sebastien Rannou * Copyright 2008 Hamish Rodda * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "massif_view.h" #include "ui_massif_view.h" #include "debug.h" +#include "massif_config.h" #include "massif_model.h" -#include "massif_settings.h" #include "massif_snapshot.h" #include "utils.h" #include #include #include namespace Valgrind { -MassifView::MassifView(KConfigGroup config, QTemporaryFile* outputFile, MassifSnapshotsModel* model, QWidget* parent) +MassifView::MassifView(KConfigGroup configGroup, QTemporaryFile* outputFile, MassifSnapshotsModel* model, QWidget* parent) : QWidget(parent) , ui(new Ui::MassifView) , m_visualizerProcess(new QProcess) { Q_ASSERT(model); model->setParent(this); Q_ASSERT(outputFile); outputFile->setParent(this); ui->setupUi(this); auto treesModel = new QStringListModel(this); ui->treesView->setModel(treesModel); ui->snapshotsView->setModel(model); ui->snapshotsView->header()->resizeSections(QHeaderView::ResizeToContents); connect(ui->snapshotsView->selectionModel(), &QItemSelectionModel::currentChanged, this, [treesModel](const QModelIndex& current, const QModelIndex&) { auto snapshot = static_cast(current.internalPointer()); treesModel->setStringList(snapshot->heapTree); }); auto startVisualizer = [this, outputFile]() { - m_visualizerProcess->start(MassifSettings::visualizerExecutablePath(), + m_visualizerProcess->start(MassifConfig::visualizerExecutablePath(), { outputFile->fileName() }); }; - MassifSettings settings; - settings.load(config); + MassifConfig config; + config.setConfigGroup(configGroup); + config.load(); setupVisualizerProcess(m_visualizerProcess.data(), ui->launchVisualizerButton, - startVisualizer, settings.launchVisualizer); + startVisualizer, config.launchVisualizer()); } MassifView::~MassifView() { m_visualizerProcess->disconnect(); // FIXME is this really needed ? } } diff --git a/tools/massif/massif_view.h b/tools/massif/massif_view.h index 334d3c1..5145751 100644 --- a/tools/massif/massif_view.h +++ b/tools/massif/massif_view.h @@ -1,51 +1,51 @@ /* This file is part of KDevelop * Copyright 2008 Hamish Rodda * Copyright 2011 Sebastien Rannou * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include #include class QProcess; class QTemporaryFile; namespace Valgrind { namespace Ui { class MassifView; } class MassifSnapshotsModel; class MassifView : public QWidget { Q_OBJECT public: - MassifView(KConfigGroup config, QTemporaryFile* outputFile, MassifSnapshotsModel* model, QWidget* parent = nullptr); + MassifView(KConfigGroup configGroup, QTemporaryFile* outputFile, MassifSnapshotsModel* model, QWidget* parent = nullptr); ~MassifView() override; private: QScopedPointer ui; QScopedPointer m_visualizerProcess; }; } diff --git a/tools/memcheck/memcheck_config.cpp b/tools/memcheck/memcheck_config.cpp new file mode 100644 index 0000000..0d4f98d --- /dev/null +++ b/tools/memcheck/memcheck_config.cpp @@ -0,0 +1,50 @@ +/* This file is part of KDevelop + Copyright 2017 Anton Anikin + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "memcheck_config.h" + +#include "memcheck_tool.h" + +namespace Valgrind +{ + +MemcheckConfig::MemcheckConfig() + : XmlConfig(MemcheckTool::self()->id()) +{ + addCmdItemString(QStringLiteral("leakResolution"), m_leakResolution, QStringLiteral("high"), QStringLiteral("leak-resolution")); + addCmdItemString(QStringLiteral("showLeakKinds"), m_showLeakKinds, QStringLiteral("definite,possible"), QStringLiteral("show-leak-kinds")); + addCmdItemString(QStringLiteral("leakCheckHeuristics"), m_leakCheckHeuristics, QStringLiteral("all"), QStringLiteral("leak-check-heuristics")); + addCmdItemString(QStringLiteral("keepStacktraces"), m_keepStacktraces, QStringLiteral("alloc-and-free"), QStringLiteral("keep-stacktraces")); + + auto itemInt = addCmdItemInt(QStringLiteral("freelistVol"), m_freelistVol, 20000000, QStringLiteral("freelist-vol")); + itemInt->setMinValue(1); + itemInt->setMaxValue(200000000); + + itemInt = addCmdItemInt(QStringLiteral("freelistBigBlocks"), m_freelistBigBlocks, 1000000, QStringLiteral("freelist-big-blocks")); + itemInt->setMinValue(1); + itemInt->setMaxValue(10000000); + + addCmdItemBool(QStringLiteral("undefValueErrors"), m_undefValueErrors, true, QStringLiteral("undef-value-errors")); + addCmdItemBool(QStringLiteral("showMismatchedFrees"), m_showMismatchedFrees, true, QStringLiteral("show-mismatched-frees")); + addCmdItemBool(QStringLiteral("partialLoadsOk"), m_partialLoadsOk, true, QStringLiteral("partial-loads-ok")); + addCmdItemBool(QStringLiteral("trackOrigins"), m_trackOrigins, false, QStringLiteral("track-origins")); + addCmdItemBool(QStringLiteral("expensiveDefinednessChecks"), m_expensiveDefinednessChecks, false, QStringLiteral("expensive-definedness-checks")); +} + +} diff --git a/tools/helgrind/helgrind_settings.h b/tools/memcheck/memcheck_config.h similarity index 65% rename from tools/helgrind/helgrind_settings.h rename to tools/memcheck/memcheck_config.h index b1025d6..fd58709 100644 --- a/tools/helgrind/helgrind_settings.h +++ b/tools/memcheck/memcheck_config.h @@ -1,43 +1,49 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once -#include "xmlsettings.h" +#include "xmlconfig.h" namespace Valgrind { -class HelgrindSettings : public XmlSettings +class MemcheckConfig : public XmlConfig { public: - HelgrindSettings(); - ~HelgrindSettings() override = default; - - StringValue historyLevel; - - IntValue conflictCacheSize; - - BoolValue trackLockorders; - BoolValue checkStackRefs; - BoolValue ignoreThreadCreation; - BoolValue freeIsWrite; + MemcheckConfig(); + ~MemcheckConfig() override = default; + +private: + QString m_leakResolution; + QString m_showLeakKinds; + QString m_leakCheckHeuristics; + QString m_keepStacktraces; + + int m_freelistVol; + int m_freelistBigBlocks; + + bool m_undefValueErrors; + bool m_showMismatchedFrees; + bool m_partialLoadsOk; + bool m_trackOrigins; + bool m_expensiveDefinednessChecks; }; } diff --git a/tools/memcheck/memcheck_configpage.cpp b/tools/memcheck/memcheck_configpage.cpp index d85b0da..409b085 100644 --- a/tools/memcheck/memcheck_configpage.cpp +++ b/tools/memcheck/memcheck_configpage.cpp @@ -1,211 +1,69 @@ /* This file is part of KDevelop * Copyright 2011 Mathieu Lornac * Copyright 2011 Damien Coppel * Copyright 2011 Lionel Duc * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "memcheck_configpage.h" #include "ui_memcheck_configpage.h" #include "debug.h" -#include "memcheck_settings.h" +#include "memcheck_config.h" #include "memcheck_tool.h" #include +#include + namespace Valgrind { MemcheckConfigPage::MemcheckConfigPage(QWidget* parent) - : ConfigPage(parent) - , ui(new Ui::MemcheckConfigPage()) -{ - ui->setupUi(this); - - connectToChanged(ui->leakResolution); - connectToChanged(ui->keepStacktraces); - connectToChanged(ui->freelistVol); - connectToChanged(ui->freelistBigBlocks); - connectToChanged(ui->extraParameters); - - connectToChanged(ui->undefValueErrors); - connectToChanged(ui->showMismatchedFrees); - connectToChanged(ui->partialLoadsOk); - connectToChanged(ui->trackOrigins); - connectToChanged(ui->expensiveDefinednessChecks); - - connectToChanged(ui->showInstructionPointer); - - static const QStringList leakKinds = { - QStringLiteral("definite"), - QStringLiteral("possible"), - QStringLiteral("indirect"), - QStringLiteral("reachable") - }; - setupMenuButton(ui->showLeakKinds, leakKinds); - - static const QStringList heuristics = { - QStringLiteral("stdstring"), - QStringLiteral("length64"), - QStringLiteral("newarray"), - QStringLiteral("multipleinheritance") - }; - setupMenuButton(ui->leakCheckHeuristics, heuristics); - - ui->leakResolutionLabel->setToolTip(ui->leakResolution->toolTip()); - ui->showLeakKindsLabel->setToolTip(ui->showLeakKinds->toolTip()); - ui->leakCheckHeuristicsLabel->setToolTip(ui->leakCheckHeuristics->toolTip()); - ui->keepStacktracesLabel->setToolTip(ui->keepStacktraces->toolTip()); - ui->freelistVolLabel->setToolTip(ui->freelistVol->toolTip()); - ui->freelistBigBlocksLabel->setToolTip(ui->freelistBigBlocks->toolTip()); -} - -MemcheckConfigPage::~MemcheckConfigPage() = default; - -QString MemcheckConfigPage::title() const -{ - return MemcheckTool::self()->name(); -} - -QIcon MemcheckConfigPage::icon() const -{ - return QIcon(); -} - -void MemcheckConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject*) -{ - QSignalBlocker blocker(this); - MemcheckSettings settings; - settings.load(cfg); - - ui->leakResolution->setCurrentText(settings.leakResolution); - updateMenuButton(ui->showLeakKinds, settings.showLeakKinds); - updateMenuButton(ui->leakCheckHeuristics, settings.leakCheckHeuristics); - ui->keepStacktraces->setCurrentText(settings.keepStacktraces); - ui->freelistVol->setValue(settings.freelistVol); - ui->freelistBigBlocks->setValue(settings.freelistBigBlocks); - ui->extraParameters->setText(settings.extraParameters); - - ui->undefValueErrors->setChecked(settings.undefValueErrors); - ui->showMismatchedFrees->setChecked(settings.showMismatchedFrees); - ui->partialLoadsOk->setChecked(settings.partialLoadsOk); - ui->trackOrigins->setChecked(settings.trackOrigins); - ui->expensiveDefinednessChecks->setChecked(settings.expensiveDefinednessChecks); - - ui->showInstructionPointer->setChecked(settings.showInstructionPointer); -} - -void MemcheckConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject*) const -{ - MemcheckSettings settings; - - settings.leakResolution = ui->leakResolution->currentText(); - settings.showLeakKinds = ui->showLeakKinds->text().trimmed().remove(QChar(' ')); - settings.leakCheckHeuristics = ui->leakCheckHeuristics->text().trimmed().remove(QChar(' ')); - settings.keepStacktraces = ui->keepStacktraces->currentText(); - settings.freelistVol = ui->freelistVol->value(); - settings.freelistBigBlocks = ui->freelistBigBlocks->value(); - settings.extraParameters = ui->extraParameters->text(); - - settings.undefValueErrors = ui->undefValueErrors->isChecked(); - settings.showMismatchedFrees = ui->showMismatchedFrees->isChecked(); - settings.partialLoadsOk = ui->partialLoadsOk->isChecked(); - settings.trackOrigins = ui->trackOrigins->isChecked(); - settings.expensiveDefinednessChecks = ui->expensiveDefinednessChecks->isChecked(); - - settings.showInstructionPointer = ui->showInstructionPointer->isChecked(); - - settings.save(cfg); -} - -QString selectedItemsText(QMenu* menu) -{ - Q_ASSERT(menu); - - QStringList selected; - const auto actions = menu->actions(); - for (auto action : actions) { - if (action->isChecked()) { - selected += action->text(); - } - } - - if (selected.isEmpty()) { - return QStringLiteral("none"); - } - - if (selected.size() == actions.size()) { - return QStringLiteral("all"); - } - - - return selected.join(QStringLiteral(", ")); -} - -void MemcheckConfigPage::setupMenuButton(QPushButton* button, const QStringList& items) -{ - Q_ASSERT(button); - - auto menu = new QMenu(button); - button->setMenu(menu); - button->setStyleSheet(QStringLiteral("Text-align:left")); - - auto slot = [button, menu]() { - button->setText(QChar(' ') + selectedItemsText(menu)); - }; - - for (const QString& text : items) { - auto action = new QAction(text, menu); - action->setCheckable(true); - action->setChecked(false); - - connect(action, &QAction::toggled, this, slot); - connect(action, &QAction::toggled, this, &MemcheckConfigPage::changed); - menu->addAction(action); - } - slot(); -} - -void MemcheckConfigPage::updateMenuButton(QPushButton* button, const QString& text) -{ - Q_ASSERT(button); - - auto enabled = text.split(QChar(',')); - const auto actions = button->menu()->actions(); - for (auto action : actions) { - if (text == QStringLiteral("all")) { - action->setChecked(true); - } else if (text == QStringLiteral("none")) { - action->setChecked(false); - } else { - action->setChecked(enabled.contains(action->text())); - } - } -} - -MemcheckConfigPageFactory::MemcheckConfigPageFactory() -{ -} - -KDevelop::LaunchConfigurationPage* MemcheckConfigPageFactory::createWidget(QWidget* parent) + : ConfigPage(MemcheckTool::self()->name(), parent) { - return new MemcheckConfigPage(parent); + Ui::MemcheckConfigPage ui; + ui.setupUi(this); + + ui.kcfg_showLeakKinds->addAction(i18n("definite"), QStringLiteral("definite")); + ui.kcfg_showLeakKinds->addAction(i18n("possible"), QStringLiteral("possible")); + ui.kcfg_showLeakKinds->addAction(i18n("indirect"), QStringLiteral("indirect")); + ui.kcfg_showLeakKinds->addAction(i18n("reachable"), QStringLiteral("reachable")); + connect(ui.kcfg_showLeakKinds, &MenuButton::valueChanged, this, &MemcheckConfigPage::changed); + + // FIXME fix i18n text ? + ui.kcfg_leakCheckHeuristics->addAction(i18n("stdstring"), QStringLiteral("stdstring")); + ui.kcfg_leakCheckHeuristics->addAction(i18n("length64"), QStringLiteral("length64")); + ui.kcfg_leakCheckHeuristics->addAction(i18n("newarray"), QStringLiteral("newarray")); + ui.kcfg_leakCheckHeuristics->addAction(i18n("multipleinheritance"), QStringLiteral("multipleinheritance")); + connect(ui.kcfg_leakCheckHeuristics, &MenuButton::valueChanged, this, &MemcheckConfigPage::changed); + + ui.kcfg_leakResolution->addItem(i18n("high"), QStringLiteral("high")); + ui.kcfg_leakResolution->addItem(i18n("medium"), QStringLiteral("med")); + ui.kcfg_leakResolution->addItem(i18n("low"), QStringLiteral("low")); + + ui.kcfg_keepStacktraces->addItem(i18n("alloc"), QStringLiteral("alloc")); + ui.kcfg_keepStacktraces->addItem(i18n("free"), QStringLiteral("free")); + ui.kcfg_keepStacktraces->addItem(i18n("alloc-and-free"), QStringLiteral("alloc-and-free")); + ui.kcfg_keepStacktraces->addItem(i18n("alloc-then-free"), QStringLiteral("alloc-then-free")); + ui.kcfg_keepStacktraces->addItem(i18n("none"), QStringLiteral("none")); + + init(new MemcheckConfig); } } diff --git a/tools/memcheck/memcheck_configpage.h b/tools/memcheck/memcheck_configpage.h index 271c50e..231031a 100644 --- a/tools/memcheck/memcheck_configpage.h +++ b/tools/memcheck/memcheck_configpage.h @@ -1,64 +1,56 @@ /* This file is part of KDevelop * Copyright 2011 Mathieu Lornac * Copyright 2011 Damien Coppel * Copyright 2011 Lionel Duc * Copyright 2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "configpage.h" class QPushButton; namespace Valgrind { -namespace Ui { class MemcheckConfigPage; } - class MemcheckConfigPage : public ConfigPage { Q_OBJECT public: explicit MemcheckConfigPage(QWidget* parent = nullptr); - ~MemcheckConfigPage() override; - - QString title() const override; - QIcon icon() const override; - - void loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project = nullptr) override; - void saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project = nullptr) const override; - -private: - void setupMenuButton(QPushButton* button, const QStringList& items); - void updateMenuButton(QPushButton* button, const QString& text); - - QScopedPointer ui; + ~MemcheckConfigPage() override = default; }; class MemcheckConfigPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: - MemcheckConfigPageFactory(); + MemcheckConfigPageFactory() + { + } + ~MemcheckConfigPageFactory() override = default; - KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override + { + return new MemcheckConfigPage(parent); + } }; } diff --git a/tools/memcheck/memcheck_configpage.ui b/tools/memcheck/memcheck_configpage.ui index 6bb9d91..58ccd34 100644 --- a/tools/memcheck/memcheck_configpage.ui +++ b/tools/memcheck/memcheck_configpage.ui @@ -1,304 +1,261 @@ Valgrind::MemcheckConfigPage 0 0 794 732 Leak resolution: - + <html><head/><body><p>When doing leak checking, determines how willing Memcheck is to consider different backtraces to be the same for the purposes of merging multiple leaks into a single leak report. When set to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">low</span>, only the first two entries need match. When <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">med</span>, four entries have to match. When <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">high</span>, all entries need to match.</p><p>For hardcore leak debugging, you probably want to use <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--leak-resolution=high</span> together with <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--num-callers=40</span> or some such large number.</p><p>Note that the <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--leak-resolution</span> setting does not affect Memcheck's ability to find leaks. It only changes how the results are presented.</p></body></html> - - - high - - - - - med - - - - - low - - Show leak kinds: - + Specifies the leak kinds to show. false Used heuristics: - + <html><head/><body><p>Specifies the set of leak check heuristics to be used during leak searches. The heuristics control which interior pointers to a block cause it to be considered as reachable.</p></body></html> Stacktraces keeping: - + <html><head/><body><p>Controls which stack trace(s) to keep for malloc'd and/or free'd blocks. </p><p>With <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">alloc-then-free</span>, a stack trace is recorded at allocation time, and is associated with the block. When the block is freed, a second stack trace is recorded, and this replaces the allocation stack trace. As a result, any &quot;use after free&quot; errors relating to this block can only show a stack trace for where the block was freed. </p><p>With <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">alloc-and-free</span>, both allocation and the deallocation stack traces for the block are stored. Hence a &quot;use after free&quot; error will show both, which may make the error easier to diagnose. Compared to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">alloc-then-free</span>, this setting slightly increases Valgrind's memory use as the block contains two references instead of one. </p><p>With <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">alloc</span>, only the allocation stack trace is recorded (and reported). With <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">free</span>, only the deallocation stack trace is recorded (and reported). These values somewhat decrease Valgrind's memory and cpu usage. They can be useful depending on the error types you are searching for and the level of detail you need to analyze them. For example, if you are only interested in memory leak errors, it is sufficient to record the allocation stack traces. </p><p>With <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">none</span>, no stack traces are recorded for malloc and free operations. If your program allocates a lot of blocks and/or allocates/frees from many different stack traces, this can significantly decrease cpu and/or memory required. Of course, few details will be reported for errors related to heap blocks. </p><p>Note that once a stack trace is recorded, Valgrind keeps the stack trace in memory even if it is not referenced by any block. Some programs (for example, recursive algorithms) can generate a huge number of stack traces. If Valgrind uses too much memory in such circumstances, you can reduce the memory required with the options <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--keep-stacktraces</span> and/or by using a smaller value for the option <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--num-callers</span>. </p></body></html> - - - alloc - - - - - free - - - - - alloc-and-free - - - - - alloc-then-free - - - - - none - - Freelist maximum size: - freelistVol + kcfg_freelistVol - + <html><head/><body><p>When the client program releases memory using <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">free</span> (in <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">C</span>) or <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete</span> (<span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">C++</span>), that memory is not immediately made available for re-allocation. Instead, it is marked inaccessible and placed in a queue of freed blocks. The purpose is to defer as long as possible the point at which freed-up memory comes back into circulation. This increases the chance that Memcheck will be able to detect invalid accesses to blocks for some significant period of time after they have been freed.</p><p>This option specifies the maximum total size, in bytes, of the blocks in the queue. The default value is twenty million bytes. Increasing this increases the total amount of memory used by Memcheck but may detect invalid uses of freed blocks which would otherwise go undetected.</p></body></html> - - 2000000000 - - - 20000000 - Freelist big-blocks: - + <html><head/><body><p>When making blocks from the queue of freed blocks available for re-allocation, Memcheck will in priority re-circulate the blocks with a size greater or equal to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--freelist-big-blocks</span>. This ensures that freeing big blocks (in particular freeing blocks bigger than <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--freelist-vol</span>) does not immediately lead to a re-circulation of all (or a lot of) the small blocks in the free list. In other words, this option increases the likelihood to discover dangling pointers for the &quot;small&quot; blocks, even when big blocks are freed.</p><p>Setting a value of 0 means that all the blocks are re-circulated in a FIFO order.</p></body></html> - - 0 - - - 100000000 - - - 1000000 - - + E&xtra parameters: - extraParameters + kcfg_extraArgs - + true Qt::Horizontal - + true <html><head/><body><p>Controls whether Memcheck reports uses of undefined value errors. Set this to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">no</span> if you don't want to see undefined value errors. It also has the side effect of speeding up Memcheck somewhat.</p></body></html> Show undefined values usage false - + <html><head/><body><p>When enabled, Memcheck checks that heap blocks are deallocated using a function that matches the allocating function. That is, it expects <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">free</span> to be used to deallocate blocks allocated by <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">malloc</span>, <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete</span> for blocks allocated by <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">new</span>, and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete[]</span> for blocks allocated by <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">new[]</span>. If a mismatch is detected, an error is reported. This is in general important because in some environments, freeing with a non-matching function can cause crashes.</p><p>There is however a scenario where such mismatches cannot be avoided. That is when the user provides implementations of <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">new</span>/<span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">new[]</span> that call <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">malloc</span> and of <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete</span>/<span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete[]</span> that call <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">free</span>, and these functions are asymmetrically inlined. For example, imagine that <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete[]</span> is inlined but <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">new[]</span> is not. The result is that Memcheck &quot;sees&quot; all <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">delete[]</span> calls as direct calls to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">free</span>, even when the program source contains no mismatched calls.</p><p>This causes a lot of confusing and irrelevant error reports. <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--show-mismatched-frees=no</span> disables these checks. It is not generally advisable to disable them, though, because you may miss real errors as a result.</p></body></html> Show mismatched frees - + <html><head/><body><p>Controls how Memcheck handles 32-, 64-, 128- and 256-bit naturally aligned loads from addresses for which some bytes are addressable and others are not. When <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">yes</span>, such loads do not produce an address error. Instead, loaded bytes originating from illegal addresses are marked as uninitialised, and those corresponding to legal addresses are handled in the normal way.</p><p>When <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">no</span>, loads from partially invalid addresses are treated the same as loads from completely invalid addresses: an illegal-address error is issued, and the resulting bytes are marked as initialised.</p><p>Note that code that behaves in this way is in violation of the ISO C/C++ standards, and should be considered broken. If at all possible, such code should be fixed.</p></body></html> Allow partial loads - + <html><head/><body><p>Controls whether Memcheck tracks the origin of uninitialised values. By default, it does not, which means that although it can tell you that an uninitialised value is being used in a dangerous way, it cannot tell you where the uninitialised value came from. This often makes it difficult to track down the root problem.</p><p>When set to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">yes</span>, Memcheck keeps track of the origins of all uninitialised values. Then, when an uninitialised value error is reported, Memcheck will try to show the origin of the value. An origin can be one of the following four places: a heap block, a stack allocation, a client request, or miscellaneous other sources (eg, a call to <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">brk</span>).</p><p>For uninitialised values originating from a heap block, Memcheck shows where the block was allocated. For uninitialised values originating from a stack allocation, Memcheck can tell you which function allocated the value, but no more than that -- typically it shows you the source location of the opening brace of the function. So you should carefully check that all of the function's local variables are initialised properly. </p><p>Performance overhead: origin tracking is expensive. It halves Memcheck's speed and increases memory use by a minimum of 100MB, and possibly more. Nevertheless it can drastically reduce the effort required to identify the root cause of uninitialised value errors, and so is often a programmer productivity win, despite running more slowly. </p><p>Accuracy: Memcheck tracks origins quite accurately. To avoid very large space and time overheads, some approximations are made. It is possible, although unlikely, that Memcheck will report an incorrect origin, or not be able to identify any origin. </p><p>Note that the combination <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--track-origins=yes</span> and <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--undef-value-errors=no</span> is nonsensical. Memcheck checks for and rejects this combination at startup.</p></body></html> Track origins of all uninitialised values - + <html><head/><body><p>Controls whether Memcheck should employ more precise but also more expensive (time consuming) algorithms when checking the definedness of a value. The default setting is not to do that and it is usually sufficient. However, for highly optimised code valgrind may sometimes incorrectly complain. Invoking valgrind with <span style=" font-family:'Monospace'; font-weight:600; font-style:italic;">--expensive-definedness-checks=yes</span> helps but comes at a performance cost. Runtime degradation of 25% have been observed but the extra cost depends a lot on the application at hand.</p></body></html> Expensive definedness checks Qt::Horizontal - + Show stack frame instruction pointer value Qt::Vertical 20 71 + + + MenuButton + QPushButton +
core/widgets/menubutton.h
+
+ + Valgrind::ComboBox + QComboBox +
core/widgets/combobox.h
+
+
- leakResolution - showLeakKinds - leakCheckHeuristics - keepStacktraces - freelistVol - freelistBigBlocks - extraParameters - undefValueErrors - showMismatchedFrees - partialLoadsOk - trackOrigins - expensiveDefinednessChecks - showInstructionPointer + kcfg_leakResolution + kcfg_showLeakKinds + kcfg_leakCheckHeuristics + kcfg_keepStacktraces + kcfg_freelistVol + kcfg_freelistBigBlocks + kcfg_extraArgs + kcfg_undefValueErrors + kcfg_showMismatchedFrees + kcfg_partialLoadsOk + kcfg_trackOrigins + kcfg_expensiveDefinednessChecks + kcfg_showInstructionPointer
diff --git a/tools/memcheck/memcheck_job.cpp b/tools/memcheck/memcheck_job.cpp index b7a44d7..bcdb00a 100644 --- a/tools/memcheck/memcheck_job.cpp +++ b/tools/memcheck/memcheck_job.cpp @@ -1,38 +1,38 @@ /* This file is part of KDevelop Copyright 2011 Mathieu Lornac Copyright 2011 Damien Coppel Copyright 2011 Lionel Duc Copyright 2011 Sebastien Rannou Copyright 2016-2017 Anton Anikin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "memcheck_job.h" #include "debug.h" -#include "memcheck_settings.h" +#include "memcheck_config.h" #include "memcheck_tool.h" namespace Valgrind { MemcheckJob::MemcheckJob(KDevelop::ILaunchConfiguration* launchConfig) - : XmlJob(MemcheckTool::self(), launchConfig, new MemcheckSettings) + : XmlJob(MemcheckTool::self(), launchConfig, new MemcheckConfig) { } } diff --git a/tools/memcheck/memcheck_settings.cpp b/tools/memcheck/memcheck_settings.cpp deleted file mode 100644 index 1abd6f7..0000000 --- a/tools/memcheck/memcheck_settings.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "memcheck_settings.h" - -#include "memcheck_tool.h" - -namespace Valgrind -{ - -MemcheckSettings::MemcheckSettings() - : XmlSettings(MemcheckTool::self()->id()) - - , leakResolution( - this, - QStringLiteral("Leak Resolution"), - QStringLiteral("leak-resolution"), - QStringLiteral("high")) - - , showLeakKinds( - this, - QStringLiteral("Show Leak Kinds"), - QStringLiteral("show-leak-kinds"), - QStringLiteral("definite,possible")) - - , leakCheckHeuristics( - this, - QStringLiteral("Leak Check Heuristics"), - QStringLiteral("leak-check-heuristics"), - QStringLiteral("all")) - - , keepStacktraces( - this, - QStringLiteral("Keep Stacktraces"), - QStringLiteral("keep-stacktraces"), - QStringLiteral("alloc-and-free")) - - , freelistVol( - this, - QStringLiteral("Freelist Volume"), - QStringLiteral("freelist-vol"), - 20000000) - - , freelistBigBlocks( - this, - QStringLiteral("Freelist Big Blocks"), - QStringLiteral("freelist-big-blocks"), - 1000000) - - , undefValueErrors( - this, - QStringLiteral("Undef Value Errors"), - QStringLiteral("undef-value-errors"), - true) - - , showMismatchedFrees( - this, - QStringLiteral("Show Mismatched Frees"), - QStringLiteral("show-mismatched-frees"), - true) - - , partialLoadsOk( - this, - QStringLiteral("Partial Loads Ok"), - QStringLiteral("partial-loads-ok"), - true) - - , trackOrigins( - this, - QStringLiteral("Track Origins"), - QStringLiteral("track-origins"), - false) - - , expensiveDefinednessChecks( - this, - QStringLiteral("Expensive Definedness Checks"), - QStringLiteral("expensive-definedness-checks"), - false) -{ -} - -} diff --git a/tools/memcheck/memcheck_settings.h b/tools/memcheck/memcheck_settings.h deleted file mode 100644 index 0ff7d02..0000000 --- a/tools/memcheck/memcheck_settings.h +++ /dev/null @@ -1,48 +0,0 @@ -/* This file is part of KDevelop - Copyright 2017 Anton Anikin - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include "xmlsettings.h" - -namespace Valgrind -{ - -class MemcheckSettings : public XmlSettings -{ -public: - MemcheckSettings(); - ~MemcheckSettings() override = default; - - StringValue leakResolution; - StringValue showLeakKinds; - StringValue leakCheckHeuristics; - StringValue keepStacktraces; - - IntValue freelistVol; - IntValue freelistBigBlocks; - - BoolValue undefValueErrors; - BoolValue showMismatchedFrees; - BoolValue partialLoadsOk; - BoolValue trackOrigins; - BoolValue expensiveDefinednessChecks; -}; - -}