1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "valgrindutils.h"
#include "valgrindprocess.h"
#include "valgrindsettings.h"
#include "valgrindtr.h"
#include <coreplugin/icore.h>
#include <projectexplorer/devicesupport/devicekitaspects.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/runcontrol.h>
using namespace Core;
using namespace ProjectExplorer;
using namespace Tasking;
using namespace Utils;
namespace Valgrind::Internal {
static QString selfModifyingCodeDetectionToString(ValgrindSettings::SelfModifyingCodeDetection detection)
{
switch (detection) {
case ValgrindSettings::DetectSmcNo: return "none";
case ValgrindSettings::DetectSmcEverywhere: return "all";
case ValgrindSettings::DetectSmcEverywhereButFile: return "all-non-file";
case ValgrindSettings::DetectSmcStackOnly: return "stack";
}
return {};
}
ExecutableItem initValgrindRecipe(const Storage<ValgrindSettings> &storage, RunControl *runControl)
{
const auto onSetup = [storage, runControl] {
storage->fromMap(runControl->settingsData(ANALYZER_VALGRIND_SETTINGS));
if (storage->valgrindExecutable().searchInPath().isExecutableFile()) {
emit runStorage()->started();
return DoneResult::Success;
}
runControl->postMessage(Tr::tr("Valgrind executable \"%1\" not found or not executable.\n"
"Check settings or ensure Valgrind is installed and available in PATH.")
.arg(storage->valgrindExecutable().toUserOutput()), ErrorMessageFormat);
return DoneResult::Error;
};
return Sync(onSetup);
}
void setupValgrindProcess(ValgrindProcess *process, RunControl *runControl,
const CommandLine &valgrindCommand)
{
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
QObject::connect(process, &ValgrindProcess::appendMessage, runControl,
[runControl](const QString &msg, OutputFormat format) {
runControl->postMessage(msg, format);
});
QObject::connect(process, &ValgrindProcess::processErrorReceived, runControl,
[runControl, valgrindCommand](const QString &errorString, ProcessResult result) {
switch (result) {
case ProcessResult::StartFailed: {
const FilePath valgrind = valgrindCommand.executable();
if (!valgrind.isEmpty()) {
runControl->postMessage(Tr::tr("Error: \"%1\" could not be started: %2")
.arg(valgrind.toUserOutput(), errorString), ErrorMessageFormat);
} else {
runControl->postMessage(Tr::tr("Error: no Valgrind executable set."),
ErrorMessageFormat);
}
break;
}
case ProcessResult::Canceled:
runControl->postMessage(Tr::tr("Process terminated."), ErrorMessageFormat);
return; // Intentional.
case ProcessResult::FinishedWithError:
runControl->postMessage(Tr::tr("Process exited with return value %1\n").arg(errorString), NormalMessageFormat);
break;
default:
break;
}
runControl->showOutputPane();
});
QObject::connect(runStorage().activeStorage(), &RunInterface::canceled, process, &ValgrindProcess::stop);
process->setValgrindCommand(valgrindCommand);
process->setDebuggee(runControl->runnable());
if (auto aspect = runControl->aspectData<TerminalAspect>())
process->setUseTerminal(aspect->useTerminal);
}
CommandLine defaultValgrindCommand(RunControl *runControl, const ValgrindSettings &settings)
{
FilePath valgrindExecutable = settings.valgrindExecutable();
if (IDevice::ConstPtr dev = RunDeviceKitAspect::device(runControl->kit()))
valgrindExecutable = dev->filePath(valgrindExecutable.path());
CommandLine valgrindCommand{valgrindExecutable};
valgrindCommand.addArgs(settings.valgrindArguments(), CommandLine::Raw);
valgrindCommand.addArg("--smc-check=" + selfModifyingCodeDetectionToString(
settings.selfModifyingCodeDetection()));
return valgrindCommand;
}
} // Valgrid::Internal
|