svf-tools 1.0.1258 → 1.0.1260

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.1258",
3
+ "version": "1.0.1260",
4
4
  "description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -37,9 +37,9 @@
37
37
  #include "AE/Svfexe/AEStat.h"
38
38
  #include "SVFIR/SVFIR.h"
39
39
  #include "Util/SVFBugReport.h"
40
+ #include "Util/WorkList.h"
40
41
  #include "Graphs/SCC.h"
41
42
  #include "Graphs/CallGraph.h"
42
- #include <deque>
43
43
 
44
44
  namespace SVF
45
45
  {
@@ -94,6 +94,12 @@ public:
94
94
  WIDEN_NARROW
95
95
  };
96
96
 
97
+ enum AEFunEntryMode
98
+ {
99
+ MAIN,
100
+ NO_MAIN
101
+ };
102
+
97
103
  virtual void runOnModule();
98
104
 
99
105
  /// Destructor
@@ -106,7 +112,7 @@ public:
106
112
  void analyzeFromAllProgEntries();
107
113
 
108
114
  /// Get all entry point functions (functions without callers)
109
- std::deque<const FunObjVar*> collectProgEntryFuns();
115
+ FIFOWorkList<const FunObjVar*> collectProgEntryFuns();
110
116
 
111
117
  /// Factory: returns the singleton instance. The concrete class is
112
118
  /// chosen once, on first call, from `Options::AESparsity()`:
@@ -254,10 +260,10 @@ private:
254
260
  virtual void handleCallSite(const ICFGNode* node);
255
261
 
256
262
  /// Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration
257
- virtual void handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller = nullptr);
263
+ virtual void handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller);
258
264
 
259
265
  /// Handle a function body via worklist-driven WTO traversal starting from funEntry
260
- void handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller = nullptr);
266
+ void handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller);
261
267
 
262
268
  /// Handle an ICFG node: execute statements; return true if state changed
263
269
  bool handleICFGNode(const ICFGNode* node);
@@ -241,6 +241,7 @@ public:
241
241
 
242
242
  // Abstract Execution
243
243
  static const OptionMap<u32_t> AESparsity;
244
+ static const OptionMap<u32_t> AEFunEntry;
244
245
  static const Option<u32_t> WidenDelay;
245
246
  /// recursion handling mode, Default: TOP
246
247
  static const OptionMap<u32_t> HandleRecur;
@@ -35,7 +35,6 @@
35
35
  #include "Graphs/CallGraph.h"
36
36
  #include "WPA/Andersen.h"
37
37
  #include <cmath>
38
- #include <deque>
39
38
  #include <memory>
40
39
 
41
40
  using namespace SVF;
@@ -118,11 +117,14 @@ AbstractInterpretation::~AbstractInterpretation()
118
117
  }
119
118
 
120
119
  /// Collect entry point functions for analysis.
121
- /// Entry points are functions without callers (no incoming edges in CallGraph).
122
- /// Uses a deque to allow efficient insertion at front for prioritizing main()
123
- std::deque<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns()
120
+ /// In main mode, entry is main/svf.main. In no-main mode,
121
+ /// entries are SCCs with no external caller in the Andersen-resolved CallGraph.
122
+ FIFOWorkList<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns()
124
123
  {
125
- std::deque<const FunObjVar*> entryFunctions;
124
+ FIFOWorkList<const FunObjVar*> entryFunctions;
125
+ const bool mainEntry = Options::AEFunEntry() == AEFunEntryMode::MAIN;
126
+ Set<NodeID> visitedEntrySCCs;
127
+ auto* callGraphSCC = preAnalysis->getCallGraphSCC();
126
128
 
127
129
  for (auto it = callGraph->begin(); it != callGraph->end(); ++it)
128
130
  {
@@ -133,39 +135,80 @@ std::deque<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns()
133
135
  if (fun->isDeclaration())
134
136
  continue;
135
137
 
136
- // Entry points are functions without callers (no incoming edges)
137
- if (cgNode->getInEdges().empty())
138
+ if (mainEntry)
138
139
  {
139
- // If main exists, put it first for priority using deque's push_front
140
140
  if (SVFUtil::isProgEntryFunction(fun))
141
141
  {
142
- entryFunctions.push_front(fun);
142
+ entryFunctions.push(fun);
143
+ break;
143
144
  }
144
- else
145
+ }
146
+ else
147
+ {
148
+ NodeID repNodeId = callGraphSCC->repNode(cgNode->getId());
149
+ if (visitedEntrySCCs.count(repNodeId))
150
+ continue;
151
+
152
+ const NodeBS& cgSCCNodes = callGraphSCC->subNodes(repNodeId);
153
+ bool hasExternalCaller = false;
154
+ for (NodeID nodeId : cgSCCNodes)
155
+ {
156
+ const CallGraphNode* sccNode = callGraph->getGNode(nodeId);
157
+ for (auto inEdge : sccNode->getInEdges())
158
+ {
159
+ if (!cgSCCNodes.test(inEdge->getSrcID()))
160
+ {
161
+ hasExternalCaller = true;
162
+ break;
163
+ }
164
+ }
165
+ if (hasExternalCaller)
166
+ break;
167
+ }
168
+
169
+ if (hasExternalCaller)
170
+ continue;
171
+
172
+ visitedEntrySCCs.insert(repNodeId);
173
+ const FunObjVar* entryFun = fun;
174
+ for (NodeID nodeId : cgSCCNodes)
145
175
  {
146
- entryFunctions.push_back(fun);
176
+ const FunObjVar* sccFun = callGraph->getGNode(nodeId)->getFunction();
177
+ if (SVFUtil::isProgEntryFunction(sccFun))
178
+ {
179
+ entryFun = sccFun;
180
+ break;
181
+ }
147
182
  }
183
+ entryFunctions.push(entryFun);
148
184
  }
149
185
  }
150
186
 
187
+ if (mainEntry && entryFunctions.empty())
188
+ {
189
+ SVFUtil::errs() << SVFUtil::errMsg(
190
+ "AE -ae-fun-entry=main requires a program entry function, but main/svf.main was not found.\n");
191
+ assert(false && "No program entry function found for -ae-fun-entry=main");
192
+ abort();
193
+ }
194
+
151
195
  return entryFunctions;
152
196
  }
