svf-lib 1.0.2674 → 1.0.2676

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.
@@ -26,25 +26,58 @@
26
26
  * Created on: May 14, 2014
27
27
  * Author: Yulei Sui, Peng Di
28
28
  *
29
- * The implementation is based on
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).
32
36
  */
33
37
 
34
38
  #ifndef MTA_H_
35
39
  #define MTA_H_
36
40
 
41
+ #include <set>
42
+ #include <string>
43
+ #include <vector>
44
+ #include <functional>
45
+ #include <memory>
46
+ #include <utility>
47
+ #include "SVFIR/SVFIR.h"
48
+ #include "SVFIR/SVFValue.h"
49
+ #include "SVFIR/SVFStatements.h"
50
+ #include "SVFIR/SVFVariables.h"
51
+ #include "MemoryModel/PointsTo.h"
52
+ #include "MTA/MHP.h"
53
+ #include "MTA/LockAnalysis.h"
54
+ #include "WPA/Andersen.h"
55
+ #include "Graphs/CallGraph.h"
56
+
37
57
  namespace SVF
38
58
  {
39
59
 
40
60
  class PointerAnalysis;
41
61
  class AndersenWaveDiff;
62
+ class AndersenBase;
42
63
  class ThreadCallGraph;
64
+ class CallGraph;
43
65
  class MTAStat;
44
66
  class TCT;
45
67
  class MHP;
46
68
  class LockAnalysis;
69
+ class SVFStmt;
47
70
  class SVFIR;
71
+ class ICFGNode;
72
+ // Forward declarations for the SlicedMTA slicing pipeline (see SlicedMTA impl).
73
+ class MTASVFGBuilder;
74
+ class SVFG;
75
+ class FlowSensitive;
76
+ class SlicedSVFGView;
77
+ class MultiStageSlicer;
78
+ class SingleSlicer;
79
+ class SlicedSVFIRView;
80
+ class SlicedTCT;
48
81
 
49
82
  /*!
50
83
  * Base data race detector
@@ -66,8 +99,8 @@ public:
66
99
  virtual MHP* computeMHP(TCT* tct);
67
100
  /// Compute locksets
68
101
  virtual LockAnalysis* computeLocksets(TCT* tct);
69
- /// Perform detection
70
- virtual void detect();
102
+ /// Run the shared detector and print a race report
103
+ virtual void reportRaces();
71
104
 
72
105
  // Not implemented for now
73
106
  // void dump(Module &module, MHP *mhp, LockAnalysis *lsa);
@@ -81,7 +114,53 @@ public:
81
114
  {
82
115
  return lsa;
83
116
  }
117
+
118
+ /// A race pair: two statements that may race.
119
+ struct RacePair
120
+ {
121
+ const SVFStmt* stmt1;
122
+ const SVFStmt* stmt2;
123
+ RacePair(const SVFStmt* s1, const SVFStmt* s2) : stmt1(s1), stmt2(s2) {}
124
+ bool operator<(const RacePair& other) const
125
+ {
126
+ if (stmt1 != other.stmt1) return stmt1 < other.stmt1;
127
+ return stmt2 < other.stmt2;
128
+ }
129
+ };
130
+
131
+ /// Shared equivalence-class race detector (used by both MTA::reportRaces and
132
+ /// the SlicedMTA pipeline). Returns the racy statements and fills outRacePairs.
133
+ static std::set<const SVFStmt*> detectRace(
134
+ SVFIR* svfIr, AndersenBase* pta, MHP* mhp, LockAnalysis* lockAnalysis,
135
+ CallGraph* callGraph, std::set<RacePair>& outRacePairs);
136
+
137
+ /// Escape/points-to helpers for the shared detector.
138
+ static PointsTo getGlobalObjectVariables(SVFIR* svfIr);
139
+ static PointsTo getPointsToClosure(AndersenBase* pta, const PointsTo& pts);
140
+
141
+ /// Whether the program has any thread (fork-target) function reachable via a
142
+ /// fork edge.
143
+ static bool hasThreadFunctions(CallGraph* callGraph);
144
+
84
145
  private:
146
+ /// One occurrence of a memory access under one thread instance.
147
+ struct RaceOccurrence
148
+ {
149
+ const SVFStmt* stmt;
150
+ const ICFGNode* node;
151
+ bool isStore;
152
+ NodeID tid;
153
+ NodeBS interleav;
154
+ bool locked;
155
+ };
156
+
157
+ /// Helpers for the equivalence-class race detector.
158
+ //@{
159
+ static bool occurrencesRace(MHP* mhp, const RaceOccurrence& first, const RaceOccurrence& second);
160
+ static void commitRacePair(std::set<RacePair>& out,
161
+ const RaceOccurrence& first, const RaceOccurrence& second);
162
+ //@}
163
+
85
164
  ThreadCallGraph* tcg;
86
165
  std::unique_ptr<TCT> tct;
87
166
  std::unique_ptr<MTAStat> stat;
@@ -89,6 +168,110 @@ private:
89
168
  LockAnalysis* lsa;
90
169
  };
91
170
 
171
+ /*!
172
+ * Multi-stage on-demand slicing race detection pipeline (MSli).
173
+ *
174
+ * runOnModule drives five stages on a pre-built SVFIR:
175
+ * 1. (caller) build SVFIR + resolve indirect calls into the PAG
176
+ * 2. pre-analysis: Andersen, TCT, MHP, lock, candidate race pairs, VFG_pre
177
+ * 3. MTA slicing: slice the thread-aware graph, build the sliced MHP/lock
178
+ * 4. PTA slicing + main flow-sensitive FSAM (FSMPTA) on the slice
179
+ * 5. final race detection on the sliced graph using FSAM points-to
180
+ *
181
+ * It operates entirely on the SVFIR (LLVM-free). The single LLVM-dependent step --
182
+ * materialising resolved indirect calls into the PAG -- is injected by the caller
183
+ * as a callback (see runOnModule).
184
+ *
185
+ * Behaviour is controlled by Options (MTFlowSensitive, EnableSlicing,
186
+ * SlicingSingle, SlicedDumpDot).
187
+ */
188
+ class SlicedMTA
189
+ {
190
+ 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
+ /// The shared race detector lives in MTA; reuse its race-pair type.
197
+ using RacePair = MTA::RacePair;
198
+
199
+ // Out-of-line (defined where the member types are complete) so callers that
200
+ // only see the forward-declared unique_ptr member types need not be complete.
201
+ SlicedMTA();
202
+ ~SlicedMTA();
203
+
204
+ SlicedMTA(const SlicedMTA&) = delete;
205
+ SlicedMTA& operator=(const SlicedMTA&) = delete;
206
+
207
+ /// Run the slicing pipeline on a pre-built SVFIR.
208
+ void runOnModule(SVFIR* pag, const ResolveIndirectCalls& resolveIndirectCalls);
209
+
210
+ private:
211
+ // --- pipeline stages ---
212
+ bool runPreAnalysis(const ResolveIndirectCalls& resolveIndirectCalls);
213
+ bool runMTASlicingAndAnalysis();
214
+ bool runPTASlicingAndAnalysis();
215
+ bool runFinalRaceDetection();
216
+ void buildVFGPre();
217
+
218
+ /// No-slice A/B baseline: run the FSAM detection on the whole program (no
219
+ /// slicing), so its time and race set can be compared against the sliced run.
220
+ void runWholeProgramDetection();
221
+
222
+ /// Main pointer-analysis instance feeding final race detection (the
223
+ /// flow-sensitive FSAM, a BVDataPTAImpl queried polymorphically).
224
+ BVDataPTAImpl* getMainPTA() const;
225
+
226
+ /// Union of both statements of every candidate race pair (the slice targets).
227
+ std::set<const SVFStmt*> getVulnerableStmts() const;
228
+
229
+ // --- race detection ---
230
+ /// Re-check the candidate race pairs on the sliced graph using FSAM points-to.
231
+ std::set<RacePair> detectRacePairsOnSlicedGraph(
232
+ BVDataPTAImpl* slicedPTA, MHP* slicedMHP, LockAnalysis* slicedLockAnalysis);
233
+
234
+ // Lock analysis over the WHOLE ICFG (real control flow, no bridging) for the
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();
240
+
241
+ // --- pipeline state (owned unless noted) ---
242
+ SVFIR* svfIr = nullptr;
243
+ // Main-phase context depth, set by runOnModule; the pre-analysis uses it
244
+ // to reconcile context-truncation-merged thread instances.
245
+ u32_t mainCxtDepth = 2;
246
+ std::unique_ptr<TCT> tct;
247
+ std::unique_ptr<MHP> mhp;
248
+ std::unique_ptr<LockAnalysis> lockAnalysis;
249
+ // Inclusion-based Andersen's pre-analysis (a shared singleton, not owned
250
+ // here -- released once in the destructor). Feeds the TCT / MHP / lock /
251
+ // race pre-analysis, the thread-aware VFG_pre, and the main FSMPTA.
252
+ AndersenWaveDiff* preAnder = nullptr;
253
+ std::unique_ptr<MTASVFGBuilder> vfgPreBuilder; // owns vfgPre
254
+ SVFG* vfgPre = nullptr;
255
+ std::unique_ptr<MultiStageSlicer> multiStageSlicer;
256
+ std::unique_ptr<SingleSlicer> singleSlicer;
257
+ // -mta-slicing-single: the one unified slice, computed in MTA slicing and reused
258
+ // (not recomputed) for PTA slicing so both stages share V_Single.
259
+ std::set<const ICFGNode*> singleSlicedNodes;
260
+ std::unique_ptr<SlicedSVFIRView> mtaSlicedView;
261
+ std::unique_ptr<SlicedSVFIRView> ptaSlicedView;
262
+ std::unique_ptr<SlicedSVFGView> slicedSVFGView;
263
+ std::unique_ptr<FlowSensitive> mtaFSMPTA;
264
+ std::unique_ptr<SlicedTCT> slicedTCT;
265
+ std::unique_ptr<MHP> slicedMhp;
266
+ 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
+ bool hasThreadFunctions = false;
272
+ std::set<RacePair> racePairs;
273
+ };
274
+
92
275
  } // End namespace SVF
