svf-lib 1.0.2680 → 1.0.2682
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-linux-aarch64/bin/mta +0 -0
- package/SVF-linux-aarch64/include/AE/Core/NumericValue.h +1 -1
- package/SVF-linux-aarch64/include/Graphs/CDG.h +1 -1
- package/SVF-linux-aarch64/include/Graphs/CallGraph.h +34 -3
- package/SVF-linux-aarch64/include/Graphs/ICFG.h +6 -0
- package/SVF-linux-aarch64/include/Graphs/SVFG.h +6 -0
- package/SVF-linux-aarch64/include/Graphs/SlicedGraphs.h +119 -84
- package/SVF-linux-aarch64/include/Graphs/ThreadCallGraph.h +37 -0
- package/SVF-linux-aarch64/include/Graphs/VFG.h +1 -1
- package/SVF-linux-aarch64/include/MTA/FSMPTA.h +50 -34
- package/SVF-linux-aarch64/include/MTA/LockAnalysis.h +95 -55
- package/SVF-linux-aarch64/include/MTA/MHP.h +65 -24
- package/SVF-linux-aarch64/include/MTA/MTA.h +99 -51
- package/SVF-linux-aarch64/include/MTA/MTASVFGBuilder.h +115 -50
- package/SVF-linux-aarch64/include/MTA/MTASlicer.h +73 -79
- package/SVF-linux-aarch64/include/MTA/MTAStat.h +54 -6
- package/SVF-linux-aarch64/include/MTA/TCT.h +13 -22
- package/SVF-linux-aarch64/include/SVF-LLVM/GEPTypeBridgeIterator.h +2 -2
- package/SVF-linux-aarch64/include/SVF-LLVM/ObjTypeInference.h +1 -1
- package/SVF-linux-aarch64/include/Util/Options.h +2 -4
- package/SVF-linux-aarch64/include/Util/SparseBitVector.h +2 -2
- package/SVF-linux-aarch64/lib/libSvfCore.so.3.4 +0 -0
- package/SVF-linux-aarch64/lib/libSvfLLVM.so.3.4 +0 -0
- package/SVF-linux-x86_64/include/SVF-LLVM/GEPTypeBridgeIterator.h +7 -3
- package/SVF-linux-x86_64/lib/libSvfLLVM.so.3.4 +0 -0
- package/package.json +1 -1
|
@@ -29,10 +29,6 @@
|
|
|
29
29
|
* The base data race detector is based on
|
|
30
30
|
* Yulei Sui, Peng Di, and Jingling Xue. "Sparse Flow-Sensitive Pointer Analysis for Multithreaded Programs".
|
|
31
31
|
* 2016 International Symposium on Code Generation and Optimization (CGO'16)
|
|
32
|
-
*
|
|
33
|
-
* This file also declares SlicedMTA, the multi-stage on-demand program slicing
|
|
34
|
-
* pipeline (MSli) introduced in "Multi-Stage On-Demand Program Slicing for
|
|
35
|
-
* Modular Analysis of Multi-Threaded Programs" (ISSTA 2026).
|
|
36
32
|
*/
|
|
37
33
|
|
|
38
34
|
#ifndef MTA_H_
|
|
@@ -41,7 +37,6 @@
|
|
|
41
37
|
#include <set>
|
|
42
38
|
#include <string>
|
|
43
39
|
#include <vector>
|
|
44
|
-
#include <functional>
|
|
45
40
|
#include <memory>
|
|
46
41
|
#include <utility>
|
|
47
42
|
#include "SVFIR/SVFIR.h"
|
|
@@ -51,6 +46,7 @@
|
|
|
51
46
|
#include "MemoryModel/PointsTo.h"
|
|
52
47
|
#include "MTA/MHP.h"
|
|
53
48
|
#include "MTA/LockAnalysis.h"
|
|
49
|
+
#include "MTA/MTASVFGBuilder.h"
|
|
54
50
|
#include "WPA/Andersen.h"
|
|
55
51
|
#include "Graphs/CallGraph.h"
|
|
56
52
|
|
|
@@ -70,7 +66,6 @@ class SVFStmt;
|
|
|
70
66
|
class SVFIR;
|
|
71
67
|
class ICFGNode;
|
|
72
68
|
// Forward declarations for the SlicedMTA slicing pipeline (see SlicedMTA impl).
|
|
73
|
-
class MTASVFGBuilder;
|
|
74
69
|
class SVFG;
|
|
75
70
|
class FlowSensitive;
|
|
76
71
|
class SlicedSVFGView;
|
|
@@ -102,9 +97,6 @@ public:
|
|
|
102
97
|
/// Run the shared detector and print a race report
|
|
103
98
|
virtual void reportRaces();
|
|
104
99
|
|
|
105
|
-
// Not implemented for now
|
|
106
|
-
// void dump(Module &module, MHP *mhp, LockAnalysis *lsa);
|
|
107
|
-
|
|
108
100
|
MHP* getMHP()
|
|
109
101
|
{
|
|
110
102
|
return mhp;
|
|
@@ -120,22 +112,33 @@ public:
|
|
|
120
112
|
{
|
|
121
113
|
const SVFStmt* stmt1;
|
|
122
114
|
const SVFStmt* stmt2;
|
|
123
|
-
RacePair(const SVFStmt* s1, const SVFStmt* s2)
|
|
115
|
+
RacePair(const SVFStmt* s1, const SVFStmt* s2)
|
|
116
|
+
: stmt1(statementLess(s2, s1) ? s2 : s1),
|
|
117
|
+
stmt2(statementLess(s2, s1) ? s1 : s2)
|
|
118
|
+
{
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static bool statementLess(const SVFStmt* lhs, const SVFStmt* rhs)
|
|
122
|
+
{
|
|
123
|
+
return lhs->getEdgeID() < rhs->getEdgeID();
|
|
124
|
+
}
|
|
125
|
+
|
|
124
126
|
bool operator<(const RacePair& other) const
|
|
125
127
|
{
|
|
126
|
-
if (stmt1 != other.stmt1)
|
|
127
|
-
|
|
128
|
+
if (stmt1->getEdgeID() != other.stmt1->getEdgeID())
|
|
129
|
+
return stmt1->getEdgeID() < other.stmt1->getEdgeID();
|
|
130
|
+
return stmt2->getEdgeID() < other.stmt2->getEdgeID();
|
|
128
131
|
}
|
|
129
132
|
};
|
|
130
133
|
|
|
131
134
|
/// Shared equivalence-class race detector (used by both MTA::reportRaces and
|
|
132
135
|
/// the SlicedMTA pipeline). Returns the racy statements and fills outRacePairs.
|
|
133
136
|
static std::set<const SVFStmt*> detectRace(
|
|
134
|
-
SVFIR*
|
|
137
|
+
SVFIR* svfir, AndersenBase* pta, MHP* mhp, LockAnalysis* lockAnalysis,
|
|
135
138
|
CallGraph* callGraph, std::set<RacePair>& outRacePairs);
|
|
136
139
|
|
|
137
140
|
/// Escape/points-to helpers for the shared detector.
|
|
138
|
-
static PointsTo getGlobalObjectVariables(SVFIR*
|
|
141
|
+
static PointsTo getGlobalObjectVariables(SVFIR* svfir);
|
|
139
142
|
static PointsTo getPointsToClosure(AndersenBase* pta, const PointsTo& pts);
|
|
140
143
|
|
|
141
144
|
/// Whether the program has any thread (fork-target) function reachable via a
|
|
@@ -150,12 +153,47 @@ private:
|
|
|
150
153
|
const ICFGNode* node;
|
|
151
154
|
bool isStore;
|
|
152
155
|
NodeID tid;
|
|
153
|
-
NodeBS
|
|
156
|
+
const NodeBS* interleaving;
|
|
157
|
+
bool locked;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
struct RaceClass
|
|
161
|
+
{
|
|
162
|
+
bool isStore;
|
|
163
|
+
bool locked;
|
|
164
|
+
size_t representative;
|
|
165
|
+
std::vector<size_t> members;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
struct RaceClassKey
|
|
169
|
+
{
|
|
170
|
+
NodeID tid;
|
|
171
|
+
bool isStore;
|
|
172
|
+
const NodeBS* interleaving;
|
|
154
173
|
bool locked;
|
|
174
|
+
NodeID lockNodeId;
|
|
175
|
+
|
|
176
|
+
bool operator<(const RaceClassKey& other) const;
|
|
155
177
|
};
|
|
156
178
|
|
|
179
|
+
using ObjectToRaceOccurrences = Map<NodeID, std::vector<size_t>>;
|
|
180
|
+
|
|
157
181
|
/// Helpers for the equivalence-class race detector.
|
|
158
182
|
//@{
|
|
183
|
+
static void collectRaceOccurrences(
|
|
184
|
+
SVFIR* svfir, AndersenBase* pta, MHP* mhp,
|
|
185
|
+
LockAnalysis* lockAnalysis, CallGraph* callGraph,
|
|
186
|
+
const PointsTo& escapedObjects,
|
|
187
|
+
std::vector<RaceOccurrence>& occurrences,
|
|
188
|
+
ObjectToRaceOccurrences& objectToOccurrences);
|
|
189
|
+
static std::vector<RaceClass> buildRaceClasses(
|
|
190
|
+
const std::vector<RaceOccurrence>& occurrences,
|
|
191
|
+
const std::vector<size_t>& occurrenceIndices);
|
|
192
|
+
static void emitRacePairs(
|
|
193
|
+
MHP* mhp, LockAnalysis* lockAnalysis,
|
|
194
|
+
const std::vector<RaceOccurrence>& occurrences,
|
|
195
|
+
const std::vector<RaceClass>& classes,
|
|
196
|
+
std::set<RacePair>& outRacePairs);
|
|
159
197
|
static bool occurrencesRace(MHP* mhp, const RaceOccurrence& first, const RaceOccurrence& second);
|
|
160
198
|
static void commitRacePair(std::set<RacePair>& out,
|
|
161
199
|
const RaceOccurrence& first, const RaceOccurrence& second);
|
|
@@ -178,21 +216,16 @@ private:
|
|
|
178
216
|
* 4. PTA slicing + main flow-sensitive FSAM (FSMPTA) on the slice
|
|
179
217
|
* 5. final race detection on the sliced graph using FSAM points-to
|
|
180
218
|
*
|
|
181
|
-
* It operates entirely on the SVFIR (LLVM-free). The
|
|
182
|
-
*
|
|
183
|
-
*
|
|
219
|
+
* It operates entirely on the SVFIR (LLVM-free). The LLVM-aware caller runs the
|
|
220
|
+
* Andersen pre-analysis and materialises its resolved indirect calls into the
|
|
221
|
+
* PAG before invoking runOnModule.
|
|
184
222
|
*
|
|
185
|
-
* Behaviour is controlled by Options (MTFlowSensitive,
|
|
186
|
-
*
|
|
223
|
+
* Behaviour is controlled by Options (MTFlowSensitive, MTAEnableSlicing,
|
|
224
|
+
* MTASingleStageSlicing, DumpMTAGraphs).
|
|
187
225
|
*/
|
|
188
226
|
class SlicedMTA
|
|
189
227
|
{
|
|
190
228
|
public:
|
|
191
|
-
/// The one LLVM-dependent step of the pipeline: resolve the indirect-call
|
|
192
|
-
/// edges discovered by Andersen into PAG copy/call edges. The caller (the
|
|
193
|
-
/// LLVM-aware tool) supplies it via SVFIRBuilder::updateCallGraph.
|
|
194
|
-
using ResolveIndirectCalls = std::function<void(CallGraph*)>;
|
|
195
|
-
|
|
196
229
|
/// The shared race detector lives in MTA; reuse its race-pair type.
|
|
197
230
|
using RacePair = MTA::RacePair;
|
|
198
231
|
|
|
@@ -204,20 +237,37 @@ public:
|
|
|
204
237
|
SlicedMTA(const SlicedMTA&) = delete;
|
|
205
238
|
SlicedMTA& operator=(const SlicedMTA&) = delete;
|
|
206
239
|
|
|
207
|
-
/// Run the slicing pipeline
|
|
208
|
-
|
|
240
|
+
/// Run the slicing pipeline with its prepared Andersen pre-analysis.
|
|
241
|
+
bool runOnModule(SVFIR* pag, AndersenWaveDiff& preAnalysis);
|
|
209
242
|
|
|
210
243
|
private:
|
|
211
244
|
// --- pipeline stages ---
|
|
212
|
-
bool runPreAnalysis(
|
|
245
|
+
bool runPreAnalysis();
|
|
213
246
|
bool runMTASlicingAndAnalysis();
|
|
214
247
|
bool runPTASlicingAndAnalysis();
|
|
215
248
|
bool runFinalRaceDetection();
|
|
216
|
-
void
|
|
249
|
+
void buildPreAnalysisSVFG();
|
|
250
|
+
|
|
251
|
+
/// Pipeline utilities shared by the sliced and whole-program paths.
|
|
252
|
+
//@{
|
|
253
|
+
static void reportOriginalStatistics(SVFIR* svfir);
|
|
254
|
+
static std::set<const ICFGNode*> collectICFGNodes(
|
|
255
|
+
SVFG* svfg, const NodeBS& svfgNodeIds);
|
|
256
|
+
static void reportPTASliceStatistics(
|
|
257
|
+
const std::set<const ICFGNode*>& icfgNodes);
|
|
258
|
+
struct RaceDigests
|
|
259
|
+
{
|
|
260
|
+
u64_t alarm;
|
|
261
|
+
u64_t pair;
|
|
262
|
+
};
|
|
263
|
+
static std::string raceStatementKey(const SVFStmt* statement);
|
|
264
|
+
static void updateDigest(u64_t& digest, const std::string& value);
|
|
265
|
+
static RaceDigests computeRaceDigests(const std::set<RacePair>& pairs);
|
|
266
|
+
//@}
|
|
217
267
|
|
|
218
268
|
/// No-slice A/B baseline: run the FSAM detection on the whole program (no
|
|
219
269
|
/// slicing), so its time and race set can be compared against the sliced run.
|
|
220
|
-
|
|
270
|
+
bool runWholeProgramDetection();
|
|
221
271
|
|
|
222
272
|
/// Main pointer-analysis instance feeding final race detection (the
|
|
223
273
|
/// flow-sensitive FSAM, a BVDataPTAImpl queried polymorphically).
|
|
@@ -227,47 +277,45 @@ private:
|
|
|
227
277
|
std::set<const SVFStmt*> getVulnerableStmts() const;
|
|
228
278
|
|
|
229
279
|
// --- race detection ---
|
|
230
|
-
///
|
|
280
|
+
/// Refine the pre-analysis candidate pairs with main-phase ILA and FSAM.
|
|
231
281
|
std::set<RacePair> detectRacePairsOnSlicedGraph(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
// final detection's lock signature. The sliced lock analysis walks bridged
|
|
236
|
-
// edges, which fabricate lock-carrying paths the whole program lacks (a
|
|
237
|
-
// query-preservation break); lock-span is control-flow-sensitive, so it must
|
|
238
|
-
// see real edges. Built lazily, cheap (no FSAM/MHP) next to the slicing win.
|
|
239
|
-
LockAnalysis* buildFullLockAnalysis();
|
|
282
|
+
const std::set<RacePair>& preAnalysisRacePairs,
|
|
283
|
+
BVDataPTAImpl* slicedPTA, MHP* slicedMHP,
|
|
284
|
+
LockAnalysis* slicedLockAnalysis);
|
|
240
285
|
|
|
241
286
|
// --- pipeline state (owned unless noted) ---
|
|
242
|
-
SVFIR*
|
|
287
|
+
SVFIR* svfir = nullptr;
|
|
243
288
|
// Main-phase context depth, set by runOnModule; the pre-analysis uses it
|
|
244
289
|
// to reconcile context-truncation-merged thread instances.
|
|
245
|
-
u32_t
|
|
290
|
+
u32_t mainContextDepth;
|
|
246
291
|
std::unique_ptr<TCT> tct;
|
|
247
292
|
std::unique_ptr<MHP> mhp;
|
|
248
293
|
std::unique_ptr<LockAnalysis> lockAnalysis;
|
|
249
294
|
// Inclusion-based Andersen's pre-analysis (a shared singleton, not owned
|
|
250
|
-
// here
|
|
295
|
+
// here; the tool releases it after this object is destroyed). Feeds TCT/MHP/lock/
|
|
251
296
|
// race pre-analysis, the thread-aware VFG_pre, and the main FSMPTA.
|
|
252
|
-
AndersenWaveDiff*
|
|
253
|
-
|
|
254
|
-
|
|
297
|
+
AndersenWaveDiff* preAndersen = nullptr;
|
|
298
|
+
ThreadCallGraph* threadCallGraph = nullptr;
|
|
299
|
+
std::unique_ptr<MTASVFGBuilder> preSVFGBuilder; // owns preSVFG
|
|
300
|
+
SVFG* preSVFG = nullptr;
|
|
255
301
|
std::unique_ptr<MultiStageSlicer> multiStageSlicer;
|
|
302
|
+
NodeBS preCandidateSolveNodeIds;
|
|
256
303
|
std::unique_ptr<SingleSlicer> singleSlicer;
|
|
304
|
+
/// VFG'_pre endpoint-filtered, context-insensitive pre-MHP candidates.
|
|
305
|
+
/// This is only a conservative worklist for rebuilding Main-TVF; the main
|
|
306
|
+
/// phase independently re-decides every edge with main MHP and lock facts.
|
|
307
|
+
MTASVFGBuilder::ThreadVFCandidateList selectedThreadVFCandidates;
|
|
257
308
|
// -mta-slicing-single: the one unified slice, computed in MTA slicing and reused
|
|
258
309
|
// (not recomputed) for PTA slicing so both stages share V_Single.
|
|
259
310
|
std::set<const ICFGNode*> singleSlicedNodes;
|
|
311
|
+
NodeBS singleSlicedSVFGNodeIds;
|
|
260
312
|
std::unique_ptr<SlicedSVFIRView> mtaSlicedView;
|
|
261
313
|
std::unique_ptr<SlicedSVFIRView> ptaSlicedView;
|
|
262
314
|
std::unique_ptr<SlicedSVFGView> slicedSVFGView;
|
|
263
|
-
std::unique_ptr<FlowSensitive>
|
|
315
|
+
std::unique_ptr<FlowSensitive> mainFSMPTA;
|
|
264
316
|
std::unique_ptr<SlicedTCT> slicedTCT;
|
|
265
|
-
std::unique_ptr<MHP>
|
|
317
|
+
std::unique_ptr<MHP> slicedMHP;
|
|
266
318
|
std::unique_ptr<LockAnalysis> slicedLockAnalysis;
|
|
267
|
-
// Whole-ICFG lock analysis for the final detection (see buildFullLockAnalysis).
|
|
268
|
-
std::unique_ptr<SlicedSVFIRView> fullLockView;
|
|
269
|
-
std::unique_ptr<SlicedTCT> fullLockTCT;
|
|
270
|
-
std::unique_ptr<LockAnalysis> fullLockAnalysis;
|
|
271
319
|
bool hasThreadFunctions = false;
|
|
272
320
|
std::set<RacePair> racePairs;
|
|
273
321
|
};
|
|
@@ -24,15 +24,6 @@
|
|
|
24
24
|
* MTASVFGBuilder.h
|
|
25
25
|
*
|
|
26
26
|
* Author: Jiawei Yang
|
|
27
|
-
*
|
|
28
|
-
* Builds a *thread-aware* Sparse Value-Flow Graph (SVFG) for the FSAM
|
|
29
|
-
* flow-sensitive multithreaded pointer analysis (Sui, Di, Xue, CGO'16).
|
|
30
|
-
*
|
|
31
|
-
* On top of the stock thread-oblivious SVFG, it adds inter-thread (interference)
|
|
32
|
-
* indirect value-flow edges between store/load and store/store statements that
|
|
33
|
-
* (1) may-happen-in-parallel (MHP), and
|
|
34
|
-
* (2) may-alias on the address-taken object, and
|
|
35
|
-
* (3) are not excluded by a common lock (non-interference lock-pair pruning).
|
|
36
27
|
*/
|
|
37
28
|
|
|
38
29
|
#ifndef INCLUDE_MTA_MTASVFGBUILDER_H_
|
|
@@ -44,14 +35,13 @@
|
|
|
44
35
|
#include "MTA/MHP.h"
|
|
45
36
|
#include "MTA/LockAnalysis.h"
|
|
46
37
|
#include "MemoryModel/PointsTo.h"
|
|
47
|
-
#include <map>
|
|
48
|
-
#include <set>
|
|
49
38
|
#include <utility>
|
|
39
|
+
#include <vector>
|
|
50
40
|
|
|
51
41
|
namespace SVF
|
|
52
42
|
{
|
|
53
43
|
|
|
54
|
-
class
|
|
44
|
+
class SlicedSVFGView;
|
|
55
45
|
|
|
56
46
|
class MTASVFGBuilder : public SVFGBuilder
|
|
57
47
|
{
|
|
@@ -59,25 +49,21 @@ public:
|
|
|
59
49
|
typedef Set<const StmtSVFGNode*> SVFGNodeSet;
|
|
60
50
|
typedef NodeBS SVFGNodeIDSet;
|
|
61
51
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
enum class InterferenceEdgeMode
|
|
53
|
+
{
|
|
54
|
+
Analysis, ///< Build labelled edges for FSMPTA.
|
|
55
|
+
SlicingOnly ///< Build unlabelled connectivity for VFG_pre slicing.
|
|
56
|
+
};
|
|
65
57
|
|
|
66
|
-
///
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/// store/load nodes (a sliced-out endpoint's edge is inert in the gated
|
|
73
|
-
/// solve, so it need not be built);
|
|
74
|
-
/// - the [THREAD-VF] query map is skipped, as only VFG_pre slicing reads it.
|
|
75
|
-
/// The pre-analysis build leaves this unset (whole program, query map built).
|
|
76
|
-
void configureForMainSolve(const SlicedICFGView* slice)
|
|
58
|
+
/// Constructor: driven by the interleaving (MHP) and lock analyses.
|
|
59
|
+
MTASVFGBuilder(MHP* mhp, LockAnalysis* lockAnalysis,
|
|
60
|
+
InterferenceEdgeMode edgeMode = InterferenceEdgeMode::Analysis)
|
|
61
|
+
: SVFGBuilder(),
|
|
62
|
+
labelInterferenceEdges(edgeMode == InterferenceEdgeMode::Analysis),
|
|
63
|
+
mhp(mhp), lockAnalysis(lockAnalysis)
|
|
77
64
|
{
|
|
78
|
-
icfgSlice = slice;
|
|
79
|
-
recordThreadVF = false;
|
|
80
65
|
}
|
|
66
|
+
~MTASVFGBuilder() override = default;
|
|
81
67
|
|
|
82
68
|
/// A candidate thread-aware value-flow edge s --o--> s' (src store, dst
|
|
83
69
|
/// load/store), keyed by its endpoint SVFG nodes.
|
|
@@ -98,11 +84,81 @@ public:
|
|
|
98
84
|
///
|
|
99
85
|
/// The value stores only the additional lock-span witnesses; the endpoint
|
|
100
86
|
/// ICFG nodes are implicit in the key and consumers must add them back.
|
|
101
|
-
|
|
87
|
+
using ThreadVFQueryMap = Map<ThreadVFEdge, Set<const ICFGNode*>>;
|
|
88
|
+
const ThreadVFQueryMap& getThreadVFQueryMap() const
|
|
102
89
|
{
|
|
103
90
|
return threadVFQueryMap;
|
|
104
91
|
}
|
|
105
92
|
|
|
93
|
+
struct ThreadVFCandidate
|
|
94
|
+
{
|
|
95
|
+
ThreadVFCandidate(NodeID sourceNodeId, NodeID destinationNodeId)
|
|
96
|
+
: sourceNodeId(sourceNodeId), destinationNodeId(destinationNodeId)
|
|
97
|
+
{
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
bool operator<(const ThreadVFCandidate& other) const
|
|
101
|
+
{
|
|
102
|
+
return sourceNodeId < other.sourceNodeId ||
|
|
103
|
+
(sourceNodeId == other.sourceNodeId &&
|
|
104
|
+
destinationNodeId < other.destinationNodeId);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
bool operator==(const ThreadVFCandidate& other) const
|
|
108
|
+
{
|
|
109
|
+
return sourceNodeId == other.sourceNodeId &&
|
|
110
|
+
destinationNodeId == other.destinationNodeId;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
NodeID sourceNodeId;
|
|
114
|
+
NodeID destinationNodeId;
|
|
115
|
+
};
|
|
116
|
+
using ThreadVFCandidateList = std::vector<ThreadVFCandidate>;
|
|
117
|
+
|
|
118
|
+
class ThreadVFBuildConfig
|
|
119
|
+
{
|
|
120
|
+
public:
|
|
121
|
+
static ThreadVFBuildConfig mainPhase(
|
|
122
|
+
const SlicedSVFGView& scope,
|
|
123
|
+
const ThreadVFCandidateList* candidates = nullptr)
|
|
124
|
+
{
|
|
125
|
+
return ThreadVFBuildConfig(&scope, candidates);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static ThreadVFBuildConfig wholeProgram()
|
|
129
|
+
{
|
|
130
|
+
return ThreadVFBuildConfig(nullptr, nullptr);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private:
|
|
134
|
+
friend class MTASVFGBuilder;
|
|
135
|
+
ThreadVFBuildConfig(const SlicedSVFGView* scope,
|
|
136
|
+
const ThreadVFCandidateList* candidates)
|
|
137
|
+
: scope(scope), candidates(candidates)
|
|
138
|
+
{
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const SlicedSVFGView* scope = nullptr; ///< null means the whole base SVFG
|
|
142
|
+
/// Optional conservative candidate universe selected from VFG_pre.
|
|
143
|
+
/// Main MHP/lock facts still decide every emitted edge; this only avoids
|
|
144
|
+
/// re-querying alias pairs that context-insensitive pre MHP rejected or
|
|
145
|
+
/// whose endpoints do not survive VFG'_pre.
|
|
146
|
+
const ThreadVFCandidateList* candidates = nullptr;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/// Replace only the ILA-dependent thread-aware overlay. The underlying
|
|
150
|
+
/// MemorySSA, stock SVFG, and fork/join value flow remain unchanged.
|
|
151
|
+
void replaceThreadAwareOverlay(MHP* mhp, LockAnalysis* lockAnalysis,
|
|
152
|
+
const ThreadVFBuildConfig& config);
|
|
153
|
+
|
|
154
|
+
/// Remove all currently attached thread-aware interference edges.
|
|
155
|
+
void clearThreadAwareOverlay();
|
|
156
|
+
|
|
157
|
+
size_t getThreadAwareEdgeCount() const
|
|
158
|
+
{
|
|
159
|
+
return threadAwareEdges.size();
|
|
160
|
+
}
|
|
161
|
+
|
|
106
162
|
protected:
|
|
107
163
|
/// Rewrite the SVFG build hook: build the stock SVFG, then add MHP edges.
|
|
108
164
|
void buildSVFG() override;
|
|
@@ -112,13 +168,16 @@ protected:
|
|
|
112
168
|
std::unique_ptr<MRGenerator> createMRGenerator(BVDataPTAImpl* pta, bool ptrOnlyMSSA) override;
|
|
113
169
|
|
|
114
170
|
private:
|
|
115
|
-
///
|
|
116
|
-
const
|
|
117
|
-
|
|
171
|
+
/// Active overlay configuration; defaults suit VFG_pre.
|
|
172
|
+
const SlicedSVFGView* overlayScope = nullptr; ///< null = whole base SVFG
|
|
173
|
+
const ThreadVFCandidateList* overlayCandidates = nullptr;
|
|
174
|
+
bool recordThreadVFQueries = true; ///< false = skip [THREAD-VF] recording
|
|
175
|
+
bool labelInterferenceEdges = true; ///< false = VFG_pre (sliced-only): omit edge points-to labels
|
|
118
176
|
|
|
119
177
|
/// Collect the store/load SVFG nodes to pair for interference edges (all of
|
|
120
178
|
/// them, or -- when a slice is set -- only the kept ones).
|
|
121
179
|
void collectLoadStoreSVFGNodes();
|
|
180
|
+
bool isInOverlayScope(const SVFGNode* node) const;
|
|
122
181
|
|
|
123
182
|
/// FSAM join-related thread-oblivious value flow (the "return" half of
|
|
124
183
|
/// treating a join as a call without a forward): connect each start
|
|
@@ -131,44 +190,50 @@ private:
|
|
|
131
190
|
/// join, mirroring SVFG::addInterIndirectVFRetEdge using the public SVFG API
|
|
132
191
|
/// (points-to intersection + dedup via hasInterVFGEdge + addSVFGEdge).
|
|
133
192
|
void addJoinRetEdge(const FormalOUTSVFGNode* formalOut,
|
|
134
|
-
const ActualOUTSVFGNode* actualOut,
|
|
193
|
+
const ActualOUTSVFGNode* actualOut,
|
|
194
|
+
CallSiteID callSiteId);
|
|
135
195
|
|
|
136
196
|
/// Connect inter-thread (interference) value-flow edges for MHP pairs.
|
|
137
197
|
void connectMHPEdges(PointerAnalysis* pta);
|
|
138
198
|
|
|
139
|
-
void handleStoreLoad(const StmtSVFGNode*
|
|
140
|
-
|
|
199
|
+
void handleStoreLoad(const StmtSVFGNode* store,
|
|
200
|
+
const StmtSVFGNode* load, PointerAnalysis* pta);
|
|
201
|
+
void handleStoreStore(const StmtSVFGNode* firstStore,
|
|
202
|
+
const StmtSVFGNode* secondStore,
|
|
203
|
+
PointerAnalysis* pta);
|
|
141
204
|
|
|
142
205
|
/// Record the [THREAD-VF] slicing sources for one candidate pair s --o--> s'
|
|
143
|
-
/// (
|
|
206
|
+
/// (source = store, destination = load/store). Adds the endpoints, and — when the
|
|
144
207
|
/// pair is protected by a common lock — the in-span successor/predecessor
|
|
145
208
|
/// witnesses needed to re-decide the non-interference (tail/head) test.
|
|
146
|
-
void recordThreadVFSource(const StmtSVFGNode*
|
|
209
|
+
void recordThreadVFSource(const StmtSVFGNode* source,
|
|
210
|
+
const StmtSVFGNode* destination,
|
|
211
|
+
bool commonLock);
|
|
147
212
|
|
|
148
213
|
/// Add a thread-MHP indirect value-flow edge srcId -> dstId carrying pts.
|
|
149
214
|
SVFGEdge* addTDEdge(NodeID srcId, NodeID dstId, const PointsTo& pts);
|
|
150
215
|
|
|
151
216
|
/// Lock-span head/tail tests (non-interference lock-pair pruning).
|
|
152
217
|
//@{
|
|
153
|
-
SVFGNodeIDSet
|
|
154
|
-
SVFGNodeIDSet
|
|
155
|
-
bool isHeadOfSpan(const StmtSVFGNode*
|
|
156
|
-
bool isTailOfSpan(const StmtSVFGNode*
|
|
218
|
+
SVFGNodeIDSet getPredecessorNodes(const StmtSVFGNode* node);
|
|
219
|
+
SVFGNodeIDSet getSuccessorNodes(const StmtSVFGNode* node);
|
|
220
|
+
bool isHeadOfSpan(const StmtSVFGNode* node);
|
|
221
|
+
bool isTailOfSpan(const StmtSVFGNode* node);
|
|
157
222
|
//@}
|
|
158
223
|
|
|
159
|
-
SVFGNodeSet
|
|
160
|
-
SVFGNodeSet
|
|
224
|
+
SVFGNodeSet storeNodes;
|
|
225
|
+
SVFGNodeSet loadNodes;
|
|
161
226
|
|
|
162
227
|
/// [THREAD-VF] per-edge query map (see getThreadVFQueryMap).
|
|
163
|
-
|
|
164
|
-
|
|
228
|
+
ThreadVFQueryMap threadVFQueryMap;
|
|
165
229
|
MHP* mhp;
|
|
166
|
-
LockAnalysis*
|
|
230
|
+
LockAnalysis* lockAnalysis;
|
|
167
231
|
|
|
168
|
-
Map<const StmtSVFGNode*, SVFGNodeIDSet>
|
|
169
|
-
Map<const StmtSVFGNode*, SVFGNodeIDSet>
|
|
170
|
-
Map<const StmtSVFGNode*, bool>
|
|
171
|
-
Map<const StmtSVFGNode*, bool>
|
|
232
|
+
Map<const StmtSVFGNode*, SVFGNodeIDSet> predecessorCache;
|
|
233
|
+
Map<const StmtSVFGNode*, SVFGNodeIDSet> successorCache;
|
|
234
|
+
Map<const StmtSVFGNode*, bool> spanHeadCache;
|
|
235
|
+
Map<const StmtSVFGNode*, bool> spanTailCache;
|
|
236
|
+
SVFGEdgeSet threadAwareEdges;
|
|
172
237
|
};
|
|
173
238
|
|
|
174
239
|
} // End namespace SVF
|