153
197
 
154
198
 
155
- /// Program entry - analyze from all entry points (multi-entry analysis is the default)
199
+ /// Program entry - entry policy is selected by -ae-fun-entry.
156
200
  void AbstractInterpretation::analyse()
157
201
  {
158
- // Always use multi-entry analysis from all entry points
159
202
  analyzeFromAllProgEntries();
160
203
  }
161
204
 
162
- /// Analyze all entry points (functions without callers) - for whole-program analysis.
205
+ /// Analyze the entry functions selected by collectProgEntryFuns().
163
206
  /// Abstract state is shared across entry points so that functions analyzed from
164
207
  /// earlier entries are not re-analyzed from scratch.
165
208
  void AbstractInterpretation::analyzeFromAllProgEntries()
166
209
  {
167
210
  // Collect all entry point functions
168
- std::deque<const FunObjVar*> entryFunctions = collectProgEntryFuns();
211
+ FIFOWorkList<const FunObjVar*> entryFunctions = collectProgEntryFuns();
169
212
 
170
213
  if (entryFunctions.empty())
171
214
  {
@@ -174,10 +217,13 @@ void AbstractInterpretation::analyzeFromAllProgEntries()
174
217
  }
175
218
  // handle Global ICFGNode of SVFModule
176
219
  handleGlobalNode();
177
- for (const FunObjVar* entryFun : entryFunctions)
220
+ const ICFGNode* globalNode = icfg->getGlobalICFGNode();
221
+ while (!entryFunctions.empty())
178
222
  {
223
+ const FunObjVar* entryFun = entryFunctions.pop();
179
224
  const ICFGNode* funEntry = icfg->getFunEntryICFGNode(entryFun);
180
- handleFunction(funEntry);
225
+ updateAbsState(funEntry, getAbsState(globalNode));
226
+ handleFunction(funEntry, nullptr);
181
227
  }
182
228
  }
183
229
 
@@ -736,8 +782,7 @@ bool AbstractInterpretation::handleICFGNode(const ICFGNode* node)
736
782
  void AbstractInterpretation::handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller)
737
783
  {
738
784
  auto it = preAnalysis->getFuncToWTO().find(funEntry->getFun());
739
- if (it == preAnalysis->getFuncToWTO().end())
740
- return;
785
+ assert(it != preAnalysis->getFuncToWTO().end() && "Missing WTO for function");
741
786
 
742
787
  // Push all top-level WTO components into the worklist in WTO order
743
788
  FIFOWorkList<const ICFGWTOComp*> worklist(it->second->getWTOComponents());
@@ -799,6 +799,20 @@ const OptionMap<u32_t> Options::AESparsity(
799
799
  "Sparse abstract execution via SVFG."
800
800
  }
801
801
  });
802
+ const OptionMap<u32_t> Options::AEFunEntry(
803
+ "ae-fun-entry",
804
+ "Abstract execution function entry mode (Default: main)",
805
+ AbstractInterpretation::AEFunEntryMode::MAIN,
806
+ {
807
+ {
808
+ AbstractInterpretation::AEFunEntryMode::MAIN, "main",
809
+ "Analyze from the program entry function only."
810
+ },
811
+ {
812
+ AbstractInterpretation::AEFunEntryMode::NO_MAIN, "no-main",
813
+ "Analyze from every no-external-caller SCC after Andersen resolves the call graph."
814
+ }
815
+ });
802
816
  const Option<u32_t> Options::WidenDelay(
803
817
  "widen-delay", "Loop Widen Delay", 3);
804
818
  const OptionMap<u32_t> Options::HandleRecur(