93
276
 
94
277
  #endif /* MTA_H_ */
@@ -0,0 +1,176 @@
1
+ //===- MTASVFGBuilder.h -- Thread-aware SVFG builder for FSAM -----------===//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-> <Yulei Sui>
6
+ //
7
+
8
+ // This program is free software: you can redistribute it and/or modify
9
+ // it under the terms of the GNU Affero General Public License as published by
10
+ // the Free Software Foundation, either version 3 of the License, or
11
+ // (at your option) any later version.
12
+
13
+ // This program is distributed in the hope that it will be useful,
14
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ // GNU Affero General Public License for more details.
17
+
18
+ // You should have received a copy of the GNU Affero General Public License
19
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ //
21
+ //===----------------------------------------------------------------------===//
22
+
23
+ /*
24
+ * MTASVFGBuilder.h
25
+ *
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
+ */
37
+
38
+ #ifndef INCLUDE_MTA_MTASVFGBUILDER_H_
39
+ #define INCLUDE_MTA_MTASVFGBUILDER_H_
40
+
41
+ #include "MSSA/SVFGBuilder.h"
42
+ #include "Graphs/SVFG.h"
43
+ #include "Graphs/SVFGEdge.h"
44
+ #include "MTA/MHP.h"
45
+ #include "MTA/LockAnalysis.h"
46
+ #include "MemoryModel/PointsTo.h"
47
+ #include <map>
48
+ #include <set>
49
+ #include <utility>
50
+
51
+ namespace SVF
52
+ {
53
+
54
+ class SlicedICFGView;
55
+
56
+ class MTASVFGBuilder : public SVFGBuilder
57
+ {
58
+ public:
59
+ typedef Set<const StmtSVFGNode*> SVFGNodeSet;
60
+ typedef NodeBS SVFGNodeIDSet;
61
+
62
+ /// Constructor: driven by the interleaving (MHP) and lock analyses.
63
+ MTASVFGBuilder(MHP* m, LockAnalysis* la) : SVFGBuilder(), mhp(m), lockana(la) {}
64
+ ~MTASVFGBuilder() override = default;
65
+
66
+ /// Number of thread-aware (interference) SVFG edges added.
67
+ static u32_t numOfNewSVFGEdges;
68
+
69
+ /// Configure the builder for the main (post-slicing) FSAM solve rather than
70
+ /// the pre-analysis VFG_pre:
71
+ /// - slice != null restricts the interference-edge construction to kept
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)
77
+ {
78
+ icfgSlice = slice;
79
+ recordThreadVF = false;
80
+ }
81
+
82
+ /// A candidate thread-aware value-flow edge s --o--> s' (src store, dst
83
+ /// load/store), keyed by its endpoint SVFG nodes.
84
+ typedef std::pair<const StmtSVFGNode*, const StmtSVFGNode*> ThreadVFEdge;
85
+
86
+ /// [THREAD-VF] per-edge query map (MSli §4.2, Fig. 6 rule [THREAD-VF]).
87
+ ///
88
+ /// While building VFG_pre we record, for every candidate thread-aware
89
+ /// value-flow edge (s,s') the construction evaluates, its Query(s --o--> s')
90
+ /// set: the endpoints {s,s'} plus — under a common lock — the in-span
91
+ /// witnesses Succ_spl(s) / Pred_spl'(s') that decide TL/HD membership, i.e.
92
+ /// whether the edge survives the non-interference test (Def. 2). The query is
93
+ /// kept *per edge* (not pre-unioned) so ILA slicing can restrict the sources
94
+ /// to the edges that survive the FSPTA slice — ThreadVF(VFG'_pre) — rather
95
+ /// than every candidate pair. Feeding the retained edges' queries into ILA
96
+ /// slicing makes the sliced MHP/lock reproduce the same value-flow decisions
97
+ /// the main phase makes, while keeping the slice minimal.
98
+ ///
99
+ /// The value stores only the additional lock-span witnesses; the endpoint
100
+ /// ICFG nodes are implicit in the key and consumers must add them back.
101
+ const std::map<ThreadVFEdge, std::set<const ICFGNode*>>& getThreadVFQueryMap() const
102
+ {
103
+ return threadVFQueryMap;
104
+ }
105
+
106
+ protected:
107
+ /// Rewrite the SVFG build hook: build the stock SVFG, then add MHP edges.
108
+ void buildSVFG() override;
109
+
110
+ /// Inject a thread-aware MRGenerator so the MemSSA mod-ref carries the FSAM
111
+ /// fork/join side effects (relocated here from core MemRegion).
112
+ std::unique_ptr<MRGenerator> createMRGenerator(BVDataPTAImpl* pta, bool ptrOnlyMSSA) override;
113
+
114
+ private:
115
+ /// Main-solve configuration (see configureForMainSolve); defaults suit VFG_pre.
116
+ const SlicedICFGView* icfgSlice = nullptr; ///< null = whole program
117
+ bool recordThreadVF = true; ///< false = skip [THREAD-VF] recording
118
+
119
+ /// Collect the store/load SVFG nodes to pair for interference edges (all of
120
+ /// them, or -- when a slice is set -- only the kept ones).
121
+ void collectLoadStoreSVFGNodes();
122
+
123
+ /// FSAM join-related thread-oblivious value flow (the "return" half of
124
+ /// treating a join as a call without a forward): connect each start
125
+ /// routine's exit defs (FormalOUT) to the ActualOUT at every site that joins
126
+ /// it (FormalOUT -> ActualOUT ret edge). Done here as a post-pass over the
127
+ /// stock SVFG, so core SVFG.cpp stays unmodified.
128
+ void connectThreadJoinEdges();
129
+
130
+ /// Add a FormalOUT -> ActualOUT inter-procedural indirect ret edge for a
131
+ /// join, mirroring SVFG::addInterIndirectVFRetEdge using the public SVFG API
132
+ /// (points-to intersection + dedup via hasInterVFGEdge + addSVFGEdge).
133
+ void addJoinRetEdge(const FormalOUTSVFGNode* formalOut,
134
+ const ActualOUTSVFGNode* actualOut, CallSiteID csId);
135
+
136
+ /// Connect inter-thread (interference) value-flow edges for MHP pairs.
137
+ void connectMHPEdges(PointerAnalysis* pta);
138
+
139
+ void handleStoreLoad(const StmtSVFGNode* n1, const StmtSVFGNode* n2, PointerAnalysis* pta);
140
+ void handleStoreStore(const StmtSVFGNode* n1, const StmtSVFGNode* n2, PointerAnalysis* pta);
141
+
142
+ /// Record the [THREAD-VF] slicing sources for one candidate pair s --o--> s'
143
+ /// (s = src store, sp = dst load/store). Adds the endpoints, and — when the
144
+ /// pair is protected by a common lock — the in-span successor/predecessor
145
+ /// witnesses needed to re-decide the non-interference (tail/head) test.
146
+ void recordThreadVFSource(const StmtSVFGNode* s, const StmtSVFGNode* sp, bool commonLock);
147
+
148
+ /// Add a thread-MHP indirect value-flow edge srcId -> dstId carrying pts.
149
+ SVFGEdge* addTDEdge(NodeID srcId, NodeID dstId, const PointsTo& pts);
150
+
151
+ /// Lock-span head/tail tests (non-interference lock-pair pruning).
152
+ //@{
153
+ SVFGNodeIDSet getPrevNodes(const StmtSVFGNode* n);
154
+ SVFGNodeIDSet getSuccNodes(const StmtSVFGNode* n);
155
+ bool isHeadOfSpan(const StmtSVFGNode* n);
156
+ bool isTailOfSpan(const StmtSVFGNode* n);
157
+ //@}
158
+
159
+ SVFGNodeSet stnodeSet; ///< all store SVFG nodes
160
+ SVFGNodeSet ldnodeSet; ///< all load SVFG nodes
161
+
162
+ /// [THREAD-VF] per-edge query map (see getThreadVFQueryMap).
163
+ std::map<ThreadVFEdge, std::set<const ICFGNode*>> threadVFQueryMap;
164
+
165
+ MHP* mhp;
166
+ LockAnalysis* lockana;
167
+
168
+ Map<const StmtSVFGNode*, SVFGNodeIDSet> prevset;
169
+ Map<const StmtSVFGNode*, SVFGNodeIDSet> succset;
170
+ Map<const StmtSVFGNode*, bool> headmap;
171
+ Map<const StmtSVFGNode*, bool> tailmap;
172
+ };
173
+
174
+ } // End namespace SVF
175
+
176
+ #endif /* INCLUDE_MTA_MTASVFGBUILDER_H_ */
@@ -0,0 +1,275 @@
1
+ //===- MTASlicer.h -- Multi-stage on-demand program slicers ---------------===//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-> <Yulei Sui>
6
+ //
7
+
8
+ // This program is free software: you can redistribute it and/or modify
9
+ // it under the terms of the GNU Affero General Public License as published by
10
+ // the Free Software Foundation, either version 3 of the License, or
11
+ // (at your option) any later version.
12
+
13
+ // This program is distributed in the hope that it will be useful,
14
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ // GNU Affero General Public License for more details.
17
+
18
+ // You should have received a copy of the GNU Affero General Public License
19
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ //
21
+ //===----------------------------------------------------------------------===//
22
+
23
+ /*
24
+ * MTASlicer.h
25
+ *
26
+ * Author: Jiawei Yang
27
+ *
28
+ * The program slicers of "Multi-Stage On-Demand Program Slicing for Modular
29
+ * Analysis of Multi-Threaded Programs" (ISSTA 2026): a shared MTASlicerBase plus
30
+ * three concrete slicers.
31
+ * - MultiStageSlicer : ILA (sync + dual + call) slice for the thread-aware analysis
32
+ * (its FSPTA stage: data-dependence slice over the thread-aware VFG_pre)
33
+ * - SingleSlicer: one unified slice combining all three dependence kinds, shared
34
+ * by both ILA and FSPTA (the single-pass baseline, MSli §3/§5.4)
35
+ */
36
+
37
+ #ifndef MTA_MTASLICER_H
38
+ #define MTA_MTASLICER_H
39
+
40
+ #include "SVFIR/SVFIR.h"
41
+ #include "SVFIR/SVFStatements.h"
42
+ #include "SVFIR/SVFVariables.h"
43
+ #include "WPA/Andersen.h"
44
+ #include "MTA/MHP.h"
45
+ #include "MTA/LockAnalysis.h"
46
+ #include "MTA/TCT.h"
47
+ #include "Graphs/SlicedGraphs.h"
48
+ #include "Graphs/ThreadCallGraph.h"
49
+ #include "Graphs/ICFG.h"
50
+ #include "Graphs/ICFGNode.h"
51
+ #include <fstream>
52
+ #include "Graphs/ICFGEdge.h"
53
+ #include "Graphs/CallGraph.h"
54
+ #include "Util/WorkList.h"
55
+ #include <memory>
56
+ #include <set>
57
+ #include <string>
58
+ #include <unordered_map>
59
+ #include <unordered_set>
60
+ #include <vector>
61
+ #include <utility>
62
+
63
+ namespace SVF
64
+ {
65
+
66
+ // Forward declarations
67
+ class SVFG;
68
+ class VFGNode; // SVFGNode is a typedef for VFGNode
69
+ class PointerAnalysis;
70
+
71
+
72
+ //===----------------------------------------------------------------------===//
73
+ // SlicedTCT - the Thread-Create-Tree rebuilt over a SlicedThreadCallGraphView.
74
+ //
75
+ // Inherits TCT and overrides the ThreadCallGraph-traversing steps to use the
76
+ // sliced view. It sits at the sliced-representation layer (built from the view,
77
+ // consumed by the sliced MHP/LockAnalysis graph-access), which is why it lives
78
+ // here with the views rather than beside the analyses.
79
+ //===----------------------------------------------------------------------===//
80
+ class SlicedTCT : public TCT
81
+ {
82
+ public:
83
+ /// @param p PointerAnalysis (the shared Andersen pre-analysis)
84
+ /// @param slicedView SlicedSVFIRView containing a SlicedThreadCallGraphView
85
+ /// @param maxContextLen Max context length (0 = use Options::MaxContextLen())
86
+ SlicedTCT(PointerAnalysis* p, const SlicedSVFIRView* slicedView, u32_t maxContextLen = 0);
87
+
88
+ ~SlicedTCT() override = default;
89
+
90
+ /// Override pushCxt to use the custom maxContextLen
91
+ void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee) override;
92
+
93
+ protected:
94
+ void build() override;
95
+ void markRelProcs() override;
96
+ void markRelProcs(const FunObjVar* fun) override;
97
+ void collectLoopInfoForJoin() override;
98
+ void handleCallRelation(CxtThreadProc& ctp, const CallGraphEdge* cgEdge, const CallICFGNode* cs) override;
99
+
100
+ private:
101
+ void collectEntryFunInCallGraph() override;
102
+
103
+ const SlicedThreadCallGraphView* tcgView; // ThreadCallGraph view (from the sliced view)
104
+ u32_t maxContextLen; // 0 means use Options::MaxContextLen()
105
+
106
+ bool isKeptNode(const CallGraphNode* node) const;
107
+ bool isKeptEdge(const CallGraphEdge* edge) const;
108
+ void getKeptForkSites(std::vector<const ICFGNode*>& out) const;
109
+ void getKeptJoinSites(std::vector<const ICFGNode*>& out) const;
110
+ };
111
+
112
+
113
+ /**
114
+ * MTASlicerBase - Base class for program slicing.
115
+ *
116
+ * Holds the shared helper methods and data members used by both concrete slicers
117
+ * (the ILA and FSPTA stages of MultiStageSlicer).
118
+ */
119
+ class MTASlicerBase
120
+ {
121
+ public:
122
+ MTASlicerBase(SVFIR* svfIr, AndersenBase* pta, MHP* mhp,
123
+ LockAnalysis* lockAnalysis, SVFG* vfg = nullptr);
124
+ virtual ~MTASlicerBase();
125
+
126
+ protected:
127
+ SVFIR* svfIr;
128
+ AndersenBase* pta;
129
+ MHP* mhp;
130
+ LockAnalysis* lockAnalysis;
131
+ CallGraph* callGraph;
132
+ SVFG* vfg; ///< thread-aware VFG_pre (PTA/Single slicers; null for MTA)
133
+
134
+ // === Data flow analysis helper ===
135
+ /**
136
+ * Paper-faithful (§4.3) data-dependence slice over the thread-aware SVFG
137
+ * (VFG_pre): seed from the value-flow nodes of the given statements and
138
+ * backward-traverse every value-flow edge -- direct (top-level def-use),
139
+ * indirect (address-taken / MemSSA def-use), and thread-aware interference.
140
+ * Returns the kept ICFG nodes. This is the single dependence model used
141
+ * by the FSPTA stage.
142
+ */
143
+ OrderedSet<const ICFGNode*> sliceDataDependenceOverVFG(
144
+ const OrderedSet<const SVFStmt*>& seeds, SVFG* vfg);
145
+
146
+ /// The SVFG-node granularity of the data-dependence slice above: the set of
147
+ /// VFG nodes reachable backward from the seeds. ThreadVF(VFG'_pre) is exactly
148
+ /// the thread-aware edges whose *both* endpoints lie in this set, so ILA
149
+ /// slicing uses it to restrict the [THREAD-VF] sources to surviving edges.
150
+ OrderedSet<const VFGNode*> computeDataDependenceSVFGNodes(
151
+ const OrderedSet<const SVFStmt*>& seeds, SVFG* vfg);
152
+
153
+ /// Project the retained VFG nodes (plus the seeds) onto their ICFG nodes.
154
+ OrderedSet<const ICFGNode*> svfgNodesToICFGNodes(
155
+ const OrderedSet<const VFGNode*>& nodes, const OrderedSet<const SVFStmt*>& seeds);
156
+
157
+ // === Thread analysis helpers ===
158
+ OrderedSet<const SVFStmt*> getDependentThreadCreate(const SVFStmt* stmt);
159
+ OrderedSet<const TCTNode*> getTCTNodeSetFromNode(const ICFGNode* node);
160
+
161
+ // === Lock analysis helpers ===
162
+ OrderedSet<const ICFGNode*> getLockSet(const ICFGNode* node);
163
+ OrderedSet<const CallICFGNode*> collectPthreadStatements(const OrderedSet<const SVFStmt*>& vulnerableStmts);
164
+ OrderedSet<const CallICFGNode*> collectMutexStatements(const OrderedSet<const SVFStmt*>& vulnerableStmts);
165
+
166
+ // === Common slicing helpers ===
167
+ /**
168
+ * Collect common pthread and mutex statements (shared by PTA and MTA slicing).
169
+ * @param vulnerableStatements Set of vulnerable statements
170
+ * @return Pair of (pthreadCallNodes, mutexCallNodes)
171
+ */
172
+ std::pair<OrderedSet<const CallICFGNode*>, OrderedSet<const CallICFGNode*>>
173
+ collectCommonThreadStatements(const OrderedSet<const SVFStmt*>& vulnerableStatements);
174
+
175
+ // === ICFG analysis helpers ===
176
+ OrderedSet<const ICFGNode*> buildBackwardICFGNodeSet(const OrderedSet<const ICFGNode*>& vulnerableNodes);
177
+
178
+ /**
179
+ * Call-dependence expansion (used by MultiStageSlicer): take the
180
+ * kept functions of the given nodes, close upward over the call graph
181
+ * (every transitive caller), then add each kept function's entry/exit nodes
182
+ * and the call/ret nodes of every call site targeting it.
183
+ * @param nodes Current set of ICFG nodes
184
+ * @return The input nodes plus the call/ret and entry/exit nodes above
185
+ */
186
+ OrderedSet<const ICFGNode*> expandCallDependence(const OrderedSet<const ICFGNode*>& nodes);
187
+
188
+ /**
189
+ * Perform dual slicing (temporal slicing): filter statements based on control flow and parallel execution.
190
+ * This is shared by both PTA and MTA slicing.
191
+ * @param slicedNodes Set of statements from statement-level slicing
192
+ * @return Set of ICFG nodes in the dual slice
193
+ */
194
+ OrderedSet<const ICFGNode*> runDualSlicing(
195
+ const OrderedSet<const ICFGNode*>& slicedNodes);
196
+ };
197
+
198
+ /**
199
+ * MultiStageSlicer - the multi-stage (differential) slicer of MSli: one class,
200
+ * two stages sharing one memoised data-dependence closure over VFG_pre.
201
+ * Stage 1 (ILA): runILASlicing -- synchronization/dual slicing + function
202
+ * expansion, feeding the sliced MHP/lock.
203
+ * Stage 2 (FSPTA): runPTASlicing -- backward data-dependence slice feeding
204
+ * the sliced flow-sensitive solve.
205
+ * Contrast: SingleSlicer below folds everything into ONE unified slice.
206
+ */
207
+ class MultiStageSlicer : public MTASlicerBase
208
+ {
209
+ public:
210
+ MultiStageSlicer(SVFIR* svfIr, AndersenBase* pta, MHP* mhp,
211
+ LockAnalysis* lockAnalysis, SVFG* vfg = nullptr);
212
+
213
+ /**
214
+ * Stage 1: the ILA slice (dual slicing + function expansion for the IRView).
215
+ * @param vulnerableStatements Set of vulnerable statements to start slicing from
216
+ * (the [INIT] rule: pre-analysis race statements).
217
+ * @param threadVFSources Extra ILA slicing sources from the [THREAD-VF] rule
218
+ * (MSli 4.2): statements whose MHP/lock-span results are queried during
219
+ * the main-phase thread-aware value-flow construction (endpoints and
220
+ * in-span non-interference witnesses collected while building VFG_pre).
221
+ * @return Set of ICFG nodes in the slice (including call/ret and entry/exit nodes)
222
+ */
223
+ OrderedSet<const ICFGNode*> runILASlicing(
224
+ const OrderedSet<const SVFStmt*>& vulnerableStatements,
225
+ const OrderedSet<const ICFGNode*>& threadVFSources = {});
226
+
227
+ /**
228
+ * Stage 2: the FSPTA slice (backward data dependence over the thread-aware
229
+ * VFG_pre; node set only, no function expansion).
230
+ */
231
+ OrderedSet<const ICFGNode*> runPTASlicing(
232
+ const OrderedSet<const SVFStmt*>& vulnerableStatements);
233
+
234
+ /**
235
+ * The FSPTA data-dependence slice at SVFG-node granularity (memoised). The
236
+ * ILA stage queries this first, to restrict the [THREAD-VF] sources to
237
+ * ThreadVF(VFG'_pre); runPTASlicing reuses the same set, so the backward
238
+ * closure over VFG_pre is computed once and shared across both stages.
239
+ */
240
+ const OrderedSet<const VFGNode*>& getRetainedSVFGNodes(
241
+ const OrderedSet<const SVFStmt*>& vulnerableStatements);
242
+
243
+ private:
244
+ OrderedSet<const VFGNode*> retainedSVFGNodes; ///< memoised data-dependence slice
245
+ bool retainedComputed = false;
246
+ };
247
+
248
+ /**
249
+ * SingleSlicer - Unified slicer combining synchronization, data, and call
250
+ * dependence into ONE slice (the single-pass baseline, MSli §3/§5.4: the
251
+ * transitive closure of the target statements under the combined dependence
252
+ * graph). Both ILA and FSPTA run on this single slice, so V_ILA, V_PTA subset
253
+ * V_Single. Used by the differential-slicing ablation (-mta-slicing-single).
254
+ *
255
+ * Iteratively applies data dependence (over the thread-aware VFG_pre) and call
256
+ * dependence until convergence, then a single dual-slicing pass.
257
+ */
258
+ class SingleSlicer : public MTASlicerBase
259
+ {
260
+ public:
261
+ SingleSlicer(SVFIR* svfIr, AndersenBase* pta, MHP* mhp,
262
+ LockAnalysis* lockAnalysis, SVFG* vfg = nullptr);
263
+
264
+ /**
265
+ * Perform unified slicing combining synchronization, data, and call dependence.
266
+ * @param vulnerableStatements Set of vulnerable statements to start slicing from
267
+ * @return Set of ICFG nodes in the slice (including call/ret and entry/exit nodes)
268
+ */
269
+ OrderedSet<const ICFGNode*> runSlicing(
270
+ const OrderedSet<const SVFStmt*>& vulnerableStatements);
271
+ };
272
+
273
+ } // End namespace SVF
274
+
275
+ #endif // MTA_MTASLICER_H